PageSourceSearch

https://portal.minsterlaw.co.uk/scripts.617ea3354da11990.js

js minsterlaw.co.uk collected 2026-10-06 01:30:22 UTC 85,685 bytes, 2,583 lines download raw bytes

1//FIX EXTERNAL SVG THING
2var ajax = new XMLHttpRequest();
3ajax.open("GET", "../images/defs.svg", true);
4ajax.send();
5ajax.onload = function(e) {
6  var div = document.createElement("div");  
7  div.innerHTML = ajax.responseText;
8  var svg = div.firstChild;
9  document.body.insertBefore(svg, document.body.childNodes[0]);
10};
11;/*!
12 * modernizr v3.6.0
13 * Build https://modernizr.com/download?-backgroundblendmode-backgroundsize-borderradius-cookies-cssanimations-csscalc-cssfilters-cssgradients-cssinvalid-cssremunit-csstransforms-csstransforms3d-csstransitions-cssvhunit-cssvwunit-eventlistener-filereader-filesystem-flexbox-fontface-fullscreen-hiddenscroll-inlinesvg-input-inputtypes-json-opacity-shapes-smil-stylescoped-svg-svgasimg-svgclippaths-svgfilters-svgforeignobject-textshadow-touchevents-video-videoautoplay-setclasses-dontmin
14 *
15 * Copyright (c)
16 *  Faruk Ates
17 *  Paul Irish
18 *  Alex Sexton
19 *  Ryan Seddon
20 *  Patrick Kettner
21 *  Stu Cox
22 *  Richard Herrera
23
24 * MIT License
25 */
26
27/*
28 * Modernizr tests which native CSS3 and HTML5 features are available in the
29 * current UA and makes the results available to you in two ways: as properties on
30 * a global `Modernizr` object, and as classes on the `<html>` element. This
31 * information allows you to progressively enhance your pages with a granular level
32 * of control over the experience.
33*/
34
35;(function(window, document, undefined){
36  var tests = [];
37  
38
39  /**
40   *
41   * ModernizrProto is the constructor for Modernizr
42   *
43   * @class
44   * @access public
45   */
46
47  var ModernizrProto = {
48    // The current version, dummy
49    _version: '3.6.0',
50
51    // Any settings that don't work as separate modules
52    // can go in here as configuration.
53    _config: {
54      'classPrefix': '',
55      'enableClasses': true,
56      'enableJSClass': true,
57      'usePrefixes': true
58    },
59
60    // Queue of tests
61    _q: [],
62
63    // Stub these for people who are listening
64    on: function(test, cb) {
65      // I don't really think people should do this, but we can
66      // safe guard it a bit.
67      // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
68      // This is in case people listen to synchronous tests. I would leave it out,
69      // but the code to *disallow* sync tests in the real version of this
70      // function is actually larger than this.
71      var self = this;
72      setTimeout(function() {
73        cb(self[test]);
74      }, 0);
75    },
76
77    addTest: function(name, fn, options) {
78      tests.push({name: name, fn: fn, options: options});
79    },
80
81    addAsyncTest: function(fn) {
82      tests.push({name: null, fn: fn});
83    }
84  };
85
86  
87
88  // Fake some of Object.create so we can force non test results to be non "own" properties.
89  var Modernizr = function() {};
90  Modernizr.prototype = ModernizrProto;
91
92  // Leak modernizr globally when you `require` it rather than force it here.
93  // Overwrite name so constructor name is nicer :D
94  Modernizr = new Modernizr();
95
96  
97
98  var classes = [];
99  
100
101  /**
102   * is returns a boolean if the typeof an obj is exactly type.
103   *
104   * @access private
105   * @function is
106   * @param {*} obj - A thing we want to check the type of
107   * @param {string} type - A string to compare the typeof against
108   * @returns {boolean}
109   */
110
111  function is(obj, type) {
112    return typeof obj === type;
113  }
114  ;
115
116  /**
117   * Run through all tests and detect their support in the current UA.
118   *
119   * @access private
120   */
121
122  function testRunner() {
123    var featureNames;
124    var feature;
125    var aliasIdx;
126    var result;
127    var nameIdx;
128    var featureName;
129    var featureNameSplit;
130
131    for (var featureIdx in tests) {
132      if (tests.hasOwnProperty(featureIdx)) {
133        featureNames = [];
134        feature = tests[featureIdx];
135        // run the test, throw the return value into the Modernizr,
136        // then based on that boolean, define an appropriate className
137        // and push it into an array of classes we'll join later.
138        //
139        // If there is no name, it's an 'async' test that is run,
140        // but not directly added to the object. That should
141        // be done with a post-run addTest call.
142        if (feature.name) {
143          featureNames.push(feature.name.toLowerCase());
144
145          if (feature.options && feature.options.aliases && feature.options.aliases.length) {
146            // Add all the aliases into the names list
147            for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
148              featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
149            }
150          }
151        }
152
153        // Run the test, or use the raw value if it's not a function
154        result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
155
156
157        // Set each of the names on the Modernizr object
158        for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
159          featureName = featureNames[nameIdx];
160          // Support dot properties as sub tests. We don't do checking to make sure
161          // that the implied parent tests have been added. You must call them in
162          // order (either in the test, or make the parent test a dependency).
163          //
164          // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
165          // hashtag famous last words
166          featureNameSplit = featureName.split('.');
167
168          if (featureNameSplit.length === 1) {
169            Modernizr[featureNameSplit[0]] = result;
170          } else {
171            // cast to a Boolean, if not one already
172            if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
173              Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
174            }
175
176            Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
177          }
178
179          classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
180        }
181      }
182    }
183  }
184  ;
185
186  /**
187   * docElement is a convenience wrapper to grab the root element of the document
188   *
189   * @access private
190   * @returns {HTMLElement|SVGElement} The root element of the document
191   */
192
193  var docElement = document.documentElement;
194  
195
196  /**
197   * A convenience helper to check if the document we are running in is an SVG document
198   *
199   * @access private
200   * @returns {boolean}
201   */
202
203  var isSVG = docElement.nodeName.toLowerCase() === 'svg';
204  
205
206  /**
207   * setClasses takes an array of class names and adds them to the root element
208   *
209   * @access private
210   * @function setClasses
211   * @param {string[]} classes - Array of class names
212   */
213
214  // Pass in an and array of class names, e.g.:
215  //  ['no-webp', 'borderradius', ...]
216  function setClasses(classes) {
217    var className = docElement.className;
218    var classPrefix = Modernizr._config.classPrefix || '';
219
220    if (isSVG) {
221      className = className.baseVal;
222    }
223
224    // Change `no-js` to `js` (independently of the `enableClasses` option)
225    // Handle classPrefix on this too
226    if (Modernizr._config.enableJSClass) {
227      var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
228      className = className.replace(reJS, '$1' + classPrefix + 'js$2');
229    }
230
231    if (Modernizr._config.enableClasses) {
232      // Add the new classes
233      className += ' ' + classPrefix + classes.join(' ' + classPrefix);
234      if (isSVG) {
235        docElement.className.baseVal = className;
236      } else {
237        docElement.className = className;
238      }
239    }
240
241  }
242
243  ;
244/*!
245{
246  "name": "Cookies",
247  "property": "cookies",
248  "tags": ["storage"],
249  "authors": ["tauren"]
250}
251!*/
252/* DOC
253Detects whether cookie support is enabled.
254*/
255
256  // https://github.com/Modernizr/Modernizr/issues/191
257
258  Modernizr.addTest('cookies', function() {
259    // navigator.cookieEnabled cannot detect custom or nuanced cookie blocking
260    // configurations. For example, when blocking cookies via the Advanced
261    // Privacy Settings in IE9, it always returns true. And there have been
262    // issues in the past with site-specific exceptions.
263    // Don't rely on it.
264
265    // try..catch because some in situations `document.cookie` is exposed but throws a
266    // SecurityError if you try to access it; e.g. documents created from data URIs
267    // or in sandboxed iframes (depending on flags/context)
268    try {
269      // Create cookie
270      document.cookie = 'cookietest=1';
271      var ret = document.cookie.indexOf('cookietest=') != -1;
272      // Delete cookie
273      document.cookie = 'cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT';
274      return ret;
275    }
276    catch (e) {
277      return false;
278    }
279  });
280
281/*!
282{
283  "name": "Event Listener",
284  "property": "eventlistener",
285  "authors": ["Andrew Betts (@triblondon)"],
286  "notes": [{
287    "name": "W3C Spec",
288    "href": "https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Registration-interfaces"
289  }],
290  "polyfills": ["eventlistener"]
291}
292!*/
293/* DOC
294Detects native support for addEventListener
295*/
296
297  Modernizr.addTest('eventlistener', 'addEventListener' in window);
298
299
300  /**
301   * If the browsers follow the spec, then they would expose vendor-specific styles as:
302   *   elem.style.WebkitBorderRadius
303   * instead of something like the following (which is technically incorrect):
304   *   elem.style.webkitBorderRadius
305
306   * WebKit ghosts their properties in lowercase but Opera & Moz do not.
307   * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
308   *   erik.eae.net/archives/2008/03/10/21.48.10/
309
310   * More here: github.com/Modernizr/Modernizr/issues/issue/21
311   *
312   * @access private
313   * @returns {string} The string representing the vendor-specific style properties
314   */
315
316  var omPrefixes = 'Moz O ms Webkit';
317  
318
319  var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
320  ModernizrProto._cssomPrefixes = cssomPrefixes;
321  
322
323
324  /**
325   * contains checks to see if a string contains another string
326   *
327   * @access private
328   * @function contains
329   * @param {string} str - The string we want to check for substrings
330   * @param {string} substr - The substring we want to search the first string for
331   * @returns {boolean}
332   */
333
334  function contains(str, substr) {
335    return !!~('' + str).indexOf(substr);
336  }
337
338  ;
339
340  /**
341   * createElement is a convenience wrapper around document.createElement. Since we
342   * use createElement all over the place, this allows for (slightly) smaller code
343   * as well as abstracting away issues with creating elements in contexts other than
344   * HTML documents (e.g. SVG documents).
345   *
346   * @access private
347   * @function createElement
348   * @returns {HTMLElement|SVGElement} An HTML or SVG element
349   */
350
351  function createElement() {
352    if (typeof document.createElement !== 'function') {
353      // This is the case in IE7, where the type of createElement is "object".
354      // For this reason, we cannot call apply() as Object is not a Function.
355      return document.createElement(arguments[0]);
356    } else if (isSVG) {
357      return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
358    } else {
359      return document.createElement.apply(document, arguments);
360    }
361  }
362
363  ;
364
365  /**
366   * Create our "modernizr" element that we do most feature tests on.
367   *
368   * @access private
369   */
370
371  var modElem = {
372    elem: createElement('modernizr')
373  };
374
375  // Clean up this element
376  Modernizr._q.push(function() {
377    delete modElem.elem;
378  });
379
380  
381
382  var mStyle = {
383    style: modElem.elem.style
384  };
385
386  // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
387  // the front of the queue.
388  Modernizr._q.unshift(function() {
389    delete mStyle.style;
390  });
391
392  
393
394  /**
395   * getBody returns the body of a document, or an element that can stand in for
396   * the body if a real body does not exist
397   *
398   * @access private
399   * @function getBody
400   * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
401   * artificially created element that stands in for the body
402   */
403
404  function getBody() {
405    // After page load injecting a fake body doesn't work so check if body exists
406    var body = document.body;
407
408    if (!body) {
409      // Can't use the real body create a fake one.
410      body = createElement(isSVG ? 'svg' : 'body');
411      body.fake = true;
412    }
413
414    return body;
415  }
416
417  ;
418
419  /**
420   * injectElementWithStyles injects an element with style element and some CSS rules
421   *
422   * @access private
423   * @function injectElementWithStyles
424   * @param {string} rule - String representing a css rule
425   * @param {function} callback - A function that is used to test the injected element
426   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
427   * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
428   * @returns {boolean}
429   */
430
431  function injectElementWithStyles(rule, callback, nodes, testnames) {
432    var mod = 'modernizr';
433    var style;
434    var ret;
435    var node;
436    var docOverflow;
437    var div = createElement('div');
438    var body = getBody();
439
440    if (parseInt(nodes, 10)) {
441      // In order not to give false positives we create a node for each test
442      // This also allows the method to scale for unspecified uses
443      while (nodes--) {
444        node = createElement('div');
445        node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
446        div.appendChild(node);
447      }
448    }
449
450    style = createElement('style');
451    style.type = 'text/css';
452    style.id = 's' + mod;
453
454    // 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.
455    // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
456    (!body.fake ? div : body).appendChild(style);
457    body.appendChild(div);
458
459    if (style.styleSheet) {
460      style.styleSheet.cssText = rule;
461    } else {
462      style.appendChild(document.createTextNode(rule));
463    }
464    div.id = mod;
465
466    if (body.fake) {
467      //avoid crashing IE8, if background image is used
468      body.style.background = '';
469      //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
470      body.style.overflow = 'hidden';
471      docOverflow = docElement.style.overflow;
472      docElement.style.overflow = 'hidden';
473      docElement.appendChild(body);
474    }
475
476    ret = callback(div, rule);
477    // If this is done after page load we don't want to remove the body so check if body exists
478    if (body.fake) {
479      body.parentNode.removeChild(body);
480      docElement.style.overflow = docOverflow;
481      // Trigger layout so kinetic scrolling isn't disabled in iOS6+
482      // eslint-disable-next-line
483      docElement.offsetHeight;
484    } else {
485      div.parentNode.removeChild(div);
486    }
487
488    return !!ret;
489
490  }
491
492  ;
493
494  /**
495   * domToCSS takes a camelCase string and converts it to kebab-case
496   * e.g. boxSizing -> box-sizing
497   *
498   * @access private
499   * @function domToCSS
500   * @param {string} name - String name of camelCase prop we want to convert
501   * @returns {string} The kebab-case version of the supplied name
502   */
503
504  function domToCSS(name) {
505    return name.replace(/([A-Z])/g, function(str, m1) {
506      return '-' + m1.toLowerCase();
507    }).replace(/^ms-/, '-ms-');
508  }
509  ;
510
511
512  /**
513   * wrapper around getComputedStyle, to fix issues with Firefox returning null when
514   * called inside of a hidden iframe
515   *
516   * @access private
517   * @function computedStyle
518   * @param {HTMLElement|SVGElement} - The element we want to find the computed styles of
519   * @param {string|null} [pseudoSelector]- An optional pseudo element selector (e.g. :before), of null if none
520   * @returns {CSSStyleDeclaration}
521   */
522
523  function computedStyle(elem, pseudo, prop) {
524    var result;
525
526    if ('getComputedStyle' in window) {
527      result = getComputedStyle.call(window, elem, pseudo);
528      var console = window.console;
529
530      if (result !== null) {
531        if (prop) {
532          result = result.getPropertyValue(prop);
533        }
534      } else {
535        if (console) {
536          var method = console.error ? 'error' : 'log';
537          console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');
538        }
539      }
540    } else {
541      result = !pseudo && elem.currentStyle && elem.currentStyle[prop];
542    }
543
544    return result;
545  }
546
547  ;
548
549  /**
550   * nativeTestProps allows for us to use native feature detection functionality if available.
551   * some prefixed form, or false, in the case of an unsupported rule
552   *
553   * @access private
554   * @function nativeTestProps
555   * @param {array} props - An array of property names
556   * @param {string} value - A string representing the value we want to check via @supports
557   * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
558   */
559
560  // Accepts a list of property names and a single value
561  // Returns `undefined` if native detection not available
562  function nativeTestProps(props, value) {
563    var i = props.length;
564    // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
565    if ('CSS' in window && 'supports' in window.CSS) {
566      // Try every prefixed variant of the property
567      while (i--) {
568        if (window.CSS.supports(domToCSS(props[i]), value)) {
569          return true;
570        }
571      }
572      return false;
573    }
574    // Otherwise fall back to at-rule (for Opera 12.x)
575    else if ('CSSSupportsRule' in window) {
576      // Build a condition string for every prefixed variant
577      var conditionText = [];
578      while (i--) {
579        conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
580      }
581      conditionText = conditionText.join(' or ');
582      return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
583        return computedStyle(node, null, 'position') == 'absolute';
584      });
585    }
586    return undefined;
587  }
588  ;
589
590  /**
591   * cssToDOM takes a kebab-case string and converts it to camelCase
592   * e.g. box-sizing -> boxSizing
593   *
594   * @access private
595   * @function cssToDOM
596   * @param {string} name - String name of kebab-case prop we want to convert
597   * @returns {string} The camelCase version of the supplied name
598   */
599
600  function cssToDOM(name) {
601    return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
602      return m1 + m2.toUpperCase();
603    }).replace(/^-/, '');
604  }
605  ;
606
607  // testProps is a generic CSS / DOM property test.
608
609  // In testing support for a given CSS property, it's legit to test:
610  //    `elem.style[styleName] !== undefined`
611  // If the property is supported it will return an empty string,
612  // if unsupported it will return undefined.
613
614  // We'll take advantage of this quick test and skip setting a style
615  // on our modernizr element, but instead just testing undefined vs
616  // empty string.
617
618  // Property names can be provided in either camelCase or kebab-case.
619
620  function testProps(props, prefixed, value, skipValueTest) {
621    skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
622
623    // Try native detect first
624    if (!is(value, 'undefined')) {
625      var result = nativeTestProps(props, value);
626      if (!is(result, 'undefined')) {
627        return result;
628      }
629    }
630
631    // Otherwise do it properly
632    var afterInit, i, propsLength, prop, before;
633
634    // If we don't have a style element, that means we're running async or after
635    // the core tests, so we'll need to create our own elements to use
636
637    // inside of an SVG element, in certain browsers, the `style` element is only
638    // defined for valid tags. Therefore, if `modernizr` does not have one, we
639    // fall back to a less used element and hope for the best.
640    // for strict XHTML browsers the hardly used samp element is used
641    var elems = ['modernizr', 'tspan', 'samp'];
642    while (!mStyle.style && elems.length) {
643      afterInit = true;
644      mStyle.modElem = createElement(elems.shift());
645      mStyle.style = mStyle.modElem.style;
646    }
647
648    // Delete the objects if we created them.
649    function cleanElems() {
650      if (afterInit) {
651        delete mStyle.style;
652        delete mStyle.modElem;
653      }
654    }
655
656    propsLength = props.length;
657    for (i = 0; i < propsLength; i++) {
658      prop = props[i];
659      before = mStyle.style[prop];
660
661      if (contains(prop, '-')) {
662        prop = cssToDOM(prop);
663      }
664
665      if (mStyle.style[prop] !== undefined) {
666
667        // If value to test has been passed in, do a set-and-check test.
668        // 0 (integer) is a valid property value, so check that `value` isn't
669        // undefined, rather than just checking it's truthy.
670        if (!skipValueTest && !is(value, 'undefined')) {
671
672          // Needs a try catch block because of old IE. This is slow, but will
673          // be avoided in most cases because `skipValueTest` will be used.
674          try {
675            mStyle.style[prop] = value;
676          } catch (e) {}
677
678          // If the property value has changed, we assume the value used is
679          // supported. If `value` is empty string, it'll fail here (because
680          // it hasn't changed), which matches how browsers have implemented
681          // CSS.supports()
682          if (mStyle.style[prop] != before) {
683            cleanElems();
684            return prefixed == 'pfx' ? prop : true;
685          }
686        }
687        // Otherwise just return true, or the property name if this is a
688        // `prefixed()` call
689        else {
690          cleanElems();
691          return prefixed == 'pfx' ? prop : true;
692        }
693      }
694    }
695    cleanElems();
696    return false;
697  }
698
699  ;
700
701  /**
702   * List of JavaScript DOM values used for tests
703   *
704   * @memberof Modernizr
705   * @name Modernizr._domPrefixes
706   * @optionName Modernizr._domPrefixes
707   * @optionProp domPrefixes
708   * @access public
709   * @example
710   *
711   * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
712   * than kebab-case properties, all properties are their Capitalized variant
713   *
714   * ```js
715   * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
716   * ```
717   */
718
719  var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
720  ModernizrProto._domPrefixes = domPrefixes;
721  
722
723  /**
724   * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
725   *
726   * @access private
727   * @function fnBind
728   * @param {function} fn - a function you want to change `this` reference to
729   * @param {object} that - the `this` you want to call the function with
730   * @returns {function} The wrapped version of the supplied function
731   */
732
733  function fnBind(fn, that) {
734    return function() {
735      return fn.apply(that, arguments);
736    };
737  }
738
739  ;
740
741  /**
742   * testDOMProps is a generic DOM property test; if a browser supports
743   *   a certain property, it won't return undefined for it.
744   *
745   * @access private
746   * @function testDOMProps
747   * @param {array.<string>} props - An array of properties to test for
748   * @param {object} obj - An object or Element you want to use to test the parameters again
749   * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
750   * @returns {false|*} returns false if the prop is unsupported, otherwise the value that is supported
751   */
752  function testDOMProps(props, obj, elem) {
753    var item;
754
755    for (var i in props) {
756      if (props[i] in obj) {
757
758        // return the property name as a string
759        if (elem === false) {
760          return props[i];
761        }
762
763        item = obj[props[i]];
764
765        // let's bind a function
766        if (is(item, 'function')) {
767          // bind to obj unless overriden
768          return fnBind(item, elem || obj);
769        }
770
771        // return the unbound function or obj or value
772        return item;
773      }
774    }
775    return false;
776  }
777
778  ;
779
780  /**
781   * testPropsAll tests a list of DOM properties we want to check against.
782   * We specify literally ALL possible (known and/or likely) properties on
783   * the element including the non-vendor prefixed one, for forward-
784   * compatibility.
785   *
786   * @access private
787   * @function testPropsAll
788   * @param {string} prop - A string of the property to test for
789   * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
790   * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
791   * @param {string} [value] - A string of a css value
792   * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
793   * @returns {false|string} returns the string version of the property, or false if it is unsupported
794   */
795  function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
796
797    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
798      props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
799
800    // did they call .prefixed('boxSizing') or are we just testing a prop?
801    if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
802      return testProps(props, prefixed, value, skipValueTest);
803
804      // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
805    } else {
806      props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
807      return testDOMProps(props, prefixed, elem);
808    }
809  }
810
811  // Modernizr.testAllProps() investigates whether a given style property,
812  // or any of its vendor-prefixed variants, is recognized
813  //
814  // Note that the property names must be provided in the camelCase variant.
815  // Modernizr.testAllProps('boxSizing')
816  ModernizrProto.testAllProps = testPropsAll;
817
818  
819
820  /**
821   * atRule returns a given CSS property at-rule (eg @keyframes), possibly in
822   * some prefixed form, or false, in the case of an unsupported rule
823   *
824   * @memberof Modernizr
825   * @name Modernizr.atRule
826   * @optionName Modernizr.atRule()
827   * @optionProp atRule
828   * @access public
829   * @function atRule
830   * @param {string} prop - String name of the @-rule to test for
831   * @returns {string|boolean} The string representing the (possibly prefixed)
832   * valid version of the @-rule, or `false` when it is unsupported.
833   * @example
834   * ```js
835   *  var keyframes = Modernizr.atRule('@keyframes');
836   *
837   *  if (keyframes) {
838   *    // keyframes are supported
839   *    // could be `@-webkit-keyframes` or `@keyframes`
840   *  } else {
841   *    // keyframes === `false`
842   *  }
843   * ```
844   *
845   */
846
847  var atRule = function(prop) {
848    var length = prefixes.length;
849    var cssrule = window.CSSRule;
850    var rule;
851
852    if (typeof cssrule === 'undefined') {
853      return undefined;
854    }
855
856    if (!prop) {
857      return false;
858    }
859
860    // remove literal @ from beginning of provided property
861    prop = prop.replace(/^@/, '');
862
863    // CSSRules use underscores instead of dashes
864    rule = prop.replace(/-/g, '_').toUpperCase() + '_RULE';
865
866    if (rule in cssrule) {
867      return '@' + prop;
868    }
869
870    for (var i = 0; i < length; i++) {
871      // prefixes gives us something like -o-, and we want O_
872      var prefix = prefixes[i];
873      var thisRule = prefix.toUpperCase() + '_' + rule;
874
875      if (thisRule in cssrule) {
876        return '@-' + prefix.toLowerCase() + '-' + prop;
877      }
878    }
879
880    return false;
881  };
882
883  ModernizrProto.atRule = atRule;
884
885  
886
887  /**
888   * prefixed returns the prefixed or nonprefixed property name variant of your input
889   *
890   * @memberof Modernizr
891   * @name Modernizr.prefixed
892   * @optionName Modernizr.prefixed()
893   * @optionProp prefixed
894   * @access public
895   * @function prefixed
896   * @param {string} prop - String name of the property to test for
897   * @param {object} [obj] - An object to test for the prefixed properties on
898   * @param {HTMLElement} [elem] - An element used to test specific properties against
899   * @returns {string|false} The string representing the (possibly prefixed) valid
900   * version of the property, or `false` when it is unsupported.
901   * @example
902   *
903   * Modernizr.prefixed takes a string css value in the DOM style camelCase (as
904   * opposed to the css style kebab-case) form and returns the (possibly prefixed)
905   * version of that property that the browser actually supports.
906   *
907   * For example, in older Firefox...
908   * ```js
909   * prefixed('boxSizing')
910   * ```
911   * returns 'MozBoxSizing'
912   *
913   * In newer Firefox, as well as any other browser that support the unprefixed
914   * version would simply return `boxSizing`. Any browser that does not support
915   * the property at all, it will return `false`.
916   *
917   * By default, prefixed is checked against a DOM element. If you want to check
918   * for a property on another object, just pass it as a second argument
919   *
920   * ```js
921   * var rAF = prefixed('requestAnimationFrame', window);
922   *
923   * raf(function() {
924   *  renderFunction();
925   * })
926   * ```
927   *
928   * Note that this will return _the actual function_ - not the name of the function.
929   * If you need the actual name of the property, pass in `false` as a third argument
930   *
931   * ```js
932   * var rAFProp = prefixed('requestAnimationFrame', window, false);
933   *
934   * rafProp === 'WebkitRequestAnimationFrame' // in older webkit
935   * ```
936   *
937   * One common use case for prefixed is if you're trying to determine which transition
938   * end event to bind to, you might do something like...
939   * ```js
940   * var transEndEventNames = {
941   *     'WebkitTransition' : 'webkitTransitionEnd', * Saf 6, Android Browser
942   *     'MozTransition'    : 'transitionend',       * only for FF < 15
943   *     'transition'       : 'transitionend'        * IE10, Opera, Chrome, FF 15+, Saf 7+
944   * };
945   *
946   * var transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
947   * ```
948   *
949   * If you want a similar lookup, but in kebab-case, you can use [prefixedCSS](#modernizr-prefixedcss).
950   */
951
952  var prefixed = ModernizrProto.prefixed = function(prop, obj, elem) {
953    if (prop.indexOf('@') === 0) {
954      return atRule(prop);
955    }
956
957    if (prop.indexOf('-') != -1) {
958      // Convert kebab-case to camelCase
959      prop = cssToDOM(prop);
960    }
961    if (!obj) {
962      return testPropsAll(prop, 'pfx');
963    } else {
964      // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
965      return testPropsAll(prop, obj, elem);
966    }
967  };
968
969  
970/*!
971{
972  "name": "Fullscreen API",
973  "property": "fullscreen",
974  "caniuse": "fullscreen",
975  "notes": [{
976    "name": "MDN documentation",
977    "href": "https://developer.mozilla.org/en/API/Fullscreen"
978  }],
979  "polyfills": ["screenfulljs"],
980  "builderAliases": ["fullscreen_api"]
981}
982!*/
983/* DOC
984Detects support for the ability to make the current website take over the user's entire screen
985*/
986
987  // github.com/Modernizr/Modernizr/issues/739
988  Modernizr.addTest('fullscreen', !!(prefixed('exitFullscreen', document, false) || prefixed('cancelFullScreen', document, false)));
989
990
991  /**
992   * testStyles injects an element with style element and some CSS rules
993   *
994   * @memberof Modernizr
995   * @name Modernizr.testStyles
996   * @optionName Modernizr.testStyles()
997   * @optionProp testStyles
998   * @access public
999   * @function testStyles
1000   * @param {string} rule - String representing a css rule
1001   * @param {function} callback - A function that is used to test the injected element
1002   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
1003   * @param {string[]}
1003 [testnames] - An array of strings that are used as ids for the additional nodes
1004   * @returns {boolean}
1005   * @example
1006   *
1007   * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
1008   * along with (possibly multiple) DOM elements. This lets you check for features
1009   * 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).
1010   *
1011   * ```js
1012   * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
1013   *   // elem is the first DOM node in the page (by default #modernizr)
1014   *   // rule is the first argument you supplied - the CSS rule in string form
1015   *
1016   *   addTest('widthworks', elem.style.width === '9px')
1017   * });
1018   * ```
1019   *
1020   * If your test requires multiple nodes, you can include a third argument
1021   * indicating how many additional div elements to include on the page. The
1022   * additional nodes are injected as children of the `elem` that is returned as
1023   * the first argument to the callback.
1024   *
1025   * ```js
1026   * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
1027   *   document.getElementById('modernizr').style.width === '1px'; // true
1028   *   document.getElementById('modernizr2').style.width === '2px'; // true
1029   *   elem.firstChild === document.getElementById('modernizr2'); // true
1030   * }, 1);
1031   * ```
1032   *
1033   * By default, all of the additional elements have an ID of `modernizr[n]`, where
1034   * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
1035   * the second additional is `#modernizr3`, etc.).
1036   * If you want to have more meaningful IDs for your function, you can provide
1037   * them as the fourth argument, as an array of strings
1038   *
1039   * ```js
1040   * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
1041   *   elem.firstChild === document.getElementById('foo'); // true
1042   *   elem.lastChild === document.getElementById('bar'); // true
1043   * }, 2, ['foo', 'bar']);
1044   * ```
1045   *
1046   */
1047
1048  var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
1049  
1050/*!
1051{
1052  "name": "Hidden Scrollbar",
1053  "property": "hiddenscroll",
1054  "authors": ["Oleg Korsunsky"],
1055  "tags": ["overlay"],
1056  "notes": [{
1057    "name": "Overlay Scrollbar description",
1058    "href": "https://developer.apple.com/library/mac/releasenotes/MacOSX/WhatsNewInOSX/Articles/MacOSX10_7.html#//apple_ref/doc/uid/TP40010355-SW39"
1059  },{
1060    "name": "Video example of overlay scrollbars",
1061    "href": "https://gfycat.com/FoolishMeaslyAtlanticsharpnosepuffer"
1062  }]
1063}
1064!*/
1065/* DOC
1066Detects overlay scrollbars (when scrollbars on overflowed blocks are visible). This is found most commonly on mobile and OS X.
1067*/
1068
1069  Modernizr.addTest('hiddenscroll', function() {
1070    return testStyles('#modernizr {width:100px;height:100px;overflow:scroll}', function(elem) {
1071      return elem.offsetWidth === elem.clientWidth;
1072    });
1073  });
1074
1075
1076  /**
1077   * since we have a fairly large number of input tests that don't mutate the input
1078   * we create a single element that can be shared with all of those tests for a
1079   * minor perf boost
1080   *
1081   * @access private
1082   * @returns {HTMLInputElement}
1083   */
1084  var inputElem = createElement('input');
1085  
1086/*!
1087{
1088  "name": "Input attributes",
1089  "property": "input",
1090  "tags": ["forms"],
1091  "authors": ["Mike Taylor"],
1092  "notes": [{
1093    "name": "WHATWG spec",
1094    "href": "https://html.spec.whatwg.org/multipage/forms.html#input-type-attr-summary"
1095  }],
1096  "knownBugs": ["Some blackberry devices report false positive for input.multiple"]
1097}
1098!*/
1099/* DOC
1100Detects support for HTML5 `<input>` element attributes and exposes Boolean subproperties with the results:
1101
1102```javascript
1103Modernizr.input.autocomplete
1104Modernizr.input.autofocus
1105Modernizr.input.list
1106Modernizr.input.max
1107Modernizr.input.min
1108Modernizr.input.multiple
1109Modernizr.input.pattern
1110Modernizr.input.placeholder
1111Modernizr.input.required
1112Modernizr.input.step
1113```
1114*/
1115
1116  // Run through HTML5's new input attributes to see if the UA understands any.
1117  // Mike Taylr has created a comprehensive resource for testing these attributes
1118  //   when applied to all input types:
1119  //   miketaylr.com/code/input-type-attr.html
1120
1121  // Only input placeholder is tested while textarea's placeholder is not.
1122  // Currently Safari 4 and Opera 11 have support only for the input placeholder
1123  // Both tests are available in feature-detects/forms-placeholder.js
1124
1125  var inputattrs = 'autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ');
1126  var attrs = {};
1127
1128  Modernizr.input = (function(props) {
1129    for (var i = 0, len = props.length; i < len; i++) {
1130      attrs[ props[i] ] = !!(props[i] in inputElem);
1131    }
1132    if (attrs.list) {
1133      // safari false positive's on datalist: webk.it/74252
1134      // see also github.com/Modernizr/Modernizr/issues/146
1135      attrs.list = !!(createElement('datalist') && window.HTMLDataListElement);
1136    }
1137    return attrs;
1138  })(inputattrs);
1139
1140/*!
1141{
1142  "name": "Form input types",
1143  "property": "inputtypes",
1144  "caniuse": "forms",
1145  "tags": ["forms"],
1146  "authors": ["Mike Taylor"],
1147  "polyfills": [
1148    "jquerytools",
1149    "webshims",
1150    "h5f",
1151    "webforms2",
1152    "nwxforms",
1153    "fdslider",
1154    "html5slider",
1155    "galleryhtml5forms",
1156    "jscolor",
1157    "html5formshim",
1158    "selectedoptionsjs",
1159    "formvalidationjs"
1160  ]
1161}
1162!*/
1163/* DOC
1164Detects support for HTML5 form input types and exposes Boolean subproperties with the results:
1165
1166```javascript
1167Modernizr.inputtypes.color
1168Modernizr.inputtypes.date
1169Modernizr.inputtypes.datetime
1170Modernizr.inputtypes['datetime-local']
1171Modernizr.inputtypes.email
1172Modernizr.inputtypes.month
1173Modernizr.inputtypes.number
1174Modernizr.inputtypes.range
1175Modernizr.inputtypes.search
1176Modernizr.inputtypes.tel
1177Modernizr.inputtypes.time
1178Modernizr.inputtypes.url
1179Modernizr.inputtypes.week
1180```
1181*/
1182
1183  // Run through HTML5's new input types to see if the UA understands any.
1184  //   This is put behind the tests runloop because it doesn't return a
1185  //   true/false like all the other tests; instead, it returns an object
1186  //   containing each input type with its corresponding true/false value
1187
1188  // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
1189  var inputtypes = 'search tel url email datetime date month week time datetime-local number range color'.split(' ');
1190  var inputs = {};
1191
1192  Modernizr.inputtypes = (function(props) {
1193    var len = props.length;
1194    var smile = '1)';
1195    var inputElemType;
1196    var defaultView;
1197    var bool;
1198
1199    for (var i = 0; i < len; i++) {
1200
1201      inputElem.setAttribute('type', inputElemType = props[i]);
1202      bool = inputElem.type !== 'text' && 'style' in inputElem;
1203
1204      // We first check to see if the type we give it sticks..
1205      // If the type does, we feed it a textual value, which shouldn't be valid.
1206      // If the value doesn't stick, we know there's input sanitization which infers a custom UI
1207      if (bool) {
1208
1209        inputElem.value         = smile;
1210        inputElem.style.cssText = 'position:absolute;visibility:hidden;';
1211
1212        if (/^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined) {
1213
1214          docElement.appendChild(inputElem);
1215          defaultView = document.defaultView;
1216
1217          // Safari 2-4 allows the smiley as a value, despite making a slider
1218          bool =  defaultView.getComputedStyle &&
1219            defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
1220            // Mobile android web browser has false positive, so must
1221            // check the height to see if the widget is actually there.
1222            (inputElem.offsetHeight !== 0);
1223
1224          docElement.removeChild(inputElem);
1225
1226        } else if (/^(search|tel)$/.test(inputElemType)) {
1227          // Spec doesn't define any special parsing or detectable UI
1228          //   behaviors so we pass these through as true
1229
1230          // Interestingly, opera fails the earlier test, so it doesn't
1231          //  even make it here.
1232
1233        } else if (/^(url|email)$/.test(inputElemType)) {
1234          // Real url and email support comes with prebaked validation.
1235          bool = inputElem.checkValidity && inputElem.checkValidity() === false;
1236
1237        } else {
1238          // If the upgraded input compontent rejects the :) text, we got a winner
1239          bool = inputElem.value != smile;
1240        }
1241      }
1242
1243      inputs[ props[i] ] = !!bool;
1244    }
1245    return inputs;
1246  })(inputtypes);
1247
1248/*!
1249{
1250  "name": "JSON",
1251  "property": "json",
1252  "caniuse": "json",
1253  "notes": [{
1254    "name": "MDN documentation",
1255    "href": "https://developer.mozilla.org/en-US/docs/Glossary/JSON"
1256  }],
1257  "polyfills": ["json2"]
1258}
1259!*/
1260/* DOC
1261Detects native support for JSON handling functions.
1262*/
1263
1264  // this will also succeed if you've loaded the JSON2.js polyfill ahead of time
1265  //   ... but that should be obvious. :)
1266
1267  Modernizr.addTest('json', 'JSON' in window && 'parse' in JSON && 'stringify' in JSON);
1268
1269/*!
1270{
1271  "name": "SVG",
1272  "property": "svg",
1273  "caniuse": "svg",
1274  "tags": ["svg"],
1275  "authors": ["Erik Dahlstrom"],
1276  "polyfills": [
1277    "svgweb",
1278    "raphael",
1279    "amplesdk",
1280    "canvg",
1281    "svg-boilerplate",
1282    "sie",
1283    "dojogfx",
1284    "fabricjs"
1285  ]
1286}
1287!*/
1288/* DOC
1289Detects support for SVG in `<embed>` or `<object>` elements.
1290*/
1291
1292  Modernizr.addTest('svg', !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect);
1293
1294
1295  /**
1296   * List of property values to set for css tests. See ticket #21
1297   * http://git.io/vUGl4
1298   *
1299   * @memberof Modernizr
1300   * @name Modernizr._prefixes
1301   * @optionName Modernizr._prefixes
1302   * @optionProp prefixes
1303   * @access public
1304   * @example
1305   *
1306   * Modernizr._prefixes is the internal list of prefixes that we test against
1307   * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply
1308   * an array of kebab-case vendor prefixes you can use within your code.
1309   *
1310   * Some common use cases include
1311   *
1312   * Generating all possible prefixed version of a CSS property
1313   * ```js
1314   * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');
1315   *
1316   * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'
1317   * ```
1318   *
1319   * Generating all possible prefixed version of a CSS value
1320   * ```js
1321   * rule = 'display:' +  Modernizr._prefixes.join('flex; display:') + 'flex';
1322   *
1323   * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'
1324   * ```
1325   */
1326
1327  // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test
1328  // values in feature detects to continue to work
1329  var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);
1330
1331  // expose these for the plugin API. Look in the source for how to join() them against your input
1332  ModernizrProto._prefixes = prefixes;
1333
1334  
1335/*!
1336{
1337  "name": "Touch Events",
1338  "property": "touchevents",
1339  "caniuse" : "touch",
1340  "tags": ["media", "attribute"],
1341  "notes": [{
1342    "name": "Touch Events spec",
1343    "href": "https://www.w3.org/TR/2013/WD-touch-events-20130124/"
1344  }],
1345  "warnings": [
1346    "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device"
1347  ],
1348  "knownBugs": [
1349    "False-positive on some configurations of Nokia N900",
1350    "False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695"
1351  ]
1352}
1353!*/
1354/* DOC
1355Indicates if the browser supports the W3C Touch Events API.
1356
1357This *does not* necessarily reflect a touchscreen device:
1358
1359* Older touchscreen devices only emulate mouse events
1360* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that
1361* Some browsers & OS setups may enable touch APIs when no touchscreen is connected
1362* Future browsers may implement other event models for touch interactions
1363
1364See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).
1365
1366It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).
1367
1368This test will also return `true` for Firefox 4 Multitouch support.
1369*/
1370
1371  // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415
1372  Modernizr.addTest('touchevents', function() {
1373    var bool;
1374    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
1375      bool = true;
1376    } else {
1377      // include the 'heartz' as a way to have a non matching MQ to help terminate the join
1378      // https://git.io/vznFH
1379      var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');
1380      testStyles(query, function(node) {
1381        bool = node.offsetTop === 9;
1382      });
1383    }
1384    return bool;
1385  });
1386
1387/*!
1388{
1389  "name": "HTML5 Video",
1390  "property": "video",
1391  "caniuse": "video",
1392  "tags": ["html5"],
1393  "knownBugs": [
1394    "Without QuickTime, `Modernizr.video.h264` will be `undefined`; https://github.com/Modernizr/Modernizr/issues/546"
1395  ],
1396  "polyfills": [
1397    "html5media",
1398    "mediaelementjs",
1399    "sublimevideo",
1400    "videojs",
1401    "leanbackplayer",
1402    "videoforeverybody"
1403  ]
1404}
1405!*/
1406/* DOC
1407Detects support for the video element, as well as testing what types of content it supports.
1408
1409Subproperties are provided to describe support for `ogg`, `h264` and `webm` formats, e.g.:
1410
1411```javascript
1412Modernizr.video         // true
1413Modernizr.video.ogg     // 'probably'
1414```
1415*/
1416
1417  // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
1418  //                     thx to NielsLeenheer and zcorpan
1419
1420  // Note: in some older browsers, "no" was a return value instead of empty string.
1421  //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
1422  //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
1423
1424  Modernizr.addTest('video', function() {
1425    var elem = createElement('video');
1426    var bool = false;
1427
1428    // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
1429    try {
1430      bool = !!elem.canPlayType
1431      if (bool) {
1432        bool = new Boolean(bool);
1433        bool.ogg = elem.canPlayType('video/ogg; codecs="theora"').replace(/^no$/, '');
1434
1435        // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
1436        bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/, '');
1437
1438        bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/, '');
1439
1440        bool.vp9 = elem.canPlayType('video/webm; codecs="vp9"').replace(/^no$/, '');
1441
1442        bool.hls = elem.canPlayType('application/x-mpegURL; codecs="avc1.42E01E"').replace(/^no$/, '');
1443      }
1444    } catch (e) {}
1445
1446    return bool;
1447  });
1448
1449
1450  /**
1451   * testAllProps determines whether a given CSS property is supported in the browser
1452   *
1453   * @memberof Modernizr
1454   * @name Modernizr.testAllProps
1455   * @optionName Modernizr.testAllProps()
1456   * @optionProp testAllProps
1457   * @access public
1458   * @function testAllProps
1459   * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
1460   * @param {string} [value] - String of the value to test
1461   * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
1462   * @example
1463   *
1464   * testAllProps determines whether a given CSS property, in some prefixed form,
1465   * is supported by the browser.
1466   *
1467   * ```js
1468   * testAllProps('boxSizing')  // true
1469   * ```
1470   *
1471   * It can optionally be given a CSS value in string form to test if a property
1472   * value is valid
1473   *
1474   * ```js
1475   * testAllProps('display', 'block') // true
1476   * testAllProps('display', 'penguin') // false
1477   * ```
1478   *
1479   * A boolean can be passed as a third parameter to skip the value check when
1480   * native detection (@supports) isn't available.
1481   *
1482   * ```js
1483   * testAllProps('shapeOutside', 'content-box', true);
1484   * ```
1485   */
1486
1487  function testAllProps(prop, value, skipValueTest) {
1488    return testPropsAll(prop, undefined, undefined, value, skipValueTest);
1489  }
1490  ModernizrProto.testAllProps = testAllProps;
1491  
1492/*!
1493{
1494  "name": "CSS Animations",
1495  "property": "cssanimations",
1496  "caniuse": "css-animation",
1497  "polyfills": ["transformie", "csssandpaper"],
1498  "tags": ["css"],
1499  "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
1500  "notes": [{
1501    "name" : "Article: 'Dispelling the Android CSS animation myths'",
1502    "href": "https://goo.gl/OGw5Gm"
1503  }]
1504}
1505!*/
1506/* DOC
1507Detects whether or not elements can be animated using CSS
1508*/
1509
1510  Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
1511
1512/*!
1513{
1514  "name": "CSS Background Blend Mode",
1515  "property": "backgroundblendmode",
1516  "caniuse": "css-backgroundblendmode",
1517  "tags": ["css"],
1518  "notes": [
1519    {
1520      "name": "CSS Blend Modes could be the next big thing in Web Design",
1521      "href": " https://medium.com/@bennettfeely/css-blend-modes-could-be-the-next-big-thing-in-web-design-6b51bf53743a"
1522    }, {
1523      "name": "Demo",
1524      "href": "http://bennettfeely.com/gradients/"
1525    }
1526  ]
1527}
1528!*/
1529/* DOC
1530Detects the ability for the browser to composite backgrounds using blending modes similar to ones found in Photoshop or Illustrator.
1531*/
1532
1533  Modernizr.addTest('backgroundblendmode', prefixed('backgroundBlendMode', 'text'));
1534
1535/*!
1536{
1537  "name": "Background Size",
1538  "property": "backgroundsize",
1539  "tags": ["css"],
1540  "knownBugs": ["This will false positive in Opera Mini - https://github.com/Modernizr/Modernizr/issues/396"],
1541  "notes": [{
1542    "name": "Related Issue",
1543    "href": "https://github.com/Modernizr/Modernizr/issues/396"
1544  }]
1545}
1546!*/
1547
1548  Modernizr.addTest('backgroundsize', testAllProps('backgroundSize', '100%', true));
1549
1550/*!
1551{
1552  "name": "Border Radius",
1553  "property": "borderradius",
1554  "caniuse": "border-radius",
1555  "polyfills": ["css3pie"],
1556  "tags": ["css"],
1557  "notes": [{
1558    "name": "Comprehensive Compat Chart",
1559    "href": "https://muddledramblings.com/table-of-css3-border-radius-compliance"
1560  }]
1561}
1562!*/
1563
1564  Modernizr.addTest('borderradius', testAllProps('borderRadius', '0px', true));
1565
1566/*!
1567{
1568  "name": "CSS Calc",
1569  "property": "csscalc",
1570  "caniuse": "calc",
1571  "tags": ["css"],
1572  "builderAliases": ["css_calc"],
1573  "authors": ["@calvein"]
1574}
1575!*/
1576/* DOC
1577Method of allowing calculated values for length units. For example:
1578
1579```css
1580//lem {
1581  width: calc(100% - 3em);
1582}
1583```
1584*/
1585
1586  Modernizr.addTest('csscalc', function() {
1587    var prop = 'width:';
1588    var value = 'calc(10px);';
1589    var el = createElement('a');
1590
1591    el.style.cssText = prop + prefixes.join(value + prop);
1592
1593    return !!el.style.length;
1594  });
1595
1596/*!
1597{
1598  "name": "CSS Supports",
1599  "property": "supports",
1600  "caniuse": "css-featurequeries",
1601  "tags": ["css"],
1602  "builderAliases": ["css_supports"],
1603  "notes": [{
1604    "name": "W3 Spec",
1605    "href": "http://dev.w3.org/csswg/css3-conditional/#at-supports"
1606  },{
1607    "name": "Related Github Issue",
1608    "href": "https://github.com/Modernizr/Modernizr/issues/648"
1609  },{
1610    "name": "W3 Info",
1611    "href": "http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface"
1612  }]
1613}
1614!*/
1615
1616  var newSyntax = 'CSS' in window && 'supports' in window.CSS;
1617  var oldSyntax = 'supportsCSS' in window;
1618  Modernizr.addTest('supports', newSyntax || oldSyntax);
1619
1620/*!
1621{
1622  "name": "CSS Filters",
1623  "property": "cssfilters",
1624  "caniuse": "css-filters",
1625  "polyfills": ["polyfilter"],
1626  "tags": ["css"],
1627  "builderAliases": ["css_filters"],
1628  "notes": [{
1629    "name": "MDN article on CSS filters",
1630    "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/filter"
1631  }]
1632}
1633!*/
1634
1635  Modernizr.addTest('cssfilters', function() {
1636    if (Modernizr.supports) {
1637      return testAllProps('filter', 'blur(2px)');
1638    } else {
1639      var el = createElement('a');
1640      el.style.cssText = prefixes.join('filter:blur(2px); ');
1641      // https://github.com/Modernizr/Modernizr/issues/615
1642      // documentMode is needed for false positives in oldIE, please see issue above
1643      return !!el.style.length && ((document.documentMode === undefined || document.documentMode > 9));
1644    }
1645  });
1646
1647
1648/*!
1649{
1650  "name": "Flexbox",
1651  "property": "flexbox",
1652  "caniuse": "flexbox",
1653  "tags": ["css"],
1654  "notes": [{
1655    "name": "The _new_ flexbox",
1656    "href": "http://dev.w3.org/csswg/css3-flexbox"
1657  }],
1658  "warnings": [
1659    "A `true` result for this detect does not imply that the `flex-wrap` property is supported; see the `flexwrap` detect."
1660  ]
1661}
1662!*/
1663/* DOC
1664Detects support for the Flexible Box Layout model, a.k.a. Flexbox, which allows easy manipulation of layout order and sizing within a container.
1665*/
1666
1667  Modernizr.addTest('flexbox', testAllProps('flexBasis', '1px', true));
1668
1669/*!
1670{
1671  "name": "@font-face",
1672  "property": "fontface",
1673  "authors": ["Diego Perini", "Mat Marquis"],
1674  "tags": ["css"],
1675  "knownBugs": [
1676    "False Positive: WebOS https://github.com/Modernizr/Modernizr/issues/342",
1677    "False Postive: WP7 https://github.com/Modernizr/Modernizr/issues/538"
1678  ],
1679  "notes": [{
1680    "name": "@font-face detection routine by Diego Perini",
1681    "href": "http://javascript.nwbox.com/CSSSupport/"
1682  },{
1683    "name": "Filament Group @font-face compatibility research",
1684    "href": "https://docs.google.com/presentation/d/1n4NyG4uPRjAA8zn_pSQ_Ket0RhcWC6QlZ6LMjKeECo0/edit#slide=id.p"
1685  },{
1686    "name": "Filament Grunticon/@font-face device testing results",
1687    "href": "https://docs.google.com/spreadsheet/ccc?key=0Ag5_yGvxpINRdHFYeUJPNnZMWUZKR2ItMEpRTXZPdUE#gid=0"
1688  },{
1689    "name": "CSS fonts on Android",
1690    "href": "https://stackoverflow.com/questions/3200069/css-fonts-on-android"
1691  },{
1692    "name": "@font-face and Android",
1693    "href": "http://archivist.incutio.com/viewlist/css-discuss/115960"
1694  }]
1695}
1696!*/
1697
1698  var blacklist = (function() {
1699    var ua = navigator.userAgent;
1700    var webos = ua.match(/w(eb)?osbrowser/gi);
1701    var wppre8 = ua.match(/windows phone/gi) && ua.match(/iemobile\/([0-9])+/gi) && parseFloat(RegExp.$1) >= 9;
1702    return webos || wppre8;
1703  }());
1704  if (blacklist) {
1705    Modernizr.addTest('fontface', false);
1706  } else {
1707    testStyles('@font-face {font-family:"font";src:url("https://")}', function(node, rule) {
1708      var style = document.getElementById('smodernizr');
1709      var sheet = style.sheet || style.styleSheet;
1710      var cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
1711      var bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
1712      Modernizr.addTest('fontface', bool);
1713    });
1714  }
1715;
1716/*!
1717{
1718  "name": "CSS Gradients",
1719  "caniuse": "css-gradients",
1720  "property": "cssgradients",
1721  "tags": ["css"],
1722  "knownBugs": ["False-positives on webOS (https://github.com/Modernizr/Modernizr/issues/202)"],
1723  "notes": [{
1724    "name": "Webkit Gradient Syntax",
1725    "href": "https://webkit.org/blog/175/introducing-css-gradients/"
1726  },{
1727    "name": "Linear Gradient Syntax",
1728    "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient"
1729  },{
1730    "name": "W3C Gradient Spec",
1731    "href": "https://drafts.csswg.org/css-images-3/#gradients"
1732  }]
1733}
1734!*/
1735
1736
1737  Modernizr.addTest('cssgradients', function() {
1738
1739    var str1 = 'background-image:';
1740    var str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));';
1741    var css = '';
1742    var angle;
1743
1744    for (var i = 0, len = prefixes.length - 1; i < len; i++) {
1745      angle = (i === 0 ? 'to ' : '');
1746      css += str1 + prefixes[i] + 'linear-gradient(' + angle + 'left top, #9f9, white);';
1747    }
1748
1749    if (Modernizr._config.usePrefixes) {
1750    // legacy webkit syntax (FIXME: remove when syntax not in use anymore)
1751      css += str1 + '-webkit-' + str2;
1752    }
1753
1754    var elem = createElement('a');
1755    var style = elem.style;
1756    style.cssText = css;
1757
1758    // IE6 returns undefined so cast to string
1759    return ('' + style.backgroundImage).indexOf('gradient') > -1;
1760  });
1761
1762/*!
1763{
1764  "name": "CSS :invalid pseudo-class",
1765  "property": "cssinvalid",
1766  "notes": [{
1767    "name": "MDN documentation",
1768    "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid"
1769  }]
1770}
1771!*/
1772/* DOC
1773  Detects support for the ':invalid' CSS pseudo-class.
1774*/
1775
1776  Modernizr.addTest('cssinvalid', function() {
1777    return testStyles('#modernizr input{height:0;border:0;padding:0;margin:0;width:10px} #modernizr input:invalid{width:50px}', function(elem) {
1778      var input = createElement('input');
1779      input.required = true;
1780      elem.appendChild(input);
1781      return input.clientWidth > 10;
1782    });
1783  });
1784
1785/*!
1786{
1787  "name": "CSS Opacity",
1788  "caniuse": "css-opacity",
1789  "property": "opacity",
1790  "tags": ["css"]
1791}
1792!*/
1793
1794  // Browsers that actually have CSS Opacity implemented have done so
1795  // according to spec, which means their return values are within the
1796  // range of [0.0,1.0] - including the leading zero.
1797
1798  Modernizr.addTest('opacity', function() {
1799    var style = createElement('a').style;
1800    style.cssText = prefixes.join('opacity:.55;');
1801
1802    // The non-literal . in this regex is intentional:
1803    // German Chrome returns this value as 0,55
1804    // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
1805    return (/^0.55$/).test(style.opacity);
1806  });
1807
1808/*!
1809{
1810  "name": "CSS Font rem Units",
1811  "caniuse": "rem",
1812  "authors": ["nsfmc"],
1813  "property": "cssremunit",
1814  "tags": ["css"],
1815  "builderAliases": ["css_remunit"],
1816  "notes": [{
1817    "name": "W3C Spec",
1818    "href": "https://www.w3.org/TR/css3-values/#relative0"
1819  },{
1820    "name": "Font Size with rem by Jonathan Snook",
1821    "href": "http://snook.ca/archives/html_and_css/font-size-with-rem"
1822  }]
1823}
1824!*/
1825
1826  // "The 'rem' unit ('root em') is relative to the computed
1827  // value of the 'font-size' value of the root element."
1828  // you can test by checking if the prop was ditched
1829
1830  Modernizr.addTest('cssremunit', function() {
1831    var style = createElement('a').style;
1832    try {
1833      style.fontSize = '3rem';
1834    }
1835    catch (e) {}
1836    return (/rem/).test(style.fontSize);
1837  });
1838
1839/*!
1840{
1841  "name": "CSS Shapes",
1842  "property": "shapes",
1843  "tags": ["css"],
1844  "notes": [{
1845    "name": "CSS Shapes W3C specification",
1846    "href": "https://www.w3.org/TR/css-shapes"
1847  },{
1848    "name": "Examples from Adobe",
1849    "href": "http://webplatform.adobe.com/shapes/"
1850  }, {
1851    "name": "Samples showcasing uses of Shapes",
1852    "href": "http://codepen.io/collection/qFesk"
1853  }]
1854}
1855!*/
1856
1857  Modernizr.addTest('shapes', testAllProps('shapeOutside', 'content-box', true));
1858
1859
1860  /**
1861   * testProp() investigates whether a given style property is recognized
1862   * Property names can be provided in either camelCase or kebab-case.
1863   *
1864   * @memberof Modernizr
1865   * @name Modernizr.testProp
1866   * @access public
1867   * @optionName Modernizr.testProp()
1868   * @optionProp testProp
1869   * @function testProp
1870   * @param {string} prop - Name of the CSS property to check
1871   * @param {string} [value] - Name of the CSS value to check
1872   * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
1873   * @returns {boolean}
1874   * @example
1875   *
1876   * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
1877   * version of the string.
1878   *
1879   * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
1880   *
1881   * ```js
1882   * Modernizr.testProp('pointerEvents')  // true
1883   * ```
1884   *
1885   * You can also provide a value as an optional second argument to check if a
1886   * specific value is supported
1887   *
1888   * ```js
1889   * Modernizr.testProp('pointerEvents', 'none') // true
1890   * Modernizr.testProp('pointerEvents', 'penguin') // false
1891   * ```
1892   */
1893
1894  var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
1895    return testProps([prop], undefined, value, useValue);
1896  };
1897  
1898/*!
1899{
1900  "name": "CSS textshadow",
1901  "property": "textshadow",
1902  "caniuse": "css-textshadow",
1903  "tags": ["css"],
1904  "knownBugs": ["FF3.0 will false positive on this test"]
1905}
1906!*/
1907
1908  Modernizr.addTest('textshadow', testProp('textShadow', '1px 1px'));
1909
1910/*!
1911{
1912  "name": "CSS Transforms",
1913  "property": "csstransforms",
1914  "caniuse": "transforms2d",
1915  "tags": ["css"]
1916}
1917!*/
1918
1919  Modernizr.addTest('csstransforms', function() {
1920    // Android < 3.0 is buggy, so we sniff and blacklist
1921    // http://git.io/hHzL7w
1922    return navigator.userAgent.indexOf('Android 2.') === -1 &&
1923           testAllProps('transform', 'scale(1)', true);
1924  });
1925
1926/*!
1927{
1928  "name": "CSS Transforms 3D",
1929  "property": "csstransforms3d",
1930  "caniuse": "transforms3d",
1931  "tags": ["css"],
1932  "warnings": [
1933    "Chrome may occassionally fail this test on some systems; more info: https://code.google.com/p/chromium/issues/detail?id=129004"
1934  ]
1935}
1936!*/
1937
1938  Modernizr.addTest('csstransforms3d', function() {
1939    return !!testAllProps('perspective', '1px', true);
1940  });
1941
1942/*!
1943{
1944  "name": "CSS Transitions",
1945  "property": "csstransitions",
1946  "caniuse": "css-transitions",
1947  "tags": ["css"]
1948}
1949!*/
1950
1951  Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true));
1952
1953
1954  /**
1955   * roundedEquals takes two integers and checks if the first is 
1955within 1 of the second
1956   *
1957   * @access private
1958   * @function roundedEquals
1959   * @param {number} a
1960   * @param {number} b
1961   * @returns {boolean}
1962   */
1963
1964  function roundedEquals(a, b) {
1965    return a - 1 === b || a === b || a + 1 === b;
1966  }
1967
1968  ;
1969/*!
1970{
1971  "name": "CSS vh unit",
1972  "property": "cssvhunit",
1973  "caniuse": "viewport-units",
1974  "tags": ["css"],
1975  "builderAliases": ["css_vhunit"],
1976  "notes": [{
1977    "name": "Related Modernizr Issue",
1978    "href": "https://github.com/Modernizr/Modernizr/issues/572"
1979  },{
1980    "name": "Similar JSFiddle",
1981    "href": "https://jsfiddle.net/FWeinb/etnYC/"
1982  }]
1983}
1984!*/
1985
1986  testStyles('#modernizr { height: 50vh; }', function(elem) {
1987    var height = parseInt(window.innerHeight / 2, 10);
1988    var compStyle = parseInt(computedStyle(elem, null, 'height'), 10);
1989
1990    Modernizr.addTest('cssvhunit', roundedEquals(compStyle, height));
1991  });
1992
1993/*!
1994{
1995  "name": "CSS vw unit",
1996  "property": "cssvwunit",
1997  "caniuse": "viewport-units",
1998  "tags": ["css"],
1999  "builderAliases": ["css_vwunit"],
2000  "notes": [{
2001    "name": "Related Modernizr Issue",
2002    "href": "https://github.com/Modernizr/Modernizr/issues/572"
2003  },{
2004    "name": "JSFiddle Example",
2005    "href": "https://jsfiddle.net/FWeinb/etnYC/"
2006  }]
2007}
2008!*/
2009
2010  testStyles('#modernizr { width: 50vw; }', function(elem) {
2011    var width = parseInt(window.innerWidth / 2, 10);
2012    var compStyle = parseInt(computedStyle(elem, null, 'width'), 10);
2013
2014    Modernizr.addTest('cssvwunit', roundedEquals(compStyle, width));
2015  });
2016
2017/*!
2018{
2019  "name": "File API",
2020  "property": "filereader",
2021  "caniuse": "fileapi",
2022  "notes": [{
2023    "name": "W3C Working Draft",
2024    "href": "https://www.w3.org/TR/FileAPI/"
2025  }],
2026  "tags": ["file"],
2027  "builderAliases": ["file_api"],
2028  "knownBugs": ["Will fail in Safari 5 due to its lack of support for the standards defined FileReader object"]
2029}
2030!*/
2031/* DOC
2032`filereader` tests for the File API specification
2033
2034Tests for objects specific to the File API W3C specification without
2035being redundant (don't bother testing for Blob since it is assumed
2036to be the File object's prototype.)
2037*/
2038
2039  Modernizr.addTest('filereader', !!(window.File && window.FileList && window.FileReader));
2040
2041/*!
2042{
2043  "name": "Filesystem API",
2044  "property": "filesystem",
2045  "caniuse": "filesystem",
2046  "notes": [{
2047    "name": "W3 Draft",
2048    "href": "http://dev.w3.org/2009/dap/file-system/file-dir-sys.html"
2049  }],
2050  "authors": ["Eric Bidelman (@ebidel)"],
2051  "tags": ["file"],
2052  "builderAliases": ["file_filesystem"],
2053  "knownBugs": ["The API will be present in Chrome incognito, but will throw an exception. See crbug.com/93417"]
2054}
2055!*/
2056
2057  Modernizr.addTest('filesystem', !!prefixed('requestFileSystem', window));
2058
2059/*!
2060{
2061  "name": "style[scoped]",
2062  "property": "stylescoped",
2063  "caniuse": "style-scoped",
2064  "tags": ["dom"],
2065  "builderAliases": ["style_scoped"],
2066  "authors": ["Cătălin Mariș"],
2067  "notes": [{
2068    "name": "WHATWG Specification",
2069    "href": "https://html.spec.whatwg.org/multipage/semantics.html#attr-style-scoped"
2070  }],
2071  "polyfills": ["scoped-styles"]
2072}
2073!*/
2074/* DOC
2075Support for the `scoped` attribute of the `<style>` element.
2076*/
2077
2078  Modernizr.addTest('stylescoped', 'scoped' in createElement('style'));
2079
2080
2081  /**
2082   * hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support
2083   *
2084   * @author kangax
2085   * @access private
2086   * @function hasOwnProp
2087   * @param {object} object - The object to check for a property
2088   * @param {string} property - The property to check for
2089   * @returns {boolean}
2090   */
2091
2092  // hasOwnProperty shim by kangax needed for Safari 2.0 support
2093  var hasOwnProp;
2094
2095  (function() {
2096    var _hasOwnProperty = ({}).hasOwnProperty;
2097    /* istanbul ignore else */
2098    /* we have no way of testing IE 5.5 or safari 2,
2099     * so just assume the else gets hit */
2100    if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
2101      hasOwnProp = function(object, property) {
2102        return _hasOwnProperty.call(object, property);
2103      };
2104    }
2105    else {
2106      hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
2107        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
2108      };
2109    }
2110  })();
2111
2112  
2113
2114
2115   // _l tracks listeners for async tests, as well as tests that execute after the initial run
2116  ModernizrProto._l = {};
2117
2118  /**
2119   * Modernizr.on is a way to listen for the completion of async tests. Being
2120   * asynchronous, they may not finish before your scripts run. As a result you
2121   * will get a possibly false negative `undefined` value.
2122   *
2123   * @memberof Modernizr
2124   * @name Modernizr.on
2125   * @access public
2126   * @function on
2127   * @param {string} feature - String name of the feature detect
2128   * @param {function} cb - Callback function returning a Boolean - true if feature is supported, false if not
2129   * @example
2130   *
2131   * ```js
2132   * Modernizr.on('flash', function( result ) {
2133   *   if (result) {
2134   *    // the browser has flash
2135   *   } else {
2136   *     // the browser does not have flash
2137   *   }
2138   * });
2139   * ```
2140   */
2141
2142  ModernizrProto.on = function(feature, cb) {
2143    // Create the list of listeners if it doesn't exist
2144    if (!this._l[feature]) {
2145      this._l[feature] = [];
2146    }
2147
2148    // Push this test on to the listener list
2149    this._l[feature].push(cb);
2150
2151    // If it's already been resolved, trigger it on next tick
2152    if (Modernizr.hasOwnProperty(feature)) {
2153      // Next Tick
2154      setTimeout(function() {
2155        Modernizr._trigger(feature, Modernizr[feature]);
2156      }, 0);
2157    }
2158  };
2159
2160  /**
2161   * _trigger is the private function used to signal test completion and run any
2162   * callbacks registered through [Modernizr.on](#modernizr-on)
2163   *
2164   * @memberof Modernizr
2165   * @name Modernizr._trigger
2166   * @access private
2167   * @function _trigger
2168   * @param {string} feature - string name of the feature detect
2169   * @param {function|boolean} [res] - A feature detection function, or the boolean =
2170   * result of a feature detection function
2171   */
2172
2173  ModernizrProto._trigger = function(feature, res) {
2174    if (!this._l[feature]) {
2175      return;
2176    }
2177
2178    var cbs = this._l[feature];
2179
2180    // Force async
2181    setTimeout(function() {
2182      var i, cb;
2183      for (i = 0; i < cbs.length; i++) {
2184        cb = cbs[i];
2185        cb(res);
2186      }
2187    }, 0);
2188
2189    // Don't trigger these again
2190    delete this._l[feature];
2191  };
2192
2193  /**
2194   * addTest allows you to define your own feature detects that are not currently
2195   * included in Modernizr (under the covers it's the exact same code Modernizr
2196   * uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)). Just like the offical detects, the result
2197   * will be added onto the Modernizr object, as well as an appropriate className set on
2198   * the html element when configured to do so
2199   *
2200   * @memberof Modernizr
2201   * @name Modernizr.addTest
2202   * @optionName Modernizr.addTest()
2203   * @optionProp addTest
2204   * @access public
2205   * @function addTest
2206   * @param {string|object} feature - The string name of the feature detect, or an
2207   * object of feature detect names and test
2208   * @param {function|boolean} test - Function returning true if feature is supported,
2209   * false if not. Otherwise a boolean representing the results of a feature detection
2210   * @example
2211   *
2212   * The most common way of creating your own feature detects is by calling
2213   * `Modernizr.addTest` with a string (preferably just lowercase, without any
2214   * punctuation), and a function you want executed that will return a boolean result
2215   *
2216   * ```js
2217   * Modernizr.addTest('itsTuesday', function() {
2218   *  var d = new Date();
2219   *  return d.getDay() === 2;
2220   * });
2221   * ```
2222   *
2223   * When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday,
2224   * and to `false` every other day of the week. One thing to notice is that the names of
2225   * feature detect functions are always lowercased when added to the Modernizr object. That
2226   * means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will.
2227   *
2228   *
2229   *  Since we only look at the returned value from any feature detection function,
2230   *  you do not need to actually use a function. For simple detections, just passing
2231   *  in a statement that will return a boolean value works just fine.
2232   *
2233   * ```js
2234   * Modernizr.addTest('hasJquery', 'jQuery' in window);
2235   * ```
2236   *
2237   * Just like before, when the above runs `Modernizr.hasjquery` will be true if
2238   * jQuery has been included on the page. Not using a function saves a small amount
2239   * of overhead for the browser, as well as making your code much more readable.
2240   *
2241   * Finally, you also have the ability to pass in an object of feature names and
2242   * their tests. This is handy if you want to add multiple detections in one go.
2243   * The keys should always be a string, and the value can be either a boolean or
2244   * function that returns a boolean.
2245   *
2246   * ```js
2247   * var detects = {
2248   *  'hasjquery': 'jQuery' in window,
2249   *  'itstuesday': function() {
2250   *    var d = new Date();
2251   *    return d.getDay() === 2;
2252   *  }
2253   * }
2254   *
2255   * Modernizr.addTest(detects);
2256   * ```
2257   *
2258   * There is really no difference between the first methods and this one, it is
2259   * just a convenience to let you write more readable code.
2260   */
2261
2262  function addTest(feature, test) {
2263
2264    if (typeof feature == 'object') {
2265      for (var key in feature) {
2266        if (hasOwnProp(feature, key)) {
2267          addTest(key, feature[ key ]);
2268        }
2269      }
2270    } else {
2271
2272      feature = feature.toLowerCase();
2273      var featureNameSplit = feature.split('.');
2274      var last = Modernizr[featureNameSplit[0]];
2275
2276      // Again, we don't check for parent test existence. Get that right, though.
2277      if (featureNameSplit.length == 2) {
2278        last = last[featureNameSplit[1]];
2279      }
2280
2281      if (typeof last != 'undefined') {
2282        // we're going to quit if you're trying to overwrite an existing test
2283        // if we were to allow it, we'd do this:
2284        //   var re = new RegExp("\\b(no-)?" + feature + "\\b");
2285        //   docElement.className = docElement.className.replace( re, '' );
2286        // but, no rly, stuff 'em.
2287        return Modernizr;
2288      }
2289
2290      test = typeof test == 'function' ? test() : test;
2291
2292      // Set the value (this is the magic, right here).
2293      if (featureNameSplit.length == 1) {
2294        Modernizr[featureNameSplit[0]] = test;
2295      } else {
2296        // cast to a Boolean, if not one already
2297        if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
2298          Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
2299        }
2300
2301        Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test;
2302      }
2303
2304      // Set a single class (either `feature` or `no-feature`)
2305      setClasses([(!!test && test != false ? '' : 'no-') + featureNameSplit.join('-')]);
2306
2307      // Trigger the event
2308      Modernizr._trigger(feature, test);
2309    }
2310
2311    return Modernizr; // allow chaining.
2312  }
2313
2314  // After all the tests are run, add self to the Modernizr prototype
2315  Modernizr._q.push(function() {
2316    ModernizrProto.addTest = addTest;
2317  });
2318
2319  
2320
2321/*!
2322{
2323  "name": "SVG as an <img> tag source",
2324  "property": "svgasimg",
2325  "caniuse" : "svg-img",
2326  "tags": ["svg"],
2327  "aliases": ["svgincss"],
2328  "authors": ["Chris Coyier"],
2329  "notes": [{
2330    "name": "HTML5 Spec",
2331    "href": "http://www.w3.org/TR/html5/embedded-content-0.html#the-img-element"
2332  }]
2333}
2334!*/
2335
2336
2337  // Original Async test by Stu Cox
2338  // https://gist.github.com/chriscoyier/8774501
2339
2340  // Now a Sync test based on good results here
2341  // http://codepen.io/chriscoyier/pen/bADFx
2342
2343  // Note http://www.w3.org/TR/SVG11/feature#Image is *supposed* to represent
2344  // support for the `<image>` tag in SVG, not an SVG file linked from an `<img>`
2345  // tag in HTML – but it’s a heuristic which works
2346  Modernizr.addTest('svgasimg', document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Image', '1.1'));
2347
2348
2349  /**
2350   * Object.prototype.toString can be used with every object and allows you to
2351   * get its class easily. Abstracting it off of an object prevents situations
2352   * where the toString property has been overridden
2353   *
2354   * @access private
2355   * @function toStringFn
2356   * @returns {function} An abstracted toString function
2357   */
2358
2359  var toStringFn = ({}).toString;
2360  
2361/*!
2362{
2363  "name": "SVG clip paths",
2364  "property": "svgclippaths",
2365  "tags": ["svg"],
2366  "notes": [{
2367    "name": "Demo",
2368    "href": "http://srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg"
2369  }]
2370}
2371!*/
2372/* DOC
2373Detects support for clip paths in SVG (only, not on HTML content).
2374
2375See [this discussion](https://github.com/Modernizr/Modernizr/issues/213) regarding applying SVG clip paths to HTML content.
2376*/
2377
2378  Modernizr.addTest('svgclippaths', function() {
2379    return !!document.createElementNS &&
2380      /SVGClipPath/.test(toStringFn.call(document.createElementNS('http://www.w3.org/2000/svg', 'clipPath')));
2381  });
2382
2383/*!
2384{
2385  "name": "SVG filters",
2386  "property": "svgfilters",
2387  "caniuse": "svg-filters",
2388  "tags": ["svg"],
2389  "builderAliases": ["svg_filters"],
2390  "authors": ["Erik Dahlstrom"],
2391  "notes": [{
2392    "name": "W3C Spec",
2393    "href": "https://www.w3.org/TR/SVG11/filters.html"
2394  }]
2395}
2396!*/
2397
2398  // Should fail in Safari: https://stackoverflow.com/questions/9739955/feature-detecting-support-for-svg-filters.
2399  Modernizr.addTest('svgfilters', function() {
2400    var result = false;
2401    try {
2402      result = 'SVGFEColorMatrixElement' in window &&
2403        SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE == 2;
2404    }
2405    catch (e) {}
2406    return result;
2407  });
2408
2409/*!
2410{
2411  "name": "SVG foreignObject",
2412  "property": "svgforeignobject",
2413  "tags": ["svg"],
2414  "notes": [{
2415    "name": "W3C Spec",
2416    "href": "https://www.w3.org/TR/SVG11/extend.html"
2417  }]
2418}
2419!*/
2420/* DOC
2421Detects support for foreignObject tag in SVG.
2422*/
2423
2424  Modernizr.addTest('svgforeignobject', function() {
2425    return !!document.createElementNS &&
2426      /SVGForeignObject/.test(toStringFn.call(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')));
2427  });
2428
2429/*!
2430{
2431  "name": "Inline SVG",
2432  "property": "inlinesvg",
2433  "caniuse": "svg-html5",
2434  "tags": ["svg"],
2435  "notes": [{
2436    "name": "Test page",
2437    "href": "https://paulirish.com/demo/inline-svg"
2438  }, {
2439    "name": "Test page and results",
2440    "href": "https://codepen.io/eltonmesquita/full/GgXbvo/"
2441  }],
2442  "polyfills": ["inline-svg-polyfill"],
2443  "knownBugs": ["False negative on some Chromia browsers."]
2444}
2445!*/
2446/* DOC
2447Detects support for inline SVG in HTML (not within XHTML).
2448*/
2449
2450  Modernizr.addTest('inlinesvg', function() {
2451    var div = createElement('div');
2452    div.innerHTML = '<svg/>';
2453    return (typeof SVGRect != 'undefined' && div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg';
2454  });
2455
2456/*!
2457{
2458  "name": "SVG SMIL animation",
2459  "property": "smil",
2460  "caniuse": "svg-smil",
2461  "tags": ["svg"],
2462  "notes": [{
2463  "name": "W3C Synchronised Multimedia spec",
2464  "href": "https://www.w3.org/AudioVideo/"
2465  }]
2466}
2467!*/
2468
2469  // SVG SMIL animation
2470  Modernizr.addTest('smil', function() {
2471    return !!document.createElementNS &&
2472      /SVGAnimate/.test(toStringFn.call(document.createElementNS('http://www.w3.org/2000/svg', 'animate')));
2473  });
2474
2475/*!
2476{
2477  "name": "Video Autoplay",
2478  "property": "videoautoplay",
2479  "tags": ["video"],
2480  "async" : true,
2481  "warnings": ["This test is very large – only include it if you absolutely need it"],
2482  "knownBugs": ["crashes with an alert on iOS7 when added to homescreen"]
2483}
2484!*/
2485/* DOC
2486Checks for support of the autoplay attribute of the video element.
2487*/
2488
2489
2490  Modernizr.addAsyncTest(function() {
2491    var timeout;
2492    var waitTime = 200;
2493    var retries = 5;
2494    var currentTry = 0;
2495    var elem = createElement('video');
2496    var elemStyle = elem.style;
2497
2498    function testAutoplay(arg) {
2499      currentTry++;
2500      clearTimeout(timeout);
2501
2502      var result = arg && arg.type === 'playing' || elem.currentTime !== 0;
2503
2504      if (!result && currentTry < retries) {
2505        //Detection can be flaky if the browser is slow, so lets retry in a little bit
2506        timeout = setTimeout(testAutoplay, waitTime);
2507        return;
2508      }
2509
2510      elem.removeEventListener('playing', testAutoplay, false);
2511      addTest('videoautoplay', result);
2512
2513      // Cleanup, but don't assume elem is still in the page -
2514      // an extension (eg Flashblock) may already have removed it.
2515      if (elem.parentNode) {
2516        elem.parentNode.removeChild(elem);
2517      }
2518    }
2519
2520    //skip the test if video itself, or the autoplay
2521    //element on it isn't supported
2522    if (!Modernizr.video || !('autoplay' in elem)) {
2523      addTest('videoautoplay', false);
2524      return;
2525    }
2526
2527    elemStyle.position = 'absolute';
2528    elemStyle.height = 0;
2529    elemStyle.width = 0;
2530
2531    try {
2532      if (Modernizr.video.ogg) {
2533        elem.src = 'data:video/ogg;base64,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';
2534      }
2535      else if (Modernizr.video.h264) {
2536        elem.src = 'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAs1tZGF0AAACrgYF//+q3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0OCByMjYwMSBhMGNkN2QzIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTEgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTEwIHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAD2WIhAA3//728P4FNjuZQQAAAu5tb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAZAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACGHRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAZAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAgAAAAIAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAAGQAAAAAAAEAAAAAAZBtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAACgAAAAEAFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAE7bWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAA+3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAgACAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFkAAr/4QAYZ2QACqzZX4iIhAAAAwAEAAADAFA8SJZYAQAGaOvjyyLAAAAAGHN0dHMAAAAAAAAAAQAAAAEAAAQAAAAAHHN0c2MAAAAAAAAAAQAAAAEAAAABAAAAAQAAABRzdHN6AAAAAAAAAsUAAAABAAAAFHN0Y28AAAAAAAAAAQAAADAAAABidWR0YQAAAFptZXRhAAAAAAAAACFoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAC1pbHN0AAAAJal0b28AAAAdZGF0YQAAAAEAAAAATGF2ZjU2LjQwLjEwMQ==';
2537      }
2538      else {
2539        addTest('videoautoplay', false);
2540        return;
2541      }
2542    }
2543
2544    catch (e) {
2545      addTest('videoautoplay', false);
2546      return;
2547    }
2548
2549    elem.setAttribute('autoplay', '');
2550    elemStyle.cssText = 'display:none';
2551    docElement.appendChild(elem);
2552    // wait for the next tick to add the listener, otherwise the element may
2553    // not have time to play in high load situations (e.g. the test suite)
2554    setTimeout(function() {
2555      elem.addEventListener('playing', testAutoplay, false);
2556      timeout = setTimeout(testAutoplay, waitTime);
2557    }, 0);
2558  });
2559
2560
2561  // Run each test
2562  testRunner();
2563
2564  // Remove the "no-js" class if it exists
2565  setClasses(classes);
2566
2567  delete ModernizrProto.addTest;
2568  delete ModernizrProto.addAsyncTest;
2569
2570  // Run the things that are supposed to run after the tests
2571  for (var i = 0; i < Modernizr._q.length; i++) {
2572    Modernizr._q[i]();
2573  }
2574
2575  // Leak Modernizr namespace
2576  window.Modernizr = Modernizr;
2577
2578
2579;
2580
2581})(window, document);
2582;
2583//# sourceMappingURL=scripts.617ea3354da11990.js.map

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.