diff --git a/assets/js/adapt.js b/assets/js/adapt.js index f4f8372..06c117d 100644 --- a/assets/js/adapt.js +++ b/assets/js/adapt.js @@ -12,141 +12,221 @@ */ // Closure. -(function(w, d, config, undefined) { - // If no config, exit. - if (!config) { - return; - } - - // Empty vars to use later. - var url, url_old, timer; - - // Alias config values. - var callback = config.callback || function(){}; - var path = config.path ? config.path : ''; - var range = config.range; - var range_len = range.length; - - // Create empty link tag: - // - var css = d.createElement('link'); - css.rel = 'stylesheet'; - css.media = 'screen'; - - // Called from within adapt(). - function change(i, width) { - // Set the URL. - css.href = url; - url_old = url; - - // Fire callback. - callback(i, width); - } - - // Adapt to width. - function adapt() { - // This clearTimeout is for IE. - // Really it belongs in react(), - // but doesn't do any harm here. - clearTimeout(timer); - - // Parse viewport width. - var width = d.documentElement ? d.documentElement.clientWidth : 0; - - // While loop vars. - var arr, arr_0, val_1, val_2, is_range, file; - - // How many ranges? - var i = range_len; - var last = range_len - 1; - - // Start with blank URL. - url = undefined; - - while (i--) { - // Turn string into array. - arr = range[i].split('='); - - // Width is to the left of "=". - arr_0 = arr[0]; - - // File name is to the right of "=". - // Presuppoes a file with no spaces. - // If no file specified, make empty. - file = arr[1] ? arr[1].replace(/\s/g, '') : undefined; - - // Assume max if "to" isn't present. - is_range = arr_0.match('to'); - - // If it's a range, split left/right sides of "to", - // and then convert each one into numerical values. - // If it's not a range, turn maximum into a number. - val_1 = is_range ? parseInt(arr_0.split('to')[0], 10) : parseInt(arr_0, 10); - val_2 = is_range ? parseInt(arr_0.split('to')[1], 10) : undefined; - - // Check for maxiumum or range. - if ((!val_2 && i === last && width > val_1) || (width > val_1 && width <= val_2)) { - // Build full URL to CSS file. - file && (url = path + file); - - // Exit the while loop. No need to continue - // if we've already found a matching range. - break; - } - } - - // Was it created yet? - if (!url_old) { - // Apply changes. - change(i, width); - - // If URL has been defined, add the CSS. - // Use faster document.head if possible. - url && (d.head || d.getElementsByTagName('head')[0]).appendChild(css); - } - else if (url_old !== url) { - // Apply changes. - change(i, width); - } - } - - // Fire off once. - adapt(); - - // Slight delay. - function react() { - // Clear the timer as window resize fires, - // so that it only calls adapt() when the - // user has finished resizing the window. - clearTimeout(timer); - - // Start the timer countdown. - timer = setTimeout(adapt, 16); - // -----------------------^^ - // Note: 15.6 milliseconds is lowest "safe" - // duration for setTimeout and setInterval. - // - // http://www.nczonline.net/blog/2011/12/14/timer-resolution-in-browsers - } - - // Do we want to watch for - // resize and device tilt? - if (config.dynamic) { - // Event listener for window resize, - // also triggered by phone rotation. - if (w.addEventListener) { - // Good browsers. - w.addEventListener('resize', react, false); - } - else if (w.attachEvent) { - // Legacy IE support. - w.attachEvent('onresize', react); - } - else { - // Old-school fallback. - w.onresize = react; - } - } - -// Pass in window, document, config, undefined. -})(this, this.document, ADAPT_CONFIG); \ No newline at end of file +(function (w, d, config, undefined) { + // If no config, exit. + if (!config) { + return; + } + + // Empty vars to use later. + var docHead, docBody, bodyClass, url, url_old, timer, css, css_old; + + // Alias config values. + var callback = config.callback || function () { }, + path = config.path ? config.path : '', + range = config.range, + range_len = range.length; + + function setupAdapt() { + d.removeEventListener( "DOMContentLoaded", setupAdapt ); + + // Cache and element reference + // Use faster document.head and document.body if possible. + docHead = (d.head || d.getElementsByTagName('head')[0]); + docBody = (d.body || d.getElementsByTagName('body')[0]); + bodyClass = ''; + + // Get existing link tag if cssId was provided + if (config.cssId) + css = d.getElementById(config.cssId); + + // Fire off once. + adapt(); + + // Clean up any preexisting body classes + var classesToRemove = []; + for (var i = 0; i < docBody.classList.length; i++) { + if( docBody.classList[i].charAt(0) == '_' && docBody.classList[i] != bodyClass ) + classesToRemove[classesToRemove.length] = docBody.classList[i]; + } + for (var i = 0; i < classesToRemove.length; i++) { + docBody.classList.remove(classesToRemove[i]); + } + + // Do we want to watch for + // resize and device tilt? + if (config.dynamic) { + // Event listener for window resize, + // also triggered by phone rotation. + if (w.addEventListener) { + // Good browsers. + w.addEventListener('resize', react, false); + } + else if (w.attachEvent) { + // Legacy IE support. + w.attachEvent('onresize', react); + } + else { + // Old-school fallback. + w.onresize = react; + } + } + } + + // Called from within adapt(). + function change(i, width, linkElement) { + // Set the URL. + linkElement.href = url; + url_old = url; + + linkElement.onload = function () { + // Remove old css + if(css_old) { + docHead.removeChild(css_old); + css_old = undefined; + } + // Fire callback. + callback(i, width); + }; + } + + // Adapt to width. + function adapt() { + // This clearTimeout is for IE. + // Really it belongs in react(), + // but doesn't do any harm here. + clearTimeout(timer); + + // Remove old css + if(css_old) { + docHead.removeChild(css_old); + css_old = undefined; + } + + // Parse viewport width. + var width = d.documentElement ? d.documentElement.clientWidth : 0; + + // While loop vars. + var arr, arr_0, val_1, val_2, is_range, file; + + // How many ranges? + var i = range_len; + var last = range_len - 1; + + // Start with blank URL. + url = undefined; + + while (i--) { + + // Find first occurance of "=". + equalPos = range[i].indexOf('='); + + // Width is to the left of "=". + arr_0 = range[i].substr(0, equalPos); + + // File name is to the right of "=". + // Presuppoes a file with no spaces. + // If no file specified, make empty. + file = range[i].substr(equalPos+1); + file = file ? file.replace(/\s/g, '') : undefined; + + // Assume max if "to" isn't present. + is_range = arr_0.match('to'); + + // If it's a range, split left/right sides of "to", + // and then convert each one into numerical values. + // If it's not a range, turn maximum into a number. + val_1 = is_range ? parseInt(arr_0.split('to')[0], 10) : parseInt(arr_0, 10); + val_2 = is_range ? parseInt(arr_0.split('to')[1], 10) : undefined; + + // Check for maxiumum or range. + if ((!val_2 && i === last && width > val_1) || (width > val_1 && width <= val_2)) { + // Build full URL to CSS file. + file && (url = path + file); + + // Exit the while loop. No need to continue + // if we've already found a matching range. + break; + } + } + + if (url) { + // Update css link tag, only if css url has changed + if(!url_old || url_old !== url) { + if (css) { + if(css.href !== url) { + // Create empty link tag: + // + var newCss = d.createElement('link'); + newCss.rel = 'stylesheet'; + newCss.media = css.media; + newCss.id = css.id; + // Apply changes. + change(i, width, newCss); + + // Prevent overflowing flash of content + css_old = css; + css_old.id += '_old'; //Prevent duplicate IDs + + // Preserve css load order with graceful content stepping + if(css.nextSibling) + docHead.insertBefore(newCss, css.nextSibling); + else + docHead.appendChild(newCss); + css = newCss; + } else { + // Fire callback even if css link element wasn't changed. + url_old = url; + callback(i, width); + } + } else { + // Create empty link tag: + // + css = d.createElement('link'); + css.rel = 'stylesheet'; + css.media = 'screen'; + // Apply changes. + change(i, width, css); + + // Append css to end of head + docHead.appendChild(css); + } + } + + // Update css body class if it has changed + var newBodyClass = '_' + url.split('/').pop().split('.')[0]; + if( newBodyClass != bodyClass ) { + // Remove bodyClass + if (bodyClass.length && docBody.classList.contains(bodyClass)) + docBody.classList.remove(bodyClass); + bodyClass = newBodyClass; + // Add bodyClass + docBody.classList.add(bodyClass); + } + } + } + + // Slight delay. + function react() { + // Clear the timer as window resize fires, + // so that it only calls adapt() when the + // user has finished resizing the window. + clearTimeout(timer); + + // Start the timer countdown. + timer = setTimeout(adapt, 20); + // -----------------------^^ + // Note: 20 milliseconds is lowest "safe" + // duration for setTimeout and setInterval. + } + + // Setup adapt after DOM is loaded + if ( d.readyState === "complete" || + ( d.readyState !== "loading" && !d.documentElement.doScroll ) ) { + setupAdapt(); + } else { + d.addEventListener( "DOMContentLoaded", setupAdapt ); + } + + // Pass in window, document, config, undefined. +})(this, this.document, ADAPT_CONFIG); diff --git a/assets/js/adapt.min.js b/assets/js/adapt.min.js index 5e1eb82..88add8a 100644 --- a/assets/js/adapt.min.js +++ b/assets/js/adapt.min.js @@ -1 +1,9 @@ -!function(a,b,c,d){function m(a,b){l.href=e,f=e,h(a,b)}function n(){clearTimeout(g);var c,h,n,o,p,q,a=b.documentElement?b.documentElement.clientWidth:0,r=k,s=k-1;for(e=d;r--;)if(c=j[r].split("="),h=c[0],q=c[1]?c[1].replace(/\s/g,""):d,p=h.match("to"),n=p?parseInt(h.split("to")[0],10):parseInt(h,10),o=p?parseInt(h.split("to")[1],10):d,!o&&r===s&&a>n||a>n&&o>=a){q&&(e=i+q);break}f?f!==e&&m(r,a):(m(r,a),e&&(b.head||b.getElementsByTagName("head")[0]).appendChild(l))}function o(){clearTimeout(g),g=setTimeout(n,16)}if(c){var e,f,g,h=c.callback||function(){},i=c.path?c.path:"",j=c.range,k=j.length,l=b.createElement("link");l.rel="stylesheet",l.media="screen",n(),c.dynamic&&(a.addEventListener?a.addEventListener("resize",o,!1):a.attachEvent?a.attachEvent("onresize",o):a.onresize=o)}}(this,this.document,ADAPT_CONFIG); \ No newline at end of file +/* + Adapt.js licensed under GPL and MIT. + Read more here: http://adapt.960.gs + Version 2.0.2 +*/ +(function(m,c,a,q){function v(){c.removeEventListener("DOMContentLoaded",v);p=c.head||c.getElementsByTagName("head")[0];g=c.body||c.getElementsByTagName("body")[0];k="";a.cssId&&(b=c.getElementById(a.cssId));y();for(var d=[],e=0;ef||d>f&&d<=n){u&&(l=C+u);break}}l&&(r&&r===l||(b? +b.href!==l?(f=c.createElement("link"),f.rel="stylesheet",f.media=b.media,f.id=b.id,z(a,d,f),h=b,h.id+="_old",b.nextSibling?p.insertBefore(f,b.nextSibling):p.appendChild(f),b=f):(r=l,A(a,d)):(b=c.createElement("link"),b.rel="stylesheet",b.media="screen",z(a,d,b),p.appendChild(b))),d="_"+l.split("/").pop().split(".")[0],d!=k&&(k.length&&g.classList.contains(k)&&g.classList.remove(k),k=d,g.classList.add(k)))}function w(){clearTimeout(x);x=setTimeout(y,20)}if(a){var p,g,k,l,r,x,b,h,A=a.callback||function(){}, +C=a.path?a.path:"",t=a.range,B=t.length;"complete"===c.readyState||"loading"!==c.readyState&&!c.documentElement.doScroll?v():c.addEventListener("DOMContentLoaded",v)}})(this,this.document,ADAPT_CONFIG);