1/*! 2 * modernizr v3.3.1 3 * Build https://modernizr.com/download?-setclasses-dontmin 4 * 5 * Copyright (c) 6 * Faruk Ates 7 * Paul Irish 8 * Alex Sexton 9 * Ryan Seddon 10 * Patrick Kettner 11 * Stu Cox 12 * Richard Herrera 13 14 * MIT License 15 */ 16 17/* 18 * Modernizr tests which native CSS3 and HTML5 features are available in the 19 * current UA and makes the results available to you in two ways: as properties on 20 * a global `Modernizr` object, and as classes on the `<html>` element. This 21 * information allows you to progressively enhance your pages with a granular level 22 * of control over the experience. 23*/ 24 25;(function(window, document, undefined){ 26 var tests = []; 27 28 29 /** 30 * 31 * ModernizrProto is the constructor for Modernizr 32 * 33 * @class 34 * @access public 35 */ 36 37 var ModernizrProto = { 38 // The current version, dummy 39 _version: '3.3.1', 40 41 // Any settings that don't work as separate modules 42 // can go in here as configuration. 43 _config: { 44 'classPrefix': '', 45 'enableClasses': true, 46 'enableJSClass': true, 47 'usePrefixes': true 48 }, 49 50 // Queue of tests 51 _q: [], 52 53 // Stub these for people who are listening 54 on: function(test, cb) { 55 // I don't really think people should do this, but we can 56 // safe guard it a bit. 57 // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests. 58 // This is in case people listen to synchronous tests. I would leave it out, 59 // but the code to *disallow* sync tests in the real version of this 60 // function is actually larger than this. 61 var self = this; 62 setTimeout(function() { 63 cb(self[test]); 64 }, 0); 65 }, 66 67 addTest: function(name, fn, options) { 68 tests.push({name: name, fn: fn, options: options}); 69 }, 70 71 addAsyncTest: function(fn) { 72 tests.push({name: null, fn: fn}); 73 } 74 }; 75 76 77 78 // Fake some of Object.create so we can force non test results to be non "own" properties. 79 var Modernizr = function() {}; 80 Modernizr.prototype = ModernizrProto; 81 82 // Leak modernizr globally when you `require` it rather than force it here. 83 // Overwrite name so constructor name is nicer :D 84 Modernizr = new Modernizr(); 85 86 87 88 var classes = []; 89 90 91 /** 92 * is returns a boolean if the typeof an obj is exactly type. 93 * 94 * @access private 95 * @function is 96 * @param {*} obj - A thing we want to check the type of 97 * @param {string} type - A string to compare the typeof against 98 * @returns {boolean} 99 */ 100 101 function is(obj, type) { 102 return typeof obj === type; 103 } 104 ; 105 106 /** 107 * Run through all tests and detect their support in the current UA. 108 * 109 * @access private 110 */ 111 112 function testRunner() { 113 var featureNames; 114 var feature; 115 var aliasIdx; 116 var result; 117 var nameIdx; 118 var featureName; 119 var featureNameSplit; 120 121 for (var featureIdx in tests) { 122 if (tests.hasOwnProperty(featureIdx)) { 123 featureNames = []; 124 feature = tests[featureIdx]; 125 // run the test, throw the return value into the Modernizr, 126 // then based on that boolean, define an appropriate className 127 // and push it into an array of classes we'll join later. 128 // 129 // If there is no name, it's an 'async' test that is run, 130 // but not directly added to the object. That should 131 // be done with a post-run addTest call. 132 if (feature.name) { 133 featureNames.push(feature.name.toLowerCase()); 134 135 if (feature.options && feature.options.aliases && feature.options.aliases.length) { 136 // Add all the aliases into the names list 137 for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) { 138 featureNames.push(feature.options.aliases[aliasIdx].toLowerCase()); 139 } 140 } 141 } 142 143 // Run the test, or use the raw value if it's not a function 144 result = is(feature.fn, 'function') ? feature.fn() : feature.fn; 145 146 147 // Set each of the names on the Modernizr object 148 for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) { 149 featureName = featureNames[nameIdx];
150 // Support dot properties as sub tests. We don't do checking to make sure 151 // that the implied parent tests have been added. You must call them in 152 // order (either in the test, or make the parent test a dependency). 153 // 154 // Cap it to TWO to make the logic simple and because who needs that kind of subtesting 155 // hashtag famous last words 156 featureNameSplit = featureName.split('.'); 157 158 if (featureNameSplit.length === 1) { 159 Modernizr[featureNameSplit[0]] = result; 160 } else { 161 // cast to a Boolean, if not one already 162 if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) { 163 Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]); 164 } 165 166 Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result; 167 } 168 169 classes.push((result ? '' : 'no-') + featureNameSplit.join('-')); 170 } 171 } 172 } 173 } 174 ; 175 176 /** 177 * docElement is a convenience wrapper to grab the root element of the document 178 * 179 * @access private 180 * @returns {HTMLElement|SVGElement} The root element of the document 181 */ 182 183 var docElement = document.documentElement; 184 185 186 /** 187 * A convenience helper to check if the document we are running in is an SVG document 188 * 189 * @access private 190 * @returns {boolean} 191 */ 192 193 var isSVG = docElement.nodeName.toLowerCase() === 'svg'; 194 195 196 /** 197 * setClasses takes an array of class names and adds them to the root element 198 * 199 * @access private 200 * @function setClasses 201 * @param {string[]} classes - Array of class names 202 */ 203 204 // Pass in an and array of class names, e.g.:
205 // ['no-webp', 'borderradius', ...] 206 function setClasses(classes) { 207 var className = docElement.className; 208 var classPrefix = Modernizr._config.classPrefix || ''; 209 210 if (isSVG) { 211 className = className.baseVal; 212 } 213 214 // Change `no-js` to `js` (independently of the `enableClasses` option) 215 // Handle classPrefix on this too 216 if (Modernizr._config.enableJSClass) { 217 var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)'); 218 className = className.replace(reJS, '$1' + classPrefix + 'js$2'); 219 } 220 221 if (Modernizr._config.enableClasses) { 222 // Add the new classes 223 className += ' ' + classPrefix + classes.join(' ' + classPrefix); 224 if (isSVG) { 225 docElement.className.baseVal = className; 226 } else { 227 docElement.className = className; 228 } 229 } 230 231 } 232 233 ; 234 235 // Run each test 236 testRunner(); 237 238 // Remove the "no-js" class if it exists 239 setClasses(classes); 240 241 delete ModernizrProto.addTest; 242 delete ModernizrProto.addAsyncTest; 243 244 // Run the things that are supposed to run after the tests 245 for (var i = 0; i < Modernizr._q.length; i++) { 246 Modernizr._q[i](); 247 } 248 249 // Leak Modernizr namespace 250 window.Modernizr = Modernizr; 251 252 253; 254 255})(window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.