Muffinresearch Labs by Stuart Colville

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

Post Tools

Comments: Add yours

1. On February 15th, 2008 at 3:01 am Nathan Smith said:

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.

2. On February 15th, 2008 at 3:19 am Jonathan Snook said:

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.

3. On February 15th, 2008 at 8:59 am Bramus! said:

(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… :-D

4. On February 15th, 2008 at 10:44 am Stuart Colville said:

@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.

5. On February 15th, 2008 at 3:17 pm Ajax Girl » Blog Archive » Using setTimeout to Solve DOMContentLoaded? said:

[...] He then thought, does setTimeout solve the DOMContentLoaded problem?. [...]

6. On February 15th, 2008 at 5:22 pm Scott Schiller said:

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.

7. On February 15th, 2008 at 8:40 pm Javascript News » Blog Archive » Using setTimeout to Solve DOMContentLoaded? said:

[...] He then thought, does setTimeout solve the DOMContentLoaded problem?. [...]

8. On February 15th, 2008 at 9:09 pm Diego Perini said:

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

9. On August 19th, 2009 at 2:08 pm Keith Clark said:

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+







XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>



Using Loggerhead with mod_wsgi|(0)

Here’s a post I wrote over on the Project Fondue Blog about our use of Loggerhead with mod_wsgi under Apache. Loggerhead is the rather nice branch viewer for bazaar branches as used on Launchpad.net.

If you’re not already subscribed to the Project Fondue blog feed then I can recommend it, as there should be some interesting posts coming out of there in the coming months (yes I’m unashamedly biased!).

Ubuntu: Turn off changing workspace with mouse wheel|(1)

I found the changing with the workspace with the mouse wheel really annoying. To disable it go to System => Preferences => CompizConfig (available if the compizconfig-settings-manager package is installed) and uncheck “Viewport Switcher” which is under the “Desktop” heading.

Photos on Flickr

© Copyright 2004-10 Stuart Colville, all rights reserved. May contain traces of Muffin. Powered by WordPress. Hosting by Slicehost.com This page was baked in 0.692s.