modernizr-prefixed.js 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554
  1. /*!
  2. * modernizr v3.7.0
  3. * Build https://modernizr.com/download?-cors-input-smil-addtest-printshiv-setclasses-testprop-dontmin-cssclassprefix:prefixed-
  4. *
  5. * Copyright (c)
  6. * Faruk Ates
  7. * Paul Irish
  8. * Alex Sexton
  9. * Ryan Seddon
  10. * Patrick Kettner
  11. * Stu Cox
  12. * Richard Herrera
  13. * MIT License
  14. */
  15. /*
  16. * Modernizr tests which native CSS3 and HTML5 features are available in the
  17. * current UA and makes the results available to you in two ways: as properties on
  18. * a global `Modernizr` object, and as classes on the `<html>` element. This
  19. * information allows you to progressively enhance your pages with a granular level
  20. * of control over the experience.
  21. */
  22. ;(function(window, document, undefined){
  23. var tests = [];
  24. /**
  25. * ModernizrProto is the constructor for Modernizr
  26. *
  27. * @class
  28. * @access public
  29. */
  30. var ModernizrProto = {
  31. // The current version, dummy
  32. _version: '3.7.0',
  33. // Any settings that don't work as separate modules
  34. // can go in here as configuration.
  35. _config: {
  36. 'classPrefix': 'prefixed-',
  37. 'enableClasses': true,
  38. 'enableJSClass': true,
  39. 'usePrefixes': true
  40. },
  41. // Queue of tests
  42. _q: [],
  43. // Stub these for people who are listening
  44. on: function(test, cb) {
  45. // I don't really think people should do this, but we can
  46. // safe guard it a bit.
  47. // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
  48. // This is in case people listen to synchronous tests. I would leave it out,
  49. // but the code to *disallow* sync tests in the real version of this
  50. // function is actually larger than this.
  51. var self = this;
  52. setTimeout(function() {
  53. cb(self[test]);
  54. }, 0);
  55. },
  56. addTest: function(name, fn, options) {
  57. tests.push({name: name, fn: fn, options: options});
  58. },
  59. addAsyncTest: function(fn) {
  60. tests.push({name: null, fn: fn});
  61. }
  62. };
  63. // Fake some of Object.create so we can force non test results to be non "own" properties.
  64. var Modernizr = function() {};
  65. Modernizr.prototype = ModernizrProto;
  66. // Leak modernizr globally when you `require` it rather than force it here.
  67. // Overwrite name so constructor name is nicer :D
  68. Modernizr = new Modernizr();
  69. var classes = [];
  70. /**
  71. * is returns a boolean if the typeof an obj is exactly type.
  72. *
  73. * @access private
  74. * @function is
  75. * @param {*} obj - A thing we want to check the type of
  76. * @param {string} type - A string to compare the typeof against
  77. * @returns {boolean} true if the typeof the first parameter is exactly the specified type, false otherwise
  78. */
  79. function is(obj, type) {
  80. return typeof obj === type;
  81. }
  82. ;
  83. /**
  84. * Run through all tests and detect their support in the current UA.
  85. *
  86. * @access private
  87. * @returns {void}
  88. */
  89. function testRunner() {
  90. var featureNames;
  91. var feature;
  92. var aliasIdx;
  93. var result;
  94. var nameIdx;
  95. var featureName;
  96. var featureNameSplit;
  97. for (var featureIdx in tests) {
  98. if (tests.hasOwnProperty(featureIdx)) {
  99. featureNames = [];
  100. feature = tests[featureIdx];
  101. // run the test, throw the return value into the Modernizr,
  102. // then based on that boolean, define an appropriate className
  103. // and push it into an array of classes we'll join later.
  104. //
  105. // If there is no name, it's an 'async' test that is run,
  106. // but not directly added to the object. That should
  107. // be done with a post-run addTest call.
  108. if (feature.name) {
  109. featureNames.push(feature.name.toLowerCase());
  110. if (feature.options && feature.options.aliases && feature.options.aliases.length) {
  111. // Add all the aliases into the names list
  112. for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
  113. featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
  114. }
  115. }
  116. }
  117. // Run the test, or use the raw value if it's not a function
  118. result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
  119. // Set each of the names on the Modernizr object
  120. for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
  121. featureName = featureNames[nameIdx];
  122. // Support dot properties as sub tests. We don't do checking to make sure
  123. // that the implied parent tests have been added. You must call them in
  124. // order (either in the test, or make the parent test a dependency).
  125. //
  126. // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
  127. // hashtag famous last words
  128. featureNameSplit = featureName.split('.');
  129. if (featureNameSplit.length === 1) {
  130. Modernizr[featureNameSplit[0]] = result;
  131. } else {
  132. // cast to a Boolean, if not one already
  133. if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
  134. Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
  135. }
  136. Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
  137. }
  138. classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
  139. }
  140. }
  141. }
  142. }
  143. ;
  144. /**
  145. * docElement is a convenience wrapper to grab the root element of the document
  146. *
  147. * @access private
  148. * @returns {HTMLElement|SVGElement} The root element of the document
  149. */
  150. var docElement = document.documentElement;
  151. /**
  152. * A convenience helper to check if the document we are running in is an SVG document
  153. *
  154. * @access private
  155. * @returns {boolean}
  156. */
  157. var isSVG = docElement.nodeName.toLowerCase() === 'svg';
  158. /**
  159. * setClasses takes an array of class names and adds them to the root element
  160. *
  161. * @access private
  162. * @function setClasses
  163. * @param {string[]} classes - Array of class names
  164. */
  165. // Pass in an and array of class names, e.g.:
  166. // ['no-webp', 'borderradius', ...]
  167. function setClasses(classes) {
  168. var className = docElement.className;
  169. var classPrefix = Modernizr._config.classPrefix || '';
  170. if (isSVG) {
  171. className = className.baseVal;
  172. }
  173. // Change `no-js` to `js` (independently of the `enableClasses` option)
  174. // Handle classPrefix on this too
  175. if (Modernizr._config.enableJSClass) {
  176. var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
  177. className = className.replace(reJS, '$1' + classPrefix + 'js$2');
  178. }
  179. if (Modernizr._config.enableClasses) {
  180. // Add the new classes
  181. if (classes.length > 0) {
  182. className += ' ' + classPrefix + classes.join(' ' + classPrefix);
  183. }
  184. if (isSVG) {
  185. docElement.className.baseVal = className;
  186. } else {
  187. docElement.className = className;
  188. }
  189. }
  190. }
  191. ;
  192. /**
  193. * hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support
  194. *
  195. * @author kangax
  196. * @access private
  197. * @function hasOwnProp
  198. * @param {object} object - The object to check for a property
  199. * @param {string} property - The property to check for
  200. * @returns {boolean}
  201. */
  202. // hasOwnProperty shim by kangax needed for Safari 2.0 support
  203. var hasOwnProp;
  204. (function() {
  205. var _hasOwnProperty = ({}).hasOwnProperty;
  206. /* istanbul ignore else */
  207. /* we have no way of testing IE 5.5 or safari 2,
  208. * so just assume the else gets hit */
  209. if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
  210. hasOwnProp = function(object, property) {
  211. return _hasOwnProperty.call(object, property);
  212. };
  213. }
  214. else {
  215. hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
  216. return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
  217. };
  218. }
  219. })();
  220. // _l tracks listeners for async tests, as well as tests that execute after the initial run
  221. ModernizrProto._l = {};
  222. /**
  223. * Modernizr.on is a way to listen for the completion of async tests. Being
  224. * asynchronous, they may not finish before your scripts run. As a result you
  225. * will get a possibly false negative `undefined` value.
  226. *
  227. * @memberOf Modernizr
  228. * @name Modernizr.on
  229. * @access public
  230. * @function on
  231. * @param {string} feature - String name of the feature detect
  232. * @param {Function} cb - Callback function returning a Boolean - true if feature is supported, false if not
  233. * @returns {void}
  234. * @example
  235. *
  236. * ```js
  237. * Modernizr.on('flash', function( result ) {
  238. * if (result) {
  239. * // the browser has flash
  240. * } else {
  241. * // the browser does not have flash
  242. * }
  243. * });
  244. * ```
  245. */
  246. ModernizrProto.on = function(feature, cb) {
  247. // Create the list of listeners if it doesn't exist
  248. if (!this._l[feature]) {
  249. this._l[feature] = [];
  250. }
  251. // Push this test on to the listener list
  252. this._l[feature].push(cb);
  253. // If it's already been resolved, trigger it on next tick
  254. if (Modernizr.hasOwnProperty(feature)) {
  255. // Next Tick
  256. setTimeout(function() {
  257. Modernizr._trigger(feature, Modernizr[feature]);
  258. }, 0);
  259. }
  260. };
  261. /**
  262. * _trigger is the private function used to signal test completion and run any
  263. * callbacks registered through [Modernizr.on](#modernizr-on)
  264. *
  265. * @memberOf Modernizr
  266. * @name Modernizr._trigger
  267. * @access private
  268. * @function _trigger
  269. * @param {string} feature - string name of the feature detect
  270. * @param {Function|boolean} [res] - A feature detection function, or the boolean =
  271. * result of a feature detection function
  272. * @returns {void}
  273. */
  274. ModernizrProto._trigger = function(feature, res) {
  275. if (!this._l[feature]) {
  276. return;
  277. }
  278. var cbs = this._l[feature];
  279. // Force async
  280. setTimeout(function() {
  281. var i, cb;
  282. for (i = 0; i < cbs.length; i++) {
  283. cb = cbs[i];
  284. cb(res);
  285. }
  286. }, 0);
  287. // Don't trigger these again
  288. delete this._l[feature];
  289. };
  290. /**
  291. * addTest allows you to define your own feature detects that are not currently
  292. * included in Modernizr (under the covers it's the exact same code Modernizr
  293. * uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)).
  294. * Just like the official detects, the result
  295. * will be added onto the Modernizr object, as well as an appropriate className set on
  296. * the html element when configured to do so
  297. *
  298. * @memberOf Modernizr
  299. * @name Modernizr.addTest
  300. * @optionName Modernizr.addTest()
  301. * @optionProp addTest
  302. * @access public
  303. * @function addTest
  304. * @param {string|Object} feature - The string name of the feature detect, or an
  305. * object of feature detect names and test
  306. * @param {Function|boolean} test - Function returning true if feature is supported,
  307. * false if not. Otherwise a boolean representing the results of a feature detection
  308. * @returns {Object} the Modernizr object to allow chaining
  309. * @example
  310. *
  311. * The most common way of creating your own feature detects is by calling
  312. * `Modernizr.addTest` with a string (preferably just lowercase, without any
  313. * punctuation), and a function you want executed that will return a boolean result
  314. *
  315. * ```js
  316. * Modernizr.addTest('itsTuesday', function() {
  317. * var d = new Date();
  318. * return d.getDay() === 2;
  319. * });
  320. * ```
  321. *
  322. * When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday,
  323. * and to `false` every other day of the week. One thing to notice is that the names of
  324. * feature detect functions are always lowercased when added to the Modernizr object. That
  325. * means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will.
  326. *
  327. *
  328. * Since we only look at the returned value from any feature detection function,
  329. * you do not need to actually use a function. For simple detections, just passing
  330. * in a statement that will return a boolean value works just fine.
  331. *
  332. * ```js
  333. * Modernizr.addTest('hasjquery', 'jQuery' in window);
  334. * ```
  335. *
  336. * Just like before, when the above runs `Modernizr.hasjquery` will be true if
  337. * jQuery has been included on the page. Not using a function saves a small amount
  338. * of overhead for the browser, as well as making your code much more readable.
  339. *
  340. * Finally, you also have the ability to pass in an object of feature names and
  341. * their tests. This is handy if you want to add multiple detections in one go.
  342. * The keys should always be a string, and the value can be either a boolean or
  343. * function that returns a boolean.
  344. *
  345. * ```js
  346. * var detects = {
  347. * 'hasjquery': 'jQuery' in window,
  348. * 'itstuesday': function() {
  349. * var d = new Date();
  350. * return d.getDay() === 2;
  351. * }
  352. * }
  353. *
  354. * Modernizr.addTest(detects);
  355. * ```
  356. *
  357. * There is really no difference between the first methods and this one, it is
  358. * just a convenience to let you write more readable code.
  359. */
  360. function addTest(feature, test) {
  361. if (typeof feature === 'object') {
  362. for (var key in feature) {
  363. if (hasOwnProp(feature, key)) {
  364. addTest(key, feature[ key ]);
  365. }
  366. }
  367. } else {
  368. feature = feature.toLowerCase();
  369. var featureNameSplit = feature.split('.');
  370. var last = Modernizr[featureNameSplit[0]];
  371. // Again, we don't check for parent test existence. Get that right, though.
  372. if (featureNameSplit.length === 2) {
  373. last = last[featureNameSplit[1]];
  374. }
  375. if (typeof last !== 'undefined') {
  376. // we're going to quit if you're trying to overwrite an existing test
  377. // if we were to allow it, we'd do this:
  378. // var re = new RegExp("\\b(no-)?" + feature + "\\b");
  379. // docElement.className = docElement.className.replace( re, '' );
  380. // but, no rly, stuff 'em.
  381. return Modernizr;
  382. }
  383. test = typeof test === 'function' ? test() : test;
  384. // Set the value (this is the magic, right here).
  385. if (featureNameSplit.length === 1) {
  386. Modernizr[featureNameSplit[0]] = test;
  387. } else {
  388. // cast to a Boolean, if not one already
  389. if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
  390. Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
  391. }
  392. Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test;
  393. }
  394. // Set a single class (either `feature` or `no-feature`)
  395. setClasses([(!!test && test !== false ? '' : 'no-') + featureNameSplit.join('-')]);
  396. // Trigger the event
  397. Modernizr._trigger(feature, test);
  398. }
  399. return Modernizr; // allow chaining.
  400. }
  401. // After all the tests are run, add self to the Modernizr prototype
  402. Modernizr._q.push(function() {
  403. ModernizrProto.addTest = addTest;
  404. });
  405. /**
  406. * @optionName html5printshiv
  407. * @optionProp html5printshiv
  408. */
  409. // Take the html5 variable out of the html5shiv scope so we can return it.
  410. var html5;
  411. if (!isSVG) {
  412. /**
  413. * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
  414. */
  415. ;(function(window, document) {
  416. /*jshint evil:true */
  417. /** version */
  418. var version = '3.7.3';
  419. /** Preset options */
  420. var options = window.html5 || {};
  421. /** Used to skip problem elements */
  422. var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
  423. /** Not all elements can be cloned in IE **/
  424. 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;
  425. /** Detect whether the browser supports default html5 styles */
  426. var supportsHtml5Styles;
  427. /** Name of the expando, to work with multiple documents or to re-shiv one document */
  428. var expando = '_html5shiv';
  429. /** The id for the the documents expando */
  430. var expanID = 0;
  431. /** Cached data for each document */
  432. var expandoData = {};
  433. /** Detect whether the browser supports unknown elements */
  434. var supportsUnknownElements;
  435. (function() {
  436. try {
  437. var a = document.createElement('a');
  438. a.innerHTML = '<xyz></xyz>';
  439. //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
  440. supportsHtml5Styles = ('hidden' in a);
  441. supportsUnknownElements = a.childNodes.length == 1 || (function() {
  442. // assign a false positive if unable to shiv
  443. (document.createElement)('a');
  444. var frag = document.createDocumentFragment();
  445. return (
  446. typeof frag.cloneNode == 'undefined' ||
  447. typeof frag.createDocumentFragment == 'undefined' ||
  448. typeof frag.createElement == 'undefined'
  449. );
  450. }());
  451. } catch(e) {
  452. // assign a false positive if detection fails => unable to shiv
  453. supportsHtml5Styles = true;
  454. supportsUnknownElements = true;
  455. }
  456. }());
  457. /*--------------------------------------------------------------------------*/
  458. /**
  459. * Creates a style sheet with the given CSS text and adds it to the document.
  460. * @private
  461. * @param {Document} ownerDocument The document.
  462. * @param {String} cssText The CSS text.
  463. * @returns {StyleSheet} The style element.
  464. */
  465. function addStyleSheet(ownerDocument, cssText) {
  466. var p = ownerDocument.createElement('p'),
  467. parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
  468. p.innerHTML = 'x<style>' + cssText + '</style>';
  469. return parent.insertBefore(p.lastChild, parent.firstChild);
  470. }
  471. /**
  472. * Returns the value of `html5.elements` as an array.
  473. * @private
  474. * @returns {Array} An array of shived element node names.
  475. */
  476. function getElements() {
  477. var elements = html5.elements;
  478. return typeof elements == 'string' ? elements.split(' ') : elements;
  479. }
  480. /**
  481. * Extends the built-in list of html5 elements
  482. * @memberOf html5
  483. * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
  484. * @param {Document} ownerDocument The context document.
  485. */
  486. function addElements(newElements, ownerDocument) {
  487. var elements = html5.elements;
  488. if(typeof elements != 'string'){
  489. elements = elements.join(' ');
  490. }
  491. if(typeof newElements != 'string'){
  492. newElements = newElements.join(' ');
  493. }
  494. html5.elements = elements +' '+ newElements;
  495. shivDocument(ownerDocument);
  496. }
  497. /**
  498. * Returns the data associated to the given document
  499. * @private
  500. * @param {Document} ownerDocument The document.
  501. * @returns {Object} An object of data.
  502. */
  503. function getExpandoData(ownerDocument) {
  504. var data = expandoData[ownerDocument[expando]];
  505. if (!data) {
  506. data = {};
  507. expanID++;
  508. ownerDocument[expando] = expanID;
  509. expandoData[expanID] = data;
  510. }
  511. return data;
  512. }
  513. /**
  514. * returns a shived element for the given nodeName and document
  515. * @memberOf html5
  516. * @param {String} nodeName name of the element
  517. * @param {Document} ownerDocument The context document.
  518. * @returns {Object} The shived element.
  519. */
  520. function createElement(nodeName, ownerDocument, data){
  521. if (!ownerDocument) {
  522. ownerDocument = document;
  523. }
  524. if(supportsUnknownElements){
  525. return ownerDocument.createElement(nodeName);
  526. }
  527. if (!data) {
  528. data = getExpandoData(ownerDocument);
  529. }
  530. var node;
  531. if (data.cache[nodeName]) {
  532. node = data.cache[nodeName].cloneNode();
  533. } else if (saveClones.test(nodeName)) {
  534. node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
  535. } else {
  536. node = data.createElem(nodeName);
  537. }
  538. // Avoid adding some elements to fragments in IE < 9 because
  539. // * Attributes like `name` or `type` cannot be set/changed once an element
  540. // is inserted into a document/fragment
  541. // * Link elements with `src` attributes that are inaccessible, as with
  542. // a 403 response, will cause the tab/window to crash
  543. // * Script elements appended to fragments will execute when their `src`
  544. // or `text` property is set
  545. return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
  546. }
  547. /**
  548. * returns a shived DocumentFragment for the given document
  549. * @memberOf html5
  550. * @param {Document} ownerDocument The context document.
  551. * @returns {Object} The shived DocumentFragment.
  552. */
  553. function createDocumentFragment(ownerDocument, data){
  554. if (!ownerDocument) {
  555. ownerDocument = document;
  556. }
  557. if(supportsUnknownElements){
  558. return ownerDocument.createDocumentFragment();
  559. }
  560. data = data || getExpandoData(ownerDocument);
  561. var clone = data.frag.cloneNode(),
  562. i = 0,
  563. elems = getElements(),
  564. l = elems.length;
  565. for(;i<l;i++){
  566. clone.createElement(elems[i]);
  567. }
  568. return clone;
  569. }
  570. /**
  571. * Shivs the `createElement` and `createDocumentFragment` methods of the document.
  572. * @private
  573. * @param {Document|DocumentFragment} ownerDocument The document.
  574. * @param {Object} data of the document.
  575. */
  576. function shivMethods(ownerDocument, data) {
  577. if (!data.cache) {
  578. data.cache = {};
  579. data.createElem = ownerDocument.createElement;
  580. data.createFrag = ownerDocument.createDocumentFragment;
  581. data.frag = data.createFrag();
  582. }
  583. ownerDocument.createElement = function(nodeName) {
  584. //abort shiv
  585. if (!html5.shivMethods) {
  586. return data.createElem(nodeName);
  587. }
  588. return createElement(nodeName, ownerDocument, data);
  589. };
  590. ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
  591. 'var n=f.cloneNode(),c=n.createElement;' +
  592. 'h.shivMethods&&(' +
  593. // unroll the `createElement` calls
  594. getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
  595. data.createElem(nodeName);
  596. data.frag.createElement(nodeName);
  597. return 'c("' + nodeName + '")';
  598. }) +
  599. ');return n}'
  600. )(html5, data.frag);
  601. }
  602. /*--------------------------------------------------------------------------*/
  603. /**
  604. * Shivs the given document.
  605. * @memberOf html5
  606. * @param {Document} ownerDocument The document to shiv.
  607. * @returns {Document} The shived document.
  608. */
  609. function shivDocument(ownerDocument) {
  610. if (!ownerDocument) {
  611. ownerDocument = document;
  612. }
  613. var data = getExpandoData(ownerDocument);
  614. if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
  615. data.hasCSS = !!addStyleSheet(ownerDocument,
  616. // corrects block display not defined in IE6/7/8/9
  617. 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
  618. // adds styling not present in IE6/7/8/9
  619. 'mark{background:#FF0;color:#000}' +
  620. // hides non-rendered elements
  621. 'template{display:none}'
  622. );
  623. }
  624. if (!supportsUnknownElements) {
  625. shivMethods(ownerDocument, data);
  626. }
  627. return ownerDocument;
  628. }
  629. /*--------------------------------------------------------------------------*/
  630. /**
  631. * The `html5` object is exposed so that more elements can be shived and
  632. * existing shiving can be detected on iframes.
  633. * @type Object
  634. * @example
  635. *
  636. * // options can be changed before the script is included
  637. * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
  638. */
  639. var html5 = {
  640. /**
  641. * An array or space separated string of node names of the elements to shiv.
  642. * @memberOf html5
  643. * @type Array|String
  644. */
  645. 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
  646. /**
  647. * current version of html5shiv
  648. */
  649. 'version': version,
  650. /**
  651. * A flag to indicate that the HTML5 style sheet should be inserted.
  652. * @memberOf html5
  653. * @type Boolean
  654. */
  655. 'shivCSS': (options.shivCSS !== false),
  656. /**
  657. * Is equal to true if a browser supports creating unknown/HTML5 elements
  658. * @memberOf html5
  659. * @type boolean
  660. */
  661. 'supportsUnknownElements': supportsUnknownElements,
  662. /**
  663. * A flag to indicate that the document's `createElement` and `createDocumentFragment`
  664. * methods should be overwritten.
  665. * @memberOf html5
  666. * @type Boolean
  667. */
  668. 'shivMethods': (options.shivMethods !== false),
  669. /**
  670. * A string to describe the type of `html5` object ("default" or "default print").
  671. * @memberOf html5
  672. * @type String
  673. */
  674. 'type': 'default',
  675. // shivs the document according to the specified `html5` object options
  676. 'shivDocument': shivDocument,
  677. //creates a shived element
  678. createElement: createElement,
  679. //creates a shived documentFragment
  680. createDocumentFragment: createDocumentFragment,
  681. //extends list of elements
  682. addElements: addElements
  683. };
  684. /*--------------------------------------------------------------------------*/
  685. // expose html5
  686. window.html5 = html5;
  687. // shiv the document
  688. shivDocument(document);
  689. /*------------------------------- Print Shiv -------------------------------*/
  690. /** Used to filter media types */
  691. var reMedia = /^$|\b(?:all|print)\b/;
  692. /** Used to namespace printable elements */
  693. var shivNamespace = 'html5shiv';
  694. /** Detect whether the browser supports shivable style sheets */
  695. var supportsShivableSheets = !supportsUnknownElements && (function() {
  696. // assign a false negative if unable to shiv
  697. var docEl = document.documentElement;
  698. return !(
  699. typeof document.namespaces == 'undefined' ||
  700. typeof document.parentWindow == 'undefined' ||
  701. typeof docEl.applyElement == 'undefined' ||
  702. typeof docEl.removeNode == 'undefined' ||
  703. typeof window.attachEvent == 'undefined'
  704. );
  705. }());
  706. /*--------------------------------------------------------------------------*/
  707. /**
  708. * Wraps all HTML5 elements in the given document with printable elements.
  709. * (eg. the "header" element is wrapped with the "html5shiv:header" element)
  710. * @private
  711. * @param {Document} ownerDocument The document.
  712. * @returns {Array} An array wrappers added.
  713. */
  714. function addWrappers(ownerDocument) {
  715. var node,
  716. nodes = ownerDocument.getElementsByTagName('*'),
  717. index = nodes.length,
  718. reElements = RegExp('^(?:' + getElements().join('|') + ')$', 'i'),
  719. result = [];
  720. while (index--) {
  721. node = nodes[index];
  722. if (reElements.test(node.nodeName)) {
  723. result.push(node.applyElement(createWrapper(node)));
  724. }
  725. }
  726. return result;
  727. }
  728. /**
  729. * Creates a printable wrapper for the given element.
  730. * @private
  731. * @param {Element} element The element.
  732. * @returns {Element} The wrapper.
  733. */
  734. function createWrapper(element) {
  735. var node,
  736. nodes = element.attributes,
  737. index = nodes.length,
  738. wrapper = element.ownerDocument.createElement(shivNamespace + ':' + element.nodeName);
  739. // copy element attributes to the wrapper
  740. while (index--) {
  741. node = nodes[index];
  742. node.specified && wrapper.setAttribute(node.nodeName, node.nodeValue);
  743. }
  744. // copy element styles to the wrapper
  745. wrapper.style.cssText = element.style.cssText;
  746. return wrapper;
  747. }
  748. /**
  749. * Shivs the given CSS text.
  750. * (eg. header{} becomes html5shiv\:header{})
  751. * @private
  752. * @param {String} cssText The CSS text to shiv.
  753. * @returns {String} The shived CSS text.
  754. */
  755. function shivCssText(cssText) {
  756. var pair,
  757. parts = cssText.split('{'),
  758. index = parts.length,
  759. reElements = RegExp('(^|[\\s,>+~])(' + getElements().join('|') + ')(?=[[\\s,>+~#.:]|$)', 'gi'),
  760. replacement = '$1' + shivNamespace + '\\:$2';
  761. while (index--) {
  762. pair = parts[index] = parts[index].split('}');
  763. pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);
  764. parts[index] = pair.join('}');
  765. }
  766. return parts.join('{');
  767. }
  768. /**
  769. * Removes the given wrappers, leaving the original elements.
  770. * @private
  771. * @params {Array} wrappers An array of printable wrappers.
  772. */
  773. function removeWrappers(wrappers) {
  774. var index = wrappers.length;
  775. while (index--) {
  776. wrappers[index].removeNode();
  777. }
  778. }
  779. /*--------------------------------------------------------------------------*/
  780. /**
  781. * Shivs the given document for print.
  782. * @memberOf html5
  783. * @param {Document} ownerDocument The document to shiv.
  784. * @returns {Document} The shived document.
  785. */
  786. function shivPrint(ownerDocument) {
  787. var shivedSheet,
  788. wrappers,
  789. data = getExpandoData(ownerDocument),
  790. namespaces = ownerDocument.namespaces,
  791. ownerWindow = ownerDocument.parentWindow;
  792. if (!supportsShivableSheets || ownerDocument.printShived) {
  793. return ownerDocument;
  794. }
  795. if (typeof namespaces[shivNamespace] == 'undefined') {
  796. namespaces.add(shivNamespace);
  797. }
  798. function removeSheet() {
  799. clearTimeout(data._removeSheetTimer);
  800. if (shivedSheet) {
  801. shivedSheet.removeNode(true);
  802. }
  803. shivedSheet= null;
  804. }
  805. ownerWindow.attachEvent('onbeforeprint', function() {
  806. removeSheet();
  807. var imports,
  808. length,
  809. sheet,
  810. collection = ownerDocument.styleSheets,
  811. cssText = [],
  812. index = collection.length,
  813. sheets = Array(index);
  814. // convert styleSheets collection to an array
  815. while (index--) {
  816. sheets[index] = collection[index];
  817. }
  818. // concat all style sheet CSS text
  819. while ((sheet = sheets.pop())) {
  820. // IE does not enforce a same origin policy for external style sheets...
  821. // but has trouble with some dynamically created stylesheets
  822. if (!sheet.disabled && reMedia.test(sheet.media)) {
  823. try {
  824. imports = sheet.imports;
  825. length = imports.length;
  826. } catch(er){
  827. length = 0;
  828. }
  829. for (index = 0; index < length; index++) {
  830. sheets.push(imports[index]);
  831. }
  832. try {
  833. cssText.push(sheet.cssText);
  834. } catch(er){}
  835. }
  836. }
  837. // wrap all HTML5 elements with printable elements and add the shived style sheet
  838. cssText = shivCssText(cssText.reverse().join(''));
  839. wrappers = addWrappers(ownerDocument);
  840. shivedSheet = addStyleSheet(ownerDocument, cssText);
  841. });
  842. ownerWindow.attachEvent('onafterprint', function() {
  843. // remove wrappers, leaving the original elements, and remove the shived style sheet
  844. removeWrappers(wrappers);
  845. clearTimeout(data._removeSheetTimer);
  846. data._removeSheetTimer = setTimeout(removeSheet, 500);
  847. });
  848. ownerDocument.printShived = true;
  849. return ownerDocument;
  850. }
  851. /*--------------------------------------------------------------------------*/
  852. // expose API
  853. html5.type += ' print';
  854. html5.shivPrint = shivPrint;
  855. // shiv for print
  856. shivPrint(document);
  857. if(typeof module == 'object' && module.exports){
  858. module.exports = html5;
  859. }
  860. }(typeof window !== "undefined" ? window : this, document));
  861. }
  862. ;
  863. /**
  864. * contains checks to see if a string contains another string
  865. *
  866. * @access private
  867. * @function contains
  868. * @param {string} str - The string we want to check for substrings
  869. * @param {string} substr - The substring we want to search the first string for
  870. * @returns {boolean} true if and only if the first string 'str' contains the second string 'substr'
  871. */
  872. function contains(str, substr) {
  873. return !!~('' + str).indexOf(substr);
  874. }
  875. ;
  876. /**
  877. * createElement is a convenience wrapper around document.createElement. Since we
  878. * use createElement all over the place, this allows for (slightly) smaller code
  879. * as well as abstracting away issues with creating elements in contexts other than
  880. * HTML documents (e.g. SVG documents).
  881. *
  882. * @access private
  883. * @function createElement
  884. * @returns {HTMLElement|SVGElement} An HTML or SVG element
  885. */
  886. function createElement() {
  887. if (typeof document.createElement !== 'function') {
  888. // This is the case in IE7, where the type of createElement is "object".
  889. // For this reason, we cannot call apply() as Object is not a Function.
  890. return document.createElement(arguments[0]);
  891. } else if (isSVG) {
  892. return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
  893. } else {
  894. return document.createElement.apply(document, arguments);
  895. }
  896. }
  897. ;
  898. /**
  899. * Create our "modernizr" element that we do most feature tests on.
  900. *
  901. * @access private
  902. */
  903. var modElem = {
  904. elem: createElement('modernizr')
  905. };
  906. // Clean up this element
  907. Modernizr._q.push(function() {
  908. delete modElem.elem;
  909. });
  910. var mStyle = {
  911. style: modElem.elem.style
  912. };
  913. // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
  914. // the front of the queue.
  915. Modernizr._q.unshift(function() {
  916. delete mStyle.style;
  917. });
  918. /**
  919. * getBody returns the body of a document, or an element that can stand in for
  920. * the body if a real body does not exist
  921. *
  922. * @access private
  923. * @function getBody
  924. * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
  925. * artificially created element that stands in for the body
  926. */
  927. function getBody() {
  928. // After page load injecting a fake body doesn't work so check if body exists
  929. var body = document.body;
  930. if (!body) {
  931. // Can't use the real body create a fake one.
  932. body = createElement(isSVG ? 'svg' : 'body');
  933. body.fake = true;
  934. }
  935. return body;
  936. }
  937. ;
  938. /**
  939. * injectElementWithStyles injects an element with style element and some CSS rules
  940. *
  941. * @access private
  942. * @function injectElementWithStyles
  943. * @param {string} rule - String representing a css rule
  944. * @param {Function} callback - A function that is used to test the injected element
  945. * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
  946. * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
  947. * @returns {boolean} the result of the specified callback test
  948. */
  949. function injectElementWithStyles(rule, callback, nodes, testnames) {
  950. var mod = 'modernizr';
  951. var style;
  952. var ret;
  953. var node;
  954. var docOverflow;
  955. var div = createElement('div');
  956. var body = getBody();
  957. if (parseInt(nodes, 10)) {
  958. // In order not to give false positives we create a node for each test
  959. // This also allows the method to scale for unspecified uses
  960. while (nodes--) {
  961. node = createElement('div');
  962. node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
  963. div.appendChild(node);
  964. }
  965. }
  966. style = createElement('style');
  967. style.type = 'text/css';
  968. style.id = 's' + mod;
  969. // 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.
  970. // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
  971. (!body.fake ? div : body).appendChild(style);
  972. body.appendChild(div);
  973. if (style.styleSheet) {
  974. style.styleSheet.cssText = rule;
  975. } else {
  976. style.appendChild(document.createTextNode(rule));
  977. }
  978. div.id = mod;
  979. if (body.fake) {
  980. //avoid crashing IE8, if background image is used
  981. body.style.background = '';
  982. //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
  983. body.style.overflow = 'hidden';
  984. docOverflow = docElement.style.overflow;
  985. docElement.style.overflow = 'hidden';
  986. docElement.appendChild(body);
  987. }
  988. ret = callback(div, rule);
  989. // If this is done after page load we don't want to remove the body so check if body exists
  990. if (body.fake) {
  991. body.parentNode.removeChild(body);
  992. docElement.style.overflow = docOverflow;
  993. // Trigger layout so kinetic scrolling isn't disabled in iOS6+
  994. // eslint-disable-next-line
  995. docElement.offsetHeight;
  996. } else {
  997. div.parentNode.removeChild(div);
  998. }
  999. return !!ret;
  1000. }
  1001. ;
  1002. /**
  1003. * domToCSS takes a camelCase string and converts it to kebab-case
  1004. * e.g. boxSizing -> box-sizing
  1005. *
  1006. * @access private
  1007. * @function domToCSS
  1008. * @param {string} name - String name of camelCase prop we want to convert
  1009. * @returns {string} The kebab-case version of the supplied name
  1010. */
  1011. function domToCSS(name) {
  1012. return name.replace(/([A-Z])/g, function(str, m1) {
  1013. return '-' + m1.toLowerCase();
  1014. }).replace(/^ms-/, '-ms-');
  1015. }
  1016. ;
  1017. /**
  1018. * wrapper around getComputedStyle, to fix issues with Firefox returning null when
  1019. * called inside of a hidden iframe
  1020. *
  1021. * @access private
  1022. * @function computedStyle
  1023. * @param {HTMLElement|SVGElement} elem - The element we want to find the computed styles of
  1024. * @param {string|null} [pseudo] - An optional pseudo element selector (e.g. :before), of null if none
  1025. * @param {string} prop - A CSS property
  1026. * @returns {CSSStyleDeclaration} the value of the specified CSS property
  1027. */
  1028. function computedStyle(elem, pseudo, prop) {
  1029. var result;
  1030. if ('getComputedStyle' in window) {
  1031. result = getComputedStyle.call(window, elem, pseudo);
  1032. var console = window.console;
  1033. if (result !== null) {
  1034. if (prop) {
  1035. result = result.getPropertyValue(prop);
  1036. }
  1037. } else {
  1038. if (console) {
  1039. var method = console.error ? 'error' : 'log';
  1040. console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');
  1041. }
  1042. }
  1043. } else {
  1044. result = !pseudo && elem.currentStyle && elem.currentStyle[prop];
  1045. }
  1046. return result;
  1047. }
  1048. ;
  1049. /**
  1050. * nativeTestProps allows for us to use native feature detection functionality if available.
  1051. * some prefixed form, or false, in the case of an unsupported rule
  1052. *
  1053. * @access private
  1054. * @function nativeTestProps
  1055. * @param {array} props - An array of property names
  1056. * @param {string} value - A string representing the value we want to check via @supports
  1057. * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
  1058. */
  1059. // Accepts a list of property names and a single value
  1060. // Returns `undefined` if native detection not available
  1061. function nativeTestProps(props, value) {
  1062. var i = props.length;
  1063. // Start with the JS API: https://www.w3.org/TR/css3-conditional/#the-css-interface
  1064. if ('CSS' in window && 'supports' in window.CSS) {
  1065. // Try every prefixed variant of the property
  1066. while (i--) {
  1067. if (window.CSS.supports(domToCSS(props[i]), value)) {
  1068. return true;
  1069. }
  1070. }
  1071. return false;
  1072. }
  1073. // Otherwise fall back to at-rule (for Opera 12.x)
  1074. else if ('CSSSupportsRule' in window) {
  1075. // Build a condition string for every prefixed variant
  1076. var conditionText = [];
  1077. while (i--) {
  1078. conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
  1079. }
  1080. conditionText = conditionText.join(' or ');
  1081. return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
  1082. return computedStyle(node, null, 'position') === 'absolute';
  1083. });
  1084. }
  1085. return undefined;
  1086. }
  1087. ;
  1088. /**
  1089. * cssToDOM takes a kebab-case string and converts it to camelCase
  1090. * e.g. box-sizing -> boxSizing
  1091. *
  1092. * @access private
  1093. * @function cssToDOM
  1094. * @param {string} name - String name of kebab-case prop we want to convert
  1095. * @returns {string} The camelCase version of the supplied name
  1096. */
  1097. function cssToDOM(name) {
  1098. return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
  1099. return m1 + m2.toUpperCase();
  1100. }).replace(/^-/, '');
  1101. }
  1102. ;
  1103. // testProps is a generic CSS / DOM property test.
  1104. // In testing support for a given CSS property, it's legit to test:
  1105. // `elem.style[styleName] !== undefined`
  1106. // If the property is supported it will return an empty string,
  1107. // if unsupported it will return undefined.
  1108. // We'll take advantage of this quick test and skip setting a style
  1109. // on our modernizr element, but instead just testing undefined vs
  1110. // empty string.
  1111. // Property names can be provided in either camelCase or kebab-case.
  1112. function testProps(props, prefixed, value, skipValueTest) {
  1113. skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
  1114. // Try native detect first
  1115. if (!is(value, 'undefined')) {
  1116. var result = nativeTestProps(props, value);
  1117. if (!is(result, 'undefined')) {
  1118. return result;
  1119. }
  1120. }
  1121. // Otherwise do it properly
  1122. var afterInit, i, propsLength, prop, before;
  1123. // If we don't have a style element, that means we're running async or after
  1124. // the core tests, so we'll need to create our own elements to use
  1125. // inside of an SVG element, in certain browsers, the `style` element is only
  1126. // defined for valid tags. Therefore, if `modernizr` does not have one, we
  1127. // fall back to a less used element and hope for the best.
  1128. // for strict XHTML browsers the hardly used samp element is used
  1129. var elems = ['modernizr', 'tspan', 'samp'];
  1130. while (!mStyle.style && elems.length) {
  1131. afterInit = true;
  1132. mStyle.modElem = createElement(elems.shift());
  1133. mStyle.style = mStyle.modElem.style;
  1134. }
  1135. // Delete the objects if we created them.
  1136. function cleanElems() {
  1137. if (afterInit) {
  1138. delete mStyle.style;
  1139. delete mStyle.modElem;
  1140. }
  1141. }
  1142. propsLength = props.length;
  1143. for (i = 0; i < propsLength; i++) {
  1144. prop = props[i];
  1145. before = mStyle.style[prop];
  1146. if (contains(prop, '-')) {
  1147. prop = cssToDOM(prop);
  1148. }
  1149. if (mStyle.style[prop] !== undefined) {
  1150. // If value to test has been passed in, do a set-and-check test.
  1151. // 0 (integer) is a valid property value, so check that `value` isn't
  1152. // undefined, rather than just checking it's truthy.
  1153. if (!skipValueTest && !is(value, 'undefined')) {
  1154. // Needs a try catch block because of old IE. This is slow, but will
  1155. // be avoided in most cases because `skipValueTest` will be used.
  1156. try {
  1157. mStyle.style[prop] = value;
  1158. } catch (e) {}
  1159. // If the property value has changed, we assume the value used is
  1160. // supported. If `value` is empty string, it'll fail here (because
  1161. // it hasn't changed), which matches how browsers have implemented
  1162. // CSS.supports()
  1163. if (mStyle.style[prop] !== before) {
  1164. cleanElems();
  1165. return prefixed === 'pfx' ? prop : true;
  1166. }
  1167. }
  1168. // Otherwise just return true, or the property name if this is a
  1169. // `prefixed()` call
  1170. else {
  1171. cleanElems();
  1172. return prefixed === 'pfx' ? prop : true;
  1173. }
  1174. }
  1175. }
  1176. cleanElems();
  1177. return false;
  1178. }
  1179. ;
  1180. /**
  1181. * testProp() investigates whether a given style property is recognized
  1182. * Property names can be provided in either camelCase or kebab-case.
  1183. *
  1184. * @memberOf Modernizr
  1185. * @name Modernizr.testProp
  1186. * @access public
  1187. * @optionName Modernizr.testProp()
  1188. * @optionProp testProp
  1189. * @function testProp
  1190. * @param {string} prop - Name of the CSS property to check
  1191. * @param {string} [value] - Name of the CSS value to check
  1192. * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
  1193. * @returns {boolean} an empty string if the property is supported, undefined if its unsupported
  1194. * @example
  1195. *
  1196. * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
  1197. * version of the string.
  1198. *
  1199. * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
  1200. *
  1201. * ```js
  1202. * Modernizr.testProp('pointerEvents') // true
  1203. * ```
  1204. *
  1205. * You can also provide a value as an optional second argument to check if a
  1206. * specific value is supported
  1207. *
  1208. * ```js
  1209. * Modernizr.testProp('pointerEvents', 'none') // true
  1210. * Modernizr.testProp('pointerEvents', 'penguin') // false
  1211. * ```
  1212. */
  1213. var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
  1214. return testProps([prop], undefined, value, useValue);
  1215. };
  1216. /*!
  1217. {
  1218. "name": "Cross-Origin Resource Sharing",
  1219. "property": "cors",
  1220. "caniuse": "cors",
  1221. "authors": ["Theodoor van Donge"],
  1222. "notes": [{
  1223. "name": "MDN Docs",
  1224. "href": "https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS"
  1225. }],
  1226. "polyfills": ["pmxdr", "ppx", "flxhr"]
  1227. }
  1228. !*/
  1229. /* DOC
  1230. Detects support for Cross-Origin Resource Sharing: method of performing XMLHttpRequests across domains.
  1231. */
  1232. Modernizr.addTest('cors', 'XMLHttpRequest' in window && 'withCredentials' in new XMLHttpRequest());
  1233. /**
  1234. * since we have a fairly large number of input tests that don't mutate the input
  1235. * we create a single element that can be shared with all of those tests for a
  1236. * minor perf boost
  1237. *
  1238. * @access private
  1239. * @returns {HTMLInputElement}
  1240. */
  1241. var inputElem = createElement('input');
  1242. /*!
  1243. {
  1244. "name": "Input attributes",
  1245. "property": "input",
  1246. "tags": ["forms"],
  1247. "authors": ["Mike Taylor"],
  1248. "notes": [{
  1249. "name": "WHATWG Spec",
  1250. "href": "https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary"
  1251. }],
  1252. "knownBugs": ["Some blackberry devices report false positive for input.multiple"]
  1253. }
  1254. !*/
  1255. /* DOC
  1256. Detects support for HTML5 `<input>` element attributes and exposes Boolean subproperties with the results:
  1257. ```javascript
  1258. Modernizr.input.autocomplete
  1259. Modernizr.input.autofocus
  1260. Modernizr.input.list
  1261. Modernizr.input.max
  1262. Modernizr.input.min
  1263. Modernizr.input.multiple
  1264. Modernizr.input.pattern
  1265. Modernizr.input.placeholder
  1266. Modernizr.input.required
  1267. Modernizr.input.step
  1268. ```
  1269. */
  1270. // Run through HTML5's new input attributes to see if the UA understands any.
  1271. // Mike Taylr has created a comprehensive resource for testing these attributes
  1272. // when applied to all input types:
  1273. // miketaylr.com/code/input-type-attr.html
  1274. // Only input placeholder is tested while textarea's placeholder is not.
  1275. // Currently Safari 4 and Opera 11 have support only for the input placeholder
  1276. // Both tests are available in feature-detects/forms-placeholder.js
  1277. var inputattrs = 'autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ');
  1278. var attrs = {};
  1279. Modernizr.input = (function(props) {
  1280. for (var i = 0, len = props.length; i < len; i++) {
  1281. attrs[ props[i] ] = !!(props[i] in inputElem);
  1282. }
  1283. if (attrs.list) {
  1284. // safari false positive's on datalist: webk.it/74252
  1285. // see also github.com/Modernizr/Modernizr/issues/146
  1286. attrs.list = !!(createElement('datalist') && window.HTMLDataListElement);
  1287. }
  1288. return attrs;
  1289. })(inputattrs);
  1290. /**
  1291. * Object.prototype.toString can be used with every object and allows you to
  1292. * get its class easily. Abstracting it off of an object prevents situations
  1293. * where the toString property has been overridden
  1294. *
  1295. * @access private
  1296. * @function toStringFn
  1297. * @returns {function} An abstracted toString function
  1298. */
  1299. var toStringFn = ({}).toString;
  1300. /*!
  1301. {
  1302. "name": "SVG SMIL animation",
  1303. "property": "smil",
  1304. "caniuse": "svg-smil",
  1305. "tags": ["svg"],
  1306. "notes": [{
  1307. "name": "W3C Spec",
  1308. "href": "https://www.w3.org/AudioVideo/"
  1309. }]
  1310. }
  1311. !*/
  1312. // SVG SMIL animation
  1313. Modernizr.addTest('smil', function() {
  1314. return !!document.createElementNS &&
  1315. /SVGAnimate/.test(toStringFn.call(document.createElementNS('http://www.w3.org/2000/svg', 'animate')));
  1316. });
  1317. // Run each test
  1318. testRunner();
  1319. // Remove the "no-js" class if it exists
  1320. setClasses(classes);
  1321. delete ModernizrProto.addTest;
  1322. delete ModernizrProto.addAsyncTest;
  1323. // Run the things that are supposed to run after the tests
  1324. for (var i = 0; i < Modernizr._q.length; i++) {
  1325. Modernizr._q[i]();
  1326. }
  1327. // Leak Modernizr namespace
  1328. window.Modernizr = Modernizr;
  1329. ;
  1330. })(window, document);