DOMContentLoaded: Test Cases and Musings
Over the past few weeks I’ve been exchanging e-mails with Bobby van der Sluis, discussing sIFR and UFO. Among the things discussed was DOMContentReady, or more specifically my implementation for Internet Explorer, which was based on the Dojo implementation. Dojo uses the following code:
if(dojo.render.html.ie && dojo.render.os.win){
document.attachEvent("onreadystatechange", function(e){
if(document.readyState == "complete"){
dj_load_init();
}
});
}
Whereas the “official” code is as follows:
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
init(); // call the onload handler
}
};
/*@end @*/
The difference may seem minor (readyState on a script instead of the document), but Dean Edwards mentioned in a comment on his site that document.readyState wouldn’t work properly. So, time for some test cases! First of all, domcontentloaded.html logs the following:
- Safari: changes to
document.readyState - Mozilla/Opera: firing of the
DOMContentLoadedevent - Internet Explorer: both techniques covered above
- All browsers: the loading of an image and
window.onload
Additionally, an external CSS file is loaded which gives the document a red background color. When the DOMContentLoaded event (or browser specific equivalent) fires, some CSS is written to the page which changes the background color to green. More on this later. The CSS file waits 5 seconds before returning data to the browser, the image waits 10 seconds.
It turns out that in Internet Explorer document.readyState fires after the loading of the image, and right before window.onload. In effect, it’s useless. The “official,” script.readyState variant does fire before the image loads, and is indeed the correct version. In the other browsers the official techniques work properly as well, and the background color of the page is green.
Safari & Style at the Opera
Now, what are we using that background color for? For sIFR it is incredibly important that all CSS has been loaded and applied before kicking into gear. It relies completely on the specified styles for the to-be-replaced elements, without it just won’t function properly. As said before, the first test case showed no surprises with the background color: it appears as if the stylesheets are applied in the correct order. In Safari and Opera, however, this turns out to be false. Enter readstyle-domcontentloaded.html. This test case is virtually the same as the one used before, however on the DOMContentLoaded event it logs the computed background color.
In Internet Explorer and Mozilla it reads out a red background color, in Safari however it reads rgba(0, 0, 0, 0) or transparent. There is also a Flash Of Unstyled Content. In Opera 9 the background color also reads as transparent, but without a FOUC. Webkit.org has an article by Dave Hyatt explaining the issue (as well as the FOUC):
(WebKit) will continue parsing a page even after a stylesheet directive has been encountered so that stylesheet and script loads can be parallelized (compared to waiting for the stylesheet to load - Mark Wubben). That way everything can be ready for display much earlier. (…) when a script attempts to access a property that involves having accurate layout/style information(, shipping Safari’s) will go ahead and lay out what it’s got even though it doesn’t have the stylesheet yet. It will also display it. This means you see FOUC whenever a script tries to access properties like scrollHeight or offsetWidth before the stylesheet has loaded. (…) we will (…) give back information that the page might consider to be incorrect, since the stylesheet that supplies the up-to-date information hasn’t loaded yet.
The article also discusses ways of solving this issue in WebKit itself. The suggested method is stalling the JavaScript execution when it tries to access a style dependent property. Unfortunately as of nightly r17760 this has not yet been implemented. This behaviour also highlights a need for something like a FinishedRendering event that would fire when the stylesheets referred to in the HTML have loaded and been applied. Right now the DOMContentLoaded movement relies quite heavily on this specific browser behaviour, if things change in Mozilla or Internet Explorer without implementing either a FinishedRendering event or stalling JavaScript execution — for backwards compatibility probably the better solution — many modern sites and applications will break.
In the mean time, no more DOMContentLoaded in sIFR for Safari and Opera.




Have you tried James Edwards’ domFunction for non-IE and non-Mozilla browsers? I use some of the code for non-IE and non-Mozilla browsers in my DOMContentLoaded Event for Browsers code and it does give me DOM ready events though I have to combine it with an onload event because sometimes the onload event fires before James’ domFunction event. I just don’t know if it will work in your case and run after the CSS has been applied.
Also, if you use the “official” code you will get a secure/non-secure error with https pages.
Tanny O'Haley | 28 November 2006, 23:12 | link
Hi Tanny. The latest sIFR nightlies use a revised version of the code on Dean Edwards’ site. More info can be found in the DOMContentLoaded.next article at Ajaxian.
Mark Wubben | 29 November 2006, 00:07 | link