JAVASCRIPT   159

respond.src.js

Guest on 24th July 2021 06:13:20 AM

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

Raw Paste


Login or Register to edit or fork this paste. It's free.