dynamically creating script: readyState never "complete"
Solution 1
As per your comment, here's a schematic of how to dynamically add a script tag using XHR (XMLHttpRequest
):
var handleRequest = function( ) { //!! set up the handleRequest callback
if(this.status != undefined) {
/* do something with the status code here */
}
if(this.readyState == 4) {
var script = document.createElement("script") ;
script.setAttribute("type","text/javascript") ;
var text = document.createTextNode(this.responseText) ;
script.appendChild(text) ;
var head = document.getElementsByTagName("head")[0] ;
head.insertBefore(script,head.firstChild) ;
}
} ;
var request ; //!! supposing you have a way to get a working XHR Object
//.. set the XHR Object
request.open("GET",url,true) ;
request.overrideMimeType("text/javascript") ;
request.onreadystatechange = handleRequest ;
request.send(null) ;
Please keep in mind that this is only to give you an idea of what I mean. A working example would have to be way more elaborate judging from the jQuery source code.
Links:
Solution 2
I've found out a trick how to make script node become 'complete' in IE7 and IE8. And also how to detect when error really happens when loading script (node.onerror working only in IE9+). The hack is in
- NOT inserting the newly created element into DOM (at once).
- Calling node.children property and checking node.onreadystate property right after it. If the property changes to 'complete' - you have loaded script, it it changes to 'loading' - it's for sure script loading error.
Try it!
var node = document.createElement('script');
node.src = 'some-[un]existing-url.js';
node.type = 'text/javscript';
node.onreadystatechange = (function(node) {
return function () {
if (/loaded|complete/.test(node.readyState)) {
_finish();
}
};
})(node);
var _finish=function() {
if (node.readyState == 'complete') {
// insert node only after completing the request, though this is not necessary
var head = document.head;
head || (head = document.getElementsByTagName('head')[0]);
head.appendChild(node);
// call success function
_success();
return;
}
var firstState = node.readyState;
// hack: calling 'children' property changes node's readyState from 'loaded' to complete
// (if script was loaded normally) or to 'loading' - if error detected
node.children;
// error detected
if (firstState == 'loaded' && node.readyState == 'loading') {
// custom error code
_error();
}
}
Related videos on Youtube
pepsi600
Updated on June 08, 2022Comments
-
pepsi600 about 2 years
I'm trying to do something AFTER a script is completely loaded. (IE8)
Script I use for testing: http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js
and the invalid one: http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.minaaaaaaaa.jsThe code...
var script = create the element and append to head... // this works fine with FF/Chrome/... script.onload = function() {alert('script loading complete');} script.onerror = function() {alert('error loading script');} // and for IE script.onreadystatechange = function() { // this will alert 1.loading 2.loaded alert(this.readyState); // this never works if(this.readyState == 'complete') {alert('script loading complete');} // this works with either a valid or INVALID url else if(this.readyState == 'loaded') {alert('script loaded');} };
In my case, the "complete" never shows, the "loaded" shows even if a url is invalid. So there's no way to tell if a script is CORRECTLY loaded UNDER IE.
Am I doing something wrong? How come I never get the complete state?
UPDATE
OK, I just read some articles and it seems that readystate is not a reliable way to detect script loading.
So is there another way to do so? without jQuery, but pure Javascript.
-
pepsi600 almost 13 yearsCome on........did you just copy and paste? You got exactly the same code as mine (I mean the structure), and this is what I'm talking about...the "readyState" is never "complete"!!! And I'm trying to figure it out.
-
user278064 almost 13 yearsIt seems that there is no way to know if loaded or complete will be fired. Look javascript pattern "Loading on Demand". The author wrote this: • In IE you subscribe to the readystatechange event and look for a readyState “loaded” or “complete.” All other browsers will ignore this.
-
James Montagne almost 13 yearsHe's saying that load IS fired, but it fires even when the script is invalid and fails (404, etc.). He wants to know how to detect that.
-
pepsi600 almost 13 years@your update: well, that's not the point. == and === in this case are the same. readyState returns a string, and loaded/complete are surrounded with quotes, so, we're not comparing types. The problem is that IE just can't do the work with DOM event. I'm switching to AJAX... Thanks anyway.
-
Semmel about 10 yearsThis is by far the best solution for script injection in IE8 with success and error handlers. It is far better then loading the script via AJAX because by script injection the AJAX CORS limits do not apply. Great find with the
node.children
trick! Btw.var node = createNode( 'script',
... is of course in plain vanilla JavaScriptvar node = document.createElement('script');
... -
Yuri Izgarshev almost 7 years@Semmel, thank you for your reply and notes - I've updated my answer with pure JS.