1 /* NUGET: BEGIN LICENSE TEXT
3 * Microsoft grants you the right to use these script files for the sole
4 * purpose of either: (i) interacting through your browser with the Microsoft
5 * website or online service, subject to the applicable licensing or use
6 * terms; or (ii) using the files as included with a Microsoft product subject
7 * to that product's license terms. Microsoft reserves all other rights to the
8 * files not expressly granted by Microsoft, whether by implication, estoppel
9 * or otherwise. Insofar as a script file is dual licensed under GPL,
10 * Microsoft neither took the code under GPL nor distributes it thereunder but
11 * under the terms set out in this paragraph. All notices and licenses
12 * below are for informational purposes only.
14 * NUGET: END LICENSE TEXT */
15 /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
16 /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
17 window.matchMedia = window.matchMedia || (function(doc, undefined){
20 docElem = doc.documentElement,
21 refNode = docElem.firstElementChild || docElem.firstChild,
22 // fakeBody required for <FF4 when executed in <head>
23 fakeBody = doc.createElement('body'),
24 div = doc.createElement('div');
27 div.style.cssText = "position:absolute;top:-100em";
28 fakeBody.style.background = "none";
29 fakeBody.appendChild(div);
33 div.innerHTML = '­<style media="'+q+'"> #mq-test-1 { width: 42px; }</style>';
35 docElem.insertBefore(fakeBody, refNode);
36 bool = div.offsetWidth == 42;
37 docElem.removeChild(fakeBody);
39 return { matches: bool, media: q };
47 /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
52 //define update even in native-mq-supporting browsers, to avoid errors
53 respond.update = function(){};
55 //expose media query support flag for external use
56 respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches;
58 //if media queries are supported, exit here
59 if( respond.mediaQueriesSupported ){ return; }
62 var doc = win.document,
63 docElem = doc.documentElement,
69 head = doc.getElementsByTagName( "head" )[0] || docElem,
70 base = doc.getElementsByTagName( "base" )[0],
71 links = head.getElementsByTagName( "link" ),
74 //loop stylesheets, send text content to translate
80 sheet, href, media, isCSS;
86 isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
88 //only links plz and prevent re-parsing
89 if( !!href && isCSS && !parsedSheets[ href ] ){
90 // selectivizr exposes css through the rawCssText expando
91 if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
92 translate( sheet.styleSheet.rawCssText, href, media );
93 parsedSheets[ href ] = true;
95 if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base)
96 || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
108 //recurse through request queue, get css text
109 makeRequests = function(){
110 if( requestQueue.length ){
111 var thisRequest = requestQueue.shift();
113 ajax( thisRequest.href, function( styles ){
114 translate( styles, thisRequest.href, thisRequest.media );
115 parsedSheets[ thisRequest.href ] = true;
121 //find media blocks in css text, convert to style blocks
122 translate = function( styles, href, media ){
123 var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ),
124 ql = qs && qs.length || 0,
125 //try to get CSS path
126 href = href.substring( 0, href.lastIndexOf( "/" )),
127 repUrls = function( css ){
128 return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
130 useMedia = !ql && media,
133 j, fullq, thisq, eachq, eql;
135 //if path exists, tack on trailing slash
136 if( href.length ){ href += "/"; }
138 //if no internal queries exist, but media attr does, use that
139 //note: this currently lacks support for situations where a media attr is specified on a link AND
140 //its associated stylesheet has internal CSS media queries.
141 //In those cases, the media attribute will currently be ignored.
147 for( ; i < ql; i++ ){
153 rules.push( repUrls( styles ) );
157 fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
158 rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
161 eachq = fullq.split( "," );
164 for( ; j < eql; j++ ){
167 media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
168 rules : rules.length - 1,
169 hasquery: thisq.indexOf("(") > -1,
170 minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
171 maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
183 // returns the value of 1em in pixels
184 getEmValue = function() {
186 div = doc.createElement('div'),
190 div.style.cssText = "position:absolute;font-size:1em;width:1em";
193 body = fakeUsed = doc.createElement( "body" );
194 body.style.background = "none";
197 body.appendChild( div );
199 docElem.insertBefore( body, docElem.firstChild );
201 ret = div.offsetWidth;
204 docElem.removeChild( body );
207 body.removeChild( div );
210 //also update eminpx before returning
211 ret = eminpx = parseFloat(ret);
216 //cached container for 1em value, populated the first time it's needed
219 //enable/disable styles
220 applyMedia = function( fromResize ){
221 var name = "clientWidth",
222 docElemProp = docElem[ name ],
223 currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
225 lastLink = links[ links.length-1 ],
226 now = (new Date()).getTime();
228 //throttle resize calls
229 if( fromResize && lastCall && now - lastCall < resizeThrottle ){
230 clearTimeout( resizeDefer );
231 resizeDefer = setTimeout( applyMedia, resizeThrottle );
238 for( var i in mediastyles ){
239 var thisstyle = mediastyles[ i ],
240 min = thisstyle.minw,
241 max = thisstyle.maxw,
242 minnull = min === null,
243 maxnull = max === null,
247 min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
250 max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
253 // 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
254 if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
255 if( !styleBlocks[ thisstyle.media ] ){
256 styleBlocks[ thisstyle.media ] = [];
258 styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
262 //remove any existing respond style element(s)
263 for( var i in appendedEls ){
264 if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){
265 head.removeChild( appendedEls[ i ] );
269 //inject active styles, grouped by media type
270 for( var i in styleBlocks ){
271 var ss = doc.createElement( "style" ),
272 css = styleBlocks[ i ].join( "\n" );
274 ss.type = "text/css";
277 //originally, ss was appended to a documentFragment and sheets were appended in bulk.
278 //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!
279 head.insertBefore( ss, lastLink.nextSibling );
281 if ( ss.styleSheet ){
282 ss.styleSheet.cssText = css;
285 ss.appendChild( doc.createTextNode( css ) );
288 //push to appendedEls to track for later removal
289 appendedEls.push( ss );
292 //tweaked Ajax functions from Quirksmode
293 ajax = function( url, callback ) {
298 req.open( "GET", url, true );
299 req.onreadystatechange = function () {
300 if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){
303 callback( req.responseText );
305 if ( req.readyState == 4 ){
311 xmlHttp = (function() {
312 var xmlhttpmethod = false;
314 xmlhttpmethod = new XMLHttpRequest();
317 xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" );
320 return xmlhttpmethod;
327 //expose update for re-running respond later on
328 respond.update = ripCSS;
331 function callMedia(){
334 if( win.addEventListener ){
335 win.addEventListener( "resize", callMedia, false );
337 else if( win.attachEvent ){
338 win.attachEvent( "onresize", callMedia );