Dynamic loading of external JavaScript (.js) files

Pythoneer

Tuesday, March 1. 2005

Dynamic loading of external JavaScript (.js) files

Problem: I simply want to have the same functionality of PHP's require()in JavaScript.

I have tried multiple approaches but not found the perfect one yet :-( There are some requirements to it: it also needs to run without ActiveX (IE's XMLHTTPRequest) and of course for as many browsers as possible.
Here is what I have tried and what the problems are.

via XMLHTTPRequest

The below way for Mozilla works fine, I think the IE way still has some problems, it's not really tested (I am simply too lazy to switch from my Powerbook to Windows :-) ). Find a crossbrowser XMLHTTPRequest here.

// Mozilla and alike load like this
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
//FIXXXXME if there are network errors the loading will hang, since it is not done asynchronous since
// we want to work with the script right after having loaded it
req.open("GET",fullUrl,false); // true= asynch, false=wait until loaded
req.send(null);
} else if (window.ActiveXObject) {
req = new ActiveXObject((navigator.userAgent.toLowerCase().indexOf('msie 5') != -1) ? "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP");
if (req) {
req.open("GET", fullUrl, false);
req.send();
}
}
if (req!==false) {
if (req.status==200) {
// eval the code in the global space (man this has cost me time to figure out how to do it grrr)
window.eval(req.responseText);
} else if (req.status==404) {
// you can do error handling here
}
}

This is a really cool way to do the loading, but:
* the ActiveX component can be turned off in IE, then it fails (and we had that problem at a customers)
* if the script you want to load is not available for some reason this loading script will simply hang, since it doesn't load asynchronous ... that sucks big time, some kind of fallback mechanism is needed here, but how when you got stuck :-)
* the eval() at the end is something that makes cold shivers go down my back ... any ideas to replace that?
* on errors you don't get the proper line numbers, it always tells you the file that loaded the external file and some obstruse line number, really annoying

via DOM loading of script tag

Very simple and straight forward, but I had to search the web for this simple idea too :-)

var e = document.createElement("script");
e.src = fullUrl;
e.type="text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);

The problem here is that Firefox (I tested 1.0.1) does not wait until the external file is completely loaded, it does that in some parallel thread it seems. But you can catch that with e.onload, which again sucks if you want to simply put a require() in the code (may be I should try to write some tricky, weird while-loop which sleeps inside until the script is loaded, but that sounds like sticking my hands into mud).
But on the other hand Opera 8 (on Windows) waits nicely until the script is loaded.
If I remember right I didn't play much in IE with it (note to myself: do it!).
I tested that in all the browser by simply loading a script which defines a function, and if I call the function right after loading the script and it doesn't bring an "Undefined function" error, I assumed that the loading was synched :-) no magic here.

To catch if the loading is done there are two ways:
* for IE you can use onreadystatechange which is just the same as for the XMLHTTPRequest, MS just enabled that for many more elements
* in FireFox it works with the above mentioned onload

via an iframe and it's src attribute

... todo

via document.write()

Not even an example, since that is something we don't do anymore :-)

Conclusion

Combine all the ways mentioned here and you get a version which works on all the browsers, I will implement it soon I hope and I will keep you updated, just watch here.
I will do it like this:
* for IE - create script element and wait until loaded using onreadystatechanged (to be able use when ActiveX is off)
* for Mozilla and the others - create script element and wait until loaded using onload event
* in Opera - simply load it via creation of script, it seems to wait until the file is loaded, cool
If the while-loop that waits for the readyState/onload to say "file loaded" doesn't work as I expect it then I will probably have to go back to the XMLHTTPRequest way.

Posted by Wolfram in JavaScript at 13:53
Comments (5)
Trackbacks (0)

Trackbacks
Trackback specific URI for this entry

No Trackbacks

Comments
Display comments as (Linear | Threaded)

I'm trying to do a loading with IE. but readyState never take "complete" value with DOM method. So my others scripts hang because the main script is not found. I've tried with XML approach but I've got a STACK OVERFLOW:0 error. May you could help me to found a trick ?
#1 Sébastien CRAMATTE (Homepage) on 2005-04-19 15:41 (Reply)
[Quote]via DOM loading of script tag Very simple and straight forward[/Quote] Allready attached js functions on htmlevents; ( EXAMPLE : ) Will not automaticly bind when a dynamic external js loads into the page; The BODY is allready parsed by your browser, at that time the allready namend functions which require the dynamic js file will be referenced to null; Any elements which has been created after the load of the js file can bind them :) ( EXAMPLE : obj = document.createElement('DIV'); obj.onclick = isallreadyloaded(); )
#2 glashio on 2005-07-04 19:50 (Reply)
Hey, I've build several load script and use IFRAMES in IE to asynchronely load many JS Files and one function that returns true or false when all frames were loaded... Frames were killed at the end of load and everything works fine, but Firefox does not load the frames, it does not load DOM-Script tags, and even document. write does not work like it should, so firefox never loads my js file after body was already executed. So please give me an answer that helps me to get Firefox load a js file when the user presses a button and wait until this is done but without opening a new document in something others than an IFRAME. Please give Sourcecode Thanks
#3 Hawkynt (Homepage) on 2005-10-17 12:07 (Reply)
There is a nice solution out there, that might become standard http://www.openjsan.org/doc/c/cw/cwest/JSAN/0.10/lib/JSAN.html I think it has not yet solved the ActiveX problem of IE, but looks pretty good for all the other open items. Wolfram
#4 Wolfram Kriesing (Homepage) on 2005-10-17 12:21 (Reply)
Unfortunately, you can't eval in global scope... :( Quote from http://nerd.newburyportion.com/2005/09/the-magic-eval "Thanks to a bug, you won’t be able to iterate global functions using Internet Explorer. Other browsers seem to work fine." The mentioned setTimeOut didn't work for me. :( As you I simply loading a script which defines a function, and if I call the function _right after_(!) loading the script and it doesn't bring an "Undefined function" error. What to do? :)
#5 Wiktor on 2006-02-26 13:27 (Reply)

Add Comment


To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

 
 

Calendar

Back May '12
Mon Tue Wed Thu Fri Sat Sun
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Quicksearch

Categories

  • XML JavaScript
  • XML Mac stuff
  • XML Miscellaneous
  • XML Missing or not found
  • XML Music
  • XML Private
  • XML Programming


All categories

Archives

  • May 2012
  • April 2012
  • March 2012
  • Recent...
  • Older...

supersized.org

Owner login

supersized s9y blog hosting
Free s9y blog!

Disclaimer

Syndicate This Blog

  • XML RSS 0.91 feed
  • XML RSS 1.0 feed
  • XML RSS 2.0 feed
  • ATOM/XML ATOM 0.3 feed
  • ATOM/XML ATOM 1.0 feed
  • XML RSS 2.0 Comments
The owner of supersized.org is not responsible for any content on this page!