markus / MarkusLogview / MARKUS_LOGVIEW / Scripts / respond.js @ 84578b97
이력 | 보기 | 이력해설 | 다운로드 (10.1 KB)
1 |
/* 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);
|