We have now had, for a while, a way of emulating the “DOMContentLoaded”
event across all the main browsers. For those of you who don’t know what
I’m talking about, a web browser fires an event, “load”, when a page
finishes loading, and JavaScript can attach code to that event which
will then run once the page has loaded. However, if there are big images
or other slow-loading things in the page then the code gets delayed
until after they’ve finished loading too; this is annoying, because most
DOM scripting doesn’t actually need the images to be loaded, and so the
delay is unnecessary. Opera and Mozilla fire a “DOMContentLoaded” event
which runs after the page has loaded but before all the slow images
and applets and Flash movies need to load, which is perfect. IE and
Safari don’t fire such an event, but it’s been possible to do IE and
Safari-specific things to make it happen. (In Safari you check
document.readyState, in IE you document.write a <script> element
with defer set. See Dean’s writeup.) If you’re using a JavaScript
library of some sort (jQuery, Prototype, Mootools, whatever) then all
this complexity gets wrapped up for you and you don’t have to worry
about it, but if you’re writing stand-alone scripts (like my
sorttable), which don’t depend on a library, then this is more of a
problem; you have to include a big swathe of boilerplate code to emulate
the DOMContentLoaded event. Recently, Hedger Wang provided an alternative approach for IE that doesn’t rely on document.write,
which is rather neat. So, it should be possible to combine the existing
Safari method, Opera and Mozilla’s DOMContentLoaded support, and
Hedger’s IE approach into a short bit of boilerplate code that can be
dropped into your standalone script. And indeed it is. See a simple demo, and more importantly, here is the short version of the code:
(function(i) {var u =navigator.userAgent;var e=/*@cc_on!@*/false; var st =
setTimeout;if(/webkit/i.test(u)){st(function(){var dr=document.readyState;
if(dr=="loaded"||dr=="complete"){i()}else{st(arguments.callee,10);}},10);}
else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
document.addEventListener("DOMContentLoaded",i,false); } else if(e){ (
function(){var t=document.createElement('doc:rdy');try{t.doScroll('left');
i();t=null;}catch(e){st(arguments.callee,0);}})();}else{window.onload=i;}})(init);
The init on the last line is the name of your “init” function; the
one that you want to call on page load. (It could be an inline function
if required.) Simply copy those 7 lines into your standalone script and
change the name of the init function to be your init, and you’re good
to go on all browsers. Remember that if you’re already using a
JavaScript library then you don’t need this, but if you’re not then it’s
simpler than the current swathes of code, and less heavy than depending
on a library just to get access to cross-browser onload event handling.