PageSourceSearch

https://xn--80ans3e.xn--j1amh/wp-content/themes/magazine-hoot/js/modernizr.custom.js?ver=2.8.3

js xn--80ans3e.xn--j1amh collected 2026-10-08 23:47:47 UTC 57,015 bytes, 1,706 lines download raw bytes

1/*!
2 * modernizr v3.3.1
3 * Build https://modernizr.com/download?-backgroundsize-borderimage-borderradius-boxshadow-cssanimations-csstransforms-csstransforms3d-csstransitions-fontface-generatedcontent-inlinesvg-opacity-rgba-textshadow-touchevents-domprefixes-mq-prefixes-setclasses-shiv-testallprops-testprop-teststyles-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 classes = [];
27  
28
29  var tests = [];
30  
31
32  /**
33   *
34   * ModernizrProto is the constructor for Modernizr
35   *
36   * @class
37   * @access public
38   */
39
40  var ModernizrProto = {
41    // The current version, dummy
42    _version: '3.3.1',
43
44    // Any settings that don't work as separate modules
45    // can go in here as configuration.
46    _config: {
47      'classPrefix': '',
48      'enableClasses': true,
49      'enableJSClass': true,
50      'usePrefixes': true
51    },
52
53    // Queue of tests
54    _q: [],
55
56    // Stub these for people who are listening
57    on: function(test, cb) {
58      // I don't really think people should do this, but we can
59      // safe guard it a bit.
60      // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
61      // This is in case people listen to synchronous tests. I would leave it out,
62      // but the code to *disallow* sync tests in the real version of this
63      // function is actually larger than this.
64      var self = this;
65      setTimeout(function() {
66        cb(self[test]);
67      }, 0);
68    },
69
70    addTest: function(name, fn, options) {
71      tests.push({name: name, fn: fn, options: options});
72    },
73
74    addAsyncTest: function(fn) {
75      tests.push({name: null, fn: fn});
76    }
77  };
78
79  
80
81  // Fake some of Object.create so we can force non test results to be non "own" properties.
82  var Modernizr = function() {};
83  Modernizr.prototype = ModernizrProto;
84
85  // Leak modernizr globally when you `require` it rather than force it here.
86  // Overwrite name so constructor name is nicer :D
87  Modernizr = new Modernizr();
88
89  
90
91  /**
92   * List of property values to set for css tests. See ticket #21
93   * http://git.io/vUGl4
94   *
95   * @memberof Modernizr
96   * @name Modernizr._prefixes
97   * @optionName Modernizr._prefixes
98   * @optionProp prefixes
99   * @access public
100   * @example
101   *
102   * Modernizr._prefixes is the internal list of prefixes that we test against
103   * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply
104   * an array of kebab-case vendor prefixes you can use within your code.
105   *
106   * Some common use cases include
107   *
108   * Generating all possible prefixed version of a CSS property
109   * ```js
110   * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');
111   *
112   * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'
113   * ```
114   *
115   * Generating all possible prefixed version of a CSS value
116   * ```js
117   * rule = 'display:' +  Modernizr._prefixes.join('flex; display:') + 'flex';
118   *
119   * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'
120   * ```
121   */
122
123  // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test
124  // values in feature detects to continue to work
125  var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);
126
127  // expose these for the plugin API. Look in the source for how to join() them against your input
128  ModernizrProto._prefixes = prefixes;
129
130  
131
132  /**
133   * is returns a boolean if the typeof an obj is exactly type.
134   *
135   * @access private
136   * @function is
137   * @param {*} obj - A thing we want to check the type of
138   * @param {string} type - A string to compare the typeof against
139   * @returns {boolean}
140   */
141
142  function is(obj, type) {
143    return typeof obj === type;
144  }
145  ;
146
147  /**
148   * Run through all tests and detect their support in the current UA.
149   *
150   * @access private
151   */
152
153  function testRunner() {
154    var featureNames;
155    var feature;
156    var aliasIdx;
157    var result;
158    var nameIdx;
159    var featureName;
160    var featureNameSplit;
161
162    for (var featureIdx in tests) {
163      if (tests.hasOwnProperty(featureIdx)) {
164        featureNames = [];
165        feature = tests[featureIdx];
166        // run the test, throw the return value into the Modernizr,
167        // then based on that boolean, define an appropriate className
168        // and push it into an array of classes we'll join later.
169        //
170        // If there is no name, it's an 'async' test that is run,
171        // but not directly added to the object. That should
172        // be done with a post-run addTest call.
173        if (feature.name) {
174          featureNames.push(feature.name.toLowerCase());
175
176          if (feature.options && feature.options.aliases && feature.options.aliases.length) {
177            // Add all the aliases into the names list
178            for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
179              featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
180            }
181          }
182        }
183
184        // Run the test, or use the raw value if it's not a function
185        result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
186
187
188        // Set each of the names on the Modernizr object
189        for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
190          featureName = featureNames[nameIdx];
191          // Support dot properties as sub tests. We don't do checking to make sure
192          // that the implied parent tests have been added. You must call them in
193          // order (either in the test, or make the parent test a dependency).
194          //
195          // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
196          // hashtag famous last words
197          featureNameSplit = featureName.split('.');
198
199          if (featureNameSplit.length === 1) {
200            Modernizr[featureNameSplit[0]] = result;
201          } else {
202            // cast to a Boolean, if not one already
203            /* jshint -W053 */
204            if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
205              Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
206            }
207
208            Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
209          }
210
211          classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
212        }
213      }
214    }
215  }
216  ;
217
218  /**
219   * docElement is a convenience wrapper to grab the root element of the document
220   *
221   * @access private
222   * @returns {HTMLElement|SVGElement} The root element of the document
223   */
224
225  var docElement = document.documentElement;
226  
227
228  /**
229   * A convenience helper to check if the document we are running in is an SVG document
230   *
231   * @access private
232   * @returns {boolean}
233   */
234
235  var isSVG = docElement.nodeName.toLowerCase() === 'svg';
236  
237
238  /**
239   * setClasses takes an array of class names and adds them to the root element
240   *
241   * @access private
242   * @function setClasses
243   * @param {string[]} classes - Array of class names
244   */
245
246  // Pass in an and array of class names, e.g.:
247  //  ['no-webp', 'borderradius', ...]
248  function setClasses(classes) {
249    var className = docElement.className;
250    var classPrefix = Modernizr._config.classPrefix || '';
251
252    if (isSVG) {
253      className = className.baseVal;
254    }
255
256    // Change `no-js` to `js` (independently of the `enableClasses` option)
257    // Handle classPrefix on this too
258    if (Modernizr._config.enableJSClass) {
259      var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
260      className = className.replace(reJS, '$1' + classPrefix + 'js$2');
261    }
262
263    if (Modernizr._config.enableClasses) {
264      // Add the new classes
265      className += ' ' + classPrefix + classes.join(' ' + classPrefix);
266      isSVG ? docElement.className.baseVal = className : docElement.className = className;
267    }
268
269  }
270
271  ;
272
273/**
274  * @optionName html5shiv
275  * @optionProp html5shiv
276  */
277
278  // Take the html5 variable out of the html5shiv scope so we can return it.
279  var html5;
280  if (!isSVG) {
281    /**
282     * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
283     */
284    ;(function(window, document) {
285      /*jshint evil:true */
286      /** version */
287      var version = '3.7.3';
288
289      /** Preset options */
290      var options = window.html5 || {};
291
292      /** Used to skip problem elements */
293      var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
294
295      /** Not all elements can be cloned in IE **/
296      var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
297
298      /** Detect whether the browser supports default html5 styles */
299      var supportsHtml5Styles;
300
301      /** Name of the expando, to work with multiple documents or to re-shiv one document */
302      var expando = '_html5shiv';
303
304      /** The id for the the documents expando */
305      var expanID = 0;
306
307      /** Cached data for each document */
308      var expandoData = {};
309
310      /** Detect whether the browser supports unknown elements */
311      var supportsUnknownElements;
312
313      (function() {
314        try {
315          var a = document.createElement('a');
316          a.innerHTML = '<xyz></xyz>';
317          //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
318          supportsHtml5Styles = ('hidden' in a);
319
320          supportsUnknownElements = a.childNodes.length == 1 || (function() {
321            // assign a false positive if unable to shiv
322            (document.createElement)('a');
323            var frag = document.createDocumentFragment();
324            return (
325              typeof frag.cloneNode == 'undefined' ||
326                typeof frag.createDocumentFragment == 'undefined' ||
327                typeof frag.createElement == 'undefined'
328            );
329          }());
330        } catch(e) {
331          // assign a false positive if detection fails => unable to shiv
332          supportsHtml5Styles = true;
333          supportsUnknownElements = true;
334        }
335
336      }());
337
338      /*--------------------------------------------------------------------------*/
339
340      /**
341       * Creates a style sheet with the given CSS text and adds it to the document.
342       * @private
343       * @param {Document} ownerDocument The document.
344       * @param {String} cssText The CSS text.
345       * @returns {StyleSheet} The style element.
346       */
347      function addStyleSheet(ownerDocument, cssText) {
348        var p = ownerDocument.createElement('p'),
349          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
350
351        p.innerHTML = 'x<style>' + cssText + '</style>';
352        return parent.insertBefore(p.lastChild, parent.firstChild);
353      }
354
355      /**
356       * Returns the value of `html5.elements` as an array.
357       * @private
358       * @returns {Array} An array of shived element node names.
359       */
360      function getElements() {
361        var elements = html5.elements;
362        return typeof elements == 'string' ? elements.split(' ') : elements;
363      }
364
365      /**
366       * Extends the built-in list of html5 elements
367       * @memberOf html5
368       * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
369       * @param {Document} ownerDocument The context document.
370       */
371      function addElements(newElements, ownerDocument) {
372        var elements = html5.elements;
373        if(typeof elements != 'string'){
374          elements = elements.join(' ');
375        }
376        if(typeof newElements != 'string'){
377          newElements = newElements.join(' ');
378        }
379        html5.elements = elements +' '+ newElements;
380        shivDocument(ownerDocument);
381      }
382
383      /**
384       * Returns the data associated to the given document
385       * @private
386       * @param {Document} ownerDocument The document.
387       * @returns {Object} An object of data.
388       */
389      function getExpandoData(ownerDocument) {
390        var data = expandoData[ownerDocument[expando]];
391        if (!data) {
392          data = {};
393          expanID++;
394          ownerDocument[expando] = expanID;
395          expandoData[expanID] = data;
396        }
397        return data;
398      }
399
400      /**
401       * returns a shived element for the given nodeName and document
402       * @memberOf html5
403       * @param {String}
vendor: 4,529 bytes, lines 403-514
403 nodeName name of the element
404       * @param {Document|DocumentFragment} ownerDocument The context document.
405       * @returns {Object} The shived element.
406       */
407      function createElement(nodeName, ownerDocument, data){
408        if (!ownerDocument) {
409          ownerDocument = document;
410        }
411        if(supportsUnknownElements){
412          return ownerDocument.createElement(nodeName);
413        }
414        if (!data) {
415          data = getExpandoData(ownerDocument);
416        }
417        var node;
418
419        if (data.cache[nodeName]) {
420          node = data.cache[nodeName].cloneNode();
421        } else if (saveClones.test(nodeName)) {
422          node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
423        } else {
424          node = data.createElem(nodeName);
425        }
426
427        // Avoid adding some elements to fragments in IE < 9 because
428        // * Attributes like `name` or `type` cannot be set/changed once an element
429        //   is inserted into a document/fragment
430        // * Link elements with `src` attributes that are inaccessible, as with
431        //   a 403 response, will cause the tab/window to crash
432        // * Script elements appended to fragments will execute when their `src`
433        //   or `text` property is set
434        return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
435      }
436
437      /**
438       * returns a shived DocumentFragment for the given document
439       * @memberOf html5
440       * @param {Document} ownerDocument The context document.
441       * @returns {Object} The shived DocumentFragment.
442       */
443      function createDocumentFragment(ownerDocument, data){
444        if (!ownerDocument) {
445          ownerDocument = document;
446        }
447        if(supportsUnknownElements){
448          return ownerDocument.createDocumentFragment();
449        }
450        data = data || getExpandoData(ownerDocument);
451        var clone = data.frag.cloneNode(),
452          i = 0,
453          elems = getElements(),
454          l = elems.length;
455        for(;i<l;i++){
456          clone.createElement(elems[i]);
457        }
458        return clone;
459      }
460
461      /**
462       * Shivs the `createElement` and `createDocumentFragment` methods of the document.
463       * @private
464       * @param {Document|DocumentFragment} ownerDocument The document.
465       * @param {Object} data of the document.
466       */
467      function shivMethods(ownerDocument, data) {
468        if (!data.cache) {
469          data.cache = {};
470          data.createElem = ownerDocument.createElement;
471          data.createFrag = ownerDocument.createDocumentFragment;
472          data.frag = data.createFrag();
473        }
474
475
476        ownerDocument.createElement = function(nodeName) {
477          //abort shiv
478          if (!html5.shivMethods) {
479            return data.createElem(nodeName);
480          }
481          return createElement(nodeName, ownerDocument, data);
482        };
483
484        ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
485                                                        'var n=f.cloneNode(),c=n.createElement;' +
486                                                        'h.shivMethods&&(' +
487                                                        // unroll the `createElement` calls
488                                                        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
489          data.createElem(nodeName);
490          data.frag.createElement(nodeName);
491          return 'c("' + nodeName + '")';
492        }) +
493          ');return n}'
494                                                       )(html5, data.frag);
495      }
496
497      /*--------------------------------------------------------------------------*/
498
499      /**
500       * Shivs the given document.
501       * @memberOf html5
502       * @param {Document} ownerDocument The document to shiv.
503       * @returns {Document} The shived document.
504       */
505      function shivDocument(ownerDocument) {
506        if (!ownerDocument) {
507          ownerDocument = document;
508        }
509        var data = getExpandoData(ownerDocument);
510
511        if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
512          data.hasCSS = !!addStyleSheet(ownerDocument,
513                                        // corrects block display not defined in IE6/7/8/9
514                                        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
514play:block}' +
515                                        // adds styling not present in IE6/7/8/9
516                                        'mark{background:#FF0;color:#000}' +
517                                        // hides non-rendered elements
518                                        'template{display:none}'
519                                       );
520        }
521        if (!supportsUnknownElements) {
522          shivMethods(ownerDocument, data);
523        }
524        return ownerDocument;
525      }
526
527      /*--------------------------------------------------------------------------*/
528
529      /**
530       * The `html5` object is exposed so that more elements can be shived and
531       * existing shiving can be detected on iframes.
532       * @type Object
533       * @example
534       *
535       * // options can be changed before the script is included
536       * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
537       */
538      var html5 = {
539
540        /**
541         * An array or space separated string of node names of the elements to shiv.
542         * @memberOf html5
543         * @type Array|String
544         */
545        'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
546
547        /**
548         * current version of html5shiv
549         */
550        'version': version,
551
552        /**
553         * A flag to indicate that the HTML5 style sheet should be inserted.
554         * @memberOf html5
555         * @type Boolean
556         */
557        'shivCSS': (options.shivCSS !== false),
558
559        /**
560         * Is equal to true if a browser supports creating unknown/HTML5 elements
561         * @memberOf html5
562         * @type boolean
563         */
564        'supportsUnknownElements': supportsUnknownElements,
565
566        /**
567         * A flag to indicate that the document's `createElement` and `createDocumentFragment`
568         * methods should be overwritten.
569         * @memberOf html5
570         * @type Boolean
571         */
572        'shivMethods': (options.shivMethods !== false),
573
574        /**
575         * A string to describe the type of `html5` object ("default" or "default print").
576         * @memberOf html5
577         * @type String
578         */
579        'type': 'default',
580
581        // shivs the document according to the specified `html5` object options
582        'shivDocument': shivDocument,
583
584        //creates a shived element
585        createElement: createElement,
586
587        //creates a shived documentFragment
588        createDocumentFragment: createDocumentFragment,
589
590        //extends list of elements
591        addElements: addElements
592      };
593
594      /*--------------------------------------------------------------------------*/
595
596      // expose html5
597      window.html5 = html5;
598
599      // shiv the document
600      shivDocument(document);
601
602      if(typeof module == 'object' && module.exports){
603        module.exports = html5;
604      }
605
606    }(typeof window !== "undefined" ? window : this, document));
607  }
608;
609
610  /**
611   * If the browsers follow the spec, then they would expose vendor-specific style as:
612   *   elem.style.WebkitBorderRadius
613   * instead of something like the following, which would be technically incorrect:
614   *   elem.style.webkitBorderRadius
615
616   * Webkit ghosts their properties in lowercase but Opera & Moz do not.
617   * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
618   *   erik.eae.net/archives/2008/03/10/21.48.10/
619
620   * More here: github.com/Modernizr/Modernizr/issues/issue/21
621   *
622   * @access private
623   * @returns {string} The string representing the vendor-specific style properties
624   */
625
626  var omPrefixes = 'Moz O ms Webkit';
627  
628
629  /**
630   * List of JavaScript DOM values used for tests
631   *
632   * @memberof Modernizr
633   * @name Modernizr._domPrefixes
634   * @optionName Modernizr._domPrefixes
635   * @optionProp domPrefixes
636   * @access public
637   * @example
638   *
639   * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
640   * than kebab-case properties, all properties are their Capitalized variant
641   *
642   * ```js
643   * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
644   * ```
645   */
646
647  var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
648  ModernizrProto._domPrefixes = domPrefixes;
649  
650
651  /**
652   * createElement is a convenience wrapper around document.createElement. Since we
653   * use createElement all over the place, this allows for (slightly) smaller code
654   * as well as abstracting away issues with creating elements in contexts other than
655   * HTML documents (e.g. SVG documents).
656   *
657   * @access private
658   * @function createElement
659   * @returns {HTMLElement|SVGElement} An HTML or SVG element
660   */
661
662  function createElement() {
663    if (typeof document.createElement !== 'function') {
664      // This is the case in IE7, where the type of createElement is "object".
665      // For this reason, we cannot call apply() as Object is not a Function.
666      return document.createElement(arguments[0]);
667    } else if (isSVG) {
668      return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
669    } else {
670      return document.createElement.apply(document, arguments);
671    }
672  }
673
674  ;
675/*!
676{
677  "name": "CSS Opacity",
678  "caniuse": "css-opacity",
679  "property": "opacity",
680  "tags": ["css"]
681}
682!*/
683
684  // Browsers that actually have CSS Opacity implemented have done so
685  // according to spec, which means their return values are within the
686  // range of [0.0,1.0] - including the leading zero.
687
688  Modernizr.addTest('opacity', function() {
689    var style = createElement('a').style;
690    style.cssText = prefixes.join('opacity:.55;');
691
692    // The non-literal . in this regex is intentional:
693    // German Chrome returns this value as 0,55
694    // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
695    return (/^0.55$/).test(style.opacity);
696  });
697
698/*!
699{
700  "name": "CSS rgba",
701  "caniuse": "css3-colors",
702  "property": "rgba",
703  "tags": ["css"],
704  "notes": [{
705    "name": "CSSTricks Tutorial",
706    "href": "https://css-tricks.com/rgba-browser-support/"
707  }]
708}
709!*/
710
711  Modernizr.addTest('rgba', function() {
712    var style = createElement('a').style;
713    style.cssText = 'background-color:rgba(150,255,150,.5)';
714
715    return ('' + style.backgroundColor).indexOf('rgba') > -1;
716  });
717
718/*!
719{
720  "name": "Inline SVG",
721  "property": "inlinesvg",
722  "caniuse": "svg-html5",
723  "tags": ["svg"],
724  "notes": [{
725    "name": "Test page",
726    "href": "https://paulirish.com/demo/inline-svg"
727  }, {
728    "name": "Test page and results",
729    "href": "https://codepen.io/eltonmesquita/full/GgXbvo/"
730  }],
731  "polyfills": ["inline-svg-polyfill"],
732  "knownBugs": ["False negative on some Chromia browsers."]
733}
734!*/
735/* DOC
736Detects support for inline SVG in HTML (not within XHTML).
737*/
738
739  Modernizr.addTest('inlinesvg', function() {
740    var div = createElement('div');
741    div.innerHTML = '<svg/>';
742    return (typeof SVGRect != 'undefined' && div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg';
743  });
744
745/*!
746{
747  "name": "CSS Supports",
748  "property": "supports",
749  "caniuse": "css-featurequeries",
750  "tags": ["css"],
751  "builderAliases": ["css_supports"],
752  "notes": [{
753    "name": "W3 Spec",
754    "href": "http://dev.w3.org/csswg/css3-conditional/#at-supports"
755  },{
756    "name": "Related Github Issue",
757    "href": "github.com/Modernizr/Modernizr/issues/648"
758  },{
759    "name": "W3 Info",
760    "href": "http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface"
761  }]
762}
763!*/
764
765  var newSyntax = 'CSS' in window && 'supports' in window.CSS;
766  var oldSyntax = 'supportsCSS' in window;
767  Modernizr.addTest('supports', newSyntax || oldSyntax);
768
769
770  /**
771   * getBody returns the body of a document, or an element that can stand in for
772   * the body if a real body does not exist
773   *
774   * @access private
775   * @function getBody
776   * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
777   * artificially created element that stands in for the body
778   */
779
780  function getBody() {
781    // After page load injecting a fake body doesn't work so check if body exists
782    var body = document.body;
783
784    if (!body) {
785      // Can't use the real body create a fake one.
786      body = createElement(isSVG ? 'svg' : 'body');
787      body.fake = true;
788    }
789
790    return body;
791  }
792
793  ;
794
795  /**
796   * injectElementWithStyles injects an element with style element and some CSS rules
797   *
798   * @access private
799   * @function injectElementWithStyles
800   * @param {string} rule - String representing a css rule
801   * @param {function} callback - A function that is used to test the injected element
802   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
803   * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
804   * @returns {boolean}
805   */
806
807  function injectElementWithStyles(rule, callback, nodes, testnames) {
808    var mod = 'modernizr';
809    var style;
810    var ret;
811    var node;
812    var docOverflow;
813    var div = createElement('div');
814    var body = getBody();
815
816    if (parseInt(nodes, 10)) {
817      // In order not to give false positives we create a node for each test
818      // This also allows the method to scale for unspecified uses
819      while (nodes--) {
820        node = createElement('div');
821        node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
822        div.appendChild(node);
823      }
824    }
825
826    style = createElement('style');
827    style.type = 'text/css';
828    style.id = 's' + mod;
829
830    // 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.
831    // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
832    (!body.fake ? div : body).appendChild(style);
833    body.appendChild(div);
834
835    if (style.styleSheet) {
836      style.styleSheet.cssText = rule;
837    } else {
838      style.appendChild(document.createTextNode(rule));
839    }
840    div.id = mod;
841
842    if (body.fake) {
843      //avoid crashing IE8, if background image is used
844      body.style.background = '';
845      //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
846      body.style.overflow = 'hidden';
847      docOverflow = docElement.style.overflow;
848      docElement.style.overflow = 'hidden';
849      docElement.appendChild(body);
850    }
851
852    ret = callback(div, rule);
853    // If this is done after page load we don't want to remove the body so check if body exists
854    if (body.fake) {
855      body.parentNode.removeChild(body);
856      docElement.style.overflow = docOverflow;
857      // Trigger layout so kinetic scrolling isn't disabled in iOS6+
858      docElement.offsetHeight;
859    } else {
860      div.parentNode.removeChild(div);
861    }
862
863    return !!ret;
864
865  }
866
867  ;
868
869  /**
870   * Modernizr.mq tests a given media query, live against the current state of the window
871   * adapted from matchMedia polyfill by Scott Jehl and Paul Irish
872   * gist.github.com/786768
873   *
874   * @memberof Modernizr
875   * @name Modernizr.mq
876   * @optionName Modernizr.mq()
877   * @optionProp mq
878   * @access public
879   * @function mq
880   * @param {string} mq - String of the media query we want to test
881   * @returns {boolean}
882   * @example
883   * Modernizr.mq allows for you to programmatically check if the current browser
884   * window state matches a media query.
885   *
886   * ```js
887   *  var query = Modernizr.mq('(min-width: 900px)');
888   *
889   *  if (query) {
890   *    // the browser window is larger than 900px
891   *  }
892   * ```
893   *
894   * Only valid media queries are supported, therefore you must always include values
895   * with your media query
896   *
897   * ```js
898   * // good
899   *  Modernizr.mq('(min-width: 900px)');
900   *
901   * // bad
902   *  Modernizr.mq('min-width');
903   * ```
904   *
905   * If you would just like to test that media queries are supported in general, use
906   *
907   * ```js
908   *  Modernizr.mq('only all'); // true if MQ are supported, false if not
909   * ```
910   *
911   *
912   * Note that if the browser does not support media queries (e.g. old IE) mq will
913   * always return false.
914   */
915
916  var mq = (function() {
917    var matchMedia = window.matchMedia || window.msMatchMedia;
918    if (matchMedia) {
919      return function(mq) {
920        var mql = matchMedia(mq);
921        return mql && mql.matches || false;
922      };
923    }
924
925    return function(mq) {
926      var bool = false;
927
928      injectElementWithStyles('@media ' + mq + ' { #modernizr { position: absolute; } }', function(node) {
929        bool = (window.getComputedStyle ?
930                window.getComputedStyle(node, null) :
931                node.currentStyle).position == 'absolute';
932      });
933
934      return bool;
935    };
936  })();
937
938
939  ModernizrProto.mq = mq;
940
941  
942
943  /**
944   * testStyles injects an element with style element and some CSS rules
945   *
946   * @memberof Modernizr
947   * @name Modernizr.testStyles
948   * @optionName Modernizr.testStyles()
949   * @optionProp testStyles
950   * @access public
951   * @function testStyles
952   * @param {string} rule - String representing a css rule
953   * @param {function} callback - A function that is used to test the injected element
954   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
955   * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
956   * @returns {boolean}
957   * @example
958   *
959   * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
960   * along with (possibly multiple) DOM elements. This lets you check for features
961   * 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).
962   *
963   * ```js
964   * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
965   *   // elem is the first DOM node in the page (by default #modernizr)
966   *   // rule is the first argument you supplied - the CSS rule in string form
967   *
968   *   addTest('widthworks', elem.style.width === '9px')
969   * });
970   * ```
971   *
972   * If your test requires multiple nodes, you can include a third argument
973   * indicating how many additional div elements to include on the page. The
974   * additional nodes are injected as children of the `elem` that is returned as
975   * the first argument to the callback.
976   *
977   * ```js
978   * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
979   *   document.getElementById('modernizr').style.width === '1px'; // true
980   *   document.getElementById('modernizr2').style.width === '2px'; // true
981   *   elem.firstChild === document.getElementById('modernizr2'); // true
982   * }, 1);
983   * ```
984   *
985   * By default, all of the additional elements have an ID of `modernizr[n]`, where
986   * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
987   * the second additional is `#modernizr3`, etc.).
988   * If you want to have more meaningful IDs for your function, you can provide
989   * them as the fourth argument, as an array of strings
990   *
991   * ```js
992   * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
993   *   elem.firstChild === document.getElementById('foo'); // true
994   *   elem.lastChild === document.getElementById('bar'); // true
995   * }, 2, ['foo', 'bar']);
996   * ```
997   *
998   */
999
1000  var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
1001  
1002/*!
1003{
1004  "name": "Touch Events",
1005  "property": "touchevents",
1006  "caniuse" : "touch",
1007  "tags": ["media", "attribute"],
1008  "notes": [{
1009    "name": "Touch Events spec",
1010    "href": "https://www.w3.org/TR/2013/WD-touch-events-20130124/"
1011  }],
1012  "warnings": [
1013    "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device"
1014  ],
1015  "knownBugs": [
1016    "False-positive on some configurations of Nokia N900",
1017    "False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695"
1018  ]
1019}
1020!*/
1021/* DOC
1022Indicates if the browser supports the W3C Touch Events API.
1023
1024This *does not* necessarily reflect a touchscreen device:
1025
1026* Older touchscreen devices only emulate mouse events
1027* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that
1028* Some browsers & OS setups may enable touch APIs when no touchscreen is connected
1029* Future browsers may implement other event models for touch interactions
1030
1031See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).
1032
1033It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).
1034
1035This test will also return `true` for Firefox 4 Multitouch support.
1036*/
1037
1038  // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415
1039  Modernizr.addTest('touchevents', function() {
1040    var bool;
1041    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
1042      bool = true;
1043    } else {
1044      // include the 'heartz' as a way to have a non matching MQ to help terminate the join
1045      // https://git.io/vznFH
1046      var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');
1047      testStyles(query, function(node) {
1048        bool = node.offsetTop === 9;
1049      });
1050    }
1051    return bool;
1052  });
1053
1054/*!
1055{
1056  "name": "@font-face",
1057  "property": "fontface",
1058  "authors": ["Diego Perini", "Mat Marquis"],
1059  "tags": ["css"],
1060  "knownBugs": [
1061    "False Positive: WebOS https://github.com/Modernizr/Modernizr/issues/342",
1062    "False Postive: WP7 https://github.com/Modernizr/Modernizr/issues/538"
1063  ],
1064  "notes": [{
1065    "name": "@font-face detection routine by Diego Perini",
1066    "href": "http://javascript.nwbox.com/CSSSupport/"
1067  },{
1068    "name": "Filament Group @font-face compatibility research",
1069    "href": "https://docs.google.com/presentation/d/1n4NyG4uPRjAA8zn_pSQ_
1069Ket0RhcWC6QlZ6LMjKeECo0/edit#slide=id.p"
1070  },{
1071    "name": "Filament Grunticon/@font-face device testing results",
1072    "href": "https://docs.google.com/spreadsheet/ccc?key=0Ag5_yGvxpINRdHFYeUJPNnZMWUZKR2ItMEpRTXZPdUE#gid=0"
1073  },{
1074    "name": "CSS fonts on Android",
1075    "href": "https://stackoverflow.com/questions/3200069/css-fonts-on-android"
1076  },{
1077    "name": "@font-face and Android",
1078    "href": "http://archivist.incutio.com/viewlist/css-discuss/115960"
1079  }]
1080}
1081!*/
1082
1083  var blacklist = (function() {
1084    var ua = navigator.userAgent;
1085    var wkvers = ua.match(/applewebkit\/([0-9]+)/gi) && parseFloat(RegExp.$1);
1086    var webos = ua.match(/w(eb)?osbrowser/gi);
1087    var wppre8 = ua.match(/windows phone/gi) && ua.match(/iemobile\/([0-9])+/gi) && parseFloat(RegExp.$1) >= 9;
1088    var oldandroid = wkvers < 533 && ua.match(/android/gi);
1089    return webos || oldandroid || wppre8;
1090  }());
1091  if (blacklist) {
1092    Modernizr.addTest('fontface', false);
1093  } else {
1094    testStyles('@font-face {font-family:"font";src:url("https://")}', function(node, rule) {
1095      var style = document.getElementById('smodernizr');
1096      var sheet = style.sheet || style.styleSheet;
1097      var cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
1098      var bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
1099      Modernizr.addTest('fontface', bool);
1100    });
1101  }
1102;
1103/*!
1104{
1105  "name": "CSS Generated Content",
1106  "property": "generatedcontent",
1107  "tags": ["css"],
1108  "warnings": ["Android won't return correct height for anything below 7px #738"],
1109  "notes": [{
1110    "name": "W3C CSS Selectors Level 3 spec",
1111    "href": "https://www.w3.org/TR/css3-selectors/#gen-content"
1112  },{
1113    "name": "MDN article on :before",
1114    "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/::before"
1115  },{
1116    "name": "MDN article on :after",
1117    "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/::before"
1118  }]
1119}
1120!*/
1121
1122  testStyles('#modernizr{font:0/0 a}#modernizr:after{content:":)";visibility:hidden;font:7px/1 a}', function(node) {
1123    Modernizr.addTest('generatedcontent', node.offsetHeight >= 7);
1124  });
1125
1126
1127  var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
1128  ModernizrProto._cssomPrefixes = cssomPrefixes;
1129  
1130
1131
1132  /**
1133   * contains checks to see if a string contains another string
1134   *
1135   * @access private
1136   * @function contains
1137   * @param {string} str - The string we want to check for substrings
1138   * @param {string} substr - The substring we want to search the first string for
1139   * @returns {boolean}
1140   */
1141
1142  function contains(str, substr) {
1143    return !!~('' + str).indexOf(substr);
1144  }
1145
1146  ;
1147
1148  /**
1149   * cssToDOM takes a kebab-case string and converts it to camelCase
1150   * e.g. box-sizing -> boxSizing
1151   *
1152   * @access private
1153   * @function cssToDOM
1154   * @param {string} name - String name of kebab-case prop we want to convert
1155   * @returns {string} The camelCase version of the supplied name
1156   */
1157
1158  function cssToDOM(name) {
1159    return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
1160      return m1 + m2.toUpperCase();
1161    }).replace(/^-/, '');
1162  }
1163  ;
1164
1165  /**
1166   * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
1167   *
1168   * @access private
1169   * @function fnBind
1170   * @param {function} fn - a function you want to change `this` reference to
1171   * @param {object} that - the `this` you want to call the function with
1172   * @returns {function} The wrapped version of the supplied function
1173   */
1174
1175  function fnBind(fn, that) {
1176    return function() {
1177      return fn.apply(that, arguments);
1178    };
1179  }
1180
1181  ;
1182
1183  /**
1184   * testDOMProps is a generic DOM property test; if a browser supports
1185   *   a certain property, it won't return undefined for it.
1186   *
1187   * @access private
1188   * @function testDOMProps
1189   * @param {array.<string>} props - An array of properties to test for
1190   * @param {object} obj - An object or Element you want to use to test the parameters again
1191   * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
1192   */
1193  function testDOMProps(props, obj, elem) {
1194    var item;
1195
1196    for (var i in props) {
1197      if (props[i] in obj) {
1198
1199        // return the property name as a string
1200        if (elem === false) {
1201          return props[i];
1202        }
1203
1204        item = obj[props[i]];
1205
1206        // let's bind a function
1207        if (is(item, 'function')) {
1208          // bind to obj unless overriden
1209          return fnBind(item, elem || obj);
1210        }
1211
1212        // return the unbound function or obj or value
1213        return item;
1214      }
1215    }
1216    return false;
1217  }
1218
1219  ;
1220
1221  /**
1222   * Create our "modernizr" element that we do most feature tests on.
1223   *
1224   * @access private
1225   */
1226
1227  var modElem = {
1228    elem: createElement('modernizr')
1229  };
1230
1231  // Clean up this element
1232  Modernizr._q.push(function() {
1233    delete modElem.elem;
1234  });
1235
1236  
1237
1238  var mStyle = {
1239    style: modElem.elem.style
1240  };
1241
1242  // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
1243  // the front of the queue.
1244  Modernizr._q.unshift(function() {
1245    delete mStyle.style;
1246  });
1247
1248  
1249
1250  /**
1251   * domToCSS takes a camelCase string and converts it to kebab-case
1252   * e.g. boxSizing -> box-sizing
1253   *
1254   * @access private
1255   * @function domToCSS
1256   * @param {string} name - String name of camelCase prop we want to convert
1257   * @returns {string} The kebab-case version of the supplied name
1258   */
1259
1260  function domToCSS(name) {
1261    return name.replace(/([A-Z])/g, function(str, m1) {
1262      return '-' + m1.toLowerCase();
1263    }).replace(/^ms-/, '-ms-');
1264  }
1265  ;
1266
1267  /**
1268   * nativeTestProps allows for us to use native feature detection functionality if available.
1269   * some prefixed form, or false, in the case of an unsupported rule
1270   *
1271   * @access private
1272   * @function nativeTestProps
1273   * @param {array} props - An array of property names
1274   * @param {string} value - A string representing the value we want to check via @supports
1275   * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
1276   */
1277
1278  // Accepts a list of property names and a single value
1279  // Returns `undefined` if native detection not available
1280  function nativeTestProps(props, value) {
1281    var i = props.length;
1282    // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
1283    if ('CSS' in window && 'supports' in window.CSS) {
1284      // Try every prefixed variant of the property
1285      while (i--) {
1286        if (window.CSS.supports(domToCSS(props[i]), value)) {
1287          return true;
1288        }
1289      }
1290      return false;
1291    }
1292    // Otherwise fall back to at-rule (for Opera 12.x)
1293    else if ('CSSSupportsRule' in window) {
1294      // Build a condition string for every prefixed variant
1295      var conditionText = [];
1296      while (i--) {
1297        conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
1298      }
1299      conditionText = conditionText.join(' or ');
1300      return injectElementWithStyles('@supports (' + conditionText 
1300+ ') { #modernizr { position: absolute; } }', function(node) {
1301        return getComputedStyle(node, null).position == 'absolute';
1302      });
1303    }
1304    return undefined;
1305  }
1306  ;
1307
1308  // testProps is a generic CSS / DOM property test.
1309
1310  // In testing support for a given CSS property, it's legit to test:
1311  //    `elem.style[styleName] !== undefined`
1312  // If the property is supported it will return an empty string,
1313  // if unsupported it will return undefined.
1314
1315  // We'll take advantage of this quick test and skip setting a style
1316  // on our modernizr element, but instead just testing undefined vs
1317  // empty string.
1318
1319  // Property names can be provided in either camelCase or kebab-case.
1320
1321  function testProps(props, prefixed, value, skipValueTest) {
1322    skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
1323
1324    // Try native detect first
1325    if (!is(value, 'undefined')) {
1326      var result = nativeTestProps(props, value);
1327      if (!is(result, 'undefined')) {
1328        return result;
1329      }
1330    }
1331
1332    // Otherwise do it properly
1333    var afterInit, i, propsLength, prop, before;
1334
1335    // If we don't have a style element, that means we're running async or after
1336    // the core tests, so we'll need to create our own elements to use
1337
1338    // inside of an SVG element, in certain browsers, the `style` element is only
1339    // defined for valid tags. Therefore, if `modernizr` does not have one, we
1340    // fall back to a less used element and hope for the best.
1341    // for strict XHTML browsers the hardly used samp element is used
1342    var elems = ['modernizr', 'tspan', 'samp'];
1343    while (!mStyle.style && elems.length) {
1344      afterInit = true;
1345      mStyle.modElem = createElement(elems.shift());
1346      mStyle.style = mStyle.modElem.style;
1347    }
1348
1349    // Delete the objects if we created them.
1350    function cleanElems() {
1351      if (afterInit) {
1352        delete mStyle.style;
1353        delete mStyle.modElem;
1354      }
1355    }
1356
1357    propsLength = props.length;
1358    for (i = 0; i < propsLength; i++) {
1359      prop = props[i];
1360      before = mStyle.style[prop];
1361
1362      if (contains(prop, '-')) {
1363        prop = cssToDOM(prop);
1364      }
1365
1366      if (mStyle.style[prop] !== undefined) {
1367
1368        // If value to test has been passed in, do a set-and-check test.
1369        // 0 (integer) is a valid property value, so check that `value` isn't
1370        // undefined, rather than just checking it's truthy.
1371        if (!skipValueTest && !is(value, 'undefined')) {
1372
1373          // Needs a try catch block because of old IE. This is slow, but will
1374          // be avoided in most cases because `skipValueTest` will be used.
1375          try {
1376            mStyle.style[prop] = value;
1377          } catch (e) {}
1378
1379          // If the property value has changed, we assume the value used is
1380          // supported. If `value` is empty string, it'll fail here (because
1381          // it hasn't changed), which matches how browsers have implemented
1382          // CSS.supports()
1383          if (mStyle.style[prop] != before) {
1384            cleanElems();
1385            return prefixed == 'pfx' ? prop : true;
1386          }
1387        }
1388        // Otherwise just return true, or the property name if this is a
1389        // `prefixed()` call
1390        else {
1391          cleanElems();
1392          return prefixed == 'pfx' ? prop : true;
1393        }
1394      }
1395    }
1396    cleanElems();
1397    return false;
1398  }
1399
1400  ;
1401
1402  /**
1403   * testProp() investigates whether a given style property is recognized
1404   * Property names can be provided in either camelCase or kebab-case.
1405   *
1406   * @memberof Modernizr
1407   * @name Modernizr.testProp
1408   * @access public
1409   * @optionName Modernizr.testProp()
1410   * @optionProp testProp
1411   * @function testProp
1412   * @param {string} prop - Name of the CSS property to check
1413   * @param {string} [value] - Name of the CSS value to check
1414   * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
1415   * @returns {boolean}
1416   * @example
1417   *
1418   * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
1419   * version of the string.
1420   *
1421   * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
1422   *
1423   * ```js
1424   * Modernizr.testProp('pointerEvents')  // true
1425   * ```
1426   *
1427   * You can also provide a value as an optional second argument to check if a
1428   * specific value is supported
1429   *
1430   * ```js
1431   * Modernizr.testProp('pointerEvents', 'none') // true
1432   * Modernizr.testProp('pointerEvents', 'penguin') // false
1433   * ```
1434   */
1435
1436  var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
1437    return testProps([prop], undefined, value, useValue);
1438  };
1439  
1440/*!
1441{
1442  "name": "CSS textshadow",
1443  "property": "textshadow",
1444  "caniuse": "css-textshadow",
1445  "tags": ["css"],
1446  "knownBugs": ["FF3.0 will false positive on this test"]
1447}
1448!*/
1449
1450  Modernizr.addTest('textshadow', testProp('textShadow', '1px 1px'));
1451
1452
1453  /**
1454   * testPropsAll tests a list of DOM properties we want to check against.
1455   * We specify literally ALL possible (known and/or likely) properties on
1456   * the element including the non-vendor prefixed one, for forward-
1457   * compatibility.
1458   *
1459   * @access private
1460   * @function testPropsAll
1461   * @param {string} prop - A string of the property to test for
1462   * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
1463   * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
1464   * @param {string} [value] - A string of a css value
1465   * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
1466   */
1467  function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
1468
1469    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
1470    props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
1471
1472    // did they call .prefixed('boxSizing') or are we just testing a prop?
1473    if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
1474      return testProps(props, prefixed, value, skipValueTest);
1475
1476      // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
1477    } else {
1478      props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
1479      return testDOMProps(props, prefixed, elem);
1480    }
1481  }
1482
1483  // Modernizr.testAllProps() investigates whether a given style property,
1484  // or any of its vendor-prefixed variants, is recognized
1485  //
1486  // Note that the property names must be provided in the camelCase variant.
1487  // Modernizr.testAllProps('boxSizing')
1488  ModernizrProto.testAllProps = testPropsAll;
1489
1490  
1491
1492  /**
1493   * testAllProps determines whether a given CSS property is supported in the browser
1494   *
1495   * @memberof Modernizr
1496   * @name Modernizr.testAllProps
1497   * @optionName Modernizr.testAllProps()
1498   * @optionProp testAllProps
1499   * @access public
1500   * @function testAllProps
1501   * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
1502   * @param {string} [value] - String of the value to test
1503   * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
1504   * @example
1505   *
1506   * testAllProps determines whether a given CSS property, in some prefixed form,
1507   * is supported by the browser.
1508   *
1509   * ```js
1510   * testAllProps('boxSizing')  // true
1511   * ```
1512   *
1513   * It can optionally be given a CSS value in string form to test if a property
1514   * value is valid
1515   *
1516   * ```js
1517   * testAllProps('display', 'block') // true
1518   * testAllProps('display', 'penguin') // false
1519   * ```
1520   *
1521   * A boolean can be passed as a third parameter to skip the value check when
1522   * native detection (@supports) isn't available.
1523   *
1524   * ```js
1525   * testAllProps('shapeOutside', 'content-box', true);
1526   * ```
1527   */
1528
1529  function testAllProps(prop, value, skipValueTest) {
1530    return testPropsAll(prop, undefined, undefined, value, skipValueTest);
1531  }
1532  ModernizrProto.testAllProps = testAllProps;
1533  
1534/*!
1535{
1536  "name": "CSS Animations",
1537  "property": "cssanimations",
1538  "caniuse": "css-animation",
1539  "polyfills": ["transformie", "csssandpaper"],
1540  "tags": ["css"],
1541  "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
1542  "notes": [{
1543    "name" : "Article: 'Dispelling the Android CSS animation myths'",
1544    "href": "https://goo.gl/OGw5Gm"
1545  }]
1546}
1547!*/
1548/* DOC
1549Detects whether or not elements can be animated using CSS
1550*/
1551
1552  Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
1553
1554/*!
1555{
1556  "name": "Background Size",
1557  "property": "backgroundsize",
1558  "tags": ["css"],
1559  "knownBugs": ["This will false positive in Opera Mini - https://github.com/Modernizr/Modernizr/issues/396"],
1560  "notes": [{
1561    "name": "Related Issue",
1562    "href": "https://github.com/Modernizr/Modernizr/issues/396"
1563  }]
1564}
1565!*/
1566
1567  Modernizr.addTest('backgroundsize', testAllProps('backgroundSize', '100%', true));
1568
1569/*!
1570{
1571  "name": "Border Image",
1572  "property": "borderimage",
1573  "caniuse": "border-image",
1574  "polyfills": ["css3pie"],
1575   "knownBugs": ["Android < 2.0 is true, but has a broken implementation"],
1576  "tags": ["css"]
1577}
1578!*/
1579
1580  Modernizr.addTest('borderimage', testAllProps('borderImage', 'url() 1', true));
1581
1582/*!
1583{
1584  "name": "Border Radius",
1585  "property": "borderradius",
1586  "caniuse": "border-radius",
1587  "polyfills": ["css3pie"],
1588  "tags": ["css"],
1589  "notes": [{
1590    "name": "Comprehensive Compat Chart",
1591    "href": "https://muddledramblings.com/table-of-css3-border-radius-compliance"
1592  }]
1593}
1594!*/
1595
1596  Modernizr.addTest('borderradius', testAllProps('borderRadius', '0px', true));
1597
1598/*!
1599{
1600  "name": "Box Shadow",
1601  "property": "boxshadow",
1602  "caniuse": "css-boxshadow",
1603  "tags": ["css"],
1604  "knownBugs": [
1605    "WebOS false positives on this test.",
1606    "The Kindle Silk browser false positives"
1607  ]
1608}
1609!*/
1610
1611  Modernizr.addTest('boxshadow', testAllProps('boxShadow', '1px 1px', true));
1612
1613/*!
1614{
1615  "name": "CSS Transforms",
1616  "property": "csstransforms",
1617  "caniuse": "transforms2d",
1618  "tags": ["css"]
1619}
1620!*/
1621
1622  Modernizr.addTest('csstransforms', function() {
1623    // Android < 3.0 is buggy, so we sniff and blacklist
1624    // http://git.io/hHzL7w
1625    return navigator.userAgent.indexOf('Android 2.') === -1 &&
1626           testAllProps('transform', 'scale(1)', true);
1627  });
1628
1629/*!
1630{
1631  "name": "CSS Transforms 3D",
1632  "property": "csstransforms3d",
1633  "caniuse": "transforms3d",
1634  "tags": ["css"],
1635  "warnings": [
1636    "Chrome may occassionally fail this test on some systems; more info: https://code.google.com/p/chromium/issues/detail?id=129004"
1637  ]
1638}
1639!*/
1640
1641  Modernizr.addTest('csstransforms3d', function() {
1642    var ret = !!testAllProps('perspective', '1px', true);
1643    var usePrefix = Modernizr._config.usePrefixes;
1644
1645    // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
1646    //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
1647    //   some conditions. As a result, Webkit typically recognizes the syntax but
1648    //   will sometimes throw a false positive, thus we must do a more thorough check:
1649    if (ret && (!usePrefix || 'webkitPerspective' in docElement.style)) {
1650      var mq;
1651      var defaultStyle = '#modernizr{width:0;height:0}';
1652      // Use CSS Conditional Rules if available
1653      if (Modernizr.supports) {
1654        mq = '@supports (perspective: 1px)';
1655      } else {
1656        // Otherwise, Webkit allows this media query to succeed only if the feature is enabled.
1657        // `@media (transform-3d),(-webkit-transform-3d){ ... }`
1658        mq = '@media (transform-3d)';
1659        if (usePrefix) {
1660          mq += ',(-webkit-transform-3d)';
1661        }
1662      }
1663
1664      mq += '{#modernizr{width:7px;height:18px;margin:0;padding:0;border:0}}';
1665
1666      testStyles(defaultStyle + mq, function(elem) {
1667        ret = elem.offsetWidth === 7 && elem.offsetHeight === 18;
1668      });
1669    }
1670
1671    return ret;
1672  });
1673
1674/*!
1675{
1676  "name": "CSS Transitions",
1677  "property": "csstransitions",
1678  "caniuse": "css-transitions",
1679  "tags": ["css"]
1680}
1681!*/
1682
1683  Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true));
1684
1685
1686  // Run each test
1687  testRunner();
1688
1689  // Remove the "no-js" class if it exists
1690  setClasses(classes);
1691
1692  delete ModernizrProto.addTest;
1693  delete ModernizrProto.addAsyncTest;
1694
1695  // Run the things that are supposed to run after the tests
1696  for (var i = 0; i < Modernizr._q.length; i++) {
1697    Modernizr._q[i]();
1698  }
1699
1700  // Leak Modernizr namespace
1701  window.Modernizr = Modernizr;
1702
1703
1704;
1705
1706})(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.