Stop The Window.Onload Madness

0 comments suggest edit

Madness - Image from DC
Comics There are a lot cool javascript libraries floating around the Intarweb these days that add cool behavior to web pages. My favorites are the ones that you simply add to the head section of your website and control via markup. It is a great way to enhance structural html markup with Javascript.

Unfortunately many of these attempt to hijack the window.onload event. Ok, a show of hands (and I have been guilty of this as well). How many of you have written code like this to handle the onload event in javascript within a .js file?

function init()
{
}

window.onload = init;

Stop it!

That line of code will completely wipe out any other functions that were attached and ready to handle the onload event. How arrogant of your script to do so. Instead, your script should learn to play nicely.

Unfortunately, Javascript doesn’t support the delegate syntax that C# has. It’d be nice to be able to do this.

function init()
{
}

window.onload += init;

But that won’t work. One approach I found on Simon Incutio’s blog (which is used by the original LightboxJS script) involves using a method that safely attaches an event handling method to the onload event without overwriting existing event handlers.

It works by checking to see if there any methods are already attached to the event. If so it attaches a new anonymous method that calls the original method along with the method you are attempting to attach.

Here is a snippet demonstrating this technique.

function highlightXFNLinks()
{
  // Does stuff...
}

//
// Adds event to window.onload without overwriting currently 
// assigned onload functions.
function addLoadEvent(func)
{    
    var oldonload = window.onload;
    if (typeof window.onload != 'function')
    {
        window.onload = func;
    } 
    else 
    {
        window.onload = function()
        {
            oldonload();
            func();
        }
    }
}

addLoadEvent(highlightXFNLinks);

This is pretty nifty, but there appears to be a whole new school of script libraries that provide this sort of functionality for attaching to any event, not just the window.onload event.

I am sure you Javascript Gurus will expose how out of date and ignorant I am of this area (it is true) but the few that I have heard of that seem to be catching on like wildfire are the Prototype JavaScript Framework (often just referred to as prototype.js), the Dojo Toolkit, and Behaviour.

I will probably end up rewriting all my libraries to use one of these tooltips so that I stop duplicating code. Since each of my javascript libraries are stand-alone, I make sure to include the addLoadEvent method in each of them. But I think its time to allow a dependency on another script to avoid this duplication.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

15 responses

  1. Avatar for Marcelo Calbucci
    Marcelo Calbucci April 6th, 2006

    Yes, there is a better way than that:
    function AddOnload(myfunc)
    {
    if(window.addEventListener)
    window.addEventListener('load', myfunc, false);
    else if(window.attachEvent)
    window.attachEvent('onload', myfunc);
    }

  2. Avatar for Jeff Lewis
    Jeff Lewis April 6th, 2006

    Marcelo's version is the "best".
    Prototype has abstractions for this and similar issues.
    I'm writing an ASP.NET v1.1 app that makes heavy use of Prototype and I've been very happy with it.

  3. Avatar for Haacked
    Haacked April 6th, 2006

    Does that work in Safari and Firefox?

  4. Avatar for Jeff Lewis
    Jeff Lewis April 6th, 2006

    Yes, Prototype works in IE/Firefox/Safari

  5. Avatar for Haacked
    Haacked April 6th, 2006

    Sorry, I meant Marcelo's version.

  6. Avatar for Alex
    Alex May 8th, 2006

    So does it?

  7. Avatar for Vincent Verbrugh
    Vincent Verbrugh June 14th, 2006

    here is an other and shorter solution:
    if (window.onload) {
    var func = window.onload;
    window.onload = function() {
    func();
    startSlideShows();
    }
    } else {
    window.onload = startSlideShows;
    }

  8. Avatar for Myo Kyaw Htun
    Myo Kyaw Htun July 16th, 2007

    I've been getting problem with "window.onload" for a long time ago. Now you solved it for me :). Really thanks.

  9. Avatar for TAD_UK
    TAD_UK August 22nd, 2007

    function MultiOnLoad(f){var o=window.onload;window.onload=function(){o?o():o;f()}}

    //the old way ;)
    window.onload = function() {alert("onload!");}
    //example :)
    new MultiOnLoad(function() {alert('second');});
    new MultiOnLoad(function() {alert('three');});

  10. Avatar for bsgu_drew
    bsgu_drew November 4th, 2007

    // Prototype version
    Event.observe(window, "load", some_function);

  11. Avatar for George
    George March 22nd, 2008

    Thanks,
    Using Vincent Verbrugh's version OK in Opera.

  12. Avatar for Peter Postma
    Peter Postma May 8th, 2008

    This helps, but the problem I'm facing is most packaged software does not do that themselves. And their functions load last.
    I had to give up and found 2 other ways to do it that work in most browsers:
    setInterval:

    function x() {
    if(divexists) {
    //perform ops
    clearInterval(mytimer);
    }
    }
    var mytimer = setInterval('x()', 250);

    what I am finding is this runs only once in most versions of FF :-((
    so I'm using this function for now:

    function x() {
    if(document.getElementById('...')) {
    // do operations
    } else {
    //if we still dont have our DOM, wait and try again.
    setTimeout('x()', 200);
    }
    }
    setTimeout('x()', 500);

    This effectively lets me run multiple window.onload operations without having to worry about what hijacks the onload method after my code is done. NOTE: you MUST use the quote marks in the setTimeout() call in the function!! This prevents the "too much recursion" error in F.F. by forcing the recursed function call to be evaluated by the browser each call.

  13. Avatar for danny
    danny September 1st, 2008

    i wrote something similar as well on how to handle multiple window events in javascript.
    however, i've received similar feedback to use window.addEventListener and window.attachEvent but as far as i know, they're browser dependant functions and not part of the core javascript language.
    if my assumption is true, wouldn't it be better to use non-browser dependant functions?

  14. Avatar for Casey
    Casey September 27th, 2011

    Vincent Verbrugh solution worked great for me, thanks.

  15. Avatar for Jorge Zenil
    Jorge Zenil June 26th, 2012

    Thanks a lot, the solutions works for me!