...

View Full Version : Best way to test for a script load



Forever Zero
06-19-2008, 07:48 PM
This is related to my previous post yesterday, but this issue is different than the one that post was about, so I decided to make a new thread. If they need to be merged, please feel free.

So, I wrote this function to load up a JS file hosted on my remote web server into the DOM (this is for a Firefox extension if you're wondering why).


function loadScript(scriptURL) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptURL;
head.appendChild(script);

// Function to check if the JS has been loaded yet
function waitForLoad() {
if(typeof testFunction != 'function') {
var t=setTimeout("waitForLoad()",100);
} else {
return true;
}
} // waitForLoad

waitForLoad();
} // loadScript


'rnd me' gave an example where I could use a local variable at the end of the script instead of a testFunction(), and just check to see if that variable is initialized instead. I was planning on changing it to do this, but figured I should wait until I see what people say about this.

Anyways, so that code above works 100% fine. The problem comes from my having to use this loadScript function to inject nine scripts. This means that the test case in waitForLoad() is broken.

Does anyone know a way that I can use to check if a script has been loaded, that does not depend on a certain method or variable within the script? Or maybe someone can suggest just any way of going about doing this?

Any help would be appreciated :)

Trinithis
06-19-2008, 08:54 PM
1) I think your scripts are loaded synchronously. That is, they will load in the order that your code loads them (after the current script is finished loaded). In that case, after you load all your scripts, load an extra "helper" script, and have him do the magic, since the others will have to be loaded by the time he is loaded. Try this, I think it will work. Aka:



// loader script file.

importScript("abc.js");
importScript("def.js");
importScript("ghi.js");
importScript("mainScript.js");


2) Use AJAX (I'm no expert at it though).

Trinithis
06-19-2008, 09:03 PM
I made this a long while ago. Not sure if it is good ajax scripting, but who knows. If I remember correctly, it worked for me.



var Importer = {
importedFiles: {},
protocol: /^\s*\w+:\/\//,
ajaxWarning: "Your browser does not support AJAX.\nYou can update your browser to get AJAX support.",
directory: window.location.href.replace(/[^\/\\]+$/, ""),
include: function(uri) {
if(!this.protocol.test(uri))
uri = this.directory + uri;
if(this.importedFiles[uri])
return;
this.importedFiles[uri] = true;
var req = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
if(!req) {
if(this.ajaxWarning !== false)
alert(this.ajaxWarning);
this.ajaxWarning = false;
return;
}
req.open("GET", uri, false);
req.send(null);
if(!window.execScript)
window.eval(req.responseText);
else
window.execScript(req.responseText);
}
};


Usage:


Importer.load("abc.js");
abcFunc1();
Importer.load("def.js");
Importer.load("ghi.js");
defFunc10();
ghiFunc4();

Forever Zero
06-19-2008, 09:03 PM
Thanks, that's really good to know.

What I got from what you said is that since they are loaded synchronously, I only need to run the waitForLoad() function on the very last script. Is that about right?

Also, about the AJAX, I would actually much rather do this, but the problem is that AJAX doesn't seem to support cross-domains. This script is for a Firefox extension I am writing, where it needs to inject some JS files to make highlighted words pop up a window when you hover over it that requires a load of JS files.

It might be possible though, maybe I should head on over to the AJAX forum :P

EDIT: Woah just saw your second post. I actually tried something like that first thing, but it kept giving me permissions denied errors. Is that code you posted able to take JS files off of either a local machine or a remote server and load them up on the current page? If it can, that would be amazing haha.

Thanks again!

Trinithis
06-19-2008, 09:13 PM
It was able to import files from my own computer, but when I tried using it to import a script from a (free) host, the host denied it. If this is just for personal use, then it should work fine if you store all your files on your own computer.

I'm not sure if it would suit your purposes, but have you heard of Greasemonkey (http://wiki.greasespot.net/Main_Page)?

Forever Zero
06-19-2008, 09:16 PM
If this can import files from your computer that is actually even better.

I was actually looking at the Greasemonkey source to try and see how they did it, but it was mind boggling for me haha (just started learning JS a week ago). One of their developers was nice enough to give me some answers, but I didn't want to bog them down with endless questions haha.

I'm gonna try out the AJAX script you posted and post the result in this thread after I mess around with it some.

Trinithis
06-19-2008, 09:23 PM
Just be sure to change the default directory value if it isn't appropriate. It defaults to the directory of the Importer.js (or whatever you put it in).


Importer.directory = "dir1";
// do some loading
Importer.directory = "dir2";
// do some more loading
. . .

rnd me
06-19-2008, 10:59 PM
i use:

function JSget(turl) {
var xJs = document.createElement("script");
xJs.type = "text/javascript";
var h = document.getElementsByTagName("head");
if (h && h[0]) {
h[0].appendChild(xJs);
}
xJs.src = turl;
return xJs;
}


it works from any domain anywhere. (http:, https:, file:, data: )

you dont even need to wait for the last script, your browser will anyway. in other words, you shouldnt have to test for it.

further, you can put code in the body, and all the code in the head will be loaded and executed before it finds body scripts.

Forever Zero
06-20-2008, 03:42 PM
i use:

function JSget(turl) {
var xJs = document.createElement("script");
xJs.type = "text/javascript";
var h = document.getElementsByTagName("head");
if (h && h[0]) {
h[0].appendChild(xJs);
}
xJs.src = turl;
return xJs;
}


it works from any domain anywhere. (http:, https:, file:, data: )

you dont even need to wait for the last script, your browser will anyway. in other words, you shouldnt have to test for it.

further, you can put code in the body, and all the code in the head will be loaded and executed before it finds body scripts.

This worked perfectly, thank you! You've been really helpful :p


I made this a long while ago. Not sure if it is good ajax scripting, but who knows. If I remember correctly, it worked for me.



var Importer = {
importedFiles: {},
protocol: /^\s*\w+:\/\//,
ajaxWarning: "Your browser does not support AJAX.\nYou can update your browser to get AJAX support.",
directory: window.location.href.replace(/[^\/\\]+$/, ""),
include: function(uri) {
if(!this.protocol.test(uri))
uri = this.directory + uri;
if(this.importedFiles[uri])
return;
this.importedFiles[uri] = true;
var req = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
if(!req) {
if(this.ajaxWarning !== false)
alert(this.ajaxWarning);
this.ajaxWarning = false;
return;
}
req.open("GET", uri, false);
req.send(null);
if(!window.execScript)
window.eval(req.responseText);
else
window.execScript(req.responseText);
}
};


Usage:


Importer.load("abc.js");
abcFunc1();
Importer.load("def.js");
Importer.load("ghi.js");
defFunc10();
ghiFunc4();


I still want to try this out because I've been curious about AJAX for some time now. I have a few questions on that...

1. I saw you said the usage was Importer.load("blah.js"), where exactly is the load function in that script? Do you mean that I should create my own function called load and warp it around that? I also noticed that it gets the uri by passing it through what (looks to me like) an unnamed function: "include: function(uri) {" but I am still unsure how exactly the script obtains the uri to use.

2. What exactly is "protocol" here? protocol: /^\s*\w+:\/\//
Also, I noticed a lot of lines like that (that use a colon instead of equals), is this how you declare a variable inside an object? Or is that the syntax for something else?

3. I'm guessing that these lines here check for IE, but could you please clarify it?


var req = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");


I'll be messing around with it still, but I want to make sure that I fully understand the stuff I'm using :).

Trinithis
06-21-2008, 07:37 PM
1. Whoops. I the usage should be Importer.include, not Importer.load.

2. The protocol regex (not sure if its a good name for it) tests whether or not the file you are importing has a relative or an absolute path. If it has an absolute path, everything's okay. Otherwise, it tacks on the directory path to the beginning of the filename.

It does this by looking for things like http://, ftp://, file://, etc.

3.


var req = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");

IE (as we all know) is a piece of crap and does not conform to conventions. Instead of having XMLHttpRequest, it uses ActiveXObject.

Forever Zero
06-24-2008, 03:20 PM
Hey,

just wanted to say that I got your script working perfectly. I couldn't get it to do cross domain requests, but apparently if you call an XMLhttpRequest from inside a chrome window, it can go cross domain (go figure).

Thanks again for your help

EDIT: And for the record, yes, IE is a piece of crap :(



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum