Reputation: 5151
Not sure if this is the right approach of if this even a "good" question, but I'm loading a javscript as part of a plugin style architecture and I have the following problem:
If a particular node has a reference to a plugin, I want to load that plugin per the url provided via the json description of that plugin. the description will have something like the following (or a functional equivalent):
{
"pluginSrc" : "http://mysite.com/plugins/1204.js",
"configData" :
{
"someData", "someValue",
"someMoreData", "etc"
}
}
When the javascript loads, I'll have an onload handler that will check to see if a function name exists on the window object and if so, create a new instance of that function and pass it the config data (more or less), this part works very well, with a few exceptions.
Sometimes I do not have a reference to the name of the function that I need to invoke and there is no way to get it from the json. What would be ideal, is if I could tell which function was added to the window object on the script's onload callback and create an instance of that function. Is this possible? I only need to worry about modern browsers, particularly webkit. Apologies if the question isn't clear, I'd be happy to clarify, but producing a fiddle might be difficult as there's a lot of code to write to reach a minimal example.
What I'm thinking about so far is to create some kind of global variable in the loaded script file like
function MediaAnalytics(){};
var LoadedClass = MediaAnalytics;
and just creating an instance of LoadedClass when the script is loaded, but this falls short of a panacea because I will not always be writing the plugin.
EDIT: These scripts will most likely not be from the same domain.
Upvotes: 4
Views: 2200
Reputation: 25165
You haven't specified how you load the script file. I hope that you will get the script text in onload handler.
Anyway I am explaining how to do this using jQuery.getScript
. In this you will get the script text in success handler as data
. So you can use this to get the loaded Function.
Suppose the script file dynamic.js contains
function MediaAnalytics(){};
load it using getScript
$.getScript("dynamic.js", function (data, textStatus, jqxhr) {
var NewFunction;
eval("NewFunction = " + data);
alert(NewFunction.name); // here you will get alert showing MediaAnalytics
});
Here NewFunction
is MediaAnalytics
.
It will be the second execution of the script as getScript
invokes the success handler after executing it and adding it to window object. You can give new NewFunction()
to instantiate.
If you don't prefer using eval
, another way is using a RegEx to find the name of the Function
$.getScript("dynamic.js", function (data, textStatus, jqxhr) {
alert(data.match(/function(.*)\(/));
});
This will alert function MediaAnalytics( . match
returns an array. The name of the function can be retrieved from it.
You can use a better RegExp to extract the exact function name and get the property of window object.
EDIT: (no jquery)
Or you can load your script as text and add to window as a script tag in your onload handler. There you can use your trick even if the plugin-script is not yours.
var dynamicjs = "function MediaAnalytics(){};"; // script loaded as text
var modified = "LoadedClass = " + dynamicjs;
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.textContent= modified; // innerText in some browsers
head.appendChild(script);
alert(LoadedClass); // LoadedClass is MediaAnalytics
Upvotes: 3
Reputation: 43253
I would suggest making it required to have the entry-function's name in the json. It would be the least hacky way to go about it in my opinion.
However, something you could try would be to iterate all the properties of window
. If you find a new function in window
after loading the script, you could assume that's the one which just got loaded.
Something like this..
var windowMembers = [];
function loadScript() {
for(var m in window) {
windowMembers.push(m);
}
//load your new script
//some code here to load the script
//put an onload handler...
s.onload = function() {
for(var m in window) {
if(windowMembers.indexOf(m) == -1) {
//window[m] was added after the script loading began
//call it:
window[m]('blah blah');
}
}
}
}
To be safe you could optionally check if the new property is a function, eg.
if(typeof window[m] == 'function')
Upvotes: 1