Unobtrusive Javascript, Opera, <body onload= and window.onload

I was working on updating the design of one of the websites at work yesterday, the design was based on our stand at a recent exhibition and I had some cunning plans with regard to animating the page with unobtrusive javascript. The 'panel' on the right of the page rotates through three different displays at a five second interval, but there is a button to pause it should you be taken by the sudden urge to examine one in more detail. When your curiosity is fully sated you can resume the animation using the continue button which has appeared, as if by magic, in place of the pause button. OK, so it's really not that impressive, but I was quite pleased with myself, all the effects get applied by the script and there are no inline event handlers, and when javascript is disabled the content of the page displays just fine.

While I was developing I kept everything all hodge-podge in the same file, HTML, CSS and javascript all together. I was dutifully testing it in IE6 and 7, Firefox and Opera as I went along, and even Konqueror after a short delay to get it compiled on the Gentoo box I have in the server room. Everything worked fine, apart from a transparency issue in Konqueror, and when it didn't I fixed it. This included an exciting excursion into the world of the IE onmouseleave and onmouseenter events and how to make the other browsers mimic that behaviour, but was all the more fun for that. But eventually I got it all working to my satisfaction in all my test browsers and started preparing it for release into the wild. My basic plan here was to split the content, presentation and behaviour into separate files, as per accepted best practice (and also because the site will end up being more than one page) and add a print stylesheet.

It ought to have been a relatively straightforward task, and really it was if I'd been thinking clearly. The problem I encountered was that, after I'd separated everything into three files my neat pause/continue content cycling stuff went haywire in Opera. Everything still worked identically in IE6/7 and Firefox, but in Opera the pause button didn't pause, the panel disappeared for ten seconds at a time and my neat fade in/out effect for the skip link stopped working. I tried lots of weird and (in retrospect) wildly improbable fixes but nothing seemed to work, in desperation I tried putting it all back into the one file but still had the same problem. In the end I gave up and went home, had some tea, then fiddled with it for another hour, but still no joy.

A night's sleep turned out to be the cure for my stupidity, here's what was causing the problem: when everything was in the same file I'd been using the onload attribute on the body element to run the javascript initialisation; when I moved everything into separate files I'd switched to attaching the init function programmatically, using a variant of Simon Willison's addLoadEvent function; while doing this I'd forgotten to remove the onload from the body element &#58;&#111;&#111;&#112;&#115;&#58;

The interesting thing is that this only affects Opera. In IE and Firefox the onload on the body element replaces anything which window.onload has been set to in script, in Opera it doesn't - both will get called, first the onload on the body element and then the window.onload. If you're using global variables to, for instance, keep track of the current state of your little animation, and you're not checking the state of those variables when running your initialisation code, this will really mess things up...