tomhoppe.com

Racing, Web Development, Photography, and Beer...Stuff that matters.

Tuesday, March 18, 2008

addDomLoadEvent

Using window.onload for Javascript creates a crappy UI, as it waits for the entire page, including all CSS, JS, and images to load. I avoided as much as possible, but for some things in the day job, we needed to use it. The best example being that we only had access to JS in the head of the page, but needed to immediately client side add some code to the bottom of the page.

For this, we used addLoadEvent and waited till everything was done. Having been fed up with this, I did some a big of searching and found a solution from The Future of the Web, by Jesse Skinner. Jesse's script puts together a cross-browser way to wait for just the DOM to load, instead of all the images and text

This is easy for FF, Safari 3 Beta, and Opera, but a pain for IE and Safari 2. I changed his script slightly to be compatible with https and came up with the below code. Thanks Jesse!

.
addDOMLoadEvent = (function(){
    // create event function stack
    var load_events = [],safari_timer,done,exec,script;
 
 var init = function () {
            done = true;

            // kill the timer
            clearInterval(safari_timer);

            // execute each function in the stack in the order they were added
            while (exec = load_events.shift())
                exec();

            if (script) script.onreadystatechange = '';
        }

    return function (func) {
        // if the init function was already ran, just run this function now and stop
        if (done) return func();

        if (!load_events[0]) {
            // for Mozilla/Opera9
            if (document.addEventListener)
                document.addEventListener("DOMContentLoaded", init, false);
    
   /*@cc_on @*/
   /*@if (@_win32)
   var proto = "src='javascript:void(0)'";
   if (location.protocol == "https:") proto = "src=//0";
   document.write("<scr"+"ipt id=__ie_onload defer " + proto + "><\/scr"+"ipt>");
   var script = document.getElementById("__ie_onload");
   script.onreadystatechange = function() {
    if (this.readyState == "complete") {
     init()
    }
   };
   /*@end @*/

            if (/WebKit/i.test(navigator.userAgent)) { // sniff
                safari_timer = setInterval(function() {
                    if (/loaded|complete/.test(document.readyState))
                        init(); // call the onload handler
                }, 10);
            }

            old_onload = window.onload;
            window.onload = function() {
                init();
                if (old_onload) old_onload();
            };
        }

        load_events.push(func);
    }
})();

Labels: ,

0 Comments:

Post a Comment

<< Home