4

I have an application that must be able to do the following:

var script1 = document.createElement('script');
script1.src = myLocation + 'script1.js';
script1.type = 'text/javascript';
document.body.appendChild(script1);

script1.addEventListener('load', function () {
    var script2 = document.createElement('script');
    script2.src = myLocation + 'script2.js';
    script2.type = 'text/javascript';
    document.body.appendChild(script2);

    script2.addEventListener('load', function () {
        var script3 = document.createElement('script');
        script3.src = myLocation + 'script3.js';
        script3.type = 'text/javascript';
        document.body.appendChild(script3);
    }, false);
}, false);

This totally works in every browser, even in IE9. In every other IE, it doesn't. I have tried falling back to Object.attachEvent('onload', function) but I think only window has that event listener.

Can anyone tell me what is the best way for this to work in every browser?

EDIT

I am trying this now, and it still doesn't work, both of them:

var script = document.createElement('script');
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';
script.type = 'text/javascript';
script.onload = function(){alert('jquery loaded');};
//script.attachEvent('load', function(){alert('jquery loaded');});
document.body.appendChild(script);
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120

3 Answers3

9

Internet Explorer, as you may have guessed, does things slightly differently. Instead of onload, an onreadystatechange event will fire. You can then check the readyState property and it can be one of a few different values. You should check for complete or loaded. There's a slight semantic difference between them that I don't remember, but sometimes it will be loaded and sometimes it will be complete.

And since you're presumably not going to have to worry about other code binding to this element, you can just use the DOM level 1 event interface:

script.onreadystatechange = function() {
  var r = script.readyState;
  if (r === 'loaded' || r === 'complete') {
    doThings();
    script.onreadystatechange = null;
  }
};

(Or you can use a regex above if you're lazy.)

chjj
  • 14,322
  • 3
  • 32
  • 24
7

I like how you attach the load event AFTER you add it to the page. Sort of like ringing the doorbell after you open the door.

addEventListener does not work in earlier versions of Internet Explorer, it uses attach event

if (script1.addEventListener){
  script1.addEventListener('load', yourFunction);
} else if (script1.attachEvent){
  script1.attachEvent('onload', yourFunction);
}

but that is still going to fail with older versions on IE, you need to use onreadystatechange like in Ajax calls.

script1.onreadystatechange= function () {
   if (this.readyState == 'complete') yourFunction();
}

So something like this:

function addScript(fileSrc, helperFnc)
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.onreadystatechange = function () {
      if (this.readyState == 'complete') helperFnc();
   }
   script.onload = helperFnc;
   script.src = fileSrc;
   head.appendChild(script);
}
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

I have found that readyState is set to 'loaded' for IE8 (IE11 in compatibility mode) so you'll need to cater for both values ('completed'), although I've not seen this other value returned in IE (thanks @chjj).
The following implements a singleton call-back that caters for both 'loaded' events, perhaps it is of use.

 function loadScript(url, callback) {
    var head = document.head || document.getElementsByTagName("head")[0];
    var scriptElement = document.createElement("script");
    scriptElement.type = "text/javascript";
    scriptElement.src = url;

    var singletonCallback = (function () {
        var handled = false;
        return function () {
            if (handled) {
                return;
            }
            handled = true;
            if (typeof (callback) === "function") {
                callback();
            }
            if (debugEnabled) {
                log("Callback executed for script load task: " + url);
            }
        };
    }());
    scriptElement.onreadystatechange = function () {
        if (this.readyState === 'complete' || this.readyState === 'loaded') {
            singletonCallback();
        }
    };
    scriptElement.onload = singletonCallback;

    if (debugEnabled) {
        log("Added scriptlink to DOM: " + url);
    }

    head.appendChild(scriptElement);
}
Nicholas
  • 572
  • 6
  • 17