-
-
Save getify/603980 to your computer and use it in GitHub Desktop.
// HOWTO: load LABjs itself dynamically! | |
// inline this code in your page to load LABjs itself dynamically, if you're so inclined. | |
(function (global, oDOC, handler) { | |
var head = oDOC.head || oDOC.getElementsByTagName("head"); | |
function LABjsLoaded() { | |
// do cool stuff with $LAB here | |
} | |
// loading code borrowed directly from LABjs itself | |
setTimeout(function () { | |
if ("item" in head) { // check if ref is still a live node list | |
if (!head[0]) { // append_to node not yet ready | |
setTimeout(arguments.callee, 25); | |
return; | |
} | |
head = head[0]; // reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists | |
} | |
var scriptElem = oDOC.createElement("script"), | |
scriptdone = false; | |
scriptElem.onload = scriptElem.onreadystatechange = function () { | |
if ((scriptElem.readyState && scriptElem.readyState !== "complete" && scriptElem.readyState !== "loaded") || scriptdone) { | |
return false; | |
} | |
scriptElem.onload = scriptElem.onreadystatechange = null; | |
scriptdone = true; | |
LABjsLoaded(); | |
}; | |
scriptElem.src = "/path/to/LAB.js"; | |
head.insertBefore(scriptElem, head.firstChild); | |
}, 0); | |
// required: shim for FF <= 3.5 not having document.readyState | |
if (oDOC.readyState == null && oDOC.addEventListener) { | |
oDOC.readyState = "loading"; | |
oDOC.addEventListener("DOMContentLoaded", handler = function () { | |
oDOC.removeEventListener("DOMContentLoaded", handler, false); | |
oDOC.readyState = "complete"; | |
}, false); | |
} | |
})(window, document); |
// compressed more suitable for inlining | |
// ~640b before gzip | |
(function(g,b,d){var c=b.head||b.getElementsByTagName("head"),D="readyState",E="onreadystatechange",F="DOMContentLoaded",G="addEventListener",H=setTimeout; | |
function f(){ | |
// $LAB stuff here | |
} | |
H(function(){if("item"in c){if(!c[0]){H(arguments.callee,25);return}c=c[0]}var a=b.createElement("script"),e=false;a.onload=a[E]=function(){if((a[D]&&a[D]!=="complete"&&a[D]!=="loaded")||e){return false}a.onload=a[E]=null;e=true;f()}; | |
a.src="/path/to/LAB.js"; | |
c.insertBefore(a,c.firstChild)},0);if(b[D]==null&&b[G]){b[D]="loading";b[G](F,d=function(){b.removeEventListener(F,d,false);b[D]="complete"},false)}})(this,document); |
Wouldnt it be possible to make this snippet smaller/simpler?
Say i define a function such as LABjsLoaded() using this type of code
var LABjsLoaded = function(){
// cool $lab stuff here
};
Then load LABjs using something smaller like google analytics style snippet
(function() {
var labjs = document.createElement('script');
lab.src = '/path/to/lab.js';
lab.setAttribute('async', 'true');
document.documentElement.firstChild.appendChild(lab);
})();
The only difference would be that the base labjs file does a LABjsLoaded() after loading. (205 bytes before gzip)
Would be nice if labjs itself looked for the existence of a particular function, if it exists, call it once labjs is ready.
@sajal-
I am not a fan of that pattern/suggestion:
-
it promotes having a global function not on the LABjs namespace, which is a bad practice to pollute the global namespace
-
it would hardwire that the name of the function had to be exactly something as manually specificed in the LABjs source code, which makes it brittle if someone can't define a global function with that name for whatever reason (conflicts, etc).
-
also, i still feel it's necessary to have the the
document.readyState
part of the snippet in there.
All in all, I think this snippet is pretty small as it is. And loading LAB.js itself dynamically is of questionable benefit anyway, because LAB.js is already itself so small, that a normal blocking script element load of it shouldn't cause any kind of noticeable delay.
Honestly, I recommend to people that instead of loading LABjs dynamically like this snippet does, instead to inline LABjs' source code into another file that they'd already be loading onto their page... For instance, on all my sites, what I do is have a single "load.js" file that I load at the bottom of the body, with a regular blocking script tag. Inside that "load.js" file, I have LABjs source code minified inline, and then I have my other page initialization code... for instance, I have my $LAB chains for what other scripts I want to load (like jQuery, etc). By having that all in one file, and loading it with a normal blocking script tag, it becomes basically like a "bootstrapper" for the page. As long as "load.js" stays decently small (<5-8k), it works pretty well.
@getify: aha come to think of it it does make sense now to use the regular <script> tag for labjs.
Ive already working on a mechanism to bundle all self owned js including labjs into a single file, and all 3rd party js is handled by $LAB . No reason to not use <script> ... nothing more to block anyways...
I was getting a little too carried over trying to over-optimize.
You probably mean: var head = oDOC.head || oDOC.getElementsByTagName("head")[0];
@tobie -- no, check lines 13-19 for how it does that
Yuck.
@tobie -- it's to address an older IE quirk/bug where the [0] element is not yet set, and if you capture a ref to it too early, when it's made available, your ref will be invalid.
Heh. Deserves a comment, don't you think?
I didn't realize that -- very interesting. Thanks again for the help!