tags:

views:

105

answers:

2

Hello,

I'm a bit confused as to when the window.onload event is fired. For example: i have a page that has lots of external js files and even an on-demand loading of the script (dynamically creating a tag). All of this code is in the page (ie. it does not get fired on click or smth, it should execute while loading). Now let's say that i have window.onload = somefunction() in the last on-demand javascript. Is it possible that window.onload will fire before all the scripts actually get loaded?

+1  A: 

No. window.onload() is invoked when all resources (the document, objects, images, css, etc) have finished rendering.

Misread the question. Yes, it is entirely possible that the window.onload event will fire before a dynamically appended script has finished downloading. Scripts added using the DOM (document.createElement()) download asynchronously and aren't subject to the usual rule that window.onload() waits for all resources to finish downloading first.

I set up a test suite for you, http://jsfiddle.net/ywSMW/. This script adds the jQuery script to the DOM dynamically and writes the value of $ to the console during the onload handler. It then writes the value again a second later. Even with the script being cached, the first write to the console returns undefined, meaning the onload even has fired before the jQuery script has been downloaded and parsed.

Tested in IE and Chrome.


Re: the comments, if you want to check if the onload event has already fired, you can set the value of a global variable inside the onload handler:

var windowHasLoaded = false;

window.onload = function () {
    windowHasLoaded = true;
}

function doSomethingWhenWindowHasLoaded() {
    if (!windowHasLoaded) {
        // onload event hasn't fired yet, wait 100ms and check again 
        window.setTimeout(doSomethingWhenWindowHasLoaded, 100);
    } else {
        // onload event has already fired, so we can continue
    }        
}        
Andy E
Is there any way i could test in the script if the window has already been loaded?
Marius S.
@Marius S: yes, you can check the *document.readyState* property. When the document is parsed, it has a value of `"loaded"`. After the *onload* has fired, it has a value of `"complete"`.
Andy E
But readyState isn't supported in all browsers. This is the reason i'm asking.
Marius S.
@Marius: which browsers are you talking about? *document.readyState* is supported in IE, Firefox, Chrome, Safari and Opera.
Andy E
@Andy: w3c shows that Firefox does not support it
Marius S.
@Marius: w3c doesn't maintain browser compatibility references. You might be confusing w3c for W3Schools. Firefox *does* support it, although only in version 3.6 and later. The simplest solution otherwise is to create a global variable, e.g. `var loaded;`, then in the *onload* event handler, set that variable to *true*. Accessing that variable from anywhere else in the code will yield *true* when the onload event has already fired.
Andy E
+1 for your answer, btw :-)
Aaron Digulla
@Aaron: thanks :-)
Andy E
+1  A: 

window.onload (a.k.a body.onload or $(document).ready()) gets fired after the main HTML, all CSS, all images and all other resources have been loaded and rendered. So if your images stall, that can take some time.

Scripts embedded in the page get executed when the browser parses the </script> of each. So to execute a script before any other script, add a <script> tag in the header just after <head>.

Aaron Digulla
Good answer. +1
Ash Burlaczenko
Whilst script is a blocking call, is it really as basic as that, I thought onload waited until all the referenced resources had downloaded too. So if you had a reference to the tracking image used by web trends or HBX that took a while to process or justa slow loading resource (a large image?) the onload event would not fire until both the HTML had been parsed and the resources that called downloaded.
Paul Hadfield
@Paul is correct. *window.onload* doesn't fire when the browser parses `</html>`, it fires when all images, objects and other resources have been downloaded and rendered. You're confusing it with the mutation event, *DOMReady*, which fires when the document has been parsed. Also, dynamically added script elements download asynchronously, so they are exempt from this rule.
Andy E
er, *DOMContentLoaded*, not *DOMReady* :)
Andy E
References anyone? I'm pretty sure JS runs before the images are loaded and it surely runs before background images are loaded. This is why people add code to preload images in JS: To force the browser to load the images earlier.
Aaron Digulla
@Aaron: I can only point you to the [MDC window.onload documentation](https://developer.mozilla.org/en/DOM/window.onload), since the event isn't defined in any specification (as far as I'm aware). You can also run the example page I provided in my answer, which shows the *onload* event is fired before the dynamically added script is parsed.
Andy E
Hmmm... I'm noticing that you're talking about "window.onload". Is that the same as "body.onload" or are they fired at different times?
Aaron Digulla
@Andy: How about images? Are they loaded, too? At least images which are defined with CSS "background: url();" load after onload (I mean the image object is there but they might be rendered several seconds later when the image data arrives).
Aaron Digulla
*body.onload* and *window.onload* are the same - *body.onload* is provided as a means to set the *window.onload* handler directly through the HTML `<BODY>` element, using the *onload* attribute. *onload* won't fire until all images are downloaded and rendered too. I'm *fairly* sure this applies to CSS images too.
Andy E
@Andy: Thanks for the info about unload. As for images, I really doubt that the browser waits for them to load. Maybe it doesn't matter since the web is so fast today that we rarely have to wait for them but a few years ago, images were loaded after the HTML in background threads and I'm pretty sure that JS was running by then. Can't prove it, though (no time :-( )
Aaron Digulla
@Aaron: I think we might be on different pages here. JS runs before the document loads, there's no doubt about that. JS is executed *immediately* after the script block containing it is parsed. The question is regarding *window.onload*, which won't fire until after images have downloaded.
Andy E
Yes, I think you're right.
Aaron Digulla