IE and DOMReady bug

Most famous method to catch DOMReady event in IE6/7 is utilizing script defer attribute:
/*@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 @*/

I’m developing a performance measurement tool and took this code to record time to DOMReady. Testing on a real site I’ve discovered that many records come with zero time to DOMReady. Filtering the records by browser I’ve got that only IE’s records were zero.
This zero time means that the event fired right after it was defined. This means that in practice on IE we could run the code bound to DOMReady before actually DOM Tree is ready.
There are similar issues described here.

After investigation I could reproduce it and found out that one of third-party advertisements caused the bug. It was inside IFRAME and it had alot of Javascript that was doing document.write() plugging next Javascript etc.

How to fix it?
There could be different solutions:

  • if possible, move the code to the bottom of the page instead of using DOMReady event
  • move the code into window.onload (execution will be delayed)
  • use another implementation of DOMReady for IE, there is solution that utilizes “doScroll()” method in order to check whether the content is ready yet

Note that it might be not so easy to find this bug. Your Javascript application that starts in DOMReady will work perfectly with your browser on your development server, but on production it may fail because of advertisements enabled and in worse scenario you’ll get geo-targeted advertisements and the bug will appear only for several countries.

How to catch it?
Measure the time in Javascript and send alert if the code runs right after event binding:

var page_start = new Date().getTime();
function bootstrap()
{
  if (0 == (new Date().getTime() - page_start))
    new Image().src="/developer_alert.php"; // send alert
...
...
}
bind_domready(bootstrap);