{"version":3,"names":[],"mappings":"","sources":["modernizr.js"],"sourcesContent":["/*!\n * modernizr v3.3.1\n * Build http://modernizr.com/download?-adownload-svg-touchevents-addtest-fnbind-printshiv-setclasses-testprop-dontmin\n *\n * Copyright (c)\n * Faruk Ates\n * Paul Irish\n * Alex Sexton\n * Ryan Seddon\n * Patrick Kettner\n * Stu Cox\n * Richard Herrera\n\n * MIT License\n */\n\n/*\n * Modernizr tests which native CSS3 and HTML5 features are available in the\n * current UA and makes the results available to you in two ways: as properties on\n * a global `Modernizr` object, and as classes on the `` element. This\n * information allows you to progressively enhance your pages with a granular level\n * of control over the experience.\n*/\n\n;(function(window, document, undefined){\n var tests = [];\n \n\n /**\n *\n * ModernizrProto is the constructor for Modernizr\n *\n * @class\n * @access public\n */\n\n var ModernizrProto = {\n // The current version, dummy\n _version: '3.3.1',\n\n // Any settings that don't work as separate modules\n // can go in here as configuration.\n _config: {\n 'classPrefix': '',\n 'enableClasses': true,\n 'enableJSClass': true,\n 'usePrefixes': true\n },\n\n // Queue of tests\n _q: [],\n\n // Stub these for people who are listening\n on: function(test, cb) {\n // I don't really think people should do this, but we can\n // safe guard it a bit.\n // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.\n // This is in case people listen to synchronous tests. I would leave it out,\n // but the code to *disallow* sync tests in the real version of this\n // function is actually larger than this.\n var self = this;\n setTimeout(function() {\n cb(self[test]);\n }, 0);\n },\n\n addTest: function(name, fn, options) {\n tests.push({name: name, fn: fn, options: options});\n },\n\n addAsyncTest: function(fn) {\n tests.push({name: null, fn: fn});\n }\n };\n\n \n\n // Fake some of Object.create so we can force non test results to be non \"own\" properties.\n var Modernizr = function() {};\n Modernizr.prototype = ModernizrProto;\n\n // Leak modernizr globally when you `require` it rather than force it here.\n // Overwrite name so constructor name is nicer :D\n Modernizr = new Modernizr();\n\n \n\n var classes = [];\n \n\n /**\n * is returns a boolean if the typeof an obj is exactly type.\n *\n * @access private\n * @function is\n * @param {*} obj - A thing we want to check the type of\n * @param {string} type - A string to compare the typeof against\n * @returns {boolean}\n */\n\n function is(obj, type) {\n return typeof obj === type;\n }\n ;\n\n /**\n * Run through all tests and detect their support in the current UA.\n *\n * @access private\n */\n\n function testRunner() {\n var featureNames;\n var feature;\n var aliasIdx;\n var result;\n var nameIdx;\n var featureName;\n var featureNameSplit;\n\n for (var featureIdx in tests) {\n if (tests.hasOwnProperty(featureIdx)) {\n featureNames = [];\n feature = tests[featureIdx];\n // run the test, throw the return value into the Modernizr,\n // then based on that boolean, define an appropriate className\n // and push it into an array of classes we'll join later.\n //\n // If there is no name, it's an 'async' test that is run,\n // but not directly added to the object. That should\n // be done with a post-run addTest call.\n if (feature.name) {\n featureNames.push(feature.name.toLowerCase());\n\n if (feature.options && feature.options.aliases && feature.options.aliases.length) {\n // Add all the aliases into the names list\n for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {\n featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());\n }\n }\n }\n\n // Run the test, or use the raw value if it's not a function\n result = is(feature.fn, 'function') ? feature.fn() : feature.fn;\n\n\n // Set each of the names on the Modernizr object\n for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {\n featureName = featureNames[nameIdx];\n // Support dot properties as sub tests. We don't do checking to make sure\n // that the implied parent tests have been added. You must call them in\n // order (either in the test, or make the parent test a dependency).\n //\n // Cap it to TWO to make the logic simple and because who needs that kind of subtesting\n // hashtag famous last words\n featureNameSplit = featureName.split('.');\n\n if (featureNameSplit.length === 1) {\n Modernizr[featureNameSplit[0]] = result;\n } else {\n // cast to a Boolean, if not one already\n /* jshint -W053 */\n if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {\n Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);\n }\n\n Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;\n }\n\n classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));\n }\n }\n }\n }\n ;\n\n /**\n * docElement is a convenience wrapper to grab the root element of the document\n *\n * @access private\n * @returns {HTMLElement|SVGElement} The root element of the document\n */\n\n var docElement = document.documentElement;\n \n\n /**\n * A convenience helper to check if the document we are running in is an SVG document\n *\n * @access private\n * @returns {boolean}\n */\n\n var isSVG = docElement.nodeName.toLowerCase() === 'svg';\n \n\n /**\n * setClasses takes an array of class names and adds them to the root element\n *\n * @access private\n * @function setClasses\n * @param {string[]} classes - Array of class names\n */\n\n // Pass in an and array of class names, e.g.:\n // ['no-webp', 'borderradius', ...]\n function setClasses(classes) {\n var className = docElement.className;\n var classPrefix = Modernizr._config.classPrefix || '';\n\n if (isSVG) {\n className = className.baseVal;\n }\n\n // Change `no-js` to `js` (independently of the `enableClasses` option)\n // Handle classPrefix on this too\n if (Modernizr._config.enableJSClass) {\n var reJS = new RegExp('(^|\\\\s)' + classPrefix + 'no-js(\\\\s|$)');\n className = className.replace(reJS, '$1' + classPrefix + 'js$2');\n }\n\n if (Modernizr._config.enableClasses) {\n // Add the new classes\n className += ' ' + classPrefix + classes.join(' ' + classPrefix);\n isSVG ? docElement.className.baseVal = className : docElement.className = className;\n }\n\n }\n\n ;\n\n /**\n * hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support\n *\n * @author kangax\n * @access private\n * @function hasOwnProp\n * @param {object} object - The object to check for a property\n * @param {string} property - The property to check for\n * @returns {boolean}\n */\n\n // hasOwnProperty shim by kangax needed for Safari 2.0 support\n var hasOwnProp;\n\n (function() {\n var _hasOwnProperty = ({}).hasOwnProperty;\n /* istanbul ignore else */\n /* we have no way of testing IE 5.5 or safari 2,\n * so just assume the else gets hit */\n if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {\n hasOwnProp = function(object, property) {\n return _hasOwnProperty.call(object, property);\n };\n }\n else {\n hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */\n return ((property in object) && is(object.constructor.prototype[property], 'undefined'));\n };\n }\n })();\n\n \n\n\n // _l tracks listeners for async tests, as well as tests that execute after the initial run\n ModernizrProto._l = {};\n\n /**\n * Modernizr.on is a way to listen for the completion of async tests. Being\n * asynchronous, they may not finish before your scripts run. As a result you\n * will get a possibly false negative `undefined` value.\n *\n * @memberof Modernizr\n * @name Modernizr.on\n * @access public\n * @function on\n * @param {string} feature - String name of the feature detect\n * @param {function} cb - Callback function returning a Boolean - true if feature is supported, false if not\n * @example\n *\n * ```js\n * Modernizr.on('flash', function( result ) {\n * if (result) {\n * // the browser has flash\n * } else {\n * // the browser does not have flash\n * }\n * });\n * ```\n */\n\n ModernizrProto.on = function(feature, cb) {\n // Create the list of listeners if it doesn't exist\n if (!this._l[feature]) {\n this._l[feature] = [];\n }\n\n // Push this test on to the listener list\n this._l[feature].push(cb);\n\n // If it's already been resolved, trigger it on next tick\n if (Modernizr.hasOwnProperty(feature)) {\n // Next Tick\n setTimeout(function() {\n Modernizr._trigger(feature, Modernizr[feature]);\n }, 0);\n }\n };\n\n /**\n * _trigger is the private function used to signal test completion and run any\n * callbacks registered through [Modernizr.on](#modernizr-on)\n *\n * @memberof Modernizr\n * @name Modernizr._trigger\n * @access private\n * @function _trigger\n * @param {string} feature - string name of the feature detect\n * @param {function|boolean} [res] - A feature detection function, or the boolean =\n * result of a feature detection function\n */\n\n ModernizrProto._trigger = function(feature, res) {\n if (!this._l[feature]) {\n return;\n }\n\n var cbs = this._l[feature];\n\n // Force async\n setTimeout(function() {\n var i, cb;\n for (i = 0; i < cbs.length; i++) {\n cb = cbs[i];\n cb(res);\n }\n }, 0);\n\n // Don't trigger these again\n delete this._l[feature];\n };\n\n /**\n * addTest allows you to define your own feature detects that are not currently\n * included in Modernizr (under the covers it's the exact same code Modernizr\n * uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)). Just like the offical detects, the result\n * will be added onto the Modernizr object, as well as an appropriate className set on\n * the html element when configured to do so\n *\n * @memberof Modernizr\n * @name Modernizr.addTest\n * @optionName Modernizr.addTest()\n * @optionProp addTest\n * @access public\n * @function addTest\n * @param {string|object} feature - The string name of the feature detect, or an\n * object of feature detect names and test\n * @param {function|boolean} test - Function returning true if feature is supported,\n * false if not. Otherwise a boolean representing the results of a feature detection\n * @example\n *\n * The most common way of creating your own feature detects is by calling\n * `Modernizr.addTest` with a string (preferably just lowercase, without any\n * punctuation), and a function you want executed that will return a boolean result\n *\n * ```js\n * Modernizr.addTest('itsTuesday', function() {\n * var d = new Date();\n * return d.getDay() === 2;\n * });\n * ```\n *\n * When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday,\n * and to `false` every other day of the week. One thing to notice is that the names of\n * feature detect functions are always lowercased when added to the Modernizr object. That\n * means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will.\n *\n *\n * Since we only look at the returned value from any feature detection function,\n * you do not need to actually use a function. For simple detections, just passing\n * in a statement that will return a boolean value works just fine.\n *\n * ```js\n * Modernizr.addTest('hasJquery', 'jQuery' in window);\n * ```\n *\n * Just like before, when the above runs `Modernizr.hasjquery` will be true if\n * jQuery has been included on the page. Not using a function saves a small amount\n * of overhead for the browser, as well as making your code much more readable.\n *\n * Finally, you also have the ability to pass in an object of feature names and\n * their tests. This is handy if you want to add multiple detections in one go.\n * The keys should always be a string, and the value can be either a boolean or\n * function that returns a boolean.\n *\n * ```js\n * var detects = {\n * 'hasjquery': 'jQuery' in window,\n * 'itstuesday': function() {\n * var d = new Date();\n * return d.getDay() === 2;\n * }\n * }\n *\n * Modernizr.addTest(detects);\n * ```\n *\n * There is really no difference between the first methods and this one, it is\n * just a convenience to let you write more readable code.\n */\n\n function addTest(feature, test) {\n\n if (typeof feature == 'object') {\n for (var key in feature) {\n if (hasOwnProp(feature, key)) {\n addTest(key, feature[ key ]);\n }\n }\n } else {\n\n feature = feature.toLowerCase();\n var featureNameSplit = feature.split('.');\n var last = Modernizr[featureNameSplit[0]];\n\n // Again, we don't check for parent test existence. Get that right, though.\n if (featureNameSplit.length == 2) {\n last = last[featureNameSplit[1]];\n }\n\n if (typeof last != 'undefined') {\n // we're going to quit if you're trying to overwrite an existing test\n // if we were to allow it, we'd do this:\n // var re = new RegExp(\"\\\\b(no-)?\" + feature + \"\\\\b\");\n // docElement.className = docElement.className.replace( re, '' );\n // but, no rly, stuff 'em.\n return Modernizr;\n }\n\n test = typeof test == 'function' ? test() : test;\n\n // Set the value (this is the magic, right here).\n if (featureNameSplit.length == 1) {\n Modernizr[featureNameSplit[0]] = test;\n } else {\n // cast to a Boolean, if not one already\n /* jshint -W053 */\n if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {\n Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);\n }\n\n Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test;\n }\n\n // Set a single class (either `feature` or `no-feature`)\n /* jshint -W041 */\n setClasses([(!!test && test != false ? '' : 'no-') + featureNameSplit.join('-')]);\n /* jshint +W041 */\n\n // Trigger the event\n Modernizr._trigger(feature, test);\n }\n\n return Modernizr; // allow chaining.\n }\n\n // After all the tests are run, add self to the Modernizr prototype\n Modernizr._q.push(function() {\n ModernizrProto.addTest = addTest;\n });\n\n \n\n\n/**\n * @optionName html5printshiv\n * @optionProp html5printshiv\n */\n\n // Take the html5 variable out of the html5shiv scope so we can return it.\n var html5;\n if (!isSVG) {\n\n /**\n * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n */\n ;(function(window, document) {\n /*jshint evil:true */\n /** version */\n var version = '3.7.3';\n\n /** Preset options */\n var options = window.html5 || {};\n\n /** Used to skip problem elements */\n var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;\n\n /** Not all elements can be cloned in IE **/\n var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;\n\n /** Detect whether the browser supports default html5 styles */\n var supportsHtml5Styles;\n\n /** Name of the expando, to work with multiple documents or to re-shiv one document */\n var expando = '_html5shiv';\n\n /** The id for the the documents expando */\n var expanID = 0;\n\n /** Cached data for each document */\n var expandoData = {};\n\n /** Detect whether the browser supports unknown elements */\n var supportsUnknownElements;\n\n (function() {\n try {\n var a = document.createElement('a');\n a.innerHTML = '';\n //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles\n supportsHtml5Styles = ('hidden' in a);\n\n supportsUnknownElements = a.childNodes.length == 1 || (function() {\n // assign a false positive if unable to shiv\n (document.createElement)('a');\n var frag = document.createDocumentFragment();\n return (\n typeof frag.cloneNode == 'undefined' ||\n typeof frag.createDocumentFragment == 'undefined' ||\n typeof frag.createElement == 'undefined'\n );\n }());\n } catch(e) {\n // assign a false positive if detection fails => unable to shiv\n supportsHtml5Styles = true;\n supportsUnknownElements = true;\n }\n\n }());\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Creates a style sheet with the given CSS text and adds it to the document.\n * @private\n * @param {Document} ownerDocument The document.\n * @param {String} cssText The CSS text.\n * @returns {StyleSheet} The style element.\n */\n function addStyleSheet(ownerDocument, cssText) {\n var p = ownerDocument.createElement('p'),\n parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;\n\n p.innerHTML = 'x';\n return parent.insertBefore(p.lastChild, parent.firstChild);\n }\n\n /**\n * Returns the value of `html5.elements` as an array.\n * @private\n * @returns {Array} An array of shived element node names.\n */\n function getElements() {\n var elements = html5.elements;\n return typeof elements == 'string' ? elements.split(' ') : elements;\n }\n\n /**\n * Extends the built-in list of html5 elements\n * @memberOf html5\n * @param {String|Array} newElements whitespace separated list or array of new element names to shiv\n * @param {Document} ownerDocument The context document.\n */\n function addElements(newElements, ownerDocument) {\n var elements = html5.elements;\n if(typeof elements != 'string'){\n elements = elements.join(' ');\n }\n if(typeof newElements != 'string'){\n newElements = newElements.join(' ');\n }\n html5.elements = elements +' '+ newElements;\n shivDocument(ownerDocument);\n }\n\n /**\n * Returns the data associated to the given document\n * @private\n * @param {Document} ownerDocument The document.\n * @returns {Object} An object of data.\n */\n function getExpandoData(ownerDocument) {\n var data = expandoData[ownerDocument[expando]];\n if (!data) {\n data = {};\n expanID++;\n ownerDocument[expando] = expanID;\n expandoData[expanID] = data;\n }\n return data;\n }\n\n /**\n * returns a shived element for the given nodeName and document\n * @memberOf html5\n * @param {String} nodeName name of the element\n * @param {Document} ownerDocument The context document.\n * @returns {Object} The shived element.\n */\n function createElement(nodeName, ownerDocument, data){\n if (!ownerDocument) {\n ownerDocument = document;\n }\n if(supportsUnknownElements){\n return ownerDocument.createElement(nodeName);\n }\n if (!data) {\n data = getExpandoData(ownerDocument);\n }\n var node;\n\n if (data.cache[nodeName]) {\n node = data.cache[nodeName].cloneNode();\n } else if (saveClones.test(nodeName)) {\n node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();\n } else {\n node = data.createElem(nodeName);\n }\n\n // Avoid adding some elements to fragments in IE < 9 because\n // * Attributes like `name` or `type` cannot be set/changed once an element\n // is inserted into a document/fragment\n // * Link elements with `src` attributes that are inaccessible, as with\n // a 403 response, will cause the tab/window to crash\n // * Script elements appended to fragments will execute when their `src`\n // or `text` property is set\n return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;\n }\n\n /**\n * returns a shived DocumentFragment for the given document\n * @memberOf html5\n * @param {Document} ownerDocument The context document.\n * @returns {Object} The shived DocumentFragment.\n */\n function createDocumentFragment(ownerDocument, data){\n if (!ownerDocument) {\n ownerDocument = document;\n }\n if(supportsUnknownElements){\n return ownerDocument.createDocumentFragment();\n }\n data = data || getExpandoData(ownerDocument);\n var clone = data.frag.cloneNode(),\n i = 0,\n elems = getElements(),\n l = elems.length;\n for(;i+~])(' + getElements().join('|') + ')(?=[[\\\\s,>+~#.:]|$)', 'gi'),\n replacement = '$1' + shivNamespace + '\\\\:$2';\n\n while (index--) {\n pair = parts[index] = parts[index].split('}');\n pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);\n parts[index] = pair.join('}');\n }\n return parts.join('{');\n }\n\n /**\n * Removes the given wrappers, leaving the original elements.\n * @private\n * @params {Array} wrappers An array of printable wrappers.\n */\n function removeWrappers(wrappers) {\n var index = wrappers.length;\n while (index--) {\n wrappers[index].removeNode();\n }\n }\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Shivs the given document for print.\n * @memberOf html5\n * @param {Document} ownerDocument The document to shiv.\n * @returns {Document} The shived document.\n */\n function shivPrint(ownerDocument) {\n var shivedSheet,\n wrappers,\n data = getExpandoData(ownerDocument),\n namespaces = ownerDocument.namespaces,\n ownerWindow = ownerDocument.parentWindow;\n\n if (!supportsShivableSheets || ownerDocument.printShived) {\n return ownerDocument;\n }\n if (typeof namespaces[shivNamespace] == 'undefined') {\n namespaces.add(shivNamespace);\n }\n\n function removeSheet() {\n clearTimeout(data._removeSheetTimer);\n if (shivedSheet) {\n shivedSheet.removeNode(true);\n }\n shivedSheet= null;\n }\n\n ownerWindow.attachEvent('onbeforeprint', function() {\n\n removeSheet();\n\n var imports,\n length,\n sheet,\n collection = ownerDocument.styleSheets,\n cssText = [],\n index = collection.length,\n sheets = Array(index);\n\n // convert styleSheets collection to an array\n while (index--) {\n sheets[index] = collection[index];\n }\n // concat all style sheet CSS text\n while ((sheet = sheets.pop())) {\n // IE does not enforce a same origin policy for external style sheets...\n // but has trouble with some dynamically created stylesheets\n if (!sheet.disabled && reMedia.test(sheet.media)) {\n\n try {\n imports = sheet.imports;\n length = imports.length;\n } catch(er){\n length = 0;\n }\n\n for (index = 0; index < length; index++) {\n sheets.push(imports[index]);\n }\n\n try {\n cssText.push(sheet.cssText);\n } catch(er){}\n }\n }\n\n // wrap all HTML5 elements with printable elements and add the shived style sheet\n cssText = shivCssText(cssText.reverse().join(''));\n wrappers = addWrappers(ownerDocument);\n shivedSheet = addStyleSheet(ownerDocument, cssText);\n\n });\n\n ownerWindow.attachEvent('onafterprint', function() {\n // remove wrappers, leaving the original elements, and remove the shived style sheet\n removeWrappers(wrappers);\n clearTimeout(data._removeSheetTimer);\n data._removeSheetTimer = setTimeout(removeSheet, 500);\n });\n\n ownerDocument.printShived = true;\n return ownerDocument;\n }\n\n /*--------------------------------------------------------------------------*/\n\n // expose API\n html5.type += ' print';\n html5.shivPrint = shivPrint;\n\n // shiv for print\n shivPrint(document);\n\n if(typeof module == 'object' && module.exports){\n module.exports = html5;\n }\n\n }(typeof window !== \"undefined\" ? window : this, document));\n }\n\n ;\n\n\n /**\n * contains checks to see if a string contains another string\n *\n * @access private\n * @function contains\n * @param {string} str - The string we want to check for substrings\n * @param {string} substr - The substring we want to search the first string for\n * @returns {boolean}\n */\n\n function contains(str, substr) {\n return !!~('' + str).indexOf(substr);\n }\n\n ;\n\n /**\n * createElement is a convenience wrapper around document.createElement. Since we\n * use createElement all over the place, this allows for (slightly) smaller code\n * as well as abstracting away issues with creating elements in contexts other than\n * HTML documents (e.g. SVG documents).\n *\n * @access private\n * @function createElement\n * @returns {HTMLElement|SVGElement} An HTML or SVG element\n */\n\n function createElement() {\n if (typeof document.createElement !== 'function') {\n // This is the case in IE7, where the type of createElement is \"object\".\n // For this reason, we cannot call apply() as Object is not a Function.\n return document.createElement(arguments[0]);\n } else if (isSVG) {\n return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);\n } else {\n return document.createElement.apply(document, arguments);\n }\n }\n\n ;\n\n /**\n * Create our \"modernizr\" element that we do most feature tests on.\n *\n * @access private\n */\n\n var modElem = {\n elem: createElement('modernizr')\n };\n\n // Clean up this element\n Modernizr._q.push(function() {\n delete modElem.elem;\n });\n\n \n\n var mStyle = {\n style: modElem.elem.style\n };\n\n // kill ref for gc, must happen before mod.elem is removed, so we unshift on to\n // the front of the queue.\n Modernizr._q.unshift(function() {\n delete mStyle.style;\n });\n\n \n\n /**\n * getBody returns the body of a document, or an element that can stand in for\n * the body if a real body does not exist\n *\n * @access private\n * @function getBody\n * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an\n * artificially created element that stands in for the body\n */\n\n function getBody() {\n // After page load injecting a fake body doesn't work so check if body exists\n var body = document.body;\n\n if (!body) {\n // Can't use the real body create a fake one.\n body = createElement(isSVG ? 'svg' : 'body');\n body.fake = true;\n }\n\n return body;\n }\n\n ;\n\n /**\n * injectElementWithStyles injects an element with style element and some CSS rules\n *\n * @access private\n * @function injectElementWithStyles\n * @param {string} rule - String representing a css rule\n * @param {function} callback - A function that is used to test the injected element\n * @param {number} [nodes] - An integer representing the number of additional nodes you want injected\n * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes\n * @returns {boolean}\n */\n\n function injectElementWithStyles(rule, callback, nodes, testnames) {\n var mod = 'modernizr';\n var style;\n var ret;\n var node;\n var docOverflow;\n var div = createElement('div');\n var body = getBody();\n\n if (parseInt(nodes, 10)) {\n // In order not to give false positives we create a node for each test\n // This also allows the method to scale for unspecified uses\n while (nodes--) {\n node = createElement('div');\n node.id = testnames ? testnames[nodes] : mod + (nodes + 1);\n div.appendChild(node);\n }\n }\n\n style = createElement('style');\n style.type = 'text/css';\n style.id = 's' + mod;\n\n // 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.\n // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270\n (!body.fake ? div : body).appendChild(style);\n body.appendChild(div);\n\n if (style.styleSheet) {\n style.styleSheet.cssText = rule;\n } else {\n style.appendChild(document.createTextNode(rule));\n }\n div.id = mod;\n\n if (body.fake) {\n //avoid crashing IE8, if background image is used\n body.style.background = '';\n //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible\n body.style.overflow = 'hidden';\n docOverflow = docElement.style.overflow;\n docElement.style.overflow = 'hidden';\n docElement.appendChild(body);\n }\n\n ret = callback(div, rule);\n // If this is done after page load we don't want to remove the body so check if body exists\n if (body.fake) {\n body.parentNode.removeChild(body);\n docElement.style.overflow = docOverflow;\n // Trigger layout so kinetic scrolling isn't disabled in iOS6+\n docElement.offsetHeight;\n } else {\n div.parentNode.removeChild(div);\n }\n\n return !!ret;\n\n }\n\n ;\n\n /**\n * domToCSS takes a camelCase string and converts it to kebab-case\n * e.g. boxSizing -> box-sizing\n *\n * @access private\n * @function domToCSS\n * @param {string} name - String name of camelCase prop we want to convert\n * @returns {string} The kebab-case version of the supplied name\n */\n\n function domToCSS(name) {\n return name.replace(/([A-Z])/g, function(str, m1) {\n return '-' + m1.toLowerCase();\n }).replace(/^ms-/, '-ms-');\n }\n ;\n\n /**\n * nativeTestProps allows for us to use native feature detection functionality if available.\n * some prefixed form, or false, in the case of an unsupported rule\n *\n * @access private\n * @function nativeTestProps\n * @param {array} props - An array of property names\n * @param {string} value - A string representing the value we want to check via @supports\n * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise\n */\n\n // Accepts a list of property names and a single value\n // Returns `undefined` if native detection not available\n function nativeTestProps(props, value) {\n var i = props.length;\n // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface\n if ('CSS' in window && 'supports' in window.CSS) {\n // Try every prefixed variant of the property\n while (i--) {\n if (window.CSS.supports(domToCSS(props[i]), value)) {\n return true;\n }\n }\n return false;\n }\n // Otherwise fall back to at-rule (for Opera 12.x)\n else if ('CSSSupportsRule' in window) {\n // Build a condition string for every prefixed variant\n var conditionText = [];\n while (i--) {\n conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');\n }\n conditionText = conditionText.join(' or ');\n return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {\n return getComputedStyle(node, null).position == 'absolute';\n });\n }\n return undefined;\n }\n ;\n\n /**\n * cssToDOM takes a kebab-case string and converts it to camelCase\n * e.g. box-sizing -> boxSizing\n *\n * @access private\n * @function cssToDOM\n * @param {string} name - String name of kebab-case prop we want to convert\n * @returns {string} The camelCase version of the supplied name\n */\n\n function cssToDOM(name) {\n return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {\n return m1 + m2.toUpperCase();\n }).replace(/^-/, '');\n }\n ;\n\n // testProps is a generic CSS / DOM property test.\n\n // In testing support for a given CSS property, it's legit to test:\n // `elem.style[styleName] !== undefined`\n // If the property is supported it will return an empty string,\n // if unsupported it will return undefined.\n\n // We'll take advantage of this quick test and skip setting a style\n // on our modernizr element, but instead just testing undefined vs\n // empty string.\n\n // Property names can be provided in either camelCase or kebab-case.\n\n function testProps(props, prefixed, value, skipValueTest) {\n skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;\n\n // Try native detect first\n if (!is(value, 'undefined')) {\n var result = nativeTestProps(props, value);\n if (!is(result, 'undefined')) {\n return result;\n }\n }\n\n // Otherwise do it properly\n var afterInit, i, propsLength, prop, before;\n\n // If we don't have a style element, that means we're running async or after\n // the core tests, so we'll need to create our own elements to use\n\n // inside of an SVG element, in certain browsers, the `style` element is only\n // defined for valid tags. Therefore, if `modernizr` does not have one, we\n // fall back to a less used element and hope for the best.\n var elems = ['modernizr', 'tspan'];\n while (!mStyle.style) {\n afterInit = true;\n mStyle.modElem = createElement(elems.shift());\n mStyle.style = mStyle.modElem.style;\n }\n\n // Delete the objects if we created them.\n function cleanElems() {\n if (afterInit) {\n delete mStyle.style;\n delete mStyle.modElem;\n }\n }\n\n propsLength = props.length;\n for (i = 0; i < propsLength; i++) {\n prop = props[i];\n before = mStyle.style[prop];\n\n if (contains(prop, '-')) {\n prop = cssToDOM(prop);\n }\n\n if (mStyle.style[prop] !== undefined) {\n\n // If value to test has been passed in, do a set-and-check test.\n // 0 (integer) is a valid property value, so check that `value` isn't\n // undefined, rather than just checking it's truthy.\n if (!skipValueTest && !is(value, 'undefined')) {\n\n // Needs a try catch block because of old IE. This is slow, but will\n // be avoided in most cases because `skipValueTest` will be used.\n try {\n mStyle.style[prop] = value;\n } catch (e) {}\n\n // If the property value has changed, we assume the value used is\n // supported. If `value` is empty string, it'll fail here (because\n // it hasn't changed), which matches how browsers have implemented\n // CSS.supports()\n if (mStyle.style[prop] != before) {\n cleanElems();\n return prefixed == 'pfx' ? prop : true;\n }\n }\n // Otherwise just return true, or the property name if this is a\n // `prefixed()` call\n else {\n cleanElems();\n return prefixed == 'pfx' ? prop : true;\n }\n }\n }\n cleanElems();\n return false;\n }\n\n ;\n\n /**\n * testProp() investigates whether a given style property is recognized\n * Property names can be provided in either camelCase or kebab-case.\n *\n * @memberof Modernizr\n * @name Modernizr.testProp\n * @access public\n * @optionName Modernizr.testProp()\n * @optionProp testProp\n * @function testProp\n * @param {string} prop - Name of the CSS property to check\n * @param {string} [value] - Name of the CSS value to check\n * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported\n * @returns {boolean}\n * @example\n *\n * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed\n * version of the string.\n *\n * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)\n *\n * ```js\n * Modernizr.testProp('pointerEvents') // true\n * ```\n *\n * You can also provide a value as an optional second argument to check if a\n * specific value is supported\n *\n * ```js\n * Modernizr.testProp('pointerEvents', 'none') // true\n * Modernizr.testProp('pointerEvents', 'penguin') // false\n * ```\n */\n\n var testProp = ModernizrProto.testProp = function(prop, value, useValue) {\n return testProps([prop], undefined, value, useValue);\n };\n \n\n /**\n * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.\n *\n * @access private\n * @function fnBind\n * @param {function} fn - a function you want to change `this` reference to\n * @param {object} that - the `this` you want to call the function with\n * @returns {function} The wrapped version of the supplied function\n */\n\n function fnBind(fn, that) {\n return function() {\n return fn.apply(that, arguments);\n };\n }\n\n ;\n\n /**\n * List of property values to set for css tests. See ticket #21\n * http://git.io/vUGl4\n *\n * @memberof Modernizr\n * @name Modernizr._prefixes\n * @optionName Modernizr._prefixes\n * @optionProp prefixes\n * @access public\n * @example\n *\n * Modernizr._prefixes is the internal list of prefixes that we test against\n * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply\n * an array of kebab-case vendor prefixes you can use within your code.\n *\n * Some common use cases include\n *\n * Generating all possible prefixed version of a CSS property\n * ```js\n * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');\n *\n * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'\n * ```\n *\n * Generating all possible prefixed version of a CSS value\n * ```js\n * rule = 'display:' + Modernizr._prefixes.join('flex; display:') + 'flex';\n *\n * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'\n * ```\n */\n\n var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : []);\n\n // expose these for the plugin API. Look in the source for how to join() them against your input\n ModernizrProto._prefixes = prefixes;\n\n \n\n /**\n * testStyles injects an element with style element and some CSS rules\n *\n * @memberof Modernizr\n * @name Modernizr.testStyles\n * @optionName Modernizr.testStyles()\n * @optionProp testStyles\n * @access public\n * @function testStyles\n * @param {string} rule - String representing a css rule\n * @param {function} callback - A function that is used to test the injected element\n * @param {number} [nodes] - An integer representing the number of additional nodes you want injected\n * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes\n * @returns {boolean}\n * @example\n *\n * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page\n * along with (possibly multiple) DOM elements. This lets you check for features\n * 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).\n *\n * ```js\n * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {\n * // elem is the first DOM node in the page (by default #modernizr)\n * // rule is the first argument you supplied - the CSS rule in string form\n *\n * addTest('widthworks', elem.style.width === '9px')\n * });\n * ```\n *\n * If your test requires multiple nodes, you can include a third argument\n * indicating how many additional div elements to include on the page. The\n * additional nodes are injected as children of the `elem` that is returned as\n * the first argument to the callback.\n *\n * ```js\n * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {\n * document.getElementById('modernizr').style.width === '1px'; // true\n * document.getElementById('modernizr2').style.width === '2px'; // true\n * elem.firstChild === document.getElementById('modernizr2'); // true\n * }, 1);\n * ```\n *\n * By default, all of the additional elements have an ID of `modernizr[n]`, where\n * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,\n * the second additional is `#modernizr3`, etc.).\n * If you want to have more meaningful IDs for your function, you can provide\n * them as the fourth argument, as an array of strings\n *\n * ```js\n * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {\n * elem.firstChild === document.getElementById('foo'); // true\n * elem.lastChild === document.getElementById('bar'); // true\n * }, 2, ['foo', 'bar']);\n * ```\n *\n */\n\n var testStyles = ModernizrProto.testStyles = injectElementWithStyles;\n \n/*!\n{\n \"name\": \"Touch Events\",\n \"property\": \"touchevents\",\n \"caniuse\" : \"touch\",\n \"tags\": [\"media\", \"attribute\"],\n \"notes\": [{\n \"name\": \"Touch Events spec\",\n \"href\": \"https://www.w3.org/TR/2013/WD-touch-events-20130124/\"\n }],\n \"warnings\": [\n \"Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device\"\n ],\n \"knownBugs\": [\n \"False-positive on some configurations of Nokia N900\",\n \"False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695\"\n ]\n}\n!*/\n/* DOC\nIndicates if the browser supports the W3C Touch Events API.\n\nThis *does not* necessarily reflect a touchscreen device:\n\n* Older touchscreen devices only emulate mouse events\n* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that\n* Some browsers & OS setups may enable touch APIs when no touchscreen is connected\n* Future browsers may implement other event models for touch interactions\n\nSee this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).\n\nIt's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).\n\nThis test will also return `true` for Firefox 4 Multitouch support.\n*/\n\n // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415\n Modernizr.addTest('touchevents', function() {\n var bool;\n if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {\n bool = true;\n } else {\n // include the 'heartz' as a way to have a non matching MQ to help terminate the join\n // https://git.io/vznFH\n var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');\n testStyles(query, function(node) {\n bool = node.offsetTop === 9;\n });\n }\n return bool;\n });\n\n/*!\n{\n \"name\": \"a[download] Attribute\",\n \"property\": \"adownload\",\n \"caniuse\" : \"download\",\n \"tags\": [\"media\", \"attribute\"],\n \"builderAliases\": [\"a_download\"],\n \"notes\": [{\n \"name\": \"WhatWG Reference\",\n \"href\": \"https://developers.whatwg.org/links.html#downloading-resources\"\n }]\n}\n!*/\n/* DOC\nWhen used on an ``, this attribute signifies that the resource it points to should be downloaded by the browser rather than navigating to it.\n*/\n\n Modernizr.addTest('adownload', !window.externalHost && 'download' in createElement('a'));\n\n/*!\n{\n \"name\": \"SVG\",\n \"property\": \"svg\",\n \"caniuse\": \"svg\",\n \"tags\": [\"svg\"],\n \"authors\": [\"Erik Dahlstrom\"],\n \"polyfills\": [\n \"svgweb\",\n \"raphael\",\n \"amplesdk\",\n \"canvg\",\n \"svg-boilerplate\",\n \"sie\",\n \"dojogfx\",\n \"fabricjs\"\n ]\n}\n!*/\n/* DOC\nDetects support for SVG in `` or `` elements.\n*/\n\n Modernizr.addTest('svg', !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect);\n\n\n // Run each test\n testRunner();\n\n // Remove the \"no-js\" class if it exists\n setClasses(classes);\n\n delete ModernizrProto.addTest;\n delete ModernizrProto.addAsyncTest;\n\n // Run the things that are supposed to run after the tests\n for (var i = 0; i < Modernizr._q.length; i++) {\n Modernizr._q[i]();\n }\n\n // Leak Modernizr namespace\n window.Modernizr = Modernizr;\n\n\n;\n\n})(window, document);"],"file":"modernizr.js","sourceRoot":"/source/"}