Plaxo’s Joseph Smarr has been playing with on-demand javascript, i.e. downloading extra JS code after the page has already loaded. When you grab the code via a remote call and eval() it, it doesn’t get into global scope. So here’s how he dealt with it.
Here’s a simplified version of the situation we faced:
function loadMyFuncModule() {
// imagine this was loaded via XHR/etc
var code = 'function myFunc() { alert(\"myFunc\"); }';
return eval(code); // doesn’t work in FF or IE
}
function runApp() {
loadMyFuncModule(); // load extra code “on demand”
myFunc(); // execute newly loaded code
}The thing to note above is that just calling eval() doesn’t stick the code in global scope in either browser. Dojo’s loader code solves this in Firefox by creating a dj_global variable that points to the global scope and then calling eval on dj_global if possible:
function loadMyFuncModule() {
// imagine this was loaded via XHR/etc
var code = 'function myFunc() { alert(\"myFunc\"); }';
var dj_global = this; // global scope object
return dj_global.eval ? dj_global.eval(code) : eval(code);
}This works in Firefox but not in IE (eval is not an object method in IE). So what to do? The answer turns out to be that you can use a proprietary IE method
window.execScriptto eval code in the global scope (thanks to Ryan “Roger” Moore on our team for figuring this out). The only thing to note about execScript is that it does NOT return any value (unlike eval). However when we’re just loading code on-demand, we aren’t returning anything so this doesn’t matter.The final working code looks like this:
function loadMyFuncModule() {
var dj_global = this; // global scope reference
if (window.execScript) {
window.execScript(code); // eval in global scope for IE
return null; // execScript doesn’t return anything
}
return dj_global.eval ? dj_global.eval(code) : eval(code);
}
function runApp() {
loadMyFuncModule(); // load extra code “on demand”
myFunc(); // execute newly loaded code
}And once again all is well in the world.
