Combining JavaScripts - Competing Onload Handlers

Scenario: You have two (or more) scripts. They work separately, but not when you combine them in one document. The most likely culprit is competing onload handlers.

JavaScripts will generally require some sort of initialization routine to be run once the document has all the necessary components in place, in particular, DOM elements required for the code. Sometimes it works to place the call to initialize the code at the end of the document, before the close body tag, but that is not consistently reliable for a variety of reasons. Calling the initialization routines onload is, or has been until recently, the method of choice.

Perhaps one initialization routine is called from the body tag onload attribute, while another is assigned to window.onload. One or another will not be called. If you have multiple assignments to window.onload each will overwrite the previous one as the code is parsed.

The purpose of this brief tutorial is to discuss various approaches to overcoming this problem, both old and new. The challenge to is to locate all of the onload function calls or assignments and to make sure that they are all successfully invoked.

Onload the Old-Fashioned Way

Depending upon when and by whom the code was written there are variety of places where one might find onload function calls or function assignments lurking. Although it is now considered poor practice to place event handlers in HTML attributes you may still find them there:

<body onload="doSomething(argument)">

It is quite simple to place multiple function calls onload in that location simply by separating them with a semicolon. One advantage of code using the body onload attribute is that you don't have to go looking throughout code to find window.onload assignments:

window.onload = doSomething;

Sometimes these statements are buried within the code and difficult to locate. Nonetheless, if you are using code that assigns a function to be called onload in this way you must find a way to reconcile that with other code also needing to be run onload.

One can place multiple function calls inside an anonymous function assigned to window.onload as follows:

window.onload = function() { 
  fn1Name(args);
  fn2Name();
}

Although the above practices still work perfectly well, they have fallen out of favor. The standard of unobtrusive JavaScript dictates that not only should JavaScript be removed from the document structure (i.e., not use HTML event handler attrubutes) but should also not obtrude on (have to commingle with) other code.

AddLoadEvent Functions

A better approach has been around and in broad use for quite some time: addLoadEvent functions, the original version most likely by Simon Willison.

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

The addLoadEvent function calls can be placed wherever you want. That is, there is no need to remove from the code in which they belong and combine in a single location:

addLoadEvent( functionToCall );

// example passing arguments:
addLoadEvent( function() { doMeOnload('Yo', 'baby!') } )

You can call as many initialization routines as you like with addLoadEvent and they will all be successfully added to the stack. However, use of addLoadEvent functions is not a magic bullet. Multiple window.onload function assignments placed ahead of the function definition can't be collected and window.onload function assignments that are parsed after the addLoadEvent function definition will overwrite it. Also, function calls placed in the body tag onload attribute will render addLoadEvent ineffective.

The objective: decide on one approach to initializing code onload and use it for all code used in your documents. Code from dyn-web currently uses addLoadEvent.

New Approaches to Onload

One drawback mentioned in the discussion of Simon Willison's addLoadEvent is that sometimes one doesn't need the entire page including images to have completed loading before code can be initialized. This wait can be especially problematic if there are numerous and large images to be loaded. What is needed is some event that fires when the DOM is ready. Enter DOMContentLoaded.

Even though the DOMContentLoaded event is not supported by all browsers there have been numerous efforts to reconcile the cross browser differences and provide the same functionality. The large libraries and frameworks currently in vogue will generally have a function that you can use to initialize code once the DOM has loaded. For example, see JQuery's ready event.

If you are not using one of these libraries you can find code to serve the same purpose. See discussion and code at:

Back to top