On Demand Script Loading
This code will return true while it's waiting to load the external script - and if called again (i.e. at a later date or if you've got an excited user) will know that the script has already been loaded.
It allows for scripts to be loaded on demand without the use of an external library such as Dojo to allow for imports.
It also caches the function that requested the script to be loaded, to then execute it again when it's ready.
Note: the code does support the calling function to have parameters - it uses the arguments.callee.caller.arguments to pass the args back in.
* Only returns true when the external script has been
* loaded in to the DOM. It uses arguments.callee.caller
* to work out which function is the callback.
*
* @param url {String} URL of external script
* @param obj {String} The name of a function or variable
* within the external script to test for.
* @license: Creative Commons License -
* ShareAlike http://creativecommons.org/licenses/by-sa/3.0/
* @author Remy Sharp / leftlogic.com
*/
function waitingForScript(url, obj) {
// doesn't work in Opera
var callback = arguments.callee.caller;
var args = arguments.callee.caller.arguments;
var s, ok, timer, doc = document;
// if the object/function doesn't exist and we've not tried to load it
// then pull it in and fire the calling function once complete
if ((typeof window[obj] == 'undefined') && !window['loading' + obj]) {
window['loading' + obj] = true;
if (!doc.getElementById('_' + obj)) {
s = doc.createElement('script');
s.src = url;
s.id = '_' + obj;
doc.body.appendChild(s);
}
timer = setInterval(function () {
ok = false;
try {
ok = (typeof window[obj] != 'undefined');
} catch (e) {}
if (ok) {
clearInterval(timer);
callback.apply(this);
}
}, 10);
// we're loading in the script now, so we're currently waiting
return true;
} else if (typeof window[obj] == 'undefined') {
// object not defined yet, so we're still waiting
return true;
} else {
// it's already loaded
return false;
}
}
Usage
function MyFunction() {
console.log('Testing whether jQuery is loaded (' + !!(typeof jQuery == 'function') + ')');
if (waitingForScript('http://jquery.com/src/jquery-latest.js', 'jQuery')) return;
console.log('Do some action with jQuery');
}
MyFunction("arg1", { "arg" : "two" });
You should follow me on Twitter here I'll tweet about JavaScript, HTML 5 and other such gems (amongst usual tweet-splurges)


Hi,
this is a nice concept you developed.
Coincidentally I developed something similar about two weeks ago. Though it works slightly different in that it is supposed to load a number of scripts based on dependancy without having to care about urls.
I'd also argue that your code is a bit hard to read, especially the last if else block.
Other than that, great work and interesting concept.
Dynamically loading external Javscript Files
Some weeks ago I read a short tutorial over at JavaScript Kit about how to load JavaScript files into your document on demand. This was a thought that I already pursued for some time as I had seen something similar already in the Scriptaculous Library....
This isn't the same technique as the link your provided.
What you read at JavaScript Kit was how to inject a script in to the DOM. This is simple stuff.
What the code above does, that's fundamentally different is that it doesn't proceed with anything until that script (or module) is in place.
I know that Dojo have some kind of 'import' method for script, and I suspect this is done using synchronous Ajax requests (i.e. ones that block) (I could well be wrong) - but this script does that job over any domain.
True, I should have pointed out the difference in your approach a little bit more. Especially the callback part.
But if you read it you might have noticed that I also stated
Though writing that I was working on the same idea was poor wording on my end.
Long story short...
This is great concept and I'd like to create a synergy between the two approaches and to improve upon the idea.
Keep up the good work here.
Remy, how did you manage to format the code in this post that way? (i mean non-pre one)
@Yansky - I've putting together a short post that explains a bunch of different ways to get this done. Should be the next few days.
Hi,
this post saved me some time - good approach and done nicely. Thanks
Not sure why you would write this function in such a complex way, but I see essentially it tests for the existence of an object. What if the script if partially loaded, and the object is defined, yet the script has not finished loading? Is this possible?
@Peru - it's probably more complicated than you expect because we have to find a way to block in JavaScript until the object is loaded. The way I'm doing this is with a timeout, but the single executed thread continues - so we're capturing the calling function and arguments to recall it later on.
Since JavaScript is single threaded, this won't happen. Once the object starts loading, it won't release resource to run some other script until it's finished. So, depending on how the object loading script is written (i.e. it doesn't contain timeouts to load data later on), the object will always be completely loaded.