Friday, July 06, 2007

Honnan tudjuk, hogy az utolag include-olt javascript mar betoltodott.

Viszonylag egyszeru utolag hozzaadni egy js filet az oldalunkhoz (1, 2), de ha rogton ezutan valamit hasznalni szeretnenk belole akkor az nem biztos, hogy menni fog, mert lehet, hogy meg nem toltodott be teljesen.

Stoyan (mar torolt) irasa szerint egy 1998-as MSDN cikkben talalkozott a readyState property-vel es azt hasznalva ez a kodreszlet IE-ben (csak ott!!) mukodik:

The idea is that after a new DOM element (a script tag) is created, you can have access to the readyState property of the element. If it says “complete”, then the new script is included and it’s OK to call functions from it. If you want to “listen” when the script download will be completed, you can attach an listener to the onreadystatechange event, just like with XMLHttpRequests.

Here’s an example:


var js;
function include_js(file) {
var html_doc = document.getElementsByTagName('head').item(0);
js = document.createElement('script');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', file);
html_doc.appendChild(js);

// alert state change
js.onreadystatechange = function () {
alert(js.readyState);


if (js.readyState == 'complete') {
// safe to call a function
// found in the new script
imready();
}
}
return false;
}

A commentek kozott Aaron Bassett egy masik megoldast javasolt, amihez modositani kell egy kicsit a betoltendo scripten (mar ha ez lehetseges), de szerinte minden browserben mukodik (bar nem probalta):

This untested but I dont see any reason why it wouldnt work, and should work across all browsers.

Right at the end of the external js file set a variable like:

var externalScriptLoaded = true;

Then in your main code you could use:


function checkScriptLoaded() {
if(!externalScriptLoaded) {
setTimout("checkScriptLoaded", 500);
} else {
// script loaded and ready to use
}
}

If you have multiple external files you want to check just make sure each has a unique variable name being set and check them accordingly.

This polling every half-second isnt perfect but it will work.

Your other option would be to create a function/method in your main script which inits the actions to perform when the external script is loaded.
Then as the very last thing in your external script you could just call that function/method

externalScripts.myScriptLoaded();

As this call would be at the end of your file it wont be run until the rest of the file ahead of it has been downloaded.

Once again this method is untested but am 99% sure will work and will be cross browser.