Monday 15 December 2008

Is the DOM Female? or is the DOM not ready YET?

Sorry about the title but I couldn't help it! I am old and very un PC at times, I do try but sometimes (and this is one of them) my old 1970's self slips through.

This post and the last one came from an email I received asking for some advice. Not, I hastily add about how long it takes females to get ready (that is a subject for "The Troubled Geek" vidcasts) ;-) but testing for the DOM being ready before doing something. Notes comes with a built in event in FORMs and PAGEs that allows you to add code at that glorious moment when the browser has got everything it needs and is in a stable state. However this can be sluggish on some pages/forms depending on content.

Say you have a function called formInit() that runs when your form is loaded. The normal process would be to pop this in here










This is basically the same as
window.onload = function() {formInit};

Now that for most forms is hunky dory but sometimes there may be a period of thumb twiddling. This happens if the window has frames, iframes and/or Big or slow loading images
the good thing is that the DOM is ready long before all of this other stuff is finished and the window object returns "yes i am ready". Even better there is an alternate method to testing the window object which looks to see if the DOM is loaded and and not the more sluggardly window object.

As in most things there is a bit of xBrowser nonsense to work around.
In Mozilla browsers you can do it using the DOMContentLoaded keyword in place of an element in the addEventListener method.
if(document.addEventListener)
{
document.addEventListener("DOMContentLoaded", formInit, false)
}
Now IE is different as there is no direct way to detect the DOM being ready (Fecking redmond gnomes!) even all the way up to IE7. However there is a IE attribute of the "script" element that we can use in combination with the onreadystatechange event of an element. The attribute is called "defer" and this tells IE to defer the load of the JS until the DOM is ready. So we can have code like this.
if(document.all)
{
externalFile = document.createElement("script");
externalFile.setAttribute("type","text/javascript");
externalFile.setAttribute("id","amIReadyYet");
externalFile.setAttribute("defer","defer");
externalFile.setAttribute("src",javascript:void(0));
document.getElementsByTagName("head")[0].appendChild(externalFile);
var amIReadyYet = document.getElementById("amIReadyYet");
amIReadyYet.onreadystatechange = function() { if(this.readyState=="complete") {formInit()} }
}
OK! I know that is a lousy check for IE but i wanted to keep the code readable, please please please use a more robust method for checking for IE!
So what is this code doing?
I build a script object that effectively does nothing other than exist.
I insert it into the page with the defer attribute set to defer forcing it to load ONLY when the DOM is ready. I then set the onreadystatechange to test this element for readyness, when it is the DOM must be ready so I can run formInit()

That should allow you to make your window.onload run as efficently as possible particulary on BIG pages and forms that could take an age to load.

We all stand on the shoulders of giants and I first came across this solution with minor DYM tweaks from an article on Dean Edwards's blog back in 2005. I heartily recommend him! He ROCKS! (He hasn't posted since March 08 I do hope he is OK and continues to share his JS knowledge)

Disqus for Domi-No-Yes-Maybe