1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321 |
- /*!
- * modernizr v3.5.0
- * Build https://modernizr.com/download?-adownload-canvas-cssanimations-csstransforms-documentfragment-fullscreen-localstorage-svg-texttrackapi_track-todataurljpeg_todataurlpng_todataurlwebp-video-websockets-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.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();
-
- /*!
- {
- "name": "SVG",
- "property": "svg",
- "caniuse": "svg",
- "tags": ["svg"],
- "authors": ["Erik Dahlstrom"],
- "polyfills": [
- "svgweb",
- "raphael",
- "amplesdk",
- "canvg",
- "svg-boilerplate",
- "sie",
- "dojogfx",
- "fabricjs"
- ]
- }
- !*/
- /* DOC
- Detects support for SVG in `<embed>` or `<object>` elements.
- */
- Modernizr.addTest('svg', !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect);
- /*!
- {
- "name": "WebSockets Support",
- "property": "websockets",
- "authors": ["Phread [fearphage]", "Mike Sherov [mikesherov]", "Burak Yigit Kaya [BYK]"],
- "caniuse": "websockets",
- "tags": ["html5"],
- "warnings": [
- "This test will reject any old version of WebSockets even if it is not prefixed such as in Safari 5.1"
- ],
- "notes": [{
- "name": "CLOSING State and Spec",
- "href": "https://www.w3.org/TR/websockets/#the-websocket-interface"
- }],
- "polyfills": [
- "sockjs",
- "socketio",
- "kaazing-websocket-gateway",
- "websocketjs",
- "atmosphere",
- "graceful-websocket",
- "portal",
- "datachannel"
- ]
- }
- !*/
- var supports = false;
- try {
- supports = 'WebSocket' in window && window.WebSocket.CLOSING === 2;
- } catch (e) {}
- Modernizr.addTest('websockets', supports);
- /*!
- {
- "name": "Local Storage",
- "property": "localstorage",
- "caniuse": "namevalue-storage",
- "tags": ["storage"],
- "knownBugs": [],
- "notes": [],
- "warnings": [],
- "polyfills": [
- "joshuabell-polyfill",
- "cupcake",
- "storagepolyfill",
- "amplifyjs",
- "yui-cacheoffline"
- ]
- }
- !*/
- // In FF4, if disabled, window.localStorage should === null.
- // Normally, we could not test that directly and need to do a
- // `('localStorage' in window)` test first because otherwise Firefox will
- // throw bugzil.la/365772 if cookies are disabled
- // Similarly, in Chrome with "Block third-party cookies and site data" enabled,
- // attempting to access `window.sessionStorage` will throw an exception. crbug.com/357625
- // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
- // will throw the exception:
- // QUOTA_EXCEEDED_ERROR DOM Exception 22.
- // Peculiarly, getItem and removeItem calls do not throw.
- // Because we are forced to try/catch this, we'll go aggressive.
- // Just FWIW: IE8 Compat mode supports these features completely:
- // www.quirksmode.org/dom/html5.html
- // But IE8 doesn't support either with local files
- Modernizr.addTest('localstorage', function() {
- var mod = 'modernizr';
- try {
- localStorage.setItem(mod, mod);
- localStorage.removeItem(mod);
- return true;
- } catch (e) {
- return false;
- }
- });
- /**
- * 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": "Document Fragment",
- "property": "documentfragment",
- "notes": [{
- "name": "W3C DOM Level 1 Reference",
- "href": "https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-B63ED1A3"
- }, {
- "name": "SitePoint Reference",
- "href": "http://reference.sitepoint.com/javascript/DocumentFragment"
- }, {
- "name": "QuirksMode Compatibility Tables",
- "href": "http://www.quirksmode.org/m/w3c_core.html#t112"
- }],
- "authors": ["Ron Waldon (@jokeyrhyme)"],
- "knownBugs": ["false-positive on Blackberry 9500, see QuirksMode note"],
- "tags": []
- }
- !*/
- /* DOC
- Append multiple elements to the DOM within a single insertion.
- */
- Modernizr.addTest('documentfragment', function() {
- return 'createDocumentFragment' in document &&
- 'appendChild' 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';
-
- /**
- * 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);
- }
- }
- ;
- /*!
- {
- "name": "Canvas",
- "property": "canvas",
- "caniuse": "canvas",
- "tags": ["canvas", "graphics"],
- "polyfills": ["flashcanvas", "excanvas", "slcanvas", "fxcanvas"]
- }
- !*/
- /* DOC
- Detects support for the `<canvas>` element for 2D drawing.
- */
- // On the S60 and BB Storm, getContext exists, but always returns undefined
- // so we actually have to call getContext() to verify
- // github.com/Modernizr/Modernizr/issues/issue/97/
- Modernizr.addTest('canvas', function() {
- var elem = createElement('canvas');
- return !!(elem.getContext && elem.getContext('2d'));
- });
- /*!
- {
- "name": "HTML5 Video",
- "property": "video",
- "caniuse": "video",
- "tags": ["html5"],
- "knownBugs": [
- "Without QuickTime, `Modernizr.video.h264` will be `undefined`; https://github.com/Modernizr/Modernizr/issues/546"
- ],
- "polyfills": [
- "html5media",
- "mediaelementjs",
- "sublimevideo",
- "videojs",
- "leanbackplayer",
- "videoforeverybody"
- ]
- }
- !*/
- /* DOC
- Detects support for the video element, as well as testing what types of content it supports.
- Subproperties are provided to describe support for `ogg`, `h264` and `webm` formats, e.g.:
- ```javascript
- Modernizr.video // true
- Modernizr.video.ogg // 'probably'
- ```
- */
- // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
- // thx to NielsLeenheer and zcorpan
- // Note: in some older browsers, "no" was a return value instead of empty string.
- // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
- // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
- Modernizr.addTest('video', function() {
- var elem = createElement('video');
- var bool = false;
- // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
- try {
- bool = !!elem.canPlayType
- if (bool) {
- bool = new Boolean(bool);
- bool.ogg = elem.canPlayType('video/ogg; codecs="theora"').replace(/^no$/, '');
- // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
- bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/, '');
- bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/, '');
- bool.vp9 = elem.canPlayType('video/webm; codecs="vp9"').replace(/^no$/, '');
- bool.hls = elem.canPlayType('application/x-mpegURL; codecs="avc1.42E01E"').replace(/^no$/, '');
- }
- } catch (e) {}
- return bool;
- });
- /*!
- {
- "name": "a[download] Attribute",
- "property": "adownload",
- "caniuse" : "download",
- "tags": ["media", "attribute"],
- "builderAliases": ["a_download"],
- "notes": [{
- "name": "WhatWG Reference",
- "href": "https://developers.whatwg.org/links.html#downloading-resources"
- }]
- }
- !*/
- /* DOC
- When used on an `<a>`, this attribute signifies that the resource it points to should be downloaded by the browser rather than navigating to it.
- */
- Modernizr.addTest('adownload', !window.externalHost && 'download' in createElement('a'));
- /*!
- {
- "name": "canvas.toDataURL type support",
- "property": ["todataurljpeg", "todataurlpng", "todataurlwebp"],
- "tags": ["canvas"],
- "builderAliases": ["canvas_todataurl_type"],
- "async" : false,
- "notes": [{
- "name": "MDN article",
- "href": "https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement.toDataURL"
- }]
- }
- !*/
- var canvas = createElement('canvas');
- Modernizr.addTest('todataurljpeg', function() {
- return !!Modernizr.canvas && canvas.toDataURL('image/jpeg').indexOf('data:image/jpeg') === 0;
- });
- Modernizr.addTest('todataurlpng', function() {
- return !!Modernizr.canvas && canvas.toDataURL('image/png').indexOf('data:image/png') === 0;
- });
- Modernizr.addTest('todataurlwebp', function() {
- var supports = false;
- // firefox 3 throws an error when you use an "invalid" toDataUrl
- try {
- supports = !!Modernizr.canvas && canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0;
- } catch (e) {}
- return supports;
- });
- /*!
- {
- "name": "Track element and Timed Text Track",
- "property": ["texttrackapi", "track"],
- "tags": ["elem"],
- "builderAliases": ["elem_track"],
- "authors": ["Addy Osmani"],
- "notes": [{
- "name": "W3 track Element Spec",
- "href": "http://www.w3.org/TR/html5/video.html#the-track-element"
- },{
- "name": "W3 track API Spec",
- "href": "http://www.w3.org/TR/html5/media-elements.html#text-track-api"
- }],
- "warnings": ["While IE10 has implemented the track element, IE10 does not expose the underlying APIs to create timed text tracks by JS (really sad)"]
- }
- !*/
- Modernizr.addTest('texttrackapi', typeof (createElement('video').addTextTrack) === 'function');
- // a more strict test for track including UI support: document.createElement('track').kind === 'subtitles'
- Modernizr.addTest('track', 'kind' in createElement('track'));
- /**
- * cssToDOM takes a kebab-case string and converts it to camelCase
- * e.g. box-sizing -> boxSizing
- *
- * @access private
- * @function cssToDOM
- * @param {string} name - String name of kebab-case prop we want to convert
- * @returns {string} The camelCase version of the supplied name
- */
- function cssToDOM(name) {
- return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
- return m1 + m2.toUpperCase();
- }).replace(/^-/, '');
- }
- ;
- /**
- * If the browsers follow the spec, then they would expose vendor-specific styles as:
- * elem.style.WebkitBorderRadius
- * instead of something like the following (which is technically incorrect):
- * elem.style.webkitBorderRadius
- * WebKit ghosts their properties in lowercase but Opera & Moz do not.
- * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
- * erik.eae.net/archives/2008/03/10/21.48.10/
- * More here: github.com/Modernizr/Modernizr/issues/issue/21
- *
- * @access private
- * @returns {string} The string representing the vendor-specific style properties
- */
- var omPrefixes = 'Moz O ms Webkit';
-
- var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
- ModernizrProto._cssomPrefixes = cssomPrefixes;
-
- /**
- * atRule returns a given CSS property at-rule (eg @keyframes), possibly in
- * some prefixed form, or false, in the case of an unsupported rule
- *
- * @memberof Modernizr
- * @name Modernizr.atRule
- * @optionName Modernizr.atRule()
- * @optionProp atRule
- * @access public
- * @function atRule
- * @param {string} prop - String name of the @-rule to test for
- * @returns {string|boolean} The string representing the (possibly prefixed)
- * valid version of the @-rule, or `false` when it is unsupported.
- * @example
- * ```js
- * var keyframes = Modernizr.atRule('@keyframes');
- *
- * if (keyframes) {
- * // keyframes are supported
- * // could be `@-webkit-keyframes` or `@keyframes`
- * } else {
- * // keyframes === `false`
- * }
- * ```
- *
- */
- var atRule = function(prop) {
- var length = prefixes.length;
- var cssrule = window.CSSRule;
- var rule;
- if (typeof cssrule === 'undefined') {
- return undefined;
- }
- if (!prop) {
- return false;
- }
- // remove literal @ from beginning of provided property
- prop = prop.replace(/^@/, '');
- // CSSRules use underscores instead of dashes
- rule = prop.replace(/-/g, '_').toUpperCase() + '_RULE';
- if (rule in cssrule) {
- return '@' + prop;
- }
- for (var i = 0; i < length; i++) {
- // prefixes gives us something like -o-, and we want O_
- var prefix = prefixes[i];
- var thisRule = prefix.toUpperCase() + '_' + rule;
- if (thisRule in cssrule) {
- return '@-' + prefix.toLowerCase() + '-' + prop;
- }
- }
- return false;
- };
- ModernizrProto.atRule = atRule;
-
- /**
- * List of JavaScript DOM values used for tests
- *
- * @memberof Modernizr
- * @name Modernizr._domPrefixes
- * @optionName Modernizr._domPrefixes
- * @optionProp domPrefixes
- * @access public
- * @example
- *
- * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
- * than kebab-case properties, all properties are their Capitalized variant
- *
- * ```js
- * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
- * ```
- */
- var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
- ModernizrProto._domPrefixes = domPrefixes;
-
- /**
- * contains checks to see if a string contains another string
- *
- * @access private
- * @function contains
- * @param {string} str - The string we want to check for substrings
- * @param {string} substr - The substring we want to search the first string for
- * @returns {boolean}
- */
- function contains(str, substr) {
- return !!~('' + str).indexOf(substr);
- }
- ;
- /**
- * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
- *
- * @access private
- * @function fnBind
- * @param {function} fn - a function you want to change `this` reference to
- * @param {object} that - the `this` you want to call the function with
- * @returns {function} The wrapped version of the supplied function
- */
- function fnBind(fn, that) {
- return function() {
- return fn.apply(that, arguments);
- };
- }
- ;
- /**
- * testDOMProps is a generic DOM property test; if a browser supports
- * a certain property, it won't return undefined for it.
- *
- * @access private
- * @function testDOMProps
- * @param {array.<string>} props - An array of properties to test for
- * @param {object} obj - An object or Element you want to use to test the parameters again
- * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
- * @returns {false|*} returns false if the prop is unsupported, otherwise the value that is supported
- */
- function testDOMProps(props, obj, elem) {
- var item;
- for (var i in props) {
- if (props[i] in obj) {
- // return the property name as a string
- if (elem === false) {
- return props[i];
- }
- item = obj[props[i]];
- // let's bind a function
- if (is(item, 'function')) {
- // bind to obj unless overriden
- return fnBind(item, elem || obj);
- }
- // return the unbound function or obj or value
- return item;
- }
- }
- return false;
- }
- ;
- /**
- * Create our "modernizr" element that we do most feature tests on.
- *
- * @access private
- */
- var modElem = {
- elem: createElement('modernizr')
- };
- // Clean up this element
- Modernizr._q.push(function() {
- delete modElem.elem;
- });
-
- var mStyle = {
- style: modElem.elem.style
- };
- // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
- // the front of the queue.
- Modernizr._q.unshift(function() {
- delete mStyle.style;
- });
-
- /**
- * domToCSS takes a camelCase string and converts it to kebab-case
- * e.g. boxSizing -> box-sizing
- *
- * @access private
- * @function domToCSS
- * @param {string} name - String name of camelCase prop we want to convert
- * @returns {string} The kebab-case version of the supplied name
- */
- function domToCSS(name) {
- return name.replace(/([A-Z])/g, function(str, m1) {
- return '-' + m1.toLowerCase();
- }).replace(/^ms-/, '-ms-');
- }
- ;
- /**
- * wrapper around getComputedStyle, to fix issues with Firefox returning null when
- * called inside of a hidden iframe
- *
- * @access private
- * @function computedStyle
- * @param {HTMLElement|SVGElement} - The element we want to find the computed styles of
- * @param {string|null} [pseudoSelector]- An optional pseudo element selector (e.g. :before), of null if none
- * @returns {CSSStyleDeclaration}
- */
- function computedStyle(elem, pseudo, prop) {
- var result;
- if ('getComputedStyle' in window) {
- result = getComputedStyle.call(window, elem, pseudo);
- var console = window.console;
- if (result !== null) {
- if (prop) {
- result = result.getPropertyValue(prop);
- }
- } else {
- if (console) {
- var method = console.error ? 'error' : 'log';
- console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');
- }
- }
- } else {
- result = !pseudo && elem.currentStyle && elem.currentStyle[prop];
- }
- return result;
- }
- ;
- /**
- * 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;
- }
- ;
- /**
- * nativeTestProps allows for us to use native feature detection functionality if available.
- * some prefixed form, or false, in the case of an unsupported rule
- *
- * @access private
- * @function nativeTestProps
- * @param {array} props - An array of property names
- * @param {string} value - A string representing the value we want to check via @supports
- * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
- */
- // Accepts a list of property names and a single value
- // Returns `undefined` if native detection not available
- function nativeTestProps(props, value) {
- var i = props.length;
- // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
- if ('CSS' in window && 'supports' in window.CSS) {
- // Try every prefixed variant of the property
- while (i--) {
- if (window.CSS.supports(domToCSS(props[i]), value)) {
- return true;
- }
- }
- return false;
- }
- // Otherwise fall back to at-rule (for Opera 12.x)
- else if ('CSSSupportsRule' in window) {
- // Build a condition string for every prefixed variant
- var conditionText = [];
- while (i--) {
- conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
- }
- conditionText = conditionText.join(' or ');
- return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
- return computedStyle(node, null, 'position') == 'absolute';
- });
- }
- return undefined;
- }
- ;
- // testProps is a generic CSS / DOM property test.
- // In testing support for a given CSS property, it's legit to test:
- // `elem.style[styleName] !== undefined`
- // If the property is supported it will return an empty string,
- // if unsupported it will return undefined.
- // We'll take advantage of this quick test and skip setting a style
- // on our modernizr element, but instead just testing undefined vs
- // empty string.
- // Property names can be provided in either camelCase or kebab-case.
- function testProps(props, prefixed, value, skipValueTest) {
- skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
- // Try native detect first
- if (!is(value, 'undefined')) {
- var result = nativeTestProps(props, value);
- if (!is(result, 'undefined')) {
- return result;
- }
- }
- // Otherwise do it properly
- var afterInit, i, propsLength, prop, before;
- // If we don't have a style element, that means we're running async or after
- // the core tests, so we'll need to create our own elements to use
- // inside of an SVG element, in certain browsers, the `style` element is only
- // defined for valid tags. Therefore, if `modernizr` does not have one, we
- // fall back to a less used element and hope for the best.
- // for strict XHTML browsers the hardly used samp element is used
- var elems = ['modernizr', 'tspan', 'samp'];
- while (!mStyle.style && elems.length) {
- afterInit = true;
- mStyle.modElem = createElement(elems.shift());
- mStyle.style = mStyle.modElem.style;
- }
- // Delete the objects if we created them.
- function cleanElems() {
- if (afterInit) {
- delete mStyle.style;
- delete mStyle.modElem;
- }
- }
- propsLength = props.length;
- for (i = 0; i < propsLength; i++) {
- prop = props[i];
- before = mStyle.style[prop];
- if (contains(prop, '-')) {
- prop = cssToDOM(prop);
- }
- if (mStyle.style[prop] !== undefined) {
- // If value to test has been passed in, do a set-and-check test.
- // 0 (integer) is a valid property value, so check that `value` isn't
- // undefined, rather than just checking it's truthy.
- if (!skipValueTest && !is(value, 'undefined')) {
- // Needs a try catch block because of old IE. This is slow, but will
- // be avoided in most cases because `skipValueTest` will be used.
- try {
- mStyle.style[prop] = value;
- } catch (e) {}
- // If the property value has changed, we assume the value used is
- // supported. If `value` is empty string, it'll fail here (because
- // it hasn't changed), which matches how browsers have implemented
- // CSS.supports()
- if (mStyle.style[prop] != before) {
- cleanElems();
- return prefixed == 'pfx' ? prop : true;
- }
- }
- // Otherwise just return true, or the property name if this is a
- // `prefixed()` call
- else {
- cleanElems();
- return prefixed == 'pfx' ? prop : true;
- }
- }
- }
- cleanElems();
- return false;
- }
- ;
- /**
- * testPropsAll tests a list of DOM properties we want to check against.
- * We specify literally ALL possible (known and/or likely) properties on
- * the element including the non-vendor prefixed one, for forward-
- * compatibility.
- *
- * @access private
- * @function testPropsAll
- * @param {string} prop - A string of the property to test for
- * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
- * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
- * @param {string} [value] - A string of a css value
- * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
- * @returns {false|string} returns the string version of the property, or false if it is unsupported
- */
- function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
- var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
- props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
- // did they call .prefixed('boxSizing') or are we just testing a prop?
- if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
- return testProps(props, prefixed, value, skipValueTest);
- // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
- } else {
- props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
- return testDOMProps(props, prefixed, elem);
- }
- }
- // Modernizr.testAllProps() investigates whether a given style property,
- // or any of its vendor-prefixed variants, is recognized
- //
- // Note that the property names must be provided in the camelCase variant.
- // Modernizr.testAllProps('boxSizing')
- ModernizrProto.testAllProps = testPropsAll;
-
- /**
- * prefixed returns the prefixed or nonprefixed property name variant of your input
- *
- * @memberof Modernizr
- * @name Modernizr.prefixed
- * @optionName Modernizr.prefixed()
- * @optionProp prefixed
- * @access public
- * @function prefixed
- * @param {string} prop - String name of the property to test for
- * @param {object} [obj] - An object to test for the prefixed properties on
- * @param {HTMLElement} [elem] - An element used to test specific properties against
- * @returns {string|false} The string representing the (possibly prefixed) valid
- * version of the property, or `false` when it is unsupported.
- * @example
- *
- * Modernizr.prefixed takes a string css value in the DOM style camelCase (as
- * opposed to the css style kebab-case) form and returns the (possibly prefixed)
- * version of that property that the browser actually supports.
- *
- * For example, in older Firefox...
- * ```js
- * prefixed('boxSizing')
- * ```
- * returns 'MozBoxSizing'
- *
- * In newer Firefox, as well as any other browser that support the unprefixed
- * version would simply return `boxSizing`. Any browser that does not support
- * the property at all, it will return `false`.
- *
- * By default, prefixed is checked against a DOM element. If you want to check
- * for a property on another object, just pass it as a second argument
- *
- * ```js
- * var rAF = prefixed('requestAnimationFrame', window);
- *
- * raf(function() {
- * renderFunction();
- * })
- * ```
- *
- * Note that this will return _the actual function_ - not the name of the function.
- * If you need the actual name of the property, pass in `false` as a third argument
- *
- * ```js
- * var rAFProp = prefixed('requestAnimationFrame', window, false);
- *
- * rafProp === 'WebkitRequestAnimationFrame' // in older webkit
- * ```
- *
- * One common use case for prefixed is if you're trying to determine which transition
- * end event to bind to, you might do something like...
- * ```js
- * var transEndEventNames = {
- * 'WebkitTransition' : 'webkitTransitionEnd', * Saf 6, Android Browser
- * 'MozTransition' : 'transitionend', * only for FF < 15
- * 'transition' : 'transitionend' * IE10, Opera, Chrome, FF 15+, Saf 7+
- * };
- *
- * var transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
- * ```
- *
- * If you want a similar lookup, but in kebab-case, you can use [prefixedCSS](#modernizr-prefixedcss).
- */
- var prefixed = ModernizrProto.prefixed = function(prop, obj, elem) {
- if (prop.indexOf('@') === 0) {
- return atRule(prop);
- }
- if (prop.indexOf('-') != -1) {
- // Convert kebab-case to camelCase
- prop = cssToDOM(prop);
- }
- if (!obj) {
- return testPropsAll(prop, 'pfx');
- } else {
- // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
- return testPropsAll(prop, obj, elem);
- }
- };
-
- /*!
- {
- "name": "Fullscreen API",
- "property": "fullscreen",
- "caniuse": "fullscreen",
- "notes": [{
- "name": "MDN documentation",
- "href": "https://developer.mozilla.org/en/API/Fullscreen"
- }],
- "polyfills": ["screenfulljs"],
- "builderAliases": ["fullscreen_api"]
- }
- !*/
- /* DOC
- Detects support for the ability to make the current website take over the user's entire screen
- */
- // github.com/Modernizr/Modernizr/issues/739
- Modernizr.addTest('fullscreen', !!(prefixed('exitFullscreen', document, false) || prefixed('cancelFullScreen', document, false)));
- /**
- * testAllProps determines whether a given CSS property is supported in the browser
- *
- * @memberof Modernizr
- * @name Modernizr.testAllProps
- * @optionName Modernizr.testAllProps()
- * @optionProp testAllProps
- * @access public
- * @function testAllProps
- * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
- * @param {string} [value] - String of the value to test
- * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
- * @example
- *
- * testAllProps determines whether a given CSS property, in some prefixed form,
- * is supported by the browser.
- *
- * ```js
- * testAllProps('boxSizing') // true
- * ```
- *
- * It can optionally be given a CSS value in string form to test if a property
- * value is valid
- *
- * ```js
- * testAllProps('display', 'block') // true
- * testAllProps('display', 'penguin') // false
- * ```
- *
- * A boolean can be passed as a third parameter to skip the value check when
- * native detection (@supports) isn't available.
- *
- * ```js
- * testAllProps('shapeOutside', 'content-box', true);
- * ```
- */
- function testAllProps(prop, value, skipValueTest) {
- return testPropsAll(prop, undefined, undefined, value, skipValueTest);
- }
- ModernizrProto.testAllProps = testAllProps;
-
- /*!
- {
- "name": "CSS Animations",
- "property": "cssanimations",
- "caniuse": "css-animation",
- "polyfills": ["transformie", "csssandpaper"],
- "tags": ["css"],
- "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
- "notes": [{
- "name" : "Article: 'Dispelling the Android CSS animation myths'",
- "href": "https://goo.gl/OGw5Gm"
- }]
- }
- !*/
- /* DOC
- Detects whether or not elements can be animated using CSS
- */
- Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
- /*!
- {
- "name": "CSS Transforms",
- "property": "csstransforms",
- "caniuse": "transforms2d",
- "tags": ["css"]
- }
- !*/
- Modernizr.addTest('csstransforms', function() {
- // Android < 3.0 is buggy, so we sniff and blacklist
- // http://git.io/hHzL7w
- return navigator.userAgent.indexOf('Android 2.') === -1 &&
- testAllProps('transform', 'scale(1)', true);
- });
- // 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);
|