Wednesday, February 21, 2007

Attaching JavaScript functions to the Window OnLoad event

In an earlier post, I had griped about IE but forgot to mention details about the actual problem. The issue was with the way we were using the html web page's onload event. We were attempting to do something like this:

<body onload="someFunk()">
Testing the onload function

...<br />

<body onload="anotherFunk()">
You shouldn't be nesting another body tag out here !
</body>

</body>


Yes, exactly, two body onload functions! I'll come to 'why' later. The above code doesn't work - only the outer BODY's onload event is really triggered (someFunk only is called)

There is in fact a better way to attach the second function (and any subsequent functions) to the onload event. A quick utility function for this can be found at http://www.dustindiaz.com/top-ten-javascript . This function simply appends your function to the existing list (meta function ?). Try this code:

<script type="text/javascript">
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else {
window.onload = function() {
oldonload();
func();
}
}
}
</script>

<body onload="someFunk()">
Testing the onload function

...<br />

This is better

<script type="text/javascript">
addLoadEvent(anotherFunk);
</script>

</body>


Neat, elegant solution and works consistently in IE and Firefox.

Now coming back to the earlier question of 'Why?'. Why did we land up with a nested body tag like that? Well we are using this framework that allows us to define a common template for a group of pages. Now some of these pages needed to trigger a javascript function on body load. This was conveniently achieved by adding a <body onload="..."> to these pages. This worked fine as long as the templates themselves did not have a <body onload="...">! The moment a template defined a body onload event, the content page body onload, if present, was ignored. Such situations happen more often than not with templates being written by one person and other content pages being developed by various other people. There was already a way to do this in our code base but we didn't spot it immediately. It took a while to figure out and it was interesting investigating this. Well, everyday you learn something new (and my writing has been deteriorating !! :)

3 comments:

noEhch said...

In your second example, you compare the window.onload property to the onload attribute.

One -- if not the -- reason why both someFunk() and anotherFunk() are being called is because of how you have the Javascript written. By including the parenthesis after someFunk, you're calling the function and setting window.onload equal to the return value.

Try this:
// set equal to identifier vs. return
window.onload = someFunk;

I don't guarantee this'll fix it, but it'll reduce the possible causes.

Aldrin M said...

@noehch
You are absolutely right! That was a faulty bit of code. Will be updating it. Thanks for pointing it out!

avrik said...

this solution doesn't work on IE8,
apparently this version doesn't allow attaching events in addition to the ones that already exist in the 'onload' of this page. are there any other suggestions? thanks, Shany.