Does setTimeout solve the DOMContentLoaded problem? | Comments (9)
Posted in Browsers, Code on 15th February 2008, 12:33 am by Stuart
I’ve recently been building a simple framework for testing the performance of arbitrary JavaScript code. Whilst doing so I was looking at the some information on setTimeout in “JavaScript the Definitive Guide” by David Flanagan.
One paragraph made me think of the DOMContentLoaded Problem:
“In practice,
setTimeout()tells the browser to invoke the function when it has finished running the event handlers for any currently pending events and has finished updated the current state of the document”
I thought to myself; what if you apply that to a situation where you don’t want to wait for window.onload to fire and use it as a way of emulating DOMContentLoaded.
So I remembered this today and set about creating a noddy little test to see if setTimeout would behave in the way that it sounded like it should do.
I found that setTimeout with a delay of zero milliseconds calls the function without waiting for other resources to finish loading on most modern browsers (IE6/7, firefox and Safari). The only fly in the ointment is Opera. However Opera (Like Mozilla) does have DOMContentLoaded, so it makes sense to use DOMContentLoaded for both Mozilla and Opera.
function DOMReady(f){
if (/(?!.*?compatible|.*?webkit)^mozilla|opera/i.test(navigator.userAgent)){ // Feeling dirty yet?
document.addEventListener("DOMContentLoaded", f, false);
}else{
window.setTimeout(f,0);
}
}
Try the demo and see what you think.
In Conclusion
setTimeout seems to be another possibility for working around the DOMContentLoaded issues. To be clear however, I’m not saying this is the most bombproof method and it certainly warrants further testing before being considered as a trusted solution.
Any thoughts and suggestions welcome.
Related Reading
- Further testing on this idea from Jonathan Snook
- The window.onload Problem – Solved!
- window.onload (again)
- DOMContentLoaded for IE, Safari, everything, without document.write
- IEContentLoaded

Nice implementation. I resorted to using setTimeout recently, to solve Safari inaccurately firing onload for iframes…
http://sonspring.com/journal/jquery-iframe-sizing
I did feel a bit dirty, but it got the job done. Glad to hear I’m not the only one who has tried it, with some measure of success.
I was originally going to respond to this as a comment but expanded on my thoughts in a blog post. Conclusion: this *may* work depending on the ability to rely on Gzip compression.
(crossposted at Snook)
Heh, this is something I’ve used before. Didn’t know it was that big of an issue; thought it was my IE flipping out once more…
@Jonathan: thanks for taking the time to put together your analysis. I think you’ve nailed it exactly and your thoughts around Gzipping certainly adds an interesting dimension to it cheers for taking it a step further.
[...] He then thought, does setTimeout solve the DOMContentLoaded problem?. [...]
Interesting approach; I’ve read of a few similar techniques (Hedger Wang and Dean Edwards of course, have spent time looking into the onload issue) – I suspect having a single timeout could be susceptible to timing issues, particularly over slower connections; my habit is to just throw a single script block at the very bottom of the document which calls an init() function. The key at that point is the whole DOM should have been parsed by the time that script block is executed. While less-than-ideal having an inline script block, it has been consistent across all browsers.
[...] He then thought, does setTimeout solve the DOMContentLoaded problem?. [...]
If you are looking for an alternative method to attach functionality earlier to a page look here:
http://javascript.nwbox.com/NWEvents/
The interesting part are the Delegates example. I know, no documentation yet but will do soon, since this is now well tested.
The code is published since mid 2007 under MIT license at:
http://nwevents.googlecode.com/
My syntax for that delegation task is:
NW.appendDelegate( selector, event_type, function, [delegate] );
Where:
selector – a full CSS3 selector string
event_type – the event type you whish to listen to
function – the user function handler
delegate – the delegate object (optional)
If the optional delegate object is passed in at the time of registration that element is used as the delegate, elsewhere the default “document.documentElement” is used to listen for that event type to bubble; at that time if the element match the selector the user function handler is executed.
This method is the all new method to avoid using an “onload” notification or similar “DOMReady” techniques.
It is a bit hard to grasp at first, but then you will realize we have always had the solution in front of us but we never saw it.
Diego Perini
I’ve been looking into this recently for a super-lightweight DOM library i’m working on.
My method is to use a self calling timer that tests for document.readyState being ‘interactive’ or ‘complete’ along with ‘document.activeElement’ (which seems to throws an error when DOM is not loaded) to determine if the DOM is ready to be interacted with.
I’ve not yet tested the technique on many browsers so i can’t be sure how compatible it is but it works fine in FF and IE 6+