20

I inherited this piece of code and it seems sub-optimal and possibly incorrect since it's adding event listeners on both the window and document objects. However, it is working properly except for blackberry 5.0. Can someone explain if all this is set up correctly or if there are any recommendations to make it better and/or more streamlined?

        if (document.readyState === "complete") 
            callback();
        else if (document.addEventListener) 
        {
            document.addEventListener("DOMContentLoaded",callback,false);
            window.addEventListener("load",callback,false);
        }
        else if(window.attachEvent) 
        {
            document.attachEvent("onreadystatechange", callback);
            window.attachEvent("onLoad",callback);
        } else
            setTimeout(callback,2000);
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
VinnyD
  • 3,500
  • 9
  • 34
  • 48
  • 2
    Put all JS at the end of the document. It is pretty much the same. – Saxoier Aug 01 '11 at 17:53
  • 1
    no its not if you have asynchronously loading scripts. – VinnyD Aug 03 '11 at 07:53
  • If you use async. scripts than you shouldn't use `DOMContentLoaded` or the way i proposed because the execution of this async. script may occur after this event fired or the HTML-Parser reaches the bottom of the html file. Therefore only `window.onload` and `xhr.onreadystatechange` can be used - both is cross browser compatible. – Saxoier Aug 03 '11 at 13:55
  • Regarding blackberry browser. I'm aghast at the amount of bugs I've heard about this particular browser! – Camilo Martin Oct 03 '12 at 16:27

3 Answers3

62

If you want to know how it's done or see a way of doing it. I recommend looking at Diego Perini's work. His work and methods are used in many DOM libraries, including jQuery. The guy doesn't seem to get much credit unfortunately. He is the one who pioneered the try/catch polling method, which is what makes cross-browser dom loaded events possible when IE is thrown into the mix.

https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js

chjj
  • 14,322
  • 3
  • 32
  • 24
5

If you want to use pure javascript, you can use thу following cross-browser function (source (in Russian): http://javascript.ru/unsorted/top-10-functions)

function bindReady(handler){
    var called = false     
    function ready() {
        if (called) return
        called = true
        handler()
    }     
    if ( document.addEventListener ) {
        document.addEventListener( "DOMContentLoaded", function(){
            ready()
        }, false )
    } else if ( document.attachEvent ) { 
        if ( document.documentElement.doScroll && window == window.top ) {
            function tryScroll(){
                if (called) return
                if (!document.body) return
                try {
                    document.documentElement.doScroll("left")
                    ready()
                } catch(e) {
                    setTimeout(tryScroll, 0)
                }
            }
            tryScroll()
        }
        document.attachEvent("onreadystatechange", function(){     
            if ( document.readyState === "complete" ) {
                ready()
            }
        })
    }
    if (window.addEventListener)
        window.addEventListener('load', ready, false)
    else if (window.attachEvent)
        window.attachEvent('onload', ready)
    /*  else  // use this 'else' statement for very old browsers :)
        window.onload=ready
    */
}
readyList = []      
function onReady(handler) {  
    if (!readyList.length) { 
        bindReady(function() { 
            for(var i=0; i<readyList.length; i++) { 
                readyList[i]() 
            } 
        }) 
    }   
    readyList.push(handler) 
}

Usage:

onReady(function() {
  // ... 
})
VIK
  • 689
  • 2
  • 9
  • 20
3

Personally I'd use jQuery for this.

jQuery is designed to handle the variety of different browser implimentations of the document ready state.

Using jQuery your above code would look like:

$(callback);
Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162