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);

Automated Data:URI CSS Sprites

Recently I found another interesting service: DURIS (Data URI Sprites). This is an automated solution for building Data:URI CSS Sprites for background images.

Basically you provide a page URL, then the service loads all styles of the page (both internal and external), finds all background images and encodes them into base64 (for data:URI format). As output, it provides a tar.gz file with HTML file and CSS files with encoded images in textual format.

The HTML contains the original pages with built-in code that checks browser version and plugs the styles with encoded images. There are several version of the styles for different browsers:

  • MHTML – for IE version < 8 (only IE8 supports data:URI )
  • data:URI – for all the other browsers
  • original styles – for the case when Javascript is disabled and for IE7 under Vista (there is a bug related to security issue with cached MHTML background images)

The advantages are:

  • all background images will be loaded in one HTTP request
  • it’s possible to quickly rebuild CSS sprites after making changes

This is a new tool that’s in beta stage so I would not use it in production.
The tool written in Java and the authors are going to opensource it as soon as release-candidate is ready.
(via Habr article in Russian)

I remind that besides Data:URI Sprites we have classic Image Sprites that involve joining images into another big image (opposite to base64 supposed by Data:URI). There are number of tools exist for Image Sprites and most advanced that I know is SmartSprites.

The advantage of Image Sprites over Data:URI Sprites is that it’s supported by almost all browsers including very old versions. The disadvantage is that Image Sprites composition cannot be fully automated and every time should be controlled by web developer.