markus / MarkusLogview / MARKUS_LOGVIEW / Scripts / respond.js @ 84578b97
이력 | 보기 | 이력해설 | 다운로드 (10.1 KB)
1 | 84578b97 | djkim | /* NUGET: BEGIN LICENSE TEXT
|
---|---|---|---|
2 | *
|
||
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.
|
||
13 | *
|
||
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){ |
||
18 | |||
19 | var bool,
|
||
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');
|
||
25 | |||
26 | div.id = 'mq-test-1';
|
||
27 | div.style.cssText = "position:absolute;top:-100em";
|
||
28 | fakeBody.style.background = "none";
|
||
29 | fakeBody.appendChild(div); |
||
30 | |||
31 | return function(q){ |
||
32 | |||
33 | div.innerHTML = '­<style media="'+q+'"> #mq-test-1 { width: 42px; }</style>'; |
||
34 | |||
35 | docElem.insertBefore(fakeBody, refNode); |
||
36 | bool = div.offsetWidth == 42;
|
||
37 | docElem.removeChild(fakeBody); |
||
38 | |||
39 | return { matches: bool, media: q }; |
||
40 | }; |
||
41 | |||
42 | })(document); |
||
43 | |||
44 | |||
45 | |||
46 | |||
47 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
|
||
48 | (function( win ){
|
||
49 | //exposed namespace
|
||
50 | win.respond = {}; |
||
51 | |||
52 | //define update even in native-mq-supporting browsers, to avoid errors
|
||
53 | respond.update = function(){}; |
||
54 | |||
55 | //expose media query support flag for external use
|
||
56 | respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches;
|
||
57 | |||
58 | //if media queries are supported, exit here
|
||
59 | if( respond.mediaQueriesSupported ){ return; } |
||
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 | var sheets = links,
|
||
77 | sl = sheets.length, |
||
78 | i = 0,
|
||
79 | //vars for loop:
|
||
80 | sheet, href, media, isCSS; |
||
81 | |||
82 | for( ; i < sl; i++ ){
|
||
83 | sheet = sheets[ i ], |
||
84 | href = sheet.href, |
||
85 | media = sheet.media, |
||
86 | isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
|
||
87 | |||
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;
|
||
94 | } else {
|
||
95 | if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) |
||
96 | || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){ |
||
97 | requestQueue.push( { |
||
98 | href: href,
|
||
99 | media: media
|
||
100 | } ); |
||
101 | } |
||
102 | } |
||
103 | } |
||
104 | } |
||
105 | makeRequests(); |
||
106 | }, |
||
107 | |||
108 | //recurse through request queue, get css text
|
||
109 | makeRequests = function(){ |
||
110 | if( requestQueue.length ){
|
||
111 | var thisRequest = requestQueue.shift();
|
||
112 | |||
113 | ajax( thisRequest.href, function( styles ){
|
||
114 | translate( styles, thisRequest.href, thisRequest.media ); |
||
115 | parsedSheets[ thisRequest.href ] = true;
|
||
116 | makeRequests(); |
||
117 | } ); |
||
118 | } |
||
119 | }, |
||
120 | |||
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" ); |
||
129 | }, |
||
130 | useMedia = !ql && media, |
||
131 | //vars used in loop
|
||
132 | i = 0,
|
||
133 | j, fullq, thisq, eachq, eql; |
||
134 | |||
135 | //if path exists, tack on trailing slash
|
||
136 | if( href.length ){ href += "/"; } |
||
137 | |||
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.
|
||
142 | if( useMedia ){
|
||
143 | ql = 1;
|
||
144 | } |
||
145 | |||
146 | |||
147 | for( ; i < ql; i++ ){
|
||
148 | j = 0;
|
||
149 | |||
150 | //media attr
|
||
151 | if( useMedia ){
|
||
152 | fullq = media; |
||
153 | rules.push( repUrls( styles ) ); |
||
154 | } |
||
155 | //parse for styles
|
||
156 | else{
|
||
157 | fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1; |
||
158 | rules.push( RegExp.$2 && repUrls( RegExp.$2 ) ); |
||
159 | } |
||
160 | |||
161 | eachq = fullq.split( "," );
|
||
162 | eql = eachq.length; |
||
163 | |||
164 | for( ; j < eql; j++ ){
|
||
165 | thisq = eachq[ j ]; |
||
166 | mediastyles.push( { |
||
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 || "" ) |
||
172 | } ); |
||
173 | } |
||
174 | } |
||
175 | |||
176 | applyMedia(); |
||
177 | }, |
||
178 | |||
179 | lastCall, |
||
180 | |||
181 | resizeDefer, |
||
182 | |||
183 | // returns the value of 1em in pixels
|
||
184 | getEmValue = function() { |
||
185 | var ret,
|
||
186 | div = doc.createElement('div'),
|
||
187 | body = doc.body, |
||
188 | fakeUsed = false;
|
||
189 | |||
190 | div.style.cssText = "position:absolute;font-size:1em;width:1em";
|
||
191 | |||
192 | if( !body ){
|
||
193 | body = fakeUsed = doc.createElement( "body" );
|
||
194 | body.style.background = "none";
|
||
195 | } |
||
196 | |||
197 | body.appendChild( div ); |
||
198 | |||
199 | docElem.insertBefore( body, docElem.firstChild ); |
||
200 | |||
201 | ret = div.offsetWidth; |
||
202 | |||
203 | if( fakeUsed ){
|
||
204 | docElem.removeChild( body ); |
||
205 | } |
||
206 | else {
|
||
207 | body.removeChild( div ); |
||
208 | } |
||
209 | |||
210 | //also update eminpx before returning
|
||
211 | ret = eminpx = parseFloat(ret); |
||
212 | |||
213 | return ret;
|
||
214 | }, |
||
215 | |||
216 | //cached container for 1em value, populated the first time it's needed
|
||
217 | eminpx, |
||
218 | |||
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,
|
||
224 | styleBlocks = {}, |
||
225 | lastLink = links[ links.length-1 ],
|
||
226 | now = (new Date()).getTime();
|
||
227 | |||
228 | //throttle resize calls
|
||
229 | if( fromResize && lastCall && now - lastCall < resizeThrottle ){
|
||
230 | clearTimeout( resizeDefer ); |
||
231 | resizeDefer = setTimeout( applyMedia, resizeThrottle ); |
||
232 | return;
|
||
233 | } |
||
234 | else {
|
||
235 | lastCall = now; |
||
236 | } |
||
237 | |||
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,
|
||
244 | em = "em";
|
||
245 | |||
246 | if( !!min ){
|
||
247 | min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); |
||
248 | } |
||
249 | if( !!max ){
|
||
250 | max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); |
||
251 | } |
||
252 | |||
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 ] = []; |
||
257 | } |
||
258 | styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] ); |
||
259 | } |
||
260 | } |
||
261 | |||
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 ] ); |
||
266 | } |
||
267 | } |
||
268 | |||
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" );
|
||
273 | |||
274 | ss.type = "text/css";
|
||
275 | ss.media = i; |
||
276 | |||
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 ); |
||
280 | |||
281 | if ( ss.styleSheet ){
|
||
282 | ss.styleSheet.cssText = css; |
||
283 | } |
||
284 | else {
|
||
285 | ss.appendChild( doc.createTextNode( css ) ); |
||
286 | } |
||
287 | |||
288 | //push to appendedEls to track for later removal
|
||
289 | appendedEls.push( ss ); |
||
290 | } |
||
291 | }, |
||
292 | //tweaked Ajax functions from Quirksmode
|
||
293 | ajax = function( url, callback ) { |
||
294 | var req = xmlHttp();
|
||
295 | if (!req){
|
||
296 | return;
|
||
297 | } |
||
298 | req.open( "GET", url, true ); |
||
299 | req.onreadystatechange = function () { |
||
300 | if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){ |
||
301 | return;
|
||
302 | } |
||
303 | callback( req.responseText ); |
||
304 | } |
||
305 | if ( req.readyState == 4 ){ |
||
306 | return;
|
||
307 | } |
||
308 | req.send( null );
|
||
309 | }, |
||
310 | //define ajax obj
|
||
311 | xmlHttp = (function() {
|
||
312 | var xmlhttpmethod = false; |
||
313 | try {
|
||
314 | xmlhttpmethod = new XMLHttpRequest();
|
||
315 | } |
||
316 | catch( e ){
|
||
317 | xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" ); |
||
318 | } |
||
319 | return function(){ |
||
320 | return xmlhttpmethod;
|
||
321 | }; |
||
322 | })(); |
||
323 | |||
324 | //translate CSS
|
||
325 | ripCSS(); |
||
326 | |||
327 | //expose update for re-running respond later on
|
||
328 | respond.update = ripCSS; |
||
329 | |||
330 | //adjust on resize
|
||
331 | function callMedia(){ |
||
332 | applyMedia( true );
|
||
333 | } |
||
334 | if( win.addEventListener ){
|
||
335 | win.addEventListener( "resize", callMedia, false ); |
||
336 | } |
||
337 | else if( win.attachEvent ){ |
||
338 | win.attachEvent( "onresize", callMedia );
|
||
339 | } |
||
340 | })(this); |