"Do not spoil what you have by desiring what you have not; but remember that what you now have was once among the things you only hoped for." -Epicurus
Execution After Page Load

Introduction

When writing JavaScript, many times we want to run a function right after the page finish loading. The two most common ways of doing it is by specifying the function call in the onload attribute of the body tag or by specifying it directly via window.onload. It is easy and it works in all of the browsers but it comes at a cost: you can only specify one and only one function to run. If you require more than one function to run, then what can you do? Many have come up some solutions and that is where we begin. Before we continue though, lets just completely eliminate the onload attribute of the body tag from our solutions because it ruins our separation of design and code as well as being very limited in its capabilities.

Delay It

One of the easiest solution is to just simply delay its execution using window.setTimeout. The idea is that when you delay its execution by however many milliseconds, it gives the page enough time to load before the function is run. In fact, Prototype is using this method to defer any execution of a function. The code for it is simple:

<script type="text/javascript">
// Function to run after page finish loading
function myinit() {
    ... do something ...
}

window.setTimeout(myinit, 100);
</script>

While that solves some of the problem and it allows you to call multiple functions simply by adding another window.setTimeout, it isn't really reliable at all. If a page takes a long time to load, the execution of the functions will be too early. Remember, window.setTimeout simply delays the execution of the function from the time it was set not after the page finish loading. So while this is a quick and simple solution, it is just that: simple and not truly suitable to use as a solution.

Encapsulation

In order to truly get a function to load when the page loads, it is better to use window.onload. That will make sure the function only gets called after the page has finish loading. So how do we allow more than one function to run? The answer is to encapsulate the functions within another function. However, instead of simply writing the encapsulation each time, it is better for us to just write the wrapper function that will do it instead. Now each time we need to add a function, we just call this wrapper function instead.

<script type="text/javascript">
// Function to run after page finish loading
function myiniti1() {
    ... do something ...
}

// Another function to run after page finish loading
function myinit2() {
    ... do something ...
}

// Wrapper function for window.onload
function myWindowOnload(func) {
    var current = window.onload;

    if(typeof(current) != 'function') {
        window.onload = func;
    } else {
        window.onload = function() {
            current.apply(current);
            func.apply(func);
        };
    }
}

myWindowOnload(myinit1);
myWindowOnload(myinit2);
</script>

The wrapper method basically gets the current value of window.onload and makes sure it is a function. If it isn't, then it just sets that function. If it is, it creates a new function which will run the current function then run our new function.

For most people, this will work near perfection without any problems. It meets both of the requirements of actually executing after the page finish loading and it can run more than one function. However, what it can't do is safely integrate with third-party scripts. This method will only work if everyone that needs window.onload use your function or at least, all of your window.onload calls happen last. So while this is an improvement over window.setTimeout, it has its own problems. But there has to be a solution right?

Listen Now

A solution does exist (or else this article wouldn't be here) but it also comes at a cost. First, it isn't fully compatible with all of the browsers. However, the majority of the newer browsers do have support for in. In fact, considering that the majority of users now use either Internet Explorer 6+, Firefox 1.5+, Safari 2+, and Opera 8+, this isn't really of a problem anymore since all of these major browsers has support for this solution. So, exactly what is this solution? The answer: event.

Note that window.onload is actually an event. However, it was further expanded by W3C to allow an element to have multiple event listeners. This truly allow JavaScript to be much more powerful. Oddly enough, not many people is using this approach and most don't even know this solution existed (trying googling about window.onload and see how many results that use this method). The fact is, using addEventListener is the best and most stable solution of them all (at the time of writing this of coruse). It has all of the benefits of window.onload without the accompanying problems. Best part is, it doesn't matter if someone is using window.onload, it does not effect your script.

Lets not get too happy, however. I did mention that there were some compatibility issues didn't I? Internet Explorer, the browser with the largest market shares, does not have support for this. Before you start to curse again at Bill Gates and Mircosoft, save your voice because even Internet Explorer (at least from 5+) has an event listener. They just call it something different like usual: attachEvent (Mac users though, sorry, no luck for you but I assume you are not using IE5 anyways, right Safari & Firefox users?). While their exact functionality is a little different, they are able to do the same thing.

Again, we will create a wrapper function to set up the event. Unlike the previous solution though, we don't care if it has been called before or after. The only thing we need to worry about is the current function itself and whether or not the current browser is IE or not. Actually, forget that last part. We don't care if it is IE or not either. We should just care if the function that listens for the event exist or not.

<script type="text/javascript">
// Function to run after page loads
function myinit1() {
    ... do something ...
}

// Another function to run after page loads
function myinit2() {
    ... do somthing ...
}

// Wrapper function for event listener
function myWindowOnload(func) {
    if(window.addEventListener) {
        // See if the browser has the function addEventListener
       window.addEventListener('load', func, false);
    } else if(window.attachEvent) {
        // See if the browser has the function attachEvent
       window.attachEvent('onload', func);
    } else {
        window.alert('Sorry, but your browser isn't supported');
    }
}
</script>

That will add the event listener to the window object after it finish loading which is basically the equivalent of window.onload except that you can have multiple window.onload and not worry about overwriting. Just in case someone is using a really old browser, we'll alert to a message to let them know their browser isn't supported.

Conclusion

Can I say that this is complete and that the window.onload solution has been completely solved? While other people have called it solved after using the second method, I am not calling it solved even with the third method. The reason is there is and will continue to be problems with each and every solution we come up as developers. With the changing of standards and with so many browsers out there (those that follow the standards and those that don't), it is never an easy task to keep your web site supported by all of the browsers. In fact, at one point, I was tempted to make my web site compatible with only Firefox but if you want people to visit your web site, you must make it compatible with as many of the browsers as possible. No solution is perfect but there are plenty that will be near perfect. Sometimes the solution is right under your nose. You just need to do some searching and look outside of the box every once in awhile. After all, I wouldn't come up with this third solution if the only thing I was determine to look at was window.onload.

User Comments

  • Posted By
  • Posted On
  •  
  • Comment
  • Jye
  • August 07, 2008
  •  
  • Thank you very much !!! thats wat i need !!

Comment Submission

Found something wrong with the information or you just want to speak your mind? Send us a comment.

  • Nickname:
  • Comment:
  • Captcha:
  • Captcha
This page was last modified on: Jun 09, 2008.