diff options
author | Alex Xu <alex_y_xu@yahoo.ca> | 2013-11-24 12:35:19 -0500 |
---|---|---|
committer | Alex Xu <alex_y_xu@yahoo.ca> | 2013-11-24 12:35:19 -0500 |
commit | fb3d7df90cbfa8ed6e6fcde64404907b62928c0c (patch) | |
tree | 08257f295cedceed5cd38e43a8defe24541a8c32 /www | |
parent | 4c9c091f7b5240b8c665cc35d634bd45815ab66b (diff) | |
download | html5ks-fb3d7df90cbfa8ed6e6fcde64404907b62928c0c.tar.xz html5ks-fb3d7df90cbfa8ed6e6fcde64404907b62928c0c.zip |
Stuff.
Diffstat (limited to 'www')
-rw-r--r-- | www/css/index.css | 16 | ||||
-rw-r--r-- | www/index.html | 2 | ||||
-rw-r--r-- | www/js/api.js | 134 | ||||
-rw-r--r-- | www/js/html5ks.js | 6 | ||||
-rw-r--r-- | www/js/lib/modernizr-build.js | 6732 | ||||
-rw-r--r-- | www/js/lib/modernizr-build.min.js | 4 |
6 files changed, 6819 insertions, 75 deletions
diff --git a/www/css/index.css b/www/css/index.css index ffd2f9f..1f147a7 100644 --- a/www/css/index.css +++ b/www/css/index.css @@ -34,11 +34,12 @@ body { width: 100%; } h2 { - font: 20px/24px Playtime; /* yes, h2 has *smaller* font */ + font-size: 20px + line-height: 24px; /* yes, h2 has *smaller* font */ font-weight: bold; } -/* warnings */ +/* interstitial */ #interstitial { visibility: hidden; cursor: auto; @@ -53,7 +54,6 @@ html.no-js #interstitial { height: 70%; left: 50%; margin-left: -300px; - overflow: auto; padding: 10px; position: absolute; top: 10%; @@ -65,7 +65,7 @@ html.js #warn li#js { display: none; } #warn li#ie { display: none; } html.video #warn li#video { display: none; } html.audio #warn li#audio { display: none; } - #warn li#opus{ display: none; } + #warn li#opus { display: none; } html.fontface #warn li#fontface { display: none; } html.csstransforms #warn li#csstransforms { display: none; } html.csstransitions #warn li#csstransitions { display: none; } @@ -80,9 +80,6 @@ html.no-js #gotit { #container, #vid { cursor: url("../dump/ui/mousecursor.png"), default; position: absolute; - -moz-backface-visibility: hidden; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; } #container, #vid { top: 50%; @@ -109,7 +106,7 @@ html.no-js #gotit { z-index: 50; width: 504px; height: 395px; - background: url(../dump/ui/bg-config.png); + background: url("../dump/ui/bg-config.png"); margin-left: -252px; margin-top: -197.5px; } @@ -244,7 +241,8 @@ html.no-js #gotit { position: absolute; bottom: 10px; right: 15px; - font: 8px/8px Playtime; + font-size: 8px; + line-height: 8px; opacity: 0.4; } diff --git a/www/index.html b/www/index.html index c5066f6..d38ae13 100644 --- a/www/index.html +++ b/www/index.html @@ -17,7 +17,7 @@ <link rel="stylesheet" type="text/css" href="css/anim.css"> <link rel="stylesheet" type="text/css" href="css/index.css"> <script src="js/lib/when/when.js"></script> - <script src="js/lib/modernizr-build.min.js"></script> + <script src="js/lib/modernizr-build.js"></script> <script src="js/html5ks.js"></script> <script src="js/menu.js"></script> <script src="js/api.js"></script> diff --git a/www/js/api.js b/www/js/api.js index 799d917..4aa6f5f 100644 --- a/www/js/api.js +++ b/www/js/api.js @@ -1,6 +1,8 @@ "use strict"; window.html5ks.api = { init: function () { + + // tag character names var chars = html5ks.data.characters; for (var ch in chars) { var chr = chars[ch]; @@ -8,26 +10,34 @@ window.html5ks.api = { chr.name = this.tag(chr.name); } } + }, iscene: function (target, is_h, is_end) { - html5ks.state.status = "scene"; - var deferred = when.defer(), - label = html5ks.data.script[html5ks.persistent.language + "_" + target], - i = 0; + + // TODO: implement timeskip if (target === "timeskip") { deferred.resolve(); return deferred.promise; } - (function run(ret) { + + html5ks.state.status = "scene"; + + var deferred = when.defer(), + label = html5ks.data.script[html5ks.persistent.language + "_" + target], + i = 0; + + var run = function (ret) { if (label[i]) { - html5ks.api.runInst(label[i]).then(run, console.error); - i++; + this.runInst(label[i++]).then(run, console.error); } else { deferred.resolve(ret); } - }()); + }.bind(this); + + run(); + return deferred.promise; }, @@ -46,32 +56,30 @@ window.html5ks.api = { return this.character(cmd, args[0]); } else { console.error("no such cmd " + cmd); - var deferred = when.defer(); - deferred.resolve(); - return deferred.promise; + return when.defer().resolve(); } } }, - _fading: {}, + _fades: {}, set_volume: function (target, delay, channel) { var deferred = when.defer(), - audio = html5ks.elements.audio[channel], - step = (target - audio.volume) / (delay * 20); + audioElement = html5ks.elements.audio[channel], + step = (target - audioElement.volume) / (delay * 20); if (!delay) { - audio.volume = target; + audioElement.volume = target; } else { - this._fading[channel] = setInterval(function () { + if (this._fades[channel]) clearInterval(this._fades[channel]); + this._fades[channel] = setInterval(function () { // clamp new volume 0-1 - audio.volume = Math.min(Math.max(audio.volume + step, 0), 1); - if (audio.volume === 0 || audio.volume === 1) { - clearInterval(this._fading); + audioElement.volume = Math.min(Math.max(audioElement.volume + step, 0), 1); + if (audioElement.volume === 0 || audioElement.volume === 1) { + clearInterval(this._fades[channel]); } }.bind(this), 50); } - deferred.resolve(); - return deferred.promise; + return deferred.resolve(); }, play: function (channel, name, ignore, fade) { @@ -94,17 +102,12 @@ window.html5ks.api = { src += "sfx/" + html5ks.data.sfx[name]; } - if (Modernizr.audio.opus) { - audio.src = src + ".opus"; - } else if (Modernizr.audio.ogg) { - audio.src = src + ".ogg"; - } else if (Modernizr.audio.m4a) { - audio.src = src + ".m4a"; - } else if (Modernizr.audio.wav) { - audio.src = src + ".wav"; - } else { - console.error("wtf, no audio formats"); - } + ["opus", "ogg", "m4a", "wav"].some(function (type) { + if (Modernizr.audio[type]) { + audio.src = src + "." + type; + return true; + } + }); audio.load(); var volume = html5ks.persistent[channel + "Volume"]; @@ -125,15 +128,19 @@ window.html5ks.api = { stop: function (channel, ignore, fade) { if (channel === "all") { - this.stop("music", ignore, fade); - this.stop("sound", ignore, fade); - return this.stop("ambient", ignore, fade); + return ["music", "sound", "ambient"].forEach(function (channel) { + this.stop(channel, ignore, fade); + }.bind(this)); } + var deferred = when.defer(), audio = html5ks.elements.audio[channel]; - if (this._fading[channel]) { - clearInterval(this._fading[channel]); + + // clear fade + if (this._fades[channel]) { + clearInterval(this._fades[channel]); } + if (fade) { this.set_volume(0, fade, channel); } else { @@ -146,27 +153,31 @@ window.html5ks.api = { movie_cutscene: function (vid_src, skippable) { var deferred = when.defer(), - video = html5ks.elements.video, - src = "dump/video/" + vid_src + "."; + video = html5ks.elements.video; this.stop("all"); this.speed("auto", false); this.speed("skip", false); - if (Modernizr.video.webm) { - video.src = src + "webm"; - } else if (Modernizr.video.ogg) { - video.src = src + "ogv"; - } else if (Modernizr.video.h264) { - video.src = src + "mp4"; - } else { - console.error("wtf is this, no video formats"); + var types = { + webm: "webm", + ogg: "ogv", + h264: "mp4" + }; + for (var type in types) { + if (Modernizr.video[type]) { + video.src = "dump/video/" + vid_src + "." + types[type]; + break; + } } - video.load(); - video.style.display = "block"; - video.volume = html5ks.persistent.musicVolume; - video.play(); + video.oncanplaythrough = function () { + video.volume = html5ks.persistent.musicVolume; + video.style.display = "block"; + video.play(); + video.onended = done; + }; + var done = function () { video.style.display = "none"; video.pause(); @@ -184,10 +195,13 @@ window.html5ks.api = { done(); } }; - video.onended = done; + video.onerror = function () { deferred.reject(this.error); }; + + video.load(); + return deferred.promise; }, @@ -198,20 +212,18 @@ window.html5ks.api = { window: function (action, transition) { - var windw = html5ks.elements.window, - deferred = when.defer(); + var windowEl = html5ks.elements.window; switch (action) { case "show": - windw.style.display = "block"; + windowEl.style.display = "block"; break; case "hide": - windw.style.display = "none"; + windowEl.style.display = "none"; break; default: - return windw.style.display !== "none"; + return windowEl.style.display !== "none"; } - deferred.resolve(action); - return deferred.promise; + return when.defer().resolve(action); }, @@ -310,6 +322,7 @@ window.html5ks.api = { } return deferred.promise; }, + hide: function (name) { var deferred = when.defer(); var show = html5ks.elements.show.children; @@ -322,6 +335,7 @@ window.html5ks.api = { } }, + tag: function (str) { var tags = [ /&/g, "&", @@ -472,7 +486,7 @@ window.html5ks.api = { return deferred.promise; }, - menu: function () { + menu: function (choices) { var args = Array.prototype.slice.call(arguments, 0); var deferred = when.defer(); var menu = html5ks.elements.choices, diff --git a/www/js/html5ks.js b/www/js/html5ks.js index 89b978d..7a1f91c 100644 --- a/www/js/html5ks.js +++ b/www/js/html5ks.js @@ -10,7 +10,7 @@ window.html5ks = { hdisable: false, skipUnread: false, skipAfterChoices: false, - useWebP: false, + useWebP: null, fullscreen: false, scaleAll: true, scaleVideo: true, @@ -22,7 +22,6 @@ window.html5ks = { language: "en" }; var loaded = localStorage.persistent ? JSON.parse(localStorage.persistent) : {}; - html5ks.state._loaded = typeof loaded.version !== undefined; var defProp = function (v) { Object.defineProperty(html5ks.persistent, k, { get: function () { @@ -43,7 +42,7 @@ window.html5ks = { html5ks.onload(); }, false); - if (html5ks.state._loaded) { + if (html5ks.persistent.useWebP === null) { var img = new Image(); img.onload = function () { html5ks.persistent.useWebP = img.width === 4; @@ -196,6 +195,7 @@ window.html5ks = { document.getElementById("opus").style.display = "block"; } for (var i = 0; i < warns.length; i++) { + var warn = warns[i]; if (window.getComputedStyle(warns[i]).getPropertyValue("display") !== "none") { warn.style.visibility = "visible"; return true; diff --git a/www/js/lib/modernizr-build.js b/www/js/lib/modernizr-build.js new file mode 100644 index 0000000..a719e2a --- /dev/null +++ b/www/js/lib/modernizr-build.js @@ -0,0 +1,6732 @@ +/*! + * Modernizr v3.0.0pre + * modernizr.com + * + * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton, Ryan Seddon, Alexander Farkas, Ben Alman, Stu Cox + * 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. + * + * Modernizr has an optional (*not included*) conditional resource loader called + * `Modernizr.load()`, based on [Yepnope.js](http://yepnopejs.com). You can get a + * build that includes `Modernizr.load()`, as well as choosing which feature tests + * to include on the [Download page](http://www.modernizr.com/download/). + */ +;(function(window, document, undefined){ + + var tests = []; + + + var ModernizrProto = { + // The current version, dummy + _version: 'v3.0.0pre', + + // Any settings that don't work as separate modules + // can go in here as configuration. + _config: { + classPrefix : '', + enableClasses : 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. + setTimeout(function() { + cb(this[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 for if typeof obj is exactly type. + */ + function is( obj, type ) { + return typeof obj === type; + } + ; + + // Run through all tests and detect their support in the current UA. + function testRunner() { + var featureNames; + var feature; + var aliasIdx; + var result; + var nameIdx; + var featureName; + var featureNameSplit; + var modernizrProp; + var mPropCount; + + for ( var featureIdx in tests ) { + 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 if (featureNameSplit.length === 2) { + Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result; + } + + classes.push((result ? '' : 'no-') + featureNameSplit.join('-')); + } + } + } + + ; + + var docElement = document.documentElement; + + + // Pass in an and array of class names, e.g.: + // ['no-webp', 'borderradius', ...] + function setClasses( classes ) { + var className = docElement.className; + var removeClasses = []; + var regex; + var classPrefix = Modernizr._config.classPrefix || ''; + + // Change `no-js` to `js` (we do this regardles of the `enableClasses` + // option) + // Handle classPrefix on this too + var reJS = new RegExp('(^|\\s)'+classPrefix+'no-js(\\s|$)'); + className = className.replace(reJS, '$1'+classPrefix+'js$2'); + + if(Modernizr._config.enableClasses) { + // Need to remove any existing `no-*` classes for features we've detected + for(var i = 0; i < classes.length; i++) { + if(!classes[i].match('^no-')) { + removeClasses.push('no-' + classes[i]); + } + } + + // Use a regex to remove the old... + regex = new RegExp('(^|\\s)' + removeClasses.join('|') + '(\\s|$)', 'g'); + className = className.replace(regex, '$1$2'); + + // Then add the new... + className += ' ' + classPrefix + classes.join(' ' + classPrefix); + + // Apply + docElement.className = className; + } + + } + + ; + + // hasOwnProperty shim by kangax needed for Safari 2.0 support + var hasOwnProp; + + (function() { + var _hasOwnProperty = ({}).hasOwnProperty; + if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { + hasOwnProp = function (object, property) { + return _hasOwnProperty.call(object, property); + }; + } + else { + hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ + return ((property in object) && is(object.constructor.prototype[property], 'undefined')); + }; + } + })(); + + + + // As far as I can think of, we shouldn't need or + // allow 'on' for non-async tests, and you can't do + // async tests without this 'addTest' module. + + // Listeners for async or post-run tests + ModernizrProto._l = {}; + + // 'addTest' implies a test after the core runloop, + // So we'll add in the events + ModernizrProto.on = function( test, cb ) { + // Create the list of listeners if it doesn't exist + if (!this._l[test]) { + this._l[test] = []; + } + + // Push this test on to the listener list + this._l[test].push(cb); + + // If it's already been resolved, trigger it on next tick + if (Modernizr.hasOwnProperty(test)) { + // Next Tick + setTimeout(function() { + Modernizr._trigger(test, Modernizr[test]); + }, 0); + } + }; + + ModernizrProto._trigger = function( test, res ) { + if (!this._l[test]) { + return; + } + + var cbs = this._l[test]; + + // Force async + setTimeout(function() { + var i, cb; + for (i = 0; i < cbs.length; i++) { + cb = cbs[i]; + cb(res); + } + },0); + + // Don't trigger these again + delete this._l[test]; + }; + + /** + * addTest allows the user to define their own feature tests + * the result will be added onto the Modernizr object, + * as well as an appropriate className set on the html element + * + * @param feature - String naming the feature + * @param test - Function returning true if feature is supported, false if not + */ + function addTest( feature, test ) { + if ( typeof feature == 'object' ) { + for ( var key in feature ) { + if ( hasOwnProp( feature, key ) ) { + addTest( key, feature[ key ] ); + } + } + } else { + + feature = feature.toLowerCase(); + var featureSplit = feature.split('.'); + var last = Modernizr[featureSplit[0]]; + + // Again, we don't check for parent test existence. Get that right, though. + if (featureSplit.length == 2) { + last = last[featureSplit[1]]; + } + + if ( typeof last != 'undefined' ) { + // we're going to quit if you're trying to overwrite an existing test + // if we were to allow it, we'd do this: + // var re = new RegExp("\\b(no-)?" + feature + "\\b"); + // docElement.className = docElement.className.replace( re, '' ); + // but, no rly, stuff 'em. + return Modernizr; + } + + test = typeof test == 'function' ? test() : test; + + // Set the value (this is the magic, right here). + if (featureSplit.length == 1) { + Modernizr[featureSplit[0]] = test; + } + else if (featureSplit.length == 2) { + Modernizr[featureSplit[0]][featureSplit[1]] = test; + } + + // Set a single class (either `feature` or `no-feature`) + setClasses([(test ? '' : 'no-') + featureSplit.join('-')]); + + // Trigger the event + Modernizr._trigger(feature, test); + } + + return Modernizr; // allow chaining. + } + + // After all the tests are run, add self + // to the Modernizr prototype + Modernizr._q.push(function() { + ModernizrProto.addTest = addTest; + }); + + + + // Take the html5 variable out of the + // html5shiv scope so we can return it. + var html5; + + /** + * @preserve HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed + */ + ;(function(window, document) { + /*jshint evil:true */ + /** version */ + var version = '3.6.2'; + + /** Preset options */ + var options = window.html5 || {}; + + /** Used to skip problem elements */ + var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; + + /** Not all elements can be cloned in IE **/ + 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; + + /** Detect whether the browser supports default html5 styles */ + var supportsHtml5Styles; + + /** Name of the expando, to work with multiple documents or to re-shiv one document */ + var expando = '_html5shiv'; + + /** The id for the the documents expando */ + var expanID = 0; + + /** Cached data for each document */ + var expandoData = {}; + + /** Detect whether the browser supports unknown elements */ + var supportsUnknownElements; + + (function() { + try { + var a = document.createElement('a'); + a.innerHTML = '<xyz></xyz>'; + //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles + supportsHtml5Styles = ('hidden' in a); + + supportsUnknownElements = a.childNodes.length == 1 || (function() { + // assign a false positive if unable to shiv + (document.createElement)('a'); + var frag = document.createDocumentFragment(); + return ( + typeof frag.cloneNode == 'undefined' || + typeof frag.createDocumentFragment == 'undefined' || + typeof frag.createElement == 'undefined' + ); + }()); + } catch(e) { + // assign a false positive if detection fails => unable to shiv + supportsHtml5Styles = true; + supportsUnknownElements = true; + } + + }()); + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a style sheet with the given CSS text and adds it to the document. + * @private + * @param {Document} ownerDocument The document. + * @param {String} cssText The CSS text. + * @returns {StyleSheet} The style element. + */ + function addStyleSheet(ownerDocument, cssText) { + var p = ownerDocument.createElement('p'), + parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; + + p.innerHTML = 'x<style>' + cssText + '</style>'; + return parent.insertBefore(p.lastChild, parent.firstChild); + } + + /** + * Returns the value of `html5.elements` as an array. + * @private + * @returns {Array} An array of shived element node names. + */ + function getElements() { + var elements = html5.elements; + return typeof elements == 'string' ? elements.split(' ') : elements; + } + + /** + * Returns the data associated to the given document + * @private + * @param {Document} ownerDocument The document. + * @returns {Object} An object of data. + */ + function getExpandoData(ownerDocument) { + var data = expandoData[ownerDocument[expando]]; + if (!data) { + data = {}; + expanID++; + ownerDocument[expando] = expanID; + expandoData[expanID] = data; + } + return data; + } + + /** + * returns a shived element for the given nodeName and document + * @memberOf html5 + * @param {String} nodeName name of the element + * @param {Document} ownerDocument The context document. + * @returns {Object} The shived element. + */ + function createElement(nodeName, ownerDocument, data){ + if (!ownerDocument) { + ownerDocument = document; + } + if(supportsUnknownElements){ + return ownerDocument.createElement(nodeName); + } + if (!data) { + data = getExpandoData(ownerDocument); + } + var node; + + if (data.cache[nodeName]) { + node = data.cache[nodeName].cloneNode(); + } else if (saveClones.test(nodeName)) { + node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); + } else { + node = data.createElem(nodeName); + } + + // Avoid adding some elements to fragments in IE < 9 because + // * Attributes like `name` or `type` cannot be set/changed once an element + // is inserted into a document/fragment + // * Link elements with `src` attributes that are inaccessible, as with + // a 403 response, will cause the tab/window to crash + // * Script elements appended to fragments will execute when their `src` + // or `text` property is set + return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node; + } + + /** + * returns a shived DocumentFragment for the given document + * @memberOf html5 + * @param {Document} ownerDocument The context document. + * @returns {Object} The shived DocumentFragment. + */ + function createDocumentFragment(ownerDocument, data){ + if (!ownerDocument) { + ownerDocument = document; + } + if(supportsUnknownElements){ + return ownerDocument.createDocumentFragment(); + } + data = data || getExpandoData(ownerDocument); + var clone = data.frag.cloneNode(), + i = 0, + elems = getElements(), + l = elems.length; + for(;i<l;i++){ + clone.createElement(elems[i]); + } + return clone; + } + + /** + * Shivs the `createElement` and `createDocumentFragment` methods of the document. + * @private + * @param {Document|DocumentFragment} ownerDocument The document. + * @param {Object} data of the document. + */ + function shivMethods(ownerDocument, data) { + if (!data.cache) { + data.cache = {}; + data.createElem = ownerDocument.createElement; + data.createFrag = ownerDocument.createDocumentFragment; + data.frag = data.createFrag(); + } + + + ownerDocument.createElement = function(nodeName) { + //abort shiv + if (!html5.shivMethods) { + return data.createElem(nodeName); + } + return createElement(nodeName, ownerDocument, data); + }; + + ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + + 'var n=f.cloneNode(),c=n.createElement;' + + 'h.shivMethods&&(' + + // unroll the `createElement` calls + getElements().join().replace(/\w+/g, function(nodeName) { + data.createElem(nodeName); + data.frag.createElement(nodeName); + return 'c("' + nodeName + '")'; + }) + + ');return n}' + )(html5, data.frag); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Shivs the given document. + * @memberOf html5 + * @param {Document} ownerDocument The document to shiv. + * @returns {Document} The shived document. + */ + function shivDocument(ownerDocument) { + if (!ownerDocument) { + ownerDocument = document; + } + var data = getExpandoData(ownerDocument); + + if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { + data.hasCSS = !!addStyleSheet(ownerDocument, + // corrects block display not defined in IE6/7/8/9 + 'article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' + + // adds styling not present in IE6/7/8/9 + 'mark{background:#FF0;color:#000}' + ); + } + if (!supportsUnknownElements) { + shivMethods(ownerDocument, data); + } + return ownerDocument; + } + + /*--------------------------------------------------------------------------*/ + + /** + * The `html5` object is exposed so that more elements can be shived and + * existing shiving can be detected on iframes. + * @type Object + * @example + * + * // options can be changed before the script is included + * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; + */ + html5 = { + + /** + * An array or space separated string of node names of the elements to shiv. + * @memberOf html5 + * @type Array|String + */ + 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video', + + /** + * current version of html5shiv + */ + 'version': version, + + /** + * A flag to indicate that the HTML5 style sheet should be inserted. + * @memberOf html5 + * @type Boolean + */ + 'shivCSS': (options.shivCSS !== false), + + /** + * Is equal to true if a browser supports creating unknown/HTML5 elements + * @memberOf html5 + * @type boolean + */ + 'supportsUnknownElements': supportsUnknownElements, + + /** + * A flag to indicate that the document's `createElement` and `createDocumentFragment` + * methods should be overwritten. + * @memberOf html5 + * @type Boolean + */ + 'shivMethods': (options.shivMethods !== false), + + /** + * A string to describe the type of `html5` object ("default" or "default print"). + * @memberOf html5 + * @type String + */ + 'type': 'default', + + // shivs the document according to the specified `html5` object options + 'shivDocument': shivDocument, + + //creates a shived element + createElement: createElement, + + //creates a shived documentFragment + createDocumentFragment: createDocumentFragment + }; + + /*--------------------------------------------------------------------------*/ + + // expose html5 + window.html5 = html5; + + // shiv the document + shivDocument(document); + + /*------------------------------- Print Shiv -------------------------------*/ + + /** Used to filter media types */ + var reMedia = /^$|\b(?:all|print)\b/; + + /** Used to namespace printable elements */ + var shivNamespace = 'html5shiv'; + + /** Detect whether the browser supports shivable style sheets */ + var supportsShivableSheets = !supportsUnknownElements && (function() { + // assign a false negative if unable to shiv + var docEl = document.documentElement; + return !( + typeof document.namespaces == 'undefined' || + typeof document.parentWindow == 'undefined' || + typeof docEl.applyElement == 'undefined' || + typeof docEl.removeNode == 'undefined' || + typeof window.attachEvent == 'undefined' + ); + }()); + + /*--------------------------------------------------------------------------*/ + + /** + * Wraps all HTML5 elements in the given document with printable elements. + * (eg. the "header" element is wrapped with the "html5shiv:header" element) + * @private + * @param {Document} ownerDocument The document. + * @returns {Array} An array wrappers added. + */ + function addWrappers(ownerDocument) { + var node, + nodes = ownerDocument.getElementsByTagName('*'), + index = nodes.length, + reElements = RegExp('^(?:' + getElements().join('|') + ')$', 'i'), + result = []; + + while (index--) { + node = nodes[index]; + if (reElements.test(node.nodeName)) { + result.push(node.applyElement(createWrapper(node))); + } + } + return result; + } + + /** + * Creates a printable wrapper for the given element. + * @private + * @param {Element} element The element. + * @returns {Element} The wrapper. + */ + function createWrapper(element) { + var node, + nodes = element.attributes, + index = nodes.length, + wrapper = element.ownerDocument.createElement(shivNamespace + ':' + element.nodeName); + + // copy element attributes to the wrapper + while (index--) { + node = nodes[index]; + node.specified && wrapper.setAttribute(node.nodeName, node.nodeValue); + } + // copy element styles to the wrapper + wrapper.style.cssText = element.style.cssText; + return wrapper; + } + + /** + * Shivs the given CSS text. + * (eg. header{} becomes html5shiv\:header{}) + * @private + * @param {String} cssText The CSS text to shiv. + * @returns {String} The shived CSS text. + */ + function shivCssText(cssText) { + var pair, + parts = cssText.split('{'), + index = parts.length, + reElements = RegExp('(^|[\\s,>+~])(' + getElements().join('|') + ')(?=[[\\s,>+~#.:]|$)', 'gi'), + replacement = '$1' + shivNamespace + '\\:$2'; + + while (index--) { + pair = parts[index] = parts[index].split('}'); + pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement); + parts[index] = pair.join('}'); + } + return parts.join('{'); + } + + /** + * Removes the given wrappers, leaving the original elements. + * @private + * @params {Array} wrappers An array of printable wrappers. + */ + function removeWrappers(wrappers) { + var index = wrappers.length; + while (index--) { + wrappers[index].removeNode(); + } + } + + /*--------------------------------------------------------------------------*/ + + /** + * Shivs the given document for print. + * @memberOf html5 + * @param {Document} ownerDocument The document to shiv. + * @returns {Document} The shived document. + */ + function shivPrint(ownerDocument) { + var shivedSheet, + wrappers, + data = getExpandoData(ownerDocument), + namespaces = ownerDocument.namespaces, + ownerWindow = ownerDocument.parentWindow; + + if (!supportsShivableSheets || ownerDocument.printShived) { + return ownerDocument; + } + if (typeof namespaces[shivNamespace] == 'undefined') { + namespaces.add(shivNamespace); + } + + function removeSheet() { + clearTimeout(data._removeSheetTimer); + if (shivedSheet) { + shivedSheet.removeNode(true); + } + shivedSheet= null; + } + + ownerWindow.attachEvent('onbeforeprint', function() { + + removeSheet(); + + var imports, + length, + sheet, + collection = ownerDocument.styleSheets, + cssText = [], + index = collection.length, + sheets = Array(index); + + // convert styleSheets collection to an array + while (index--) { + sheets[index] = collection[index]; + } + // concat all style sheet CSS text + while ((sheet = sheets.pop())) { + // IE does not enforce a same origin policy for external style sheets... + // but has trouble with some dynamically created stylesheets + if (!sheet.disabled && reMedia.test(sheet.media)) { + + try { + imports = sheet.imports; + length = imports.length; + } catch(er){ + length = 0; + } + + for (index = 0; index < length; index++) { + sheets.push(imports[index]); + } + + try { + cssText.push(sheet.cssText); + } catch(er){} + } + } + + // wrap all HTML5 elements with printable elements and add the shived style sheet + cssText = shivCssText(cssText.reverse().join('')); + wrappers = addWrappers(ownerDocument); + shivedSheet = addStyleSheet(ownerDocument, cssText); + + }); + + ownerWindow.attachEvent('onafterprint', function() { + // remove wrappers, leaving the original elements, and remove the shived style sheet + removeWrappers(wrappers); + clearTimeout(data._removeSheetTimer); + data._removeSheetTimer = setTimeout(removeSheet, 500); + }); + + ownerDocument.printShived = true; + return ownerDocument; + } + + /*--------------------------------------------------------------------------*/ + + // expose API + html5.type += ' print'; + html5.shivPrint = shivPrint; + + // shiv for print + shivPrint(document); + + }(this, document)); + + +// yepnope.js +// Version - 1.5.4pre +// +// by +// Alex Sexton - @SlexAxton - AlexSexton[at]gmail.com +// Ralph Holzmann - @ralphholzmann - ralphholzmann[at]gmail.com +// +// http://yepnopejs.com/ +// https://github.com/SlexAxton/yepnope.js/ +// +// Tri-license - WTFPL | MIT | BSD +// +// Please minify before use. +// Also available as Modernizr.load via the Modernizr Project +// +( function ( window, doc, undef ) { + +var docElement = doc.documentElement, + sTimeout = window.setTimeout, + firstScript = doc.getElementsByTagName( "script" )[ 0 ], + toString = {}.toString, + execStack = [], + started = 0, + noop = function () {}, + // Before you get mad about browser sniffs, please read: + // https://github.com/Modernizr/Modernizr/wiki/Undetectables + // If you have a better solution, we are actively looking to solve the problem + isGecko = ( "MozAppearance" in docElement.style ), + isGeckoLTE18 = isGecko && !! doc.createRange().compareNode, + insBeforeObj = isGeckoLTE18 ? docElement : firstScript.parentNode, + // Thanks to @jdalton for showing us this opera detection (by way of @kangax) (and probably @miketaylr too, or whatever...) + isOpera = window.opera && toString.call( window.opera ) == "[object Opera]", + isIE = !! doc.attachEvent && !isOpera, + strJsElem = isGecko ? "object" : isIE ? "script" : "img", + strCssElem = isIE ? "script" : strJsElem, + isArray = Array.isArray || function ( obj ) { + return toString.call( obj ) == "[object Array]"; + }, + isObject = function ( obj ) { + return Object(obj) === obj; + }, + isString = function ( s ) { + return typeof s == "string"; + }, + isFunction = function ( fn ) { + return toString.call( fn ) == "[object Function]"; + }, + readFirstScript = function() { + if (!firstScript || !firstScript.parentNode) { + firstScript = doc.getElementsByTagName( "script" )[ 0 ]; + } + }, + globalFilters = [], + scriptCache = {}, + prefixes = { + // key value pair timeout options + timeout : function( resourceObj, prefix_parts ) { + if ( prefix_parts.length ) { + resourceObj['timeout'] = prefix_parts[ 0 ]; + } + return resourceObj; + } + }, + handler, + yepnope; + + /* Loader helper functions */ + function isFileReady ( readyState ) { + // Check to see if any of the ways a file can be ready are available as properties on the file's element + return ( ! readyState || readyState == "loaded" || readyState == "complete" || readyState == "uninitialized" ); + } + + + // Takes a preloaded js obj (changes in different browsers) and injects it into the head + // in the appropriate order + function injectJs ( src, cb, attrs, timeout, /* internal use */ err, internal ) { + + var script = doc.createElement( "script" ), + done, i; + + timeout = timeout || yepnope['errorTimeout']; + + script.src = src; + + // Add our extra attributes to the script element + for ( i in attrs ) { + script.setAttribute( i, attrs[ i ] ); + } + + cb = internal ? executeStack : ( cb || noop ); + + // Bind to load events + script.onreadystatechange = script.onload = function () { + + if ( ! done && isFileReady( script.readyState ) ) { + + // Set done to prevent this function from being called twice. + done = 1; + cb(); + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + } + }; + + // 404 Fallback + sTimeout(function () { + if ( ! done ) { + done = 1; + // Might as well pass in an error-state if we fire the 404 fallback + cb(1); + } + }, timeout ); + + // Inject script into to document + // or immediately callback if we know there + // was previously a timeout error + readFirstScript(); + err ? script.onload() : firstScript.parentNode.insertBefore( script, firstScript ); + } + + // Takes a preloaded css obj (changes in different browsers) and injects it into the head + function injectCss ( href, cb, attrs, timeout, /* Internal use */ err, internal ) { + + // Create stylesheet link + var link = doc.createElement( "link" ), + done, i; + + timeout = timeout || yepnope['errorTimeout']; + + cb = internal ? executeStack : ( cb || noop ); + + // Add attributes + link.href = href; + link.rel = "stylesheet"; + link.type = "text/css"; + + // Add our extra attributes to the link element + for ( i in attrs ) { + link.setAttribute( i, attrs[ i ] ); + } + + if ( ! err ) { + readFirstScript(); + firstScript.parentNode.insertBefore( link, firstScript ); + sTimeout(cb, 0); + } + } + + function executeStack ( ) { + // shift an element off of the stack + var i = execStack.shift(); + started = 1; + + // if a is truthy and the first item in the stack has an src + if ( i ) { + // if it's a script, inject it into the head with no type attribute + if ( i['t'] ) { + // Inject after a timeout so FF has time to be a jerk about it and + // not double load (ignore the cache) + sTimeout( function () { + (i['t'] == "c" ? yepnope['injectCss'] : yepnope['injectJs'])( i['s'], 0, i['a'], i['x'], i['e'], 1 ); + }, 0 ); + } + // Otherwise, just call the function and potentially run the stack + else { + i(); + executeStack(); + } + } + else { + // just reset out of recursive mode + started = 0; + } + } + + function preloadFile ( elem, url, type, splicePoint, dontExec, attrObj, timeout ) { + + timeout = timeout || yepnope['errorTimeout']; + + // Create appropriate element for browser and type + var preloadElem = doc.createElement( elem ), + done = 0, + firstFlag = 0, + stackObject = { + "t": type, // type + "s": url, // src + //r: 0, // ready + "e": dontExec,// set to true if we don't want to reinject + "a": attrObj, + "x": timeout + }; + + // The first time (common-case) + if ( scriptCache[ url ] === 1 ) { + firstFlag = 1; + scriptCache[ url ] = []; + } + + function onload ( first ) { + // If the script/css file is loaded + if ( ! done && isFileReady( preloadElem.readyState ) ) { + + // Set done to prevent this function from being called twice. + stackObject['r'] = done = 1; + + ! started && executeStack(); + + if ( first ) { + if ( elem != "img" ) { + sTimeout( function () { + insBeforeObj.removeChild( preloadElem ); + }, 50); + } + + for ( var i in scriptCache[ url ] ) { + if ( scriptCache[ url ].hasOwnProperty( i ) ) { + scriptCache[ url ][ i ].onload(); + } + } + + // Handle memory leak in IE + preloadElem.onload = preloadElem.onreadystatechange = null; + } + } + } + + + // Setting url to data for objects or src for img/scripts + if ( elem == "object" ) { + preloadElem.data = url; + + // Setting the type attribute to stop Firefox complaining about the mimetype when running locally. + // The type doesn't matter as long as it's real, thus text/css instead of text/javascript. + preloadElem.setAttribute("type", "text/css"); + } else { + preloadElem.src = url; + + // Setting bogus script type to allow the script to be cached + preloadElem.type = elem; + } + + // Don't let it show up visually + preloadElem.width = preloadElem.height = "0"; + + // Attach handlers for all browsers + preloadElem.onerror = preloadElem.onload = preloadElem.onreadystatechange = function(){ + onload.call(this, firstFlag); + }; + // inject the element into the stack depending on if it's + // in the middle of other scripts or not + execStack.splice( splicePoint, 0, stackObject ); + + // The only place these can't go is in the <head> element, since objects won't load in there + // so we have two options - insert before the head element (which is hard to assume) - or + // insertBefore technically takes null/undefined as a second param and it will insert the element into + // the parent last. We try the head, and it automatically falls back to undefined. + if ( elem != "img" ) { + // If it's the first time, or we've already loaded it all the way through + if ( firstFlag || scriptCache[ url ] === 2 ) { + readFirstScript(); + insBeforeObj.insertBefore( preloadElem, isGeckoLTE18 ? null : firstScript ); + + // If something fails, and onerror doesn't fire, + // continue after a timeout. + sTimeout( onload, timeout ); + } + else { + // instead of injecting, just hold on to it + scriptCache[ url ].push( preloadElem ); + } + } + } + + function load ( resource, type, dontExec, attrObj, timeout ) { + // If this method gets hit multiple times, we should flag + // that the execution of other threads should halt. + started = 0; + + // We'll do 'j' for js and 'c' for css, yay for unreadable minification tactics + type = type || "j"; + if ( isString( resource ) ) { + // if the resource passed in here is a string, preload the file + preloadFile( type == "c" ? strCssElem : strJsElem, resource, type, this['i']++, dontExec, attrObj, timeout ); + } else { + // Otherwise it's a callback function and we can splice it into the stack to run + execStack.splice( this['i']++, 0, resource ); + execStack.length == 1 && executeStack(); + } + + // OMG is this jQueries? For chaining... + return this; + } + + // return the yepnope object with a fresh loader attached + function getYepnope () { + var y = yepnope; + y['loader'] = { + "load": load, + "i" : 0 + }; + return y; + } + + /* End loader helper functions */ + // Yepnope Function + yepnope = function ( needs ) { + + var i, + need, + // start the chain as a plain instance + chain = this['yepnope']['loader']; + + function satisfyPrefixes ( url ) { + // split all prefixes out + var parts = url.split( "!" ), + gLen = globalFilters.length, + origUrl = parts.pop(), + pLen = parts.length, + res = { + "url" : origUrl, + // keep this one static for callback variable consistency + "origUrl" : origUrl, + "prefixes" : parts + }, + mFunc, + j, + prefix_parts; + + // loop through prefixes + // if there are none, this automatically gets skipped + for ( j = 0; j < pLen; j++ ) { + prefix_parts = parts[ j ].split( '=' ); + mFunc = prefixes[ prefix_parts.shift() ]; + if ( mFunc ) { + res = mFunc( res, prefix_parts ); + } + } + + // Go through our global filters + for ( j = 0; j < gLen; j++ ) { + res = globalFilters[ j ]( res ); + } + + // return the final url + return res; + } + + function getExtension ( url ) { + //The extension is always the last characters before the ? and after a period. + //The previous method was not accounting for the possibility of a period in the query string. + var b = url.split('?')[0]; + return b.substr(b.lastIndexOf('.')+1); + } + + function loadScriptOrStyle ( input, callback, chain, index, testResult ) { + // run through our set of prefixes + var resource = satisfyPrefixes( input ), + autoCallback = resource['autoCallback'], + extension = getExtension( resource['url'] ); + + // if no object is returned or the url is empty/0 just exit the load + if ( resource['bypass'] ) { + return; + } + + // Determine callback, if any + if ( callback ) { + callback = isFunction( callback ) ? + callback : + callback[ input ] || + callback[ index ] || + callback[ ( input.split( "/" ).pop().split( "?" )[ 0 ] ) ]; + } + + // if someone is overriding all normal functionality + if ( resource['instead'] ) { + return resource['instead']( input, callback, chain, index, testResult ); + } + else { + // Handle if we've already had this url and it's completed loaded already + if ( scriptCache[ resource['url'] ] && resource['reexecute'] !== true) { + // don't let this execute again + resource['noexec'] = true; + } + else { + scriptCache[ resource['url'] ] = 1; + } + + // Throw this into the queue + input && chain.load( resource['url'], ( ( resource['forceCSS'] || ( ! resource['forceJS'] && "css" == getExtension( resource['url'] ) ) ) ) ? "c" : undef, resource['noexec'], resource['attrs'], resource['timeout'] ); + + // If we have a callback, we'll start the chain over + if ( isFunction( callback ) || isFunction( autoCallback ) ) { + // Call getJS with our current stack of things + chain['load']( function () { + // Hijack yepnope and restart index counter + getYepnope(); + // Call our callbacks with this set of data + callback && callback( resource['origUrl'], testResult, index ); + autoCallback && autoCallback( resource['origUrl'], testResult, index ); + + // Override this to just a boolean positive + scriptCache[ resource['url'] ] = 2; + } ); + } + } + } + + function loadFromTestObject ( testObject, chain ) { + var testResult = !! testObject['test'], + group = testResult ? testObject['yep'] : testObject['nope'], + always = testObject['load'] || testObject['both'], + callback = testObject['callback'] || noop, + cbRef = callback, + complete = testObject['complete'] || noop, + needGroupSize; + + // Reusable function for dealing with the different input types + // NOTE:: relies on closures to keep 'chain' up to date, a bit confusing, but + // much smaller than the functional equivalent in this case. + function handleGroup ( needGroup, moreToCome ) { + /* jshint -W083 */ + if ( '' !== needGroup && ! needGroup ) { + // Call the complete callback when there's nothing to load. + ! moreToCome && complete(); + } + // If it's a string + else if ( isString( needGroup ) ) { + // if it's a string, it's the last + if ( !moreToCome ) { + // Add in the complete callback to go at the end + callback = function () { + var args = [].slice.call( arguments ); + cbRef.apply( this, args ); + complete(); + }; + } + // Just load the script of style + loadScriptOrStyle( needGroup, callback, chain, 0, testResult ); + } + // See if we have an object. Doesn't matter if it's an array or a key/val hash + // Note:: order cannot be guaranteed on an key value object with multiple elements + // since the for-in does not preserve order. Arrays _should_ go in order though. + else if ( isObject( needGroup ) ) { + // I hate this, but idk another way for objects. + needGroupSize = (function(){ + var count = 0, i; + for (i in needGroup ) { + if ( needGroup.hasOwnProperty( i ) ) { + count++; + } + } + return count; + })(); + + for ( var callbackKey in needGroup ) { + // Safari 2 does not have hasOwnProperty, but not worth the bytes for a shim + // patch if needed. Kangax has a nice shim for it. Or just remove the check + // and promise not to extend the object prototype. + if ( needGroup.hasOwnProperty( callbackKey ) ) { + // Find the last added resource, and append to it's callback. + if ( ! moreToCome && ! ( --needGroupSize ) ) { + // If this is an object full of callbacks + if ( ! isFunction( callback ) ) { + // Add in the complete callback to go at the end + callback[ callbackKey ] = (function( innerCb ) { + return function () { + var args = [].slice.call( arguments ); + innerCb && innerCb.apply( this, args ); + complete(); + }; + })( cbRef[ callbackKey ] ); + } + // If this is just a single callback + else { + callback = function () { + var args = [].slice.call( arguments ); + cbRef.apply( this, args ); + complete(); + }; + } + } + loadScriptOrStyle( needGroup[ callbackKey ], callback, chain, callbackKey, testResult ); + } + } + } + } + + // figure out what this group should do + handleGroup( group, !!always || !!testObject['complete']); + + // Run our loader on the load/both group too + // the always stuff always loads second. + always && handleGroup( always ); + + // If complete callback is used without loading anything + !always && !!testObject['complete'] && handleGroup(''); + + } + + // Someone just decides to load a single script or css file as a string + if ( isString( needs ) ) { + loadScriptOrStyle( needs, 0, chain, 0 ); + } + // Normal case is likely an array of different types of loading options + else if ( isArray( needs ) ) { + // go through the list of needs + for( i = 0; i < needs.length; i++ ) { + need = needs[ i ]; + + // if it's a string, just load it + if ( isString( need ) ) { + loadScriptOrStyle( need, 0, chain, 0 ); + } + // if it's an array, call our function recursively + else if ( isArray( need ) ) { + yepnope( need ); + } + // if it's an object, use our modernizr logic to win + else if ( isObject( need ) ) { + loadFromTestObject( need, chain ); + } + } + } + // Allow a single object to be passed in + else if ( isObject( needs ) ) { + loadFromTestObject( needs, chain ); + } + }; + + // This publicly exposed function is for allowing + // you to add functionality based on prefixes on the + // string files you add. 'css!' is a builtin prefix + // + // The arguments are the prefix (not including the !) as a string + // and + // A callback function. This function is passed a resource object + // that can be manipulated and then returned. (like middleware. har.) + // + // Examples of this can be seen in the officially supported ie prefix + yepnope['addPrefix'] = function ( prefix, callback ) { + prefixes[ prefix ] = callback; + }; + + // A filter is a global function that every resource + // object that passes through yepnope will see. You can + // of course conditionally choose to modify the resource objects + // or just pass them along. The filter function takes the resource + // object and is expected to return one. + // + // The best example of a filter is the 'autoprotocol' officially + // supported filter + yepnope['addFilter'] = function ( filter ) { + globalFilters.push( filter ); + }; + + // Default error timeout to 10sec - modify to alter + yepnope['errorTimeout'] = 1e4; + + // Webreflection readystate hack + // safe for jQuery 1.4+ ( i.e. don't use yepnope with jQuery 1.3.2 ) + // if the readyState is null and we have a listener + if ( doc.readyState == null && doc.addEventListener ) { + // set the ready state to loading + doc.readyState = "loading"; + // call the listener + doc.addEventListener( "DOMContentLoaded", handler = function () { + // Remove the listener + doc.removeEventListener( "DOMContentLoaded", handler, 0 ); + // Set it to ready + doc.readyState = "complete"; + }, 0 ); + } + + // Attach loader & + // Leak it + window['yepnope'] = getYepnope(); + + // Exposing executeStack to better facilitate plugins + window['yepnope']['executeStack'] = executeStack; + window['yepnope']['injectJs'] = injectJs; + window['yepnope']['injectCss'] = injectCss; + +})( window, document ); + +// Reappropriate +ModernizrProto['load'] = function() { + window['yepnope'].apply(window, [].slice.call(arguments,0)); +}; + + + + /** + * contains returns a boolean for if substr is found within str. + */ + function contains( str, substr ) { + return !!~('' + str).indexOf(substr); + } + + ; + + var createElement = function() { + return document.createElement.apply(document, arguments); + }; + + + /** + * Create our "modernizr" element that we do most feature tests on. + */ + 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; + }); + + + + 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('body'); + body.fake = true; + } + + return body; + } + + ; + + // Inject element with style element and some CSS rules + 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> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed + // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element + // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements. + // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx + // Documents served as xml will throw if using ­ so use xml friendly encoded version. See issue #277 + style = ['­','<style id="s', mod, '">', rule, '</style>'].join(''); + div.id = 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).innerHTML += style; + body.appendChild(div); + 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+ + docElement.offsetHeight; + } else { + div.parentNode.removeChild(div); + } + + return !!ret; + + } + + ; + + // Helper function for e.g. boxSizing -> box-sizing + function domToHyphenated( name ) { + return name.replace(/([A-Z])/g, function(str, m1) { + return '-' + m1.toLowerCase(); + }).replace(/^ms-/, '-ms-'); + } + ; + + // Function to allow us to use native feature detection functionality if available. + // 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(domToHyphenated(props[i]), value)) { + return true; + } + } + return false; + } + // Otherwise fall back to at-rule (for FF 17 and Opera 12.x) + else if ('CSSSupportsRule' in window) { + // Build a condition string for every prefixed variant + var conditionText = []; + while (i--) { + conditionText.push('(' + domToHyphenated(props[i]) + ':' + value + ')'); + } + conditionText = conditionText.join(' or '); + return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function( node ) { + return (window.getComputedStyle ? + getComputedStyle(node, null) : + node.currentStyle)['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. + + // Because the testing of the CSS property names (with "-", as + // opposed to the camelCase DOM properties) is non-portable and + // non-standard but works in WebKit and IE (but not Gecko or Opera), + // we explicitly reject properties with dashes so that authors + // developing in WebKit or IE first don't end up with + // browser-specific content by accident. + + 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, j, 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 + if ( !mStyle.style ) { + afterInit = true; + mStyle.modElem = createElement('modernizr'); + mStyle.style = mStyle.modElem.style; + } + + // Delete the objects if we + // we created them. + function cleanElems() { + if (afterInit) { + delete mStyle.style; + delete mStyle.modElem; + } + } + + for ( i in props ) { + prop = props[i]; + before = mStyle.style[prop]; + + if ( !contains(prop, "-") && 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; + } + + ; + + // Modernizr.testProp() investigates whether a given style property is recognized + // Note that the property names must be provided in the camelCase variant. + // Modernizr.testProp('pointerEvents') + // Also accepts optional 2nd arg, of a value to use for native feature detection, e.g.: + // Modernizr.testProp('pointerEvents', 'none') + var testProp = ModernizrProto.testProp = function( prop, value, useValue ) { + return testProps([prop], undefined, value, useValue); + }; + + + var slice = classes.slice; + + + // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js + // es5.github.com/#x15.3.4.5 + + if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { + + var target = this; + + if (typeof target != "function") { + throw new TypeError(); + } + + var args = slice.call(arguments, 1); + var bound = function() { + + if (this instanceof bound) { + + var F = function(){}; + F.prototype = target.prototype; + var self = new F(); + + var result = target.apply( + self, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return self; + + } else { + + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + + return bound; + }; + } + + ; +/*! +{ + "name": "a[download] Attribute", + "property": "adownload", + "caniuse" : "download", + "tags": ["media", "attribute"], + "notes": [{ + "name": "WhatWG Reference", + "href": "http://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": "Application Cache", + "property": "applicationcache", + "caniuse": "offline-apps", + "tags": ["storage", "offline"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en/docs/HTML/Using_the_application_cache" + }], + "polyfills": ["html5gears"] +} +!*/ +/* DOC + +Detects support for the Application Cache, for storing data to enable web-based applications run offline. + +The API has been [heavily criticized](http://alistapart.com/article/application-cache-is-a-douchebag) and discussions are underway to address this. + +*/ + + Modernizr.addTest('applicationcache', 'applicationCache' in window); + +/*! +{ + "name": "Web Audio API", + "property": "webaudio", + "caniuse": "audio-api", + "polyfills": ["xaudiojs", "dynamicaudiojs", "audiolibjs"], + "tags": ["audio", "media"], + "authors": ["Addy Osmani"], + "notes": [{ + "name": "W3 Specification", + "href": "https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html" + }] +} +!*/ + + Modernizr.addTest('webaudio', 'webkitAudioContext' in window || 'AudioContext' in window); + +/*! +{ + "name" : "HTML5 Audio Element", + "property": "audio", + "aliases" : [], + "tags" : ["html5", "audio", "media"], + "doc" : "/docs/#audio", + "knownBugs": [], + "authors" : [] +} +!*/ + + // This tests evaluates support of the audio element, as well as + // testing what types of content it supports. + // + // We're using the Boolean constructor here, so that we can extend the value + // e.g. Modernizr.audio // true + // Modernizr.audio.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('audio', function() { + /* jshint -W053 */ + var elem = createElement('audio'); + var bool = false; + + try { + if ( bool = !!elem.canPlayType ) { + bool = new Boolean(bool); + bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); + bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); + bool.opus = elem.canPlayType('audio/ogg; codecs="opus"') .replace(/^no$/,''); + + // Mimetypes accepted: + // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements + // bit.ly/iphoneoscodecs + bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); + bool.m4a = ( elem.canPlayType('audio/x-m4a;') || + elem.canPlayType('audio/aac;')) .replace(/^no$/,''); + } + } catch(e) { } + + return bool; + }); + + + // Following spec is to expose vendor-specific style properties as: + // elem.style.WebkitBorderRadius + // and the following would be 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 + var omPrefixes = 'Webkit Moz O ms'; + + + var cssomPrefixes = omPrefixes.split(' '); + ModernizrProto._cssomPrefixes = cssomPrefixes; + + + var domPrefixes = omPrefixes.toLowerCase().split(' '); + ModernizrProto._domPrefixes = domPrefixes; + + + /** + * testDOMProps is a generic DOM property test; if a browser supports + * a certain property, it won't return undefined for it. + */ + 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 (and it has a bind method -- certain native objects that report that they are a + // function don't [such as webkitAudioContext]) + if (is(item, 'function') && 'bind' in item){ + // default to autobind unless override + return item.bind(elem || obj); + } + + // return the unbound function or obj or value + return item; + } + } + return false; + } + + ; + + // List of property values to set for css tests. See ticket #21 + var prefixes = ' -webkit- -moz- -o- -ms- '.split(' '); + + // expose these for the plugin API. Look in the source for how to join() them against your input + ModernizrProto._prefixes = prefixes; + + + + /** + * 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. + */ + 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; + + + + // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input + // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' + + // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. + // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: + // + // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); + + // If you're trying to ascertain which transition end event to bind to, you might do something like... + // + // var transEndEventNames = { + // 'WebkitTransition' : 'webkitTransitionEnd',// Saf 6, Android Browser + // 'MozTransition' : 'transitionend', // only for FF < 15 + // 'transition' : 'transitionend' // IE10, Opera, Chrome, FF 15+, Saf 7+ + // }, + // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; + + var prefixed = ModernizrProto.prefixed = function( prop, obj, elem ) { + if (!obj) { + return testPropsAll(prop, 'pfx'); + } else { + // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' + return testPropsAll(prop, obj, elem); + } + }; + + +/*! +{ + "name": "Low Battery Level", + "property": "lowbattery", + "tags": ["hardware", "mobile"], + "authors": ["Paul Sayre"], + "notes": [{ + "name": "MDN Docs", + "href": "http://developer.mozilla.org/en/DOM/window.navigator.mozBattery" + }] +} +!*//* DOC +Enable a developer to remove CPU intensive CSS/JS when battery is low +*/ + + Modernizr.addTest('lowbattery', function() { + var minLevel = 0.20; + var battery = prefixed('battery', navigator); + return !!(battery && !battery.charging && battery.level <= minLevel); + }); + +/*! +{ + "name": "Battery API", + "property": "batteryapi", + "aliases": ["battery-api"], + "tags": ["device", "media"], + "authors": ["Paul Sayre"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en/DOM/window.navigator.mozBattery" + }] +} +!*/ +/* DOC + +Detect support for the Battery API, for accessing information about the system's battery charge level. + +*/ + + Modernizr.addTest('batteryapi', !!prefixed('battery', navigator), { aliases: ['battery-api'] }); + +/*! +{ + "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": "canvas.toDataURL type support", + "property": ["todataurljpeg", "todataurlpng", "todataurlwebp"], + "tags": ["canvas"], + "async" : false, + "notes": [{ + "name": "HTML5 Spec", + "href": "http://www.w3.org/TR/html5/the-canvas-element.html#dom-canvas-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() { + return !!Modernizr.canvas && canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0; + }); + + +/*! +{ + "name": "Canvas text", + "property": "canvastext", + "caniuse": "canvas-text", + "tags": ["canvas", "graphics"], + "polyfills": ["canvastext"] +} +!*/ +/* DOC + +Detects support for the text APIs for `<canvas>` elements. + +*/ + + Modernizr.addTest('canvastext', function() { + if (Modernizr.canvas === false) return false; + return typeof createElement('canvas').getContext('2d').fillText == 'function'; + }); + +/*! +{ + "name": "Web Cryptography API getRandomValues method", + "property": "getrandomvalues", + "caniuse": "window.crypto.getRandomValues", + "tags": ["crypto"], + "authors": ["komachi"], + "notes": [{ + "name": "W3C Editor’s Draft", + "href": "https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#RandomSource-method-getRandomValues" + }], + "polyfills": [ + "polycrypt" + ] +} +!*/ +/* DOC + +Detects support for the window.crypto.getRandomValues for generate cryptographically secure random numbers + +*/ + + Modernizr.addTest('getrandomvalues', 'crypto' in window && 'getRandomValues' in window.crypto); + +/*! +{ + "name": "Content Editable", + "property": "contenteditable", + "caniuse": "contenteditable", + "notes": [{ + "name": "WHATWG spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#contenteditable" + }] +} +!*/ +/* DOC + +Detects support for the `contenteditable` attribute of elements, allowing their DOM text contents to be edited directly by the user. + +*/ + + Modernizr.addTest('contenteditable', function() { + // early bail out + if (!('contentEditable' in docElement)) return; + + // some mobile browsers (android < 3.0, iOS < 5) claim to support + // contentEditable, but but don't really. This test checks to see + // confirms wether or not it actually supports it. + + var div = createElement('div'); + div.contentEditable = true; + return div.contentEditable === "true"; + }); + +/*! +{ + "name": "Content Security Policy", + "property": "contentsecuritypolicy", + "caniuse": "contentsecuritypolicy", + "tags": ["security"], + "notes": [{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/CSP/" + },{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/Security/CSP" + }] +} +!*/ +/* DOC + +Detects support for the Content Security Policy protocol for mitigating and reporting security attacks. + +*/ + + Modernizr.addTest('contentsecuritypolicy', 'SecurityPolicy' in document); + +/*! +{ + "name": "Context menus", + "property": "contextmenu", + "caniuse": "menu", + "notes": [{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/html5/interactive-elements.html#context-menus" + },{ + "name": "thewebrocks.com Demo", + "href": "http://thewebrocks.com/demos/context-menu/" + }], + "polyfills": ["jquery-contextmenu"] +} +!*/ +/* DOC + +Detects support for custom context menus. + +*/ + + Modernizr.addTest( + 'contextmenu', + ('contextMenu' in docElement && 'HTMLMenuItemElement' in window) + ); + +/*! +{ + "name": "Cookies", + "property": "cookies", + "tags": ["storage"], + "authors": ["tauren"] +} +!*/ +/* DOC + +Detects whether cookie support is enabled. + +*/ + + // https://github.com/Modernizr/Modernizr/issues/191 + + Modernizr.addTest('cookies', function () { + // navigator.cookieEnabled is in IE9 but always true. Don't rely on it. + + // Create cookie + document.cookie = "cookietest=1"; + var ret = document.cookie.indexOf("cookietest=") != -1; + // Delete cookie + document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT"; + return ret; + }); + +/*! +{ + "name": "Cross-Origin Resource Sharing", + "property": "cors", + "caniuse": "cors", + "authors": ["Theodoor van Donge"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS" + }], + "polyfills": ["pmxdr", "ppx", "flxhr"] +} +!*/ +/* DOC + +Detects support for Cross-Origin Resource Sharing: method of performing XMLHttpRequests across domains. + +*/ + + Modernizr.addTest('cors', 'XMLHttpRequest' in window && 'withCredentials' in new XMLHttpRequest()); + + + /** + * testAllProps determines whether a given CSS property, in some prefixed + * form, is supported by the browser. It can optionally be given a value; in + * which case testAllProps will only return true if the browser supports that + * value for the named property; this latter case will use native detection + * (via window.CSS.supports) if available. A boolean can be passed as a 3rd + * parameter to skip the value check when native detection isn't available, + * to improve performance when simply testing for support of a property. + * + * @param prop - String naming the property to test + * @param value - [optional] String of the value to test + * @param skipValueTest - [optional] Whether to skip testing that the value + * is supported when using non-native detection + * (default: false) + */ + 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": "http://goo.gl/CHVJm" + }] +} +!*/ + + Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true)); + +/*! +{ + "name": "CSS Background Clip Text", + "property": "backgroundcliptext", + "authors": ["ausi"], + "tags": ["css"], + "notes": [ + { + "name": "CSS Tricks Article", + "href": "http://css-tricks.com/image-under-text/" + }, + { + "name": "MDN Docs", + "href": "http://developer.mozilla.org/en/CSS/background-clip" + }, + { + "name": "Related Github Issue", + "href": "http://github.com/Modernizr/Modernizr/issues/199" + } + ] +} +!*/ + + Modernizr.addTest('backgroundcliptext', function() { + return testAllProps('backgroundClip', 'text'); + }); + +/*! +{ + "name": "Background Position Shorthand", + "property": "bgpositionshorthand", + "tags": ["css"], + "notes": [{ + "name": "MDN Docs", + "href": "https://developer.mozilla.org/en/CSS/background-position" + }, { + "name": "W3 Spec", + "href": "http://www.w3.org/TR/css3-background/#background-position" + }, { + "name": "Demo", + "href": "http://jsfiddle.net/Blink/bBXvt/" + }] +} +!*/ + + Modernizr.addTest('bgpositionshorthand', function() { + var elem = createElement('a'); + var eStyle = elem.style; + var val = 'right 10px bottom 10px'; + eStyle.cssText = 'background-position: ' + val + ';'; + return (eStyle.backgroundPosition === val); + }); + +/*! +{ + "name": "Background Position XY", + "property": "bgpositionxy", + "tags": ["css"], + "authors": ["Allan Lei", "Brandom Aaron"], + "notes": [{ + "name": "Demo", + "href": "http://jsfiddle.net/allanlei/R8AYS/" + }, { + "name": "Adapted From", + "href": "https://github.com/brandonaaron/jquery-cssHooks/blob/master/bgpos.js" + }] +} +!*/ + + Modernizr.addTest('bgpositionxy', function () { + return testAllProps('backgroundPositionX', '3px', true) && testAllProps('backgroundPositionY', '5px', true); + }); + +/*! +{ + "name": "Background Repeat", + "property": ["bgrepeatspace", "bgrepeatround"], + "tags": ["css"], + "authors": ["Ryan Seddon"], + "notes": [{ + "name": "MDN Docs", + "href": "http://developer.mozilla.org/en/CSS/background-repeat" + }, { + "name": "Test Page", + "href": "http://jsbin.com/uzesun/" + }, { + "name": "Demo", + "href": "http://jsfiddle.net/ryanseddon/yMLTQ/6/" + }] +} +!*/ + + // Must value-test these + Modernizr.addTest('bgrepeatround', testAllProps('backgroundRepeat', 'round')); + Modernizr.addTest('bgrepeatspace', testAllProps('backgroundRepeat', 'space')); + +/*! +{ + "name": "Background Size", + "property": "backgroundsize", + "tags": ["css"], + "knownBugs": ["This will false positive in Opera Mini - http://github.com/Modernizr/Modernizr/issues/396"], + "notes": [{ + "name": "Related Issue", + "href": "http://github.com/Modernizr/Modernizr/issues/396" + }] +} +!*/ + + Modernizr.addTest('backgroundsize', testAllProps('backgroundSize', '100%', true)); + +/*! +{ + "name": "Background Size Cover", + "property": "bgsizecover", + "tags": ["css"], + "notes": [{ + "name" : "MDN Docs", + "href": "http://developer.mozilla.org/en/CSS/background-size" + }] +} +!*/ + + // Must test value, as this specifically tests the `cover` value + Modernizr.addTest('bgsizecover', testAllProps('backgroundSize', 'cover')); + +/*! +{ + "name": "Border Image", + "property": "borderimage", + "caniuse": "border-image", + "polyfills": ["css3pie"], + "tags": ["css"] +} +!*/ + + Modernizr.addTest('borderimage', testAllProps('borderImage', 'url() 1', true)); + +/*! +{ + "name": "Border Radius", + "property": "borderradius", + "caniuse": "border-radius", + "polyfills": ["css3pie"], + "tags": ["css"], + "notes": [{ + "name": "Comprehensive Compat Chart", + "href": "http://muddledramblings.com/table-of-css3-border-radius-compliance" + }] +} +!*/ + + Modernizr.addTest('borderradius', testAllProps('borderRadius', '0px', true)); + +/*! +{ + "name": "Box Shadow", + "property": "boxshadow", + "caniuse": "css-boxshadow", + "tags": ["css"], + "knownBugs": ["WebOS false positives on this test."] +} +!*/ + + Modernizr.addTest('boxshadow', testAllProps('boxShadow', '1px 1px', true)); + +/*! +{ + "name": "Box Sizing", + "property": "boxsizing", + "caniuse": "css3-boxsizing", + "polyfills": ["borderboxmodel", "boxsizingpolyfill", "borderbox"], + "tags": ["css"], + "notes": [{ + "name": "MDN Docs", + "href": "http://developer.mozilla.org/en/CSS/box-sizing" + },{ + "name": "Related Github Issue", + "href": "http://github.com/Modernizr/Modernizr/issues/248" + }] +} +!*/ + + Modernizr.addTest('boxsizing', testAllProps('boxSizing', 'border-box', true) && (document.documentMode === undefined || document.documentMode > 7)); + +/*! +{ + "name": "CSS Calc", + "property": "csscalc", + "caniuse": "calc", + "tags": ["css"], + "authors": ["@calvein"] +} +!*//* DOC + +Method of allowing calculated values for length units. For example: + +```css +#elem { + width: calc(100% - 3em); +} +``` + +*/ + + Modernizr.addTest('csscalc', function() { + var prop = 'width:'; + var value = 'calc(10px);'; + var el = createElement('div'); + + el.style.cssText = prop + prefixes.join(value + prop); + + return !!el.style.length; + }); + + + var testStyles = ModernizrProto.testStyles = injectElementWithStyles; + +/*! +{ + "name": "CSS :checked pseudo-selector", + "caniuse": "css-sel3", + "property": "checked", + "tags": ["css"], + "notes": [{ + "name": "Related Github Issue", + "href": "https://github.com/Modernizr/Modernizr/pull/879" + }] +} +!*/ + + Modernizr.addTest('checked', function(){ + return testStyles('#modernizr {position:absolute} #modernizr input {margin-left:10px} #modernizr :checked {margin-left:20px;display:block}', function(elem, rule){ + var cb = createElement('input'); + cb.setAttribute("type", "checkbox"); + cb.setAttribute("checked", "checked"); + elem.appendChild(cb); + return cb.offsetLeft === 20; + }); + }); + +/*! +{ + "name": "CSS Columns", + "property": "csscolumns", + "caniuse": "multicolumn", + "polyfills": ["css3multicolumnjs"], + "tags": ["css"] +} +!*/ + + + (function() { + + /* jshint -W053 */ + Modernizr.addTest('csscolumns', function(){ + var bool = false; + var test = testAllProps('columnCount'); + try { + if ( bool = !!test ) { + bool = new Boolean(bool); + } + } catch(e){} + + return bool; + }); + + var props = ['Width', 'Span', 'Fill', 'Gap', 'Rule', 'RuleColor', 'RuleStyle', 'RuleWidth', 'BreakBefore', 'BreakAfter', 'BreakInside']; + var name, test; + + for (var i = 0; i < props.length; i++) { + name = props[i].toLowerCase(); + test = testAllProps('column' + props[i]); + + // break-before, break-after & break-inside are not "column"-prefixed in spec + if (name === 'breakbefore' || name === 'breakafter' || name == 'breakinside') { + test = test || testAllProps(props[i]); + } + + Modernizr.addTest('csscolumns.' + name, test); + } + + + })(); + + +/*! +{ + "name": "CSS Cubic Bezier Range", + "property": "cubicbezierrange", + "tags": ["css"], + "doc" : null, + "authors": ["@calvein"], + "warnings": ["cubic-bezier values can't be > 1 for Webkit until [bug #45761](https://bugs.webkit.org/show_bug.cgi?id=45761) is fixed"] +} +!*/ + + Modernizr.addTest('cubicbezierrange', function() { + var el = createElement('div'); + el.style.cssText = prefixes.join('transition-timing-function:cubic-bezier(1,0,0,1.1); '); + return !!el.style.length; + }); + +/*! +{ + "name": "CSS Display run-in", + "property": "display-runin", + "authors": ["alanhogan"], + "tags": ["css"], + "notes": [{ + "name": "CSS Tricks Article", + "href": "http://css-tricks.com/596-run-in/" + },{ + "name": "Related Github Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/198" + }] +} +!*/ + + Modernizr.addTest('displayrunin', testAllProps('display', 'run-in'), + { aliases: ['display-runin'] }); + +/*! +{ + "name": "CSS Display table", + "property": "displaytable", + "caniuse": "css-table", + "authors": ["scottjehl"], + "tags": ["css"], + "notes": [{ + "name": "All additional table display values", + "href": "http://pastebin.com/Gk9PeVaQ" + }] +} +!*//* DOC + +`display: table` and `table-cell` test. (both are tested under one name `table-cell` ) + +All additional table display values are here: http://pastebin.com/Gk9PeVaQ though Scott +has seen some IE false positives with that sort of weak detection. +More testing neccessary perhaps. + +*/ + + // If a document is in rtl mode this test will fail so we force ltr mode on the injeced + // element https://github.com/Modernizr/Modernizr/issues/716 + testStyles('#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}', function( elem ) { + var ret; + var child = elem.children; + ret = child[0].offsetLeft < child[1].offsetLeft; + Modernizr.addTest('displaytable', ret, { aliases: ['display-table'] }); + },2); + +/*! +{ + "name": "CSS text-overflow ellipsis", + "property": "ellipsis", + "caniuse": "text-overflow", + "polyfills": [ + "text-overflow" + ], + "tags": ["css"] +} +!*/ + + Modernizr.addTest('ellipsis', testAllProps('textOverflow', 'ellipsis')); + +/*! +{ + "name": "CSS Filters", + "property": "cssfilters", + "caniuse": "css-filters", + "polyfills": ["polyfilter"], + "tags": ["css"] +} +!*/ + + // https://github.com/Modernizr/Modernizr/issues/615 + // documentMode is needed for false positives in oldIE, please see issue above + Modernizr.addTest('cssfilters', function() { + var el = createElement('div'); + el.style.cssText = prefixes.join('filter:blur(2px); '); + return !!el.style.length && ((document.documentMode === undefined || document.documentMode > 9)); + }); + + +/*! +{ + "name": "Flexbox", + "property": "flexbox", + "caniuse": "flexbox", + "tags": ["css"], + "notes": [{ + "name": "The _new_ flexbox", + "href": "http://dev.w3.org/csswg/css3-flexbox" + }] +} +!*/ + + Modernizr.addTest('flexbox', testAllProps('flexBasis', '1px', true)); + +/*! +{ + "name": "Flexbox (legacy)", + "property": "flexboxlegacy", + "tags": ["css"], + "polyfills": ["flexie"], + "notes": [{ + "name": "The _old_ flexbox", + "href": "http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/" + }] +} +!*/ + + Modernizr.addTest('flexboxlegacy', testAllProps('boxDirection', 'reverse', true)); + +/*! +{ + "name": "Flexbox (tweener)", + "property": "flexboxtweener", + "tags": ["css"], + "polyfills": ["flexie"], + "notes": [{ + "name": "The _inbetween_ flexbox", + "href": "http://www.w3.org/TR/2011/WD-css3-flexbox-20111129/" + }] +} +!*/ + + Modernizr.addTest('flexboxtweener', testAllProps('flexAlign', 'end', true)); + +/*! +{ + "name": "@font-face", + "property": "fontface", + "authors": ["Diego Perini"], + "tags": ["css"], + "knownBugs": [ + "False Positive: WebOS http://github.com/Modernizr/Modernizr/issues/342", + "False Postive: WP7 http://github.com/Modernizr/Modernizr/issues/538" + ], + "notes": [{ + "name": "@font-face detection routine by Diego Perini", + "href": "http://javascript.nwbox.com/CSSSupport/" + }] +} +!*/ + + testStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { + var style = document.getElementById('smodernizr'); + var sheet = style.sheet || style.styleSheet; + var cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; + var bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; + + Modernizr.addTest('fontface', bool); + }); + +/*! +{ + "name": "CSS Generated Content", + "property": "generatedcontent", + "tags": ["css"], + "warnings": ["Android won't return correct height for anything below 7px #738"] +} +!*/ + + testStyles('#modernizr{font:0/0 a}#modernizr:after{content:":)";visibility:hidden;font:7px/1 a}', function( node ) { + Modernizr.addTest('generatedcontent', node.offsetHeight >= 7); + }); + +/*! +{ + "name": "CSS Gradients", + "caniuse": "css-gradients", + "property": "cssgradients", + "tags": ["css"], + "knownBugs": ["False-positives on webOS (https://github.com/Modernizr/Modernizr/issues/202)"], + "notes": [{ + "name": "Webkit Gradient Syntax", + "href": "http://webkit.org/blog/175/introducing-css-gradients/" + },{ + "name": "Mozilla Linear Gradient Syntax", + "href": "http://developer.mozilla.org/en/CSS/-moz-linear-gradient" + },{ + "name": "Mozilla Radial Gradient Syntax", + "href": "http://developer.mozilla.org/en/CSS/-moz-radial-gradient" + },{ + "name": "W3C Gradient Spec", + "href": "dev.w3.org/csswg/css3-images/#gradients-" + }] +} +!*/ + + + Modernizr.addTest('cssgradients', function() { + + var str1 = 'background-image:'; + var str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));'; + var str3 = 'linear-gradient(left top,#9f9, white);'; + + var css = + // legacy webkit syntax (FIXME: remove when syntax not in use anymore) + (str1 + '-webkit- '.split(' ').join(str2 + str1) + + // standard syntax // trailing 'background-image:' + prefixes.join(str3 + str1)).slice(0, -str1.length); + + var elem = createElement('div'); + var style = elem.style; + style.cssText = css; + + // IE6 returns undefined so cast to string + return ('' + style.backgroundImage).indexOf('gradient') > -1; + }); + +/*! +{ + "name": "CSS HSLA Colors", + "caniuse": "css3-colors", + "property": "hsla", + "tags": ["css"], + "notes": ["Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, except IE9 who retains it as hsla"] +} +!*/ + + Modernizr.addTest('hsla', function() { + var elem = createElement('div'); + var style = elem.style; + style.cssText = 'background-color:hsla(120,40%,100%,.5)'; + return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla'); + }); + +/*! +{ + "name": "CSS Hyphens", + "caniuse": "css-hyphens", + "property": ["csshyphens", "softhyphens", "softhyphensfind"], + "tags": ["css"], + "async" : true, + "authors": ["David Newton"], + "warnings": [ + "These tests currently require document.body to be present", + "If loading Hyphenator.js via Modernizr.load, be cautious of issue 158: http://code.google.com/p/hyphenator/issues/detail?id=158", + "This is very large – only include it if you absolutely need it" + ], + "notes": [ + "csshyphens - tests hyphens:auto actually adds hyphens to text", + "softhyphens - tests that ­ does its job", + "softhyphensfind - tests that in-browser Find functionality still works correctly with ­", + { + "name": "The Current State of Hyphenation on the Web.", + "href": "http://davidnewton.ca/the-current-state-of-hyphenation-on-the-web" + }, + { + "name": "Hyphenation Test Page", + "href": "http://davidnewton.ca/demos/hyphenation/test.html" + }, + { + "name": "Hyphenation is Language Specific", + "href": " http://code.google.com/p/hyphenator/source/diff?spec=svn975&r=975&format=side&path=/trunk/Hyphenator.js#sc_svn975_313" + }, + { + "name": "Related Modernizr Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/312" + } + ] +} +!*/ + + + Modernizr.addAsyncTest(function() { + var waitTime = 300; + setTimeout(runHyphenTest, waitTime); + // Wait 1000ms so we can hope for document.body + function runHyphenTest() { + if (!document.body && !document.getElementsByTagName('body')[0]) { + setTimeout(runHyphenTest, waitTime); + return; + } + + // functional test of adding hyphens:auto + function test_hyphens_css() { + try { + /* create a div container and a span within that + * these have to be appended to document.body, otherwise some browsers can give false negative */ + var div = createElement('div'); + var span = createElement('span'); + var divStyle = div.style; + var spanHeight = 0; + var spanWidth = 0; + var result = false; + var firstChild = document.body.firstElementChild || document.body.firstChild; + + div.appendChild(span); + span.innerHTML = 'Bacon ipsum dolor sit amet jerky velit in culpa hamburger et. Laborum dolor proident, enim dolore duis commodo et strip steak. Salami anim et, veniam consectetur dolore qui tenderloin jowl velit sirloin. Et ad culpa, fatback cillum jowl ball tip ham hock nulla short ribs pariatur aute. Pig pancetta ham bresaola, ut boudin nostrud commodo flank esse cow tongue culpa. Pork belly bresaola enim pig, ea consectetur nisi. Fugiat officia turkey, ea cow jowl pariatur ullamco proident do laborum velit sausage. Magna biltong sint tri-tip commodo sed bacon, esse proident aliquip. Ullamco ham sint fugiat, velit in enim sed mollit nulla cow ut adipisicing nostrud consectetur. Proident dolore beef ribs, laborum nostrud meatball ea laboris rump cupidatat labore culpa. Shankle minim beef, velit sint cupidatat fugiat tenderloin pig et ball tip. Ut cow fatback salami, bacon ball tip et in shank strip steak bresaola. In ut pork belly sed mollit tri-tip magna culpa veniam, short ribs qui in andouille ham consequat. Dolore bacon t-bone, velit short ribs enim strip steak nulla. Voluptate labore ut, biltong swine irure jerky. Cupidatat excepteur aliquip salami dolore. Ball tip strip steak in pork dolor. Ad in esse biltong. Dolore tenderloin exercitation ad pork loin t-bone, dolore in chicken ball tip qui pig. Ut culpa tongue, sint ribeye dolore ex shank voluptate hamburger. Jowl et tempor, boudin pork chop labore ham hock drumstick consectetur tri-tip elit swine meatball chicken ground round. Proident shankle mollit dolore. Shoulder ut duis t-bone quis reprehenderit. Meatloaf dolore minim strip steak, laboris ea aute bacon beef ribs elit shank in veniam drumstick qui. Ex laboris meatball cow tongue pork belly. Ea ball tip reprehenderit pig, sed fatback boudin dolore flank aliquip laboris eu quis. Beef ribs duis beef, cow corned beef adipisicing commodo nisi deserunt exercitation. Cillum dolor t-bone spare ribs, ham hock est sirloin. Brisket irure meatloaf in, boudin pork belly sirloin ball tip. Sirloin sint irure nisi nostrud aliqua. Nostrud nulla aute, enim officia culpa ham hock. Aliqua reprehenderit dolore sunt nostrud sausage, ea boudin pork loin ut t-bone ham tempor. Tri-tip et pancetta drumstick laborum. Ham hock magna do nostrud in proident. Ex ground round fatback, venison non ribeye in.'; + + document.body.insertBefore(div, firstChild); + + /* get size of unhyphenated text */ + divStyle.cssText = 'position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;'; + spanHeight = span.offsetHeight; + spanWidth = span.offsetWidth; + + /* compare size with hyphenated text */ + divStyle.cssText = 'position:absolute;top:0;left:0;width:5em;text-align:justify;'+ + 'text-justification:newspaper;'+ + prefixes.join('hyphens:auto; '); + + result = (span.offsetHeight != spanHeight || span.offsetWidth != spanWidth); + + /* results and cleanup */ + document.body.removeChild(div); + div.removeChild(span); + + return result; + } catch(e) { + return false; + } + } + + // for the softhyphens test + function test_hyphens( delimiter, testWidth ) { + try { + /* create a div container and a span within that + * these have to be appended to document.body, otherwise some browsers can give false negative */ + var div = createElement('div'); + var span = createElement('span'); + var divStyle = div.style; + var spanSize = 0; + var result = false; + var result1 = false; + var result2 = false; + var firstChild = document.body.firstElementChild || document.body.firstChild; + + divStyle.cssText = 'position:absolute;top:0;left:0;overflow:visible;width:1.25em;'; + div.appendChild(span); + document.body.insertBefore(div, firstChild); + + + /* get height of unwrapped text */ + span.innerHTML = 'mm'; + spanSize = span.offsetHeight; + + /* compare height w/ delimiter, to see if it wraps to new line */ + span.innerHTML = 'm' + delimiter + 'm'; + result1 = (span.offsetHeight > spanSize); + + /* if we're testing the width too (i.e. for soft-hyphen, not zws), + * this is because tested Blackberry devices will wrap the text but not display the hyphen */ + if (testWidth) { + /* get width of wrapped, non-hyphenated text */ + span.innerHTML = 'm<br />m'; + spanSize = span.offsetWidth; + + /* compare width w/ wrapped w/ delimiter to see if hyphen is present */ + span.innerHTML = 'm' + delimiter + 'm'; + result2 = (span.offsetWidth > spanSize); + } else { + result2 = true; + } + + /* results and cleanup */ + if (result1 === true && result2 === true) { result = true; } + document.body.removeChild(div); + div.removeChild(span); + + return result; + } catch(e) { + return false; + } + } + + // testing if in-browser Find functionality will work on hyphenated text + function test_hyphens_find( delimiter ) { + try { + /* create a dummy input for resetting selection location, and a div container + * these have to be appended to document.body, otherwise some browsers can give false negative + * div container gets the doubled testword, separated by the delimiter + * Note: giving a width to div gives false positive in iOS Safari */ + var dummy = createElement('input'); + var div = createElement('div'); + var testword = 'lebowski'; + var result = false; + var textrange; + var firstChild = document.body.firstElementChild || document.body.firstChild; + + div.innerHTML = testword + delimiter + testword; + + document.body.insertBefore(div, firstChild); + document.body.insertBefore(dummy, div); + + + /* reset the selection to the dummy input element, i.e. BEFORE the div container + * stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area */ + if (dummy.setSelectionRange) { + dummy.focus(); + dummy.setSelectionRange(0,0); + } else if (dummy.createTextRange) { + textrange = dummy.createTextRange(); + textrange.collapse(true); + textrange.moveEnd('character', 0); + textrange.moveStart('character', 0); + textrange.select(); + } + + /* try to find the doubled testword, without the delimiter */ + if (window.find) { + result = window.find(testword + testword); + } else { + try { + textrange = window.self.document.body.createTextRange(); + result = textrange.findText(testword + testword); + } catch(e) { + result = false; + } + } + + document.body.removeChild(div); + document.body.removeChild(dummy); + + return result; + } catch(e) { + return false; + } + } + + addTest("csshyphens", function() { + + if (!testAllProps('hyphens', 'auto', true)) return false; + + /* Chrome lies about its hyphens support so we need a more robust test + crbug.com/107111 + */ + try { + return test_hyphens_css(); + } catch(e) { + return false; + } + }); + + addTest("softhyphens", function() { + try { + // use numeric entity instead of ­ in case it's XHTML + return test_hyphens('­', true) && test_hyphens('​', false); + } catch(e) { + return false; + } + }); + + addTest("softhyphensfind", function() { + try { + return test_hyphens_find('­') && test_hyphens_find('​'); + } catch(e) { + return false; + } + }); + + } + }); + +/*! +{ + "name": "CSS :last-child pseudo-selector", + "caniuse": "css-sel3", + "property": "lastchild", + "tags": ["css"], + "notes": [{ + "name": "Related Github Issue", + "href": "https://github.com/Modernizr/Modernizr/pull/304" + }] +} +!*/ + + testStyles("#modernizr div {width:100px} #modernizr :last-child{width:200px;display:block}", function( elem ) { + Modernizr.addTest('lastchild', elem.lastChild.offsetWidth > elem.firstChild.offsetWidth); + }, 2); + +/*! +{ + "name": "CSS Mask", + "caniuse": "css-masks", + "property": "cssmask", + "tags": ["css"], + "notes": [ + "This is for the -webkit-mask feature, not for the similar svg mask in Firefox.", + { + "name": "Webkit blog on CSS Masks", + "href": "http://www.webkit.org/blog/181/css-masks/" + }, + { + "name": "Safari Docs", + "href": "http://developer.apple.com/library/safari/#documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/Masks/Masks.html" + }, + { + "name": "Mozilla css svg mask (not this)", + "href": "http://developer.mozilla.org/en/CSS/mask" + }, + { + "name": "Combine with clippaths for awesomeness", + "href": "http://generic.cx/for/webkit/test.html" + } + ] +} +!*/ + + Modernizr.addTest('cssmask', testAllProps('maskRepeat', 'repeat-x', true)); + + + // adapted from matchMedia polyfill + // by Scott Jehl and Paul Irish + // gist.github.com/786768 + var testMediaQuery = (function () { + var matchMedia = window.matchMedia || window.msMatchMedia; + if ( matchMedia ) { + return function ( mq ) { + var mql = matchMedia(mq); + return mql && mql.matches || false; + }; + } + + return function ( mq ) { + var bool = false; + + injectElementWithStyles('@media ' + mq + ' { #modernizr { position: absolute; } }', function( node ) { + bool = (window.getComputedStyle ? + window.getComputedStyle(node, null) : + node.currentStyle)['position'] == 'absolute'; + }); + + return bool; + }; + })(); + + + + // Modernizr.mq tests a given media query, live against the current state of the window + // A few important notes: + // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false + // * A max-width or orientation query will be evaluated against the current state, which may change later. + // * You must specify values. Eg. If you are testing support for the min-width media query use: + // Modernizr.mq('(min-width:0)') + // usage: + // Modernizr.mq('only screen and (max-width:768)') + var mq = ModernizrProto.mq = testMediaQuery; + +/*! +{ + "name": "CSS Media Queries", + "caniuse": "css-mediaqueries", + "property": "mediaqueries", + "tags": ["css"] +} +!*/ + + Modernizr.addTest('mediaqueries', mq('only all')); + +/*! +{ + "name": "CSS Multiple Backgrounds", + "caniuse": "multibackgrounds", + "property": "multiplebgs", + "tags": ["css"] +} +!*/ + + // Setting multiple images AND a color on the background shorthand property + // and then querying the style.background property value for the number of + // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! + + Modernizr.addTest('multiplebgs', function() { + var elem = createElement('div'); + var style = elem.style; + style.cssText = 'background:url(https://),url(https://),red url(https://)'; + + // If the UA supports multiple backgrounds, there should be three occurrences + // of the string "url(" in the return value for elemStyle.background + return (/(url\s*\(.*?){3}/).test(style.background); + }); + +/*! +{ + "name": "CSS Object Fit", + "caniuse": "object-fit", + "property": "objectfit", + "tags": ["css"], + "notes": [{ + "name": "Opera Article on Object Fit", + "href": "http://dev.opera.com/articles/view/css3-object-fit-object-position/" + }] +} +!*/ + + Modernizr.addTest('objectfit', !!prefixed('objectFit'), { aliases: ['object-fit'] }); + +/*! +{ + "name": "CSS Opacity", + "caniuse": "css-opacity", + "property": "opacity", + "tags": ["css"], + "notes": ["Opacity must be be in the range of [0.0,1.0], according to the spec."] +} +!*/ + + // Browsers that actually have CSS Opacity implemented have done so + // according to spec, which means their return values are within the + // range of [0.0,1.0] - including the leading zero. + + Modernizr.addTest('opacity', function() { + var elem = createElement('div'); + var style = elem.style; + style.cssText = prefixes.join('opacity:.55;'); + + // The non-literal . in this regex is intentional: + // German Chrome returns this value as 0,55 + // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 + return (/^0.55$/).test(style.opacity); + }); + +/*! +{ + "name": "CSS Overflow Scrolling", + "property": "overflowscrolling", + "tags": ["css"], + "warnings": ["Introduced in iOS5b2. API is subject to change."], + "notes": [{ + "name": "Article on iOS overflow scrolling", + "href": "http://johanbrook.com/browsers/native-momentum-scrolling-ios-5/" + }] +} +!*/ + + Modernizr.addTest('overflowscrolling', testAllProps('overflowScrolling', 'touch', true)); + +/*! +{ + "name": "CSS Pointer Events", + "caniuse": "pointer-events", + "property": "csspointerevents", + "authors": ["ausi"], + "tags": ["css"], + "notes": [ + { + "name": "MDN Docs", + "href": "http://developer.mozilla.org/en/CSS/pointer-events" + },{ + "name": "Test Project Page", + "href": "http://ausi.github.com/Feature-detection-technique-for-pointer-events/" + },{ + "name": "Test Project Wiki", + "href": "http://github.com/ausi/Feature-detection-technique-for-pointer-events/wiki" + }, + { + "name": "Related Github Issue", + "href": "http://github.com/Modernizr/Modernizr/issues/80" + } + ] +} +!*/ + + Modernizr.addTest('csspointerevents', function() { + var element = createElement('x'); + element.style.cssText = 'pointer-events:auto'; + return element.style.pointerEvents === 'auto'; + }); + +/*! +{ + "name": "CSS position: sticky", + "property": "csspositionsticky", + "tags": ["css"] +} +!*/ + + // Sticky positioning - constrains an element to be positioned inside the + // intersection of its container box, and the viewport. + Modernizr.addTest('csspositionsticky', function() { + var prop = 'position:'; + var value = 'sticky'; + var el = createElement('modernizr'); + var mStyle = el.style; + + mStyle.cssText = prop + prefixes.join(value + ';' + prop).slice(0, -prop.length); + + return mStyle.position.indexOf(value) !== -1; + }); + +/*! +{ + "name": "CSS Generated Content Animations", + "property": "csspseudoanimations", + "tags": ["css"] +} +!*/ + + Modernizr.addTest('csspseudoanimations', function () { + var result = false; + + if (!Modernizr.cssanimations || !window.getComputedStyle) { + return result; + } + + var styles = [ + '@', Modernizr._prefixes.join('keyframes csspseudoanimations { from { font-size: 10px; } }@').replace(/\@$/,''), + '#modernizr:before { content:" "; font-size:5px;', + Modernizr._prefixes.join('animation:csspseudoanimations 1ms infinite;'), + '}' + ].join(''); + + Modernizr.testStyles(styles, function (elem) { + result = window.getComputedStyle(elem, ':before').getPropertyValue('font-size') === '10px'; + }); + + return result; + }); + +/*! +{ + "name": "CSS Transitions", + "property": "csstransitions", + "caniuse": "css-transitions", + "tags": ["css"] +} +!*/ + + Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true)); + +/*! +{ + "name": "CSS Generated Content Transitions", + "property": "csspseudotransitions", + "tags": ["css"] +} +!*/ + + Modernizr.addTest('csspseudotransitions', function () { + var result = false; + + if (!Modernizr.csstransitions || !window.getComputedStyle) { + return result; + } + + var styles = + '#modernizr:before { content:" "; font-size:5px;' + Modernizr._prefixes.join('transition:0s 100s;') + '}' + + '#modernizr.trigger:before { font-size:10px; }'; + + Modernizr.testStyles(styles, function (elem) { + // Force rendering of the element's styles so that the transition will trigger + window.getComputedStyle(elem, ':before').getPropertyValue('font-size'); + elem.className += 'trigger'; + result = window.getComputedStyle(elem, ':before').getPropertyValue('font-size') === '5px'; + }); + + return result; + }); + +/*! +{ + "name": "CSS Reflections", + "caniuse": "css-reflections", + "property": "cssreflections", + "tags": ["css"] +} +!*/ + + Modernizr.addTest('cssreflections', testAllProps('boxReflect', 'above', true)); + +/*! +{ + "name": "CSS Regions", + "caniuse": "css-regions", + "authors": ["Mihai Balan"], + "property": "regions", + "tags": ["css"], + "notes": [{ + "name": "W3C Specification", + "href": "http://www.w3.org/TR/css3-regions/" + }] +} +!*/ + + // We start with a CSS parser test then we check page geometry to see if it's affected by regions + // Later we might be able to retire the second part, as WebKit builds with the false positives die out + + Modernizr.addTest('regions', function() { + + /* Get the 'flowFrom' property name available in the browser. Either default or vendor prefixed. + If the property name can't be found we'll get Boolean 'false' and fail quickly */ + var flowFromProperty = Modernizr.prefixed("flowFrom"); + var flowIntoProperty = Modernizr.prefixed("flowInto"); + + if (!flowFromProperty || !flowIntoProperty){ + return false; + } + + /* If CSS parsing is there, try to determine if regions actually work. */ + var container = createElement('div'); + var content = createElement('div'); + var region = createElement('div'); + + /* we create a random, unlikely to be generated flow number to make sure we don't + clash with anything more vanilla, like 'flow', or 'article', or 'f1' */ + var flowName = 'modernizr_flow_for_regions_check'; + + /* First create a div with two adjacent divs inside it. The first will be the + content, the second will be the region. To be able to distinguish between the two, + we'll give the region a particular padding */ + content.innerText = 'M'; + container.style.cssText = 'top: 150px; left: 150px; padding: 0px;'; + region.style.cssText = 'width: 50px; height: 50px; padding: 42px;'; + + region.style[flowFromProperty] = flowName; + container.appendChild(content); + container.appendChild(region); + docElement.appendChild(container); + + /* Now compute the bounding client rect, before and after attempting to flow the + content div in the region div. If regions are enabled, the after bounding rect + should reflect the padding of the region div.*/ + var flowedRect, delta; + var plainRect = content.getBoundingClientRect(); + + + content.style[flowIntoProperty] = flowName; + flowedRect = content.getBoundingClientRect(); + + delta = parseInt(flowedRect.left - plainRect.left, 10); + docElement.removeChild(container); + content = region = container = undefined; + + return (delta == 42); + }); + +/*! +{ + "name": "CSS Font rem Units", + "caniuse": "rem", + "authors": ["nsfmc"], + "property": "cssremunit", + "tags": ["css"], + "notes": [{ + "name": "W3C Spec", + "href": "http://www.w3.org/TR/css3-values/#relative0" + },{ + "name": "Font Size with rem by Jonathan Snook", + "href": "http://snook.ca/archives/html_and_css/font-size-with-rem" + }] +} +!*/ + + // "The 'rem' unit ('root em') is relative to the computed + // value of the 'font-size' value of the root element." + // you can test by checking if the prop was ditched + + Modernizr.addTest('cssremunit', function() { + var div = createElement('div'); + try { + div.style.fontSize = '3rem'; + } + catch( er ) {} + return (/rem/).test(div.style.fontSize); + }); + +/*! +{ + "name": "CSS UI Resize", + "property": "cssresize", + "caniuse": "css-resize", + "tags": ["css"], + "notes": [{ + "name": "W3C Specification", + "href": "http://www.w3.org/TR/css3-ui/#resize" + },{ + "name": "MDN Docs", + "href": "https://developer.mozilla.org/en/CSS/resize" + }] +} +!*/ +/* DOC + +Test for CSS 3 UI "resize" property + +*/ + + Modernizr.addTest('cssresize', testAllProps('resize', 'both', true)); + +/*! +{ + "name": "CSS rgba", + "caniuse": "css3-colors", + "property": "rgba", + "tags": ["css"], + "notes": [{ + "name": "CSSTricks Tutorial", + "href": "http://css-tricks.com/rgba-browser-support/" + }] +} +!*/ + + Modernizr.addTest('rgba', function() { + var elem = createElement('div'); + var style = elem.style; + style.cssText = 'background-color:rgba(150,255,150,.5)'; + + return ('' + style.backgroundColor).indexOf('rgba') > -1; + }); + +/*! +{ + "name": "CSS Stylable Scrollbars", + "property": "cssscrollbar", + "tags": ["css"] +} +!*/ + + testStyles('#modernizr{overflow: scroll; width: 40px; height: 40px; }#' + prefixes + .join('scrollbar{width:0px}'+' #modernizr::') + .split('#') + .slice(1) + .join('#') + 'scrollbar{width:0px}', + function( node ) { + Modernizr.addTest('cssscrollbar', node.scrollWidth == 40); + }); + +/*! +{ + "name": "CSS Shapes", + "property": "shapes", + "tags": ["css"], + "notes": [{ + "name": "CSS Shapes W3C specification", + "href": "http://www.w3.org/TR/css-shapes" + },{ + "name": "Examples from Adobe", + "href": "http://html.adobe.com/webplatform/layout/shapes" + }, { + "name": "Samples showcasing uses of Shapes", + "href": "http://codepen.io/collection/qFesk" + }] +} +!*/ + + Modernizr.addTest('shapes', function () { + var prefixedProperty = prefixed('shapeOutside'); + + if (!prefixedProperty) + return false; + + var shapeOutsideProperty = prefixedProperty.replace(/([A-Z])/g, function (str, m1) { return '-' + m1.toLowerCase(); }).replace(/^ms-/, '-ms-'); + + return testStyles('#modernizr { float: left; ' + shapeOutsideProperty + ':rectangle(0,0,0,0,0,0) }', function (elem) { + // Check against computed value + var styleObj = window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle; + return styleObj[prefixed('shapeOutside', docElement.style, false)] == 'rectangle(0px, 0px, 0px, 0px, 0px, 0px)'; + }); + }); + +/*! +{ + "name": "CSS general sibling selector", + "caniuse": "css-sel3", + "property": "siblinggeneral", + "tags": ["css"], + "notes": [{ + "name": "Related Github Issue", + "href": "https://github.com/Modernizr/Modernizr/pull/889" + }] +} +!*/ + + Modernizr.addTest('siblinggeneral', function(){ + return testStyles('#modernizr div {width:100px} #modernizr div ~ div {width:200px;display:block}', function(elem, rule){ + return elem.lastChild.offsetWidth == 200; + }, 2); + }); + +/*! +{ + "name": "CSS Subpixel Fonts", + "property": "subpixelfont", + "tags": ["css"], + "authors": [ + "@derSchepp", + "@gerritvanaaken", + "@rodneyrehm", + "@yatil", + "@ryanseddon" + ], + "notes": [{ + "name": "Origin Test", + "href": "https://github.com/gerritvanaaken/subpixeldetect" + }] +} +!*/ + + /* + * (to infer if GDI or DirectWrite is used on Windows) + */ + testStyles( + '#modernizr{position: absolute; top: -10em; visibility:hidden; font: normal 10px arial;}#subpixel{float: left; font-size: 33.3333%;}', + function( elem ) { + var subpixel = elem.firstChild; + subpixel.innerHTML = 'This is a text written in Arial'; + Modernizr.addTest('subpixelfont', window.getComputedStyle ? + window.getComputedStyle(subpixel, null).getPropertyValue("width") !== '44px' + : false); + }, 1, ['subpixel']); + +/*! +{ + "name": "CSS Supports", + "property": "supports", + "caniuse": "css-featurequeries", + "tags": ["css"], + "notes": [{ + "name": "W3 Spec", + "href": "http://dev.w3.org/csswg/css3-conditional/#at-supports" + },{ + "name": "Related Github Issue", + "href": "github.com/Modernizr/Modernizr/issues/648" + },{ + "name": "W3 Info", + "href": "http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface" + }] +} +!*/ + + // Relies on the fact that a browser vendor should expose the CSSSupportsRule interface + + Modernizr.addTest('supports', 'CSSSupportsRule' in window); + +/*! +{ + "name": "CSS textshadow", + "property": "textshadow", + "caniuse": "css-textshadow", + "tags": ["css"], + "knownBugs": ["FF3.0 will false positive on this test"] +} +!*/ + + Modernizr.addTest('textshadow', testProp('textShadow', '1px 1px')); + +/*! +{ + "name": "CSS Transforms", + "property": "csstransforms", + "caniuse": "transforms2d", + "tags": ["css"] +} +!*/ + + Modernizr.addTest('csstransforms', testAllProps('transform', 'scale(1)', true)); + +/*!
+{
+ "name": "CSS Transform Style preserve-3d",
+ "property": "preserve3d",
+ "authors": ["edmellum"],
+ "tags": ["css"],
+ "notes": [{
+ "name": "MDN Docs",
+ "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style"
+ },{
+ "name": "Related Github Issue",
+ "href": "https://github.com/Modernizr/Modernizr/issues/762"
+ }]
+}
+!*/
+/* DOC
+
+Detects support for `transform-style: preserve-3d`, for getting a proper 3D perspective on elements.
+
+*/
+
+ Modernizr.addTest('preserve3d', testAllProps('transformStyle', 'preserve-3d'));
+ +/*! +{ + "name": "CSS Transforms 3D", + "property": "csstransforms3d", + "caniuse": "transforms3d", + "tags": ["css"], + "warnings": [ + "Chrome may occassionally fail this test on some systems; more info: https://code.google.com/p/chromium/issues/detail?id=129004" + ] +} +!*/ + + Modernizr.addTest('csstransforms3d', function() { + var ret = !!testAllProps('perspective', '1px', true); + + // Webkit's 3D transforms are passed off to the browser's own graphics renderer. + // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in + // some conditions. As a result, Webkit typically recognizes the syntax but + // will sometimes throw a false positive, thus we must do a more thorough check: + if ( ret && 'webkitPerspective' in docElement.style ) { + + // Webkit allows this media query to succeed only if the feature is enabled. + // `@media (transform-3d),(-webkit-transform-3d){ ... }` + // If loaded inside the body tag and the test element inherits any padding, margin or borders it will fail #740 + testStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:5px;margin:0;padding:0;border:0}}', function( node, rule ) { + ret = node.offsetLeft === 9 && node.offsetHeight === 5; + }); + } + + return ret; + }); + +/*! +{ + "name": "CSS user-select", + "property": "userselect", + "caniuse": "user-select-none", + "authors": ["ryan seddon"], + "tags": ["css"], + "notes": [{ + "name": "Related Modernizr Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/250" + }] +} +!*/ + + //https://github.com/Modernizr/Modernizr/issues/250 + Modernizr.addTest('userselect', testAllProps('userSelect', 'none', true)); + +/*! +{ + "name": "CSS vh unit", + "property": "cssvhunit", + "caniuse": "viewport-units", + "tags": ["css"], + "notes": [{ + "name": "Related Modernizr Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/572" + },{ + "name": "Similar JSFiddle", + "href": "http://jsfiddle.net/FWeinb/etnYC/" + }] +} +!*/ + + testStyles('#modernizr { height: 50vh; }', function( elem, rule ) { + var height = parseInt(window.innerHeight/2,10); + var compStyle = parseInt((window.getComputedStyle ? + getComputedStyle(elem, null) : + elem.currentStyle)['height'],10); + Modernizr.addTest('cssvhunit', compStyle == height); + }); + +/*! +{ + "name": "CSS vmax unit", + "property": "cssvmaxunit", + "caniuse": "viewport-units", + "tags": ["css"], + "notes": [{ + "name": "Related Modernizr Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/572" + },{ + "name": "JSFiddle Example", + "href": "http://jsfiddle.net/glsee/JDsWQ/4/" + }] +} +!*/ + + testStyles('#modernizr { width: 50vmax; }', function( elem, rule ) { + var one_vw = window.innerWidth/100; + var one_vh = window.innerHeight/100; + var compWidth = parseInt((window.getComputedStyle ? + getComputedStyle(elem, null) : + elem.currentStyle)['width'],10); + Modernizr.addTest('cssvmaxunit', parseInt(Math.max(one_vw, one_vh)*50,10) == compWidth ); + }); + +/*! +{ + "name": "CSS vmin unit", + "property": "cssvminunit", + "caniuse": "viewport-units", + "tags": ["css"], + "notes": [{ + "name": "Related Modernizr Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/572" + },{ + "name": "JSFiddle Example", + "href": "http://jsfiddle.net/glsee/JRmdq/8/" + }] +} +!*/ + + testStyles('#modernizr { width: 50vmin; }', function( elem, rule ) { + var one_vw = window.innerWidth/100; + var one_vh = window.innerHeight/100; + var compWidth = parseInt((window.getComputedStyle ? + getComputedStyle(elem, null) : + elem.currentStyle)['width'],10); + Modernizr.addTest('cssvminunit', parseInt(Math.min(one_vw, one_vh)*50,10) == compWidth ); + }); + +/*! +{ + "name": "CSS vw unit", + "property": "cssvwunit", + "caniuse": "viewport-units", + "tags": ["css"], + "notes": [{ + "name": "Related Modernizr Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/572" + },{ + "name": "JSFiddle Example", + "href": "http://jsfiddle.net/FWeinb/etnYC/" + }] +} +!*/ + + testStyles('#modernizr { width: 50vw; }', function( elem, rule ) { + var width = parseInt(window.innerWidth/2,10); + var compStyle = parseInt((window.getComputedStyle ? + getComputedStyle(elem, null) : + elem.currentStyle)['width'],10); + + Modernizr.addTest('cssvwunit', compStyle == width); + }); + +/*! +{ + "name": "CSS wrap-flow", + "property": "wrapflow", + "tags": ["css"], + "notes": [ + "This is a separate test from the rest of CSS Exclusions as as IE10 has just implemented this alone.", + { + "name": "W3C Exclusions spec", + "href": "http://www.w3.org/TR/css3-exclusions" + }, + { + "name": "Example by Adobe", + "href": "http://html.adobe.com/webstandards/cssexclusions" + } + ] +} +!*/ + + Modernizr.addTest('wrapflow', function () { + var prefixedProperty = prefixed('wrapFlow'); + if (!prefixedProperty) + return false; + + var wrapFlowProperty = prefixedProperty.replace(/([A-Z])/g, function (str, m1) { return '-' + m1.toLowerCase(); }).replace(/^ms-/, '-ms-'); + + /* If the CSS parsing is there we need to determine if wrap-flow actually works to avoid false positive cases, e.g. the browser parses + the property, but it hasn't got the implementation for the functionality yet. */ + var container = createElement('div'); + var exclusion = createElement('div'); + var content = createElement('span'); + + /* First we create a div with two adjacent divs inside it. The first div will be the content, the second div will be the exclusion area. + We use the "wrap-flow: end" property to test the actual behavior. (http://dev.w3.org/csswg/css3-exclusions/#wrap-flow-property) + The wrap-flow property is applied to the exclusion area what has a 50px left offset and a 100px width. + If the wrap-flow property is working correctly then the content should start after the exclusion area, so the content's left offset should be 150px. */ + exclusion.style.cssText = 'position: absolute; left: 50px; width: 100px; height: 20px;' + wrapFlowProperty + ':end;'; + content.innerText = 'X'; + + container.appendChild(exclusion); + container.appendChild(content); + docElement.appendChild(container); + + var leftOffset = content.offsetLeft; + + docElement.removeChild(container); + exclusion = content = container = undefined; + + return (leftOffset == 150); + }); + +/*! +{ + "name": "Custom protocol handler", + "property": "customprotocolhandler", + "authors": ["Ben Schwarz"], + "notes": [{ + "name": "WHATWG overview", + "href": "http://developers.whatwg.org/timers.html#custom-handlers" + },{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/Web/API/navigator.registerProtocolHandler" + }], + "warnings": [], + "polyfills": [] +} +!*/ +/* DOC + +Detects support for the `window.registerProtocolHandler()` API to allow web sites to register themselves as possible handlers for particular protocols. + +*/ + + Modernizr.addTest('customprotocolhandler', !!navigator.registerProtocolHandler); + +/*! +{ + "name": "Dart", + "property": "dart", + "authors": ["Theodoor van Donge"], + "notes": [{ + "name": "Language website", + "href": "http://www.dartlang.org/" + }] +} +!*/ +/* DOC + +Detects native support for the Dart programming language. + +*/ + + Modernizr.addTest('dart', !!prefixed('startDart', navigator)); + +/*! +{ + "name": "DataView", + "property": "dataview", + "authors": ["Addy Osmani"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en/JavaScript_typed_arrays/DataView" + }], + "polyfills": ["jdataview"] +} +!*/ +/* DOC + +Detects support for the DataView interface for reading data from an ArrayBuffer as part of the Typed Array spec. + +*/ + + Modernizr.addTest('dataview', (typeof DataView !== 'undefined' && 'getFloat64' in DataView.prototype)); + +/*! +{ + "name": "classList", + "caniuse": "classlist", + "property": "classlist", + "tags": ["dom"], + "notes": [{ + "name": "MDN Docs", + "href": "https://developer.mozilla.org/en/DOM/element.classList" + }] +} +!*/ + + Modernizr.addTest('classlist', 'classList' in docElement); + +/*! +{ + "name": "createElement with Attributes", + "property": ["createelementattrs", "createelement-attrs"], + "tags": ["dom"], + "authors": ["James A. Rosen"], + "notes": [{ + "name": "Related Github Issue", + "href": "https://github.com/Modernizr/Modernizr/issues/258" + }] +} +!*/ + + Modernizr.addTest('createelementattrs', function() { + try { + return createElement('<input name="test" />').getAttribute('name') == 'test'; + } catch( e ) { + return false; + } + }, { + aliases: ['createelement-attrs'] + }); + +/*! +{ + "name": "dataset API", + "caniuse": "dataset", + "property": "dataset", + "tags": ["dom"], + "authors": ["@phiggins42"] +} +!*/ + + // dataset API for data-* attributes + Modernizr.addTest('dataset', function() { + var n = createElement("div"); + n.setAttribute("data-a-b", "c"); + return !!(n.dataset && n.dataset.aB === "c"); + }); + +/*! +{ + "name": "microdata", + "property": "microdata", + "tags": ["dom"], + "notes": [{ + "name": "W3 Spec", + "href": "http://www.w3.org/TR/html5/microdata.html" + }] +} +!*/ + + Modernizr.addTest('microdata', 'getItems' in document); + +/*! +{ + "name": "Drag & Drop", + "property": "draganddrop", + "caniuse": "dragndrop", + "notes": [{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/2010/WD-html5-20101019/dnd.html" + }], + "polyfills": ["dropfile", "moxie", "fileapi"] +} +!*/ +/* DOC + +Detects support for native drag & drop of elements. + +*/ + + Modernizr.addTest('draganddrop', function() { + var div = createElement('div'); + return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); + }); + + + var attrs = {}; + + + var inputattrs = 'autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '); + + + var inputElem = createElement('input'); + +/*! +{ + "name": "Input attributes", + "property": "input", + "tags": ["forms"], + "authors": ["Mike Taylor"], + "notes": [{ + "name": "WHATWG spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary" + }] +} +!*/ +/* 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 + 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"], + "warnings": ["This test is a dupe of Modernizr.input.list. Only around for legacy reasons."], + "notes": [{ + "name": "CSS Tricks Article", + "href": "http://css-tricks.com/15346-relevant-dropdowns-polyfill-for-datalist/" + },{ + "name": "Mike Taylor Test", + "href": "http://miketaylr.com/test/datalist.html" + },{ + "name": "Mike Taylor Code", + "href": "http://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": "details Element", + "caniuse": "details", + "property": "details", + "tags": ["elem"], + "authors": ["@mathias"], + "notes": [{ + "name": "Mathias' Original", + "href": "http://mths.be/axh" + }] +} +!*/ + + Modernizr.addTest('details', function() { + var el = createElement('details'); + var diff; + + // return early if possible; thanks @aFarkas! + if (!('open' in el)) { + return false; + } + + testStyles('#modernizr details{display:block}', function( node ) { + node.appendChild(el); + el.innerHTML = '<summary>a</summary>b'; + diff = el.offsetHeight; + el.open = true; + diff = diff != el.offsetHeight; + }); + + + return diff; + }); + +/*! +{ + "name": "output Element", + "property": "outputelem", + "tags": ["elem"], + "notes": [{ + "name": "WhatWG Spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-output-element" + }] +} +!*/ + + Modernizr.addTest('outputelem', 'value' in createElement('output')); + +/*! +{ + "name": "progress Element", + "caniuse": "progressmeter", + "property": ["progressbar", "meter"], + "tags": ["elem"], + "authors": ["Stefan Wallin"] +} +!*/ + + // Tests for progressbar-support. All browsers that don't support progressbar returns undefined =) + Modernizr.addTest('progressbar', createElement('progress').max !== undefined); + + // Tests for meter-support. All browsers that don't support meters returns undefined =) + Modernizr.addTest('meter', createElement('meter').max !== undefined); + +/*! +{ + "name": "ruby, rp, rt Elements", + "caniuse": "ruby", + "property": "ruby", + "tags": ["elem"], + "authors": ["Cătălin MariÈ™"], + "notes": [{ + "name": "WHATWG Specification", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-ruby-element" + }] +} +!*/ + + Modernizr.addTest('ruby', function () { + + var ruby = createElement('ruby'); + var rt = createElement('rt'); + var rp = createElement('rp'); + var displayStyleProperty = 'display'; + // 'fontSize' - because it`s only used for IE6 and IE7 + var fontSizeStyleProperty = 'fontSize'; + + ruby.appendChild(rp); + ruby.appendChild(rt); + docElement.appendChild(ruby); + + // browsers that support <ruby> hide the <rp> via "display:none" + if ( getStyle(rp, displayStyleProperty) == 'none' || // for non-IE browsers + // but in IE browsers <rp> has "display:inline" so, the test needs other conditions: + getStyle(ruby, displayStyleProperty) == 'ruby' && getStyle(rt, displayStyleProperty) == 'ruby-text' || // for IE8+ + getStyle(rp, fontSizeStyleProperty) == '6pt' && getStyle(rt, fontSizeStyleProperty) == '6pt' ) { // for IE6 & IE7 + + cleanUp(); + return true; + + } else { + cleanUp(); + return false; + } + + function getStyle( element, styleProperty ) { + var result; + + if ( window.getComputedStyle ) { // for non-IE browsers + result = document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProperty); + } else if ( element.currentStyle ) { // for IE + result = element.currentStyle[styleProperty]; + } + + return result; + } + + function cleanUp() { + docElement.removeChild(ruby); + // the removed child node still exists in memory, so ... + ruby = null; + rt = null; + rp = null; + } + + }); + + +/*! +{ + "name": "time Element", + "caniuse": "html5semantic", + "property": "time", + "tags": ["elem"], + "notes": [{ + "name": "WhatWG Spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#the-time-element-0" + }] +} +!*/ + + Modernizr.addTest('time', 'valueAsDate' in createElement('time')); + +/*! +{ + "name": "Track element and Timed Text Track API", + "property": ["texttrackapi", "track"], + "tags": ["elem"], + "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')); + +/*! +{ + "name": "Emoji", + "property": "emoji" +} +!*/ +/* DOC + +Detects support for emoji character sets. + +*/ + + Modernizr.addTest('emoji', function() { + if (!Modernizr.canvastext) return false; + var node = createElement('canvas'), + ctx = node.getContext('2d'); + ctx.textBaseline = 'top'; + ctx.font = '32px Arial'; + ctx.fillText('\ud83d\ude03', 0, 0); // "smiling face with open mouth" emoji + return ctx.getImageData(16, 16, 1, 1).data[0] !== 0; + }); + +/*! +{ + "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"] +} +!*/ +/* DOC + +Check if browser implements ECMAScript 5 Object strict mode. + +*/ + + Modernizr.addTest('strictmode', (function(){ return !this; })()); + +/*! +{ + "name": "ES5 String.prototype.contains", + "property": "contains", + "authors": ["Robert Kowalski"], + "tags": ["es6"] +} +!*/ +/* DOC + +Check if browser implements ECMAScript 6 `String.prototype.contains` per specification. + +*/ + + Modernizr.addTest('contains', is(String.prototype.contains, 'function')); + +/*! +{ + "name": "Device Orientation and Motion Events", + "property": ["devicemotion", "deviceorientation"], + "caniuse": "deviceorientation", + "notes": [{ + "name": "W3C Editor's Draft", + "href": "http://dev.w3.org/geo/api/spec-source-orientation.html" + },{ + "name": "Implementation by iOS Safari (Orientation)", + "href": "http://goo.gl/fhce3" + },{ + "name": "Implementation by iOS Safari (Motion)", + "href": "http://goo.gl/rLKz8" + }], + "authors": ["Shi Chuan"], + "tags": ["event"] +} +!*/ +/* DOC + +Part of Device Access aspect of HTML5, same category as geolocation. + +`devicemotion` tests for Device Motion Event support, returns boolean value true/false. + +`deviceorientation` tests for Device Orientation Event support, returns boolean value true/false + +*/ + + Modernizr.addTest('devicemotion', 'DeviceMotionEvent' in window); + Modernizr.addTest('deviceorientation', 'DeviceOrientationEvent' in window); + + + // isEventSupported determines if the given element supports the given event + // kangax.github.com/iseventsupported/ + // github.com/Modernizr/Modernizr/pull/636 + // + // Known incorrects: + // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative + // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 + var isEventSupported = (function (undefined) { + + // Detect whether event support can be detected via `in`. Test on a DOM element + // using the "blur" event b/c it should always exist. bit.ly/event-detection + var needsFallback = !('onblur' in document.documentElement); + + /** + * @param {string|*} eventName is the name of an event to test for (e.g. "resize") + * @param {(Object|string|*)=} element is the element|document|window|tagName to test on + * @return {boolean} + */ + function isEventSupportedInner( eventName, element ) { + + var isSupported; + if ( !eventName ) { return false; } + if ( !element || typeof element === 'string' ) { + element = createElement(element || 'div'); + } + + // Testing via the `in` operator is sufficient for modern browsers and IE. + // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and + // "resize", whereas `in` "catches" those. + eventName = 'on' + eventName; + isSupported = eventName in element; + + // Fallback technique for old Firefox - bit.ly/event-detection + if ( !isSupported && needsFallback ) { + if ( !element.setAttribute ) { + // Switch to generic element if it lacks `setAttribute`. + // It could be the `document`, `window`, or something else. + element = createElement('div'); + } + if ( element.setAttribute && element.removeAttribute ) { + element.setAttribute(eventName, ''); + isSupported = typeof element[eventName] === 'function'; + + if ( element[eventName] !== undefined ) { + // If property was created, "remove it" by setting value to `undefined`. + element[eventName] = undefined; + } + element.removeAttribute(eventName); + } + } + + return isSupported; + } + return isEventSupportedInner; + })(); + + + + // Modernizr.hasEvent() detects support for a given event, with an optional element to test on + // Modernizr.hasEvent('gesturestart', elem) + var hasEvent = ModernizrProto.hasEvent = isEventSupported; + +/*! +{ + "name": "onInput Event", + "property": "oninput", + "notes": [{ + "name": "MDN article", + "href": "https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.oninput" + },{ + "name": "WHATWG spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#common-event-behaviors" + },{ + "name": "Detecting onInput support", + "href": "http://danielfriesen.name/blog/2010/02/16/html5-browser-maze-oninput-support" + }], + "authors": ["Patrick Kettner"], + "tags": ["event"] +} +!*/ +/* DOC + +`oninput` tests if the browser is able to detect the input event + +*/ + + + Modernizr.addTest('oninput', function() { + var input = createElement('input'); + input.setAttribute("oninput", "return"); + + if (hasEvent('oninput', docElement) || typeof input.oninput == "function") { + return true; + } + + // IE doesn't support onInput, so we wrap up the non IE APIs + // (createEvent, addEventListener) in a try catch, rather than test for + // their trident equivalent. + try { + // Older Firefox didn't map oninput attribute to oninput property + var testEvent = document.createEvent("KeyboardEvent"); + var supportsOnInput = false; + var handler = function(e) { + supportsOnInput = true; + e.preventDefault(); + e.stopPropagation(); + }; + + testEvent.initKeyEvent("keypress", true, true, window, false, false, false, false, 0, "e".charCodeAt(0)); + docElement.appendChild(input); + input.addEventListener("input", handler, false); + input.focus(); + input.dispatchEvent(testEvent); + input.removeEventListener("input", handler, false); + docElement.removeChild(input); + return supportsOnInput; + } catch (e) {} + }); + +/*! +{ + "name": "EXIF Orientation", + "property": "exiforientation", + "tags": ["image"], + "async": true, + "authors": ["Paul Sayre"], + "notes": [{ + "name": "Article by Dave Perrett", + "href": "http://recursive-design.com/blog/2012/07/28/exif-orientation-handling-is-a-ghetto/" + },{ + "name": "Article by Calvin Hass", + "href": "http://www.impulseadventure.com/photo/exif-orientation.html" + }] +} +!*/ +/* DOC + +Detects support for EXIF Orientation in JPEG images. + +iOS looks at the EXIF Orientation flag in JPEGs and rotates the image accordingly. Most desktop browsers just ignore this data. + +*/ + + // Bug trackers: + // bugzil.la/298619 (unimplemented) + // crbug.com/56845 (looks incomplete) + // webk.it/19688 (available upstream but its up all ports to turn on individually) + Modernizr.addAsyncTest(function() { + var img = new Image(); + + img.onerror = function() { + addTest('exiforientation', false, { aliases: ['exif-orientation'] }); + }; + + img.onload = function() { + addTest('exiforientation', img.width !== 2, { aliases: ['exif-orientation'] }); + }; + + // There may be a way to shrink this more, it's a 1x2 white jpg with the orientation flag set to 6 + img.src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q=="; + }); + +/*! +{ + "name": "File API", + "property": "filereader", + "caniuse": "fileapi", + "notes": [{ + "name": "W3C Working Draft", + "href": "http://www.w3.org/TR/FileAPI/" + }], + "tags": ["file"], + "knownBugs": ["Will fail in Safari 5 due to its lack of support for the standards defined FileReader object"] +} +!*/ +/* DOC + +`filereader` tests for the File API specification + +Tests for objects specific to the File API W3C specification without +being redundant (don't bother testing for Blob since it is assumed +to be the File object's prototype.) + +*/ + + Modernizr.addTest('filereader', !!(window.File && window.FileList && window.FileReader)); + +/*! +{ + "name": "Filesystem API", + "property": "filesystem", + "caniuse": "filesystem", + "notes": [{ + "name": "W3 Draft", + "href": "dev.w3.org/2009/dap/file-system/file-dir-sys.html" + }], + "authors": ["Eric Bidelman (@ebidel)"], + "tags": ["file"], + "knownBugs": ["The API will be present in Chrome incognito, but will throw an exception. See crbug.com/93417"] +} +!*/ + + Modernizr.addTest('filesystem', !!prefixed('requestFileSystem', window)); + +/*! +{ + "name": "input[file] Attribute", + "property": "fileinput", + "caniuse" : "forms", + "tags": ["file", "forms", "input"] +} +!*/ +/* DOC + +Detects whether input type="file" is available on the platform + +E.g. iOS < 6 and some android version don't support this + +*/ + + Modernizr.addTest('fileinput', function() { + if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/)) { + return false; + } + var elem = createElement('input'); + elem.type = 'file'; + return !elem.disabled; + }); + +/*! +{ + "name": "input[form] Attribute", + "property": "formattribute", + "tags": ["attribute", "forms", "input"] +} +!*/ +/* DOC + +Detects whether input form="form_id" is available on the platform +E.g. IE 10 (and below), don't support this + +*/ + + + Modernizr.addTest('formattribute', function() { + var form = createElement('form'); + var input = createElement('input'); + var div = createElement('div'); + var id = 'formtest' + (new Date()).getTime(); + var attr; + var bool = false; + + form.id = id; + + //IE6/7 confuses the form idl attribute and the form content attribute, so we use document.createAttribute + try { + input.setAttribute("form", id); + } + catch( e ) { + if( document.createAttribute ) { + attr = document.createAttribute("form"); + attr.nodeValue = id; + input.setAttributeNode(attr); + } + } + + div.appendChild(form); + div.appendChild(input); + + docElement.appendChild(div); + + bool = form.elements.length === 1 && input.form == form; + + div.parentNode.removeChild(div); + return bool; + }); + +/*! +{ + "name": "input[type=\"number\"] Localization", + "property": "localizednumber", + "tags": ["forms", "localization", "attribute"], + "authors": ["Peter Janes"], + "notes": [{ + "name": "Webkit Bug Tracker Listing", + "href": "https://bugs.webkit.org/show_bug.cgi?id=42484" + },{ + "name": "Based on This", + "href": "http://trac.webkit.org/browser/trunk/LayoutTests/fast/forms/script-tests/input-number-keyoperation.js?rev=80096#L9" + }] +} +!*/ +/* DOC + +Detects whether input type="number" is capable of receiving and +displaying localized numbers, e.g. with comma separator + +*/ + + Modernizr.addTest('localizednumber', function() { + var el = createElement('div'); + var diff; + var body = getBody(); + + var root = (function() { + return docElement.insertBefore(body, docElement.firstElementChild || docElement.firstChild); + }()); + el.innerHTML = '<input type="number" value="1.0" step="0.1"/>'; + var input = el.childNodes[0]; + root.appendChild(el); + input.focus(); + try { + document.execCommand('InsertText', false, '1,1'); + } catch(e) { // prevent warnings in IE + } + diff = input.type === 'number' && input.valueAsNumber === 1.1 && input.checkValidity(); + root.removeChild(el); + body.fake && root.parentNode.removeChild(root); + return diff; + }); + + +/*! +{ + "name": "placeholder attribute", + "property": "placeholder", + "tags": ["forms", "attribute"] +} +!*/ +/* DOC + +Tests for placeholder attribute in inputs and textareas + +*/ + + Modernizr.addTest('placeholder', ('placeholder' in createElement('input') && 'placeholder' in createElement('textarea'))); + +/*! +{ + "name": "Speech Input API", + "property": "speechinput", + "tags": ["forms", "speech", "attribute"], + "authors": ["Cătălin MariÈ™"], + "knownBugs": [ + "This detect only checks the webkit version because the Speech Input API was only implemented in Chrome and it was deprecated in favor of the Web Speech API." + ], + "notes": [{ + "name": "W3C Speech Input API Specification", + "href": "http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html" + }], + "warnings": [ + "Do not use the Speech Input API as it was deprecated in favor of the Web Speech API.", + "Only Chrome ever implemented this API, and they are planning to deprecate and remove the related code: https://code.google.com/p/chromium/issues/detail?id=223198." + ] +} +!*/ + + + // `webkitSpeech` in elem doesn`t work correctly in all versions of Chromium based browsers. + // It can return false even if they have support for speech i.imgur.com/2Y40n.png + // Testing with 'onwebkitspeechchange' seems to fix this problem. + + Modernizr.addTest('speechinput', function() { + var elem = createElement('input'); + return 'speech' in elem || 'onwebkitspeechchange' in elem; + }); + +/*! +{ + "name": "Form Validation", + "property": "formvalidation", + "tags": ["forms", "validation", "attribute"] +} +!*/ +/* DOC + +This implementation only tests support for interactive form validation. +To check validation for a specific type or a specific other constraint, +the test can be combined: + +- `Modernizr.inputtypes.number && Modernizr.formvalidation` (browser supports rangeOverflow, typeMismatch etc. for type=number) +- `Modernizr.input.required && Modernizr.formvalidation` (browser supports valueMissing) + +*/ + + Modernizr.addTest('formvalidation', function() { + var form = createElement('form'); + if ( !('checkValidity' in form) || !('addEventListener' in form) ) { + return false; + } + var invaildFired = false; + var input; + + Modernizr.formvalidationapi = true; + + // Prevent form from being submitted + form.addEventListener('submit', function(e) { + //Opera does not validate form, if submit is prevented + if ( !window.opera ) { + e.preventDefault(); + } + e.stopPropagation(); + }, false); + + // Calling form.submit() doesn't trigger interactive validation, + // use a submit button instead + //older opera browsers need a name attribute + form.innerHTML = '<input name="modTest" required><button></button>'; + + testStyles('#modernizr form{position:absolute;top:-99999em}', function( node ) { + node.appendChild(form); + + input = form.getElementsByTagName('input')[0]; + + // Record whether "invalid" event is fired + input.addEventListener('invalid', function(e) { + invaildFired = true; + e.preventDefault(); + e.stopPropagation(); + }, false); + + //Opera does not fully support the validationMessage property + Modernizr.formvalidationmessage = !!input.validationMessage; + + // Submit form by clicking submit button + form.getElementsByTagName('button')[0].click(); + }); + + return invaildFired; + }); + +/*! +{ + "name": "Fullscreen API", + "property": "fullscreen", + "caniuse": "fullscreen", + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en/API/Fullscreen" + }], + "polyfills": ["screenfulljs"] +} +!*/ + + // github.com/Modernizr/Modernizr/issues/739 + Modernizr.addTest('fullscreen', !!(prefixed("exitFullscreen", document, false) || prefixed("cancelFullScreen", document, false))); + +/*! +{ + "name": "GamePad API", + "property": "gamepads", + "authors": ["Eric Bidelman"], + "tags": ["media"], + "notes": [{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/gamepad/" + },{ + "name": "HTML5 Rocks tutorial", + "href": "http://www.html5rocks.com/en/tutorials/doodles/gamepad/#toc-featuredetect" + }], + "warnings": [], + "polyfills": [] +} +!*/ +/* DOC + +Detects support for the Gamepad API, for access to gamepads and controllers. + +*/ + + // FF has Gamepad API support only in special builds, but not in any release (even behind a flag) + // Their current implementation has no way to feature detect, only events to bind to, but a patch + // will bring them up to date with the spec when it lands (and they'll pass this test) + // https://bugzilla.mozilla.org/show_bug.cgi?id=690935 + + Modernizr.addTest('gamepads', !!prefixed('getGamepads', navigator)); + +/*! +{ + "name": "Geolocation API", + "property": "geolocation", + "caniuse": "geolocation", + "tags": ["media"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/WebAPI/Using_geolocation" + }], + "polyfills": [ + "joshuabell-polyfill", + "webshims", + "geolocationshim", + "geo-location-javascript", + "geolocation-api-polyfill" + ] +} +!*/ +/* DOC + +Detects support for the Geolocation API for users to provide their location to web applications. + +*/ + + // geolocation is often considered a trivial feature detect... + // Turns out, it's quite tricky to get right: + // + // Using !!navigator.geolocation does two things we don't want. It: + // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 + // 2. Disables page caching in WebKit: webk.it/43956 + // + // Meanwhile, in Firefox < 8, an about:config setting could expose + // a false positive that would throw an exception: bugzil.la/688158 + + Modernizr.addTest('geolocation', 'geolocation' in navigator); + +/*! +{ + "name": "Hashchange event", + "property": "hashchange", + "caniuse": "hashchange", + "tags": ["history"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/Web/API/window.onhashchange" + }], + "polyfills": [ + "jquery-hashchange", + "moo-historymanager", + "jquery-ajaxy", + "hasher", + "shistory" + ] +} +!*/ +/* DOC + +Detects support for the `hashchange` event, fired when the current location fragment changes. + +*/ + + Modernizr.addTest('hashchange', function() { + if (hasEvent('hashchange', window) === false) { + return false; + } + + // documentMode logic from YUI to filter out IE8 Compat Mode + // which false positives. + return (document.documentMode === undefined || document.documentMode > 7); + }); + +/*! +{ + "name": "History API", + "property": "history", + "caniuse": "history", + "tags": ["history"], + "authors": ["Hay Kranen", "Alexander Farkas"], + "notes": [{ + "name": "W3C Spec", + "href": "http://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 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, stock browser, and not Chrome which identifies + // itself as 'Mobile Safari' as well + if (ua.indexOf('Android 2') !== -1 && + ua.indexOf('Mobile Safari') !== -1 && + ua.indexOf('Chrome') === -1) { + return false; + } + + // Return the regular check + return (window.history && 'pushState' in window.history); + }); + +/*! +{ + "name": "IE8 compat mode", + "property": "ie8compat", + "authors": ["Erich Ocean"] +} +!*/ +/* DOC + +Detects whether or not the current browser is IE8 in compatibility mode (i.e. acting as IE7). + +*/ + + // In this case, IE8 will be acting as IE7. You may choose to remove features in this case. + + // related: + // james.padolsey.com/javascript/detect-ie-in-js-using-conditional-comments/ + + Modernizr.addTest('ie8compat', (!window.addEventListener && !!document.documentMode && document.documentMode === 7)); + +/*! +{ + "name": "iframe[sandbox] Attribute", + "property": "sandbox", + "tags": ["iframe"], + "notes": [{ + "name": "WhatWG Spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox" + }] +} +!*/ +/* DOC + +Test for `sandbox` attribute in iframes. + +*/ + + Modernizr.addTest('sandbox', 'sandbox' in createElement('iframe')); + +/*! +{ + "name": "iframe[seamless] Attribute", + "property": "seamless", + "tags": ["iframe"], + "notes": [{ + "name": "WhatWG Spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-seamless" + }] +} +!*/ +/* DOC + +Test for `seamless` attribute in iframes. + +*/ + + Modernizr.addTest('seamless', 'seamless' in createElement('iframe')); + +/*! +{ + "name": "iframe[srcdoc] Attribute", + "property": "srcdoc", + "tags": ["iframe"], + "notes": [{ + "name": "WhatWG Spec", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-srcdoc" + }] +} +!*/ +/* DOC + +Test for `srcdoc` attribute in iframes. + +*/ + + Modernizr.addTest('srcdoc', 'srcdoc' in createElement('iframe')); + +/*! +{ + "name": "Animated PNG", + "async": true, + "property": "apng", + "tags": ["image"], + "notes": [{ + "name": "Wikipedia Article", + "href": "http://en.wikipedia.org/wiki/APNG" + }] +} +!*/ +/* DOC + +Test for animated png support. + +*/ + + Modernizr.addAsyncTest(function () { + if (!Modernizr.canvas) { + return false; + } + + var image = new Image(); + var canvas = createElement('canvas'); + var ctx = canvas.getContext('2d'); + + image.onload = function () { + addTest('apng', function () { + if (typeof canvas.getContext == 'undefined') { + return false; + } + else { + ctx.drawImage(image, 0, 0); + return ctx.getImageData(0, 0, 1, 1).data[3] === 0; + } + }); + }; + + image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg=="; + }); + +/*! +{ + "name": "Webp Lossless", + "async": true, + "property": ["webplossless", "webp-lossless"], + "tags": ["image"], + "authors": ["@amandeep", "Rich Bradshaw", "Ryan Seddon", "Paul Irish"], + "notes": [{ + "name": "Webp Info", + "href": "http://code.google.com/speed/webp/" + },{ + "name": "Webp Lossless Spec", + "href": "https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification" + }] +} +!*/ +/* DOC + +Tests for non-alpha lossless webp support. + +*/ + + Modernizr.addAsyncTest(function(){ + var image = new Image(); + + image.onerror = function() { + addTest('webplossless', false, { aliases: ['webp-lossless'] }); + }; + + image.onload = function() { + addTest('webplossless', image.width == 1, { aliases: ['webp-lossless'] }); + }; + + image.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA='; + }); + +/*! +{ + "name": "Webp", + "async": true, + "property": "webp", + "tags": ["image"], + "authors": ["Rich Bradshaw", "Ryan Seddon", "Paul Irish"], + "notes": [{ + "name": "Webp Info", + "href": "http://code.google.com/speed/webp/" + }] +} +!*/ +/* DOC + +Tests for lossy, non-alpha webp support. + +*/ + + Modernizr.addAsyncTest(function(){ + var image = new Image(); + + image.onerror = function() { + addTest('webp', false); + }; + + image.onload = function() { + addTest('webp', image.width == 1); + }; + + image.src = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA='; + }); + +/*! +{ + "name": "IndexedDB", + "property": "indexeddb", + "caniuse": "indexeddb", + "tags": ["storage"], + "polyfills": ["indexeddb"] +} +!*/ +/* DOC + +Detects support for the IndexedDB client-side storage API (final spec). + +*/ + + // Vendors had inconsistent prefixing with the experimental Indexed DB: + // - Webkit's implementation is accessible through webkitIndexedDB + // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB + // For speed, we don't test the legacy (and beta-only) indexedDB + + Modernizr.addTest('indexeddb', !!prefixed("indexedDB", window)); + + + var inputtypes = 'search tel url email datetime date month week time datetime-local number range color'.split(' '); + + + var inputs = {}; + + + var smile = ':)'; + +/*! +{ + "name": "Form input types", + "property": "inputtypes", + "caniuse": "forms", + "tags": ["forms"], + "authors": ["Mike Taylor"], + "polyfills": [ + "jquerytools", + "webshims", + "h5f", + "webforms2", + "nwxforms", + "fdslider", + "html5slider", + "galleryhtml5forms", + "jscolor", + "html5formshim", + "jqueryformshim", + "selectedoptionsjs", + "formvalidationjs" + ] +} +!*/ +/* DOC + +Detects support for HTML5 form input types and exposes Boolean subproperties with the results: + +```javascript +Modernizr.inputtypes.color +Modernizr.inputtypes.date +Modernizr.inputtypes.datetime +Modernizr.inputtypes['datetime-local'] +Modernizr.inputtypes.email +Modernizr.inputtypes.month +Modernizr.inputtypes.number +Modernizr.inputtypes.range +Modernizr.inputtypes.search +Modernizr.inputtypes.tel +Modernizr.inputtypes.time +Modernizr.inputtypes.url +Modernizr.inputtypes.week +``` + +*/ + + // Run through HTML5's new input types to see if the UA understands any. + // This is put behind the tests runloop because it doesn't return a + // true/false like all the other tests; instead, it returns an object + // containing each input type with its corresponding true/false value + + // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ + Modernizr['inputtypes'] = (function(props) { + var bool; + var inputElemType; + var defaultView; + var len = props.length; + + for ( var i = 0; i < len; i++ ) { + + inputElem.setAttribute('type', inputElemType = props[i]); + bool = inputElem.type !== 'text'; + + // We first check to see if the type we give it sticks.. + // If the type does, we feed it a textual value, which shouldn't be valid. + // If the value doesn't stick, we know there's input sanitization which infers a custom UI + if ( bool ) { + + inputElem.value = smile; + inputElem.style.cssText = 'position:absolute;visibility:hidden;'; + + if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { + + docElement.appendChild(inputElem); + defaultView = document.defaultView; + + // Safari 2-4 allows the smiley as a value, despite making a slider + bool = defaultView.getComputedStyle && + defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && + // Mobile android web browser has false positive, so must + // check the height to see if the widget is actually there. + (inputElem.offsetHeight !== 0); + + docElement.removeChild(inputElem); + + } else if ( /^(search|tel)$/.test(inputElemType) ){ + // Spec doesn't define any special parsing or detectable UI + // behaviors so we pass these through as true + + // Interestingly, opera fails the earlier test, so it doesn't + // even make it here. + + } else if ( /^(url|email)$/.test(inputElemType) ) { + // Real url and email support comes with prebaked validation. + bool = inputElem.checkValidity && inputElem.checkValidity() === false; + + } else { + // If the upgraded input compontent rejects the :) text, we got a winner + bool = inputElem.value != smile; + } + } + + inputs[ props[i] ] = !!bool; + } + return inputs; + })(inputtypes); + +/*! +{ + "name": "JSON", + "property": "json", + "caniuse": "json", + "notes": [{ + "name": "MDN documentation", + "href": "http://developer.mozilla.org/en/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); + +/*! +{ + "name": "Reverse Ordered Lists", + "property": "olreversed", + "notes": [{ + "name": "Impressive Webs article", + "href": "http://impressivewebs.com/reverse-ordered-lists-html5" + }], + "polyfills": ["impressivewebs"] +} +!*/ +/* DOC + +Detects support for the `reversed` attribute on the `<ol>` element. + +*/ + + Modernizr.addTest('olreversed', 'reversed' in createElement('ol')); + +/*! +{ + "name": "MathML", + "property": "mathml", + "caniuse": "mathml", + "authors": ["Addy Osmani", "Davide P. Cervone", "David Carlisle"], + "notes": [{ + "name": "W3C spec", + "href": "http://www.w3.org/Math/" + }], + "polyfills": ["mathjax"] +} +!*/ +/* DOC + +Detects support for MathML, for mathematic equations in web pages. + +*/ + + // Based on work by Davide (@dpvc) and David (@davidcarlisle) + // in https://github.com/mathjax/MathJax/issues/182 + + Modernizr.addTest('mathml', function() { + var ret; + + Modernizr.testStyles("#modernizr{position:absolute}", function(node){ + node.innerHTML = "<math><mfrac><mi>xx</mi><mi>yy</mi></mfrac></math>"; + + ret = node.offsetHeight > node.offsetWidth; + }); + + return ret; + }); + +/*! +{ + "name": "Low Bandwidth Connection", + "property": "lowbandwidth", + "tags": ["network"] +} +!*/ +/* DOC + +Tests for determining low-bandwidth via `navigator.connection` + +There are two iterations of the `navigator.connection` interface. + +The first is present in Android 2.2+ and only in the Browser (not WebView) + +- http://docs.phonegap.com/en/1.2.0/phonegap_connection_connection.md.html#connection.type +- http://davidbcalhoun.com/2010/using-navigator-connection-android + +The second is specced at http://dev.w3.org/2009/dap/netinfo/ and perhaps landing in WebKit + +- http://bugs.webkit.org/show_bug.cgi?id=73528 + +Unknown devices are assumed as fast + +For more rigorous network testing, consider boomerang.js: http://github.com/bluesmoon/boomerang/ + +*/ + + Modernizr.addTest('lowbandwidth', function() { + // polyfill + var connection = navigator.connection || { type: 0 }; + + return connection.type == 3 || // connection.CELL_2G + connection.type == 4 || // connection.CELL_3G + /^[23]g$/.test(connection.type); // string value in new spec + }); + +/*! +{ + "name": "Server Sent Events", + "property": "eventsource", + "tags": ["network"], + "notes": [{ + "name": "W3 Spec", + "href": "http://dev.w3.org/html5/eventsource/" + }] +} +!*/ +/* DOC + +Tests for server sent events aka eventsource. + +*/ + + Modernizr.addTest('eventsource', 'EventSource' in window); + +/*! +{ + "name": "XML HTTP Request Level 2 XHR2", + "property": "xhr2", + "tags": ["network"], + "notes": [{ + "name": "W3 Spec", + "href": "http://www.w3.org/TR/XMLHttpRequest2/" + },{ + "name": "Details on Related Github Issue", + "href": "http://github.com/Modernizr/Modernizr/issues/385" + }] +} +!*/ +/* DOC + +Tests for XHR2. +*/ + + // all three of these details report consistently across all target browsers: + // !!(window.ProgressEvent); + // !!(window.FormData); + // window.XMLHttpRequest && "withCredentials" in new XMLHttpRequest; + Modernizr.addTest('xhr2', 'FormData' in window); + + + // http://mathiasbynens.be/notes/xhr-responsetype-json#comment-4 + var testXhrType = function(type) { + if (typeof XMLHttpRequest == 'undefined') { + return false; + } + var xhr = new XMLHttpRequest(); + xhr.open('get', '/', true); + try { + xhr.responseType = type; + } catch(error) { + return false; + } + return 'response' in xhr && xhr.responseType == type; + }; + + +/*! +{ + "name": "XMLHttpRequest xhr.responseType='arraybuffer'", + "property": "xhrresponsetypearraybuffer", + "tags": ["network"], + "notes": [{ + "name": "XMLHttpRequest Living Standard", + "href": "http://xhr.spec.whatwg.org/#the-responsetype-attribute" + }] +} +!*/ +/* DOC + +Tests for XMLHttpRequest xhr.responseType='arraybuffer'. + +*/ + + Modernizr.addTest('xhrresponsetypearraybuffer', testXhrType('arraybuffer')); + +/*! +{ + "name": "XMLHttpRequest xhr.responseType='document'", + "property": "xhrresponsetypedocument", + "tags": ["network"], + "notes": [{ + "name": "XMLHttpRequest Living Standard", + "href": "http://xhr.spec.whatwg.org/#the-responsetype-attribute" + }] +} +!*/ +/* DOC + +Tests for XMLHttpRequest xhr.responseType='document'. + +*/ + + Modernizr.addTest('xhrresponsetypedocument', testXhrType('document')); + +/*! +{ + "name": "XMLHttpRequest xhr.responseType='json'", + "property": "xhrresponsetypejson", + "tags": ["network"], + "notes": [{ + "name": "XMLHttpRequest Living Standard", + "href": "http://xhr.spec.whatwg.org/#the-responsetype-attribute" + },{ + "name": "Explanation of xhr.responseType='json'", + "href": "http://mathiasbynens.be/notes/xhr-responsetype-json" + }] +} +!*/ +/* DOC + +Tests for XMLHttpRequest xhr.responseType='json'. + +*/ + + Modernizr.addTest('xhrresponsetypejson', testXhrType('json')); + +/*! +{ + "name": "XMLHttpRequest xhr.responseType='text'", + "property": "xhrresponsetypetext", + "tags": ["network"], + "notes": [{ + "name": "XMLHttpRequest Living Standard", + "href": "http://xhr.spec.whatwg.org/#the-responsetype-attribute" + }] +} +!*/ +/* DOC + +Tests for XMLHttpRequest xhr.responseType='text'. + +*/ + + Modernizr.addTest('xhrresponsetypetext', testXhrType('text')); + +/*! +{ + "name": "XMLHttpRequest xhr.responseType", + "property": "xhrresponsetype", + "tags": ["network"], + "notes": [{ + "name": "XMLHttpRequest Living Standard", + "href": "http://xhr.spec.whatwg.org/#the-responsetype-attribute" + }] +} +!*/ +/* DOC + +Tests for XMLHttpRequest xhr.responseType. + +*/ + + Modernizr.addTest('xhrresponsetype', (function() { + if (typeof XMLHttpRequest == 'undefined') { + return false; + } + var xhr = new XMLHttpRequest(); + xhr.open('get', '/', true); + return 'response' in xhr; + }())); + +/*! +{ + "name": "Notification", + "property": "notification", + "caniuse": "notifications", + "authors": ["Theodoor van Donge", "Hendrik Beskow"], + "notes": [{ + "name": "HTML5 Rocks tutorial", + "href": "http://www.html5rocks.com/en/tutorials/notifications/quick/" + },{ + "name": "W3C spec", + "href": "www.w3.org/TR/notifications/" + }], + "polyfills": ["desktop-notify", "html5-notifications"] +} +!*/ +/* DOC + +Detects support for the Notifications API + +*/ + + Modernizr.addTest('notification', 'Notification' in window && 'permission' in window.Notification && 'requestPermission' in window.Notification); + +/*! +{ + "name": "Page Visibility API", + "property": "pagevisibility", + "caniuse": "pagevisibility", + "tags": ["performance"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/DOM/Using_the_Page_Visibility_API" + },{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/2011/WD-page-visibility-20110602/" + },{ + "name": "HTML5 Rocks tutorial", + "href": "http://www.html5rocks.com/en/tutorials/pagevisibility/intro/" + }], + "polyfills": ["visibilityjs", "visiblyjs", "jquery-visibility"] +} +!*/ +/* DOC + +Detects support for the Page Visibility API, which can be used to disable unnecessary actions and otherwise improve user experience. + +*/ + + Modernizr.addTest('pagevisibility', !!prefixed("hidden", document, false)); + +/*! +{ + "name": "Navigation Timing API", + "property": "performance", + "caniuse": "nav-timing", + "tags": ["performance"], + "authors": ["Scott Murphy (@uxder)"], + "notes": [{ + "name": "W3C Spec", + "href": "http://www.w3.org/TR/navigation-timing/" + },{ + "name": "HTML5 Rocks article", + "href": "http://www.html5rocks.com/en/tutorials/webperformance/basics/" + }], + "polyfills": ["perfnow"] +} +!*/ +/* DOC + +Detects support for the Navigation Timing API, for measuring browser and connection performance. + +*/ + + Modernizr.addTest('performance', !!prefixed('performance', window)); + +/*! +{ + "name": "DOM Pointer Events API", + "property": "pointerevents", + "tags": ["input"], + "authors": ["Stu Cox"], + "notes": [ + "This property name used to refer to the CSS `pointer-events` property, which is now named `csspointerevents`.", + { + "name": "W3C spec submission", + "href": "http://www.w3.org/Submission/pointer-events/" + } + ], + "warnings": ["This property name now refers to W3C DOM PointerEvents: https://github.com/Modernizr/Modernizr/issues/548#issuecomment-12812099"], + "polyfills": ["handjs"] +} +!*/ +/* DOC + +Detects support for the DOM Pointer Events API, which provides a unified event interface for pointing input devices, as implemented in IE10+. + +*/ + + // **Test name hijacked!** + // Now refers to W3C DOM PointerEvents spec rather than the CSS pointer-events property. + Modernizr.addTest('pointerevents', function () { + // Cannot use `.prefixed()` for events, so test each prefix + var bool = false, + i = domPrefixes.length; + + // Don't forget un-prefixed... + bool = Modernizr.hasEvent('pointerdown'); + + while (i-- && !bool) { + if (hasEvent(domPrefixes[i] + 'pointerdown')) { + bool = true; + } + } + return bool; + }); + +/*! +{ + "name": "Pointer Lock API", + "property": "pointerlock", + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/API/Pointer_Lock_API" + }] +} +!*/ + + // https://developer.mozilla.org/en-US/docs/API/Pointer_Lock_API + Modernizr.addTest('pointerlock', !!prefixed('exitPointerLock', document)); + +/*! +{ + "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": "Quota Storage Management API", + "property": "quotamanagement", + "tags": ["storage"], + "notes": [{ + "name": "W3C Spec", + "href": "http://www.w3.org/TR/quota-api/" + }] +} +!*/ +/* DOC + + + +*/ + + Modernizr.addTest('quotamanagement', function() { + var tempStorage = prefixed('temporaryStorage', navigator); + var persStorage = prefixed('persistentStorage', navigator); + + return !!(tempStorage && persStorage); + }); + +/*! +{ + "name": "requestAnimationFrame", + "property": "requestanimationframe", + "aliases": ["raf"], + "caniuse": "requestanimationframe", + "tags": ["animation"], + "authors": ["Addy Osmani"], + "notes": [{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/animation-timing/" + }], + "polyfills": ["raf"] +} +!*/ +/* DOC + +Detects support for the `window.requestAnimationFrame` API, for offloading animation repainting to the browser for optimized performance. + +*/ + + Modernizr.addTest('requestanimationframe', !!prefixed('requestAnimationFrame', window), { aliases: ['raf'] }); + +/*! +{ + "name": "script[async]", + "property": "scriptasync", + "caniuse": "script-async", + "tags": ["script"], + "authors": ["Theodoor van Donge"] +} +!*/ +/* DOC + +Detects support for the `async` attribute on the `<script>` element. + +*/ + + Modernizr.addTest('scriptasync', 'async' in createElement('script')); + +/*! +{ + "name": "script[defer]", + "property": "scriptdefer", + "caniuse": "script-defer", + "tags": ["script"], + "authors": ["Theodoor van Donge"], + "warnings": ["Browser implementation of the `defer` attribute vary: http://stackoverflow.com/questions/3952009/defer-attribute-chrome#answer-3982619"] +} +!*/ +/* DOC + +Detects support for the `defer` attribute on the `<script>` element. + +*/ + + Modernizr.addTest('scriptdefer', 'defer' in createElement('script')); + +/*! +{ + "name": "ServiceWorker API", + "property": "serviceworker", + "notes": [{ + "name": "ServiceWorkers Explained", + "href": "https://developer.mozilla.org/en-US/docs/WebAPI/Using_geolocation" + }] +} +!*/ +/* DOC + +ServiceWorkers (formerly Navigation Controllers) are a way to persistently cache resources to built apps that work better offline. + +*/ + + Modernizr.addTest('serviceworker', 'serviceWorker' in navigator); + +/*! +{ + "authors": ["Cătălin MariÈ™"], + "name": "Speech Recognition API", + "notes": [ + { + "name": "W3C Web Speech API Specification - The SpeechRecognition Interface", + "href": "https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechreco-section" + }, + { + "name": "Introduction to the Web Speech API", + "href": "http://updates.html5rocks.com/2013/01/Voice-Driven-Web-Apps-Introduction-to-the-Web-Speech-API" + } + ], + "property": "speechrecognition", + "tags": ["input", "speech"] +} +!*/ + + + Modernizr.addTest('speechrecognition', !!prefixed('SpeechRecognition', window)); + +/*! +{ + "authors": ["Cătălin MariÈ™"], + "name": "Speech Synthesis API", + "notes": [ + { + "name": "W3C Web Speech API Specification - The SpeechSynthesis Interface", + "href": "https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section" + } + ], + "property": "speechsynthesis", + "tags": ["input", "speech"] +} +!*/ + + + Modernizr.addTest('speechsynthesis', 'SpeechSynthesisUtterance' in window); + +/*! +{ + "name": "Local Storage", + "property": "localstorage", + "caniuse": "namevalue-storage", + "tags": ["storage"], + "knownBugs": [], + "notes": [], + "warnings": [], + "polyfills": [ + "joshuabell-polyfill", + "cupcake", + "storagepolyfill", + "amplifyjs", + "yui-cacheoffline", + "textstorage" + ] +} +!*/ + + // 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 + + // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem + // will throw the exception: + // QUOTA_EXCEEDED_ERRROR 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; + } + }); + +/*! +{ + "name": "Session Storage", + "property": "sessionstorage", + "tags": ["storage"], + "polyfills": ["joshuabell-polyfill", "cupcake", "sessionstorage"] +} +!*/ + + // 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('sessionstorage', function() { + var mod = 'modernizr'; + try { + sessionStorage.setItem(mod, mod); + sessionStorage.removeItem(mod); + return true; + } catch(e) { + return false; + } + }); + +/*! +{ + "name": "Web SQL Database", + "property": "websqldatabase", + "caniuse": "sql-storage", + "tags": ["storage"] +} +!*/ + + // Chrome incognito mode used to throw an exception when using openDatabase + // It doesn't anymore. + Modernizr.addTest('websqldatabase', 'openDatabase' in window); + +/*! +{ + "name": "style[scoped]", + "property": "stylescoped", + "caniuse": "style-scoped", + "tags": ["dom"], + "authors": ["Cătălin MariÈ™"], + "notes": [{ + "name": "WHATWG Specification", + "href": "http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#attr-style-scoped" + }], + "polyfills": ["scoped-styles"] +} +!*/ +/* DOC + +Support for the `scoped` attribute of the `<style>` element. + +*/ + + Modernizr.addTest('stylescoped', 'scoped' in createElement('style')); + +/*! +{ + "name": "SVG as an <img> tag source", + "property": "svgasimg", + "caniuse" : "svg-img", + "tags": ["svg"], + "authors": ["Stu Cox"], + "async" : true, + "notes": [{ + "name": "HTML5 Spec", + "href": "http://www.w3.org/TR/html5/embedded-content-0.html#the-img-element" + }] +} +!*/ + + // Assumes data URI support, but according to caniuse every browser which + // supports SVG in an <img> also supports data URIs + Modernizr.addAsyncTest(function () { + var img = new Image(); + + img.onerror = function () { + addTest('svgasimg', false); + }; + img.onload = function () { + addTest('svgasimg', img.width == 1 && img.height == 1); + }; + + // 1px x 1px SVG; must be base64 or URI encoded for IE9... base64 is shorter + img.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg=='; + }); + + + var toStringFn = ({}).toString; + +/*! +{ + "name": "SVG clip paths", + "property": "svgclippaths", + "tags": ["svg"], + "notes": [{ + "name": "Demo", + "href": "http://srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg" + }] +} +!*/ +/* DOC + +Detects support for clip paths in SVG (only, not on HTML content). + +See [this discussion](http://github.com/Modernizr/Modernizr/issues/213) regarding applying SVG clip paths to HTML content. + +*/ + + Modernizr.addTest('svgclippaths', function() { + return !!document.createElementNS && + /SVGClipPath/.test(toStringFn.call(document.createElementNS('http://www.w3.org/2000/svg', 'clipPath'))); + }); + +/*! +{ + "name": "SVG filters", + "property": "svgfilters", + "caniuse": "svg-filters", + "tags": ["svg"], + "authors": ["Erik Dahlstrom"], + "notes": [{ + "name": "W3C Spec", + "href": "http://www.w3.org/TR/SVG11/filters.html" + }] +} +!*/ + + // Should fail in Safari: http://stackoverflow.com/questions/9739955/feature-detecting-support-for-svg-filters. + Modernizr.addTest('svgfilters', function() { + var result = false; + try { + result = typeof SVGFEColorMatrixElement !== undefined && + SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE == 2; + } + catch(e) {} + return result; + }); + +/*! +{ + "name": "Inline SVG", + "property": "inlinesvg", + "caniuse": "svg-html5", + "tags": ["svg"], + "notes": [{ + "name": "Test page", + "href": "http://paulirish.com/demo/inline-svg" + }], + "polyfills": ["inline-svg-polyfill"] +} +!*/ +/* DOC + +Detects support for inline SVG in HTML (not within XHTML). + +*/ + + Modernizr.addTest('inlinesvg', function() { + var div = createElement('div'); + div.innerHTML = '<svg/>'; + return (div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg'; + }); + +/*! +{ + "name": "SVG SMIL animation", + "property": "smil", + "caniuse": "svg-smil", + "tags": ["svg"], + "notes": [{ + "name": "W3C Synchronised Multimedia spec", + "href": "http://www.w3.org/AudioVideo/" + }] +} +!*/ + + // SVG SMIL animation + Modernizr.addTest('smil', function() { + return !!document.createElementNS && + /SVGAnimate/.test(toStringFn.call(document.createElementNS('http://www.w3.org/2000/svg', 'animate'))); + }); + +/*! +{ + "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": "Touch Events", + "property": "touchevents", + "caniuse" : "touch", + "tags": ["media", "attribute"], + "notes": [{ + "name": "Touch Events spec", + "href": "http://www.w3.org/TR/2013/WD-touch-events-20130124/" + }], + "warnings": [ + "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device" + ], + "knownBugs": [ + "False-positive on some configurations of Nokia N900", + "False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695" + ] +} +!*/ +/* DOC + +Indicates if the browser supports the W3C Touch Events API. + +This *does not* necessarily reflect a touchscreen device: + +* Older touchscreen devices only emulate mouse events +* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that +* Some browsers & OS setups may enable touch APIs when no touchscreen is connected +* Future browsers may implement other event models for touch interactions + +See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/). + +It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/). + +This test will also return `true` for Firefox 4 Multitouch support. + +*/ + + // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415 + Modernizr.addTest('touchevents', function() { + var bool; + if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { + bool = true; + } else { + var query = ['@media (',prefixes.join('touch-enabled),('),'heartz',')','{#modernizr{top:9px;position:absolute}}'].join(''); + testStyles(query, function( node ) { + bool = node.offsetTop === 9; + }); + } + return bool; + }); + +/*! +{ + "name": "Typed arrays", + "property": "typedarrays", + "caniuse": "typedarrays", + "tags": ["js"], + "authors": ["Stanley Stuart (@fivetanley)"], + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/JavaScript_typed_arrays" + },{ + "name": "Kronos spec", + "href": "http://www.khronos.org/registry/typedarray/specs/latest/" + }], + "polyfills": ["joshuabell-polyfill"] +} +!*/ +/* DOC + +Detects support for native binary data manipulation via Typed Arrays in JavaScript. + +Does not check for DataView support; use `Modernizr.dataview` for that. + +*/ + + // Should fail in: + // Internet Explorer <= 9 + // Firefox <= 3.6 + // Chrome <= 6.0 + // iOS Safari < 4.2 + // Safari < 5.1 + // Opera < 11.6 + // Opera Mini, <= 7.0 + // Android Browser < 4.0 + // Blackberry Browser < 10.0 + + Modernizr.addTest('typedarrays', 'ArrayBuffer' in window ); + +/*! +{ + "name": "Unicode characters", + "property": "unicode", + "tags": ["encoding"], + "warnings": [ + "positive Unicode support doesn't mean you can use it inside <title>, this seams more related to OS & Language packs" + ] +} +!*/ +/* DOC + +Detects if unicode characters are supported in the current document. + +*/ + + /** + * Unicode special character support + * + * Detection is made by testing missing glyph box rendering against star character + * If widths are the same, this "probably" means the browser didn't support the star character and rendered a glyph box instead + * Just need to ensure the font characters have different widths + */ + Modernizr.addTest('unicode', function() { + var bool; + var missingGlyph = createElement('span'); + var star = document.createElement('span'); + + testStyles('#modernizr{font-family:Arial,sans;font-size:300em;}', function( node ) { + + missingGlyph.innerHTML = 'ᝣ'; + star.innerHTML = '☆'; + + node.appendChild(missingGlyph); + node.appendChild(star); + + bool = 'offsetWidth' in missingGlyph && missingGlyph.offsetWidth !== star.offsetWidth; + }); + + return bool; + + }); + +/*! +{ + "name": "Data URI", + "property": "datauri", + "caniuse": "datauri", + "tags": ["url"], + "async": true, + "notes": [{ + "name": "Wikipedia article", + "href": "http://en.wikipedia.org/wiki/Data_URI_scheme" + }], + "warnings": ["Support in Internet Explorer 8 is limited to images and linked resources like CSS files, not HTML files"] +} +!*/ +/* DOC + +Detects support for data URIs. Provides a subproperty to report support for data URIs over 32kb in size: + +```javascript +Modernizr.datauri // true +Modernizr.datauri.over32kb // false in IE8 +``` + +*/ + + // https://github.com/Modernizr/Modernizr/issues/14 + Modernizr.addAsyncTest(function() { + /* jshint -W053 */ + + // IE7 throw a mixed content warning on HTTPS for this test, so we'll + // just blacklist it (we know it doesn't support data URIs anyway) + // https://github.com/Modernizr/Modernizr/issues/362 + if(navigator.userAgent.indexOf('MSIE 7.') !== -1) { + // Keep the test async + setTimeout(function () { + addTest('datauri', false); + }, 10); + } + + var datauri = new Image(); + + datauri.onerror = function() { + addTest('datauri', false); + }; + datauri.onload = function() { + if(datauri.width == 1 && datauri.height == 1) { + testOver32kb(); + } + else { + addTest('datauri', false); + } + }; + + datauri.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; + + // Once we have datauri, let's check to see if we can use data URIs over + // 32kb (IE8 can't). https://github.com/Modernizr/Modernizr/issues/321 + function testOver32kb(){ + + var datauriBig = new Image(); + + datauriBig.onerror = function() { + addTest('datauri', true); + Modernizr.datauri = new Boolean(true); + Modernizr.datauri.over32kb = false; + }; + datauriBig.onload = function() { + addTest('datauri', true); + Modernizr.datauri = new Boolean(true); + Modernizr.datauri.over32kb = (datauriBig.width == 1 && datauriBig.height == 1); + }; + + var base64str = "R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; + while (base64str.length < 33000) { + base64str = "\r\n" + base64str; + } + datauriBig.src= "data:image/gif;base64," + base64str; + } + + }); + +/*! +{ + "name": "IE User Data API", + "property": "userdata", + "tags": ["storage"], + "authors": ["@stereobooster"], + "notes": [{ + "name": "MSDN Documentation", + "href": "http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx" + }] +} +!*/ +/* DOC + +Detects support for IE userData for persisting data, an API similar to localStorage but supported since IE5. + +*/ + + Modernizr.addTest('userdata', !!createElement('div').addBehavior); + +/*! +{ + "name": "Vibration API", + "property": "vibrate", + "notes": [{ + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en/DOM/window.navigator.mozVibrate" + },{ + "name": "W3C spec", + "href": "http://www.w3.org/TR/vibration/" + }] +} +!*/ +/* DOC + +Detects support for the API that provides access to the vibration mechanism of the hosting device, to provide tactile feedback. + +*/ + + Modernizr.addTest('vibrate', !!prefixed('vibrate', navigator)); + +/*! +{ + "name": "HTML5 Video", + "property": "video", + "caniuse": "video", + "tags": ["html5"], + "knownBugs": [ + "Without QuickTime, `Modernizr.video.h264` will be `undefined`; http://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() { + /* jshint -W053 */ + var elem = createElement('video'); + var bool = false; + + // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 + try { + if ( bool = !!elem.canPlayType ) { + 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$/,''); + } + } catch(e){} + + return bool; + }); + +/*! +{ + "name": "Web Animation API", + "property": "animation", + "tags": ["webanimations"], + "polyfills": ["webanimationsjs"], + "notes": { + "name": "Introducing Web Animations", + "href": "http://brian.sol1.net/svg/2013/06/26/introducing-web-animations/" + } +} +!*/ +/* DOC + +Detects support for the Web Animation API, a way to create css animations in js + +*/ + + Modernizr.addTest('webanimations', 'Animation' in window); + +/*! +{ + "name": "Web Intents", + "property": "webintents", + "authors": ["Eric Bidelman"], + "notes": [{ + "name": "Web Intents project site", + "href": "http://webintents.org/" + }], + "polyfills": ["webintents"] +} +!*/ +/* DOC + +Detects native support for the Web Intents APIs for service discovery and inter-application communication. + +Chrome added support for this in v19, but [removed it again in v24](http://lists.w3.org/Archives/Public/public-web-intents/2012Nov/0000.html) because of "a number of areas for +development in both the API and specific user experience in Chrome". No other browsers currently support it, however a [JavaScript shim](http://webintents.org/#javascriptshim) is available. + +*/ + + Modernizr.addTest('webintents', !!prefixed('startActivity', navigator)); + +/*! +{ + "name": "WebGL", + "property": "webgl", + "caniuse": "webgl", + "tags": ["webgl", "graphics"], + "polyfills": ["jebgl", "webglcompat", "cwebgl", "iewebgl"] +} +!*/ + + // webk.it/70117 is tracking a legit WebGL feature detect proposal + Modernizr.addTest('webgl', 'WebGLRenderingContext' in window); + +/*! +{ + "name": "WebGL Extensions", + "property": "webglextensions", + "tags": ["webgl", "graphics"], + "async" : true, + "authors": ["Ilmari Heikkinen"], + "knownBugs": [], + "notes": [{ + "name": "Kronos extensions registry", + "href": "http://www.khronos.org/registry/webgl/extensions/" + }] +} +!*/ +/* DOC + +Detects support for OpenGL extensions in WebGL. It's `true` if the [WebGL extensions API](https://developer.mozilla.org/en-US/docs/Web/WebGL/Using_Extensions) is supported, then exposes the supported extensions as subproperties, e.g.: + +```javascript +if (Modernizr.webglextensions) { + // WebGL extensions API supported +} +if ('OES_vertex_array_object' in Modernizr.webglextensions) { + // Vertex Array Objects extension supported +} +``` + +*/ + + // based on code from ilmari heikkinen + // code.google.com/p/graphics-detect/source/browse/js/detect.js + + // Not Async but handles it's own self + Modernizr.addAsyncTest(function() { + /* jshint -W053 */ + + // Not a good candidate for css classes, so we avoid addTest stuff + Modernizr.webglextensions = new Boolean(false); + + if (!Modernizr.webgl) { + return; + } + + var canvas; + var ctx; + var exts; + + try { + canvas = createElement('canvas'); + ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + exts = ctx.getSupportedExtensions(); + } + catch (e) { + return; + } + + if (ctx !== undefined) { + Modernizr.webglextensions = new Boolean(true); + } + + for (var i = -1, len = exts.length; ++i < len; ){ + Modernizr.webglextensions[exts[i]] = true; + } + + canvas = undefined; + }); + +/*! +{ + "name": "getUserMedia", + "property": "getusermedia", + "caniuse": "stream", + "tags": ["webrtc"], + "authors": ["Eric Bidelman"], + "notes": [{ + "name": "W3C Media Capture and Streams spec", + "href": "http://www.w3.org/TR/mediacapture-streams/" + }], + "polyfills": ["getusermedia"] +} +!*/ + + Modernizr.addTest('getusermedia', !!prefixed('getUserMedia', navigator)); + +/*! +{ + "name": "RTC Peer Connection", + "property": "peerconnection", + "tags": ["webrtc"], + "authors": ["Ankur Oberoi"], + "notes": [{ + "name": "W3C Web RTC spec", + "href": "http://www.w3.org/TR/webrtc/" + }] +} +!*/ + + Modernizr.addTest('peerconnection', !!prefixed('RTCPeerConnection', window)); + +/*! +{ + "name": "Binary WebSockets", + "property": "websocketsbinary", + "tags": ["websockets"] +} +!*/ + + // binaryType is truthy if there is support.. returns "blob" in new-ish chrome. + // plus.google.com/115535723976198353696/posts/ERN6zYozENV + // github.com/Modernizr/Modernizr/issues/370 + + Modernizr.addTest('websocketsbinary', function() { + var protocol = 'https:'==location.protocol?'wss':'ws', + protoBin; + + if("WebSocket" in window) { + if( protoBin = "binaryType" in WebSocket.prototype ) { + return protoBin; + } + try { + return !!(new WebSocket(protocol+'://.').binaryType); + } catch (e){} + } + + return false; + }); + +/*! +{ + "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": "http://www.w3.org/TR/websockets/#the-websocket-interface" + }], + "polyfills": [ + "sockjs", + "socketio", + "kaazing-websocket-gateway", + "websocketjs", + "atmosphere", + "graceful-websocket", + "portal", + "datachannel" + ] +} +!*/ + + Modernizr.addTest('websockets', 'WebSocket' in window && window.WebSocket.CLOSING === 2); + +/*! +{ + "name": "Framed window", + "property": "framed", + "tags": ["window"] +} +!*/ +/* DOC + +Tests if page is iframed. + +*/ + + // github.com/Modernizr/Modernizr/issues/242 + + Modernizr.addTest('framed', window.location != top.location); + +/*! +{ + "name": "Workers from Data URIs", + "property": "dataworkers", + "caniuse" : "dataworkers", + "tags": ["performance", "workers"], + "notes": [{ + "name": "W3C Reference", + "href": "http://www.w3.org/TR/workers/" + }], + "knownBugs": ["This test may output garbage to console."], + "authors": ["Jussi Kalliokoski"], + "async": true +} +!*/ +/* DOC + +Detects support for creating Web Workers from Data URIs. + +*/ + + Modernizr.addAsyncTest(function() { + try { + var data = 'Modernizr', + worker = new Worker('data:text/javascript;base64,dGhpcy5vbm1lc3NhZ2U9ZnVuY3Rpb24oZSl7cG9zdE1lc3NhZ2UoZS5kYXRhKX0='); + + worker.onmessage = function(e) { + worker.terminate(); + addTest('dataworkers', data === e.data); + worker = null; + }; + + // Just in case... + worker.onerror = function() { + addTest('dataworkers', false); + worker = null; + }; + + setTimeout(function() { + addTest('dataworkers', false); + }, 200); + + worker.postMessage(data); + } catch (e) { + setTimeout(function () { + addTest('dataworkers', false); + }, 0); + } + }); + +/*! +{ + "name": "Shared Workers", + "property": "sharedworkers", + "caniuse" : "sharedworkers", + "tags": ["performance", "workers"], + "notes": [{ + "name": "W3C Reference", + "href": "http://www.w3.org/TR/workers/" + }] +} +!*/ +/* DOC + +Detects support for the `SharedWorker` API from the Web Workers spec. + +*/ + + Modernizr.addTest('sharedworkers', 'SharedWorker' in window); + +/*! +{ + "name": "Web Workers", + "property": "webworkers", + "caniuse" : "webworkers", + "tags": ["performance", "workers"], + "notes": [{ + "name": "W3C Reference", + "href": "http://www.w3.org/TR/workers/" + }, { + "name": "HTML5 Rocks article", + "href": "http://www.html5rocks.com/en/tutorials/workers/basics/" + }, { + "name": "MDN documentation", + "href": "https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers" + }], + "polyfills": ["fakeworker", "html5shims"] +} +!*/ +/* DOC + +Detects support for the basic `Worker` API from the Web Workers spec. Web Workers provide a simple means for web content to run scripts in background threads. + +*/ + + Modernizr.addTest('webworkers', 'Worker' in window); + + + // 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; + + + + + +})(this, document);
\ No newline at end of file diff --git a/www/js/lib/modernizr-build.min.js b/www/js/lib/modernizr-build.min.js index d5f87d4..35b0108 100644 --- a/www/js/lib/modernizr-build.min.js +++ b/www/js/lib/modernizr-build.min.js @@ -1,2 +1,2 @@ -/*! Modernizr 3.0.0pre (Custom Build) | MIT */!function(a,b,c){function d(a,b){return typeof a===b}function e(){var a,b,c,e,f;for(var g in q){if(a=[],b=q[g],b.name&&(a.push(b.name.toLowerCase()),b.options&&b.options.aliases&&b.options.aliases.length))for(c=0;c<b.options.aliases.length;c++)a.push(b.options.aliases[c].toLowerCase());for(e=d(b.fn,"function")?b.fn():b.fn,f=0;f<a.length;f++)Modernizr[a[f]]=e,t.push((Modernizr[a[f]]?"":"no-")+a[f])}}function f(a){var b,c=u.className,d=[];if(c=c.replace(/(^|\s)no-js(\s|$)/,"$1js$2"),Modernizr._config.enableClasses){for(var e=0;e<a.length;e++)a[e].match("^no-")||d.push("no-"+a[e]);b=new RegExp("(^|\\s)"+d.join("|")+"(\\s|$)","g"),c=c.replace(b,"$1$2"),c+=" "+a.join(" "+(Modernizr._config.classPrefix||"")),u.className=c}}function g(a,b){if("object"==typeof a)for(var d in a)s(a,d)&&g(d,a[d]);else{if(a=a.toLowerCase(),Modernizr[a]!==c)return Modernizr;b="function"==typeof b?b():b,Modernizr[a]=b,f([(b?"":"no-")+a]),Modernizr._trigger(a,b)}return Modernizr}function h(a,b){return!!~(""+a).indexOf(b)}function i(){var a=b.body;return a||(a=w("body"),a.fake=!0),a}function j(a,b,c,d){var e,f,g,h,j="modernizr",k=w("div"),l=i();if(parseInt(c,10))for(;c--;)g=w("div"),g.id=d?d[c]:j+(c+1),k.appendChild(g);return e=["­",'<style id="s',j,'">',a,"</style>"].join(""),k.id=j,(l.fake?l:k).innerHTML+=e,l.appendChild(k),l.fake&&(l.style.background="",l.style.overflow="hidden",h=u.style.overflow,u.style.overflow="hidden",u.appendChild(l)),f=b(k,a),l.fake?(l.parentNode.removeChild(l),u.style.overflow=h):k.parentNode.removeChild(k),!!f}function k(a){return a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-")}function l(b,d){var e=b.length;if("CSS"in a&&"supports"in a.CSS){for(;e--;)if(a.CSS.supports(k(b[e]),d))return!0;return!1}if("CSSSupportsRule"in a){for(var f=[];e--;)f.push("("+k(b[e])+":"+d+")");return f=f.join(" or "),j("@supports ("+f+") { #modernizr { position: absolute; } }",function(b){return"absolute"==(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position})}return c}function m(a,b,e,f){function g(){j&&(delete y.style,delete y.modElem)}if(f=d(f,"undefined")?!1:f,!d(e,"undefined")){var i=l(a,e);if(!d(i,"undefined"))return i}var j,k,m,n;y.style||(j=!0,y.modElem=w("modernizr"),y.style=y.modElem.style);for(k in a)if(m=a[k],n=y.style[m],!h(m,"-")&&y.style[m]!==c){if(f||d(e,"undefined"))return g(),"pfx"==b?m:!0;try{y.style[m]=e}catch(o){}if(y.style[m]!=n)return g(),"pfx"==b?m:!0}return g(),!1}function n(a,b,c){var e;for(var f in a)if(a[f]in b)return c===!1?a[f]:(e=b[a[f]],d(e,"function")&&"bind"in e?e.bind(c||b):e);return!1}function o(a,b,c,e,f){var g=a.charAt(0).toUpperCase()+a.slice(1),h=(a+" "+C.join(g+" ")+g).split(" ");return d(b,"string")||d(b,"undefined")?m(h,b,e,f):(h=(a+" "+D.join(g+" ")+g).split(" "),n(h,b,c))}function p(a,b,d){return o(a,c,c,b,d)}var q=[],r={_version:"v3.0.0pre",_config:{classPrefix:"",enableClasses:!0},_q:[],on:function(a,b){setTimeout(function(){b(this[a])},0)},addTest:function(a,b,c){q.push({name:a,fn:b,options:c})},addAsyncTest:function(a){q.push({name:null,fn:a})}},Modernizr=function(){};Modernizr.prototype=r,Modernizr=new Modernizr;var s,t=[],u=b.documentElement;!function(){var a={}.hasOwnProperty;s=d(a,"undefined")||d(a.call,"undefined")?function(a,b){return b in a&&d(a.constructor.prototype[b],"undefined")}:function(b,c){return a.call(b,c)}}(),r._l={},r.on=function(a,b){this._l[a]||(this._l[a]=[]),this._l[a].push(b),Modernizr.hasOwnProperty(a)&&setTimeout(function(){Modernizr._trigger(a,Modernizr[a])},0)},r._trigger=function(a,b){if(this._l[a]){var c=this._l[a];setTimeout(function(){var a,d;for(a=0;a<c.length;a++)d=c[a],d(b)},0),delete this._l[a]}},Modernizr._q.push(function(){r.addTest=g});var v;!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=v.elements;return"string"==typeof a?a.split(" "):a}function e(a){var b=x[a[u]];return b||(b={},w++,a[u]=w,x[w]=b),b}function f(a,c,d){if(c||(c=b),p)return c.createElement(a);d||(d=e(c));var f;return f=d.cache[a]?d.cache[a].cloneNode():t.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),f.canHaveChildren&&!s.test(a)?d.frag.appendChild(f):f}function g(a,c){if(a||(a=b),p)return a.createDocumentFragment();c=c||e(a);for(var f=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)f.createElement(h[g]);return f}function h(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return v.shivMethods?f(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(v,b.frag)}function i(a){a||(a=b);var d=e(a);return!v.shivCSS||o||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}")),p||h(a,d),a}function j(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(k(b)));return g}function k(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(z+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function l(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+z+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function m(a){for(var b=a.length;b--;)a[b].removeNode()}function n(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,f,g=e(a),h=a.namespaces,i=a.parentWindow;return!A||a.printShived?a:("undefined"==typeof h[z]&&h.add(z),i.attachEvent("onbeforeprint",function(){b();for(var e,g,h,i=a.styleSheets,k=[],m=i.length,n=Array(m);m--;)n[m]=i[m];for(;h=n.pop();)if(!h.disabled&&y.test(h.media)){try{e=h.imports,g=e.length}catch(o){g=0}for(m=0;g>m;m++)n.push(e[m]);try{k.push(h.cssText)}catch(o){}}k=l(k.reverse().join("")),f=j(a),d=c(a,k)}),i.attachEvent("onafterprint",function(){m(f),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var o,p,q="3.6.2",r=a.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,t=/^(?: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,u="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",o="hidden"in a,p=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){o=!0,p=!0}}(),v={elements:r.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:q,shivCSS:r.shivCSS!==!1,supportsUnknownElements:p,shivMethods:r.shivMethods!==!1,type:"default",shivDocument:i,createElement:f,createDocumentFragment:g},a.html5=v,i(b);var y=/^$|\b(?:all|print)\b/,z="html5shiv",A=!p&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();v.type+=" print",v.shivPrint=n,n(b)}(this,b),function(a,b,c){function d(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function e(a,c,e,f,h,i){var j,k,m=b.createElement("script");f=f||l.errorTimeout,m.src=a;for(k in e)m.setAttribute(k,e[k]);c=i?g:c||s,m.onreadystatechange=m.onload=function(){!j&&d(m.readyState)&&(j=1,c(),m.onload=m.onreadystatechange=null)},n(function(){j||(j=1,c(1))},f),E(),h?m.onload():o.parentNode.insertBefore(m,o)}function f(a,c,d,e,f,h){var i,j=b.createElement("link");e=e||l.errorTimeout,c=h?g:c||s,j.href=a,j.rel="stylesheet",j.type="text/css";for(i in d)j.setAttribute(i,d[i]);f||(E(),o.parentNode.insertBefore(j,o),n(c,0))}function g(){var a=q.shift();r=1,a?a.t?n(function(){("c"==a.t?l.injectCss:l.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),g()):r=0}function h(a,c,e,f,h,i,j){function k(b){if(!p&&d(m.readyState)&&(t.r=p=1,!r&&g(),b)){"img"!=a&&n(function(){v.removeChild(m)},50);for(var e in G[c])G[c].hasOwnProperty(e)&&G[c][e].onload();m.onload=m.onreadystatechange=null}}j=j||l.errorTimeout;var m=b.createElement(a),p=0,s=0,t={t:e,s:c,e:h,a:i,x:j};1===G[c]&&(s=1,G[c]=[]),"object"==a?(m.data=c,m.setAttribute("type","text/css")):(m.src=c,m.type=a),m.width=m.height="0",m.onerror=m.onload=m.onreadystatechange=function(){k.call(this,s)},q.splice(f,0,t),"img"!=a&&(s||2===G[c]?(E(),v.insertBefore(m,u?null:o),n(k,j)):G[c].push(m))}function i(a,b,c,d,e){return r=0,b=b||"j",C(a)?h("c"==b?z:y,a,b,this.i++,c,d,e):(q.splice(this.i++,0,a),1==q.length&&g()),this}function j(){var a=l;return a.loader={load:i,i:0},a}var k,l,m=b.documentElement,n=a.setTimeout,o=b.getElementsByTagName("script")[0],p={}.toString,q=[],r=0,s=function(){},t="MozAppearance"in m.style,u=t&&!!b.createRange().compareNode,v=u?m:o.parentNode,w=a.opera&&"[object Opera]"==p.call(a.opera),x=!!b.attachEvent&&!w,y=t?"object":x?"script":"img",z=x?"script":y,A=Array.isArray||function(a){return"[object Array]"==p.call(a)},B=function(a){return Object(a)===a},C=function(a){return"string"==typeof a},D=function(a){return"[object Function]"==p.call(a)},E=function(){o&&o.parentNode||(o=b.getElementsByTagName("script")[0])},F=[],G={},H={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}};l=function(a){function b(a){var b,c,d,e=a.split("!"),f=F.length,g=e.pop(),h=e.length,i={url:g,origUrl:g,prefixes:e};for(c=0;h>c;c++)d=e[c].split("="),b=H[d.shift()],b&&(i=b(i,d));for(c=0;f>c;c++)i=F[c](i);return i}function d(a){var b=a.split("?")[0];return b.substr(b.lastIndexOf(".")+1)}function e(a,e,f,g,h){var i=b(a),k=i.autoCallback;return d(i.url),i.bypass?void 0:(e&&(e=D(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(G[i.url]&&i.reexecute!==!0?i.noexec=!0:G[i.url]=1,a&&f.load(i.url,i.forceCSS||!i.forceJS&&"css"==d(i.url)?"c":c,i.noexec,i.attrs,i.timeout),(D(e)||D(k))&&f.load(function(){j(),e&&e(i.origUrl,h,g),k&&k(i.origUrl,h,g),G[i.url]=2}),void 0))}function f(a,b){function c(a,c){if(""===a||a){if(C(a))c||(i=function(){var a=[].slice.call(arguments);j.apply(this,a),k()}),e(a,i,b,0,f);else if(B(a)){d=function(){var b,c=0;for(b in a)a.hasOwnProperty(b)&&c++;return c}();for(var g in a)a.hasOwnProperty(g)&&(c||--d||(D(i)?i=function(){var a=[].slice.call(arguments);j.apply(this,a),k()}:i[g]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),k()}}(j[g])),e(a[g],i,b,g,f))}}else!c&&k()}var d,f=!!a.test,g=f?a.yep:a.nope,h=a.load||a.both,i=a.callback||s,j=i,k=a.complete||s;c(g,!!h||!!a.complete),h&&c(h),!h&&!!a.complete&&c("")}var g,h,i=this.yepnope.loader;if(C(a))e(a,0,i,0);else if(A(a))for(g=0;g<a.length;g++)h=a[g],C(h)?e(h,0,i,0):A(h)?l(h):B(h)&&f(h,i);else B(a)&&f(a,i)},l.addPrefix=function(a,b){H[a]=b},l.addFilter=function(a){F.push(a)},l.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",k=function(){b.removeEventListener("DOMContentLoaded",k,0),b.readyState="complete"},0)),a.yepnope=j(),a.yepnope.executeStack=g,a.yepnope.injectJs=e,a.yepnope.injectCss=f}(a,b),r.load=function(){a.yepnope.apply(a,[].slice.call(arguments,0))};var w=function(){return b.createElement.apply(b,arguments)},x={elem:w("modernizr")};Modernizr._q.push(function(){delete x.elem});var y={style:x.elem.style};Modernizr._q.unshift(function(){delete y.style});var z=r.testProp=function(a,b,d){return m([a],c,b,d)},A=t.slice;Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=A.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(A.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(A.call(arguments)))};return d}),Modernizr.addTest("adownload",!a.externalHost&&"download"in w("a")),Modernizr.addTest("applicationcache","applicationCache"in a),Modernizr.addTest("webaudio","webkitAudioContext"in a||"AudioContext"in a),Modernizr.addTest("audio",function(){var a=w("audio"),b=!1;try{(b=!!a.canPlayType)&&(b=new Boolean(b),b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),b.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),b.opus=a.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),b.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),b.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,""))}catch(c){}return b});var B="Webkit Moz O ms",C=B.split(" ");r._cssomPrefixes=C;var D=B.toLowerCase().split(" ");r._domPrefixes=D;var E=" -webkit- -moz- -o- -ms- ".split(" ");r._prefixes=E,r.testAllProps=o;var F=r.prefixed=function(a,b,c){return b?o(a,b,c):o(a,"pfx")};Modernizr.addTest("lowbattery",function(){var a=.2,b=F("battery",navigator);return!!(b&&!b.charging&&b.level<=a)}),Modernizr.addTest("batteryapi",!!F("battery",navigator),{aliases:["battery-api"]}),Modernizr.addTest("blobconstructor",function(){try{return!!new Blob}catch(a){return!1}},{aliases:["blob-constructor"]}),Modernizr.addTest("canvas",function(){var a=w("canvas");return!(!a.getContext||!a.getContext("2d"))});var G=w("canvas");Modernizr.addTest("todataurljpeg",function(){return!!Modernizr.canvas&&0===G.toDataURL("image/jpeg").indexOf("data:image/jpeg")}),Modernizr.addTest("todataurlpng",function(){return!!Modernizr.canvas&&0===G.toDataURL("image/png").indexOf("data:image/png")}),Modernizr.addTest("todataurlwebp",function(){return!!Modernizr.canvas&&0===G.toDataURL("image/webp").indexOf("data:image/webp")}),Modernizr.addTest("canvastext",function(){return Modernizr.canvas===!1?!1:"function"==typeof w("canvas").getContext("2d").fillText}),Modernizr.addTest("contenteditable",function(){if("contentEditable"in u){var a=w("div");return a.contentEditable=!0,"true"===a.contentEditable}}),Modernizr.addTest("contentsecuritypolicy","SecurityPolicy"in b),Modernizr.addTest("contextmenu","contextMenu"in u&&"HTMLMenuItemElement"in a),Modernizr.addTest("cookies",function(){b.cookie="cookietest=1";var a=-1!=b.cookie.indexOf("cookietest=");return b.cookie="cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT",a}),Modernizr.addTest("cors","XMLHttpRequest"in a&&"withCredentials"in new XMLHttpRequest),r.testAllProps=p,Modernizr.addTest("cssanimations",p("animationName","a",!0)),Modernizr.addTest("backgroundcliptext",function(){return p("backgroundClip","text")}),Modernizr.addTest("bgpositionshorthand",function(){var a=w("a"),b=a.style,c="right 10px bottom 10px";return b.cssText="background-position: "+c+";",b.backgroundPosition===c}),Modernizr.addTest("bgpositionxy",function(){return p("backgroundPositionX","3px",!0)&&p("backgroundPositionY","5px",!0)}),Modernizr.addTest("bgrepeatround",p("backgroundRepeat","round")),Modernizr.addTest("bgrepeatspace",p("backgroundRepeat","space")),Modernizr.addTest("backgroundsize",p("backgroundSize","100%",!0)),Modernizr.addTest("bgsizecover",p("backgroundSize","cover")),Modernizr.addTest("borderimage",p("borderImage","url() 1",!0)),Modernizr.addTest("borderradius",p("borderRadius","0px",!0)),Modernizr.addTest("boxshadow",p("boxShadow","1px 1px",!0)),Modernizr.addTest("boxsizing",p("boxSizing","border-box",!0)&&(b.documentMode===c||b.documentMode>7)),Modernizr.addTest("csscalc",function(){var a="width:",b="calc(10px);",c=w("div");return c.style.cssText=a+E.join(b+a),!!c.style.length});var H=r.testStyles=j;Modernizr.addTest("checked",function(){return H("#modernizr {position:absolute} #modernizr input {margin-left:10px} #modernizr :checked {margin-left:20px;display:block}",function(a){var b=w("input");return b.setAttribute("type","checkbox"),b.setAttribute("checked","checked"),a.appendChild(b),20===b.offsetLeft})}),Modernizr.addTest("csscolumns",p("columnCount","1",!0)),Modernizr.addTest("cubicbezierrange",function(){var a=w("div");return a.style.cssText=E.join("transition-timing-function:cubic-bezier(1,0,0,1.1); "),!!a.style.length}),Modernizr.addTest("displayrunin",p("display","run-in"),{aliases:["display-runin"]}),H("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(a){var b,c=a.children;b=c[0].offsetLeft<c[1].offsetLeft,Modernizr.addTest("displaytable",b,{aliases:["display-table"]})},2),Modernizr.addTest("ellipsis",p("textOverflow","ellipsis")),Modernizr.addTest("cssfilters",function(){var a=w("div");return a.style.cssText=E.join("filter:blur(2px); "),!!a.style.length&&(b.documentMode===c||b.documentMode>9)}),Modernizr.addTest("flexbox",p("flexBasis","1px",!0)),Modernizr.addTest("flexboxlegacy",p("boxDirection","reverse",!0)),Modernizr.addTest("flexboxtweener",p("flexAlign","end",!0)),H('@font-face {font-family:"font";src:url("https://")}',function(a,c){var d=b.getElementById("smodernizr"),e=d.sheet||d.styleSheet,f=e?e.cssRules&&e.cssRules[0]?e.cssRules[0].cssText:e.cssText||"":"",g=/src/i.test(f)&&0===f.indexOf(c.split(" ")[0]);Modernizr.addTest("fontface",g)}),H('#modernizr{font:0/0 a}#modernizr:after{content:":)";visibility:hidden;font:7px/1 a}',function(a){Modernizr.addTest("generatedcontent",a.offsetHeight>=7)}),Modernizr.addTest("cssgradients",function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);",d=(a+"-webkit- ".split(" ").join(b+a)+E.join(c+a)).slice(0,-a.length),e=w("div"),f=e.style;return f.cssText=d,(""+f.backgroundImage).indexOf("gradient")>-1}),Modernizr.addTest("hsla",function(){var a=w("div"),b=a.style;return b.cssText="background-color:hsla(120,40%,100%,.5)",h(b.backgroundColor,"rgba")||h(b.backgroundColor,"hsla")}),Modernizr.addAsyncTest(function(){function c(){function e(){try{var a=w("div"),c=w("span"),d=a.style,e=0,f=0,g=!1,h=b.body.firstElementChild||b.body.firstChild;return a.appendChild(c),c.innerHTML="Bacon ipsum dolor sit amet jerky velit in culpa hamburger et. Laborum dolor proident, enim dolore duis commodo et strip steak. Salami anim et, veniam consectetur dolore qui tenderloin jowl velit sirloin. Et ad culpa, fatback cillum jowl ball tip ham hock nulla short ribs pariatur aute. Pig pancetta ham bresaola, ut boudin nostrud commodo flank esse cow tongue culpa. Pork belly bresaola enim pig, ea consectetur nisi. Fugiat officia turkey, ea cow jowl pariatur ullamco proident do laborum velit sausage. Magna biltong sint tri-tip commodo sed bacon, esse proident aliquip. Ullamco ham sint fugiat, velit in enim sed mollit nulla cow ut adipisicing nostrud consectetur. Proident dolore beef ribs, laborum nostrud meatball ea laboris rump cupidatat labore culpa. Shankle minim beef, velit sint cupidatat fugiat tenderloin pig et ball tip. Ut cow fatback salami, bacon ball tip et in shank strip steak bresaola. In ut pork belly sed mollit tri-tip magna culpa veniam, short ribs qui in andouille ham consequat. Dolore bacon t-bone, velit short ribs enim strip steak nulla. Voluptate labore ut, biltong swine irure jerky. Cupidatat excepteur aliquip salami dolore. Ball tip strip steak in pork dolor. Ad in esse biltong. Dolore tenderloin exercitation ad pork loin t-bone, dolore in chicken ball tip qui pig. Ut culpa tongue, sint ribeye dolore ex shank voluptate hamburger. Jowl et tempor, boudin pork chop labore ham hock drumstick consectetur tri-tip elit swine meatball chicken ground round. Proident shankle mollit dolore. Shoulder ut duis t-bone quis reprehenderit. Meatloaf dolore minim strip steak, laboris ea aute bacon beef ribs elit shank in veniam drumstick qui. Ex laboris meatball cow tongue pork belly. Ea ball tip reprehenderit pig, sed fatback boudin dolore flank aliquip laboris eu quis. Beef ribs duis beef, cow corned beef adipisicing commodo nisi deserunt exercitation. Cillum dolor t-bone spare ribs, ham hock est sirloin. Brisket irure meatloaf in, boudin pork belly sirloin ball tip. Sirloin sint irure nisi nostrud aliqua. Nostrud nulla aute, enim officia culpa ham hock. Aliqua reprehenderit dolore sunt nostrud sausage, ea boudin pork loin ut t-bone ham tempor. Tri-tip et pancetta drumstick laborum. Ham hock magna do nostrud in proident. Ex ground round fatback, venison non ribeye in.",b.body.insertBefore(a,h),d.cssText="position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;",e=c.offsetHeight,f=c.offsetWidth,d.cssText="position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;"+E.join("hyphens:auto; "),g=c.offsetHeight!=e||c.offsetWidth!=f,b.body.removeChild(a),a.removeChild(c),g}catch(i){return!1}}function f(a,c){try{var d=w("div"),e=w("span"),f=d.style,g=0,h=!1,i=!1,j=!1,k=b.body.firstElementChild||b.body.firstChild;return f.cssText="position:absolute;top:0;left:0;overflow:visible;width:1.25em;",d.appendChild(e),b.body.insertBefore(d,k),e.innerHTML="mm",g=e.offsetHeight,e.innerHTML="m"+a+"m",i=e.offsetHeight>g,c?(e.innerHTML="m<br />m",g=e.offsetWidth,e.innerHTML="m"+a+"m",j=e.offsetWidth>g):j=!0,i===!0&&j===!0&&(h=!0),b.body.removeChild(d),d.removeChild(e),h}catch(l){return!1}}function h(c){try{var d,e=w("input"),f=w("div"),g="lebowski",h=!1,i=b.body.firstElementChild||b.body.firstChild;if(f.innerHTML=g+c+g,b.body.insertBefore(f,i),b.body.insertBefore(e,f),e.setSelectionRange?(e.focus(),e.setSelectionRange(0,0)):e.createTextRange&&(d=e.createTextRange(),d.collapse(!0),d.moveEnd("character",0),d.moveStart("character",0),d.select()),a.find)h=a.find(g+g);else try{d=a.self.document.body.createTextRange(),h=d.findText(g+g)}catch(j){h=!1}return b.body.removeChild(f),b.body.removeChild(e),h}catch(j){return!1}}return b.body||b.getElementsByTagName("body")[0]?(g("csshyphens",function(){if(!p("hyphens","auto",!0))return!1;try{return e()}catch(a){return!1}}),g("softhyphens",function(){try{return f("­",!0)&&f("​",!1)}catch(a){return!1}}),g("softhyphensfind",function(){try{return h("­")&&h("​")}catch(a){return!1}}),void 0):(setTimeout(c,d),void 0)}var d=300;setTimeout(c,d)}),H("#modernizr div {width:100px} #modernizr :last-child{width:200px;display:block}",function(a){Modernizr.addTest("lastchild",a.lastChild.offsetWidth>a.firstChild.offsetWidth)},2),Modernizr.addTest("cssmask",p("maskRepeat","repeat-x",!0));var I=function(b){var c,d=a.matchMedia||a.msMatchMedia;return d?d(b)&&d(b).matches||!1:(j("@media "+b+" { #modernizr { position: absolute; } }",function(b){c="absolute"==(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position}),c)},J=r.mq=I;Modernizr.addTest("mediaqueries",J("only all")),Modernizr.addTest("multiplebgs",function(){var a=w("div"),b=a.style;return b.cssText="background:url(https://),url(https://),red url(https://)",/(url\s*\(.*?){3}/.test(b.background)}),Modernizr.addTest("objectfit",!!F("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("opacity",function(){var a=w("div"),b=a.style;return b.cssText=E.join("opacity:.55;"),/^0.55$/.test(b.opacity)}),Modernizr.addTest("overflowscrolling",p("overflowScrolling","touch",!0)),Modernizr.addTest("csspointerevents",function(){var a=w("x");return a.style.cssText="pointer-events:auto","auto"===a.style.pointerEvents}),Modernizr.addTest("csspositionsticky",function(){var a="position:",b="sticky",c=w("modernizr"),d=c.style;return d.cssText=a+E.join(b+";"+a).slice(0,-a.length),-1!==d.position.indexOf(b)}),Modernizr.addTest("csspseudoanimations",function(){var b=!1;if(!Modernizr.cssanimations||!a.getComputedStyle)return b;var c=["@",Modernizr._prefixes.join("keyframes csspseudoanimations { from { font-size: 10px; } }@").replace(/\@$/,""),'#modernizr:before { content:" "; font-size:5px;',Modernizr._prefixes.join("animation:csspseudoanimations 1ms infinite;"),"}"].join("");return Modernizr.testStyles(c,function(c){b="10px"===a.getComputedStyle(c,":before").getPropertyValue("font-size")}),b}),Modernizr.addTest("csstransitions",p("transition","all",!0)),Modernizr.addTest("csspseudotransitions",function(){var b=!1;if(!Modernizr.csstransitions||!a.getComputedStyle)return b;var c='#modernizr:before { content:" "; font-size:5px;'+Modernizr._prefixes.join("transition:0s 100s;")+"}"+"#modernizr.trigger:before { font-size:10px; }";return Modernizr.testStyles(c,function(c){a.getComputedStyle(c,":before").getPropertyValue("font-size"),c.className+="trigger",b="5px"===a.getComputedStyle(c,":before").getPropertyValue("font-size")}),b}),Modernizr.addTest("cssreflections",p("boxReflect","above",!0)),Modernizr.addTest("regions",function(){var a=Modernizr.prefixed("flowFrom"),b=Modernizr.prefixed("flowInto");if(!a||!b)return!1;var d=w("div"),e=w("div"),f=w("div"),g="modernizr_flow_for_regions_check";e.innerText="M",d.style.cssText="top: 150px; left: 150px; padding: 0px;",f.style.cssText="width: 50px; height: 50px; padding: 42px;",f.style[a]=g,d.appendChild(e),d.appendChild(f),u.appendChild(d);var h,i,j=e.getBoundingClientRect();return e.style[b]=g,h=e.getBoundingClientRect(),i=parseInt(h.left-j.left,10),u.removeChild(d),e=f=d=c,42==i}),Modernizr.addTest("cssremunit",function(){var a=w("div");try{a.style.fontSize="3rem"}catch(b){}return/rem/.test(a.style.fontSize)}),Modernizr.addTest("cssresize",p("resize","both",!0)),Modernizr.addTest("rgba",function(){var a=w("div"),b=a.style;return b.cssText="background-color:rgba(150,255,150,.5)",(""+b.backgroundColor).indexOf("rgba")>-1}),H("#modernizr{overflow: scroll; width: 40px; height: 40px; }#"+E.join("scrollbar{width:0px} #modernizr::").split("#").slice(1).join("#")+"scrollbar{width:0px}",function(a){Modernizr.addTest("cssscrollbar",40==a.scrollWidth)}),Modernizr.addTest("shapes",function(){var b=F("shapeInside");if(!b)return!1;var c=b.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-");return H("#modernizr { "+c+":rectangle(0,0,0,0,0,0) }",function(b){var c=a.getComputedStyle?getComputedStyle(b,null):b.currentStyle;return"rectangle(0px, 0px, 0px, 0px, 0px, 0px)"==c[F("shapeInside",u.style,!1)]})}),Modernizr.addTest("siblinggeneral",function(){return H("#modernizr div {width:100px} #modernizr div ~ div {width:200px;display:block}",function(a){return 200==a.lastChild.offsetWidth},2)}),H("#modernizr{position: absolute; top: -10em; visibility:hidden; font: normal 10px arial;}#subpixel{float: left; font-size: 33.3333%;}",function(b){var c=b.firstChild;c.innerHTML="This is a text written in Arial",Modernizr.addTest("subpixelfont",a.getComputedStyle?"44px"!==a.getComputedStyle(c,null).getPropertyValue("width"):!1)},1,["subpixel"]),Modernizr.addTest("supports","CSSSupportsRule"in a),Modernizr.addTest("textshadow",z("textShadow","1px 1px")),Modernizr.addTest("csstransforms",p("transform","scale(1)",!0)),Modernizr.addTest("csstransforms3d",function(){var a=!!p("perspective","1px",!0);return a&&"webkitPerspective"in u.style&&H("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:5px;margin:0;padding:0;border:0}}",function(b){a=9===b.offsetLeft&&5===b.offsetHeight}),a}),Modernizr.addTest("userselect",p("userSelect","none",!0)),H("#modernizr { height: 50vh; }",function(b){var c=parseInt(a.innerHeight/2,10),d=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).height,10);Modernizr.addTest("cssvhunit",d==c)}),H("#modernizr { width: 50vmax; }",function(b){var c=a.innerWidth/100,d=a.innerHeight/100,e=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).width,10);Modernizr.addTest("cssvmaxunit",parseInt(50*Math.max(c,d),10)==e)}),H("#modernizr { width: 50vmin; }",function(b){var c=a.innerWidth/100,d=a.innerHeight/100,e=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).width,10);Modernizr.addTest("cssvminunit",parseInt(50*Math.min(c,d),10)==e)}),H("#modernizr { width: 50vw; }",function(b){var c=parseInt(a.innerWidth/2,10),d=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).width,10);Modernizr.addTest("cssvwunit",d==c)}),Modernizr.addTest("wrapflow",function(){var a=F("wrapFlow");if(!a)return!1;var b=a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-"),d=w("div"),e=w("div"),f=w("span");e.style.cssText="position: absolute; left: 50px; width: 100px; height: 20px;"+b+":end;",f.innerText="X",d.appendChild(e),d.appendChild(f),u.appendChild(d);var g=f.offsetLeft;return u.removeChild(d),e=f=d=c,150==g}),Modernizr.addTest("customprotocolhandler",!!navigator.registerProtocolHandler),Modernizr.addTest("dart",!!F("startDart",navigator)),Modernizr.addTest("dataview","undefined"!=typeof DataView&&"getFloat64"in DataView.prototype),Modernizr.addTest("classlist","classList"in u),Modernizr.addTest("createelementattrs",function(){try{return"test"==w('<input name="test" />').getAttribute("name")}catch(a){return!1}},{aliases:["createelement-attrs"]}),Modernizr.addTest("dataset",function(){var a=w("div");return a.setAttribute("data-a-b","c"),!(!a.dataset||"c"!==a.dataset.aB)}),Modernizr.addTest("microdata","getItems"in b),Modernizr.addTest("draganddrop",function(){var a=w("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a});var K={},L="autocomplete autofocus list placeholder max min multiple pattern required step".split(" "),M=w("input");Modernizr.input=function(b){for(var c=0,d=b.length;d>c;c++)K[b[c]]=!!(b[c]in M);return K.list&&(K.list=!(!w("datalist")||!a.HTMLDataListElement)),K}(L),Modernizr.addTest("datalistelem",Modernizr.input.list),Modernizr.addTest("details",function(){var a,b=w("details");return"open"in b?(H("#modernizr details{display:block}",function(c){c.appendChild(b),b.innerHTML="<summary>a</summary>b",a=b.offsetHeight,b.open=!0,a=a!=b.offsetHeight}),a):!1}),Modernizr.addTest("outputelem","value"in w("output")),Modernizr.addTest("progressbar",w("progress").max!==c),Modernizr.addTest("meter",w("meter").max!==c),Modernizr.addTest("ruby",function(){function c(c,d){var e;return a.getComputedStyle?e=b.defaultView.getComputedStyle(c,null).getPropertyValue(d):c.currentStyle&&(e=c.currentStyle[d]),e}function d(){u.removeChild(e),e=null,f=null,g=null}var e=w("ruby"),f=w("rt"),g=w("rp"),h="display",i="fontSize";return e.appendChild(g),e.appendChild(f),u.appendChild(e),"none"==c(g,h)||"ruby"==c(e,h)&&"ruby-text"==c(f,h)||"6pt"==c(g,i)&&"6pt"==c(f,i)?(d(),!0):(d(),!1)}),Modernizr.addTest("time","valueAsDate"in w("time")),Modernizr.addTest("texttrackapi","function"==typeof w("video").addTextTrack),Modernizr.addTest("track","kind"in w("track")),Modernizr.addTest("emoji",function(){if(!Modernizr.canvastext)return!1;var a=w("canvas"),b=a.getContext("2d");return b.textBaseline="top",b.font="32px Arial",b.fillText("\ud83d\ude03",0,0),0!==b.getImageData(16,16,1,1).data[0]}),Modernizr.addTest("strictmode",function(){return!this}()),Modernizr.addTest("contains",d(String.prototype.contains,"function")),Modernizr.addTest("devicemotion","DeviceMotionEvent"in a),Modernizr.addTest("deviceorientation","DeviceOrientationEvent"in a),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("exiforientation",!1,{aliases:["exif-orientation"]})},a.onload=function(){g("exiforientation",2!==a.width,{aliases:["exif-orientation"]})},a.src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q==" -}),Modernizr.addTest("filereader",!!(a.File&&a.FileList&&a.FileReader)),Modernizr.addTest("filesystem",!!F("requestFileSystem",a)),Modernizr.addTest("fileinput",function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var a=w("input");return a.type="file",!a.disabled}),Modernizr.addTest("formattribute",function(){var a,c=w("form"),d=w("input"),e=w("div"),f="formtest"+(new Date).getTime(),g=!1;c.id=f;try{d.setAttribute("form",f)}catch(h){b.createAttribute&&(a=b.createAttribute("form"),a.nodeValue=f,d.setAttributeNode(a))}return e.appendChild(c),e.appendChild(d),u.appendChild(e),g=1===c.elements.length&&d.form==c,e.parentNode.removeChild(e),g}),Modernizr.addTest("localizednumber",function(){var a,c=w("div"),d=i(),e=function(){return u.insertBefore(d,u.firstElementChild||u.firstChild)}();c.innerHTML='<input type="number" value="1.0" step="0.1"/>';var f=c.childNodes[0];e.appendChild(c),f.focus();try{b.execCommand("InsertText",!1,"1,1")}catch(g){}return a="number"===f.type&&1.1===f.valueAsNumber&&f.checkValidity(),e.removeChild(c),d.fake&&e.parentNode.removeChild(e),a}),Modernizr.addTest("placeholder","placeholder"in w("input")&&"placeholder"in w("textarea")),Modernizr.addTest("speechinput",function(){var a=w("input");return"speech"in a||"onwebkitspeechchange"in a}),Modernizr.addTest("formvalidation",function(){var b=w("form");if(!("checkValidity"in b&&"addEventListener"in b))return!1;var c,d=!1;return Modernizr.formvalidationapi=!0,b.addEventListener("submit",function(b){a.opera||b.preventDefault(),b.stopPropagation()},!1),b.innerHTML='<input name="modTest" required><button></button>',H("#modernizr form{position:absolute;top:-99999em}",function(a){a.appendChild(b),c=b.getElementsByTagName("input")[0],c.addEventListener("invalid",function(a){d=!0,a.preventDefault(),a.stopPropagation()},!1),Modernizr.formvalidationmessage=!!c.validationMessage,b.getElementsByTagName("button")[0].click()}),d}),Modernizr.addTest("fullscreen",!(!F("exitFullscreen",b,!1)&&!F("cancelFullScreen",b,!1))),Modernizr.addTest("gamepads",!!F("getGamepads",navigator)),Modernizr.addTest("geolocation","geolocation"in navigator);var N=function(a){function c(b,c){var e;return b?(c&&"string"!=typeof c||(c=w(c||"div")),b="on"+b,e=b in c,!e&&d&&(c.setAttribute||(c=w("div")),c.setAttribute&&c.removeAttribute&&(c.setAttribute(b,""),e="function"==typeof c[b],c[b]!==a&&(c[b]=a),c.removeAttribute(b))),e):!1}var d=!("onblur"in b.documentElement);return c}(),O=r.hasEvent=N;Modernizr.addTest("hashchange",function(){return O("hashchange",a)===!1?!1:b.documentMode===c||b.documentMode>7}),Modernizr.addTest("history",function(){var b=navigator.userAgent;return-1!==b.indexOf("Android 2")&&-1!==b.indexOf("Mobile Safari")&&-1===b.indexOf("Chrome")?!1:a.history&&"pushState"in a.history}),Modernizr.addTest("ie8compat",!a.addEventListener&&!!b.documentMode&&7===b.documentMode),Modernizr.addTest("sandbox","sandbox"in w("iframe")),Modernizr.addTest("seamless","seamless"in w("iframe")),Modernizr.addTest("srcdoc","srcdoc"in w("iframe")),Modernizr.addAsyncTest(function(){if(!Modernizr.canvas)return!1;var a=new Image,b=w("canvas"),c=b.getContext("2d");a.onload=function(){g("apng",function(){return"undefined"==typeof b.getContext?!1:(c.drawImage(a,0,0),0===c.getImageData(0,0,1,1).data[3])})},a.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg=="}),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("webplossless",!1,{aliases:["webp-lossless"]})},a.onload=function(){g("webplossless",1==a.width,{aliases:["webp-lossless"]})},a.src="data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=="}),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("webp",!1)},a.onload=function(){g("webp",1==a.width)},a.src="data:image/webp;base64,UklGRiwAAABXRUJQVlA4ICAAAAAUAgCdASoBAAEAL/3+/3+CAB/AAAFzrNsAAP5QAAAAAA=="}),Modernizr.addTest("indexeddb",!!F("indexedDB",a));var P="search tel url email datetime date month week time datetime-local number range color".split(" "),Q={},R=":)";Modernizr.inputtypes=function(a){for(var d,e,f,g=a.length,h=0;g>h;h++)M.setAttribute("type",e=a[h]),d="text"!==M.type,d&&(M.value=R,M.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(e)&&M.style.WebkitAppearance!==c?(u.appendChild(M),f=b.defaultView,d=f.getComputedStyle&&"textfield"!==f.getComputedStyle(M,null).WebkitAppearance&&0!==M.offsetHeight,u.removeChild(M)):/^(search|tel)$/.test(e)||(d=/^(url|email)$/.test(e)?M.checkValidity&&M.checkValidity()===!1:M.value!=R)),Q[a[h]]=!!d;return Q}(P),Modernizr.addTest("json","JSON"in a&&"parse"in JSON),Modernizr.addTest("olreversed","reversed"in w("ol")),Modernizr.addTest("mathml",function(){var a;return Modernizr.testStyles("#modernizr{position:absolute}",function(b){b.innerHTML="<math><mfrac><mi>xx</mi><mi>yy</mi></mfrac></math>",a=b.offsetHeight>b.offsetWidth}),a}),Modernizr.addTest("lowbandwidth",function(){var a=navigator.connection||{type:0};return 3==a.type||4==a.type||/^[23]g$/.test(a.type)}),Modernizr.addTest("eventsource","EventSource"in a),Modernizr.addTest("xhr2","FormData"in a);var S=function(a){if("undefined"==typeof XMLHttpRequest)return!1;var b=new XMLHttpRequest;b.open("get","/",!0);try{b.responseType=a}catch(c){return!1}return"response"in b&&b.responseType==a};Modernizr.addTest("xhrresponsetypearraybuffer",S("arraybuffer")),Modernizr.addTest("xhrresponsetypeblob",S("blob")),Modernizr.addTest("xhrresponsetypedocument",S("document")),Modernizr.addTest("xhrresponsetypejson",S("json")),Modernizr.addTest("xhrresponsetypetext",S("text")),Modernizr.addTest("xhrresponsetype",function(){if("undefined"==typeof XMLHttpRequest)return!1;var a=new XMLHttpRequest;return a.open("get","/",!0),"response"in a}()),Modernizr.addTest("notification","Notification"in a&&"permission"in a.Notification&&"requestPermission"in a.Notification),Modernizr.addTest("pagevisibility",!!F("hidden",b,!1)),Modernizr.addTest("performance",!!F("performance",a)),Modernizr.addTest("pointerevents",function(){var a=!1,b=D.length;for(a=Modernizr.hasEvent("pointerdown");b--&&!a;)O(D[b]+"pointerdown")&&(a=!0);return a}),Modernizr.addTest("pointerlock",!!F("exitPointerLock",b)),Modernizr.addTest("postmessage","postMessage"in a),Modernizr.addTest("quotamanagement",function(){var a=F("temporaryStorage",navigator),b=F("persistentStorage",navigator);return!(!a||!b)}),Modernizr.addTest("requestanimationframe",!!F("requestAnimationFrame",a),{aliases:["raf"]}),Modernizr.addTest("scriptasync","async"in w("script")),Modernizr.addTest("scriptdefer","defer"in w("script")),Modernizr.addTest("localstorage",function(){var a="modernizr";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(b){return!1}}),Modernizr.addTest("sessionstorage",function(){var a="modernizr";try{return sessionStorage.setItem(a,a),sessionStorage.removeItem(a),!0}catch(b){return!1}}),Modernizr.addTest("websqldatabase","openDatabase"in a),Modernizr.addTest("stylescoped","scoped"in w("style")),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("svgasimg",!1)},a.onload=function(){g("svgasimg",1==a.width&&1==a.height)},a.src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg=="});var T={}.toString;Modernizr.addTest("svgclippaths",function(){return!!b.createElementNS&&/SVGClipPath/.test(T.call(b.createElementNS("http://www.w3.org/2000/svg","clipPath")))}),Modernizr.addTest("svgfilters",function(){var a=!1;try{a=typeof SVGFEColorMatrixElement!==c&&2==SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE}catch(b){}return a}),Modernizr.addTest("inlinesvg",function(){var a=w("div");return a.innerHTML="<svg/>","http://www.w3.org/2000/svg"==(a.firstChild&&a.firstChild.namespaceURI)}),Modernizr.addTest("smil",function(){return!!b.createElementNS&&/SVGAnimate/.test(T.call(b.createElementNS("http://www.w3.org/2000/svg","animate")))}),Modernizr.addTest("svg",!!b.createElementNS&&!!b.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect),Modernizr.addTest("touchevents",function(){var c;if("ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch)c=!0;else{var d=["@media (",E.join("touch-enabled),("),"heartz",")","{#modernizr{top:9px;position:absolute}}"].join("");H(d,function(a){c=9===a.offsetTop})}return c}),Modernizr.addTest("typedarrays","ArrayBuffer"in a),Modernizr.addTest("unicode",function(){var a,c=w("span"),d=b.createElement("span");return H("#modernizr{font-family:Arial,sans;font-size:300em;}",function(b){c.innerHTML="ᝣ",d.innerHTML="☆",b.appendChild(c),b.appendChild(d),a="offsetWidth"in c&&c.offsetWidth!==d.offsetWidth}),a}),Modernizr.addAsyncTest(function(){function a(){var a=new Image;a.onerror=function(){g("datauri",!0),Modernizr.datauri=new Boolean(!0),Modernizr.datauri.over32kb=!1},a.onload=function(){g("datauri",!0),Modernizr.datauri=new Boolean(!0),Modernizr.datauri.over32kb=1==a.width&&1==a.height};for(var b="R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";b.length<33e3;)b="\r\n"+b;a.src="data:image/gif;base64,"+b}-1!==navigator.userAgent.indexOf("MSIE 7.")&&setTimeout(function(){g("datauri",!1)},10);var b=new Image;b.onerror=function(){g("datauri",!1)},b.onload=function(){1==b.width&&1==b.height?a():g("datauri",!1)},b.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="}),Modernizr.addTest("userdata",!!w("div").addBehavior),Modernizr.addTest("vibrate",!!F("vibrate",navigator)),Modernizr.addTest("video",function(){var a=w("video"),b=!1;try{(b=!!a.canPlayType)&&(b=new Boolean(b),b.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,""))}catch(c){}return b}),Modernizr.addAsyncTest(function(){var a,c=b.createElement("video"),d=c.style,e=function(){clearTimeout(a),g("videoautoplay",0!==c.currentTime),c.parentNode.removeChild(c)};return Modernizr.video&&"autoplay"in c?(d.height=0,d.width=0,c.src=Modernizr.video.h264?"data:video/mp4;base64,AAAAHGZ0eXBtcDQyAAAAAG1wNDJpc29tYXZjMQAAAz5tb292AAAAbG12aGQAAAAAzaNacc2jWnEAAV+QAAFfkAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT////3//AAACQ3RyYWsAAABcdGtoZAAAAAHNo1pxzaNacQAAAAEAAAAAAAFfkAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAEAAAABAAAAAAAd9tZGlhAAAAIG1kaGQAAAAAzaNacc2jWnEAAV+QAAFfkFXEAAAAAAAhaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAAAAAAGWbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABVnN0YmwAAACpc3RzZAAAAAAAAAABAAAAmWF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAEAAQAEgAAABIAAAAAAAAAAEOSlZUL0FWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwH0AAr/4QAZZ/QACq609NQYBBkAAAMAAQAAAwAKjxImoAEABWjOAa8gAAAAEmNvbHJuY2xjAAYAAQAGAAAAGHN0dHMAAAAAAAAAAQAAAAUAAEZQAAAAKHN0c3oAAAAAAAAAAAAAAAUAAAIqAAAACAAAAAgAAAAIAAAACAAAAChzdHNjAAAAAAAAAAIAAAABAAAABAAAAAEAAAACAAAAAQAAAAEAAAAYc3RjbwAAAAAAAAACAAADYgAABaQAAAAUc3RzcwAAAAAAAAABAAAAAQAAABFzZHRwAAAAAAREREREAAAAb3VkdGEAAABnbWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcgAAAAAAAAAAAAAAAAAAAAA6aWxzdAAAADKpdG9vAAAAKmRhdGEAAAABAAAAAEhhbmRCcmFrZSAwLjkuOCAyMDEyMDcxODAwAAACUm1kYXQAAAHkBgX/4NxF6b3m2Ui3lizYINkj7u94MjY0IC0gY29yZSAxMjAgLSBILjI2NC9NUEVHLTQgQVZDIGNvZGVjIC0gQ29weWxlZnQgMjAwMy0yMDExIC0gaHR0cDovL3d3dy52aWRlb2xhbi5vcmcveDI2NC5odG1sIC0gb3B0aW9uczogY2FiYWM9MCByZWY9MSBkZWJsb2NrPTE6MDowIGFuYWx5c2U9MHgxOjAgbWU9ZXNhIHN1Ym1lPTkgcHN5PTAgbWl4ZWRfcmVmPTAgbWVfcmFuZ2U9NCBjaHJvbWFfbWU9MSB0cmVsbGlzPTAgOHg4ZGN0PTAgY3FtPTAgZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0wIGNocm9tYV9xcF9vZmZzZXQ9MCB0aHJlYWRzPTYgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTUwIGtleWludF9taW49NSBzY2VuZWN1dD00MCBpbnRyYV9yZWZyZXNoPTAgcmM9Y3FwIG1idHJlZT0wIHFwPTAAgAAAAD5liISscR8A+E4ACAACFoAAITAAAgsAAPgYCoKgoC+L4vi+KAvi+L4YfAEAACMzgABF9AAEUGUgABDJiXnf4AAAAARBmiKUAAAABEGaQpQAAAAEQZpilAAAAARBmoKU":"data:video/ogg;base64,T2dnUwACAAAAAAAAAABmnCATAAAAAHDEixYBKoB0aGVvcmEDAgEAAQABAAAQAAAQAAAAAAAFAAAAAQAAAAAAAAAAAGIAYE9nZ1MAAAAAAAAAAAAAZpwgEwEAAAACrA7TDlj///////////////+QgXRoZW9yYSsAAABYaXBoLk9yZyBsaWJ0aGVvcmEgMS4xIDIwMDkwODIyIChUaHVzbmVsZGEpAQAAABoAAABFTkNPREVSPWZmbXBlZzJ0aGVvcmEtMC4yOYJ0aGVvcmG+zSj3uc1rGLWpSUoQc5zmMYxSlKQhCDGMYhCEIQhAAAAAAAAAAAAAEW2uU2eSyPxWEvx4OVts5ir1aKtUKBMpJFoQ/nk5m41mUwl4slUpk4kkghkIfDwdjgajQYC8VioUCQRiIQh8PBwMhgLBQIg4FRba5TZ5LI/FYS/Hg5W2zmKvVoq1QoEykkWhD+eTmbjWZTCXiyVSmTiSSCGQh8PB2OBqNBgLxWKhQJBGIhCHw8HAyGAsFAiDgUCw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDAwPEhQUFQ0NDhESFRUUDg4PEhQVFRUOEBETFBUVFRARFBUVFRUVEhMUFRUVFRUUFRUVFRUVFRUVFRUVFRUVEAwLEBQZGxwNDQ4SFRwcGw4NEBQZHBwcDhATFhsdHRwRExkcHB4eHRQYGxwdHh4dGxwdHR4eHh4dHR0dHh4eHRALChAYKDM9DAwOExo6PDcODRAYKDlFOA4RFh0zV1A+EhYlOkRtZ00YIzdAUWhxXDFATldneXhlSFxfYnBkZ2MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEhIVGRoaGhoSFBYaGhoaGhUWGRoaGhoaGRoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhESFh8kJCQkEhQYIiQkJCQWGCEkJCQkJB8iJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQREhgvY2NjYxIVGkJjY2NjGBo4Y2NjY2MvQmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRISEhUXGBkbEhIVFxgZGxwSFRcYGRscHRUXGBkbHB0dFxgZGxwdHR0YGRscHR0dHhkbHB0dHR4eGxwdHR0eHh4REREUFxocIBERFBcaHCAiERQXGhwgIiUUFxocICIlJRcaHCAiJSUlGhwgIiUlJSkcICIlJSUpKiAiJSUlKSoqEBAQFBgcICgQEBQYHCAoMBAUGBwgKDBAFBgcICgwQEAYHCAoMEBAQBwgKDBAQEBgICgwQEBAYIAoMEBAQGCAgAfF5cdH1e3Ow/L66wGmYnfIUbwdUTe3LMRbqON8B+5RJEvcGxkvrVUjTMrsXYhAnIwe0dTJfOYbWrDYyqUrz7dw/JO4hpmV2LsQQvkUeGq1BsZLx+cu5iV0e0eScJ91VIQYrmqfdVSK7GgjOU0oPaPOu5IcDK1mNvnD+K8LwS87f8Jx2mHtHnUkTGAurWZlNQa74ZLSFH9oF6FPGxzLsjQO5Qe0edcpttd7BXBSqMCL4k/4tFrHIPuEQ7m1/uIWkbDMWVoDdOSuRQ9286kvVUlQjzOE6VrNguN4oRXYGkgcnih7t13/9kxvLYKQezwLTrO44sVmMPgMqORo1E0sm1/9SludkcWHwfJwTSybR4LeAz6ugWVgRaY8mV/9SluQmtHrzsBtRF/wPY+X0JuYTs+ltgrXAmlk10xQHmTu9VSIAk1+vcvU4ml2oNzrNhEtQ3CysNP8UeR35wqpKUBdGdZMSjX4WVi8nJpdpHnbhzEIdx7mwf6W1FKAiucMXrWUWVjyRf23chNtR9mIzDoT/6ZLYailAjhFlZuvPtSeZ+2oREubDoWmT3TguY+JHPdRVSLKxfKH3vgNqJ/9emeEYikGXDFNzaLjvTeGAL61mogOoeG3y6oU4rW55ydoj0lUTSR/mmRhPmF86uwIfzp3FtiufQCmppaHDlGE0r2iTzXIw3zBq5hvaTldjG4CPb9wdxAme0SyedVKczJ9AtYbgPOzYKJvZZImsN7ecrxWZg5dR6ZLj/j4qpWsIA+vYwE+Tca9ounMIsrXMB4Stiib2SPQtZv+FVIpfEbzv8ncZoLBXc3YBqTG1HsskTTotZOYTG+oVUjLk6zhP8bg4RhMUNtfZdO7FdpBuXzhJ5Fh8IKlJG7wtD9ik8rWOJxy6iQ3NwzBpQ219mlyv+FLicYs2iJGSE0u2txzed++D61ZWCiHD/cZdQVCqkO2gJpdpNaObhnDfAPrT89RxdWFZ5hO3MseBSIlANppdZNIV/Rwe5eLTDvkfWKzFnH+QJ7m9QWV1KdwnuIwTNtZdJMoXBf74OhRnh2t+OTGL+AVUnIkyYY+QG7g9itHXyF3OIygG2s2kud679ZWKqSFa9n3IHD6MeLv1lZ0XyduRhiDRtrNnKoyiFVLcBm0ba5Yy3fQkDh4XsFE34isVpOzpa9nR8iCpS4HoxG2rJpnRhf3YboVa1PcRouh5LIJv/uQcPNd095ickTaiGBnWLKVWRc0OnYTSyex/n2FofEPnDG8y3PztHrzOLK1xo6RAml2k9owKajOC0Wr4D5x+3nA0UEhK2m198wuBHF3zlWWVKWLN1CHzLClUfuoYBcx4b1llpeBKmbayaR58njtE9onD66lUcsg0Spm2snsb+8HaJRn4dYcLbCuBuYwziB8/5U1C1DOOz2gZjSZtrLJk6vrLF3hwY4Io9xuT/ruUFRSBkNtUzTOWhjh26irLEPx4jPZL3Fo3QrReoGTTM21xYTT9oFdhTUIvjqTkfkvt0bzgVUjq/hOYY8j60IaO/0AzRBtqkTS6R5ellZd5uKdzzhb8BFlDdAcrwkE0rbXTOPB+7Y0FlZO96qFL4Ykg21StJs8qIW7h16H5hGiv8V2Cflau7QVDepTAHa6Lgt6feiEvJDM21StJsmOH/hynURrKxvUpQ8BH0JF7BiyG2qZpnL/7AOU66gt+reLEXY8pVOCQvSsBtqZTNM8bk9ohRcwD18o/WVkbvrceVKRb9I59IEKysjBeTMmmbA21xu/6iHadLRxuIzkLpi8wZYmmbbWi32RVAUjruxWlJ//iFxE38FI9hNKOoCdhwf5fDe4xZ81lgREhK2m1j78vW1CqkuMu/AjBNK210kzRUX/B+69cMMUG5bYrIeZxVSEZISmkzbXOi9yxwIfPgdsov7R71xuJ7rFcACjG/9PzApqFq7wEgzNJm2suWESPuwrQvejj7cbnQxMkxpm21lUYJL0fKmogPPqywn7e3FvB/FCNxPJ85iVUkCE9/tLKx31G4CgNtWTTPFhMvlu8G4/TrgaZttTChljfNJGgOT2X6EqpETy2tYd9cCBI4lIXJ1/3uVUllZEJz4baqGF64yxaZ+zPLYwde8Uqn1oKANtUrSaTOPHkhvuQP3bBlEJ/LFe4pqQOHUI8T8q7AXx3fLVBgSCVpMba55YxN3rv8U1Dv51bAPSOLlZWebkL8vSMGI21lJmmeVxPRwFlZF1CpqCN8uLwymaZyjbXHCRytogPN3o/n74CNykfT+qqRv5AQlHcRxYrC5KvGmbbUwmZY/29BvF6C1/93x4WVglXDLFpmbapmF89HKTogRwqqSlGbu+oiAkcWFbklC6Zhf+NtTLFpn8oWz+HsNRVSgIxZWON+yVyJlE5tq/+GWLTMutYX9ekTySEQPLVNQQ3OfycwJBM0zNtZcse7CvcKI0V/zh16Dr9OSA21MpmmcrHC+6pTAPHPwoit3LHHqs7jhFNRD6W8+EBGoSEoaZttTCZljfduH/fFisn+dRBGAZYtMzbVMwvul/T/crK1NQh8gN0SRRa9cOux6clC0/mDLFpmbarmF8/e6CopeOLCNW6S/IUUg3jJIYiAcDoMcGeRbOvuTPjXR/tyo79LK3kqqkbxkkMRAOB0GODPItnX3Jnxro/25Ud+llbyVVSN4ySGIgHA6DHBnkWzr7kz410f7cqO/Syt5KqpFVJwn6gBEvBM0zNtZcpGOEPiysW8vvRd2R0f7gtjhqUvXL+gWVwHm4XJDBiMpmmZtrLfPwd/IugP5+fKVSysH1EXreFAcEhelGmbbUmZY4Xdo1vQWVnK19P4RuEnbf0gQnR+lDCZlivNM22t1ESmopPIgfT0duOfQrsjgG4tPxli0zJmF5trdL1JDUIUT1ZXSqQDeR4B8mX3TrRro/2McGeUvLtwo6jIEKMkCUXWsLyZROd9P/rFYNtXPBli0z398iVUlVKAjFlY437JXImUTm2r/4ZYtMy61hf16RPJIU9nZ1MABAwAAAAAAAAAZpwgEwIAAABhp658BScAAAAAAADnUFBQXIDGXLhwtttNHDhw5OcpQRMETBEwRPduylKVB0HRdF0A",c.setAttribute("autoplay",""),u.appendChild(c),c.addEventListener("playing",e),a=setTimeout(e,300),void 0):!1}),Modernizr.addTest("webintents",!!F("startActivity",navigator)),Modernizr.addTest("webgl","WebGLRenderingContext"in a),Modernizr.addAsyncTest(function(){if(Modernizr.webglextensions=new Boolean(!1),Modernizr.webgl){var a,b,d;try{a=w("canvas"),b=a.getContext("webgl")||a.getContext("experimental-webgl"),d=b.getSupportedExtensions()}catch(e){return}b!==c&&(Modernizr.webglextensions=new Boolean(!0));for(var f=-1,g=d.length;++f<g;)Modernizr.webglextensions[d[f]]=!0;a=c}}),Modernizr.addTest("getusermedia",!!F("getUserMedia",navigator)),Modernizr.addTest("peerconnection",!!F("RTCPeerConnection",a)),Modernizr.addTest("websocketsbinary",function(){var b,c="https:"==location.protocol?"wss":"ws";if("WebSocket"in a){if(b="binaryType"in WebSocket.prototype)return b;try{return!!new WebSocket(c+"://.").binaryType}catch(d){}}return!1}),Modernizr.addTest("websockets","WebSocket"in a&&2===a.WebSocket.CLOSING),Modernizr.addTest("framed",a.location!=top.location),Modernizr.addAsyncTest(function(){try{var b=a.MozBlobBuilder||a.WebKitBlobBuilder||a.MSBlobBuilder||a.OBlobBuilder||a.BlobBuilder,c=a.MozURL||a.webkitURL||a.MSURL||a.OURL||a.URL,d="Modernizr",e=new b;e.append("this.onmessage=function(e){postMessage(e.data)}");var f=c.createObjectURL(e.getBlob()),h=new Worker(f);e=null,h.onmessage=function(a){h.terminate(),c.revokeObjectURL(f),g("blobworkers",d===a.data),h=null},h.onerror=function(){g("blobworkers",!1),h=null},setTimeout(function(){g("blobworkers",!1)},200),h.postMessage(d)}catch(i){g("blobworkers",!1)}}),Modernizr.addAsyncTest(function(){try{var a="Modernizr",b=new Worker("data:text/javascript;base64,dGhpcy5vbm1lc3NhZ2U9ZnVuY3Rpb24oZSl7cG9zdE1lc3NhZ2UoZS5kYXRhKX0=");b.onmessage=function(c){b.terminate(),g("dataworkers",a===c.data),b=null},b.onerror=function(){g("dataworkers",!1),b=null},setTimeout(function(){g("dataworkers",!1)},200),b.postMessage(a)}catch(c){setTimeout(function(){g("dataworkers",!1)},0)}}),Modernizr.addTest("sharedworkers","SharedWorker"in a),Modernizr.addTest("webworkers","Worker"in a),e(),f(t),delete r.addTest,delete r.addAsyncTest;for(var U=0;U<Modernizr._q.length;U++)Modernizr._q[U]();a.Modernizr=Modernizr}(this,document);
\ No newline at end of file +/*! Modernizr 3.0.0pre (Custom Build) | MIT */!function(a,b,c){function d(a,b){return typeof a===b}function e(){var a,b,c,e,f,g,h;for(var i in q){if(a=[],b=q[i],b.name&&(a.push(b.name.toLowerCase()),b.options&&b.options.aliases&&b.options.aliases.length))for(c=0;c<b.options.aliases.length;c++)a.push(b.options.aliases[c].toLowerCase());for(e=d(b.fn,"function")?b.fn():b.fn,f=0;f<a.length;f++)g=a[f],h=g.split("."),1===h.length?Modernizr[h[0]]=e:2===h.length&&(Modernizr[h[0]][h[1]]=e),t.push((e?"":"no-")+h.join("-"))}}function f(a){var b,c=u.className,d=[],e=Modernizr._config.classPrefix||"",f=new RegExp("(^|\\s)"+e+"no-js(\\s|$)");if(c=c.replace(f,"$1"+e+"js$2"),Modernizr._config.enableClasses){for(var g=0;g<a.length;g++)a[g].match("^no-")||d.push("no-"+a[g]);b=new RegExp("(^|\\s)"+d.join("|")+"(\\s|$)","g"),c=c.replace(b,"$1$2"),c+=" "+e+a.join(" "+e),u.className=c}}function g(a,b){if("object"==typeof a)for(var c in a)s(a,c)&&g(c,a[c]);else{a=a.toLowerCase();var d=a.split("."),e=Modernizr[d[0]];if(2==d.length&&(e=e[d[1]]),"undefined"!=typeof e)return Modernizr;b="function"==typeof b?b():b,1==d.length?Modernizr[d[0]]=b:2==d.length&&(Modernizr[d[0]][d[1]]=b),f([(b?"":"no-")+d.join("-")]),Modernizr._trigger(a,b)}return Modernizr}function h(a,b){return!!~(""+a).indexOf(b)}function i(){var a=b.body;return a||(a=w("body"),a.fake=!0),a}function j(a,b,c,d){var e,f,g,h,j="modernizr",k=w("div"),l=i();if(parseInt(c,10))for(;c--;)g=w("div"),g.id=d?d[c]:j+(c+1),k.appendChild(g);return e=["­",'<style id="s',j,'">',a,"</style>"].join(""),k.id=j,(l.fake?l:k).innerHTML+=e,l.appendChild(k),l.fake&&(l.style.background="",l.style.overflow="hidden",h=u.style.overflow,u.style.overflow="hidden",u.appendChild(l)),f=b(k,a),l.fake?(l.parentNode.removeChild(l),u.style.overflow=h,u.offsetHeight):k.parentNode.removeChild(k),!!f}function k(a){return a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-")}function l(b,d){var e=b.length;if("CSS"in a&&"supports"in a.CSS){for(;e--;)if(a.CSS.supports(k(b[e]),d))return!0;return!1}if("CSSSupportsRule"in a){for(var f=[];e--;)f.push("("+k(b[e])+":"+d+")");return f=f.join(" or "),j("@supports ("+f+") { #modernizr { position: absolute; } }",function(b){return"absolute"==(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position})}return c}function m(a,b,e,f){function g(){j&&(delete y.style,delete y.modElem)}if(f=d(f,"undefined")?!1:f,!d(e,"undefined")){var i=l(a,e);if(!d(i,"undefined"))return i}var j,k,m,n;y.style||(j=!0,y.modElem=w("modernizr"),y.style=y.modElem.style);for(k in a)if(m=a[k],n=y.style[m],!h(m,"-")&&y.style[m]!==c){if(f||d(e,"undefined"))return g(),"pfx"==b?m:!0;try{y.style[m]=e}catch(o){}if(y.style[m]!=n)return g(),"pfx"==b?m:!0}return g(),!1}function n(a,b,c){var e;for(var f in a)if(a[f]in b)return c===!1?a[f]:(e=b[a[f]],d(e,"function")&&"bind"in e?e.bind(c||b):e);return!1}function o(a,b,c,e,f){var g=a.charAt(0).toUpperCase()+a.slice(1),h=(a+" "+C.join(g+" ")+g).split(" ");return d(b,"string")||d(b,"undefined")?m(h,b,e,f):(h=(a+" "+D.join(g+" ")+g).split(" "),n(h,b,c))}function p(a,b,d){return o(a,c,c,b,d)}var q=[],r={_version:"v3.0.0pre",_config:{classPrefix:"",enableClasses:!0},_q:[],on:function(a,b){setTimeout(function(){b(this[a])},0)},addTest:function(a,b,c){q.push({name:a,fn:b,options:c})},addAsyncTest:function(a){q.push({name:null,fn:a})}},Modernizr=function(){};Modernizr.prototype=r,Modernizr=new Modernizr;var s,t=[],u=b.documentElement;!function(){var a={}.hasOwnProperty;s=d(a,"undefined")||d(a.call,"undefined")?function(a,b){return b in a&&d(a.constructor.prototype[b],"undefined")}:function(b,c){return a.call(b,c)}}(),r._l={},r.on=function(a,b){this._l[a]||(this._l[a]=[]),this._l[a].push(b),Modernizr.hasOwnProperty(a)&&setTimeout(function(){Modernizr._trigger(a,Modernizr[a])},0)},r._trigger=function(a,b){if(this._l[a]){var c=this._l[a];setTimeout(function(){var a,d;for(a=0;a<c.length;a++)d=c[a],d(b)},0),delete this._l[a]}},Modernizr._q.push(function(){r.addTest=g});var v;!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=v.elements;return"string"==typeof a?a.split(" "):a}function e(a){var b=x[a[u]];return b||(b={},w++,a[u]=w,x[w]=b),b}function f(a,c,d){if(c||(c=b),p)return c.createElement(a);d||(d=e(c));var f;return f=d.cache[a]?d.cache[a].cloneNode():t.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),f.canHaveChildren&&!s.test(a)?d.frag.appendChild(f):f}function g(a,c){if(a||(a=b),p)return a.createDocumentFragment();c=c||e(a);for(var f=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)f.createElement(h[g]);return f}function h(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return v.shivMethods?f(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(v,b.frag)}function i(a){a||(a=b);var d=e(a);return!v.shivCSS||o||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}")),p||h(a,d),a}function j(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(k(b)));return g}function k(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(z+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function l(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+z+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function m(a){for(var b=a.length;b--;)a[b].removeNode()}function n(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,f,g=e(a),h=a.namespaces,i=a.parentWindow;return!A||a.printShived?a:("undefined"==typeof h[z]&&h.add(z),i.attachEvent("onbeforeprint",function(){b();for(var e,g,h,i=a.styleSheets,k=[],m=i.length,n=Array(m);m--;)n[m]=i[m];for(;h=n.pop();)if(!h.disabled&&y.test(h.media)){try{e=h.imports,g=e.length}catch(o){g=0}for(m=0;g>m;m++)n.push(e[m]);try{k.push(h.cssText)}catch(o){}}k=l(k.reverse().join("")),f=j(a),d=c(a,k)}),i.attachEvent("onafterprint",function(){m(f),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var o,p,q="3.6.2",r=a.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,t=/^(?: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,u="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",o="hidden"in a,p=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){o=!0,p=!0}}(),v={elements:r.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:q,shivCSS:r.shivCSS!==!1,supportsUnknownElements:p,shivMethods:r.shivMethods!==!1,type:"default",shivDocument:i,createElement:f,createDocumentFragment:g},a.html5=v,i(b);var y=/^$|\b(?:all|print)\b/,z="html5shiv",A=!p&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();v.type+=" print",v.shivPrint=n,n(b)}(this,b),function(a,b,c){function d(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function e(a,c,e,f,h,i){var j,k,m=b.createElement("script");f=f||l.errorTimeout,m.src=a;for(k in e)m.setAttribute(k,e[k]);c=i?g:c||s,m.onreadystatechange=m.onload=function(){!j&&d(m.readyState)&&(j=1,c(),m.onload=m.onreadystatechange=null)},n(function(){j||(j=1,c(1))},f),E(),h?m.onload():o.parentNode.insertBefore(m,o)}function f(a,c,d,e,f,h){var i,j=b.createElement("link");e=e||l.errorTimeout,c=h?g:c||s,j.href=a,j.rel="stylesheet",j.type="text/css";for(i in d)j.setAttribute(i,d[i]);f||(E(),o.parentNode.insertBefore(j,o),n(c,0))}function g(){var a=q.shift();r=1,a?a.t?n(function(){("c"==a.t?l.injectCss:l.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),g()):r=0}function h(a,c,e,f,h,i,j){function k(b){if(!p&&d(m.readyState)&&(t.r=p=1,!r&&g(),b)){"img"!=a&&n(function(){v.removeChild(m)},50);for(var e in G[c])G[c].hasOwnProperty(e)&&G[c][e].onload();m.onload=m.onreadystatechange=null}}j=j||l.errorTimeout;var m=b.createElement(a),p=0,s=0,t={t:e,s:c,e:h,a:i,x:j};1===G[c]&&(s=1,G[c]=[]),"object"==a?(m.data=c,m.setAttribute("type","text/css")):(m.src=c,m.type=a),m.width=m.height="0",m.onerror=m.onload=m.onreadystatechange=function(){k.call(this,s)},q.splice(f,0,t),"img"!=a&&(s||2===G[c]?(E(),v.insertBefore(m,u?null:o),n(k,j)):G[c].push(m))}function i(a,b,c,d,e){return r=0,b=b||"j",C(a)?h("c"==b?z:y,a,b,this.i++,c,d,e):(q.splice(this.i++,0,a),1==q.length&&g()),this}function j(){var a=l;return a.loader={load:i,i:0},a}var k,l,m=b.documentElement,n=a.setTimeout,o=b.getElementsByTagName("script")[0],p={}.toString,q=[],r=0,s=function(){},t="MozAppearance"in m.style,u=t&&!!b.createRange().compareNode,v=u?m:o.parentNode,w=a.opera&&"[object Opera]"==p.call(a.opera),x=!!b.attachEvent&&!w,y=t?"object":x?"script":"img",z=x?"script":y,A=Array.isArray||function(a){return"[object Array]"==p.call(a)},B=function(a){return Object(a)===a},C=function(a){return"string"==typeof a},D=function(a){return"[object Function]"==p.call(a)},E=function(){o&&o.parentNode||(o=b.getElementsByTagName("script")[0])},F=[],G={},H={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}};l=function(a){function b(a){var b,c,d,e=a.split("!"),f=F.length,g=e.pop(),h=e.length,i={url:g,origUrl:g,prefixes:e};for(c=0;h>c;c++)d=e[c].split("="),b=H[d.shift()],b&&(i=b(i,d));for(c=0;f>c;c++)i=F[c](i);return i}function d(a){var b=a.split("?")[0];return b.substr(b.lastIndexOf(".")+1)}function e(a,e,f,g,h){{var i=b(a),k=i.autoCallback;d(i.url)}if(!i.bypass)return e&&(e=D(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(G[i.url]&&i.reexecute!==!0?i.noexec=!0:G[i.url]=1,a&&f.load(i.url,i.forceCSS||!i.forceJS&&"css"==d(i.url)?"c":c,i.noexec,i.attrs,i.timeout),(D(e)||D(k))&&f.load(function(){j(),e&&e(i.origUrl,h,g),k&&k(i.origUrl,h,g),G[i.url]=2}),void 0)}function f(a,b){function c(a,c){if(""===a||a){if(C(a))c||(i=function(){var a=[].slice.call(arguments);j.apply(this,a),k()}),e(a,i,b,0,f);else if(B(a)){d=function(){var b,c=0;for(b in a)a.hasOwnProperty(b)&&c++;return c}();for(var g in a)a.hasOwnProperty(g)&&(c||--d||(D(i)?i=function(){var a=[].slice.call(arguments);j.apply(this,a),k()}:i[g]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),k()}}(j[g])),e(a[g],i,b,g,f))}}else!c&&k()}var d,f=!!a.test,g=f?a.yep:a.nope,h=a.load||a.both,i=a.callback||s,j=i,k=a.complete||s;c(g,!!h||!!a.complete),h&&c(h),!h&&!!a.complete&&c("")}var g,h,i=this.yepnope.loader;if(C(a))e(a,0,i,0);else if(A(a))for(g=0;g<a.length;g++)h=a[g],C(h)?e(h,0,i,0):A(h)?l(h):B(h)&&f(h,i);else B(a)&&f(a,i)},l.addPrefix=function(a,b){H[a]=b},l.addFilter=function(a){F.push(a)},l.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",k=function(){b.removeEventListener("DOMContentLoaded",k,0),b.readyState="complete"},0)),a.yepnope=j(),a.yepnope.executeStack=g,a.yepnope.injectJs=e,a.yepnope.injectCss=f}(a,b),r.load=function(){a.yepnope.apply(a,[].slice.call(arguments,0))};var w=function(){return b.createElement.apply(b,arguments)},x={elem:w("modernizr")};Modernizr._q.push(function(){delete x.elem});var y={style:x.elem.style};Modernizr._q.unshift(function(){delete y.style});var z=r.testProp=function(a,b,d){return m([a],c,b,d)},A=t.slice;Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=A.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(A.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(A.call(arguments)))};return d}),Modernizr.addTest("adownload",!a.externalHost&&"download"in w("a")),Modernizr.addTest("applicationcache","applicationCache"in a),Modernizr.addTest("webaudio","webkitAudioContext"in a||"AudioContext"in a),Modernizr.addTest("audio",function(){var a=w("audio"),b=!1;try{(b=!!a.canPlayType)&&(b=new Boolean(b),b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),b.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),b.opus=a.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),b.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),b.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,""))}catch(c){}return b});var B="Webkit Moz O ms",C=B.split(" ");r._cssomPrefixes=C;var D=B.toLowerCase().split(" ");r._domPrefixes=D;var E=" -webkit- -moz- -o- -ms- ".split(" ");r._prefixes=E,r.testAllProps=o;var F=r.prefixed=function(a,b,c){return b?o(a,b,c):o(a,"pfx")};Modernizr.addTest("lowbattery",function(){var a=.2,b=F("battery",navigator);return!!(b&&!b.charging&&b.level<=a)}),Modernizr.addTest("batteryapi",!!F("battery",navigator),{aliases:["battery-api"]}),Modernizr.addTest("blobconstructor",function(){try{return!!new Blob}catch(a){return!1}},{aliases:["blob-constructor"]}),Modernizr.addTest("canvas",function(){var a=w("canvas");return!(!a.getContext||!a.getContext("2d"))});var G=w("canvas");Modernizr.addTest("todataurljpeg",function(){return!!Modernizr.canvas&&0===G.toDataURL("image/jpeg").indexOf("data:image/jpeg")}),Modernizr.addTest("todataurlpng",function(){return!!Modernizr.canvas&&0===G.toDataURL("image/png").indexOf("data:image/png")}),Modernizr.addTest("todataurlwebp",function(){return!!Modernizr.canvas&&0===G.toDataURL("image/webp").indexOf("data:image/webp")}),Modernizr.addTest("canvastext",function(){return Modernizr.canvas===!1?!1:"function"==typeof w("canvas").getContext("2d").fillText}),Modernizr.addTest("getrandomvalues","crypto"in a&&"getRandomValues"in a.crypto),Modernizr.addTest("contenteditable",function(){if("contentEditable"in u){var a=w("div");return a.contentEditable=!0,"true"===a.contentEditable}}),Modernizr.addTest("contentsecuritypolicy","SecurityPolicy"in b),Modernizr.addTest("contextmenu","contextMenu"in u&&"HTMLMenuItemElement"in a),Modernizr.addTest("cookies",function(){b.cookie="cookietest=1";var a=-1!=b.cookie.indexOf("cookietest=");return b.cookie="cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT",a}),Modernizr.addTest("cors","XMLHttpRequest"in a&&"withCredentials"in new XMLHttpRequest),r.testAllProps=p,Modernizr.addTest("cssanimations",p("animationName","a",!0)),Modernizr.addTest("backgroundcliptext",function(){return p("backgroundClip","text")}),Modernizr.addTest("bgpositionshorthand",function(){var a=w("a"),b=a.style,c="right 10px bottom 10px";return b.cssText="background-position: "+c+";",b.backgroundPosition===c}),Modernizr.addTest("bgpositionxy",function(){return p("backgroundPositionX","3px",!0)&&p("backgroundPositionY","5px",!0)}),Modernizr.addTest("bgrepeatround",p("backgroundRepeat","round")),Modernizr.addTest("bgrepeatspace",p("backgroundRepeat","space")),Modernizr.addTest("backgroundsize",p("backgroundSize","100%",!0)),Modernizr.addTest("bgsizecover",p("backgroundSize","cover")),Modernizr.addTest("borderimage",p("borderImage","url() 1",!0)),Modernizr.addTest("borderradius",p("borderRadius","0px",!0)),Modernizr.addTest("boxshadow",p("boxShadow","1px 1px",!0)),Modernizr.addTest("boxsizing",p("boxSizing","border-box",!0)&&(b.documentMode===c||b.documentMode>7)),Modernizr.addTest("csscalc",function(){var a="width:",b="calc(10px);",c=w("div");return c.style.cssText=a+E.join(b+a),!!c.style.length});var H=r.testStyles=j;Modernizr.addTest("checked",function(){return H("#modernizr {position:absolute} #modernizr input {margin-left:10px} #modernizr :checked {margin-left:20px;display:block}",function(a){var b=w("input");return b.setAttribute("type","checkbox"),b.setAttribute("checked","checked"),a.appendChild(b),20===b.offsetLeft})}),function(){Modernizr.addTest("csscolumns",function(){var a=!1,b=p("columnCount");try{(a=!!b)&&(a=new Boolean(a))}catch(c){}return a});for(var a,b,c=["Width","Span","Fill","Gap","Rule","RuleColor","RuleStyle","RuleWidth","BreakBefore","BreakAfter","BreakInside"],d=0;d<c.length;d++)a=c[d].toLowerCase(),b=p("column"+c[d]),("breakbefore"===a||"breakafter"===a||"breakinside"==a)&&(b=b||p(c[d])),Modernizr.addTest("csscolumns."+a,b)}(),Modernizr.addTest("cubicbezierrange",function(){var a=w("div");return a.style.cssText=E.join("transition-timing-function:cubic-bezier(1,0,0,1.1); "),!!a.style.length}),Modernizr.addTest("displayrunin",p("display","run-in"),{aliases:["display-runin"]}),H("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(a){var b,c=a.children;b=c[0].offsetLeft<c[1].offsetLeft,Modernizr.addTest("displaytable",b,{aliases:["display-table"]})},2),Modernizr.addTest("ellipsis",p("textOverflow","ellipsis")),Modernizr.addTest("cssfilters",function(){var a=w("div");return a.style.cssText=E.join("filter:blur(2px); "),!!a.style.length&&(b.documentMode===c||b.documentMode>9)}),Modernizr.addTest("flexbox",p("flexBasis","1px",!0)),Modernizr.addTest("flexboxlegacy",p("boxDirection","reverse",!0)),Modernizr.addTest("flexboxtweener",p("flexAlign","end",!0)),H('@font-face {font-family:"font";src:url("https://")}',function(a,c){var d=b.getElementById("smodernizr"),e=d.sheet||d.styleSheet,f=e?e.cssRules&&e.cssRules[0]?e.cssRules[0].cssText:e.cssText||"":"",g=/src/i.test(f)&&0===f.indexOf(c.split(" ")[0]);Modernizr.addTest("fontface",g)}),H('#modernizr{font:0/0 a}#modernizr:after{content:":)";visibility:hidden;font:7px/1 a}',function(a){Modernizr.addTest("generatedcontent",a.offsetHeight>=7)}),Modernizr.addTest("cssgradients",function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);",d=(a+"-webkit- ".split(" ").join(b+a)+E.join(c+a)).slice(0,-a.length),e=w("div"),f=e.style;return f.cssText=d,(""+f.backgroundImage).indexOf("gradient")>-1}),Modernizr.addTest("hsla",function(){var a=w("div"),b=a.style;return b.cssText="background-color:hsla(120,40%,100%,.5)",h(b.backgroundColor,"rgba")||h(b.backgroundColor,"hsla")}),Modernizr.addAsyncTest(function(){function c(){function e(){try{var a=w("div"),c=w("span"),d=a.style,e=0,f=0,g=!1,h=b.body.firstElementChild||b.body.firstChild;return a.appendChild(c),c.innerHTML="Bacon ipsum dolor sit amet jerky velit in culpa hamburger et. Laborum dolor proident, enim dolore duis commodo et strip steak. Salami anim et, veniam consectetur dolore qui tenderloin jowl velit sirloin. Et ad culpa, fatback cillum jowl ball tip ham hock nulla short ribs pariatur aute. Pig pancetta ham bresaola, ut boudin nostrud commodo flank esse cow tongue culpa. Pork belly bresaola enim pig, ea consectetur nisi. Fugiat officia turkey, ea cow jowl pariatur ullamco proident do laborum velit sausage. Magna biltong sint tri-tip commodo sed bacon, esse proident aliquip. Ullamco ham sint fugiat, velit in enim sed mollit nulla cow ut adipisicing nostrud consectetur. Proident dolore beef ribs, laborum nostrud meatball ea laboris rump cupidatat labore culpa. Shankle minim beef, velit sint cupidatat fugiat tenderloin pig et ball tip. Ut cow fatback salami, bacon ball tip et in shank strip steak bresaola. In ut pork belly sed mollit tri-tip magna culpa veniam, short ribs qui in andouille ham consequat. Dolore bacon t-bone, velit short ribs enim strip steak nulla. Voluptate labore ut, biltong swine irure jerky. Cupidatat excepteur aliquip salami dolore. Ball tip strip steak in pork dolor. Ad in esse biltong. Dolore tenderloin exercitation ad pork loin t-bone, dolore in chicken ball tip qui pig. Ut culpa tongue, sint ribeye dolore ex shank voluptate hamburger. Jowl et tempor, boudin pork chop labore ham hock drumstick consectetur tri-tip elit swine meatball chicken ground round. Proident shankle mollit dolore. Shoulder ut duis t-bone quis reprehenderit. Meatloaf dolore minim strip steak, laboris ea aute bacon beef ribs elit shank in veniam drumstick qui. Ex laboris meatball cow tongue pork belly. Ea ball tip reprehenderit pig, sed fatback boudin dolore flank aliquip laboris eu quis. Beef ribs duis beef, cow corned beef adipisicing commodo nisi deserunt exercitation. Cillum dolor t-bone spare ribs, ham hock est sirloin. Brisket irure meatloaf in, boudin pork belly sirloin ball tip. Sirloin sint irure nisi nostrud aliqua. Nostrud nulla aute, enim officia culpa ham hock. Aliqua reprehenderit dolore sunt nostrud sausage, ea boudin pork loin ut t-bone ham tempor. Tri-tip et pancetta drumstick laborum. Ham hock magna do nostrud in proident. Ex ground round fatback, venison non ribeye in.",b.body.insertBefore(a,h),d.cssText="position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;",e=c.offsetHeight,f=c.offsetWidth,d.cssText="position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;"+E.join("hyphens:auto; "),g=c.offsetHeight!=e||c.offsetWidth!=f,b.body.removeChild(a),a.removeChild(c),g}catch(i){return!1}}function f(a,c){try{var d=w("div"),e=w("span"),f=d.style,g=0,h=!1,i=!1,j=!1,k=b.body.firstElementChild||b.body.firstChild;return f.cssText="position:absolute;top:0;left:0;overflow:visible;width:1.25em;",d.appendChild(e),b.body.insertBefore(d,k),e.innerHTML="mm",g=e.offsetHeight,e.innerHTML="m"+a+"m",i=e.offsetHeight>g,c?(e.innerHTML="m<br />m",g=e.offsetWidth,e.innerHTML="m"+a+"m",j=e.offsetWidth>g):j=!0,i===!0&&j===!0&&(h=!0),b.body.removeChild(d),d.removeChild(e),h}catch(l){return!1}}function h(c){try{var d,e=w("input"),f=w("div"),g="lebowski",h=!1,i=b.body.firstElementChild||b.body.firstChild;if(f.innerHTML=g+c+g,b.body.insertBefore(f,i),b.body.insertBefore(e,f),e.setSelectionRange?(e.focus(),e.setSelectionRange(0,0)):e.createTextRange&&(d=e.createTextRange(),d.collapse(!0),d.moveEnd("character",0),d.moveStart("character",0),d.select()),a.find)h=a.find(g+g);else try{d=a.self.document.body.createTextRange(),h=d.findText(g+g)}catch(j){h=!1}return b.body.removeChild(f),b.body.removeChild(e),h}catch(j){return!1}}return b.body||b.getElementsByTagName("body")[0]?(g("csshyphens",function(){if(!p("hyphens","auto",!0))return!1;try{return e()}catch(a){return!1}}),g("softhyphens",function(){try{return f("­",!0)&&f("​",!1)}catch(a){return!1}}),g("softhyphensfind",function(){try{return h("­")&&h("​")}catch(a){return!1}}),void 0):(setTimeout(c,d),void 0)}var d=300;setTimeout(c,d)}),H("#modernizr div {width:100px} #modernizr :last-child{width:200px;display:block}",function(a){Modernizr.addTest("lastchild",a.lastChild.offsetWidth>a.firstChild.offsetWidth)},2),Modernizr.addTest("cssmask",p("maskRepeat","repeat-x",!0));var I=function(){var b=a.matchMedia||a.msMatchMedia;return b?function(a){var c=b(a);return c&&c.matches||!1}:function(b){var c=!1;return j("@media "+b+" { #modernizr { position: absolute; } }",function(b){c="absolute"==(a.getComputedStyle?a.getComputedStyle(b,null):b.currentStyle).position}),c}}(),J=r.mq=I;Modernizr.addTest("mediaqueries",J("only all")),Modernizr.addTest("multiplebgs",function(){var a=w("div"),b=a.style;return b.cssText="background:url(https://),url(https://),red url(https://)",/(url\s*\(.*?){3}/.test(b.background)}),Modernizr.addTest("objectfit",!!F("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("opacity",function(){var a=w("div"),b=a.style;return b.cssText=E.join("opacity:.55;"),/^0.55$/.test(b.opacity)}),Modernizr.addTest("overflowscrolling",p("overflowScrolling","touch",!0)),Modernizr.addTest("csspointerevents",function(){var a=w("x");return a.style.cssText="pointer-events:auto","auto"===a.style.pointerEvents}),Modernizr.addTest("csspositionsticky",function(){var a="position:",b="sticky",c=w("modernizr"),d=c.style;return d.cssText=a+E.join(b+";"+a).slice(0,-a.length),-1!==d.position.indexOf(b)}),Modernizr.addTest("csspseudoanimations",function(){var b=!1;if(!Modernizr.cssanimations||!a.getComputedStyle)return b;var c=["@",Modernizr._prefixes.join("keyframes csspseudoanimations { from { font-size: 10px; } }@").replace(/\@$/,""),'#modernizr:before { content:" "; font-size:5px;',Modernizr._prefixes.join("animation:csspseudoanimations 1ms infinite;"),"}"].join("");return Modernizr.testStyles(c,function(c){b="10px"===a.getComputedStyle(c,":before").getPropertyValue("font-size")}),b}),Modernizr.addTest("csstransitions",p("transition","all",!0)),Modernizr.addTest("csspseudotransitions",function(){var b=!1;if(!Modernizr.csstransitions||!a.getComputedStyle)return b;var c='#modernizr:before { content:" "; font-size:5px;'+Modernizr._prefixes.join("transition:0s 100s;")+"}#modernizr.trigger:before { font-size:10px; }";return Modernizr.testStyles(c,function(c){a.getComputedStyle(c,":before").getPropertyValue("font-size"),c.className+="trigger",b="5px"===a.getComputedStyle(c,":before").getPropertyValue("font-size")}),b}),Modernizr.addTest("cssreflections",p("boxReflect","above",!0)),Modernizr.addTest("regions",function(){var a=Modernizr.prefixed("flowFrom"),b=Modernizr.prefixed("flowInto");if(!a||!b)return!1;var d=w("div"),e=w("div"),f=w("div"),g="modernizr_flow_for_regions_check";e.innerText="M",d.style.cssText="top: 150px; left: 150px; padding: 0px;",f.style.cssText="width: 50px; height: 50px; padding: 42px;",f.style[a]=g,d.appendChild(e),d.appendChild(f),u.appendChild(d);var h,i,j=e.getBoundingClientRect();return e.style[b]=g,h=e.getBoundingClientRect(),i=parseInt(h.left-j.left,10),u.removeChild(d),e=f=d=c,42==i}),Modernizr.addTest("cssremunit",function(){var a=w("div");try{a.style.fontSize="3rem"}catch(b){}return/rem/.test(a.style.fontSize)}),Modernizr.addTest("cssresize",p("resize","both",!0)),Modernizr.addTest("rgba",function(){var a=w("div"),b=a.style;return b.cssText="background-color:rgba(150,255,150,.5)",(""+b.backgroundColor).indexOf("rgba")>-1}),H("#modernizr{overflow: scroll; width: 40px; height: 40px; }#"+E.join("scrollbar{width:0px} #modernizr::").split("#").slice(1).join("#")+"scrollbar{width:0px}",function(a){Modernizr.addTest("cssscrollbar",40==a.scrollWidth)}),Modernizr.addTest("shapes",function(){var b=F("shapeOutside");if(!b)return!1;var c=b.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-");return H("#modernizr { float: left; "+c+":rectangle(0,0,0,0,0,0) }",function(b){var c=a.getComputedStyle?getComputedStyle(b,null):b.currentStyle;return"rectangle(0px, 0px, 0px, 0px, 0px, 0px)"==c[F("shapeOutside",u.style,!1)]})}),Modernizr.addTest("siblinggeneral",function(){return H("#modernizr div {width:100px} #modernizr div ~ div {width:200px;display:block}",function(a){return 200==a.lastChild.offsetWidth},2)}),H("#modernizr{position: absolute; top: -10em; visibility:hidden; font: normal 10px arial;}#subpixel{float: left; font-size: 33.3333%;}",function(b){var c=b.firstChild;c.innerHTML="This is a text written in Arial",Modernizr.addTest("subpixelfont",a.getComputedStyle?"44px"!==a.getComputedStyle(c,null).getPropertyValue("width"):!1)},1,["subpixel"]),Modernizr.addTest("supports","CSSSupportsRule"in a),Modernizr.addTest("textshadow",z("textShadow","1px 1px")),Modernizr.addTest("csstransforms",p("transform","scale(1)",!0)),Modernizr.addTest("preserve3d",p("transformStyle","preserve-3d")),Modernizr.addTest("csstransforms3d",function(){var a=!!p("perspective","1px",!0);return a&&"webkitPerspective"in u.style&&H("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:5px;margin:0;padding:0;border:0}}",function(b){a=9===b.offsetLeft&&5===b.offsetHeight}),a}),Modernizr.addTest("userselect",p("userSelect","none",!0)),H("#modernizr { height: 50vh; }",function(b){var c=parseInt(a.innerHeight/2,10),d=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).height,10);Modernizr.addTest("cssvhunit",d==c)}),H("#modernizr { width: 50vmax; }",function(b){var c=a.innerWidth/100,d=a.innerHeight/100,e=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).width,10);Modernizr.addTest("cssvmaxunit",parseInt(50*Math.max(c,d),10)==e)}),H("#modernizr { width: 50vmin; }",function(b){var c=a.innerWidth/100,d=a.innerHeight/100,e=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).width,10);Modernizr.addTest("cssvminunit",parseInt(50*Math.min(c,d),10)==e)}),H("#modernizr { width: 50vw; }",function(b){var c=parseInt(a.innerWidth/2,10),d=parseInt((a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).width,10);Modernizr.addTest("cssvwunit",d==c)}),Modernizr.addTest("wrapflow",function(){var a=F("wrapFlow");if(!a)return!1;var b=a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()}).replace(/^ms-/,"-ms-"),d=w("div"),e=w("div"),f=w("span");e.style.cssText="position: absolute; left: 50px; width: 100px; height: 20px;"+b+":end;",f.innerText="X",d.appendChild(e),d.appendChild(f),u.appendChild(d);var g=f.offsetLeft;return u.removeChild(d),e=f=d=c,150==g}),Modernizr.addTest("customprotocolhandler",!!navigator.registerProtocolHandler),Modernizr.addTest("dart",!!F("startDart",navigator)),Modernizr.addTest("dataview","undefined"!=typeof DataView&&"getFloat64"in DataView.prototype),Modernizr.addTest("classlist","classList"in u),Modernizr.addTest("createelementattrs",function(){try{return"test"==w('<input name="test" />').getAttribute("name")}catch(a){return!1}},{aliases:["createelement-attrs"]}),Modernizr.addTest("dataset",function(){var a=w("div");return a.setAttribute("data-a-b","c"),!(!a.dataset||"c"!==a.dataset.aB)}),Modernizr.addTest("microdata","getItems"in b),Modernizr.addTest("draganddrop",function(){var a=w("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a});var K={},L="autocomplete autofocus list placeholder max min multiple pattern required step".split(" "),M=w("input");Modernizr.input=function(b){for(var c=0,d=b.length;d>c;c++)K[b[c]]=!!(b[c]in M);return K.list&&(K.list=!(!w("datalist")||!a.HTMLDataListElement)),K}(L),Modernizr.addTest("datalistelem",Modernizr.input.list),Modernizr.addTest("details",function(){var a,b=w("details");return"open"in b?(H("#modernizr details{display:block}",function(c){c.appendChild(b),b.innerHTML="<summary>a</summary>b",a=b.offsetHeight,b.open=!0,a=a!=b.offsetHeight}),a):!1}),Modernizr.addTest("outputelem","value"in w("output")),Modernizr.addTest("progressbar",w("progress").max!==c),Modernizr.addTest("meter",w("meter").max!==c),Modernizr.addTest("ruby",function(){function c(c,d){var e;return a.getComputedStyle?e=b.defaultView.getComputedStyle(c,null).getPropertyValue(d):c.currentStyle&&(e=c.currentStyle[d]),e}function d(){u.removeChild(e),e=null,f=null,g=null}var e=w("ruby"),f=w("rt"),g=w("rp"),h="display",i="fontSize";return e.appendChild(g),e.appendChild(f),u.appendChild(e),"none"==c(g,h)||"ruby"==c(e,h)&&"ruby-text"==c(f,h)||"6pt"==c(g,i)&&"6pt"==c(f,i)?(d(),!0):(d(),!1)}),Modernizr.addTest("time","valueAsDate"in w("time")),Modernizr.addTest("texttrackapi","function"==typeof w("video").addTextTrack),Modernizr.addTest("track","kind"in w("track")),Modernizr.addTest("emoji",function(){if(!Modernizr.canvastext)return!1;var a=w("canvas"),b=a.getContext("2d");return b.textBaseline="top",b.font="32px Arial",b.fillText("\ud83d\ude03",0,0),0!==b.getImageData(16,16,1,1).data[0]}),Modernizr.addTest("strictmode",function(){return!this}()),Modernizr.addTest("contains",d(String.prototype.contains,"function")),Modernizr.addTest("devicemotion","DeviceMotionEvent"in a),Modernizr.addTest("deviceorientation","DeviceOrientationEvent"in a); +var N=function(a){function c(b,c){var e;return b?(c&&"string"!=typeof c||(c=w(c||"div")),b="on"+b,e=b in c,!e&&d&&(c.setAttribute||(c=w("div")),c.setAttribute&&c.removeAttribute&&(c.setAttribute(b,""),e="function"==typeof c[b],c[b]!==a&&(c[b]=a),c.removeAttribute(b))),e):!1}var d=!("onblur"in b.documentElement);return c}(),O=r.hasEvent=N;Modernizr.addTest("oninput",function(){var c=w("input");if(c.setAttribute("oninput","return"),O("oninput",u)||"function"==typeof c.oninput)return!0;try{var d=b.createEvent("KeyboardEvent"),e=!1,f=function(a){e=!0,a.preventDefault(),a.stopPropagation()};return d.initKeyEvent("keypress",!0,!0,a,!1,!1,!1,!1,0,"e".charCodeAt(0)),u.appendChild(c),c.addEventListener("input",f,!1),c.focus(),c.dispatchEvent(d),c.removeEventListener("input",f,!1),u.removeChild(c),e}catch(g){}}),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("exiforientation",!1,{aliases:["exif-orientation"]})},a.onload=function(){g("exiforientation",2!==a.width,{aliases:["exif-orientation"]})},a.src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q=="}),Modernizr.addTest("filereader",!!(a.File&&a.FileList&&a.FileReader)),Modernizr.addTest("filesystem",!!F("requestFileSystem",a)),Modernizr.addTest("fileinput",function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var a=w("input");return a.type="file",!a.disabled}),Modernizr.addTest("formattribute",function(){var a,c=w("form"),d=w("input"),e=w("div"),f="formtest"+(new Date).getTime(),g=!1;c.id=f;try{d.setAttribute("form",f)}catch(h){b.createAttribute&&(a=b.createAttribute("form"),a.nodeValue=f,d.setAttributeNode(a))}return e.appendChild(c),e.appendChild(d),u.appendChild(e),g=1===c.elements.length&&d.form==c,e.parentNode.removeChild(e),g}),Modernizr.addTest("localizednumber",function(){var a,c=w("div"),d=i(),e=function(){return u.insertBefore(d,u.firstElementChild||u.firstChild)}();c.innerHTML='<input type="number" value="1.0" step="0.1"/>';var f=c.childNodes[0];e.appendChild(c),f.focus();try{b.execCommand("InsertText",!1,"1,1")}catch(g){}return a="number"===f.type&&1.1===f.valueAsNumber&&f.checkValidity(),e.removeChild(c),d.fake&&e.parentNode.removeChild(e),a}),Modernizr.addTest("placeholder","placeholder"in w("input")&&"placeholder"in w("textarea")),Modernizr.addTest("speechinput",function(){var a=w("input");return"speech"in a||"onwebkitspeechchange"in a}),Modernizr.addTest("formvalidation",function(){var b=w("form");if(!("checkValidity"in b&&"addEventListener"in b))return!1;var c,d=!1;return Modernizr.formvalidationapi=!0,b.addEventListener("submit",function(b){a.opera||b.preventDefault(),b.stopPropagation()},!1),b.innerHTML='<input name="modTest" required><button></button>',H("#modernizr form{position:absolute;top:-99999em}",function(a){a.appendChild(b),c=b.getElementsByTagName("input")[0],c.addEventListener("invalid",function(a){d=!0,a.preventDefault(),a.stopPropagation()},!1),Modernizr.formvalidationmessage=!!c.validationMessage,b.getElementsByTagName("button")[0].click()}),d}),Modernizr.addTest("fullscreen",!(!F("exitFullscreen",b,!1)&&!F("cancelFullScreen",b,!1))),Modernizr.addTest("gamepads",!!F("getGamepads",navigator)),Modernizr.addTest("geolocation","geolocation"in navigator),Modernizr.addTest("hashchange",function(){return O("hashchange",a)===!1?!1:b.documentMode===c||b.documentMode>7}),Modernizr.addTest("history",function(){var b=navigator.userAgent;return-1!==b.indexOf("Android 2")&&-1!==b.indexOf("Mobile Safari")&&-1===b.indexOf("Chrome")?!1:a.history&&"pushState"in a.history}),Modernizr.addTest("ie8compat",!a.addEventListener&&!!b.documentMode&&7===b.documentMode),Modernizr.addTest("sandbox","sandbox"in w("iframe")),Modernizr.addTest("seamless","seamless"in w("iframe")),Modernizr.addTest("srcdoc","srcdoc"in w("iframe")),Modernizr.addAsyncTest(function(){if(!Modernizr.canvas)return!1;var a=new Image,b=w("canvas"),c=b.getContext("2d");a.onload=function(){g("apng",function(){return"undefined"==typeof b.getContext?!1:(c.drawImage(a,0,0),0===c.getImageData(0,0,1,1).data[3])})},a.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg=="}),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("webplossless",!1,{aliases:["webp-lossless"]})},a.onload=function(){g("webplossless",1==a.width,{aliases:["webp-lossless"]})},a.src="data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA="}),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("webp",!1)},a.onload=function(){g("webp",1==a.width)},a.src="data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA="}),Modernizr.addTest("indexeddb",!!F("indexedDB",a));var P="search tel url email datetime date month week time datetime-local number range color".split(" "),Q={},R=":)";Modernizr.inputtypes=function(a){for(var d,e,f,g=a.length,h=0;g>h;h++)M.setAttribute("type",e=a[h]),d="text"!==M.type,d&&(M.value=R,M.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(e)&&M.style.WebkitAppearance!==c?(u.appendChild(M),f=b.defaultView,d=f.getComputedStyle&&"textfield"!==f.getComputedStyle(M,null).WebkitAppearance&&0!==M.offsetHeight,u.removeChild(M)):/^(search|tel)$/.test(e)||(d=/^(url|email)$/.test(e)?M.checkValidity&&M.checkValidity()===!1:M.value!=R)),Q[a[h]]=!!d;return Q}(P),Modernizr.addTest("json","JSON"in a&&"parse"in JSON),Modernizr.addTest("olreversed","reversed"in w("ol")),Modernizr.addTest("mathml",function(){var a;return Modernizr.testStyles("#modernizr{position:absolute}",function(b){b.innerHTML="<math><mfrac><mi>xx</mi><mi>yy</mi></mfrac></math>",a=b.offsetHeight>b.offsetWidth}),a}),Modernizr.addTest("lowbandwidth",function(){var a=navigator.connection||{type:0};return 3==a.type||4==a.type||/^[23]g$/.test(a.type)}),Modernizr.addTest("eventsource","EventSource"in a),Modernizr.addTest("xhr2","FormData"in a);var S=function(a){if("undefined"==typeof XMLHttpRequest)return!1;var b=new XMLHttpRequest;b.open("get","/",!0);try{b.responseType=a}catch(c){return!1}return"response"in b&&b.responseType==a};Modernizr.addTest("xhrresponsetypearraybuffer",S("arraybuffer")),Modernizr.addTest("xhrresponsetypeblob",S("blob")),Modernizr.addTest("xhrresponsetypedocument",S("document")),Modernizr.addTest("xhrresponsetypejson",S("json")),Modernizr.addTest("xhrresponsetypetext",S("text")),Modernizr.addTest("xhrresponsetype",function(){if("undefined"==typeof XMLHttpRequest)return!1;var a=new XMLHttpRequest;return a.open("get","/",!0),"response"in a}()),Modernizr.addTest("notification","Notification"in a&&"permission"in a.Notification&&"requestPermission"in a.Notification),Modernizr.addTest("pagevisibility",!!F("hidden",b,!1)),Modernizr.addTest("performance",!!F("performance",a)),Modernizr.addTest("pointerevents",function(){var a=!1,b=D.length;for(a=Modernizr.hasEvent("pointerdown");b--&&!a;)O(D[b]+"pointerdown")&&(a=!0);return a}),Modernizr.addTest("pointerlock",!!F("exitPointerLock",b)),Modernizr.addTest("postmessage","postMessage"in a),Modernizr.addTest("quotamanagement",function(){var a=F("temporaryStorage",navigator),b=F("persistentStorage",navigator);return!(!a||!b)}),Modernizr.addTest("requestanimationframe",!!F("requestAnimationFrame",a),{aliases:["raf"]}),Modernizr.addTest("scriptasync","async"in w("script")),Modernizr.addTest("scriptdefer","defer"in w("script")),Modernizr.addTest("serviceworker","serviceWorker"in navigator),Modernizr.addTest("speechrecognition",!!F("SpeechRecognition",a)),Modernizr.addTest("speechsynthesis","SpeechSynthesisUtterance"in a),Modernizr.addTest("localstorage",function(){var a="modernizr";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(b){return!1}}),Modernizr.addTest("sessionstorage",function(){var a="modernizr";try{return sessionStorage.setItem(a,a),sessionStorage.removeItem(a),!0}catch(b){return!1}}),Modernizr.addTest("websqldatabase","openDatabase"in a),Modernizr.addTest("stylescoped","scoped"in w("style")),Modernizr.addAsyncTest(function(){var a=new Image;a.onerror=function(){g("svgasimg",!1)},a.onload=function(){g("svgasimg",1==a.width&&1==a.height)},a.src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg=="});var T={}.toString;Modernizr.addTest("svgclippaths",function(){return!!b.createElementNS&&/SVGClipPath/.test(T.call(b.createElementNS("http://www.w3.org/2000/svg","clipPath")))}),Modernizr.addTest("svgfilters",function(){var a=!1;try{a=typeof SVGFEColorMatrixElement!==c&&2==SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE}catch(b){}return a}),Modernizr.addTest("inlinesvg",function(){var a=w("div");return a.innerHTML="<svg/>","http://www.w3.org/2000/svg"==(a.firstChild&&a.firstChild.namespaceURI)}),Modernizr.addTest("smil",function(){return!!b.createElementNS&&/SVGAnimate/.test(T.call(b.createElementNS("http://www.w3.org/2000/svg","animate")))}),Modernizr.addTest("svg",!!b.createElementNS&&!!b.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect),Modernizr.addTest("touchevents",function(){var c;if("ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch)c=!0;else{var d=["@media (",E.join("touch-enabled),("),"heartz",")","{#modernizr{top:9px;position:absolute}}"].join("");H(d,function(a){c=9===a.offsetTop})}return c}),Modernizr.addTest("typedarrays","ArrayBuffer"in a),Modernizr.addTest("unicode",function(){var a,c=w("span"),d=b.createElement("span");return H("#modernizr{font-family:Arial,sans;font-size:300em;}",function(b){c.innerHTML="ᝣ",d.innerHTML="☆",b.appendChild(c),b.appendChild(d),a="offsetWidth"in c&&c.offsetWidth!==d.offsetWidth}),a}),Modernizr.addAsyncTest(function(){function a(){var a=new Image;a.onerror=function(){g("datauri",!0),Modernizr.datauri=new Boolean(!0),Modernizr.datauri.over32kb=!1},a.onload=function(){g("datauri",!0),Modernizr.datauri=new Boolean(!0),Modernizr.datauri.over32kb=1==a.width&&1==a.height};for(var b="R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";b.length<33e3;)b="\r\n"+b;a.src="data:image/gif;base64,"+b}-1!==navigator.userAgent.indexOf("MSIE 7.")&&setTimeout(function(){g("datauri",!1)},10);var b=new Image;b.onerror=function(){g("datauri",!1)},b.onload=function(){1==b.width&&1==b.height?a():g("datauri",!1)},b.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="}),Modernizr.addTest("userdata",!!w("div").addBehavior),Modernizr.addTest("vibrate",!!F("vibrate",navigator)),Modernizr.addTest("video",function(){var a=w("video"),b=!1;try{(b=!!a.canPlayType)&&(b=new Boolean(b),b.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,""))}catch(c){}return b}),Modernizr.addAsyncTest(function(){var a,c=b.createElement("video"),d=c.style,e=function(){clearTimeout(a),g("videoautoplay",0!==c.currentTime),c.parentNode.removeChild(c)};if(!(Modernizr.video&&"autoplay"in c))return!1;d.height=0,d.width=0;try{c.src=Modernizr.video.h264?"data:video/mp4;base64,AAAAHGZ0eXBtcDQyAAAAAG1wNDJpc29tYXZjMQAAAz5tb292AAAAbG12aGQAAAAAzaNacc2jWnEAAV+QAAFfkAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT////3//AAACQ3RyYWsAAABcdGtoZAAAAAHNo1pxzaNacQAAAAEAAAAAAAFfkAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAEAAAABAAAAAAAd9tZGlhAAAAIG1kaGQAAAAAzaNacc2jWnEAAV+QAAFfkFXEAAAAAAAhaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAAAAAAGWbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABVnN0YmwAAACpc3RzZAAAAAAAAAABAAAAmWF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAEAAQAEgAAABIAAAAAAAAAAEOSlZUL0FWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwH0AAr/4QAZZ/QACq609NQYBBkAAAMAAQAAAwAKjxImoAEABWjOAa8gAAAAEmNvbHJuY2xjAAYAAQAGAAAAGHN0dHMAAAAAAAAAAQAAAAUAAEZQAAAAKHN0c3oAAAAAAAAAAAAAAAUAAAIqAAAACAAAAAgAAAAIAAAACAAAAChzdHNjAAAAAAAAAAIAAAABAAAABAAAAAEAAAACAAAAAQAAAAEAAAAYc3RjbwAAAAAAAAACAAADYgAABaQAAAAUc3RzcwAAAAAAAAABAAAAAQAAABFzZHRwAAAAAAREREREAAAAb3VkdGEAAABnbWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcgAAAAAAAAAAAAAAAAAAAAA6aWxzdAAAADKpdG9vAAAAKmRhdGEAAAABAAAAAEhhbmRCcmFrZSAwLjkuOCAyMDEyMDcxODAwAAACUm1kYXQAAAHkBgX/4NxF6b3m2Ui3lizYINkj7u94MjY0IC0gY29yZSAxMjAgLSBILjI2NC9NUEVHLTQgQVZDIGNvZGVjIC0gQ29weWxlZnQgMjAwMy0yMDExIC0gaHR0cDovL3d3dy52aWRlb2xhbi5vcmcveDI2NC5odG1sIC0gb3B0aW9uczogY2FiYWM9MCByZWY9MSBkZWJsb2NrPTE6MDowIGFuYWx5c2U9MHgxOjAgbWU9ZXNhIHN1Ym1lPTkgcHN5PTAgbWl4ZWRfcmVmPTAgbWVfcmFuZ2U9NCBjaHJvbWFfbWU9MSB0cmVsbGlzPTAgOHg4ZGN0PTAgY3FtPTAgZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0wIGNocm9tYV9xcF9vZmZzZXQ9MCB0aHJlYWRzPTYgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTUwIGtleWludF9taW49NSBzY2VuZWN1dD00MCBpbnRyYV9yZWZyZXNoPTAgcmM9Y3FwIG1idHJlZT0wIHFwPTAAgAAAAD5liISscR8A+E4ACAACFoAAITAAAgsAAPgYCoKgoC+L4vi+KAvi+L4YfAEAACMzgABF9AAEUGUgABDJiXnf4AAAAARBmiKUAAAABEGaQpQAAAAEQZpilAAAAARBmoKU":"data:video/ogg;base64,T2dnUwACAAAAAAAAAABmnCATAAAAAHDEixYBKoB0aGVvcmEDAgEAAQABAAAQAAAQAAAAAAAFAAAAAQAAAAAAAAAAAGIAYE9nZ1MAAAAAAAAAAAAAZpwgEwEAAAACrA7TDlj///////////////+QgXRoZW9yYSsAAABYaXBoLk9yZyBsaWJ0aGVvcmEgMS4xIDIwMDkwODIyIChUaHVzbmVsZGEpAQAAABoAAABFTkNPREVSPWZmbXBlZzJ0aGVvcmEtMC4yOYJ0aGVvcmG+zSj3uc1rGLWpSUoQc5zmMYxSlKQhCDGMYhCEIQhAAAAAAAAAAAAAEW2uU2eSyPxWEvx4OVts5ir1aKtUKBMpJFoQ/nk5m41mUwl4slUpk4kkghkIfDwdjgajQYC8VioUCQRiIQh8PBwMhgLBQIg4FRba5TZ5LI/FYS/Hg5W2zmKvVoq1QoEykkWhD+eTmbjWZTCXiyVSmTiSSCGQh8PB2OBqNBgLxWKhQJBGIhCHw8HAyGAsFAiDgUCw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDAwPEhQUFQ0NDhESFRUUDg4PEhQVFRUOEBETFBUVFRARFBUVFRUVEhMUFRUVFRUUFRUVFRUVFRUVFRUVFRUVEAwLEBQZGxwNDQ4SFRwcGw4NEBQZHBwcDhATFhsdHRwRExkcHB4eHRQYGxwdHh4dGxwdHR4eHh4dHR0dHh4eHRALChAYKDM9DAwOExo6PDcODRAYKDlFOA4RFh0zV1A+EhYlOkRtZ00YIzdAUWhxXDFATldneXhlSFxfYnBkZ2MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEhIVGRoaGhoSFBYaGhoaGhUWGRoaGhoaGRoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhESFh8kJCQkEhQYIiQkJCQWGCEkJCQkJB8iJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQREhgvY2NjYxIVGkJjY2NjGBo4Y2NjY2MvQmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRISEhUXGBkbEhIVFxgZGxwSFRcYGRscHRUXGBkbHB0dFxgZGxwdHR0YGRscHR0dHhkbHB0dHR4eGxwdHR0eHh4REREUFxocIBERFBcaHCAiERQXGhwgIiUUFxocICIlJRcaHCAiJSUlGhwgIiUlJSkcICIlJSUpKiAiJSUlKSoqEBAQFBgcICgQEBQYHCAoMBAUGBwgKDBAFBgcICgwQEAYHCAoMEBAQBwgKDBAQEBgICgwQEBAYIAoMEBAQGCAgAfF5cdH1e3Ow/L66wGmYnfIUbwdUTe3LMRbqON8B+5RJEvcGxkvrVUjTMrsXYhAnIwe0dTJfOYbWrDYyqUrz7dw/JO4hpmV2LsQQvkUeGq1BsZLx+cu5iV0e0eScJ91VIQYrmqfdVSK7GgjOU0oPaPOu5IcDK1mNvnD+K8LwS87f8Jx2mHtHnUkTGAurWZlNQa74ZLSFH9oF6FPGxzLsjQO5Qe0edcpttd7BXBSqMCL4k/4tFrHIPuEQ7m1/uIWkbDMWVoDdOSuRQ9286kvVUlQjzOE6VrNguN4oRXYGkgcnih7t13/9kxvLYKQezwLTrO44sVmMPgMqORo1E0sm1/9SludkcWHwfJwTSybR4LeAz6ugWVgRaY8mV/9SluQmtHrzsBtRF/wPY+X0JuYTs+ltgrXAmlk10xQHmTu9VSIAk1+vcvU4ml2oNzrNhEtQ3CysNP8UeR35wqpKUBdGdZMSjX4WVi8nJpdpHnbhzEIdx7mwf6W1FKAiucMXrWUWVjyRf23chNtR9mIzDoT/6ZLYailAjhFlZuvPtSeZ+2oREubDoWmT3TguY+JHPdRVSLKxfKH3vgNqJ/9emeEYikGXDFNzaLjvTeGAL61mogOoeG3y6oU4rW55ydoj0lUTSR/mmRhPmF86uwIfzp3FtiufQCmppaHDlGE0r2iTzXIw3zBq5hvaTldjG4CPb9wdxAme0SyedVKczJ9AtYbgPOzYKJvZZImsN7ecrxWZg5dR6ZLj/j4qpWsIA+vYwE+Tca9ounMIsrXMB4Stiib2SPQtZv+FVIpfEbzv8ncZoLBXc3YBqTG1HsskTTotZOYTG+oVUjLk6zhP8bg4RhMUNtfZdO7FdpBuXzhJ5Fh8IKlJG7wtD9ik8rWOJxy6iQ3NwzBpQ219mlyv+FLicYs2iJGSE0u2txzed++D61ZWCiHD/cZdQVCqkO2gJpdpNaObhnDfAPrT89RxdWFZ5hO3MseBSIlANppdZNIV/Rwe5eLTDvkfWKzFnH+QJ7m9QWV1KdwnuIwTNtZdJMoXBf74OhRnh2t+OTGL+AVUnIkyYY+QG7g9itHXyF3OIygG2s2kud679ZWKqSFa9n3IHD6MeLv1lZ0XyduRhiDRtrNnKoyiFVLcBm0ba5Yy3fQkDh4XsFE34isVpOzpa9nR8iCpS4HoxG2rJpnRhf3YboVa1PcRouh5LIJv/uQcPNd095ickTaiGBnWLKVWRc0OnYTSyex/n2FofEPnDG8y3PztHrzOLK1xo6RAml2k9owKajOC0Wr4D5x+3nA0UEhK2m198wuBHF3zlWWVKWLN1CHzLClUfuoYBcx4b1llpeBKmbayaR58njtE9onD66lUcsg0Spm2snsb+8HaJRn4dYcLbCuBuYwziB8/5U1C1DOOz2gZjSZtrLJk6vrLF3hwY4Io9xuT/ruUFRSBkNtUzTOWhjh26irLEPx4jPZL3Fo3QrReoGTTM21xYTT9oFdhTUIvjqTkfkvt0bzgVUjq/hOYY8j60IaO/0AzRBtqkTS6R5ellZd5uKdzzhb8BFlDdAcrwkE0rbXTOPB+7Y0FlZO96qFL4Ykg21StJs8qIW7h16H5hGiv8V2Cflau7QVDepTAHa6Lgt6feiEvJDM21StJsmOH/hynURrKxvUpQ8BH0JF7BiyG2qZpnL/7AOU66gt+reLEXY8pVOCQvSsBtqZTNM8bk9ohRcwD18o/WVkbvrceVKRb9I59IEKysjBeTMmmbA21xu/6iHadLRxuIzkLpi8wZYmmbbWi32RVAUjruxWlJ//iFxE38FI9hNKOoCdhwf5fDe4xZ81lgREhK2m1j78vW1CqkuMu/AjBNK210kzRUX/B+69cMMUG5bYrIeZxVSEZISmkzbXOi9yxwIfPgdsov7R71xuJ7rFcACjG/9PzApqFq7wEgzNJm2suWESPuwrQvejj7cbnQxMkxpm21lUYJL0fKmogPPqywn7e3FvB/FCNxPJ85iVUkCE9/tLKx31G4CgNtWTTPFhMvlu8G4/TrgaZttTChljfNJGgOT2X6EqpETy2tYd9cCBI4lIXJ1/3uVUllZEJz4baqGF64yxaZ+zPLYwde8Uqn1oKANtUrSaTOPHkhvuQP3bBlEJ/LFe4pqQOHUI8T8q7AXx3fLVBgSCVpMba55YxN3rv8U1Dv51bAPSOLlZWebkL8vSMGI21lJmmeVxPRwFlZF1CpqCN8uLwymaZyjbXHCRytogPN3o/n74CNykfT+qqRv5AQlHcRxYrC5KvGmbbUwmZY/29BvF6C1/93x4WVglXDLFpmbapmF89HKTogRwqqSlGbu+oiAkcWFbklC6Zhf+NtTLFpn8oWz+HsNRVSgIxZWON+yVyJlE5tq/+GWLTMutYX9ekTySEQPLVNQQ3OfycwJBM0zNtZcse7CvcKI0V/zh16Dr9OSA21MpmmcrHC+6pTAPHPwoit3LHHqs7jhFNRD6W8+EBGoSEoaZttTCZljfduH/fFisn+dRBGAZYtMzbVMwvul/T/crK1NQh8gN0SRRa9cOux6clC0/mDLFpmbarmF8/e6CopeOLCNW6S/IUUg3jJIYiAcDoMcGeRbOvuTPjXR/tyo79LK3kqqkbxkkMRAOB0GODPItnX3Jnxro/25Ud+llbyVVSN4ySGIgHA6DHBnkWzr7kz410f7cqO/Syt5KqpFVJwn6gBEvBM0zNtZcpGOEPiysW8vvRd2R0f7gtjhqUvXL+gWVwHm4XJDBiMpmmZtrLfPwd/IugP5+fKVSysH1EXreFAcEhelGmbbUmZY4Xdo1vQWVnK19P4RuEnbf0gQnR+lDCZlivNM22t1ESmopPIgfT0duOfQrsjgG4tPxli0zJmF5trdL1JDUIUT1ZXSqQDeR4B8mX3TrRro/2McGeUvLtwo6jIEKMkCUXWsLyZROd9P/rFYNtXPBli0z398iVUlVKAjFlY437JXImUTm2r/4ZYtMy61hf16RPJIU9nZ1MABAwAAAAAAAAAZpwgEwIAAABhp658BScAAAAAAADnUFBQXIDGXLhwtttNHDhw5OcpQRMETBEwRPduylKVB0HRdF0A"}catch(f){return!1}c.setAttribute("autoplay",""),u.appendChild(c),c.addEventListener("playing",e),a=setTimeout(e,300)}),Modernizr.addTest("webanimations","Animation"in a),Modernizr.addTest("webintents",!!F("startActivity",navigator)),Modernizr.addTest("webgl","WebGLRenderingContext"in a),Modernizr.addAsyncTest(function(){if(Modernizr.webglextensions=new Boolean(!1),Modernizr.webgl){var a,b,d;try{a=w("canvas"),b=a.getContext("webgl")||a.getContext("experimental-webgl"),d=b.getSupportedExtensions()}catch(e){return}b!==c&&(Modernizr.webglextensions=new Boolean(!0));for(var f=-1,g=d.length;++f<g;)Modernizr.webglextensions[d[f]]=!0;a=c}}),Modernizr.addTest("getusermedia",!!F("getUserMedia",navigator)),Modernizr.addTest("peerconnection",!!F("RTCPeerConnection",a)),Modernizr.addTest("websocketsbinary",function(){var b,c="https:"==location.protocol?"wss":"ws";if("WebSocket"in a){if(b="binaryType"in WebSocket.prototype)return b;try{return!!new WebSocket(c+"://.").binaryType}catch(d){}}return!1}),Modernizr.addTest("websockets","WebSocket"in a&&2===a.WebSocket.CLOSING),Modernizr.addTest("framed",a.location!=top.location),Modernizr.addAsyncTest(function(){try{var b=a.MozBlobBuilder||a.WebKitBlobBuilder||a.MSBlobBuilder||a.OBlobBuilder||a.BlobBuilder,c=a.MozURL||a.webkitURL||a.MSURL||a.OURL||a.URL,d="Modernizr",e=new b;e.append("this.onmessage=function(e){postMessage(e.data)}");var f=c.createObjectURL(e.getBlob()),h=new Worker(f);e=null,h.onmessage=function(a){h.terminate(),c.revokeObjectURL(f),g("blobworkers",d===a.data),h=null},h.onerror=function(){g("blobworkers",!1),h=null},setTimeout(function(){g("blobworkers",!1)},200),h.postMessage(d)}catch(i){g("blobworkers",!1)}}),Modernizr.addAsyncTest(function(){try{var a="Modernizr",b=new Worker("data:text/javascript;base64,dGhpcy5vbm1lc3NhZ2U9ZnVuY3Rpb24oZSl7cG9zdE1lc3NhZ2UoZS5kYXRhKX0=");b.onmessage=function(c){b.terminate(),g("dataworkers",a===c.data),b=null},b.onerror=function(){g("dataworkers",!1),b=null},setTimeout(function(){g("dataworkers",!1)},200),b.postMessage(a)}catch(c){setTimeout(function(){g("dataworkers",!1)},0)}}),Modernizr.addTest("sharedworkers","SharedWorker"in a),Modernizr.addTest("webworkers","Worker"in a),e(),f(t),delete r.addTest,delete r.addAsyncTest;for(var U=0;U<Modernizr._q.length;U++)Modernizr._q[U]();a.Modernizr=Modernizr}(this,document);
\ No newline at end of file |