diff --git a/README.md b/README.md
index 2cdc7c29..cb5254d0 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,15 @@ Usage Instructions
3. Crack open Internet Explorer and pump fists in delight
+Options
+======
+
+- Set `window.RESPOND_REPLACE_STYLES = true` before referencing this library to avoid altering the order of media queries in the CSS. NOTE: this is not as fast as the default, but still quick. See the notes below and #325.
+```html
+
+
+```
+
CDN/X-Domain Setup
======
@@ -69,6 +78,8 @@ Some notes to keep in mind:
- As you might guess, this implementation is quite dumb in regards to CSS parsing rules. This is a good thing, because that allows it to run really fast, but its looseness may also cause unexpected behavior. For example: if you enclose a whole media query in a comment intending to disable its rules, you'll probably find that those rules will end up enabled in non-media-query-supporting browsers.
+- Respond.js by default will change the order of media queries by moving them after the stylesheet they came from. This is the best performing method but does have a drawback: see #325. To fix that, but at a slight cost to performance, set `window.RESPOND_REPLACE_STYLES = true` before this script runs: each stylesheet is removed and replaced with a parsed `',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";if(a.matchMedia&&a.matchMedia("all").addListener)return!1;var b=a.matchMedia,c=b("only all").matches,d=!1,e=0,f=[],g=function(){a.clearTimeout(e),e=a.setTimeout(function(){for(var c=0,d=f.length;d>c;c++){var e=f[c].mql,g=f[c].listeners||[],h=b(e.media).matches;if(h!==e.matches){e.matches=h;for(var i=0,j=g.length;j>i;i++)g[i].call(a,e)}}},30)};a.matchMedia=function(e){var h=b(e),i=[],j=0;return h.addListener=function(b){c&&(d||(d=!0,a.addEventListener("resize",g,!0)),0===j&&(j=f.push({mql:h,listeners:i})),i.push(b))},h.removeListener=function(a){for(var b=0,c=i.length;c>b;b++)i[b]===a&&i.splice(b,1)},h}}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b #mq-test-1 { width: 42px; }',d.insertBefore(f,e),c=42===g.offsetWidth,d.removeChild(f),{matches:c,media:a}}}(a.document)}(this),function(a){"use strict";if(a.matchMedia&&a.matchMedia("all").addListener)return!1;var b=a.matchMedia,c=b("only all").matches,d=!1,e=0,f=[],g=function(c){a.clearTimeout(e),e=a.setTimeout(function(){for(var c=0,d=f.length;d>c;c++){var e=f[c].mql,g=f[c].listeners||[],h=b(e.media).matches;if(h!==e.matches){e.matches=h;for(var i=0,j=g.length;j>i;i++)g[i].call(a,e)}}},30)};a.matchMedia=function(e){var h=b(e),i=[],j=0;return h.addListener=function(b){c&&(d||(d=!0,a.addEventListener("resize",g,!0)),0===j&&(j=f.push({mql:h,listeners:i})),i.push(b))},h.removeListener=function(a){for(var b=0,c=i.length;c>b;b++)i[b]===a&&i.splice(b,1)},h}}(this),function(a){"use strict";function b(){x(!0)}a.RESPOND_REPLACE_STYLES=a.RESPOND_REPLACE_STYLES||!1;var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{(([^\{\}]*\{[^\}\{]*\})+)[^\}]*\}/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)\}$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p={},q=30,r=j.getElementsByTagName("head")[0]||k,s=j.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},v=function(a,b,c){var d="clientWidth",e=k[d],f="CSS1Compat"===j.compatMode&&e||j.body[d]||e,g=null===b,h=null===c,l="em";return b&&(b=parseFloat(b)*(b.indexOf(l)>-1?i||u():1)),c&&(c=parseFloat(c)*(c.indexOf(l)>-1?i||u():1)),!a||(!g||!h)&&(g||f>=b)&&(h||c>=f)},w=function(a,b,c,d){return a.substring(0,c)+b+a.substring(d)},x=function(b){var c,d=(new Date).getTime();return c=a.RESPOND_REPLACE_STYLES?z:A,b&&g&&q>d-g?(a.clearTimeout(h),void(h=a.setTimeout(c,q))):(g=d,void c())},y=function(){for(var a in n)n.hasOwnProperty(a)&&n[a]&&n[a].parentNode===r&&r.removeChild(n[a]);n.length=0},z=function(){t[t.length-1];y();for(var a in o)if(o.hasOwnProperty(a)){var b,c,d,e=o[a],f=e.styles,g=e.sheet,h=f,i={},j=[],k={};for(var l in e.mediastyles)e.mediastyles.hasOwnProperty(l)&&(b=e.mediastyles[l],c=b.minw,d=b.maxw,"all"===b.media?j.push(b):v(b.hasquery,c,d)&&(i[b.media]||(i[b.media]=[]),i[b.media].push(m[b.rules])));for(var n=j.length-1;n>=0;n--){b=j[n],c=b.minw,d=b.maxw;var p=m[b.rules],q=b.replaceIndexStart,s=b.replaceIndexEnd,u="";k[p]||(v(b.hasquery,c,d)&&(u=p),h=w(h,u,q,s),k[p]=!0)}B(h,"all",e.insertBefore),null!==g.parentElement&&r.removeChild(g);for(var x in i)i.hasOwnProperty(x)&&B(i[x].join("\n"),"all",e.insertBefore)}},A=function(){var a={},b=t[t.length-1];for(var c in l)if(l.hasOwnProperty(c)){var d=l[c],e=d.minw,f=d.maxw;v(d.hasquery,e,f)&&(a[d.media]||(a[d.media]=[]),a[d.media].push(m[d.rules]))}y();for(var g in a)a.hasOwnProperty(g)&&B(a[g].join("\n"),g,b.nextSibling)},B=function(a,b,c){var d=j.createElement("style");d.type="text/css",d.media=b,r.insertBefore(d,c),d.styleSheet?d.styleSheet.cssText=a:d.appendChild(j.createTextNode(a)),n.push(d)},C=function(a,b){return b=b.substring(0,b.lastIndexOf("/")),b.length&&(b+="/"),a.replace(c.regex.urls,"$1"+b+"$2$3")},D=function(b,d,e){a.RESPOND_REPLACE_STYLES&&(b=C(b,d),o[d].styles=b,o[d].mediastyles=[]);var f=b.replace(c.regex.keyframes,"").match(c.regex.media),g=f&&f.length||0,h=!g&&e;h&&(g=1);for(var i=0;g>i;i++){var j,k,n,p,q;h?(j=e,q=b):(j=f[i].match(c.regex.findStyles)&&RegExp.$1,q=RegExp.$2),a.RESPOND_REPLACE_STYLES?m.push(q):m.push(q&&C(q,d)),n=j.split(","),p=n.length;for(var r=0;p>r;r++){k=n[r];var s={media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")};a.RESPOND_REPLACE_STYLES?(s.replaceIndexStart=o[d].styles.indexOf(f[i]),s.replaceIndexEnd=s.replaceIndexStart+f[i].length,o[d].mediastyles.push(s)):l.push(s)}}x()},E=function(){if(d.length){var b=d.shift();f(b.href,function(c){a.RESPOND_REPLACE_STYLES&&(o[b.href]={sheet:b.sheet,insertBefore:b.sheet.nextSibling,styles:c}),D(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){E()},0)})}},F=function(){for(var b=0;b -1 ? eminpx || getEmValue() : 1);
+ }
+ if (!!max) {
+ max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
+ }
+ return !hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max);
+ }, replaceStringBetween = function(source, replacement, start, end) {
+ return source.substring(0, start) + replacement + source.substring(end);
}, applyMedia = function(fromResize) {
- var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();
+ var method, now = new Date().getTime();
+ if (w.RESPOND_REPLACE_STYLES) {
+ method = applyMediaReplace;
+ } else {
+ method = applyMediaAppend;
+ }
if (fromResize && lastCall && now - lastCall < resizeThrottle) {
w.clearTimeout(resizeDefer);
- resizeDefer = w.setTimeout(applyMedia, resizeThrottle);
+ resizeDefer = w.setTimeout(method, resizeThrottle);
return;
} else {
lastCall = now;
}
- for (var i in mediastyles) {
- if (mediastyles.hasOwnProperty(i)) {
- var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em";
- if (!!min) {
- min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
+ method();
+ }, removeAppendEls = function() {
+ for (var j in appendedEls) {
+ if (appendedEls.hasOwnProperty(j)) {
+ if (appendedEls[j] && appendedEls[j].parentNode === head) {
+ head.removeChild(appendedEls[j]);
+ }
+ }
+ }
+ appendedEls.length = 0;
+ }, applyMediaReplace = function() {
+ var lastLink = links[links.length - 1];
+ removeAppendEls();
+ for (var l in storedSheets) {
+ if (storedSheets.hasOwnProperty(l)) {
+ var stored = storedSheets[l], styles = stored.styles, sheet = stored.sheet, css = styles, styleBlocks = {}, styleBlocksAll = [], alreadyReplaced = {}, thisstyle, min, max;
+ for (var m in stored.mediastyles) {
+ if (stored.mediastyles.hasOwnProperty(m)) {
+ thisstyle = stored.mediastyles[m];
+ min = thisstyle.minw;
+ max = thisstyle.maxw;
+ if (thisstyle.media === "all") {
+ styleBlocksAll.push(thisstyle);
+ } else if (isRuleActive(thisstyle.hasquery, min, max)) {
+ if (!styleBlocks[thisstyle.media]) {
+ styleBlocks[thisstyle.media] = [];
+ }
+ styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
+ }
+ }
+ }
+ for (var n = styleBlocksAll.length - 1; n >= 0; n--) {
+ thisstyle = styleBlocksAll[n];
+ min = thisstyle.minw;
+ max = thisstyle.maxw;
+ var rule = rules[thisstyle.rules], start = thisstyle.replaceIndexStart, end = thisstyle.replaceIndexEnd, replacement = "";
+ if (alreadyReplaced[rule]) {
+ continue;
+ }
+ if (isRuleActive(thisstyle.hasquery, min, max)) {
+ replacement = rule;
+ }
+ css = replaceStringBetween(css, replacement, start, end);
+ alreadyReplaced[rule] = true;
}
- if (!!max) {
- max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
+ insertCss(css, "all", stored.insertBefore);
+ if (sheet.parentElement !== null) {
+ head.removeChild(sheet);
}
- if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {
- if (!styleBlocks[thisstyle.media]) {
- styleBlocks[thisstyle.media] = [];
+ for (var o in styleBlocks) {
+ if (styleBlocks.hasOwnProperty(o)) {
+ insertCss(styleBlocks[o].join("\n"), "all", stored.insertBefore);
}
- styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
}
}
}
- for (var j in appendedEls) {
- if (appendedEls.hasOwnProperty(j)) {
- if (appendedEls[j] && appendedEls[j].parentNode === head) {
- head.removeChild(appendedEls[j]);
+ }, applyMediaAppend = function() {
+ var styleBlocks = {}, lastLink = links[links.length - 1];
+ for (var i in mediastyles) {
+ if (mediastyles.hasOwnProperty(i)) {
+ var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw;
+ if (isRuleActive(thisstyle.hasquery, min, max)) {
+ if (!styleBlocks[thisstyle.media]) {
+ styleBlocks[thisstyle.media] = [];
+ }
+ styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
}
}
}
- appendedEls.length = 0;
+ removeAppendEls();
for (var k in styleBlocks) {
if (styleBlocks.hasOwnProperty(k)) {
- var ss = doc.createElement("style"), css = styleBlocks[k].join("\n");
- ss.type = "text/css";
- ss.media = k;
- head.insertBefore(ss, lastLink.nextSibling);
- if (ss.styleSheet) {
- ss.styleSheet.cssText = css;
- } else {
- ss.appendChild(doc.createTextNode(css));
- }
- appendedEls.push(ss);
+ insertCss(styleBlocks[k].join("\n"), k, lastLink.nextSibling);
}
}
- }, translate = function(styles, href, media) {
- var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0;
+ }, insertCss = function(css, media, insertBefore) {
+ var ss = doc.createElement("style");
+ ss.type = "text/css";
+ ss.media = media;
+ head.insertBefore(ss, insertBefore);
+ if (ss.styleSheet) {
+ ss.styleSheet.cssText = css;
+ } else {
+ ss.appendChild(doc.createTextNode(css));
+ }
+ appendedEls.push(ss);
+ }, replaceUrls = function(styles, href) {
href = href.substring(0, href.lastIndexOf("/"));
- var repUrls = function(css) {
- return css.replace(respond.regex.urls, "$1" + href + "$2$3");
- }, useMedia = !ql && media;
if (href.length) {
href += "/";
}
+ return styles.replace(respond.regex.urls, "$1" + href + "$2$3");
+ }, translate = function(styles, href, media) {
+ if (w.RESPOND_REPLACE_STYLES) {
+ styles = replaceUrls(styles, href);
+ storedSheets[href].styles = styles;
+ storedSheets[href].mediastyles = [];
+ }
+ var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0, useMedia = !ql && media;
if (useMedia) {
ql = 1;
}
for (var i = 0; i < ql; i++) {
- var fullq, thisq, eachq, eql;
+ var fullq, thisq, eachq, eql, rule;
if (useMedia) {
fullq = media;
- rules.push(repUrls(styles));
+ rule = styles;
} else {
fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;
- rules.push(RegExp.$2 && repUrls(RegExp.$2));
+ rule = RegExp.$2;
+ }
+ if (!w.RESPOND_REPLACE_STYLES) {
+ rules.push(rule && replaceUrls(rule, href));
+ } else {
+ rules.push(rule);
}
eachq = fullq.split(",");
eql = eachq.length;
for (var j = 0; j < eql; j++) {
thisq = eachq[j];
- mediastyles.push({
+ var thisstyle = {
media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all",
rules: rules.length - 1,
hasquery: thisq.indexOf("(") > -1,
minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""),
maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "")
- });
+ };
+ if (w.RESPOND_REPLACE_STYLES) {
+ thisstyle.replaceIndexStart = storedSheets[href].styles.indexOf(qs[i]);
+ thisstyle.replaceIndexEnd = thisstyle.replaceIndexStart + qs[i].length;
+ storedSheets[href].mediastyles.push(thisstyle);
+ } else {
+ mediastyles.push(thisstyle);
+ }
}
}
applyMedia();
@@ -230,6 +310,13 @@
if (requestQueue.length) {
var thisRequest = requestQueue.shift();
ajax(thisRequest.href, function(styles) {
+ if (w.RESPOND_REPLACE_STYLES) {
+ storedSheets[thisRequest.href] = {
+ sheet: thisRequest.sheet,
+ insertBefore: thisRequest.sheet.nextSibling,
+ styles: styles
+ };
+ }
translate(styles, thisRequest.href, thisRequest.media);
parsedSheets[thisRequest.href] = true;
w.setTimeout(function() {
@@ -242,6 +329,13 @@
var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
if (!!href && isCSS && !parsedSheets[href]) {
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
+ if (w.RESPOND_REPLACE_STYLES) {
+ storedSheets[href] = {
+ sheet: sheet,
+ insertBefore: sheet.nextSibling,
+ styles: sheet.styleSheet.rawCssText
+ };
+ }
translate(sheet.styleSheet.rawCssText, href, media);
parsedSheets[href] = true;
} else {
@@ -250,6 +344,7 @@
href = w.location.protocol + href;
}
requestQueue.push({
+ sheet: sheet,
href: href,
media: media
});
diff --git a/dest/respond.min.js b/dest/respond.min.js
index 80a7b69d..b8f848d5 100644
--- a/dest/respond.min.js
+++ b/dest/respond.min.js
@@ -1,5 +1,5 @@
-/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
+/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2015 Scott Jehl
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
* */
-!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b #mq-test-1 { width: 42px; }',d.insertBefore(f,e),c=42===g.offsetWidth,d.removeChild(f),{matches:c,media:a}}}(a.document)}(this),function(a){"use strict";function b(){x(!0)}a.RESPOND_REPLACE_STYLES=a.RESPOND_REPLACE_STYLES||!1;var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{(([^\{\}]*\{[^\}\{]*\})+)[^\}]*\}/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)\}$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p={},q=30,r=j.getElementsByTagName("head")[0]||k,s=j.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},v=function(a,b,c){var d="clientWidth",e=k[d],f="CSS1Compat"===j.compatMode&&e||j.body[d]||e,g=null===b,h=null===c,l="em";return b&&(b=parseFloat(b)*(b.indexOf(l)>-1?i||u():1)),c&&(c=parseFloat(c)*(c.indexOf(l)>-1?i||u():1)),!a||(!g||!h)&&(g||f>=b)&&(h||c>=f)},w=function(a,b,c,d){return a.substring(0,c)+b+a.substring(d)},x=function(b){var c,d=(new Date).getTime();return c=a.RESPOND_REPLACE_STYLES?z:A,b&&g&&q>d-g?(a.clearTimeout(h),void(h=a.setTimeout(c,q))):(g=d,void c())},y=function(){for(var a in n)n.hasOwnProperty(a)&&n[a]&&n[a].parentNode===r&&r.removeChild(n[a]);n.length=0},z=function(){t[t.length-1];y();for(var a in o)if(o.hasOwnProperty(a)){var b,c,d,e=o[a],f=e.styles,g=e.sheet,h=f,i={},j=[],k={};for(var l in e.mediastyles)e.mediastyles.hasOwnProperty(l)&&(b=e.mediastyles[l],c=b.minw,d=b.maxw,"all"===b.media?j.push(b):v(b.hasquery,c,d)&&(i[b.media]||(i[b.media]=[]),i[b.media].push(m[b.rules])));for(var n=j.length-1;n>=0;n--){b=j[n],c=b.minw,d=b.maxw;var p=m[b.rules],q=b.replaceIndexStart,s=b.replaceIndexEnd,u="";k[p]||(v(b.hasquery,c,d)&&(u=p),h=w(h,u,q,s),k[p]=!0)}B(h,"all",e.insertBefore),null!==g.parentElement&&r.removeChild(g);for(var x in i)i.hasOwnProperty(x)&&B(i[x].join("\n"),"all",e.insertBefore)}},A=function(){var a={},b=t[t.length-1];for(var c in l)if(l.hasOwnProperty(c)){var d=l[c],e=d.minw,f=d.maxw;v(d.hasquery,e,f)&&(a[d.media]||(a[d.media]=[]),a[d.media].push(m[d.rules]))}y();for(var g in a)a.hasOwnProperty(g)&&B(a[g].join("\n"),g,b.nextSibling)},B=function(a,b,c){var d=j.createElement("style");d.type="text/css",d.media=b,r.insertBefore(d,c),d.styleSheet?d.styleSheet.cssText=a:d.appendChild(j.createTextNode(a)),n.push(d)},C=function(a,b){return b=b.substring(0,b.lastIndexOf("/")),b.length&&(b+="/"),a.replace(c.regex.urls,"$1"+b+"$2$3")},D=function(b,d,e){a.RESPOND_REPLACE_STYLES&&(b=C(b,d),o[d].styles=b,o[d].mediastyles=[]);var f=b.replace(c.regex.keyframes,"").match(c.regex.media),g=f&&f.length||0,h=!g&&e;h&&(g=1);for(var i=0;g>i;i++){var j,k,n,p,q;h?(j=e,q=b):(j=f[i].match(c.regex.findStyles)&&RegExp.$1,q=RegExp.$2),a.RESPOND_REPLACE_STYLES?m.push(q):m.push(q&&C(q,d)),n=j.split(","),p=n.length;for(var r=0;p>r;r++){k=n[r];var s={media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")};a.RESPOND_REPLACE_STYLES?(s.replaceIndexStart=o[d].styles.indexOf(f[i]),s.replaceIndexEnd=s.replaceIndexStart+f[i].length,o[d].mediastyles.push(s)):l.push(s)}}x()},E=function(){if(d.length){var b=d.shift();f(b.href,function(c){a.RESPOND_REPLACE_STYLES&&(o[b.href]={sheet:b.sheet,insertBefore:b.sheet.nextSibling,styles:c}),D(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){E()},0)})}},F=function(){for(var b=0;b -1 ? eminpx || getEmValue() : 1);
+ }
+ if (!!max) {
+ max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
+ }
+ return !hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max);
+ }, replaceStringBetween = function(source, replacement, start, end) {
+ return source.substring(0, start) + replacement + source.substring(end);
}, applyMedia = function(fromResize) {
- var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();
+ var method, now = new Date().getTime();
+ if (w.RESPOND_REPLACE_STYLES) {
+ method = applyMediaReplace;
+ } else {
+ method = applyMediaAppend;
+ }
if (fromResize && lastCall && now - lastCall < resizeThrottle) {
w.clearTimeout(resizeDefer);
- resizeDefer = w.setTimeout(applyMedia, resizeThrottle);
+ resizeDefer = w.setTimeout(method, resizeThrottle);
return;
} else {
lastCall = now;
}
- for (var i in mediastyles) {
- if (mediastyles.hasOwnProperty(i)) {
- var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em";
- if (!!min) {
- min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
+ method();
+ }, removeAppendEls = function() {
+ for (var j in appendedEls) {
+ if (appendedEls.hasOwnProperty(j)) {
+ if (appendedEls[j] && appendedEls[j].parentNode === head) {
+ head.removeChild(appendedEls[j]);
}
- if (!!max) {
- max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
+ }
+ }
+ appendedEls.length = 0;
+ }, applyMediaReplace = function() {
+ var lastLink = links[links.length - 1];
+ removeAppendEls();
+ for (var l in storedSheets) {
+ if (storedSheets.hasOwnProperty(l)) {
+ var stored = storedSheets[l], styles = stored.styles, sheet = stored.sheet, css = styles, styleBlocks = {}, styleBlocksAll = [], alreadyReplaced = {}, thisstyle, min, max;
+ for (var m in stored.mediastyles) {
+ if (stored.mediastyles.hasOwnProperty(m)) {
+ thisstyle = stored.mediastyles[m];
+ min = thisstyle.minw;
+ max = thisstyle.maxw;
+ if (thisstyle.media === "all") {
+ styleBlocksAll.push(thisstyle);
+ } else if (isRuleActive(thisstyle.hasquery, min, max)) {
+ if (!styleBlocks[thisstyle.media]) {
+ styleBlocks[thisstyle.media] = [];
+ }
+ styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
+ }
+ }
}
- if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {
- if (!styleBlocks[thisstyle.media]) {
- styleBlocks[thisstyle.media] = [];
+ for (var n = styleBlocksAll.length - 1; n >= 0; n--) {
+ thisstyle = styleBlocksAll[n];
+ min = thisstyle.minw;
+ max = thisstyle.maxw;
+ var rule = rules[thisstyle.rules], start = thisstyle.replaceIndexStart, end = thisstyle.replaceIndexEnd, replacement = "";
+ if (alreadyReplaced[rule]) {
+ continue;
+ }
+ if (isRuleActive(thisstyle.hasquery, min, max)) {
+ replacement = rule;
+ }
+ css = replaceStringBetween(css, replacement, start, end);
+ alreadyReplaced[rule] = true;
+ }
+ insertCss(css, "all", stored.insertBefore);
+ if (sheet.parentElement !== null) {
+ head.removeChild(sheet);
+ }
+ for (var o in styleBlocks) {
+ if (styleBlocks.hasOwnProperty(o)) {
+ insertCss(styleBlocks[o].join("\n"), "all", stored.insertBefore);
}
- styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
}
}
}
- for (var j in appendedEls) {
- if (appendedEls.hasOwnProperty(j)) {
- if (appendedEls[j] && appendedEls[j].parentNode === head) {
- head.removeChild(appendedEls[j]);
+ }, applyMediaAppend = function() {
+ var styleBlocks = {}, lastLink = links[links.length - 1];
+ for (var i in mediastyles) {
+ if (mediastyles.hasOwnProperty(i)) {
+ var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw;
+ if (isRuleActive(thisstyle.hasquery, min, max)) {
+ if (!styleBlocks[thisstyle.media]) {
+ styleBlocks[thisstyle.media] = [];
+ }
+ styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
}
}
}
- appendedEls.length = 0;
+ removeAppendEls();
for (var k in styleBlocks) {
if (styleBlocks.hasOwnProperty(k)) {
- var ss = doc.createElement("style"), css = styleBlocks[k].join("\n");
- ss.type = "text/css";
- ss.media = k;
- head.insertBefore(ss, lastLink.nextSibling);
- if (ss.styleSheet) {
- ss.styleSheet.cssText = css;
- } else {
- ss.appendChild(doc.createTextNode(css));
- }
- appendedEls.push(ss);
+ insertCss(styleBlocks[k].join("\n"), k, lastLink.nextSibling);
}
}
- }, translate = function(styles, href, media) {
- var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0;
+ }, insertCss = function(css, media, insertBefore) {
+ var ss = doc.createElement("style");
+ ss.type = "text/css";
+ ss.media = media;
+ head.insertBefore(ss, insertBefore);
+ if (ss.styleSheet) {
+ ss.styleSheet.cssText = css;
+ } else {
+ ss.appendChild(doc.createTextNode(css));
+ }
+ appendedEls.push(ss);
+ }, replaceUrls = function(styles, href) {
href = href.substring(0, href.lastIndexOf("/"));
- var repUrls = function(css) {
- return css.replace(respond.regex.urls, "$1" + href + "$2$3");
- }, useMedia = !ql && media;
if (href.length) {
href += "/";
}
+ return styles.replace(respond.regex.urls, "$1" + href + "$2$3");
+ }, translate = function(styles, href, media) {
+ if (w.RESPOND_REPLACE_STYLES) {
+ styles = replaceUrls(styles, href);
+ storedSheets[href].styles = styles;
+ storedSheets[href].mediastyles = [];
+ }
+ var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0, useMedia = !ql && media;
if (useMedia) {
ql = 1;
}
for (var i = 0; i < ql; i++) {
- var fullq, thisq, eachq, eql;
+ var fullq, thisq, eachq, eql, rule;
if (useMedia) {
fullq = media;
- rules.push(repUrls(styles));
+ rule = styles;
} else {
fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;
- rules.push(RegExp.$2 && repUrls(RegExp.$2));
+ rule = RegExp.$2;
+ }
+ if (!w.RESPOND_REPLACE_STYLES) {
+ rules.push(rule && replaceUrls(rule, href));
+ } else {
+ rules.push(rule);
}
eachq = fullq.split(",");
eql = eachq.length;
for (var j = 0; j < eql; j++) {
thisq = eachq[j];
- mediastyles.push({
+ var thisstyle = {
media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all",
rules: rules.length - 1,
hasquery: thisq.indexOf("(") > -1,
minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""),
maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "")
- });
+ };
+ if (w.RESPOND_REPLACE_STYLES) {
+ thisstyle.replaceIndexStart = storedSheets[href].styles.indexOf(qs[i]);
+ thisstyle.replaceIndexEnd = thisstyle.replaceIndexStart + qs[i].length;
+ storedSheets[href].mediastyles.push(thisstyle);
+ } else {
+ mediastyles.push(thisstyle);
+ }
}
}
applyMedia();
@@ -181,6 +261,13 @@
if (requestQueue.length) {
var thisRequest = requestQueue.shift();
ajax(thisRequest.href, function(styles) {
+ if (w.RESPOND_REPLACE_STYLES) {
+ storedSheets[thisRequest.href] = {
+ sheet: thisRequest.sheet,
+ insertBefore: thisRequest.sheet.nextSibling,
+ styles: styles
+ };
+ }
translate(styles, thisRequest.href, thisRequest.media);
parsedSheets[thisRequest.href] = true;
w.setTimeout(function() {
@@ -193,6 +280,13 @@
var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
if (!!href && isCSS && !parsedSheets[href]) {
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
+ if (w.RESPOND_REPLACE_STYLES) {
+ storedSheets[href] = {
+ sheet: sheet,
+ insertBefore: sheet.nextSibling,
+ styles: sheet.styleSheet.rawCssText
+ };
+ }
translate(sheet.styleSheet.rawCssText, href, media);
parsedSheets[href] = true;
} else {
@@ -201,6 +295,7 @@
href = w.location.protocol + href;
}
requestQueue.push({
+ sheet: sheet,
href: href,
media: media
});
diff --git a/src/respond.js b/src/respond.js
index 7b77134f..6e7f4cfd 100644
--- a/src/respond.js
+++ b/src/respond.js
@@ -3,6 +3,9 @@
"use strict";
+ //when set to true, linked stylesheets will be replaced entirely with style elements for "all" media whilst other media are appended in individual styles, to ensure the cascade is not altered
+ w.RESPOND_REPLACE_STYLES = w.RESPOND_REPLACE_STYLES || false;
+
//exposed namespace
var respond = {};
w.respond = respond;
@@ -50,10 +53,10 @@
// expose for testing
respond.regex = {
- media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
+ media: /@media[^\{]+\{(([^\{\}]*\{[^\}\{]*\})+)[^\}]*\}/gi,
keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
- findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
+ findStyles: /@media *([^\{]+)\{([\S\s]+?)\}$/,
only: /(only\s+)?([a-zA-Z]+)\s?/,
minw: /\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,
maxw: /\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/
@@ -73,6 +76,7 @@
mediastyles = [],
rules = [],
appendedEls = [],
+ storedSheets = {},
parsedSheets = {},
resizeThrottle = 30,
head = doc.getElementsByTagName( "head" )[0] || docElem,
@@ -134,43 +138,154 @@
return ret;
},
- //enable/disable styles
- applyMedia = function( fromResize ){
+ isRuleActive = function( hasquery, min, max ){
var name = "clientWidth",
docElemProp = docElem[ name ],
currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
- styleBlocks = {},
- lastLink = links[ links.length-1 ],
+ minnull = min === null,
+ maxnull = max === null,
+ em = "em";
+
+ if( !!min ){
+ min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
+ }
+ if( !!max ){
+ max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
+ }
+
+ // 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
+ return !hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max );
+ },
+
+ replaceStringBetween = function( source, replacement, start, end ){
+ //replace the content between a start and end index
+ return source.substring( 0, start ) + replacement + source.substring( end );
+ },
+
+ applyMedia = function( fromResize ){
+ var method,
now = (new Date()).getTime();
+ if( w.RESPOND_REPLACE_STYLES ){
+ method = applyMediaReplace;
+ }
+ else{
+ method = applyMediaAppend;
+ }
+
//throttle resize calls
if( fromResize && lastCall && now - lastCall < resizeThrottle ){
w.clearTimeout( resizeDefer );
- resizeDefer = w.setTimeout( applyMedia, resizeThrottle );
+ resizeDefer = w.setTimeout( method, resizeThrottle );
return;
}
else {
lastCall = now;
}
+ method();
+ },
+
+ removeAppendEls = function(){
+ //remove any existing respond style element(s)
+ for( var j in appendedEls ){
+ if( appendedEls.hasOwnProperty( j ) ){
+ if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
+ head.removeChild( appendedEls[ j ] );
+ }
+ }
+ }
+ appendedEls.length = 0;
+ },
+
+ applyMediaReplace = function(){
+ var lastLink = links[ links.length-1 ];
+
+ removeAppendEls();
+
+ //inject active styles, replacing current stylesheet
+ for( var l in storedSheets ){
+ if( storedSheets.hasOwnProperty( l ) ){
+ var stored = storedSheets[ l ],
+ styles = stored.styles,
+ sheet = stored.sheet,
+ css = styles,
+ styleBlocks = {},
+ styleBlocksAll = [],
+ alreadyReplaced = {},
+ thisstyle, min, max;
+
+ for( var m in stored.mediastyles ){
+ if( stored.mediastyles.hasOwnProperty( m ) ){
+ thisstyle = stored.mediastyles[ m ];
+ min = thisstyle.minw;
+ max = thisstyle.maxw;
+
+ if( thisstyle.media === "all" ){
+ styleBlocksAll.push(thisstyle);
+ }
+ else if( isRuleActive( thisstyle.hasquery, min, max ) ){
+ //group by media type
+ if( !styleBlocks[ thisstyle.media ] ){
+ styleBlocks[ thisstyle.media ] = [];
+ }
+ styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
+ }
+ }
+ }
+
+ //replace active rules with @media stripped and remove inactive rules, in reverse order so replace index won't change
+ for( var n = styleBlocksAll.length - 1; n >= 0; n-- ){
+ thisstyle = styleBlocksAll[ n ];
+ min = thisstyle.minw;
+ max = thisstyle.maxw;
+ var rule = rules[ thisstyle.rules ],
+ start = thisstyle.replaceIndexStart,
+ end = thisstyle.replaceIndexEnd,
+ replacement = '';
+
+ if( alreadyReplaced[ rule ] ){
+ //this rule has already been applied for "all" media, we don't need to add it again for the other media queries it is under
+ continue;
+ }
+
+ if( isRuleActive( thisstyle.hasquery, min, max ) ){
+ replacement = rule;
+ }
+
+ css = replaceStringBetween( css, replacement, start, end );
+ alreadyReplaced[ rule ] = true;
+ }
+
+ insertCss( css, "all", stored.insertBefore );
+
+ //remove original stylesheet
+ if( sheet.parentElement !== null ){
+ head.removeChild( sheet );
+ }
+
+ //inject active styles, grouped by media type
+ for( var o in styleBlocks ){
+ if( styleBlocks.hasOwnProperty( o ) ){
+ insertCss( styleBlocks[ o ].join( "\n" ), "all", stored.insertBefore );
+ }
+ }
+ }
+ }
+ },
+
+ //enable/disable styles
+ applyMediaAppend = function(){
+ var styleBlocks = {},
+ lastLink = links[ links.length-1 ];
+
for( var i in mediastyles ){
if( mediastyles.hasOwnProperty( i ) ){
var thisstyle = mediastyles[ i ],
min = thisstyle.minw,
- max = thisstyle.maxw,
- minnull = min === null,
- maxnull = max === null,
- em = "em";
-
- if( !!min ){
- min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
- }
- if( !!max ){
- max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
- }
+ max = thisstyle.maxw;
- // 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
- if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
+ if( isRuleActive( thisstyle.hasquery, min, max ) ){
if( !styleBlocks[ thisstyle.media ] ){
styleBlocks[ thisstyle.media ] = [];
}
@@ -179,57 +294,59 @@
}
}
- //remove any existing respond style element(s)
- for( var j in appendedEls ){
- if( appendedEls.hasOwnProperty( j ) ){
- if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
- head.removeChild( appendedEls[ j ] );
- }
- }
- }
- appendedEls.length = 0;
+ removeAppendEls();
//inject active styles, grouped by media type
for( var k in styleBlocks ){
if( styleBlocks.hasOwnProperty( k ) ){
- var ss = doc.createElement( "style" ),
- css = styleBlocks[ k ].join( "\n" );
+ insertCss( styleBlocks[ k ].join( "\n" ), k, lastLink.nextSibling );
+ }
+ }
+ },
- ss.type = "text/css";
- ss.media = k;
+ insertCss = function( css, media, insertBefore ){
+ var ss = doc.createElement( "style" );
- //originally, ss was appended to a documentFragment and sheets were appended in bulk.
- //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!
- head.insertBefore( ss, lastLink.nextSibling );
+ ss.type = "text/css";
+ ss.media = media;
- if ( ss.styleSheet ){
- ss.styleSheet.cssText = css;
- }
- else {
- ss.appendChild( doc.createTextNode( css ) );
- }
+ //originally, ss was appended to a documentFragment and sheets were appended in bulk.
+ //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!
+ head.insertBefore( ss, insertBefore );
- //push to appendedEls to track for later removal
- appendedEls.push( ss );
- }
+ if ( ss.styleSheet ){
+ ss.styleSheet.cssText = css;
+ }
+ else {
+ ss.appendChild( doc.createTextNode( css ) );
}
+
+ //push to appendedEls to track for later removal
+ appendedEls.push( ss );
},
- //find media blocks in css text, convert to style blocks
- translate = function( styles, href, media ){
- var qs = styles.replace( respond.regex.keyframes, '' ).match( respond.regex.media ),
- ql = qs && qs.length || 0;
+ replaceUrls = function( styles, href ){
//try to get CSS path
href = href.substring( 0, href.lastIndexOf( "/" ) );
- var repUrls = function( css ){
- return css.replace( respond.regex.urls, "$1" + href + "$2$3" );
- },
- useMedia = !ql && media;
-
//if path exists, tack on trailing slash
if( href.length ){ href += "/"; }
+ return styles.replace( respond.regex.urls, "$1" + href + "$2$3" );
+ },
+
+ //find media blocks in css text, convert to style blocks
+ translate = function( styles, href, media ){
+ if( w.RESPOND_REPLACE_STYLES ){
+ styles = replaceUrls( styles, href );
+ storedSheets[ href ].styles = styles;
+ storedSheets[ href ].mediastyles = [];
+ }
+
+ var qs = styles.replace( respond.regex.keyframes, '' ).match( respond.regex.media ),
+ ql = qs && qs.length || 0,
+ useMedia = !ql && media;
+
//if no internal queries exist, but media attr does, use that
//note: this currently lacks support for situations where a media attr is specified on a link AND
//its associated stylesheet has internal CSS media queries.
@@ -239,17 +356,24 @@
}
for( var i = 0; i < ql; i++ ){
- var fullq, thisq, eachq, eql;
+ var fullq, thisq, eachq, eql, rule;
//media attr
if( useMedia ){
fullq = media;
- rules.push( repUrls( styles ) );
+ rule = styles;
}
//parse for styles
else{
fullq = qs[ i ].match( respond.regex.findStyles ) && RegExp.$1;
- rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
+ rule = RegExp.$2;
+ }
+
+ if( !w.RESPOND_REPLACE_STYLES ){
+ rules.push( rule && replaceUrls( rule, href ) );
+ }
+ else {
+ rules.push( rule );
}
eachq = fullq.split( "," );
@@ -257,13 +381,21 @@
for( var j = 0; j < eql; j++ ){
thisq = eachq[ j ];
- mediastyles.push( {
+ var thisstyle = {
media : thisq.split( "(" )[ 0 ].match( respond.regex.only ) && RegExp.$2 || "all",
rules : rules.length - 1,
hasquery : thisq.indexOf("(") > -1,
minw : thisq.match( respond.regex.minw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
maxw : thisq.match( respond.regex.maxw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
- } );
+ };
+ if( w.RESPOND_REPLACE_STYLES ){
+ thisstyle.replaceIndexStart = storedSheets[ href ].styles.indexOf( qs[ i ] );
+ thisstyle.replaceIndexEnd = thisstyle.replaceIndexStart + qs[ i ].length;
+ storedSheets[ href ].mediastyles.push( thisstyle );
+ }
+ else {
+ mediastyles.push( thisstyle );
+ }
}
}
@@ -276,6 +408,13 @@
var thisRequest = requestQueue.shift();
ajax( thisRequest.href, function( styles ){
+ if( w.RESPOND_REPLACE_STYLES ){
+ storedSheets[ thisRequest.href ] = {
+ sheet: thisRequest.sheet,
+ insertBefore: thisRequest.sheet.nextSibling,
+ styles: styles
+ };
+ }
translate( styles, thisRequest.href, thisRequest.media );
parsedSheets[ thisRequest.href ] = true;
@@ -299,6 +438,13 @@
if( !!href && isCSS && !parsedSheets[ href ] ){
// selectivizr exposes css through the rawCssText expando
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
+ if( w.RESPOND_REPLACE_STYLES ){
+ storedSheets[ href ] = {
+ sheet: sheet,
+ insertBefore: sheet.nextSibling,
+ styles: sheet.styleSheet.rawCssText
+ };
+ }
translate( sheet.styleSheet.rawCssText, href, media );
parsedSheets[ href ] = true;
} else {
@@ -308,6 +454,7 @@
// manually add in the protocol
if ( href.substring(0,2) === "//" ) { href = w.location.protocol + href; }
requestQueue.push( {
+ sheet: sheet,
href: href,
media: media
} );