View Full Version : script.onload observer?

DHTML Kitchen
05-01-2006, 08:26 PM
Is there an observer for a "script loaded" event?
Or maybe an observable property so I can tell if the script is loaded via polling?

Thinking something like:

callback = function() {
alert("script loaded");

var script = document.createElement("script");
script.addEventListener(type, callback, false);
script.src = "/js/bark.js";

05-01-2006, 08:31 PM
I don't believe so. What are you trying to accomplish?

DHTML Kitchen
05-01-2006, 08:50 PM
Why for loading external scripts, of course!

Dojo uses a require function to accomplish it, calling eval( responseText ); Problem is: If the responseText contains a js error, you can't debug it, or if it's 404 or 500 error page, then it will of course cause a js error. I'm not gonna say anything more about Dojo...

t should be possible to listen for the script load event and get the http status code, too. The browser already has access to it, but read access isn't just provided in js.

We need this functionality. It's more than useful: It's necessary.

05-01-2006, 09:07 PM
You could implement it easily. For every JS file you load:

Beginning of the JS file:

if (!("scripts" in window)) var scripts = new Object();
scripts["jsfilename.js"] = false;

Then you have the rest of the code. Then at the end:

scripts["jsfilename.js"] = true;

And then you can just poll the scripts object for completion. If you wanted to be fancy, you could assign a callback .watch() for Gecko, and a callback via onpropertychange for IE (if you change the new Object() to say, document.createElement("script") so it's a DOM object).

DHTML Kitchen
05-01-2006, 09:43 PM
That's one approach.

We can poll to wait for "true" to appear, and clearTimeout after a while, throw a custom error (e.g. ScriptNotLoaded).

DHTML Kitchen
05-01-2006, 10:37 PM
Ok, I think i'm onto something...

function loadScript(src, callback) {
var script = document.createElement("script");

script.addEventListener("load", callback, false);
else if(script.attachEvent)
function() { loadScript.callbackIE(callback); });

script.src = src;
loadScript.callbackIE = function(callback) {
var target = window.event.srcElement;
if(target.readyState == "loaded")

// load 30k script.
// Listener.cleanUp is defined at the bottom of drag.js
callback = function() {
var self = this;
alert("Loaded: " + this.src + "\nListener.cleanUp (nested):" + Listener.cleanUp);
loadScript("http://dhtmlkitchen.com/editor/js/drag.js", callback);

05-01-2006, 11:46 PM
DHTML Kitchen: How good control do you have over the script on the server, and what type of content can be found in it? If the contents is in the form of JSON, a JavaScript function literal or an object literal a solution to your problem might look like this:
function callback(o){
/* Script is loaded, it's sent an object back to the callback.
Do whatever you need to do with the object. */
}And then you append the scripts using DOM, with a query string of '?fn=callback'. The server uses this query string to build
/* JSON object, JavaScript function literal or object literal */

The same way of doing it, but appending the callback to the end of the file instead of wrapping it also works for libraries where you use function declarations, variable declarations, or globally executed code. If you do have those though, it's normally pretty quick work to make the former approach work perfectly too.

It demands some control over the server side of it, though.

DHTML Kitchen
05-02-2006, 12:05 AM
I don't know what you mean. We can send back anything we want from the server. We have total control. The callback executes after the script is loaded.

I'm trying to get some sort of "waitForCondition" to pause script execution until the script file is fully loaded.

The load event is capturable. readyState == "loaded", and useCapture = false.

I just need a waitForCondition. I want to waitForCondition before returning the script. Selenium has waitForCondition functionality. I'm going look into that.

along the lines of
waitForCondition("scripts['"+jsfilename.js+"'] == true;");

05-03-2006, 12:00 AM
Another thing you might try is to preload the script using ajax. I've done this with stylesheets before and it works, so it might work for scripts as well.

The idea is, make a GET request for the script, and inside that request's completed readystate function (200 or 304) create the script and append it to the page. At this point the script should be drawn from cache, and hence you can consider its loading to be instantaneous.

That's the theory anyway!

05-03-2006, 06:15 AM
You can actually shorten the code you already made:

function loadScript(src, callback) {
var node = document.createElement("script");
if (node.addEventListener)
node.addEventListener("load", callback, false);
node.onreadystatechange = function() {
if (this.readyState == "complete") callback.call(this);
node.src = src;
node = null;

Tested successfully in IE6 and Firefox 1.5, and no memory leaks. :)

Frontend Studio
09-28-2009, 06:27 PM
thank you guys for the tip, but I had to work it around like this in order to work properly (readyState "complete" ain't gonna get recognized in IE, so I used "loaded"). Furtherly, I was using Prototype methods besides.

var isIE6 = myWork.BrowserCheck.IE6; // custom method, use "navigator.userAgent.yaddayadda" instead

var newSliderScript = new Element("script", {
type: "text/javascript",

if(isIE6) {
newSliderScript.onreadystatechange = function() {
//alert(this.readyState); // test IE loading state
if (this.readyState == "loaded") document.fire("myWork:sliderReady");
} else {
// "good" browsers go here
newSliderScript.observe("load", function(){

document.observe("myWork:sliderReady", function() {

// ... your code that should run on "load" here ....


This does the trick for me and "my" IE 6 and FF 3 :-)