123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- /*!
- * modernizr v3.6.0
- * Build https://modernizr.com/download?-mq-setclasses-dontmin
- *
- * Copyright (c)
- * Faruk Ates
- * Paul Irish
- * Alex Sexton
- * Ryan Seddon
- * Patrick Kettner
- * Stu Cox
- * Richard Herrera
- * MIT License
- */
- /*
- * Modernizr tests which native CSS3 and HTML5 features are available in the
- * current UA and makes the results available to you in two ways: as properties on
- * a global `Modernizr` object, and as classes on the `<html>` element. This
- * information allows you to progressively enhance your pages with a granular level
- * of control over the experience.
- */
- ;(function(window, document, undefined){
- var classes = [];
- var tests = [];
- /**
- *
- * ModernizrProto is the constructor for Modernizr
- *
- * @class
- * @access public
- */
- var ModernizrProto = {
- // The current version, dummy
- _version: '3.6.0',
- // Any settings that don't work as separate modules
- // can go in here as configuration.
- _config: {
- 'classPrefix': '',
- 'enableClasses': true,
- 'enableJSClass': true,
- 'usePrefixes': true
- },
- // Queue of tests
- _q: [],
- // Stub these for people who are listening
- on: function(test, cb) {
- // I don't really think people should do this, but we can
- // safe guard it a bit.
- // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
- // This is in case people listen to synchronous tests. I would leave it out,
- // but the code to *disallow* sync tests in the real version of this
- // function is actually larger than this.
- var self = this;
- setTimeout(function() {
- cb(self[test]);
- }, 0);
- },
- addTest: function(name, fn, options) {
- tests.push({name: name, fn: fn, options: options});
- },
- addAsyncTest: function(fn) {
- tests.push({name: null, fn: fn});
- }
- };
- // Fake some of Object.create so we can force non test results to be non "own" properties.
- var Modernizr = function() {};
- Modernizr.prototype = ModernizrProto;
- // Leak modernizr globally when you `require` it rather than force it here.
- // Overwrite name so constructor name is nicer :D
- Modernizr = new Modernizr();
- /**
- * is returns a boolean if the typeof an obj is exactly type.
- *
- * @access private
- * @function is
- * @param {*} obj - A thing we want to check the type of
- * @param {string} type - A string to compare the typeof against
- * @returns {boolean}
- */
- function is(obj, type) {
- return typeof obj === type;
- }
- ;
- /**
- * Run through all tests and detect their support in the current UA.
- *
- * @access private
- */
- function testRunner() {
- var featureNames;
- var feature;
- var aliasIdx;
- var result;
- var nameIdx;
- var featureName;
- var featureNameSplit;
- for (var featureIdx in tests) {
- if (tests.hasOwnProperty(featureIdx)) {
- featureNames = [];
- feature = tests[featureIdx];
- // run the test, throw the return value into the Modernizr,
- // then based on that boolean, define an appropriate className
- // and push it into an array of classes we'll join later.
- //
- // If there is no name, it's an 'async' test that is run,
- // but not directly added to the object. That should
- // be done with a post-run addTest call.
- if (feature.name) {
- featureNames.push(feature.name.toLowerCase());
- if (feature.options && feature.options.aliases && feature.options.aliases.length) {
- // Add all the aliases into the names list
- for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
- featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
- }
- }
- }
- // Run the test, or use the raw value if it's not a function
- result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
- // Set each of the names on the Modernizr object
- for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
- featureName = featureNames[nameIdx];
- // Support dot properties as sub tests. We don't do checking to make sure
- // that the implied parent tests have been added. You must call them in
- // order (either in the test, or make the parent test a dependency).
- //
- // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
- // hashtag famous last words
- featureNameSplit = featureName.split('.');
- if (featureNameSplit.length === 1) {
- Modernizr[featureNameSplit[0]] = result;
- } else {
- // cast to a Boolean, if not one already
- if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
- Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
- }
- Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
- }
- classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
- }
- }
- }
- }
- ;
- /**
- * docElement is a convenience wrapper to grab the root element of the document
- *
- * @access private
- * @returns {HTMLElement|SVGElement} The root element of the document
- */
- var docElement = document.documentElement;
- /**
- * A convenience helper to check if the document we are running in is an SVG document
- *
- * @access private
- * @returns {boolean}
- */
- var isSVG = docElement.nodeName.toLowerCase() === 'svg';
- /**
- * setClasses takes an array of class names and adds them to the root element
- *
- * @access private
- * @function setClasses
- * @param {string[]} classes - Array of class names
- */
- // Pass in an and array of class names, e.g.:
- // ['no-webp', 'borderradius', ...]
- function setClasses(classes) {
- var className = docElement.className;
- var classPrefix = Modernizr._config.classPrefix || '';
- if (isSVG) {
- className = className.baseVal;
- }
- // Change `no-js` to `js` (independently of the `enableClasses` option)
- // Handle classPrefix on this too
- if (Modernizr._config.enableJSClass) {
- var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
- className = className.replace(reJS, '$1' + classPrefix + 'js$2');
- }
- if (Modernizr._config.enableClasses) {
- // Add the new classes
- className += ' ' + classPrefix + classes.join(' ' + classPrefix);
- if (isSVG) {
- docElement.className.baseVal = className;
- } else {
- docElement.className = className;
- }
- }
- }
- ;
- /**
- * createElement is a convenience wrapper around document.createElement. Since we
- * use createElement all over the place, this allows for (slightly) smaller code
- * as well as abstracting away issues with creating elements in contexts other than
- * HTML documents (e.g. SVG documents).
- *
- * @access private
- * @function createElement
- * @returns {HTMLElement|SVGElement} An HTML or SVG element
- */
- function createElement() {
- if (typeof document.createElement !== 'function') {
- // This is the case in IE7, where the type of createElement is "object".
- // For this reason, we cannot call apply() as Object is not a Function.
- return document.createElement(arguments[0]);
- } else if (isSVG) {
- return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
- } else {
- return document.createElement.apply(document, arguments);
- }
- }
- ;
- /**
- * getBody returns the body of a document, or an element that can stand in for
- * the body if a real body does not exist
- *
- * @access private
- * @function getBody
- * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
- * artificially created element that stands in for the body
- */
- function getBody() {
- // After page load injecting a fake body doesn't work so check if body exists
- var body = document.body;
- if (!body) {
- // Can't use the real body create a fake one.
- body = createElement(isSVG ? 'svg' : 'body');
- body.fake = true;
- }
- return body;
- }
- ;
- /**
- * injectElementWithStyles injects an element with style element and some CSS rules
- *
- * @access private
- * @function injectElementWithStyles
- * @param {string} rule - String representing a css rule
- * @param {function} callback - A function that is used to test the injected element
- * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
- * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
- * @returns {boolean}
- */
- function injectElementWithStyles(rule, callback, nodes, testnames) {
- var mod = 'modernizr';
- var style;
- var ret;
- var node;
- var docOverflow;
- var div = createElement('div');
- var body = getBody();
- if (parseInt(nodes, 10)) {
- // In order not to give false positives we create a node for each test
- // This also allows the method to scale for unspecified uses
- while (nodes--) {
- node = createElement('div');
- node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
- div.appendChild(node);
- }
- }
- style = createElement('style');
- style.type = 'text/css';
- style.id = 's' + mod;
- // 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.
- // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
- (!body.fake ? div : body).appendChild(style);
- body.appendChild(div);
- if (style.styleSheet) {
- style.styleSheet.cssText = rule;
- } else {
- style.appendChild(document.createTextNode(rule));
- }
- div.id = mod;
- if (body.fake) {
- //avoid crashing IE8, if background image is used
- body.style.background = '';
- //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
- body.style.overflow = 'hidden';
- docOverflow = docElement.style.overflow;
- docElement.style.overflow = 'hidden';
- docElement.appendChild(body);
- }
- ret = callback(div, rule);
- // If this is done after page load we don't want to remove the body so check if body exists
- if (body.fake) {
- body.parentNode.removeChild(body);
- docElement.style.overflow = docOverflow;
- // Trigger layout so kinetic scrolling isn't disabled in iOS6+
- // eslint-disable-next-line
- docElement.offsetHeight;
- } else {
- div.parentNode.removeChild(div);
- }
- return !!ret;
- }
- ;
- /**
- * Modernizr.mq tests a given media query, live against the current state of the window
- * adapted from matchMedia polyfill by Scott Jehl and Paul Irish
- * gist.github.com/786768
- *
- * @memberof Modernizr
- * @name Modernizr.mq
- * @optionName Modernizr.mq()
- * @optionProp mq
- * @access public
- * @function mq
- * @param {string} mq - String of the media query we want to test
- * @returns {boolean}
- * @example
- * Modernizr.mq allows for you to programmatically check if the current browser
- * window state matches a media query.
- *
- * ```js
- * var query = Modernizr.mq('(min-width: 900px)');
- *
- * if (query) {
- * // the browser window is larger than 900px
- * }
- * ```
- *
- * Only valid media queries are supported, therefore you must always include values
- * with your media query
- *
- * ```js
- * // good
- * Modernizr.mq('(min-width: 900px)');
- *
- * // bad
- * Modernizr.mq('min-width');
- * ```
- *
- * If you would just like to test that media queries are supported in general, use
- *
- * ```js
- * Modernizr.mq('only all'); // true if MQ are supported, false if not
- * ```
- *
- *
- * Note that if the browser does not support media queries (e.g. old IE) mq will
- * always return false.
- */
- var mq = (function() {
- var matchMedia = window.matchMedia || window.msMatchMedia;
- if (matchMedia) {
- return function(mq) {
- var mql = matchMedia(mq);
- return mql && mql.matches || false;
- };
- }
- return function(mq) {
- var bool = false;
- injectElementWithStyles('@media ' + mq + ' { #modernizr { position: absolute; } }', function(node) {
- bool = (window.getComputedStyle ?
- window.getComputedStyle(node, null) :
- node.currentStyle).position == 'absolute';
- });
- return bool;
- };
- })();
- ModernizrProto.mq = mq;
- // Run each test
- testRunner();
- // Remove the "no-js" class if it exists
- setClasses(classes);
- delete ModernizrProto.addTest;
- delete ModernizrProto.addAsyncTest;
- // Run the things that are supposed to run after the tests
- for (var i = 0; i < Modernizr._q.length; i++) {
- Modernizr._q[i]();
- }
- // Leak Modernizr namespace
- window.Modernizr = Modernizr;
- ;
- })(window, document);
|