vendor: 30,415 bytes, lines 1-1156
1/* 2css3-mediaqueries.js - CSS Helper and CSS3 Media Queries Enabler 3 4author: Wouter van der Graaf <wouter at dynora nl> 5version: 1.0 (20110330) 6license: MIT 7website: http://code.google.com/p/css3-mediaqueries-js/ 8 9W3C spec: http://www.w3.org/TR/css3-mediaqueries/ 10 11Note: use of embedded <style> is not recommended when using media queries, because IE has no way of returning the raw literal css text from a <style> element. 12*/ 13 14 15// true prototypal inheritance (http://javascript.crockford.com/prototypal.html) 16if (typeof Object.create !== 'function') { 17 Object.create = function (o) { 18 function F() {} 19 F.prototype = o; 20 return new F(); 21 }; 22} 23 24 25// user agent sniffing shortcuts 26var ua = { 27 toString: function () { 28 return navigator.userAgent; 29 }, 30 test: function (s) { 31 return this.toString().toLowerCase().indexOf(s.toLowerCase()) > -1; 32 } 33}; 34ua.version = (ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1]; 35ua.webkit = ua.test('webkit'); 36ua.gecko = ua.test('gecko') && !ua.webkit; 37ua.opera = ua.test('opera'); 38ua.ie = ua.test('msie') && !ua.opera; 39ua.ie6 = ua.ie && document.compatMode && typeof document.documentElement.style.maxHeight === 'undefined'; 40ua.ie7 = ua.ie && document.documentElement && typeof document.documentElement.style.maxHeight !== 'undefined' && typeof XDomainRequest === 'undefined'; 41ua.ie8 = ua.ie && typeof XDomainRequest !== 'undefined'; 42 43 44 45// initialize when DOM content is loaded 46var domReady = function () { 47 var fns = []; 48 var init = function () { 49 if (!arguments.callee.done) { // run init functions once 50 arguments.callee.done = true; 51 for (var i = 0; i < fns.length; i++) { 52 fns[i](); 53 } 54 } 55 }; 56 57 // listeners for different browsers 58 if (document.addEventListener) { 59 document.addEventListener('DOMContentLoaded', init, false); 60 } 61 if (ua.ie) { 62 (function () { 63 try { 64 // throws errors until after ondocumentready 65 document.documentElement.doScroll('left'); 66 67 // If we are in an iframe, the above does not work properly. 68 // Trying to access the length attribute of document.body, however, 69 // does throw an error until ondocumentready, fixing this issue. 70 document.body.length; 71 } 72 catch (e) { 73 setTimeout(arguments.callee, 50); 74 return; 75 } 76 // no errors, fire 77 init(); 78 })(); 79 // trying to always fire before onload 80 document.onreadystatechange = function () { 81 if (document.readyState === 'complete') { 82 document.onreadystatechange = null; 83 init(); 84 } 85 }; 86 } 87 if (ua.webkit && document.readyState) { 88 (function () { 89 if (document.readyState !== 'loading') { 90 init(); 91 } 92 else { 93 setTimeout(arguments.callee, 10); 94 } 95 })(); 96 } 97 window.onload = init; // fallback 98 99 return function (fn) { // add fn to init functions 100 if (typeof fn === 'function') { 101 // If DOM ready has already been fired, fire the function 102 // right away. 103 if(init.done) { 104 fn(); 105 } else { 106 // Add to the queue 107 fns[fns.length] = fn; 108 } 109 } 110 return fn; 111 }; 112}(); 113 114 115// helper library for parsing css to objects 116var cssHelper = function () { 117 118 var regExp = { 119 BLOCKS: /[^\s{;][^{;]*\{(?:[^{}]*\{[^{}]*\}[^{}]*|[^{}]*)*\}/g, 120 BLOCKS_INSIDE: /[^\s{][^{]*\{[^{}]*\}/g, 121 DECLARATIONS: /[a-zA-Z\-]+[^;]*:[^;]+;/g, 122 RELATIVE_URLS: /url\(['"]?([^\/\)'"][^:\)'"]+)['"]?\)/g, 123 // strip whitespace and comments, @import is evil 124 REDUNDANT_COMPONENTS: /(?:\/\*([^*\\\\]|\*(?!\/))+\*\/|@import[^;]+;|@-moz-document\s*url-prefix\(\)\s*{(([^{}])+{([^{}])+}([^{}])+)+})/g, 125 REDUNDANT_WHITESPACE: /\s*(,|:|;|\{|\})\s*/g, 126 WHITESPACE_IN_PARENTHESES: /\(\s*(\S*)\s*\)/g, 127 MORE_WHITESPACE: /\s{2,}/g, 128 FINAL_SEMICOLONS: /;\}/g, 129 NOT_WHITESPACE: /\S+/g 130 }; 131 132 var parsed, parsing = false; 133 134 var waiting = []; 135 var wait = function (fn) { 136 if (typeof fn === 'function') { 137 waiting[waiting.length] = fn; 138 } 139 }; 140 var ready = function () { 141 for (var i = 0; i < waiting.length; i++) { 142 waiting[i](parsed); 143 } 144 }; 145 var events = {}; 146 var broadcast = function (n, v) { 147 if (events[n]) { 148 var listeners = events[n].listeners; 149 if (listeners) { 150 for (var i = 0; i < listeners.length; i++) { 151 listeners[i](v); 152 } 153 } 154 } 155 }; 156 157 var requestText = function (url, fnSuccess, fnFailure) { 158 if (ua.ie && !window.XMLHttpRequest) { 159 window.XMLHttpRequest = function () { 160 return new ActiveXObject('Microsoft.XMLHTTP'); 161 }; 162 } 163 if (!XMLHttpRequest) { 164 return ''; 165 } 166 var r = new XMLHttpRequest(); 167 try { 168 r.open('get', url, true); 169 r.setRequestHeader('X_REQUESTED_WITH', 'XMLHttpRequest'); 170 } 171 catch (e) { 172 fnFailure(); 173 return; 174 } 175 var done = false; 176 setTimeout(function () { 177 done = true; 178 }, 5000); 179 document.documentElement.style.cursor = 'progress'; 180 r.onreadystatechange = function () { 181 if (r.readyState === 4 && !done) { 182 if (!r.status && location.protocol === 'file:' || 183 (r.status >= 200 && r.status < 300) || 184 r.status === 304 || 185 navigator.userAgent.indexOf('Safari') > -1 && typeof r.status === 'undefined') { 186 fnSuccess(r.responseText); 187 } 188 else { 189 fnFailure(); 190 } 191 document.documentElement.style.cursor = ''; 192 r = null; // avoid memory leaks 193 } 194 }; 195 r.send(''); 196 }; 197 198 var sanitize = function (text) { 199 text = text.replace(regExp.REDUNDANT_COMPONENTS, ''); 200 text = text.replace(regExp.REDUNDANT_WHITESPACE, '$1'); 201 text = text.replace(regExp.WHITESPACE_IN_PARENTHESES, '($1)'); 202 text = text.replace(regExp.MORE_WHITESPACE, ' '); 203 text = text.replace(regExp.FINAL_SEMICOLONS, '}'); // optional final semicolons 204 return text; 205 }; 206 207 var objects = { 208 stylesheet: function (el) { 209 var o = {}; 210 var amqs = [], mqls = [], rs = [], rsw = []; 211 var s = el.cssHelperText; 212 213 // add attribute media queries 214 var attr = el.getAttribute('media'); 215 if (attr) { 216 var qts = attr.toLowerCase().split(',') 217 } 218 else { 219 var qts = ['all'] // imply 'all' 220 } 221 for (var i = 0; i < qts.length; i++) { 222 amqs[amqs.length] = objects.mediaQuery(qts[i], o); 223 } 224 225 // add media query lists and rules (top down order) 226 var blocks = s.match(regExp.BLOCKS); // @charset is not a block 227 if (blocks !== null) { 228 for (var i = 0; i < blocks.length; i++) { 229 if (blocks[i].substring(0, 7) === '@media ') { // media query (list) 230 var mql = objects.mediaQueryList(blocks[i], o); 231 rs = rs.concat(mql.getRules()); 232 mqls[mqls.length] = mql; 233 } 234 else { // regular rule set, page context (@page) or font description (@font-face) 235 rs[rs.length] = rsw[rsw.length] = objects.rule(blocks[i], o, null); 236 } 237 } 238 } 239 240 o.element = el; 241 o.getCssText = function () { 242 return s; 243 }; 244 o.getAttrMediaQueries = function () { 245 return amqs; 246 }; 247 o.getMediaQueryLists = function () { 248 return mqls; 249 }; 250 o.getRules = function () { 251 return rs; 252 }; 253 o.getRulesWithoutMQ = function () { 254 return rsw; 255 }; 256 return o; 257 }, 258 259 mediaQueryList: function (s, stsh) { 260 var o = {}; 261 var idx = s.indexOf('{'); 262 var lt = s.substring(0, idx); 263 s = s.substring(idx + 1, s.length - 1); 264 var mqs = [], rs = []; 265 266 // add media queries 267 var qts = lt.toLowerCase().substring(7).split(','); 268 for (var i = 0; i < qts.length; i++) { // parse each media query 269 mqs[mqs.length] = objects.mediaQuery(qts[i], o); 270 } 271 272 // add rule sets 273 var rts = s.match(regExp.BLOCKS_INSIDE); 274 if (rts !== null) { 275 for (i = 0; i < rts.length; i++) { 276 rs[rs.length] = objects.rule(rts[i], stsh, o); 277 } 278 } 279 280 o.type = 'mediaQueryList'; 281 o.getMediaQueries = function () { 282 return mqs; 283 }; 284 o.getRules = function () { 285 return rs; 286 }; 287 o.getListText = function () { 288 return lt; 289 }; 290 o.getCssText = function () { 291 return s; 292 }; 293 return o; 294 }, 295 296 mediaQuery: function (s, listOrSheet) { 297 s = s || ''; 298 var mql, stsh; 299 if (listOrSheet.type === 'mediaQueryList') { 300 mql = listOrSheet; 301 } 302 else { 303 stsh = listOrSheet; 304 } 305 var not = false, type; 306 var expr = []; 307 var valid = true; 308 var tokens = s.match(regExp.NOT_WHITESPACE); 309 310 311 312 for (var i = 0; i < tokens.length; i++) { 313 var token = tokens[i]; 314 if (!type && (token === 'not' || token === 'only')) { // 'not' and 'only' keywords 315 // keyword 'only' does nothing, as if it was not present 316 if (token === 'not') { 317 not = true; 318 } 319 } 320 else if (!type) { // media type 321 type = token; 322 } 323 else if (token.charAt(0) === '(') { // media feature expression 324 var pair = token.substring(1, token.length - 1).split(':'); 325 expr[expr.length] = { 326 mediaFeature: pair[0], 327 value: pair[1] || null 328 }; 329 } 330 } 331 332 return { 333 getQueryText: function () { 334 return s; 335 }, 336 getAttrStyleSheet: function () { 337 return stsh || null; 338 }, 339 getList: function () { 340 return mql || null; 341 }, 342 getValid: function () { 343 return valid; 344 }, 345 getNot: function () { 346 return not; 347 }, 348 getMediaType: function () { 349 return type; 350 }, 351 getExpressions: function () { 352 return expr; 353 } 354 }; 355 }, 356 357 rule: function (s, stsh, mql) { 358 var o = {}; 359 var idx = s.indexOf('{'); 360 var st = s.substring(0, idx); 361 var ss = st.split(','); 362 var ds = []; 363 var dts = s.substring(idx + 1, s.length - 1).split(';'); 364 for (var i = 0; i < dts.length; i++) { 365 ds[ds.length] = objects.declaration(dts[i], o); 366 } 367 368 o.getStylesheet = function () { 369 return stsh || null; 370 }; 371 o.getMediaQueryList = function () { 372 return mql || null; 373 }; 374 o.getSelectors = function () { 375 return ss; 376 }; 377 o.getSelectorText = function () { 378 return st; 379 }; 380 o.getDeclarations = function () { 381 return ds; 382 }; 383 o.getPropertyValue = function (n) { 384 for (var i = 0; i < ds.length; i++) { 385 if (ds[i].getProperty() === n) { 386 return ds[i].getValue(); 387 } 388 } 389 return null; 390 }; 391 return o; 392 }, 393 394 declaration: function (s, r) { 395 var idx = s.indexOf(':'); 396 var p = s.substring(0, idx); 397 var v = s.substring(idx + 1); 398 return { 399 getRule: function () { 400 return r || null; 401 }, 402 getProperty: function () { 403 return p; 404 }, 405 getValue: function () { 406 return v; 407 } 408 }; 409 } 410 }; 411 412 var parseText = function (el) { 413 if (typeof el.cssHelperText !== 'string') { 414 return; 415 } 416 var o = { 417 stylesheet: null, 418 mediaQueryLists: [], 419 rules: [], 420 selectors: {}, 421 declarations: [], 422 properties: {} 423 }; 424 425 // build stylesheet object 426 var stsh = o.stylesheet = objects.stylesheet(el); 427 428 // collect media query lists 429 var mqls = o.mediaQueryLists = stsh.getMediaQueryLists(); 430 431 // collect all rules 432 var ors = o.rules = stsh.getRules(); 433 434 // collect all selectors 435 var oss = o.selectors; 436 var collectSelectors = function (r) { 437 var ss = r.getSelectors(); 438 for (var i = 0; i < ss.length; i++) { 439 var n = ss[i]; 440 if (!oss[n]) { 441 oss[n] = []; 442 } 443 oss[n][oss[n].length] = r; 444 } 445 }; 446 for (i = 0; i < ors.length; i++) { 447 collectSelectors(ors[i]); 448 } 449 450 // collect all declarations 451 var ods = o.declarations; 452 for (i = 0; i < ors.length; i++) { 453 ods = o.declarations = ods.concat(ors[i].getDeclarations()); 454 } 455 456 // collect all properties 457 var ops = o.properties; 458 for (i = 0; i < ods.length; i++) { 459 var n = ods[i].getProperty(); 460 if (!ops[n]) { 461 ops[n] = []; 462 } 463 ops[n][ops[n].length] = ods[i]; 464 } 465 466 el.cssHelperParsed = o; 467 parsed[parsed.length] = el; 468 return o; 469 }; 470 471 var parseEmbedded = function (el, s) { 472 return; 473 // This function doesn't work because of a bug in IE, where innerHTML gives us parsed css instead of raw literal. 474 el.cssHelperText = sanitize(s || el.innerHTML); 475 return parseText(el); 476 }; 477 478 var parse = function () { 479 parsing = true; 480 parsed = []; 481 var linked = []; 482 var finish = function () { 483 for (var i = 0; i < linked.length; i++) { 484 parseText(linked[i]); 485 } 486 var styles = document.getElementsByTagName('style'); 487 for (i = 0; i < styles.length; i++) { 488 parseEmbedded(styles[i]); 489 } 490 parsing = false; 491 ready(); 492 }; 493 var links = document.getElementsByTagName('link'); 494 for (var i = 0; i < links.length; i++) { 495 var link = links[i]; 496 if (link.getAttribute('rel').indexOf('style') > -1 && link.href && link.href.length !== 0 && !link.disabled) { 497 linked[linked.length] = link; 498 } 499 } 500 if (linked.length > 0) { 501 var c = 0; 502 var checkForFinish = function () { 503 c++; 504 if (c === linked.length) { // parse in right order, so after last link is read 505 finish(); 506 } 507 }; 508 var processLink = function (link) { 509 var href = link.href; 510 requestText(href, function (text) { 511 // fix url's 512 text = sanitize(text).replace(regExp.RELATIVE_URLS, 'url(' + href.substring(0, href.lastIndexOf('/')) + '/$1)'); 513 link.cssHelperText = text; 514 checkForFinish(); 515 }, checkForFinish); 516 }; 517 for (i = 0; i < linked.length; i++) { 518 processLink(linked[i]); 519 } 520 } 521 else { 522 finish(); 523 } 524 }; 525 526 var types = { 527 stylesheets: 'array', 528 mediaQueryLists: 'array', 529 rules: 'array', 530 selectors: 'object', 531 declarations: 'array', 532 properties: 'object' 533 }; 534 535 var collections = { 536 stylesheets: null, 537 mediaQueryLists: null, 538 rules: null, 539 selectors: null, 540 declarations: null, 541 properties: null 542 }; 543 544 var addToCollection = function (name, v) { 545 if (collections[name] !== null) { 546 if (types[name] === 'array') { 547 return (collections[name] = collections[name].concat(v)); 548 } 549 else { 550 var c = collections[name]; 551 for (var n in v) { 552 if (v.hasOwnProperty(n)) { 553 if (!c[n]) { 554 c[n] = v[n]; 555 } 556 else { 557 c[n] = c[n].concat(v[n]); 558 } 559 } 560 } 561 return c; 562 } 563 } 564 }; 565 566 var collect = function (name) { 567 collections[name] = (types[name] === 'array') ? [] : {}; 568 for (var i = 0; i < parsed.length; i++) { 569 var pname = name === 'stylesheets' ? 'stylesheet' : name; // the exception 570 addToCollection(name, parsed[i].cssHelperParsed[pname]); 571 } 572 return collections[name]; 573 }; 574 575 // viewport size 576 var getViewportSize = function (d) { 577 if (typeof window.innerWidth != 'undefined') { 578 return window['inner' + d]; 579 } 580 else if (typeof document.documentElement !== 'undefined' 581 && typeof document.documentElement.clientWidth !== 'undefined' 582 && document.documentElement.clientWidth != 0) { 583 return document.documentElement['client' + d]; 584 } 585 }; 586 587 // public static functions 588 return { 589 addStyle: function (s, mediaTypes, process) { 590 var el; 591 var styleElId = 'css-mediaqueries-js'; 592 var styleMedia = ''; 593 594 var styleEl = document.getElementById(styleElId); 595 596 if (mediaTypes && mediaTypes.length > 0) { 597 styleMedia = mediaTypes.join(','); 598 styleElId += styleMedia; 599 } 600 601 if (null !== styleEl) { 602 el = styleEl; 603 } 604 else { 605 el = document.createElement('style'); 606 el.setAttribute('type', 'text/css'); 607 el.setAttribute('id', styleElId); 608 el.setAttribute('media', styleMedia); 609 document.getElementsByTagName('head')[0].appendChild(el); 610 } 611 612 if (el.styleSheet) { // IE 613 el.styleSheet.cssText += s; 614 } 615 else { 616 el.appendChild(document.createTextNode(s)); 617 } 618 619 el.addedWithCssHelper = true; 620 621 if (typeof process === 'undefined' || process === true) { 622 cssHelper.parsed(function (parsed) { 623 var o = parseEmbedded(el, s); 624 for (var n in o) { 625 if (o.hasOwnProperty(n)) { 626 addToCollection(n, o[n]); 627 } 628 } 629 broadcast('newStyleParsed', el); 630 }); 631 } 632 else { 633 el.parsingDisallowed = true; 634 } 635 return el; 636 }, 637 638 removeStyle: function (el) { 639 if (el.parentNode) 640 return el.parentNode.removeChild(el); 641 }, 642 643 parsed: function (fn) { 644 if (parsing) { 645 wait(fn); 646 } 647 else { 648 if (typeof parsed !== 'undefined') { 649 if (typeof fn === 'function') { 650 fn(parsed); 651 } 652 } 653 else { 654 wait(fn); 655 parse(); 656 } 657 } 658 }, 659 660 stylesheets: function (fn) { 661 cssHelper.parsed(function (parsed) { 662 fn(collections.stylesheets || collect('stylesheets')); 663 }); 664 }, 665 666 mediaQueryLists: function (fn) { 667 cssHelper.parsed(function (parsed) { 668 fn(collections.mediaQueryLists || collect('mediaQueryLists')); 669 }); 670 }, 671 672 rules: function (fn) { 673 cssHelper.parsed(function (parsed) { 674 fn(collections.rules || collect('rules')); 675 }); 676 }, 677 678 selectors: function (fn) { 679 cssHelper.parsed(function (parsed) { 680 fn(collections.selectors || collect('selectors')); 681 }); 682 }, 683 684 declarations: function (fn) { 685 cssHelper.parsed(function (parsed) { 686 fn(collections.declarations || collect('declarations')); 687 }); 688 }, 689 690 properties: function (fn) { 691 cssHelper.parsed(function (parsed) { 692 fn(collections.properties || collect('properties')); 693 }); 694 }, 695 696 broadcast: broadcast, 697 698 addListener: function (n, fn) { // in case n is 'styleadd': added function is called everytime style is added and parsed 699 if (typeof fn === 'function') { 700 if (!events[n]) { 701 events[n] = { 702 listeners: [] 703 }; 704 } 705 events[n].listeners[events[n].listeners.length] = fn; 706 } 707 }, 708 709 removeListener: function (n, fn) { 710 if (typeof fn === 'function' && events[n]) { 711 var ls = events[n].listeners; 712 for (var i = 0; i < ls.length; i++) { 713 if (ls[i] === fn) { 714 ls.splice(i, 1); 715 i -= 1; 716 } 717 } 718 } 719 }, 720 721 getViewportWidth: function () { 722 return getViewportSize('Width'); 723 }, 724 725 getViewportHeight: function () { 726 return getViewportSize('Height'); 727 } 728 }; 729}(); 730 731 732 733// function to test and apply parsed media queries against browser capabilities 734domReady(function enableCssMediaQueries() { 735 var meter; 736 737 var regExp = { 738 LENGTH_UNIT: /[0-9]+(em|ex|px|in|cm|mm|pt|pc)$/, 739 RESOLUTION_UNIT: /[0-9]+(dpi|dpcm)$/, 740 ASPECT_RATIO: /^[0-9]+\/[0-9]+$/, 741 ABSOLUTE_VALUE: /^[0-9]*(\.[0-9]+)*$/ 742 }; 743 744 var styles = []; 745 746 var nativeSupport = function () { 747 // check support for media queries 748 var id = 'css3-mediaqueries-test'; 749 var el = document.createElement('div'); 750 el.id = id; 751 var style = cssHelper.addStyle('@media all and (width) { #' + id + 752 ' { width: 1px !important; } }', [], false); // false means don't parse this temp style 753 document.body.appendChild(el); 754 var ret = el.offsetWidth === 1; 755 style.parentNode.removeChild(style); 756 el.parentNode.removeChild(el); 757 nativeSupport = function () { 758 return ret; 759 }; 760 return ret; 761 }; 762 763 var createMeter = function () { // create measuring element 764 meter = document.createElement('div'); 765 meter.style.cssText = 'position:absolute;top:-9999em;left:-9999em;' + 766 'margin:0;border:none;padding:0;width:1em;font-size:1em;'; // cssText is needed for IE, works for the others 767 document.body.appendChild(meter); 768 // meter must have browser default font size of 16px 769 if (meter.offsetWidth !== 16) { 770 meter.style.fontSize = 16 / meter.offsetWidth + 'em'; 771 } 772 meter.style.width = ''; 773 }; 774 775 var measure = function (value) { 776 meter.style.width = value; 777 var amount = meter.offsetWidth; 778 meter.style.width = ''; 779 return amount; 780 }; 781 782 var testMediaFeature = function (feature, value) { 783 // non-testable features: monochrome|min-monochrome|max-monochrome|scan|grid 784 var l = feature.length; 785 var min = (feature.substring(0, 4) === 'min-'); 786 var max = (!min && feature.substring(0, 4) === 'max-'); 787 788 if (value !== null) { // determine value type and parse to usable amount 789 var valueType; 790 var amount; 791 if (regExp.LENGTH_UNIT.exec(value)) { 792 valueType = 'length'; 793 amount = measure(value); 794 } 795 else if (regExp.RESOLUTION_UNIT.exec(value)) { 796 valueType = 'resolution'; 797 amount = parseInt(value, 10); 798 var unit = value.substring((amount + '').length); 799 } 800 else if (regExp.ASPECT_RATIO.exec(value)) { 801 valueType = 'aspect-ratio'; 802 amount = value.split('/'); 803 } 804 else if (regExp.ABSOLUTE_VALUE) { 805 valueType = 'absolute'; 806 amount = value; 807 } 808 else { 809 valueType = 'unknown'; 810 } 811 } 812 813 var width, height; 814 if ('device-width' === feature.substring(l - 12, l)) { // screen width 815 width = screen.width; 816 if (value !== null) { 817 if (valueType === 'length') { 818 return ((min && width >= amount) || (max && width < amount) || (!min && !max && width === amount)); 819 } 820 else { 821 return false; 822 } 823 } 824 else { // test width without value 825 return width > 0; 826 } 827 } 828 else if ('device-height' === feature.substring(l - 13, l)) { // screen height 829 height = screen.height; 830 if (value !== null) { 831 if (valueType === 'length') { 832 return ((min && height >= amount) || (max && height < amount) || (!min && !max && height === amount)); 833 } 834 else { 835 return false; 836 } 837 } 838 else { // test height without value 839 return height > 0; 840 } 841 } 842 else if ('width' === feature.substring(l - 5, l)) { // viewport width 843 width = document.documentElement.clientWidth || document.body.clientWidth; // the latter for IE quirks mode 844 if (value !== null) { 845 if (valueType === 'length') { 846 return ((min && width >= amount) || (max && width < amount) || (!min && !max && width === amount)); 847 } 848 else { 849 return false; 850 } 851 } 852 else { // test width without value 853 return width > 0; 854 } 855 } 856 else if ('height' === feature.substring(l - 6, l)) { // viewport height 857 height = document.documentElement.clientHeight || document.body.clientHeight; // the latter for IE quirks mode 858 if (value !== null) { 859 if (valueType === 'length') { 860 return ((min && height >= amount) || (max && height < amount) || (!min && !max && height === amount)); 861 } 862 else { 863 return false; 864 } 865 } 866 else { // test height without value 867 return height > 0; 868 } 869 } 870 else if ('orientation' === feature.substring(l - 11, l)) { // orientation 871 872 width = document.documentElement.clientWidth || document.body.clientWidth; // the latter for IE quirks mode 873 height = document.documentElement.clientHeight || document.body.clientHeight; // the latter for IE quirks mode 874 875 if (valueType === 'absolute') { 876 return (amount === 'portrait') ? (width <= height) : (width > height); 877 } 878 else { 879 return false; 880 } 881 } 882 else if ('aspect-ratio' === feature.substring(l - 12, l)) { // window aspect ratio 883 width = document.documentElement.clientWidth || document.body.clientWidth; // the latter for IE quirks mode 884 height = document.documentElement.clientHeight || document.body.clientHeight; // the latter for IE quirks mode 885 886 var curRatio = width / height; 887 var ratio = amount[1] / amount[0]; 888 889 if (valueType === 'aspect-ratio') { 890 return ((min && curRatio >= ratio) || (max && curRatio < ratio) || (!min && !max && curRatio === ratio)); 891 } 892 else { 893 return false; 894 } 895 } 896 else if ('device-aspect-ratio' === feature.substring(l - 19, l)) { // screen aspect ratio 897 return valueType === 'aspect-ratio' && screen.width * amount[1] === screen.height * amount[0]; 898 } 899 else if ('color-index' === feature.substring(l - 11, l)) { // number of colors 900 var colors = Math.pow(2, screen.colorDepth); 901 if (value !== null) { 902 if (valueType === 'absolute') { 903 return ((min && colors >= amount) || (max && colors < amount) || (!min && !max && colors === amount)); 904 } 905 else { 906 return false; 907 } 908 } 909 else { // test height without value 910 return colors > 0; 911 } 912 } 913 else if ('color' === feature.substring(l - 5, l)) { // bits per color component 914 var color = screen.colorDepth; 915 if (value !== null) { 916 if (valueType === 'absolute') { 917 return ((min && color >= amount) || (max && color < amount) || (!min && !max && color === amount)); 918 } 919 else { 920 return false; 921 } 922 } 923 else { // test height without value 924 return color > 0; 925 } 926 } 927 else if ('resolution' === feature.substring(l - 10, l)) { 928 var res; 929 if (unit === 'dpcm') { 930 res = measure('1cm'); 931 } 932 else { 933 res = measure('1in'); 934 } 935 if (value !== null) { 936 if (valueType === 'resolution') { 937 return ((min && res >= amount) || (max && res < amount) || (!min && !max && res === amount)); 938 } 939 else { 940 return false; 941 } 942 } 943 else { // test height without value 944 return res > 0; 945 } 946 } 947 else { 948 return false; 949 } 950 }; 951 952 var testMediaQuery = function (mq) { 953 var test = mq.getValid(); 954 var expressions = mq.getExpressions(); 955 var l = expressions.length; 956 if (l > 0) { 957 for (var i = 0; i < l && test; i++) { 958 test = testMediaFeature(expressions[i].mediaFeature, expressions[i].value); 959 } 960 var not = mq.getNot(); 961 return (test && !not || not && !test); 962 } 963 return test; 964 }; 965 966 var testMediaQueryList = function (mql, ts) { 967 // ts is null or an array with any media type but 'all'. 968 var mqs = mql.getMediaQueries(); 969 var t = {}; 970 for (var i = 0; i < mqs.length; i++) { 971 var type = mqs[i].getMediaType(); 972 if (mqs[i].getExpressions().length === 0) { 973 continue; 974 // TODO: Browser check! Assuming old browsers do apply the bare media types, even in a list with media queries. 975 } 976 var typeAllowed = true; 977 if (type !== 'all' && ts && ts.length > 0) { 978 typeAllowed = false; 979 for (var j = 0; j < ts.length; j++) { 980 if (ts[j] === type) { 981 typeAllowed = true; 982 } 983 } 984 } 985 if (typeAllowed && testMediaQuery(mqs[i])) { 986 t[type] = true; 987 } 988 } 989 var s = [], c = 0; 990 for (var n in t) { 991 if (t.hasOwnProperty(n)) { 992 if (c > 0) { 993 s[c++] = ','; 994 } 995 s[c++] = n; 996 } 997 } 998 if (s.length > 0) { 999 styles[styles.length] = cssHelper.addStyle('@media ' + s.join('') + '{' + mql.getCssText() + '}', ts, false); 1000 } 1001 }; 1002 1003 var testMediaQueryLists = function (mqls, ts) { 1004 for (var i = 0; i < mqls.length; i++) { 1005 testMediaQueryList(mqls[i], ts); 1006 } 1007 }; 1008 1009 var testStylesheet = function (stsh) { 1010 var amqs = stsh.getAttrMediaQueries(); 1011 var allPassed = false; 1012 var t = {}; 1013 for (var i = 0; i < amqs.length; i++) { 1014 if (testMediaQuery(amqs[i])) { 1015 t[amqs[i].getMediaType()] = amqs[i].getExpressions().length > 0; 1016 } 1017 } 1018 var ts = [], tswe = []; 1019 for (var n in t) { 1020 if (t.hasOwnProperty(n)) { 1021 ts[ts.length] = n; 1022 if (t[n]) { 1023 tswe[tswe.length] = n 1024 } 1025 if (n === 'all') { 1026 allPassed = true; 1027 } 1028 } 1029 } 1030 if (tswe.length > 0) { // types with query expressions that passed the test 1031 styles[styles.length] = cssHelper.addStyle(stsh.getCssText(), tswe, false); 1032 } 1033 var mqls = stsh.getMediaQueryLists(); 1034 if (allPassed) { 1035 // If 'all' in media attribute passed the test, then test all @media types in linked CSS and create style with those types. 1036 testMediaQueryLists(mqls); 1037 } 1038 else { 1039 // Or else, test only media attribute types that passed the test and also 'all'. 1040 // For positive '@media all', create style with attribute types that passed their test. 1041 testMediaQueryLists(mqls, ts); 1042 } 1043 }; 1044 1045 var testStylesheets = function (stshs) { 1046 for (var i = 0; i < stshs.length; i++) { 1047 testStylesheet(stshs[i]); 1048 } 1049 if (ua.ie) { 1050 // force repaint in IE 1051 document.documentElement.style.display = 'block'; 1052 setTimeout(function () { 1053 document.documentElement.style.display = ''; 1054 }, 0); 1055 // delay broadcast somewhat for IE 1056 setTimeout(function () { 1057 cssHelper.broadcast('cssMediaQueriesTested'); 1058 }, 100); 1059 } 1060 else { 1061 cssHelper.broadcast('cssMediaQueriesTested'); 1062 } 1063 }; 1064 1065 var test = function () { 1066 for (var i = 0; i < styles.length; i++) { 1067 cssHelper.removeStyle(styles[i]); 1068 } 1069 styles = []; 1070 cssHelper.stylesheets(testStylesheets); 1071 }; 1072 1073 var scrollbarWidth = 0; 1074 var checkForResize = function () { 1075 var cvpw = cssHelper.getViewportWidth(); 1076 var cvph = cssHelper.getViewportHeight(); 1077 1078 // determine scrollbar width in IE, see resizeHandler 1079 if (ua.ie) { 1080 var el = document.createElement('div'); 1081 el.style.position = 'absolute'; 1082 el.style.top = '-9999em'; 1083 el.style.overflow = 'scroll'; 1084 document.body.appendChild(el); 1085 scrollbarWidth = el.offsetWidth - el.clientWidth; 1086 document.body.removeChild(el); 1087 } 1088 1089 var timer; 1090 var resizeHandler = function () { 1091 var vpw = cssHelper.getViewportWidth(); 1092 var vph = cssHelper.getViewportHeight(); 1093 // check whether vp size has really changed, because IE also triggers resize event when body size changes 1094 // 20px allowance to accomodate short appearance of scrollbars in IE in some cases 1095 if (Math.abs(vpw - cvpw) > scrollbarWidth || Math.abs(vph - cvph) > scrollbarWidth) { 1096 cvpw = vpw; 1097 cvph = vph; 1098 clearTimeout(timer); 1099 timer = setTimeout(function () { 1100 if (!nativeSupport()) { 1101 test(); 1102 } 1103 else { 1104 cssHelper.broadcast('cssMediaQueriesTested'); 1105 } 1106 }, 500); 1107 } 1108 }; 1109 1110 window.onresize = function () { 1111 var x = window.onresize || function () {}; // save original 1112 return function () { 1113 x(); 1114 resizeHandler(); 1115 }; 1116 }(); 1117 }; 1118 1119 // prevent jumping of layout by hiding everything before painting <body> 1120 var docEl = document.documentElement; 1121 docEl.style.marginLeft = '-32767px'; 1122 1123 // make sure it comes back after a while 1124 setTimeout(function () { 1125 docEl.style.marginLeft = ''; 1126 }, 5000); 1127 1128 return function () { 1129 if (!nativeSupport()) { // if browser doesn't support media queries 1130 cssHelper.addListener('newStyleParsed', function (el) { 1131 testStylesheet(el.cssHelperParsed.stylesheet); 1132 }); 1133 // return visibility after media queries are tested 1134 cssHelper.addListener('cssMediaQueriesTested', function () { 1135 // force repaint in IE by changing width 1136 if (ua.ie) { 1137 docEl.style.width = '1px'; 1138 } 1139 setTimeout(function () { 1140 docEl.style.width = ''; // undo width 1141 docEl.style.marginLeft = ''; // undo hide 1142 }, 0); 1143 // remove this listener to prevent following execution 1144 cssHelper.removeListener('cssMediaQueriesTested', arguments.callee); 1145 }); 1146 createMeter(); 1147 test(); 1148 } 1149 else { 1150 docEl.style.marginLeft = ''; // undo visibility hidden 1151 } 1152 checkForResize(); 1153 }; 1154}()); 1155 1156
1157// bonus: hotfix for IE6 SP1 (bug KB823727) 1158try { 1159 document.execCommand('BackgroundImageCache', false, true); 1160} catch (e) {}
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.