vendor: 9,524 bytes, lines 1-282
1/*! 2 * modernizr v3.0.0-alpha.3 3 * Build http://v3.modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-touchevents-domprefixes-load-mq-prefixed-prefixes-shiv-testallprops-testprop-teststyles-dontmin 4 * 5 * Copyright (c) 6 * Faruk Ates 7 * Paul Irish 8 * Alex Sexton 9 * Ryan Seddon 10 * Alexander Farkas 11 * Patrick Kettner 12 * Stu Cox 13 * Richard Herrera 14 15 * MIT License 16 */ 17 18/* 19 * Modernizr tests which native CSS3 and HTML5 features are available in the 20 * current UA and makes the results available to you in two ways: as properties on 21 * a global `Modernizr` object, and as classes on the `<html>` element. This 22 * information allows you to progressively enhance your pages with a granular level 23 * of control over the experience. 24*/ 25 26;(function(window, document, undefined){ 27 var classes = []; 28 29 30 // Take the html5 variable out of the 31 // html5shiv scope so we can return it. 32 var html5; 33 /** 34 * @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 35 */ 36 ;(function(window, document) { 37 /*jshint evil:true */ 38 /** version */ 39 var version = '3.7.2'; 40 41 /** Preset options */ 42 var options = window.html5 || {}; 43 44 /** Used to skip problem elements */ 45 var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; 46 47 /** Not all elements can be cloned in IE **/ 48 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; 49 50 /** Detect whether the browser supports default html5 styles */ 51 var supportsHtml5Styles; 52 53 /** Name of the expando, to work with multiple documents or to re-shiv one document */ 54 var expando = '_html5shiv'; 55 56 /** The id for the the documents expando */ 57 var expanID = 0; 58 59 /** Cached data for each document */ 60 var expandoData = {}; 61 62 /** Detect whether the browser supports unknown elements */ 63 var supportsUnknownElements; 64 65 (function() { 66 try { 67 var a = document.createElement('a'); 68 a.innerHTML = '<xyz></xyz>'; 69 //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles 70 supportsHtml5Styles = ('hidden' in a); 71 72 supportsUnknownElements = a.childNodes.length == 1 || (function() { 73 // assign a false positive if unable to shiv 74 (document.createElement)('a'); 75 var frag = document.createDocumentFragment(); 76 return ( 77 typeof frag.cloneNode == 'undefined' || 78 typeof frag.createDocumentFragment == 'undefined' || 79 typeof frag.createElement == 'undefined' 80 ); 81 }()); 82 } catch(e) { 83 // assign a false positive if detection fails => unable to shiv 84 supportsHtml5Styles = true; 85 supportsUnknownElements = true; 86 } 87 88 }()); 89 90 /*--------------------------------------------------------------------------*/ 91 92 /** 93 * Creates a style sheet with the given CSS text and adds it to the document. 94 * @private 95 * @param {Document} ownerDocument The document. 96 * @param {String} cssText The CSS text. 97 * @returns {StyleSheet} The style element. 98 */ 99 function addStyleSheet(ownerDocument, cssText) { 100 var p = ownerDocument.createElement('p'), 101 parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; 102 103 p.innerHTML = 'x<style>' + cssText + '</style>'; 104 return parent.insertBefore(p.lastChild, parent.firstChild); 105 } 106 107 /** 108 * Returns the value of `html5.elements` as an array. 109 * @private 110 * @returns {Array} An array of shived element node names. 111 */ 112 function getElements() { 113 var elements = html5.elements; 114 return typeof elements == 'string' ? elements.split(' ') : elements; 115 } 116 117 /** 118 * Extends the built-in list of html5 elements 119 * @memberOf html5 120 * @param {String|Array} newElements whitespace separated list or array of new element names to shiv 121 * @param {Document} ownerDocument The context document. 122 */ 123 function addElements(newElements, ownerDocument) { 124 var elements = html5.elements; 125 if(typeof elements != 'string'){ 126 elements = elements.join(' '); 127 } 128 if(typeof newElements != 'string'){ 129 newElements = newElements.join(' '); 130 } 131 html5.elements = elements +' '+ newElements; 132 shivDocument(ownerDocument); 133 } 134 135 /** 136 * Returns the data associated to the given document 137 * @private 138 * @param {Document} ownerDocument The document. 139 * @returns {Object} An object of data. 140 */ 141 function getExpandoData(ownerDocument) { 142 var data = expandoData[ownerDocument[expando]]; 143 if (!data) { 144 data = {}; 145 expanID++; 146 ownerDocument[expando] = expanID; 147 expandoData[expanID] = data; 148 } 149 return data; 150 } 151 152 /** 153 * returns a shived element for the given nodeName and document 154 * @memberOf html5 155 * @param {String} nodeName name of the element 156 * @param {Document} ownerDocument The context document. 157 * @returns {Object} The shived element. 158 */ 159 function createElement(nodeName, ownerDocument, data){ 160 if (!ownerDocument) { 161 ownerDocument = document; 162 } 163 if(supportsUnknownElements){ 164 return ownerDocument.createElement(nodeName); 165 } 166 if (!data) { 167 data = getExpandoData(ownerDocument); 168 } 169 var node; 170 171 if (data.cache[nodeName]) { 172 node = data.cache[nodeName].cloneNode(); 173 } else if (saveClones.test(nodeName)) { 174 node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); 175 } else { 176 node = data.createElem(nodeName); 177 } 178 179 // Avoid adding some elements to fragments in IE < 9 because 180 // * Attributes like `name` or `type` cannot be set/changed once an element 181 // is inserted into a document/fragment 182 // * Link elements with `src` attributes that are inaccessible, as with 183 // a 403 response, will cause the tab/window to crash 184 // * Script elements appended to fragments will execute when their `src` 185 // or `text` property is set 186 return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; 187 } 188 189 /** 190 * returns a shived DocumentFragment for the given document 191 * @memberOf html5 192 * @param {Document} ownerDocument The context document. 193 * @returns {Object} The shived DocumentFragment. 194 */ 195 function createDocumentFragment(ownerDocument, data){ 196 if (!ownerDocument) { 197 ownerDocument = document; 198 } 199 if(supportsUnknownElements){ 200 return ownerDocument.createDocumentFragment(); 201 } 202 data = data || getExpandoData(ownerDocument); 203 var clone = data.frag.cloneNode(), 204 i = 0, 205 elems = getElements(), 206 l = elems.length; 207 for(;i<l;i++){ 208 clone.createElement(elems[i]); 209 } 210 return clone; 211 } 212 213 /** 214 * Shivs the `createElement` and `createDocumentFragment` methods of the document. 215 * @private 216 * @param {Document|DocumentFragment} ownerDocument The document. 217 * @param {Object} data of the document. 218 */ 219 function shivMethods(ownerDocument, data) { 220 if (!data.cache) { 221 data.cache = {}; 222 data.createElem = ownerDocument.createElement; 223 data.createFrag = ownerDocument.createDocumentFragment; 224 data.frag = data.createFrag(); 225 } 226 227 228 ownerDocument.createElement = function(nodeName) { 229 //abort shiv 230 if (!html5.shivMethods) { 231 return data.createElem(nodeName); 232 } 233 return createElement(nodeName, ownerDocument, data); 234 }; 235 236 ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + 237 'var n=f.cloneNode(),c=n.createElement;' + 238 'h.shivMethods&&(' + 239 // unroll the `createElement` calls 240 getElements().join().replace(/[\w\-:]+/g, function(nodeName) { 241 data.createElem(nodeName); 242 data.frag.createElement(nodeName); 243 return 'c("' + nodeName + '")'; 244 }) + 245 ');return n}' 246 )(html5, data.frag); 247 } 248 249 /*--------------------------------------------------------------------------*/ 250 251 /** 252 * Shivs the given document. 253 * @memberOf html5 254 * @param {Document} ownerDocument The document to shiv. 255 * @returns {Document} The shived document. 256 */ 257 function shivDocument(ownerDocument) { 258 if (!ownerDocument) { 259 ownerDocument = document; 260 } 261 var data = getExpandoData(ownerDocument); 262 263 if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { 264 data.hasCSS = !!addStyleSheet(ownerDocument, 265 // corrects block display not defined in IE6/7/8/9 266 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' + 267 // adds styling not present in IE6/7/8/9 268 'mark{background:#FF0;color:#000}' + 269 // hides non-rendered elements 270 'template{display:none}' 271 ); 272 } 273 if (!supportsUnknownElements) { 274 shivMethods(ownerDocument, data); 275 } 276 return ownerDocument; 277 } 278 279 /*--------------------------------------------------------------------------*/ 280 281 /** 282 * The `html5` object is exposed so that more elements can be shived and
283 * existing shiving can be detected on iframes. 284 * @type Object 285 * @example 286 * 287 * // options can be changed before the script is included 288 * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; 289 */ 290 var html5 = { 291 292 /** 293 * An array or space separated string of node names of the elements to shiv. 294 * @memberOf html5 295 * @type Array|String 296 */ 297 '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', 298 299 /** 300 * current version of html5shiv 301 */ 302 'version': version, 303 304 /** 305 * A flag to indicate that the HTML5 style sheet should be inserted. 306 * @memberOf html5 307 * @type Boolean 308 */ 309 'shivCSS': (options.shivCSS !== false), 310 311 /** 312 * Is equal to true if a browser supports creating unknown/HTML5 elements 313 * @memberOf html5 314 * @type boolean 315 */ 316 'supportsUnknownElements': supportsUnknownElements, 317 318 /** 319 * A flag to indicate that the document's `createElement` and `createDocumentFragment` 320 * methods should be overwritten. 321 * @memberOf html5 322 * @type Boolean 323 */ 324 'shivMethods': (options.shivMethods !== false), 325 326 /** 327 * A string to describe the type of `html5` object ("default" or "default print"). 328 * @memberOf html5
329 * @type String 330 */ 331 'type': 'default', 332 333 // shivs the document according to the specified `html5` object options 334 'shivDocument': shivDocument, 335 336 //creates a shived element 337 createElement: createElement, 338 339 //creates a shived documentFragment 340 createDocumentFragment: createDocumentFragment, 341 342 //extends list of elements 343 addElements: addElements 344 }; 345 346 /*--------------------------------------------------------------------------*/ 347 348 // expose html5 349 window.html5 = html5; 350 351 // shiv the document 352 shivDocument(document); 353 354 }(this, document)); 355 356 357 var tests = []; 358 359 360 var ModernizrProto = { 361 // The current version, dummy 362 _version: '3.0.0-alpha.3', 363 364 // Any settings that don't work as separate modules 365 // can go in here as configuration. 366 _config: { 367 'classPrefix' : '', 368 'enableClasses' : true, 369 'enableJSClass' : true, 370 'usePrefixes' : true 371 }, 372 373 // Queue of tests 374 _q: [], 375 376 // Stub these for people who are listening 377 on: function( test, cb ) { 378 // I don't really think people should do this, but we can 379 // safe guard it a bit. 380 // -- NOTE:: this gets WAY overridden in src/addTest for 381 // actual async tests. This is in case people listen to 382 // synchronous tests. I would leave it out, but the code 383 // to *disallow* sync tests in the real version of this 384 // function is actually larger than this. 385 var self = this; 386 setTimeout(function() { 387 cb(self[test]); 388 }, 0); 389 }, 390 391 addTest: function( name, fn, options ) { 392 tests.push({name : name, fn : fn, options : options }); 393 }, 394 395 addAsyncTest: function (fn) { 396 tests.push({name : null, fn : fn}); 397 } 398 }; 399 400 401 402 // Fake some of Object.create 403 // so we can force non test results 404 // to be non "own" properties. 405 var Modernizr = function(){}; 406 Modernizr.prototype = ModernizrProto; 407 408 // Leak modernizr globally when you `require` it 409 // rather than force it here. 410 // Overwrite name so constructor name is nicer :D 411 Modernizr = new Modernizr(); 412 413 414 415 416 var err = function() {}; 417 var warn = function() {}; 418 419 if (window.console) { 420 err = function() { 421 var method = console.error ? 'error' : 'log'; 422 window.console[method].apply( window.console, Array.prototype.slice.call(arguments) ); 423 }; 424 425 warn = function() { 426 var method = console.warn ? 'warn' : 'log'; 427 window.console[method].apply( window.console, Array.prototype.slice.call(arguments) ); 428 }; 429 } 430 431 ModernizrProto.load = function() { 432 if ('yepnope' in window) { 433 warn('yepnope.js (aka Modernizr.load) is no longer included as part of Modernizr. yepnope appears to be available on the page, so weâll use it to handle this call to Modernizr.load, but please update your code to use yepnope directly.\n See http://github.com/Modernizr/Modernizr/issues/1182 for more information.'); 434 window.yepnope.apply(window, [].slice.call(arguments,0)); 435 } else { 436 err('yepnope.js (aka Modernizr.load) is no longer included as part of Modernizr. Get it from http://yepnopejs.com. See http://github.com/Modernizr/Modernizr/issues/1182 for more information.'); 437 } 438 }; 439 440 441 442 // List of property values to set for css tests. See ticket #21 443 var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : []); 444 445 // expose these for the plugin API. Look in the source for how to join() them against your input 446 ModernizrProto._prefixes = prefixes; 447 448 449 450 /** 451 * is returns a boolean for if typeof obj is exactly type. 452 */ 453 function is( obj, type ) { 454 return typeof obj === type; 455 } 456 ; 457 458 // Run through all tests and detect their support in the current UA. 459 function testRunner() { 460 var featureNames; 461 var feature; 462 var aliasIdx; 463 var result; 464 var nameIdx; 465 var featureName; 466 var featureNameSplit; 467 468 for ( var featureIdx in tests ) { 469 featureNames = []; 470 feature = tests[featureIdx]; 471 // run the test, throw the return value into the Modernizr, 472 // then based on that boolean, define an appropriate className 473 // and push it into an array of classes we'll join later. 474 // 475 // If there is no name, it's an 'async' test that is run, 476 // but not directly added to the object. That should 477 // be done with a post-run addTest call. 478 if ( feature.name ) { 479 featureNames.push(feature.name.toLowerCase()); 480 481 if (feature.options && feature.options.aliases && feature.options.aliases.length) { 482 // Add all the aliases into the names list 483 for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) { 484 featureNames.push(feature.options.aliases[aliasIdx].toLowerCase()); 485 } 486 } 487 } 488 489 // Run the test, or use the raw value if it's not a function 490 result = is(feature.fn, 'function') ? feature.fn() : feature.fn; 491 492 493 // Set each of the names on the Modernizr object 494 for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) { 495 featureName = featureNames[nameIdx];
496 // Support dot properties as sub tests. We don't do checking to make sure 497 // that the implied parent tests have been added. You must call them in 498 // order (either in the test, or make the parent test a dependency). 499 // 500 // Cap it to TWO to make the logic simple and because who needs that kind of subtesting 501 // hashtag famous last words 502 featureNameSplit = featureName.split('.'); 503 504 if (featureNameSplit.length === 1) { 505 Modernizr[featureNameSplit[0]] = result; 506 } else { 507 // cast to a Boolean, if not one already 508 /* jshint -W053 */ 509 if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) { 510 Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]); 511 } 512 513 Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result; 514 } 515 516 classes.push((result ? '' : 'no-') + featureNameSplit.join('-')); 517 } 518 } 519 } 520 521 ; 522 523 var docElement = document.documentElement; 524 525 526 // Pass in an and array of class names, e.g.:
527 // ['no-webp', 'borderradius', ...] 528 function setClasses( classes ) { 529 var className = docElement.className; 530 var classPrefix = Modernizr._config.classPrefix || ''; 531 532 // Change `no-js` to `js` (we do this independently of the `enableClasses` 533 // option) 534 // Handle classPrefix on this too 535 if(Modernizr._config.enableJSClass) { 536 var reJS = new RegExp('(^|\\s)'+classPrefix+'no-js(\\s|$)'); 537 className = className.replace(reJS, '$1'+classPrefix+'js$2'); 538 } 539 540 if(Modernizr._config.enableClasses) { 541 // Add the new classes 542 className += ' ' + classPrefix + classes.join(' ' + classPrefix); 543 docElement.className = className; 544 } 545 546 } 547 548 ; 549 550 // Helper function for converting kebab-case to camelCase, 551 // e.g. box-sizing -> boxSizing 552 function cssToDOM( name ) { 553 return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) { 554 return m1 + m2.toUpperCase(); 555 }).replace(/^-/, ''); 556 } 557 ; 558 559 // Following spec is to expose vendor-specific style properties as: 560 // elem.style.WebkitBorderRadius 561 // and the following would be incorrect: 562 // elem.style.webkitBorderRadius 563 564 // Webkit ghosts their properties in lowercase but Opera & Moz do not. 565 // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ 566 // erik.eae.net/archives/2008/03/10/21.48.10/ 567 568 // More here: github.com/Modernizr/Modernizr/issues/issue/21 569 var omPrefixes = 'Moz O ms Webkit'; 570 571 572 var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []); 573 ModernizrProto._domPrefixes = domPrefixes; 574 575/*! 576{ 577 "name": "CSS Supports", 578 "property": "supports", 579 "caniuse": "css-featurequeries", 580 "tags": ["css"], 581 "builderAliases": ["css_supports"], 582 "notes": [{ 583 "name": "W3 Spec", 584 "href": "http://dev.w3.org/csswg/css3-conditional/#at-supports" 585 },{ 586 "name": "Related Github Issue", 587 "href": "github.com/Modernizr/Modernizr/issues/648" 588 },{ 589 "name": "W3 Info", 590 "href": "http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface" 591 }] 592} 593!*/ 594 595 var newSyntax = 'CSS' in window && 'supports' in window.CSS; 596 var oldSyntax = 'supportsCSS' in window; 597 Modernizr.addTest('supports', newSyntax || oldSyntax); 598 599 600 var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []); 601 ModernizrProto._cssomPrefixes = cssomPrefixes; 602 603 604 /** 605 * atRule returns a given CSS property at-rule (eg @keyframes), possibly in 606 * some prefixed form, or false, in the case of an unsupported rule 607 * 608 * @param prop - String naming the property to test 609 */ 610 611 var atRule = function(prop) { 612 var length = prefixes.length; 613 var cssrule = window.CSSRule; 614 var rule; 615 616 if (typeof cssrule === 'undefined') { 617 return undefined; 618 } 619 620 if (!prop) { 621 return false; 622 } 623 624 // remove literal @ from beginning of provided property 625 prop = prop.replace(/^@/,''); 626 627 // CSSRules use underscores instead of dashes 628 rule = prop.replace(/-/g,'_').toUpperCase() + '_RULE'; 629 630 if (rule in cssrule) { 631 return '@' + prop; 632 } 633 634 for ( var i = 0; i < length; i++ ) { 635 // prefixes gives us something like -o-, and we want O_ 636 var prefix = prefixes[i]; 637 var thisRule = prefix.toUpperCase() + '_' + rule; 638 639 if (thisRule in cssrule) { 640 return '@-' + prefix.toLowerCase() + '-' + prop; 641 } 642 } 643 644 return false; 645 }; 646 647 648 649 var createElement = function() { 650 if (typeof document.createElement !== 'function') { 651 // This is the case in IE7, where the type of createElement is "object". 652 // For this reason, we cannot call apply() as Object is not a Function. 653 return document.createElement(arguments[0]); 654 } else { 655 return document.createElement.apply(document, arguments); 656 } 657 }; 658 659 660 function getBody() { 661 // After page load injecting a fake body doesn't work so check if body exists 662 var body = document.body; 663 664 if(!body) { 665 // Can't use the real body create a fake one. 666 body = createElement('body'); 667 body.fake = true; 668 } 669 670 return body; 671 } 672 673 ; 674 675 // Inject element with style element and some CSS rules 676 function injectElementWithStyles( rule, callback, nodes, testnames ) { 677 var mod = 'modernizr'; 678 var style; 679 var ret; 680 var node; 681 var docOverflow; 682 var div = createElement('div'); 683 var body = getBody(); 684 685 if ( parseInt(nodes, 10) ) { 686 // In order not to give false positives we create a node for each test
687 // This also allows the method to scale for unspecified uses 688 while ( nodes-- ) { 689 node = createElement('div'); 690 node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 691 div.appendChild(node); 692 } 693 } 694 695 // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed 696 // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element 697 // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements. 698 // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx 699 // Documents served as xml will throw if using ­ so use xml friendly encoded version. See issue #277 700 style = ['­','<style id="s', mod, '">', rule, '</style>'].join(''); 701 div.id = mod; 702 // 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. 703 // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 704 (!body.fake ? div : body).innerHTML += style; 705 body.appendChild(div); 706 if ( body.fake ) { 707 //avoid crashing IE8, if background image is used 708 body.style.background = ''; 709 //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible 710 body.style.overflow = 'hidden'; 711 docOverflow = docElement.style.overflow; 712 docElement.style.overflow = 'hidden'; 713 docElement.appendChild(body); 714 } 715 716 ret = callback(div, rule); 717 // If this is done after page load we don't want to remove the body so check if body exists 718 if ( body.fake ) { 719 body.parentNode.removeChild(body); 720 docElement.style.overflow = docOverflow; 721 // Trigger layout so kinetic scrolling isn't disabled in iOS6+ 722 docElement.offsetHeight; 723 } else { 724 div.parentNode.removeChild(div); 725 } 726 727 return !!ret; 728 729 } 730 731 ; 732 733 var testStyles = ModernizrProto.testStyles = injectElementWithStyles; 734 735/*! 736{ 737 "name": "Touch Events", 738 "property": "touchevents", 739 "caniuse" : "touch", 740 "tags": ["media", "attribute"], 741 "notes": [{ 742 "name": "Touch Events spec", 743 "href": "http://www.w3.org/TR/2013/WD-touch-events-20130124/" 744 }], 745 "warnings": [ 746 "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device" 747 ], 748 "knownBugs": [ 749 "False-positive on some configurations of Nokia N900", 750 "False-positive on some BlackBerry 6.0 builds â https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695" 751 ] 752} 753!*/ 754/* DOC 755Indicates if the browser supports the W3C Touch Events API. 756 757This *does not* necessarily reflect a touchscreen device: 758 759* Older touchscreen devices only emulate mouse events 760* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that 761* Some browsers & OS setups may enable touch APIs when no touchscreen is connected 762* Future browsers may implement other event models for touch interactions 763 764See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/). 765 766It's recommended to bind both mouse and touch/pointer events simultaneously â see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/). 767 768This test will also return `true` for Firefox 4 Multitouch support. 769*/ 770 771 // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415 772 Modernizr.addTest('touchevents', function() { 773 var bool; 774 if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { 775 bool = true; 776 } else { 777 var query = ['@media (',prefixes.join('touch-enabled),('),'heartz',')','{#modernizr{top:9px;position:absolute}}'].join(''); 778 testStyles(query, function( node ) { 779 bool = node.offsetTop === 9; 780 }); 781 } 782 return bool; 783 }); 784 785 786 // adapted from matchMedia polyfill 787 // by Scott Jehl and Paul Irish 788 // gist.github.com/786768 789 var testMediaQuery = (function () { 790 var matchMedia = window.matchMedia || window.msMatchMedia; 791 if ( matchMedia ) { 792 return function ( mq ) { 793 var mql = matchMedia(mq); 794 return mql && mql.matches || false; 795 }; 796 } 797 798 return function ( mq ) { 799 var bool = false;
800 801 injectElementWithStyles('@media ' + mq + ' { #modernizr { position: absolute; } }', function( node ) { 802 bool = (window.getComputedStyle ? 803 window.getComputedStyle(node, null) : 804 node.currentStyle)['position'] == 'absolute'; 805 }); 806 807 return bool; 808 }; 809 })(); 810 811 812 813 /** Modernizr.mq tests a given media query, live against the current state of the window 814 * A few important notes: 815 * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false 816 * A max-width or orientation query will be evaluated against the current state, which may change later. 817 * You must specify values. Eg. If you are testing support for the min-width media query use: 818 Modernizr.mq('(min-width:0)') 819 * usage: 820 * Modernizr.mq('only screen and (max-width:768)') 821 */ 822 var mq = ModernizrProto.mq = testMediaQuery; 823 824 825 /** 826 * contains returns a boolean for if substr is found within str. 827 */ 828 function contains( str, substr ) { 829 return !!~('' + str).indexOf(substr); 830 } 831 832 ; 833 834 // Change the function's scope. 835 function fnBind(fn, that) { 836 return function() { 837 return fn.apply(that, arguments); 838 }; 839 } 840 841 ; 842 843 /** 844 * testDOMProps is a generic DOM property test; if a browser supports 845 * a certain property, it won't return undefined for it. 846 */ 847 function testDOMProps( props, obj, elem ) { 848 var item; 849 850 for ( var i in props ) { 851 if ( props[i] in obj ) { 852 853 // return the property name as a string 854 if (elem === false) return props[i]; 855 856 item = obj[props[i]]; 857 858 // let's bind a function 859 if (is(item, 'function')) { 860 // bind to obj unless overriden 861 return fnBind(item, elem || obj); 862 } 863 864 // return the unbound function or obj or value 865 return item; 866 } 867 } 868 return false; 869 } 870 871 ; 872 873 /** 874 * Create our "modernizr" element that we do most feature tests on. 875 */ 876 var modElem = { 877 elem : createElement('modernizr') 878 }; 879 880 // Clean up this element 881 Modernizr._q.push(function() { 882 delete modElem.elem; 883 }); 884 885 886 887 var mStyle = { 888 style : modElem.elem.style 889 }; 890 891 // kill ref for gc, must happen before 892 // mod.elem is removed, so we unshift on to 893 // the front of the queue. 894 Modernizr._q.unshift(function() { 895 delete mStyle.style; 896 }); 897 898 899 900 // Helper function for converting camelCase to kebab-case, 901 // e.g. boxSizing -> box-sizing 902 function domToCSS( name ) { 903 return name.replace(/([A-Z])/g, function(str, m1) { 904 return '-' + m1.toLowerCase(); 905 }).replace(/^ms-/, '-ms-'); 906 } 907 ; 908 909 // Function to allow us to use native feature detection functionality if available. 910 // Accepts a list of property names and a single value 911 // Returns `undefined` if native detection not available 912 function nativeTestProps ( props, value ) { 913 var i = props.length; 914 // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface 915 if ('CSS' in window && 'supports' in window.CSS) { 916 // Try every prefixed variant of the property 917 while (i--) { 918 if (window.CSS.supports(domToCSS(props[i]), value)) { 919 return true; 920 } 921 } 922 return false; 923 } 924 // Otherwise fall back to at-rule (for Opera 12.x) 925 else if ('CSSSupportsRule' in window) { 926 // Build a condition string for every prefixed variant 927 var conditionText = []; 928 while (i--) { 929 conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')'); 930 } 931 conditionText = conditionText.join(' or '); 932 return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function( node ) { 933 return getComputedStyle(node, null).position == 'absolute'; 934 }); 935 } 936 return undefined; 937 } 938 ; 939 940 // testProps is a generic CSS / DOM property test. 941 942 // In testing support for a given CSS property, it's legit to test: 943 // `elem.style[styleName] !== undefined` 944 // If the property is supported it will return an empty string, 945 // if unsupported it will return undefined. 946 947 // We'll take advantage of this quick test and skip setting a style 948 // on our modernizr element, but instead just testing undefined vs 949 // empty string. 950 951 // Property names can be provided in either camelCase or kebab-case. 952 953 function testProps( props, prefixed, value, skipValueTest ) { 954 skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest; 955 956 // Try native detect first 957 if (!is(value, 'undefined')) { 958 var result = nativeTestProps(props, value); 959 if(!is(result, 'undefined')) { 960 return result; 961 } 962 } 963 964 // Otherwise do it properly 965 var afterInit, i, propsLength, prop, before; 966 967 // If we don't have a style element, that means 968 // we're running async or after the core tests, 969 // so we'll need to create our own elements to use 970 if ( !mStyle.style ) { 971 afterInit = true; 972 mStyle.modElem = createElement('modernizr'); 973 mStyle.style = mStyle.modElem.style; 974 } 975 976 // Delete the objects if we 977 // we created them. 978 function cleanElems() { 979 if (afterInit) { 980 delete mStyle.style; 981 delete mStyle.modElem; 982 } 983 } 984 985 propsLength = props.length; 986 for ( i = 0; i < propsLength; i++ ) { 987 prop = props[i]; 988 before = mStyle.style[prop]; 989 990 if (contains(prop, '-')) { 991 prop = cssToDOM(prop); 992 } 993 994 if ( mStyle.style[prop] !== undefined ) { 995 996 // If value to test has been passed in, do a set-and-check test. 997 // 0 (integer) is a valid property value, so check that `value` isn't 998 // undefined, rather than just checking it's truthy. 999 if (!skipValueTest && !is(value, 'undefined')) { 1000 1001 // Needs a try catch block because of old IE. This is slow, but will 1002 // be avoided in most cases because `skipValueTest` will be used. 1003 try { 1004 mStyle.style[prop] = value; 1005 } catch (e) {} 1006 1007 // If the property value has changed, we assume the value used is 1008 // supported. If `value` is empty string, it'll fail here (because 1009 // it hasn't changed), which matches how browsers have implemented 1010 // CSS.supports() 1011 if (mStyle.style[prop] != before) { 1012 cleanElems(); 1013 return prefixed == 'pfx' ? prop : true; 1014 } 1015 } 1016 // Otherwise just return true, or the property name if this is a 1017 // `prefixed()` call 1018 else { 1019 cleanElems(); 1020 return prefixed == 'pfx' ? prop : true; 1021 } 1022 } 1023 } 1024 cleanElems(); 1025 return false;
1026 } 1027 1028 ; 1029 1030 // Modernizr.testProp() investigates whether a given style property is recognized 1031 // Property names can be provided in either camelCase or kebab-case. 1032 // Modernizr.testProp('pointerEvents') 1033 // Also accepts optional 2nd arg, of a value to use for native feature detection, e.g.: 1034 // Modernizr.testProp('pointerEvents', 'none') 1035 var testProp = ModernizrProto.testProp = function( prop, value, useValue ) { 1036 return testProps([prop], undefined, value, useValue); 1037 }; 1038 1039 1040 /** 1041 * testPropsAll tests a list of DOM properties we want to check against. 1042 * We specify literally ALL possible (known and/or likely) properties on 1043 * the element including the non-vendor prefixed one, for forward- 1044 * compatibility. 1045 */ 1046 function testPropsAll( prop, prefixed, elem, value, skipValueTest ) { 1047 1048 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 1049 props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 1050 1051 // did they call .prefixed('boxSizing') or are we just testing a prop? 1052 if(is(prefixed, 'string') || is(prefixed, 'undefined')) { 1053 return testProps(props, prefixed, value, skipValueTest); 1054 1055 // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) 1056 } else { 1057 props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 1058 return testDOMProps(props, prefixed, elem); 1059 } 1060 } 1061 1062 // Modernizr.testAllProps() investigates whether a given style property, 1063 // or any of its vendor-prefixed variants, is recognized 1064 // Note that the property names must be provided in the camelCase variant. 1065 // Modernizr.testAllProps('boxSizing') 1066 ModernizrProto.testAllProps = testPropsAll; 1067 1068 1069 1070 // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input 1071 // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' 1072 1073 // Properties can be passed as DOM-style camelCase or CSS-style kebab-case. 1074 // Return values will always be in camelCase; if you want kebab-case, use Modernizr.prefixedCSS(). 1075 1076 // If you're trying to ascertain which transition end event to bind to, you might do something like... 1077 // 1078 // var transEndEventNames = { 1079 // 'WebkitTransition' : 'webkitTransitionEnd',// Saf 6, Android Browser 1080 // 'MozTransition' : 'transitionend', // only for FF < 15 1081 // 'transition' : 'transitionend' // IE10, Opera, Chrome, FF 15+, Saf 7+ 1082 // }, 1083 // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; 1084 1085 var prefixed = ModernizrProto.prefixed = function( prop, obj, elem ) { 1086 if (prop.indexOf('@') === 0) { 1087 return atRule(prop); 1088 } 1089 1090 if (prop.indexOf('-') != -1) { 1091 // Convert kebab-case to camelCase 1092 prop = cssToDOM(prop); 1093 } 1094 if (!obj) { 1095 return testPropsAll(prop, 'pfx'); 1096 } else { 1097 // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' 1098 return testPropsAll(prop, obj, elem); 1099 } 1100 }; 1101 1102 1103 1104 /** 1105 * testAllProps determines whether a given CSS property, in some prefixed 1106 * form, is supported by the browser. It can optionally be given a value; in 1107 * which case testAllProps will only return true if the browser supports that 1108 * value for the named property; this latter case will use native detection 1109 * (via window.CSS.supports) if available. A boolean can be passed as a 3rd 1110 * parameter to skip the value check when native detection isn't available, 1111 * to improve performance when simply testing for support of a property. 1112 * 1113 * @param prop - String naming the property to test (either camelCase or 1114 * kebab-case) 1115 * @param value - [optional] String of the value to test 1116 * @param skipValueTest - [optional] Whether to skip testing that the value 1117 * is supported when using non-native detection 1118 * (default: false) 1119 */ 1120 function testAllProps (prop, value, skipValueTest) { 1121 return testPropsAll(prop, undefined, undefined, value, skipValueTest); 1122 } 1123 ModernizrProto.testAllProps = testAllProps; 1124 1125/*! 1126{ 1127 "name": "CSS Transforms", 1128 "property": "csstransforms", 1129 "caniuse": "transforms2d", 1130 "tags": ["css"] 1131} 1132!*/ 1133 1134 Modernizr.addTest('csstransforms', function() { 1135 // Android < 3.0 is buggy, so we sniff and blacklist 1136 // http://git.io/hHzL7w 1137 return navigator.userAgent.indexOf('Android 2.') === -1 && 1138 testAllProps('transform', 'scale(1)', true); 1139 }); 1140 1141/*! 1142{ 1143 "name": "CSS Transforms 3D", 1144 "property": "csstransforms3d", 1145 "caniuse": "transforms3d", 1146 "tags": ["css"], 1147 "warnings": [ 1148 "Chrome may occassionally fail this test on some systems; more info: https://code.google.com/p/chromium/issues/detail?id=129004" 1149 ] 1150} 1151!*/ 1152 1153 Modernizr.addTest('csstransforms3d', function() { 1154 var ret = !!testAllProps('perspective', '1px', true); 1155 var usePrefix = Modernizr._config.usePrefixes; 1156 1157 // Webkit's 3D transforms are passed off to the browser's own graphics renderer. 1158 // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in 1159 // some conditions. As a result, Webkit typically recognizes the syntax but 1160 // will sometimes throw a false positive, thus we must do a more thorough check: 1161 if ( ret && (!usePrefix || 'webkitPerspective' in docElement.style )) { 1162 var mq; 1163 // Use CSS Conditional Rules if available 1164 if (Modernizr.supports) { 1165 mq = '@supports (perspective: 1px)'; 1166 } else { 1167 // Otherwise, Webkit allows this media query to succeed only if the feature is enabled. 1168 // `@media (transform-3d),(-webkit-transform-3d){ ... }` 1169 mq = '@media (transform-3d)'; 1170 if (usePrefix ) mq += ',(-webkit-transform-3d)'; 1171 } 1172 // If loaded inside the body tag and the test element inherits any padding, margin or borders it will fail #740 1173 mq += '{#modernizr{left:9px;position:absolute;height:5px;margin:0;padding:0;border:0}}'; 1174 1175 testStyles(mq, function( elem ) { 1176 ret = elem.offsetLeft === 9 && elem.offsetHeight === 5; 1177 }); 1178 } 1179 1180 return ret; 1181 }); 1182 1183/*! 1184{ 1185 "name": "CSS Transitions", 1186 "property": "csstransitions", 1187 "caniuse": "css-transitions", 1188 "tags": ["css"] 1189} 1190!*/ 1191 1192 Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true)); 1193 1194 1195 // Run each test 1196 testRunner(); 1197 1198 // Remove the "no-js" class if it exists 1199 setClasses(classes); 1200 1201 delete ModernizrProto.addTest; 1202 delete ModernizrProto.addAsyncTest; 1203 1204 // Run the things that are supposed to run after the tests 1205 for (var i = 0; i < Modernizr._q.length; i++) { 1206 Modernizr._q[i](); 1207 } 1208 1209 // Leak Modernizr namespace 1210 window.Modernizr = Modernizr; 1211 1212 1213; 1214 1215})(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.