| /*! |
| * modernizr v3.5.0 |
| * Build https://modernizr.com/download?-classlist-datalistelem-es5-eventlistener-framed-hidden-history-postmessage-queryselector-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 tests = []; |
| |
| |
| /** |
| * |
| * ModernizrProto is the constructor for Modernizr |
| * |
| * @class |
| * @access public |
| */ |
| |
| var ModernizrProto = { |
| // The current version, dummy |
| _version: '3.5.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(); |
| |
| |
| |
| var classes = []; |
| |
| |
| /** |
| * 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; |
| |
| /*! |
| { |
| "name": "classList", |
| "caniuse": "classlist", |
| "property": "classlist", |
| "tags": ["dom"], |
| "builderAliases": ["dataview_api"], |
| "notes": [{ |
| "name": "MDN Docs", |
| "href": "https://developer.mozilla.org/en/DOM/element.classList" |
| }] |
| } |
| !*/ |
| |
| Modernizr.addTest('classlist', 'classList' in docElement); |
| |
| |
| /** |
| * 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'; |
| |
| |
| /** |
| * 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); |
| } |
| } |
| |
| ; |
| /*! |
| { |
| "name": "[hidden] Attribute", |
| "property": "hidden", |
| "tags": ["dom"], |
| "notes": [{ |
| "name": "WHATWG: The hidden attribute", |
| "href": "https://developers.whatwg.org/editing.html#the-hidden-attribute" |
| }, { |
| "name": "original implementation of detect code", |
| "href": "https://github.com/aFarkas/html5shiv/blob/bf4fcc4/src/html5shiv.js#L38" |
| }], |
| "polyfills": ["html5shiv"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"] |
| } |
| !*/ |
| /* DOC |
| Does the browser support the HTML5 [hidden] attribute? |
| */ |
| |
| Modernizr.addTest('hidden', 'hidden' in createElement('a')); |
| |
| |
| /** |
| * since we have a fairly large number of input tests that don't mutate the input |
| * we create a single element that can be shared with all of those tests for a |
| * minor perf boost |
| * |
| * @access private |
| * @returns {HTMLInputElement} |
| */ |
| var inputElem = createElement('input'); |
| |
| /*! |
| { |
| "name": "Input attributes", |
| "property": "input", |
| "tags": ["forms"], |
| "authors": ["Mike Taylor"], |
| "notes": [{ |
| "name": "WHATWG spec", |
| "href": "https://html.spec.whatwg.org/multipage/forms.html#input-type-attr-summary" |
| }], |
| "knownBugs": ["Some blackberry devices report false positive for input.multiple"] |
| } |
| !*/ |
| /* DOC |
| Detects support for HTML5 `<input>` element attributes and exposes Boolean subproperties with the results: |
| |
| ```javascript |
| Modernizr.input.autocomplete |
| Modernizr.input.autofocus |
| Modernizr.input.list |
| Modernizr.input.max |
| Modernizr.input.min |
| Modernizr.input.multiple |
| Modernizr.input.pattern |
| Modernizr.input.placeholder |
| Modernizr.input.required |
| Modernizr.input.step |
| ``` |
| */ |
| |
| // Run through HTML5's new input attributes to see if the UA understands any. |
| // Mike Taylr has created a comprehensive resource for testing these attributes |
| // when applied to all input types: |
| // miketaylr.com/code/input-type-attr.html |
| |
| // Only input placeholder is tested while textarea's placeholder is not. |
| // Currently Safari 4 and Opera 11 have support only for the input placeholder |
| // Both tests are available in feature-detects/forms-placeholder.js |
| |
| var inputattrs = 'autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '); |
| var attrs = {}; |
| |
| Modernizr.input = (function(props) { |
| for (var i = 0, len = props.length; i < len; i++) { |
| attrs[ props[i] ] = !!(props[i] in inputElem); |
| } |
| if (attrs.list) { |
| // safari false positive's on datalist: webk.it/74252 |
| // see also github.com/Modernizr/Modernizr/issues/146 |
| attrs.list = !!(createElement('datalist') && window.HTMLDataListElement); |
| } |
| return attrs; |
| })(inputattrs); |
| |
| /*! |
| { |
| "name": "datalist Element", |
| "caniuse": "datalist", |
| "property": "datalistelem", |
| "tags": ["elem"], |
| "builderAliases": ["elem_datalist"], |
| "warnings": ["This test is a dupe of Modernizr.input.list. Only around for legacy reasons."], |
| "notes": [{ |
| "name": "CSS Tricks Article", |
| "href": "https://css-tricks.com/15346-relevant-dropdowns-polyfill-for-datalist/" |
| },{ |
| "name": "Mike Taylor Code", |
| "href": "https://miketaylr.com/code/datalist.html" |
| }] |
| } |
| !*/ |
| |
| // lol. we already have a test for datalist built in! silly you. |
| // Leaving it around in case anyone's using it |
| |
| Modernizr.addTest('datalistelem', Modernizr.input.list); |
| |
| /*! |
| { |
| "name": "ES5 Array", |
| "property": "es5array", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "polyfills": ["es5shim"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements ECMAScript 5 Array per specification. |
| */ |
| |
| Modernizr.addTest('es5array', function() { |
| return !!(Array.prototype && |
| Array.prototype.every && |
| Array.prototype.filter && |
| Array.prototype.forEach && |
| Array.prototype.indexOf && |
| Array.prototype.lastIndexOf && |
| Array.prototype.map && |
| Array.prototype.some && |
| Array.prototype.reduce && |
| Array.prototype.reduceRight && |
| Array.isArray); |
| }); |
| |
| /*! |
| { |
| "name": "ES5 Date", |
| "property": "es5date", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "polyfills": ["es5shim"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements ECMAScript 5 Date per specification. |
| */ |
| |
| Modernizr.addTest('es5date', function() { |
| var isoDate = '2013-04-12T06:06:37.307Z', |
| canParseISODate = false; |
| try { |
| canParseISODate = !!Date.parse(isoDate); |
| } catch (e) { |
| // no ISO date parsing yet |
| } |
| return !!(Date.now && |
| Date.prototype && |
| Date.prototype.toISOString && |
| Date.prototype.toJSON && |
| canParseISODate); |
| }); |
| |
| /*! |
| { |
| "name": "ES5 Function", |
| "property": "es5function", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "polyfills": ["es5shim"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements ECMAScript 5 Function per specification. |
| */ |
| |
| Modernizr.addTest('es5function', function() { |
| return !!(Function.prototype && Function.prototype.bind); |
| }); |
| |
| /*! |
| { |
| "name": "ES5 Object", |
| "property": "es5object", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "polyfills": ["es5shim", "es5sham"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements ECMAScript 5 Object per specification. |
| */ |
| |
| Modernizr.addTest('es5object', function() { |
| return !!(Object.keys && |
| Object.create && |
| Object.getPrototypeOf && |
| Object.getOwnPropertyNames && |
| Object.isSealed && |
| Object.isFrozen && |
| Object.isExtensible && |
| Object.getOwnPropertyDescriptor && |
| Object.defineProperty && |
| Object.defineProperties && |
| Object.seal && |
| Object.freeze && |
| Object.preventExtensions); |
| }); |
| |
| /*! |
| { |
| "name": "ES5 Strict Mode", |
| "property": "strictmode", |
| "caniuse": "sctrict-mode", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "authors": ["@kangax"], |
| "tags": ["es5"], |
| "builderAliases": ["es5_strictmode"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements ECMAScript 5 Object strict mode. |
| */ |
| |
| Modernizr.addTest('strictmode', (function() {'use strict'; return !this; })()); |
| |
| /*! |
| { |
| "name": "ES5 String", |
| "property": "es5string", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "polyfills": ["es5shim"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements ECMAScript 5 String per specification. |
| */ |
| |
| Modernizr.addTest('es5string', function() { |
| return !!(String.prototype && String.prototype.trim); |
| }); |
| |
| /*! |
| { |
| "name": "JSON", |
| "property": "json", |
| "caniuse": "json", |
| "notes": [{ |
| "name": "MDN documentation", |
| "href": "https://developer.mozilla.org/en-US/docs/Glossary/JSON" |
| }], |
| "polyfills": ["json2"] |
| } |
| !*/ |
| /* DOC |
| Detects native support for JSON handling functions. |
| */ |
| |
| // this will also succeed if you've loaded the JSON2.js polyfill ahead of time |
| // ... but that should be obvious. :) |
| |
| Modernizr.addTest('json', 'JSON' in window && 'parse' in JSON && 'stringify' in JSON); |
| |
| /*! |
| { |
| "name": "ES5 Syntax", |
| "property": "es5syntax", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }, { |
| "name": "original implementation of detect code", |
| "href": "http://kangax.github.io/es5-compat-table/" |
| }], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "warnings": ["This detect uses `eval()`, so CSP may be a problem."], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser accepts ECMAScript 5 syntax. |
| */ |
| |
| Modernizr.addTest('es5syntax', function() { |
| var value, obj, stringAccess, getter, setter, reservedWords, zeroWidthChars; |
| try { |
| /* eslint no-eval: "off" */ |
| // Property access on strings |
| stringAccess = eval('"foobar"[3] === "b"'); |
| // Getter in property initializer |
| getter = eval('({ get x(){ return 1 } }).x === 1'); |
| eval('({ set x(v){ value = v; } }).x = 1'); |
| // Setter in property initializer |
| setter = value === 1; |
| // Reserved words as property names |
| eval('obj = ({ if: 1 })'); |
| reservedWords = obj['if'] === 1; |
| // Zero-width characters in identifiers |
| zeroWidthChars = eval('_\u200c\u200d = true'); |
| |
| return stringAccess && getter && setter && reservedWords && zeroWidthChars; |
| } catch (ignore) { |
| return false; |
| } |
| }); |
| |
| /*! |
| { |
| "name": "ES5 Immutable Undefined", |
| "property": "es5undefined", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }, { |
| "name": "original implementation of detect code", |
| "href": "http://kangax.github.io/es5-compat-table/" |
| }], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser prevents assignment to global `undefined` per ECMAScript 5. |
| */ |
| |
| Modernizr.addTest('es5undefined', function() { |
| var result, originalUndefined; |
| try { |
| originalUndefined = window.undefined; |
| window.undefined = 12345; |
| result = typeof window.undefined === 'undefined'; |
| window.undefined = originalUndefined; |
| } catch (e) { |
| return false; |
| } |
| return result; |
| }); |
| |
| /*! |
| { |
| "name": "ES5", |
| "property": "es5", |
| "notes": [{ |
| "name": "ECMAScript 5.1 Language Specification", |
| "href": "http://www.ecma-international.org/ecma-262/5.1/" |
| }], |
| "polyfills": ["es5shim", "es5sham"], |
| "authors": ["Ron Waldon (@jokeyrhyme)"], |
| "tags": ["es5"] |
| } |
| !*/ |
| /* DOC |
| Check if browser implements everything as specified in ECMAScript 5. |
| */ |
| |
| Modernizr.addTest('es5', function() { |
| return !!( |
| Modernizr.es5array && |
| Modernizr.es5date && |
| Modernizr.es5function && |
| Modernizr.es5object && |
| Modernizr.strictmode && |
| Modernizr.es5string && |
| Modernizr.json && |
| Modernizr.es5syntax && |
| Modernizr.es5undefined |
| ); |
| }); |
| |
| /*! |
| { |
| "name": "Event Listener", |
| "property": "eventlistener", |
| "authors": ["Andrew Betts (@triblondon)"], |
| "notes": [{ |
| "name": "W3C Spec", |
| "href": "https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Registration-interfaces" |
| }], |
| "polyfills": ["eventlistener"] |
| } |
| !*/ |
| /* DOC |
| Detects native support for addEventListener |
| */ |
| |
| Modernizr.addTest('eventlistener', 'addEventListener' in window); |
| |
| /*! |
| { |
| "name": "History API", |
| "property": "history", |
| "caniuse": "history", |
| "tags": ["history"], |
| "authors": ["Hay Kranen", "Alexander Farkas"], |
| "notes": [{ |
| "name": "W3C Spec", |
| "href": "https://www.w3.org/TR/html51/browsers.html#the-history-interface" |
| }, { |
| "name": "MDN documentation", |
| "href": "https://developer.mozilla.org/en-US/docs/Web/API/window.history" |
| }], |
| "polyfills": ["historyjs", "html5historyapi"] |
| } |
| !*/ |
| /* DOC |
| Detects support for the History API for manipulating the browser session history. |
| */ |
| |
| Modernizr.addTest('history', function() { |
| // Issue #733 |
| // The stock browser on Android 2.2 & 2.3, and 4.0.x returns positive on history support |
| // Unfortunately support is really buggy and there is no clean way to detect |
| // these bugs, so we fall back to a user agent sniff :( |
| var ua = navigator.userAgent; |
| |
| // We only want Android 2 and 4.0, stock browser, and not Chrome which identifies |
| // itself as 'Mobile Safari' as well, nor Windows Phone (issue #1471). |
| if ((ua.indexOf('Android 2.') !== -1 || |
| (ua.indexOf('Android 4.0') !== -1)) && |
| ua.indexOf('Mobile Safari') !== -1 && |
| ua.indexOf('Chrome') === -1 && |
| ua.indexOf('Windows Phone') === -1 && |
| // Since all documents on file:// share an origin, the History apis are |
| // blocked there as well |
| location.protocol !== 'file:' |
| ) { |
| return false; |
| } |
| |
| // Return the regular check |
| return (window.history && 'pushState' in window.history); |
| }); |
| |
| /*! |
| { |
| "name": "postMessage", |
| "property": "postmessage", |
| "caniuse": "x-doc-messaging", |
| "notes": [{ |
| "name": "W3C Spec", |
| "href": "http://www.w3.org/TR/html5/comms.html#posting-messages" |
| }], |
| "polyfills": ["easyxdm", "postmessage-jquery"] |
| } |
| !*/ |
| /* DOC |
| Detects support for the `window.postMessage` protocol for cross-document messaging. |
| */ |
| |
| Modernizr.addTest('postmessage', 'postMessage' in window); |
| |
| /*! |
| { |
| "name": "QuerySelector", |
| "property": "queryselector", |
| "caniuse": "queryselector", |
| "tags": ["queryselector"], |
| "authors": ["Andrew Betts (@triblondon)"], |
| "notes": [{ |
| "name" : "W3C Selectors reference", |
| "href": "https://www.w3.org/TR/selectors-api/#queryselectorall" |
| }], |
| "polyfills": ["css-selector-engine"] |
| } |
| !*/ |
| /* DOC |
| Detects support for querySelector. |
| */ |
| |
| Modernizr.addTest('queryselector', 'querySelector' in document && 'querySelectorAll' in document); |
| |
| /*! |
| { |
| "name": "Framed window", |
| "property": "framed", |
| "tags": ["window"], |
| "builderAliases": ["window_framed"] |
| } |
| !*/ |
| /* DOC |
| Tests if page is iframed. |
| */ |
| |
| // github.com/Modernizr/Modernizr/issues/242 |
| |
| Modernizr.addTest('framed', window.location != top.location); |
| |
| |
| // Run each test |
| testRunner(); |
| |
| 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); |