Permalink
Browse files

Issue 3: no more repetitive addClass() to cause multiple reflows

  • Loading branch information...
1 parent 65bfc75 commit f525d30352a96f02d6fb03e8e5791b2ba8eb3a29 @tipiirai tipiirai committed Dec 1, 2010
Showing with 62 additions and 42 deletions.
  1. +1 −1 head.min.js
  2. +31 −21 src/head.core.js
  3. +12 −7 src/head.detect.js
  4. +11 −9 src/head.loader.js
  5. +7 −4 test/index.html
View
2 head.min.js
@@ -4,4 +4,4 @@
copyright: "tipiirai" / Tero Piirainen
license: MIT
*/
-(function(a){var b=a.documentElement,c={screens:[320,480,640,768,1024,1280,1440,1680,1920],section:"-section",page:"-page",head:"head"};if(typeof window.head_conf=="object")for(var d in head_conf)c[d]=head_conf[d];window.head_conf=c;function e(a){b.className+=" "+a}function f(a){var c=new RegExp("\\b"+a+"\\b");b.className=b.className.replace(c,"")}function g(a,b){for(var c=0;c<a.length;c++)b.call(a,a[c],c)}var h=window[c.head]=function(){h.ready.apply(null,arguments)};h.feature=function(a,b){f("no-"+a),f(a),e((b?"":"no-")+a),h[a]=b;return h};var i=navigator.userAgent.toLowerCase();i=/(webkit)[ \/]([\w.]+)/.exec(i)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(i)||/(msie) ([\w.]+)/.exec(i)||!/compatible/.test(i)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(i)||[],i[1]=="msie"&&(i[1]="ie"),e(i[1]),h.browser={version:i[2]},h.browser[i[1]]=!0;if(h.browser.ie)for(var j=3;j<11;j++)parseFloat(i[2])<j&&e("lt-ie"+j);g("abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video".split("|"),function(b){a.createElement(b)});var k=location.pathname,l=k.split("/"),m=l.slice(0,l.length-1).join("-")||"root",n=l.slice(-1)[0]||"index",o=n.indexOf(".");o>=0&&(n=n.substring(0,o)),h.section=m,h.pageId=n,e(m+c.section),b.id=n+c.page;function p(){var a=document.width||window.outerWidth||document.documentElement.clientWidth;b.className=b.className.replace(/ (w|lt)-\d+/g,""),e("w-"+Math.round(a/100)*100),g(c.screens,function(b){a<=b&&e("lt-"+b)})}p(),window.onresize=p,head.feature("script",!0)})(document),function(a){var b=a.createElement("i"),c=b.style,d=" -o- -moz- -ms- -webkit- -khtml- ".split(" ");function e(a){c.cssText=d.join(a+";");var b=c.cssText?c.cssText.length:0;return b>0&&!c.cssText.split(";")[1]}var f={gradient:function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(#fff));",e="linear-gradient(left top,#eee,#fff);";c.cssText=(a+d.join(b+a)+d.join(e+a)).slice(0,-a.length);return c.backgroundImage},rgba:function(){c.cssText="background-color:rgba(0,0,0,0.5)";return c.backgroundColor},boxshadow:function(){return e("box-shadow: 0 0 0 red")},textshadow:function(){return c.textShadow===""},multiplebgs:function(){c.cssText="background:url(//:),url(//:),red url(//:)";return(new RegExp("(url\\s*\\(.*?){3}")).test(c.background)},borderimage:function(){return e("border-image: url(m.png) 1 1 stretch")},borderradius:function(){return e("border-radius:0")},opacity:function(){return e("opacity:.1")},reflections:function(){return e("box-reflect:right 0")},transforms:function(){return e("transform:rotate(1deg)")},transitions:function(){return e("transition:all .1s linear")}},g=window[head_conf.head];for(var h in f)g.feature(h,f[h].call())}(document),function(a){var b=!1,c=[],d=[],e={},f={},g=window.head_conf&&head_conf.head||"head",h=window[g]=window[g]||{};h.js=function(){var a=arguments,d=[].slice.call(a,1),e=d[0];if(!b)return c.push(function(){h.js.apply(null,a)});e?(k(e)||l.apply(null,d),n(i(a[0]),k(e)?e:function(){h.js.apply(null,d)})):n(i(a[0]));return h.js},h.ready=function(a,b){if(k(a))return d.push(a);var c=e[a];c?c.push[b]:c=e[a]=[b];return h.js};function i(a){var b=f[a.url||a];if(b)return b;if(typeof a=="object")for(var c in a)b={name:c,url:a[c]};else b={name:a.substring(a.indexOf("/",10)+1,a.indexOf("?")),url:a};f[b.url]=b;return b}function j(a,b){if(a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c<a.length;c++)b.call(a,a[c],c)}}function k(a){return Object.prototype.toString.call(a)=="[object Function]"}function l(){j(arguments,function(a){k(a)||m(i(a))})}function m(b,c){if(!b.state){b.state="preloading",b.onpreload=[];function d(){b.state="preloaded",j(b.onpreload,function(a){a.call()})}if(/Firefox/.test(navigator.userAgent)){var e=a.createElement("object");e.data=b.url,e.width=0,e.height=0,e.onload=function(){d(),setTimeout(function(){a.body.removeChild(e)},1)},a.body.appendChild(e)}else o({src:b.url,type:"cache"},d)}}function n(a,b){if(a.state=="loaded")return b();if(a.state=="preloading")return a.onpreload.push(function(){n(a,b)});a.state="loading",o(a.url,function(){a.state="loaded",b&&b.call(),j(e[a.name],function(a){a.call()});var c=!0;for(var g in f)f[g].state!="loaded"&&(c=!1);c&&j(d,function(a){a.done||a.call(),a.done=!0})})}function o(b,c){var d=a.getElementsByTagName("head")[0],e=a.createElement("script");e.type="text/"+(b.type||"javascript"),e.src=b.src||b,e.onreadystatechange=e.onload=function(){c.done||(c.call(),c.done=!0),document.all||d.removeChild(e)},d.appendChild(e)}setTimeout(function(){b=!0,j(c,function(a){a.call()})},50)}(document)
+(function(a){var b=a.documentElement,c={screens:[320,480,640,768,1024,1280,1440,1680,1920],section:"-section",page:"-page",head:"head"};if(typeof window.head_conf=="object")for(var d in head_conf)c[d]=head_conf[d];window.head_conf=c;function e(a){b.className+=" "+a}function f(a){var c=new RegExp("\\b"+a+"\\b");b.className=b.className.replace(c,"")}function g(a,b){for(var c=0;c<a.length;c++)b.call(a,a[c],c)}var h=window[c.head]=function(){h.ready.apply(null,arguments)};h.feature=function(a,b){f("no-"+a),f(a),e((b?"":"no-")+a),h[a]=b;return h};var i=navigator.userAgent.toLowerCase();i=/(webkit)[ \/]([\w.]+)/.exec(i)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(i)||/(msie) ([\w.]+)/.exec(i)||!/compatible/.test(i)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(i)||[],i[1]=="msie"&&(i[1]="ie"),e(i[1]),h.browser={version:i[2]},h.browser[i[1]]=!0;if(h.browser.ie)for(var j=3;j<11;j++)parseFloat(i[2])<j&&e("lt-ie"+j);g("abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video".split("|"),function(b){a.createElement(b)});var k=location.pathname,l=k.split("/"),m=l.slice(0,l.length-1).join("-")||"root",n=l.slice(-1)[0]||"index",o=n.indexOf(".");o>=0&&(n=n.substring(0,o)),h.section=m,h.pageId=n,e(m+c.section),b.id=n+c.page;function p(){var a=document.width||window.outerWidth||document.documentElement.clientWidth;b.className=b.className.replace(/ (w|lt)-\d+/g,""),e("w-"+Math.round(a/100)*100),g(c.screens,function(b){a<=b&&e("lt-"+b)})}p(),window.onresize=p,head.feature("script",!0)})(document),function(a){var b=a.createElement("i"),c=b.style,d=" -o- -moz- -ms- -webkit- -khtml- ".split(" ");function e(a){c.cssText=d.join(a+";");var b=c.cssText?c.cssText.length:0;return b>0&&!c.cssText.split(";")[1]}var f={gradient:function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(#fff));",e="linear-gradient(left top,#eee,#fff);";c.cssText=(a+d.join(b+a)+d.join(e+a)).slice(0,-a.length);return c.backgroundImage},rgba:function(){c.cssText="background-color:rgba(0,0,0,0.5)";return c.backgroundColor},boxshadow:function(){return e("box-shadow: 0 0 0 red")},textshadow:function(){return c.textShadow===""},multiplebgs:function(){c.cssText="background:url(//:),url(//:),red url(//:)";return(new RegExp("(url\\s*\\(.*?){3}")).test(c.background)},borderimage:function(){return e("border-image: url(m.png) 1 1 stretch")},borderradius:function(){return e("border-radius:0")},opacity:function(){return e("opacity:.1")},reflections:function(){return e("box-reflect:right 0")},transforms:function(){return e("transform:rotate(1deg)")},transitions:function(){return e("transition:all .1s linear")}},g=window[head_conf.head];for(var h in f)g.feature(h,f[h].call())}(document),function(a){var b=!1,c=[],d=[],e={},f={},g=window.head_conf&&head_conf.head||"head",h=window[g]=window[g]||{};h.js=function(){var a=arguments,d=[].slice.call(a,1),e=d[0];if(!b)return c.push(function(){h.js.apply(null,a)});e?(k(e)||l.apply(null,d),n(i(a[0]),k(e)?e:function(){h.js.apply(null,d)})):n(i(a[0]));return h.js},h.ready=function(a,b){if(k(a))return d.push(a);var c=e[a];c?c.push[b]:c=e[a]=[b];return h.js};function i(a){var b=f[a.url||a];if(b)return b;if(typeof a=="object")for(var c in a)b={name:c,url:a[c]};else b={name:a.substring(a.indexOf("/",10)+1,a.indexOf("?")),url:a};f[b.url]=b;return b}function j(a,b){if(a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c<a.length;c++)b.call(a,a[c],c)}}function k(a){return Object.prototype.toString.call(a)=="[object Function]"}function l(){j(arguments,function(a){k(a)||m(i(a))})}function m(b,c){if(!b.state){b.state="preloading",b.onpreload=[];function d(){b.state="preloaded",j(b.onpreload,function(a){a.call()})}if(/Firefox/.test(navigator.userAgent)){var e=a.createElement("object");e.data=b.url,e.width=0,e.height=0,e.onload=function(){d(),setTimeout(function(){a.body.removeChild(e)},1)},a.body.appendChild(e)}else o({src:b.url,type:"cache"},d)}}function n(a,b){if(a.state=="loaded")return b();if(a.state=="preloading")return a.onpreload.push(function(){n(a,b)});a.state="loading",o(a.url,function(){a.state="loaded",b&&b.call(),j(e[a.name],function(a){a.call()});var c=!0;for(var g in f)f[g].state!="loaded"&&(c=!1);c&&j(d,function(a){a.done||a.call(),a.done=!0})})}function o(b,c){var d=a.getElementsByTagName("head")[0],e=a.createElement("script");e.type="text/"+(b.type||"javascript"),e.src=b.src||b,e.onreadystatechange=e.onload=function(){c.done||(c.call(),c.done=!0),document.all||d.removeChild(e)},d.appendChild(e)}setTimeout(function(){b=!0,j(c,function(a){a.call()})},250)}(document)
View
52 src/head.core.js
@@ -1,18 +1,19 @@
/**
Head JS: The only script in your <HEAD>.
- copyright: "tipiirai" / Tero Piirainen
+ Copyright: "tipiirai" / Tero Piirainen
license: MIT
*/
(function(doc) {
var html = doc.documentElement,
- conf = {
+ conf = {
screens: [320, 480, 640, 768, 1024, 1280, 1440, 1680, 1920],
section: "-section",
page: "-page",
head: "head"
- };
+ },
+ klass = [];
if (typeof window.head_conf == 'object') {
for (var key in head_conf) {
@@ -22,13 +23,13 @@
window.head_conf = conf;
- function addClass(name) {
- html.className += ' ' + name;
+ function pushClass(name) {
+ klass.push(name);
}
function removeClass(name) {
var re = new RegExp("\\b" + name + "\\b");
- html.className = html.className.replace(re, '');
+ html.className = html.className.replace(re, '');
}
function each(arr, fn) {
@@ -41,10 +42,18 @@
api.ready.apply(null, arguments);
};
- api.feature = function(key, enabled) {
- removeClass('no-' + key);
- removeClass(key);
- addClass((enabled ? '' : 'no-') + key);
+ api.feature = function(key, enabled, queue) {
+
+ /*% internal %*/
+ if (!key) {
+ html.className += ' ' + klass.join( ' ' );
+ klass = [];
+ } else if (!queue) {
+ removeClass('no-' + key); removeClass(key);
+ }
+ /*% endinternal %*/
+
+ pushClass((enabled ? '' : 'no-') + key);
api[key] = !!enabled;
return api;
};
@@ -58,8 +67,8 @@
!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || [];
if (ua[1] == 'msie') ua[1] = 'ie';
- addClass(ua[1]);
- // addClass(ua[1] + ua[2].replace(/\./g, "").substring(0, 3));
+ pushClass(ua[1]);
+ // pushClass(ua[1] + ua[2].replace(/\./g, "").substring(0, 3));
api.browser = { version: ua[2] };
api.browser[ua[1]] = true;
@@ -69,7 +78,7 @@
// IE versions
for (var ver = 3; ver < 11; ver++) {
- if (parseFloat(ua[2]) < ver) { addClass("lt-ie" + ver); }
+ if (parseFloat(ua[2]) < ver) { pushClass("lt-ie" + ver); }
}
}
@@ -91,29 +100,30 @@
api.section = section;
api.pageId = pageId;
- addClass(section + conf.section);
+ pushClass(section + conf.section);
html.id = pageId + conf.page;
// screen resolution: w-100, lt-480, lt-1024 ...
function screenSize() {
var w = document.width || window.outerWidth || document.documentElement.clientWidth;
- // remove earlier screens
+ // remove earlier widths
html.className = html.className.replace(/ (w|lt)-\d+/g, "");
- addClass("w-" + Math.round(w / 100) * 100);
+
+ // add new ones
+ pushClass("w-" + Math.round(w / 100) * 100);
each(conf.screens, function(width) {
- if (w <= width) { addClass("lt-" + width); }
+ if (w <= width) { pushClass("lt-" + width); }
})
}
screenSize();
- window.onresize = screenSize;
-
- head.feature("script", true);
-
+ window.onresize = screenSize;
+ api.feature("script", true).feature();
+
})(document);
View
19 src/head.detect.js
@@ -17,10 +17,10 @@
https://github.com/Modernizr/Modernizr/blob/master/modernizr.js
*/
-(function(doc) {
+(function(api) {
/* CSS modernizer */
- var el = doc.createElement("i"),
+ var el = document.createElement("i"),
style = el.style,
prefs = ' -o- -moz- -ms- -webkit- -khtml- '.split(' ');
@@ -89,11 +89,16 @@
}
};
-
- var api = window[head_conf.head];
-
+
+ // queue features
for (var key in tests) {
- api.feature(key, tests[key].call());
+ api.feature(key, tests[key].call(), true);
}
-})(document);
+ // enable features at once
+ api.feature();
+
+
+})(window[head_conf.head]);
+
+
View
20 src/head.loader.js
@@ -6,7 +6,8 @@
*/
(function(doc) {
- var ready = false,
+ var head = doc.documentElement,
+ ready = false,
queue = [],
thelast = [], // functions to be executed last
waiters = {}, // functions waiting for scripts
@@ -138,10 +139,10 @@
onload();
// avoid spinning progress indicator with setTimeout
- setTimeout(function() { doc.body.removeChild(obj); }, 1);
+ setTimeout(function() { head.removeChild(obj); }, 1);
};
- doc.body.appendChild(obj);
+ head.appendChild(obj);
} else {
scriptTag({ src: script.url, type: 'cache'}, onload);
@@ -199,9 +200,7 @@
// if callback == true --> preload
function scriptTag(src, callback) {
- var head = doc.getElementsByTagName('head')[0],
- elem = doc.createElement('script');
-
+ var elem = doc.createElement('script');
elem.type = 'text/' + (src.type || 'javascript');
elem.src = src.src || src;
@@ -220,13 +219,16 @@
head.appendChild(elem);
}
- // DomContentLoaded no better
+ /*
+ This timer delays the start a little. All just become more robust.
+ Still a bit of a mystery. Will investigate report when all clear.
+ Not related to DomContentLoaded.
+ */
setTimeout(function() {
ready = true;
each(queue, function(fn) {
fn.call();
});
- }, 50);
-
+ }, 200);
})(document);
View
11 test/index.html
@@ -5,20 +5,23 @@
<!--[if IE]><script src="ie.js"></script><![endif]-->
<script>var head_conf = {screens: [100, 200, 2000], section: '-area', page: 'page'};</script>
- <script src="../head.min.js"></script>
+ <!-- <script src="../head.js"></script> -->
+
+ <link rel="stylesheet" type="text/css" href="http://192.168.0.102:2000/style.css?time=1"/>
- <!-- <script src="../src/head.core.js"></script>
+ <script src="../src/head.core.js"></script>
<script src="../src/head.detect.js"></script>
- <script src="../src/head.loader.js"></script> -->
- <link rel="stylesheet" type="text/css" href="http://192.168.0.102:2000/style.css?time=1"/>
+ <script src="../src/head.loader.js"></script>
</head>
<body>
+
<h2>headjs</h2>
<div id="info"></div>
+
<script>

0 comments on commit f525d30

Please sign in to comment.