Firing scripts on page load

I. Firing scripts on page load
This tutorial describes several ways of ensuring that scripts that we want to fire on page load will actually do so. We will not be concerned with matters having to do with asynchronous loading, execution speed, parser blocking etc.

II. Moving scripts to the bottom of the body section
Many coders seem to think that putting a script at the end of the body tag guarantees that it will fire because of its position in the document. While this is true in many cases, we can't rely on this because a script put at the end of the document starts to run as soon as the dom is ready (unless we inform it to wait using a timeout or another method). At this 'domready stage', there may be scripts on our page that are still loading. Consider the following scenario. Suppose we have an iframe that must produce an alert ('iframe loaded') as soon as it has finished loading. We could do <iframe src="http://www.dynamicdrive.com" onload="alert('iframe loaded')"></iframe>, of course. But let's assume for the sake of the argument that we have reasons not to do this and that we prefer the alert to be dependent on a value that is assigned to a variable (say: var message) after the iframe has loaded. Then we could have something like <iframe src="http://www.dynamicdrive.com" onload="message='iframe loaded'"></iframe>  and a script like <script>var message; function show_message(){alert(message)}</script> that is supposed to do exactly the same thing as <iframe src="http://www.dynamicdrive.com" onload="alert('iframe loaded')"></iframe>  if <script> show_message() </script> is put at the end of the document:
<script>var message; function show_message(){alert(message)}</script>
<iframe src="http://www.dynamicdrive.com" onload="message='iframe loaded'"></iframe>
<!-- at the end of the document -->
<script> show_message() </script>
But this is not what happens in our scenario. The reason is that show_message() fires too soon, that is, when the dom is ready while the iframe is still loading. So putting a script at the end of the body tag does not guarantee that it will always fire.

III. Using window.onload=... or <body onload="...">
The script does fire when we use window.onload=show_message or window.onload=function(){show_message()}  instead ofshow_message(), even if we put the window.onload in the head (but we must put it after <script>var message; function show_message(){alert(message)}</script>). It will also fire when we do <body onload="show_message()">. So this works:
<script>var message; function show_message(){alert(message)}</script>
<iframe src="http://www.dynamicdrive.com" onload="message='iframe loaded'"></iframe>
<!-- you may put the script below anywhere but after the script it invokes ( = the script at the top);
you can also use window.onload=function(){show_message()} or put onload="show_message()" in the opening body tag -->
<script> window.onload=show_message </script>
It should be noted however that using multiple window.onload 's, as in:
<script>
window.onload=some_function1();
/* or window.onload=function(){some_function1()} */

window.onload=some_function2();
/* or window.onload=function(){some_function2()} */
</script>
produces unwanted results. The second window.onload will override the first one, and we only get the result produced by the second function. We should do this instead:
<script>
window.onload=function(){some_function1();some_function2()}
</script>
or:
<body onload="some_function1();some_function2()">
(There's only one exception to this rule: we can use multiple window.onload 's when using native functions. Example: <script>window.onload=alert('a'); window.onload=document.body.style.background='yellow'</script>).
 
We can avoid this complication by using onload-methods like the ones described below. They allow us to add lines for firing load events to already existing ones without further ado.

IV. A script for handling multiple onload functions
If we put the script below (written by Simon Willison) in the head of our document, we can do away with window.onload=... or <body onload="..."> and fire as many load events as we want by just adding javascript-lines to existing ones:
<script>
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
</script>
For each script we want to execute on page load, we simply add addLoadEvent(function() {some_function()}). In our case, this means that we just do addLoadEvent(function() {show_message()}) to make sure that our function show_message() executes when the page has finished loading:
<script>var message; function show_message(){alert(message)}</script>
<iframe src="http://www.dynamicdrive.com" onload="message='iframe loaded'"></iframe>
<!-- put the script below wherever you want, but after the main script it invokes ( = the script having function addLoadEvent(func) ); we have just one addLoadEvent here, but we can add more; we could have, for instance:
<script>addLoadEvent(function() {show_message()});</script>
<script>addLoadEvent(function() {another_function()});</script>
<script>addLoadEvent(function() {yet_another_function()});</script> -->
<script> addLoadEvent(function() {show_message()}); </script>

V. Attaching event listeners to onloads
A 'native way' (no need for a custom script) for handling onloads is to attach event listeners to onloads, like this:
<script>
window.addEventListener('load', function (){some_function()}, false);
</script>
So to get our alert once the page has loaded we can do:
<script>var message; function show_message(){alert(message)}</script>
<iframe src="http://www.dynamicdrive.com" onload="message='iframe loaded'"></iframe>
<!-- put the script below wherever you want, even at the very top of the head; we have just one window.addEventListener here, but we can add more; we could have, for instance:
<script>window.addEventListener('load', function (){show_message()}, false);</script>
<script>window.addEventListener('load', function (){another_function()}, false);</script>
<script>window.addEventListener('load', function (){yet_another_function()}, false);</script> -->
<script> window.addEventListener('load', function (){show_message()}, false); </script>
The nice thing about this method is that it only uses native javascript and that the script for firing a load event can be put anywhere we want, even at the top of the head!
Here again, we can fire as many load events as we want by just adding javascript-lines to existing ones.

VI. Doing it using jQuery $(window).load
This is also true for jQuery $(window).load. The following script is the jQuery-equivalent of pure javascript used for doing onloads:
<script>
$(window).load(function() { some_function(); });
</script>
So to get our message, we can do:
<script>var message; function show_message(){alert(message)}</script>
<iframe src="http://www.dynamicdrive.com" onload="message='iframe loaded'"></iframe>
<!-- put the script below wherever you want, even at the very top of the head (but after the script referencing the jQuery library, of course); we have just one $(window).load(function(), but we can add more; we could have, for instance:
<script> $(window).load(function() { show_message(); }); </script>
<script> $(window).load(function() { another_function(); }); </script>
<script> $(window).load(function() { yet_another_function(); }); </script> -->
<script> $(window).load(function() { show_message(); }); </script>

VII. The best method
The cleanest load-method is perhaps the one discussed in V above (event listeners attached to onloads), because it only uses native javascript and doesn't have certain shortcomings that other native methods have (window.onload, <body onload>). And the line(s) for firing load events can be put anywhere on the page, even at the very top of the head.
If we want to make sure that a function some_function() (defined somewhere on our page) fires on page load, we just put the following anywhere:
<script>window.addEventListener('load', function (){some_function()}, false); </script>
Adding any number of similar lines can be done without a problem.

VIII. Onresize
Scripts that fire on page load are often used to define how to position certain elements on the page. The positions of these elements are often wrong after the page is resized, since the scripts only fire on page load. There may be other cases where things go wrong after page resizing. In this respect, we should observe the following:
1. We can combine window.onload and window.onresize by doing window.onload=window.onresize=... This is also possible in the script given in IV above, where replacing window.onload=func width window.onload=window.onresize=func will force the script to handle loads and resizes in excatly the same way. But we must keep load and resize separate when we 'do it' in the body tag: <body onload="..." onresize="..."> etc.
2. We can attach event listeners to resize events in the same way we attach them to load events (see V above). That means that we can put lines like <script> window.addEventListener('resize', function (){some_fuction()}, false); </script> wherever we want and in any number.
3. The same is true for $(window).resize(function() vs $(window).load(function(). We can have any number of jQuery resizes indeed (as we can have any number of jQuery loads) and we can put them where we want (but after the general script referencing the jQuery library).

Arie Molendijk, mesdomaines.nu.