Section E. Initialization


E. Initialization

Once you've imported your scripts, you need to make sure they start at the right moment. In order to explain the problems here, let's take a detailed look at what happens when you include a script in an HTML page. We'll start with a very simple example:

<head> <script type="text/javascript" src="/books/1/521/1/html/2/hello.js"></script> </head> // hello.js contains alert('Hello world'); 


When the browser encounters the <script> tag, it sends out an HTTP request to fetch the script file. The parsing and rendering of the HTML page is now halted until the script file has been loaded, or until the browser decides it doesn't want to wait any more (and the time at which it decides that depends on the browser). Therefore, if you import scripts from a slow server, page rendering may be delayed.

Once the script file has been received, it is parsed and the JavaScript statements are executed directly, if necessary. This means that the statement alert('Hello world') is executed as soon as the browser encounters it. Only after this has been done does the browser resume the normal HTML parsing. Therefore users of this page will first see the alert, and the rest of the page only when they click OK.

Let's go to a more complicated example:

<head> <script type="text/javascript" src="/books/1/521/1/html/2/test.js"></script> </head> <body> <div >This is a test div</div> </body> // test.js contains var test = document.getElementById('test'); test.onclick = function () {alert('Hello world!')}; 


A simple event-handler registration, you'd say. If the user clicks on the element, the alert pops up. That's true as far as it goes, but at the moment the browser executes these statements there is no element with yet. After all, the browser first loads the script file, then executes any statements, and only then continues parsing the HTML document. Therefore the element is not present at the moment the JavaScript code is executed, and the script generates an error message.

In order to prevent such problems, you enclose most of your statements in functions:

function initializePage() {        var x = document.getElementById('test');        x.onclick = function () {alert('Hello world!')}; } 


Now the browser creates the function but doesn't execute it, because it hasn't yet received a command to do so. The trick, of course, is that you execute this function only when the page has been loaded.

The load event

The load event fires when the page has been loaded completely. Obviously this is exactly what we need for the initialization of our scripts. It works as follows:

function initializePage() {        var x = document.getElementById('test');        x.onclick = function () {alert('Hello world!')}; } window.onload = initializePage; 


This executes the initializePage() function when the page has been loaded completely. The script can now find the element with , and it sets the onclick event handler.

Most scripts start up only when the page has been loaded completely, because only at that time are all HTML elements on which the script wants to act present in the page. If the scripts started up earlier, they probably couldn't find most elements they need, and would give errors.

Unfortunately, the load event has two problems: correct mass initialization (i.e., initializing more than one script at the same time), and the exact timing of the event.

Mass initialization

window.onload (which we used above) essentially defines a method of the window object (see 5J). The problem is that if another script does the same, the window.onload value of the first script is overwritten, and the first script is never initialized.

Let's return to the Dropdown Menus and Edit Style Sheets examples. Say that I'd initialize the scripts like this:

   // dropdown.js    window.onload = initNavigation;    // editstyles.js    window.onload = initStyleChange; 


Only initStyleChange() will be executed, since it's the last defined value of window.onload. It overwrites the value given in dropdown.js, and Dropdown Menus is never initialized.

In order to execute both scripts, I need a better solutionone that allows me to set an unlimited number of event handlers on the same element. In order to do so I use my addEventSimple()/removeEventSimple() functions.

We'll discuss these functions in 7C, but by using them I can set several handlers for the same event on the same element. Now I can do this:

[Dropdown Menu, line 84]

addEventSimple(window,'load',initNavigation); 


[Edit Style Sheets, line 104]

addEventSimple(window,'load',initStyleChange); 


Now both event handlers are set. Better still, they don't overwrite each other.

Unobtrusive initialization

I created Site Survey and Usable Forms as independent modules that can be added to any site. Any Web developer who wishes to use them simply includes the correct script files, adds a bit of HTML, and the script works.

This means that I cannot use window.onload in the scripts. If I did that, my window.onload would either overwrite or be overwritten by the site's window.onload. Either case is unacceptable. Site Survey's general document.onclick event handler might overwrite or be overwritten by an existing document.onclick in the site, and that, too, would be unacceptable.

In these cases, I use the addEventSimple() solution, too. I add an extra onload event handler on top of any handler that may already exist.

Waiting for the load event

The load event fires when the page has been loaded completely, and that includes the images. This can cause a noticeable delay when a page contains huge image files.

When Dropdown Menu had been implemented on all of my client's sites, one clueless Webmaster added a 6 MB bitmap image to his homepage. This caused the site's usability to die a messy death. When a page appears ready, users expect to be able to use it, including its dropdown menus. Unfortunately, the mouseover events were not defined because they had to wait for the load event, which in turn had to wait for the 6 MB bitmap. That's confusing.

This problem is very hard to solve. Ideally, we'd want to have a sort of onLoadExceptForImages event that fires when the HTML page structure is loaded completely, but that doesn't wait for images. Unfortunately, such an event does not exist.

The DOMContentLoaded event comes closest. It fires when the DOM of the content is available, i.e., when the document has been parsed entirely, even though images may not yet be loaded. Unfortunately, at the time of writing this event is available only in Mozilla.

Another Solution to Long Wait Times

Dean Edwards describes a solution that works in Explorer and Mozilla, but no other browsers, at http://dean.edwards.name/weblog/2005/09/busted2/.


A solution would be not to use the onload event at all, but to simply include your script just before the </body> tag:

<body> [all HTML] <script type="text/javascript" src="/books/1/521/1/html/2/dropdown.js"></script> </body> </html> // at the end of dropdown.js initNavigation(); 


This way, when the browser gets around to executing this statement, the entire page has already been loaded, and the script has access to all elements. It doesn't wait for the images, though.

The best way?

Unfortunately, all of them have drawbacks as well as advantages, and the context in which you write a script is of paramount importance in selecting an initialization method. I hope that this section has given you enough information to make your own decision.

In general, I myself still use the old window.onload, except when I have to initialize a script unobtrusively. In that case I use the addEventSimple() solution. We'll get back to this problem in 7C.



ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net