1/*! 2 * modernizr v3.2.0 3 * Build http://modernizr.com/download?-bgsizecover-csscalc-csstransforms-csstransitions-cssvhunit-cssvwunit-flexbox-flexboxlegacy-flexboxtweener-flexwrap-inlinesvg-dontmin 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 14 * MIT License 15 */ 16 17/* 18 * Modernizr tests which native CSS3 and HTML5 features are available in the 19 * current UA and makes the results available to you in two ways: as properties on 20 * a global `Modernizr` object, and as classes on the `<html>` element. This 21 * information allows you to progressively enhance your pages with a granular level 22 * of control over the experience. 23*/ 24 25;(function(window, document, undefined){ 26 var tests = []; 27 28 29 /** 30 * 31 * ModernizrProto is the constructor for Modernizr 32 * 33 * @class 34 * @access public 35 */ 36 37 var ModernizrProto = { 38 // The current version, dummy 39 _version: '3.2.0', 40 41 // Any settings that don't work as separate modules 42 // can go in here as configuration. 43 _config: { 44 'classPrefix' : '', 45 'enableClasses' : true, 46 'enableJSClass' : true, 47 'usePrefixes' : true 48 }, 49 50 // Queue of tests 51 _q: [], 52 53 // Stub these for people who are listening 54 on: function(test, cb) { 55 // I don't really think people should do this, but we can 56 // safe guard it a bit. 57 // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests. 58 // This is in case people listen to synchronous tests. I would leave it out, 59 // but the code to *disallow* sync tests in the real version of this 60 // function is actually larger than this. 61 var self = this; 62 setTimeout(function() { 63 cb(self[test]); 64 }, 0); 65 }, 66 67 addTest: function(name, fn, options) { 68 tests.push({name : name, fn : fn, options : options}); 69 }, 70 71 addAsyncTest: function(fn) { 72 tests.push({name : null, fn : fn}); 73 } 74 }; 75 76 77 78 // Fake some of Object.create so we can force non test results to be non "own" properties. 79 var Modernizr = function() {}; 80 Modernizr.prototype = ModernizrProto; 81 82 // Leak modernizr globally when you `require` it rather than force it here. 83 // Overwrite name so constructor name is nicer :D 84 Modernizr = new Modernizr(); 85 86 87 88 var classes = []; 89 90 91 /** 92 * is returns a boolean if the typeof an obj is exactly type. 93 * 94 * @access private 95 * @function is 96 * @param {*} obj - A thing we want to check the type of 97 * @param {string} type - A string to compare the typeof against 98 * @returns {boolean} 99 */ 100 101 function is(obj, type) { 102 return typeof obj === type; 103 } 104 ; 105 106 /** 107 * Run through all tests and detect their support in the current UA. 108 * 109 * @access private 110 */ 111 112 function testRunner() { 113 var featureNames; 114 var feature; 115 var aliasIdx; 116 var result; 117 var nameIdx; 118 var featureName; 119 var featureNameSplit; 120 121 for (var featureIdx in tests) { 122 if (tests.hasOwnProperty(featureIdx)) { 123 featureNames = []; 124 feature = tests[featureIdx]; 125 // run the test, throw the return value into the Modernizr, 126 // then based on that boolean, define an appropriate className 127 // and push it into an array of classes we'll join later. 128 // 129 // If there is no name, it's an 'async' test that is run, 130 // but not directly added to the object. That should 131 // be done with a post-run addTest call. 132 if (feature.name) { 133 featureNames.push(feature.name.toLowerCase()); 134 135 if (feature.options && feature.options.aliases && feature.options.aliases.length) { 136 // Add all the aliases into the names list 137 for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) { 138 featureNames.push(feature.options.aliases[aliasIdx].toLowerCase()); 139 } 140 } 141 } 142 143 // Run the test, or use the raw value if it's not a function 144 result = is(feature.fn, 'function') ? feature.fn() : feature.fn; 145 146 147 // Set each of the names on the Modernizr object 148 for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) { 149 featureName = featureNames[nameIdx];
150 // Support dot properties as sub tests. We don't do checking to make sure 151 // that the implied parent tests have been added. You must call them in 152 // order (either in the test, or make the parent test a dependency). 153 // 154 // Cap it to TWO to make the logic simple and because who needs that kind of subtesting 155 // hashtag famous last words 156 featureNameSplit = featureName.split('.'); 157 158 if (featureNameSplit.length === 1) { 159 Modernizr[featureNameSplit[0]] = result; 160 } else { 161 // cast to a Boolean, if not one already 162 /* jshint -W053 */ 163 if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) { 164 Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]); 165 } 166 167 Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result; 168 } 169 170 classes.push((result ? '' : 'no-') + featureNameSplit.join('-')); 171 } 172 } 173 } 174 } 175 ; 176 177 /** 178 * docElement is a convenience wrapper to grab the root element of the document 179 * 180 * @access private 181 * @returns {HTMLElement|SVGElement} The root element of the document 182 */ 183 184 var docElement = document.documentElement; 185 186 187 /** 188 * A convenience helper to check if the document we are running in is an SVG document 189 * 190 * @access private 191 * @returns {boolean} 192 */ 193 194 var isSVG = docElement.nodeName.toLowerCase() === 'svg'; 195 196 197 /** 198 * setClasses takes an array of class names and adds them to the root element 199 * 200 * @access private 201 * @function setClasses 202 * @param {string[]} classes - Array of class names 203 */ 204 205 // Pass in an and array of class names, e.g.:
206 // ['no-webp', 'borderradius', ...] 207 function setClasses(classes) { 208 var className = docElement.className; 209 var classPrefix = Modernizr._config.classPrefix || ''; 210 211 if (isSVG) { 212 className = className.baseVal; 213 } 214 215 // Change `no-js` to `js` (independently of the `enableClasses` option) 216 // Handle classPrefix on this too 217 if (Modernizr._config.enableJSClass) { 218 var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)'); 219 className = className.replace(reJS, '$1' + classPrefix + 'js$2'); 220 } 221 222 if (Modernizr._config.enableClasses) { 223 // Add the new classes 224 className += ' ' + classPrefix + classes.join(' ' + classPrefix); 225 isSVG ? docElement.className.baseVal = className : docElement.className = className; 226 } 227 228 } 229 230 ; 231 232 /** 233 * createElement is a convenience wrapper around document.createElement. Since we 234 * use createElement all over the place, this allows for (slightly) smaller code 235 * as well as abstracting away issues with creating elements in contexts other than 236 * HTML documents (e.g. SVG documents). 237 * 238 * @access private 239 * @function createElement 240 * @returns {HTMLElement|SVGElement} An HTML or SVG element 241 */ 242 243 function createElement() { 244 if (typeof document.createElement !== 'function') { 245 // This is the case in IE7, where the type of createElement is "object". 246 // For this reason, we cannot call apply() as Object is not a Function. 247 return document.createElement(arguments[0]); 248 } else if (isSVG) { 249 return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]); 250 } else { 251 return document.createElement.apply(document, arguments); 252 } 253 } 254 255 ; 256 257 /** 258 * List of property values to set for css tests. See ticket #21 259 * http://git.io/vUGl4 260 * 261 * @memberof Modernizr 262 * @name Modernizr._prefixes 263 * @optionName Modernizr._prefixes 264 * @optionProp prefixes 265 * @access public 266 * @example 267 * 268 * Modernizr._prefixes is the internal list of prefixes that we test against 269 * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply 270 * an array of kebab-case vendor prefixes you can use within your code. 271 * 272 * Some common use cases include 273 * 274 * Generating all possible prefixed version of a CSS property 275 * ```js 276 * var rule = Modernizr._prefixes.join('transform: rotate(20deg); '); 277 * 278 * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);' 279 * ``` 280 * 281 * Generating all possible prefixed version of a CSS value 282 * ```js 283 * rule = 'display:' + Modernizr._prefixes.join('flex; display:') + 'flex'; 284 * 285 * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex' 286 * ``` 287 */ 288 289 var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : []); 290 291 // expose these for the plugin API. Look in the source for how to join() them against your input 292 ModernizrProto._prefixes = prefixes; 293 294 295/*! 296{ 297 "name": "CSS Calc", 298 "property": "csscalc", 299 "caniuse": "calc", 300 "tags": ["css"], 301 "builderAliases": ["css_calc"], 302 "authors": ["@calvein"] 303} 304!*/ 305/* DOC 306Method of allowing calculated values for length units. For example: 307 308```css 309//lem { 310 width: calc(100% - 3em); 311} 312``` 313*/ 314 315 Modernizr.addTest('csscalc', function() { 316 var prop = 'width:'; 317 var value = 'calc(10px);'; 318 var el = createElement('a'); 319 320 el.style.cssText = prop + prefixes.join(value + prop); 321 322 return !!el.style.length; 323 }); 324 325 326 /** 327 * If the browsers follow the spec, then they would expose vendor-specific style as: 328 * elem.style.WebkitBorderRadius 329 * instead of something like the following, which would be technically incorrect: 330 * elem.style.webkitBorderRadius 331 332 * Webkit ghosts their properties in lowercase but Opera & Moz do not. 333 * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ 334 * erik.eae.net/archives/2008/03/10/21.48.10/ 335 336 * More here: github.com/Modernizr/Modernizr/issues/issue/21 337 * 338 * @access private 339 * @returns {string} The string representing the vendor-specific style properties 340 */ 341 342 var omPrefixes = 'Moz O ms Webkit'; 343 344 345 var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []); 346 ModernizrProto._cssomPrefixes = cssomPrefixes; 347 348 349 350 /** 351 * contains checks to see if a string contains another string 352 * 353 * @access private 354 * @function contains 355 * @param {string} str - The string we want to check for substrings 356 * @param {string} substr - The substring we want to search the first string for 357 * @returns {boolean} 358 */ 359 360 function contains(str, substr) {
361 return !!~('' + str).indexOf(substr); 362 } 363 364 ; 365 366 /** 367 * Create our "modernizr" element that we do most feature tests on. 368 * 369 * @access private 370 */ 371 372 var modElem = { 373 elem : createElement('modernizr') 374 }; 375 376 // Clean up this element 377 Modernizr._q.push(function() { 378 delete modElem.elem; 379 }); 380 381 382 383 var mStyle = { 384 style : modElem.elem.style 385 }; 386 387 // kill ref for gc, must happen before mod.elem is removed, so we unshift on to 388 // the front of the queue. 389 Modernizr._q.unshift(function() { 390 delete mStyle.style; 391 }); 392 393 394 395 /** 396 * getBody returns the body of a document, or an element that can stand in for 397 * the body if a real body does not exist 398 * 399 * @access private 400 * @function getBody 401 * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an 402 * artificially created element that stands in for the body 403 */ 404 405 function getBody() { 406 // After page load injecting a fake body doesn't work so check if body exists 407 var body = document.body; 408 409 if (!body) { 410 // Can't use the real body create a fake one. 411 body = createElement(isSVG ? 'svg' : 'body'); 412 body.fake = true; 413 } 414 415 return body; 416 } 417 418 ; 419 420 /** 421 * injectElementWithStyles injects an element with style element and some CSS rules 422 * 423 * @access private 424 * @function injectElementWithStyles 425 * @param {string} rule - String representing a css rule 426 * @param {function} callback - A function that is used to test the injected element 427 * @param {number} [nodes] - An integer representing the number of additional nodes you want injected 428 * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes 429 * @returns {boolean} 430 */ 431 432 function injectElementWithStyles(rule, callback, nodes, testnames) { 433 var mod = 'modernizr'; 434 var style; 435 var ret; 436 var node; 437 var docOverflow; 438 var div = createElement('div'); 439 var body = getBody(); 440 441 if (parseInt(nodes, 10)) { 442 // In order not to give false positives we create a node for each test 443 // This also allows the method to scale for unspecified uses 444 while (nodes--) { 445 node = createElement('div'); 446 node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 447 div.appendChild(node); 448 } 449 } 450 451 style = createElement('style'); 452 style.type = 'text/css'; 453 style.id = 's' + mod; 454 455 // 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. 456 // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 457 (!body.fake ? div : body).appendChild(style); 458 body.appendChild(div); 459 460 if (style.styleSheet) { 461 style.styleSheet.cssText = rule; 462 } else { 463 style.appendChild(document.createTextNode(rule)); 464 } 465 div.id = mod; 466 467 if (body.fake) { 468 //avoid crashing IE8, if background image is used 469 body.style.background = ''; 470 //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible 471 body.style.overflow = 'hidden'; 472 docOverflow = docElement.style.overflow; 473 docElement.style.overflow = 'hidden'; 474 docElement.appendChild(body); 475 } 476 477 ret = callback(div, rule); 478 // If this is done after page load we don't want to remove the body so check if body exists 479 if (body.fake) { 480 body.parentNode.removeChild(body); 481 docElement.style.overflow = docOverflow; 482 // Trigger layout so kinetic scrolling isn't disabled in iOS6+ 483 docElement.offsetHeight; 484 } else { 485 div.parentNode.removeChild(div); 486 } 487 488 return !!ret; 489 490 } 491 492 ; 493 494 /** 495 * domToCSS takes a camelCase string and converts it to kebab-case 496 * e.g. boxSizing -> box-sizing 497 * 498 * @access private 499 * @function domToCSS 500 * @param {string} name - String name of camelCase prop we want to convert 501 * @returns {string} The kebab-case version of the supplied name 502 */ 503 504 function domToCSS(name) { 505 return name.replace(/([A-Z])/g, function(str, m1) { 506 return '-' + m1.toLowerCase(); 507 }).replace(/^ms-/, '-ms-'); 508 } 509 ; 510 511 /** 512 * nativeTestProps allows for us to use native feature detection functionality if available. 513 * some prefixed form, or false, in the case of an unsupported rule 514 * 515 * @access private 516 * @function nativeTestProps 517 * @param {array} props - An array of property names 518 * @param {string} value - A string representing the value we want to check via @supports 519 * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise 520 */ 521 522 // Accepts a list of property names and a single value 523 // Returns `undefined` if native detection not available 524 function nativeTestProps (props, value) { 525 var i = props.length; 526 // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface 527 if ('CSS' in window && 'supports' in window.CSS) { 528 // Try every prefixed variant of the property 529 while (i--) { 530 if (window.CSS.supports(domToCSS(props[i]), value)) { 531 return true; 532 } 533 } 534 return false;
535 } 536 // Otherwise fall back to at-rule (for Opera 12.x) 537 else if ('CSSSupportsRule' in window) { 538 // Build a condition string for every prefixed variant 539 var conditionText = []; 540 while (i--) { 541 conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')'); 542 } 543 conditionText = conditionText.join(' or '); 544 return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) { 545 return getComputedStyle(node, null).position == 'absolute'; 546 }); 547 } 548 return undefined; 549 } 550 ; 551 552 /** 553 * cssToDOM takes a kebab-case string and converts it to camelCase 554 * e.g. box-sizing -> boxSizing 555 * 556 * @access private 557 * @function cssToDOM 558 * @param {string} name - String name of kebab-case prop we want to convert 559 * @returns {string} The camelCase version of the supplied name 560 */ 561 562 function cssToDOM(name) { 563 return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) { 564 return m1 + m2.toUpperCase(); 565 }).replace(/^-/, ''); 566 } 567 ; 568 569 // testProps is a generic CSS / DOM property test. 570 571 // In testing support for a given CSS property, it's legit to test: 572 // `elem.style[styleName] !== undefined` 573 // If the property is supported it will return an empty string, 574 // if unsupported it will return undefined. 575 576 // We'll take advantage of this quick test and skip setting a style 577 // on our modernizr element, but instead just testing undefined vs 578 // empty string. 579 580 // Property names can be provided in either camelCase or kebab-case. 581 582 function testProps(props, prefixed, value, skipValueTest) { 583 skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest; 584 585 // Try native detect first 586 if (!is(value, 'undefined')) { 587 var result = nativeTestProps(props, value); 588 if (!is(result, 'undefined')) { 589 return result; 590 } 591 } 592 593 // Otherwise do it properly 594 var afterInit, i, propsLength, prop, before; 595 596 // If we don't have a style element, that means we're running async or after 597 // the core tests, so we'll need to create our own elements to use 598 599 // inside of an SVG element, in certain browsers, the `style` element is only 600 // defined for valid tags. Therefore, if `modernizr` does not have one, we 601 // fall back to a less used element and hope for the best. 602 var elems = ['modernizr', 'tspan']; 603 while (!mStyle.style) { 604 afterInit = true; 605 mStyle.modElem = createElement(elems.shift()); 606 mStyle.style = mStyle.modElem.style; 607 } 608 609 // Delete the objects if we created them. 610 function cleanElems() { 611 if (afterInit) { 612 delete mStyle.style; 613 delete mStyle.modElem; 614 } 615 } 616 617 propsLength = props.length; 618 for (i = 0; i < propsLength; i++) { 619 prop = props[i]; 620 before = mStyle.style[prop]; 621 622 if (contains(prop, '-')) { 623 prop = cssToDOM(prop); 624 } 625 626 if (mStyle.style[prop] !== undefined) { 627 628 // If value to test has been passed in, do a set-and-check test. 629 // 0 (integer) is a valid property value, so check that `value` isn't 630 // undefined, rather than just checking it's truthy. 631 if (!skipValueTest && !is(value, 'undefined')) { 632 633 // Needs a try catch block because of old IE. This is slow, but will 634 // be avoided in most cases because `skipValueTest` will be used. 635 try { 636 mStyle.style[prop] = value; 637 } catch (e) {} 638 639 // If the property value has changed, we assume the value used is 640 // supported. If `value` is empty string, it'll fail here (because 641 // it hasn't changed), which matches how browsers have implemented 642 // CSS.supports() 643 if (mStyle.style[prop] != before) { 644 cleanElems(); 645 return prefixed == 'pfx' ? prop : true; 646 } 647 } 648 // Otherwise just return true, or the property name if this is a 649 // `prefixed()` call 650 else { 651 cleanElems(); 652 return prefixed == 'pfx' ? prop : true; 653 } 654 } 655 } 656 cleanElems(); 657 return false;
658 } 659 660 ; 661 662 /** 663 * List of JavaScript DOM values used for tests 664 * 665 * @memberof Modernizr 666 * @name Modernizr._domPrefixes 667 * @optionName Modernizr._domPrefixes 668 * @optionProp domPrefixes 669 * @access public 670 * @example 671 * 672 * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather 673 * than kebab-case properties, all properties are their Capitalized variant 674 * 675 * ```js 676 * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ]; 677 * ``` 678 */ 679 680 var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []); 681 ModernizrProto._domPrefixes = domPrefixes; 682 683 684 /** 685 * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill. 686 * 687 * @access private 688 * @function fnBind 689 * @param {function} fn - a function you want to change `this` reference to 690 * @param {object} that - the `this` you want to call the function with 691 * @returns {function} The wrapped version of the supplied function 692 */ 693 694 function fnBind(fn, that) { 695 return function() { 696 return fn.apply(that, arguments); 697 }; 698 } 699 700 ; 701 702 /** 703 * testDOMProps is a generic DOM property test; if a browser supports 704 * a certain property, it won't return undefined for it. 705 */ 706 function testDOMProps(props, obj, elem) { 707 var item; 708 709 for (var i in props) { 710 if (props[i] in obj) { 711 712 // return the property name as a string 713 if (elem === false) { 714 return props[i]; 715 } 716 717 item = obj[props[i]]; 718 719 // let's bind a function 720 if (is(item, 'function')) { 721 // bind to obj unless overriden 722 return fnBind(item, elem || obj); 723 } 724 725 // return the unbound function or obj or value 726 return item; 727 } 728 } 729 return false; 730 } 731 732 ; 733 734 /** 735 * testPropsAll tests a list of DOM properties we want to check against. 736 * We specify literally ALL possible (known and/or likely) properties on 737 * the element including the non-vendor prefixed one, for forward- 738 * compatibility. 739 */ 740 function testPropsAll(prop, prefixed, elem, value, skipValueTest) { 741 742 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 743 props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 744 745 // did they call .prefixed('boxSizing') or are we just testing a prop? 746 if (is(prefixed, 'string') || is(prefixed, 'undefined')) { 747 return testProps(props, prefixed, value, skipValueTest); 748 749 // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) 750 } else { 751 props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 752 return testDOMProps(props, prefixed, elem); 753 } 754 } 755 756 // Modernizr.testAllProps() investigates whether a given style property, 757 // or any of its vendor-prefixed variants, is recognized 758 // 759 // Note that the property names must be provided in the camelCase variant. 760 // Modernizr.testAllProps('boxSizing') 761 ModernizrProto.testAllProps = testPropsAll; 762 763 764 765 /** 766 * testAllProps determines whether a given CSS property is supported in the browser 767 * 768 * @memberof Modernizr 769 * @name Modernizr.testAllProps 770 * @optionName Modernizr.testAllProps() 771 * @optionProp testAllProps 772 * @access public 773 * @function testAllProps 774 * @param {string} prop - String naming the property to test (either camelCase or kebab-case) 775 * @param {string} [value] - String of the value to test 776 * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection 777 * @example 778 * 779 * testAllProps determines whether a given CSS property, in some prefixed form, 780 * is supported by the browser. 781 * 782 * ```js 783 * testAllProps('boxSizing') // true 784 * ``` 785 * 786 * It can optionally be given a CSS value in string form to test if a property 787 * value is valid 788 * 789 * ```js 790 * testAllProps('display', 'block') // true 791 * testAllProps('display', 'penguin') // false 792 * ``` 793 * 794 * A boolean can be passed as a third parameter to skip the value check when 795 * native detection (@supports) isn't available. 796 * 797 * ```js 798 * testAllProps('shapeOutside', 'content-box', true); 799 * ``` 800 */ 801 802 function testAllProps (prop, value, skipValueTest) { 803 return testPropsAll(prop, undefined, undefined, value, skipValueTest); 804 } 805 ModernizrProto.testAllProps = testAllProps; 806 807/*! 808{ 809 "name": "Flexbox", 810 "property": "flexbox", 811 "caniuse": "flexbox", 812 "tags": ["css"], 813 "notes": [{ 814 "name": "The _new_ flexbox", 815 "href": "http://dev.w3.org/csswg/css3-flexbox" 816 }], 817 "warnings": [ 818 "A `true` result for this detect does not imply that the `flex-wrap` property is supported; see the `flexwrap` detect." 819 ] 820} 821!*/ 822/* DOC 823Detects support for the Flexible Box Layout model, a.k.a. Flexbox, which allows easy manipulation of layout order and sizing within a container. 824*/ 825 826 Modernizr.addTest('flexbox', testAllProps('flexBasis', '1px', true)); 827 828/*! 829{ 830 "name": "Flexbox (legacy)", 831 "property": "flexboxlegacy", 832 "tags": ["css"], 833 "polyfills": ["flexie"], 834 "notes": [{ 835 "name": "The _old_ flexbox", 836 "href": "http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/" 837 }] 838} 839!*/ 840 841 Modernizr.addTest('flexboxlegacy', testAllProps('boxDirection', 'reverse', true)); 842 843/*! 844{ 845 "name": "Flexbox (tweener)", 846 "property": "flexboxtweener", 847 "tags": ["css"], 848 "polyfills": ["flexie"], 849 "notes": [{ 850 "name": "The _inbetween_ flexbox", 851 "href": "http://www.w3.org/TR/2011/WD-css3-flexbox-20111129/" 852 }], 853 "warnings": ["This represents an old syntax, not the latest standard syntax."] 854} 855!*/ 856 857 Modernizr.addTest('flexboxtweener', testAllProps('flexAlign', 'end', true)); 858 859/*! 860{ 861 "name": "Flex Line Wrapping", 862 "property": "flexwrap", 863 "tags": ["css", "flexbox"], 864 "notes": [{ 865 "name": "W3C Flexible Box Layout spec", 866 "href": "http://dev.w3.org/csswg/css3-flexbox" 867 }], 868 "warnings": [ 869 "Does not imply a modern implementation â see documentation." 870 ] 871} 872!*/ 873/* DOC 874Detects support for the `flex-wrap` CSS property, part of Flexbox, which isnât present in all Flexbox implementations (notably Firefox). 875 876This featured in both the 'tweener' syntax (implemented by IE10) and the 'modern' syntax (implemented by others). This detect will return `true` for either of these implementations, as long as the `flex-wrap` property is supported. So to ensure the modern syntax is supported, use together with `Modernizr.flexbox`: 877 878```javascript 879if (Modernizr.flexbox && Modernizr.flexwrap) { 880 // Modern Flexbox with `flex-wrap` supported 881} 882else { 883 // Either old Flexbox syntax, or `flex-wrap` not supported 884} 885``` 886*/ 887 888 Modernizr.addTest('flexwrap', testAllProps('flexWrap', 'wrap', true)); 889 890/*! 891{ 892 "name": "CSS Transforms", 893 "property": "csstransforms", 894 "caniuse": "transforms2d", 895 "tags": ["css"] 896} 897!*/ 898 899 Modernizr.addTest('csstransforms', function() { 900 // Android < 3.0 is buggy, so we sniff and blacklist 901 // http://git.io/hHzL7w 902 return navigator.userAgent.indexOf('Android 2.') === -1 && 903 testAllProps('transform', 'scale(1)', true); 904 }); 905 906/*! 907{ 908 "name": "CSS Transitions", 909 "property": "csstransitions", 910 "caniuse": "css-transitions", 911 "tags": ["css"] 912} 913!*/ 914 915 Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true)); 916 917 918 /** 919 * testStyles injects an element with style element and some CSS rules 920 * 921 * @memberof Modernizr 922 * @name Modernizr.testStyles 923 * @optionName Modernizr.testStyles() 924 * @optionProp testStyles 925 * @access public 926 * @function testStyles 927 * @param {string} rule - String representing a css rule 928 * @param {function} callback - A function that is used to test the injected element 929 * @param {number} [nodes] - An integer representing the number of additional nodes you want injected 930 * @param {string[]}
930 [testnames] - An array of strings that are used as ids for the additional nodes 931 * @returns {boolean} 932 * @example 933 * 934 * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page 935 * along with (possibly multiple) DOM elements. This lets you check for features 936 * that can not be detected by simply checking the [IDL](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Interface_development_guide/IDL_interface_rules). 937 * 938 * ```js 939 * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) { 940 * // elem is the first DOM node in the page (by default #modernizr) 941 * // rule is the first argument you supplied - the CSS rule in string form 942 * 943 * addTest('widthworks', elem.style.width === '9px') 944 * }); 945 * ``` 946 * 947 * If your test requires multiple nodes, you can include a third argument 948 * indicating how many additional div elements to include on the page. The 949 * additional nodes are injected as children of the `elem` that is returned as 950 * the first argument to the callback. 951 * 952 * ```js 953 * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) { 954 * document.getElementById('modernizr').style.width === '1px'; // true 955 * document.getElementById('modernizr2').style.width === '2px'; // true 956 * elem.firstChild === document.getElementById('modernizr2'); // true 957 * }, 1); 958 * ``` 959 * 960 * By default, all of the additional elements have an ID of `modernizr[n]`, where 961 * `n` is its index (e.g. the first additional, second overall is `#modernizr2`, 962 * the second additional is `#modernizr3`, etc.). 963 * If you want to have more meaningful IDs for your function, you can provide 964 * them as the fourth argument, as an array of strings 965 * 966 * ```js 967 * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) { 968 * elem.firstChild === document.getElementById('foo'); // true 969 * elem.lastChild === document.getElementById('bar'); // true 970 * }, 2, ['foo', 'bar']); 971 * ``` 972 * 973 */ 974 975 var testStyles = ModernizrProto.testStyles = injectElementWithStyles; 976 977/*! 978{ 979 "name": "CSS vh unit", 980 "property": "cssvhunit", 981 "caniuse": "viewport-units", 982 "tags": ["css"], 983 "builderAliases": ["css_vhunit"], 984 "notes": [{ 985 "name": "Related Modernizr Issue", 986 "href": "https://github.com/Modernizr/Modernizr/issues/572" 987 },{ 988 "name": "Similar JSFiddle", 989 "href": "http://jsfiddle.net/FWeinb/etnYC/" 990 }] 991} 992!*/ 993 994 testStyles('#modernizr { height: 50vh; }', function(elem) { 995 var height = parseInt(window.innerHeight / 2, 10); 996 var compStyle = parseInt((window.getComputedStyle ? 997 getComputedStyle(elem, null) : 998 elem.currentStyle)['height'], 10); 999 Modernizr.addTest('cssvhunit', compStyle == height); 1000 }); 1001 1002/*! 1003{ 1004 "name": "CSS vw unit", 1005 "property": "cssvwunit", 1006 "caniuse": "viewport-units", 1007 "tags": ["css"], 1008 "builderAliases": ["css_vwunit"], 1009 "notes": [{ 1010 "name": "Related Modernizr Issue", 1011 "href": "https://github.com/Modernizr/Modernizr/issues/572" 1012 },{ 1013 "name": "JSFiddle Example", 1014 "href": "http://jsfiddle.net/FWeinb/etnYC/" 1015 }] 1016} 1017!*/ 1018 1019 testStyles('#modernizr { width: 50vw; }', function(elem) { 1020 var width = parseInt(window.innerWidth / 2, 10); 1021 var compStyle = parseInt((window.getComputedStyle ? 1022 getComputedStyle(elem, null) : 1023 elem.currentStyle).width, 10); 1024 1025 Modernizr.addTest('cssvwunit', compStyle == width); 1026 }); 1027 1028/*! 1029{ 1030 "name": "Inline SVG", 1031 "property": "inlinesvg", 1032 "caniuse": "svg-html5", 1033 "tags": ["svg"], 1034 "notes": [{ 1035 "name": "Test page", 1036 "href": "http://paulirish.com/demo/inline-svg" 1037 }, { 1038 "name": "Test page and results", 1039 "href": "http://codepen.io/eltonmesquita/full/GgXbvo/" 1040 }], 1041 "polyfills": ["inline-svg-polyfill"], 1042 "knownBugs": ["False negative on some Chromia browsers."] 1043} 1044!*/ 1045/* DOC 1046Detects support for inline SVG in HTML (not within XHTML). 1047*/ 1048
1049 Modernizr.addTest('inlinesvg', function() { 1050 var div = createElement('div'); 1051 div.innerHTML = '<svg/>'; 1052 return (typeof SVGRect != 'undefined' && div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg'; 1053 }); 1054 1055/*! 1056{ 1057 "name": "Background Size Cover", 1058 "property": "bgsizecover", 1059 "tags": ["css"], 1060 "builderAliases": ["css_backgroundsizecover"], 1061 "notes": [{ 1062 "name" : "MDN Docs", 1063 "href": "http://developer.mozilla.org/en/CSS/background-size" 1064 }] 1065} 1066!*/ 1067 1068 // Must test value, as this specifically tests the `cover` value 1069 Modernizr.addTest('bgsizecover', testAllProps('backgroundSize', 'cover')); 1070 1071 1072 // Run each test 1073 testRunner(); 1074 1075 // Remove the "no-js" class if it exists 1076 setClasses(classes); 1077 1078 delete ModernizrProto.addTest; 1079 delete ModernizrProto.addAsyncTest; 1080 1081 // Run the things that are supposed to run after the tests 1082 for (var i = 0; i < Modernizr._q.length; i++) { 1083 Modernizr._q[i](); 1084 } 1085 1086 // Leak Modernizr namespace 1087 window.Modernizr = Modernizr; 1088 1089 1090; 1091 1092})(window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.