1/*! Respond.js v1.4.0: min/max-width media query polyfill. (c) Scott Jehl. MIT Lic. j.mp/respondjs */ 2(function( w ){ 3 4 "use strict"; 5 6 //exposed namespace 7 var respond = {}; 8 w.respond = respond; 9 10 //define update even in native-mq-supporting browsers, to avoid errors 11 respond.update = function(){}; 12 13 //define ajax obj 14 var requestQueue = [], 15 xmlHttp = (function() { 16 var xmlhttpmethod = false; 17 try { 18 xmlhttpmethod = new w.XMLHttpRequest(); 19 } 20 catch( e ){ 21 xmlhttpmethod = new w.ActiveXObject( "Microsoft.XMLHTTP" ); 22 } 23 return function(){ 24 return xmlhttpmethod; 25 }; 26 })(), 27 28 //tweaked Ajax functions from Quirksmode 29 ajax = function( url, callback ) { 30 var req = xmlHttp(); 31 if (!req){ 32 return; 33 } 34 req.open( "GET", url, true ); 35 req.onreadystatechange = function () { 36 if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){ 37 return; 38 } 39 callback( req.responseText ); 40 }; 41 if ( req.readyState === 4 ){ 42 return; 43 } 44 req.send( null ); 45 }; 46 47 //expose for testing 48 respond.ajax = ajax; 49 respond.queue = requestQueue; 50 51 // expose for testing 52 respond.regex = { 53 media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi, 54 keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi, 55 comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi, 56 urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, 57 findStyles: /@media *([^\{]+)\{([\S\s]+?)$/, 58 only: /(only\s+)?([a-zA-Z]+)\s?/, 59 minw: /\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/, 60 maxw: /\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ 61 }; 62 63 //expose media query support flag for external use 64 respond.mediaQueriesSupported = w.matchMedia && w.matchMedia( "only all" ) !== null && w.matchMedia( "only all" ).matches; 65 66 //if media queries are supported, exit here 67 if( respond.mediaQueriesSupported ){ 68 return; 69 } 70 71 //define vars 72 var doc = w.document, 73 docElem = doc.documentElement, 74 mediastyles = [], 75 rules = [], 76 appendedEls = [], 77 parsedSheets = {}, 78 resizeThrottle = 30, 79 head = doc.getElementsByTagName( "head" )[0] || docElem, 80 base = doc.getElementsByTagName( "base" )[0], 81 links = head.getElementsByTagName( "link" ), 82 83 lastCall, 84 resizeDefer, 85 86 //cached container for 1em value, populated the first time it's needed 87 eminpx, 88 89 // returns the value of 1em in pixels 90 getEmValue = function() { 91 var ret, 92 div = doc.createElement('div'), 93 body = doc.body, 94 originalHTMLFontSize = docElem.style.fontSize, 95 originalBodyFontSize = body && body.style.fontSize, 96 fakeUsed = false; 97 98 div.style.cssText = "position:absolute;font-size:1em;width:1em"; 99 100 if( !body ){ 101 body = fakeUsed = doc.createElement( "body" ); 102 body.style.background = "none"; 103 } 104 105 // 1em in a media query is the value of the default font size of the browser 106 // reset docElem and body to ensure the correct value is returned 107 docElem.style.fontSize = "100%"; 108 body.style.fontSize = "100%"; 109 110 body.appendChild( div ); 111 112 if( fakeUsed ){ 113 docElem.insertBefore( body, docElem.firstChild ); 114 } 115 116 ret = div.offsetWidth; 117 118 if( fakeUsed ){ 119 docElem.removeChild( body ); 120 } 121 else { 122 body.removeChild( div ); 123 } 124 125 // restore the original values 126 docElem.style.fontSize = originalHTMLFontSize; 127 if( originalBodyFontSize ) { 128 body.style.fontSize = originalBodyFontSize; 129 } 130 131 132 //also update eminpx before returning 133 ret = eminpx = parseFloat(ret); 134 135 return ret; 136 }, 137 138 //enable/disable styles 139 applyMedia = function( fromResize ){ 140 var name = "clientWidth", 141 docElemProp = docElem[ name ], 142 currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp, 143 styleBlocks = {}, 144 lastLink = links[ links.length-1 ], 145 now = (new Date()).getTime(); 146 147 //throttle resize calls 148 if( fromResize && lastCall && now - lastCall < resizeThrottle ){ 149 w.clearTimeout( resizeDefer ); 150 resizeDefer = w.setTimeout( applyMedia, resizeThrottle ); 151 return; 152 } 153 else {
154 lastCall = now; 155 } 156 157 for( var i in mediastyles ){ 158 if( mediastyles.hasOwnProperty( i ) ){ 159 var thisstyle = mediastyles[ i ], 160 min = thisstyle.minw, 161 max = thisstyle.maxw, 162 minnull = min === null, 163 maxnull = max === null, 164 em = "em"; 165 166 if( !!min ){ 167 min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 168 } 169 if( !!max ){ 170 max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 171 } 172 173 // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true 174 if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){ 175 if( !styleBlocks[ thisstyle.media ] ){ 176 styleBlocks[ thisstyle.media ] = []; 177 } 178 styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] ); 179 } 180 } 181 } 182 183 //remove any existing respond style element(s) 184 for( var j in appendedEls ){ 185 if( appendedEls.hasOwnProperty( j ) ){ 186 if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){ 187 head.removeChild( appendedEls[ j ] ); 188 } 189 } 190 } 191 appendedEls.length = 0; 192 193 //inject active styles, grouped by media type 194 for( var k in styleBlocks ){ 195 if( styleBlocks.hasOwnProperty( k ) ){ 196 var ss = doc.createElement( "style" ), 197 css = styleBlocks[ k ].join( "\n" ); 198 199 ss.type = "text/css"; 200 ss.media = k; 201 202 //originally, ss was appended to a documentFragment and sheets were appended in bulk. 203 //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one! 204 head.insertBefore( ss, lastLink.nextSibling ); 205 206 if ( ss.styleSheet ){ 207 ss.styleSheet.cssText = css; 208 } 209 else { 210 ss.appendChild( doc.createTextNode( css ) ); 211 } 212 213 //push to appendedEls to track for later removal 214 appendedEls.push( ss ); 215 } 216 } 217 }, 218 //find media blocks in css text, convert to style blocks 219 translate = function( styles, href, media ){ 220 var qs = styles.replace( respond.regex.comments, '' ) 221 .replace( respond.regex.keyframes, '' ) 222 .match( respond.regex.media ), 223 ql = qs && qs.length || 0; 224 225 //try to get CSS path 226 href = href.substring( 0, href.lastIndexOf( "/" ) ); 227 228 var repUrls = function( css ){ 229 return css.replace( respond.regex.urls, "$1" + href + "$2$3" ); 230 }, 231 useMedia = !ql && media; 232 233 //if path exists, tack on trailing slash 234 if( href.length ){ href += "/"; } 235 236 //if no internal queries exist, but media attr does, use that
237 //note: this currently lacks support for situations where a media attr is specified on a link AND 238 //its associated stylesheet has internal CSS media queries. 239 //In those cases, the media attribute will currently be ignored. 240 if( useMedia ){ 241 ql = 1; 242 } 243 244 for( var i = 0; i < ql; i++ ){ 245 var fullq, thisq, eachq, eql; 246 247 //media attr 248 if( useMedia ){ 249 fullq = media; 250 rules.push( repUrls( styles ) ); 251 } 252 //parse for styles 253 else{ 254 fullq = qs[ i ].match( respond.regex.findStyles ) && RegExp.$1; 255 rules.push( RegExp.$2 && repUrls( RegExp.$2 ) ); 256 } 257 258 eachq = fullq.split( "," ); 259 eql = eachq.length; 260 261 for( var j = 0; j < eql; j++ ){ 262 thisq = eachq[ j ]; 263 mediastyles.push( { 264 media : thisq.split( "(" )[ 0 ].match( respond.regex.only ) && RegExp.$2 || "all", 265 rules : rules.length - 1, 266 hasquery : thisq.indexOf("(") > -1, 267 minw : thisq.match( respond.regex.minw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ), 268 maxw : thisq.match( respond.regex.maxw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ) 269 } ); 270 } 271 } 272 273 applyMedia(); 274 }, 275 276 //recurse through request queue, get css text 277 makeRequests = function(){ 278 if( requestQueue.length ){ 279 var thisRequest = requestQueue.shift(); 280 281 ajax( thisRequest.href, function( styles ){ 282 translate( styles, thisRequest.href, thisRequest.media ); 283 parsedSheets[ thisRequest.href ] = true; 284 285 // by wrapping recursive function call in setTimeout 286 // we prevent "Stack overflow" error in IE7 287 w.setTimeout(function(){ makeRequests(); },0); 288 } ); 289 } 290 }, 291 292 //loop stylesheets, send text content to translate 293 ripCSS = function(){ 294 295 for( var i = 0; i < links.length; i++ ){ 296 var sheet = links[ i ], 297 href = sheet.href, 298 media = sheet.media, 299 isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 300 301 //only links plz and prevent re-parsing 302 if( !!href && isCSS && !parsedSheets[ href ] ){ 303 // selectivizr exposes css through the rawCssText expando 304 if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 305 translate( sheet.styleSheet.rawCssText, href, media ); 306 parsedSheets[ href ] = true; 307 } else { 308 if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) || 309 href.replace( RegExp.$1, "" ).split( "/" )[0] === w.location.host ){ 310 // IE7 doesn't handle urls that start with '//' for ajax request 311 // manually add in the protocol 312 if ( href.substring(0,2) === "//" ) { href = w.location.protocol + href; } 313 requestQueue.push( { 314 href: href, 315 media: media 316 } ); 317 } 318 } 319 } 320 } 321 makeRequests(); 322 }; 323 324 //translate CSS 325 ripCSS(); 326 327 //expose update for re-running respond later on 328 respond.update = ripCSS; 329 330 //expose getEmValue 331 respond.getEmValue = getEmValue; 332 333 //adjust on resize 334 function callMedia(){ 335 applyMedia( true ); 336 } 337 338 if( w.addEventListener ){ 339 w.addEventListener( "resize", callMedia, false ); 340 } 341 else if( w.attachEvent ){ 342 w.attachEvent( "onresize", callMedia ); 343 } 344})(this);
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.