PageSourceSearch

https://mental-fitness.hu/js/plugins/modernizr.js

js mental-fitness.hu collected 2026-10-08 04:58:34 UTC 28,815 bytes, 902 lines download raw bytes

1/*!
2 * modernizr v3.3.1
3 * Build http://modernizr.com/download?-csstransforms3d-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            /* jshint -W053 */
163            if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
164              Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
165            }
166
167            Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
168          }
169
170          classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
171        }
172      }
173    }
174  }
175  ;
176
177  /**
178   * docElement is a convenience wrapper to grab the root element of the document
179   *
180   * @access private
181   * @returns {HTMLElement|SVGElement} The root element of the document
182   */
183
184  var docElement = document.documentElement;
185  
186
187  /**
188   * A convenience helper to check if the document we are running in is an SVG document
189   *
190   * @access private
191   * @returns {boolean}
192   */
193
194  var isSVG = docElement.nodeName.toLowerCase() === 'svg';
195  
196
197  /**
198   * setClasses takes an array of class names and adds them to the root element
199   *
200   * @access private
201   * @function setClasses
202   * @param {string[]} classes - Array of class names
203   */
204
205  // Pass in an and array of class names, e.g.:
206  //  ['no-webp', 'borderradius', ...]
207  function setClasses(classes) {
208    var className = docElement.className;
209    var classPrefix = Modernizr._config.classPrefix || '';
210
211    if (isSVG) {
212      className = className.baseVal;
213    }
214
215    // Change `no-js` to `js` (independently of the `enableClasses` option)
216    // Handle classPrefix on this too
217    if (Modernizr._config.enableJSClass) {
218      var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
219      className = className.replace(reJS, '$1' + classPrefix + 'js$2');
220    }
221
222    if (Modernizr._config.enableClasses) {
223      // Add the new classes
224      className += ' ' + classPrefix + classes.join(' ' + classPrefix);
225      isSVG ? docElement.className.baseVal = className : docElement.className = className;
226    }
227
228  }
229
230  ;
231
232  /**
233   * If the browsers follow the spec, then they would expose vendor-specific style as:
234   *   elem.style.WebkitBorderRadius
235   * instead of something like the following, which would be technically incorrect:
236   *   elem.style.webkitBorderRadius
237
238   * Webkit ghosts their properties in lowercase but Opera & Moz do not.
239   * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
240   *   erik.eae.net/archives/2008/03/10/21.48.10/
241
242   * More here: github.com/Modernizr/Modernizr/issues/issue/21
243   *
244   * @access private
245   * @returns {string} The string representing the vendor-specific style properties
246   */
247
248  var omPrefixes = 'Moz O ms Webkit';
249  
250
251  var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
252  ModernizrProto._cssomPrefixes = cssomPrefixes;
253  
254
255
256  /**
257   * contains checks to see if a string contains another string
258   *
259   * @access private
260   * @function contains
261   * @param {string} str - The string we want to check for substrings
262   * @param {string} substr - The substring we want to search the first string for
263   * @returns {boolean}
264   */
265
266  function contains(str, substr) {
267    return !!~('' + str).indexOf(substr);
268  }
269
270  ;
271
272  /**
273   * createElement is a convenience wrapper around document.createElement. Since we
274   * use createElement all over the place, this allows for (slightly) smaller code
275   * as well as abstracting away issues with creating elements in contexts other than
276   * HTML documents (e.g. SVG documents).
277   *
278   * @access private
279   * @function createElement
280   * @returns {HTMLElement|SVGElement} An HTML or SVG element
281   */
282
283  function createElement() {
284    if (typeof document.createElement !== 'function') {
285      // This is the case in IE7, where the type of createElement is "object".
286      // For this reason, we cannot call apply() as Object is not a Function.
287      return document.createElement(arguments[0]);
288    } else if (isSVG) {
289      return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
290    } else {
291      return document.createElement.apply(document, arguments);
292    }
293  }
294
295  ;
296
297  /**
298   * Create our "modernizr" element that we do most feature tests on.
299   *
300   * @access private
301   */
302
303  var modElem = {
304    elem: createElement('modernizr')
305  };
306
307  // Clean up this element
308  Modernizr._q.push(function() {
309    delete modElem.elem;
310  });
311
312  
313
314  var mStyle = {
315    style: modElem.elem.style
316  };
317
318  // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
319  // the front of the queue.
320  Modernizr._q.unshift(function() {
321    delete mStyle.style;
322  });
323
324  
325
326  /**
327   * getBody returns the body of a document, or an element that can stand in for
328   * the body if a real body does not exist
329   *
330   * @access private
331   * @function getBody
332   * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
333   * artificially created element that stands in for the body
334   */
335
336  function getBody() {
337    // After page load injecting a fake body doesn't work so check if body exists
338    var body = document.body;
339
340    if (!body) {
341      // Can't use the real body create a fake one.
342      body = createElement(isSVG ? 'svg' : 'body');
343      body.fake = true;
344    }
345
346    return body;
347  }
348
349  ;
350
351  /**
352   * injectElementWithStyles injects an element with style element and some CSS rules
353   *
354   * @access private
355   * @function injectElementWithStyles
356   * @param {string} rule - String representing a css rule
357   * @param {function} callback - A function that is used to test the injected element
358   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
359   * @param {string[]}
359 [testnames] - An array of strings that are used as ids for the additional nodes
360   * @returns {boolean}
361   */
362
363  function injectElementWithStyles(rule, callback, nodes, testnames) {
364    var mod = 'modernizr';
365    var style;
366    var ret;
367    var node;
368    var docOverflow;
369    var div = createElement('div');
370    var body = getBody();
371
372    if (parseInt(nodes, 10)) {
373      // In order not to give false positives we create a node for each test
374      // This also allows the method to scale for unspecified uses
375      while (nodes--) {
376        node = createElement('div');
377        node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
378        div.appendChild(node);
379      }
380    }
381
382    style = createElement('style');
383    style.type = 'text/css';
384    style.id = 's' + mod;
385
386    // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
387    // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
388    (!body.fake ? div : body).appendChild(style);
389    body.appendChild(div);
390
391    if (style.styleSheet) {
392      style.styleSheet.cssText = rule;
393    } else {
394      style.appendChild(document.createTextNode(rule));
395    }
396    div.id = mod;
397
398    if (body.fake) {
399      //avoid crashing IE8, if background image is used
400      body.style.background = '';
401      //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
402      body.style.overflow = 'hidden';
403      docOverflow = docElement.style.overflow;
404      docElement.style.overflow = 'hidden';
405      docElement.appendChild(body);
406    }
407
408    ret = callback(div, rule);
409    // If this is done after page load we don't want to remove the body so check if body exists
410    if (body.fake) {
411      body.parentNode.removeChild(body);
412      docElement.style.overflow = docOverflow;
413      // Trigger layout so kinetic scrolling isn't disabled in iOS6+
414      docElement.offsetHeight;
415    } else {
416      div.parentNode.removeChild(div);
417    }
418
419    return !!ret;
420
421  }
422
423  ;
424
425  /**
426   * domToCSS takes a camelCase string and converts it to kebab-case
427   * e.g. boxSizing -> box-sizing
428   *
429   * @access private
430   * @function domToCSS
431   * @param {string} name - String name of camelCase prop we want to convert
432   * @returns {string} The kebab-case version of the supplied name
433   */
434
435  function domToCSS(name) {
436    return name.replace(/([A-Z])/g, function(str, m1) {
437      return '-' + m1.toLowerCase();
438    }).replace(/^ms-/, '-ms-');
439  }
440  ;
441
442  /**
443   * nativeTestProps allows for us to use native feature detection functionality if available.
444   * some prefixed form, or false, in the case of an unsupported rule
445   *
446   * @access private
447   * @function nativeTestProps
448   * @param {array} props - An array of property names
449   * @param {string} value - A string representing the value we want to check via @supports
450   * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
451   */
452
453  // Accepts a list of property names and a single value
454  // Returns `undefined` if native detection not available
455  function nativeTestProps(props, value) {
456    var i = props.length;
457    // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
458    if ('CSS' in window && 'supports' in window.CSS) {
459      // Try every prefixed variant of the property
460      while (i--) {
461        if (window.CSS.supports(domToCSS(props[i]), value)) {
462          return true;
463        }
464      }
465      return false;
466    }
467    // Otherwise fall back to at-rule (for Opera 12.x)
468    else if ('CSSSupportsRule' in window) {
469      // Build a condition string for every prefixed variant
470      var conditionText = [];
471      while (i--) {
472        conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
473      }
474      conditionText = conditionText.join(' or ');
475      return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
476        return getComputedStyle(node, null).position == 'absolute';
477      });
478    }
479    return undefined;
480  }
481  ;
482
483  /**
484   * cssToDOM takes a kebab-case string and converts it to camelCase
485   * e.g. box-sizing -> boxSizing
486   *
487   * @access private
488   * @function cssToDOM
489   * @param {string} name - String name of kebab-case prop we want to convert
490   * @returns {string} The camelCase version of the supplied name
491   */
492
493  function cssToDOM(name) {
494    return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
495      return m1 + m2.toUpperCase();
496    }).replace(/^-/, '');
497  }
498  ;
499
500  // testProps is a generic CSS / DOM property test.
501
502  // In testing support for a given CSS property, it's legit to test:
503  //    `elem.style[styleName] !== undefined`
504  // If the property is supported it will return an empty string,
505  // if unsupported it will return undefined.
506
507  // We'll take advantage of this quick test and skip setting a style
508  // on our modernizr element, but instead just testing undefined vs
509  // empty string.
510
511  // Property names can be provided in either camelCase or kebab-case.
512
513  function testProps(props, prefixed, value, skipValueTest) {
514    skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
515
516    // Try native detect first
517    if (!is(value, 'undefined')) {
518      var result = nativeTestProps(props, value);
519      if (!is(result, 'undefined')) {
520        return result;
521      }
522    }
523
524    // Otherwise do it properly
525    var afterInit, i, propsLength, prop, before;
526
527    // If we don't have a style element, that means we're running async or after
528    // the core tests, so we'll need to create our own elements to use
529
530    // inside of an SVG element, in certain browsers, the `style` element is only
531    // defined for valid tags. Therefore, if `modernizr` does not have one, we
532    // fall back to a less used element and hope for the best.
533    var elems = ['modernizr', 'tspan'];
534    while (!mStyle.style) {
535      afterInit = true;
536      mStyle.modElem = createElement(elems.shift());
537      mStyle.style = mStyle.modElem.style;
538    }
539
540    // Delete the objects if we created them.
541    function cleanElems() {
542      if (afterInit) {
543        delete mStyle.style;
544        delete mStyle.modElem;
545      }
546    }
547
548    propsLength = props.length;
549    for (i = 0; i < propsLength; i++) {
550      prop = props[i];
551      before = mStyle.style[prop];
552
553      if (contains(prop, '-')) {
554        prop = cssToDOM(prop);
555      }
556
557      if (mStyle.style[prop] !== undefined) {
558
559        // If value to test has been passed in, do a set-and-check test.
560        // 0 (integer) is a valid property value, so check that `value` isn't
561        // undefined, rather than just checking it's truthy.
562        if (!skipValueTest && !is(value, 'undefined')) {
563
564          // Needs a try catch block because of old IE. This is slow, but will
565          // be avoided in most cases because `skipValueTest` will be used.
566          try {
567            mStyle.style[prop] = value;
568          } catch (e) {}
569
570          // If the property value has changed, we assume the value used is
571          // supported. If `value` is empty string, it'll fail here (because
572          // it hasn't changed), which matches how browsers have implemented
573          // CSS.supports()
574          if (mStyle.style[prop] != before) {
575            cleanElems();
576            return prefixed == 'pfx' ? prop : true;
577          }
578        }
579        // Otherwise just return true, or the property name if this is a
580        // `prefixed()` call
581        else {
582          cleanElems();
583          return prefixed == 'pfx' ? prop : true;
584        }
585      }
586    }
587    cleanElems();
588    return false;
589  }
590
591  ;
592
593  /**
594   * List of JavaScript DOM values used for tests
595   *
596   * @memberof Modernizr
597   * @name Modernizr._domPrefixes
598   * @optionName Modernizr._domPrefixes
599   * @optionProp domPrefixes
600   * @access public
601   * @example
602   *
603   * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
604   * than kebab-case properties, all properties are their Capitalized variant
605   *
606   * ```js
607   * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
608   * ```
609   */
610
611  var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
612  ModernizrProto._domPrefixes = domPrefixes;
613  
614
615  /**
616   * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
617   *
618   * @access private
619   * @function fnBind
620   * @param {function} fn - a function you want to change `this` reference to
621   * @param {object} that - the `this` you want to call the function with
622   * @returns {function} The wrapped version of the supplied function
623   */
624
625  function fnBind(fn, that) {
626    return function() {
627      return fn.apply(that, arguments);
628    };
629  }
630
631  ;
632
633  /**
634   * testDOMProps is a generic DOM property test; if a browser supports
635   *   a certain property, it won't return undefined for it.
636   *
637   * @access private
638   * @function testDOMProps
639   * @param {array.<string>} props - An array of properties to test for
640   * @param {object} obj - An object or Element you want to use to test the parameters again
641   * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
642   */
643  function testDOMProps(props, obj, elem) {
644    var item;
645
646    for (var i in props) {
647      if (props[i] in obj) {
648
649        // return the property name as a string
650        if (elem === false) {
651          return props[i];
652        }
653
654        item = obj[props[i]];
655
656        // let's bind a function
657        if (is(item, 'function')) {
658          // bind to obj unless overriden
659          return fnBind(item, elem || obj);
660        }
661
662        // return the unbound function or obj or value
663        return item;
664      }
665    }
666    return false;
667  }
668
669  ;
670
671  /**
672   * testPropsAll tests a list of DOM properties we want to check against.
673   * We specify literally ALL possible (known and/or likely) properties on
674   * the element including the non-vendor prefixed one, for forward-
675   * compatibility.
676   *
677   * @access private
678   * @function testPropsAll
679   * @param {string} prop - A string of the property to test for
680   * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
681   * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
682   * @param {string} [value] - A string of a css value
683   * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
684   */
685  function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
686
687    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
688    props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
689
690    // did they call .prefixed('boxSizing') or are we just testing a prop?
691    if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
692      return testProps(props, prefixed, value, skipValueTest);
693
694      // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
695    } else {
696      props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
697      return testDOMProps(props, prefixed, elem);
698    }
699  }
700
701  // Modernizr.testAllProps() investigates whether a given style property,
702  // or any of its vendor-prefixed variants, is recognized
703  //
704  // Note that the property names must be provided in the camelCase variant.
705  // Modernizr.testAllProps('boxSizing')
706  ModernizrProto.testAllProps = testPropsAll;
707
708  
709
710  /**
711   * testAllProps determines whether a given CSS property is supported in the browser
712   *
713   * @memberof Modernizr
714   * @name Modernizr.testAllProps
715   * @optionName Modernizr.testAllProps()
716   * @optionProp testAllProps
717   * @access public
718   * @function testAllProps
719   * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
720   * @param {string} [value] - String of the value to test
721   * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
722   * @example
723   *
724   * testAllProps determines whether a given CSS property, in some prefixed form,
725   * is supported by the browser.
726   *
727   * ```js
728   * testAllProps('boxSizing')  // true
729   * ```
730   *
731   * It can optionally be given a CSS value in string form to test if a property
732   * value is valid
733   *
734   * ```js
735   * testAllProps('display', 'block') // true
736   * testAllProps('display', 'penguin') // false
737   * ```
738   *
739   * A boolean can be passed as a third parameter to skip the value check when
740   * native detection (@supports) isn't available.
741   *
742   * ```js
743   * testAllProps('shapeOutside', 'content-box', true);
744   * ```
745   */
746
747  function testAllProps(prop, value, skipValueTest) {
748    return testPropsAll(prop, undefined, undefined, value, skipValueTest);
749  }
750  ModernizrProto.testAllProps = testAllProps;
751  
752
753  /**
754   * testStyles injects an element with style element and some CSS rules
755   *
756   * @memberof Modernizr
757   * @name Modernizr.testStyles
758   * @optionName Modernizr.testStyles()
759   * @optionProp testStyles
760   * @access public
761   * @function testStyles
762   * @param {string} rule - String representing a css rule
763   * @param {function} callback - A function that is used to test the injected element
764   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
765   * @param {string[]}
765 [testnames] - An array of strings that are used as ids for the additional nodes
766   * @returns {boolean}
767   * @example
768   *
769   * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
770   * along with (possibly multiple) DOM elements. This lets you check for features
771   * that can not be detected by simply checking the [IDL](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Interface_development_guide/IDL_interface_rules).
772   *
773   * ```js
774   * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
775   *   // elem is the first DOM node in the page (by default #modernizr)
776   *   // rule is the first argument you supplied - the CSS rule in string form
777   *
778   *   addTest('widthworks', elem.style.width === '9px')
779   * });
780   * ```
781   *
782   * If your test requires multiple nodes, you can include a third argument
783   * indicating how many additional div elements to include on the page. The
784   * additional nodes are injected as children of the `elem` that is returned as
785   * the first argument to the callback.
786   *
787   * ```js
788   * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
789   *   document.getElementById('modernizr').style.width === '1px'; // true
790   *   document.getElementById('modernizr2').style.width === '2px'; // true
791   *   elem.firstChild === document.getElementById('modernizr2'); // true
792   * }, 1);
793   * ```
794   *
795   * By default, all of the additional elements have an ID of `modernizr[n]`, where
796   * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
797   * the second additional is `#modernizr3`, etc.).
798   * If you want to have more meaningful IDs for your function, you can provide
799   * them as the fourth argument, as an array of strings
800   *
801   * ```js
802   * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
803   *   elem.firstChild === document.getElementById('foo'); // true
804   *   elem.lastChild === document.getElementById('bar'); // true
805   * }, 2, ['foo', 'bar']);
806   * ```
807   *
808   */
809
810  var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
811  
812/*!
813{
814  "name": "CSS Supports",
815  "property": "supports",
816  "caniuse": "css-featurequeries",
817  "tags": ["css"],
818  "builderAliases": ["css_supports"],
819  "notes": [{
820    "name": "W3 Spec",
821    "href": "http://dev.w3.org/csswg/css3-conditional/#at-supports"
822  },{
823    "name": "Related Github Issue",
824    "href": "github.com/Modernizr/Modernizr/issues/648"
825  },{
826    "name": "W3 Info",
827    "href": "http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface"
828  }]
829}
830!*/
831
832  var newSyntax = 'CSS' in window && 'supports' in window.CSS;
833  var oldSyntax = 'supportsCSS' in window;
834  Modernizr.addTest('supports', newSyntax || oldSyntax);
835
836/*!
837{
838  "name": "CSS Transforms 3D",
839  "property": "csstransforms3d",
840  "caniuse": "transforms3d",
841  "tags": ["css"],
842  "warnings": [
843    "Chrome may occassionally fail this test on some systems; more info: https://code.google.com/p/chromium/issues/detail?id=129004"
844  ]
845}
846!*/
847
848  Modernizr.addTest('csstransforms3d', function() {
849    var ret = !!testAllProps('perspective', '1px', true);
850    var usePrefix = Modernizr._config.usePrefixes;
851
852    // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
853    //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
854    //   some conditions. As a result, Webkit typically recognizes the syntax but
855    //   will sometimes throw a false positive, thus we must do a more thorough check:
856    if (ret && (!usePrefix || 'webkitPerspective' in docElement.style)) {
857      var mq;
858      var defaultStyle = '#modernizr{width:0;height:0}';
859      // Use CSS Conditional Rules if available
860      if (Modernizr.supports) {
861        mq = '@supports (perspective: 1px)';
862      } else {
863        // Otherwise, Webkit allows this media query to succeed only if the feature is enabled.
864        // `@media (transform-3d),(-webkit-transform-3d){ ... }`
865        mq = '@media (transform-3d)';
866        if (usePrefix) {
867          mq += ',(-webkit-transform-3d)';
868        }
869      }
870
871      mq += '{#modernizr{width:7px;height:18px;margin:0;padding:0;border:0}}';
872
873      testStyles(defaultStyle + mq, function(elem) {
874        ret = elem.offsetWidth === 7 && elem.offsetHeight === 18;
875      });
876    }
877
878    return ret;
879  });
880
881
882  // Run each test
883  testRunner();
884
885  // Remove the "no-js" class if it exists
886  setClasses(classes);
887
888  delete ModernizrProto.addTest;
889  delete ModernizrProto.addAsyncTest;
890
891  // Run the things that are supposed to run after the tests
892  for (var i = 0; i < Modernizr._q.length; i++) {
893    Modernizr._q[i]();
894  }
895
896  // Leak Modernizr namespace
897  window.Modernizr = Modernizr;
898
899
900;
901
902})(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.