Simple Deferred DOM Access
One of the common Framework features that I like is the ability to defer the execution a Function until the DOM is stable. For example, YUI has the Function “YAHOO.util.Event.onDOMReady” which you can use in place of “window.onload”. Any Function passed to “onDOMReady” will be executed when the page HTML content has loaded, but before images and other binary data. This allows more or all of your initialization JavaScript to execute before the user feels the page has loaded.
I am mostly a standard purist and until recently, I have always put my JavaScript into the header of the page. Therefore, to reference HTMLElements by ID that were not yet loaded, I used “onDOMReady” religiously to initialize my scripts. However, after the release of YSlow, I did some research, realizing that it was more efficient and acceptable to include your JavaScript content as the last elements of the Body Tag. This mostly eliminated the need for deferred DOM loading.
However, while messing around with the Lazy Function Definition Pattern (which I had a lot of fun playing with this week), I realized a simple way to test if the DOM is ready. Consider the following:
var isDOMReady = function() { var bd = document.getElementsByTagName('body')[0]; if (! bd) { return false; } bd.appendChild(createElement('div')); isDOMReady = function() {return true;} } var checkDOM = function() { if (isDOMReady()) { alert('ready'); } else { setTimeout(checkDOM, 250); } } checkDOM();
The “checkDOM” Function is a runner thread that polls “isDOMReady”, until there is a Body Tag found using the “getElementsByTagName” method on the document. This returns the Body Tag only after the body has completly loaded. We use the Lazy Function Definition Pattern to overwrite the implementation of “isDOMReady” on the assumption that once the DOM is ready, it will always be ready, so no need to keep testing. “checkDOM” then fires an alert saying that the DOM is ready.
Obviously, this is only a semi-functional test example, but you get the idea. If you replace the alert with a CustomEvent, or another equivalent event system (that different Functions can subscribe to), then you would fire it now, completing your onDOMReady system.

Matt - nice post, but I think this particular technique has already been worked over and improved upon. See: http://peter.michaux.ca/article/3752 (among others). But you’re right: the onDOMReady functionality is certainly essential in all JS suites, even the most lightweight. And this particular one has the advantages of simplicity and universal compatibility, though you may find some “exposure” as DOM elements become visible before the onDOMReady event fires. In particular, this implementation of onDOMReady will not fire until: the complete HTML source is downloaded, parsed and rendered, and CSS styling is applied, which, depending on server latency, page size, and the user’s machine, may open a small window of exposure. You won’t have to wait for images to download, as you would with a pure window.onload solution, so this may be fine for most applications.
Comment by David Golightly — October 6, 2007 @ 9:36 am
You are right probably about the exposure period. I have not done slow connection testing to check this, but it makes sense. I am still searching for the JavaScript only method that has no exposure.
Comment by admin — October 6, 2007 @ 11:41 am