PageSourceSearch

https://oh-naika.com/asset/respond.js

js oh-naika.com collected 2026-10-05 11:13:01 UTC 17,399 bytes, 410 lines download raw bytes

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

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.