atlasgp
02-01-2010, 08:09 PM
Given an html page which loads usin a dynamic script tag as follows:
<script type="text/javascript" src="code1.js"></script>
If I load a dynamic script with the code1.js file using createElement:
script = document.createElement("script")
script.setAttribute("type", "text/javascript")
script.setAttribute("src", "code2.js")
document.getElementsByTagName("head")[0].appendChild(script)
The order of events is as follows:
code1.js executes, loads script onto dom, code2.js then executes. My reading let me to believe that regardless of how the browser loads the script files ( in parallel or synchronously ), the dom would interpret each node in order, thus the code in code2.js executes after code1.js finishes.
However, this is not the case if the script I load is an inline script ( not loading via the src attribute ):
script = document.createElement("script")
script.setAttribute("type", "text/javascript")
script.text = "MyFunction();";
document.getElementsByTagName("head")[0].appendChild(script)
The behavior with the above dom element added is as follows:
code1.js executes, as soon as I add the script element with the inline 'MyFunction' call it immediately executes, finally code1.js finishes executing. So, even though I added a script tag at the end of the dom, it executed ( interpreted ) the contents of the tag immediately. Is this correct? How can I ensure that script tag 2 executes AFTER script tag one? I tested this with IE8 and Mozilla 3.5 and obviously I'm not understanding how the interpreter analyses the code. Any help is appreciated.
TinyScript
02-02-2010, 02:27 AM
http://www.websiteoptimization.com/speed/tweak/defer/
I'm not sure if this helps. I thought I remember seeing this do what you want, but I could very easily be wrong.
I'd try giving the script tag an id and then have the second script load using the id.onload as the trigger
var thefirstscript=document.getElementById("scriptID")
thefirstscript.onload=function(){loadsecondscript()}
Not sure if it will work without seeing your scripts. I know I've seen scripts added after page load, but I'm not sure if you can load them to the head without having to reload the page also.
Best of luck. Hope this helped
rnd me
02-02-2010, 05:44 AM
How can I ensure that script tag 2 executes AFTER script tag one?
hard-coded <script> tags (internal or external) fire one-at-a-time. Everything else in the loading processes freezes until that script tag is parsed and executed.
when you add a script with the dom, it does NOT block the browser's loading process. This is essiantially the same as a defer attrib, which also tells the browser "don't wait on my behalf".
there are lots of ways around this issue.
i won't elaborate because you can find details with google, or by asking a follow-up question.
1. hard-code your script tags instead of injecting them.
2. use document.write() instead of createElement/dom
Printing a script tag with document.write DOES block the browser. The major shortcoming of this method is that it can only be used while the page is loading. Using it after window.onload() fires will kill the whole page.
function addJS2(url){
document.write(" <script type='text/javascript' src='"+url+"'><\/script> ");
}
3. chain them together by altering each script file.
Include a line to call the "next" script at the bottom of each script:
script1.js
addJS("script2.js");
4. Look for smoking guns from the other file.
This is especially useful when you cannot modify the source code of a dependent file.
for example, the green code needs jquery to run:
(function _pageLoad(){
if(!window.jQuery ){
window.setTimeout( _pageLoad , 20);
return;
}//end if jQuery
var $=jQuery; //just in case
$(".accessibility, .hivis").hide().attr("aria-hidden","true");
}());//end _pageLoad
by using this wait-and-see approach, it can sense when jQuery is available, and keep the code from executing until jQuery is ready.
5. use script tag events.
script.onload() works in good browsers.
IE's script tags have a .readyState that can be monitored using their .onreadystatechange() event.
Using these events, uou can tell when a script loads, allowing you opportunity to call a delayed function, add another script, etc.
6. go centralized.
combine the above techniques into a common class than can be re-used on all your projects.
Wrap each script file's code in a wrapper function: this allows you to have script code without executing it.
Place a header in every javascript file that "checks in" the script when it arrives.
This centralized loader manages dependencies, memorizes incoming scripts for re-use (by grabbing the wrapper function's .toString() value), dispatches scripts on demand, and organizes your files into a collection you can iterate.
i won't post the code you need to do all that, but after trying everything else i could find to load javascript on-demand, i think a centralized loader tool is the way to go for non-small projects.
here is a redacted example of the header syntax i am using for my new CMS.
every module's .js file has a header like this:
App.loadModule({
name: "tabbed",
group: "widgets",
css: [],
keys: {right:"next", left:"prev", "escape":"exit"},
init: function Tabbed(mod){
// tab widget code goes inside here
});//end Tabbed container module
App.loadModule does a lot of things, i mention the most generic.
the other key to this approach is having a good depends library.
you need to know the file, the dependencies, and a common name.
App.widgets={
tabbed:{
name: "tabbed",
file: "widget-tabs.js",
ver: "0.902",
requires: ["jQuery","ARIA"],
hit: ".tabbed" },
accordion:{
name: "accordion",
file: "widget-accordion.js",
ver: "0.900",
requires: ["jQuery","ARIA"],
hit: ".accordion" }
};//end widget def
i use the .hit property to determine if a page needs the module to be loaded.
i use the version (.ver) so i can persist any widget's source code on the client without getting out-of-sync weeks later.
as you can see, a centralized loader offer several advantages to simpler methods.
It also takes more work to build the script's json db and modularize your files.
The tabbed file knows it need jquery and the ARIA library.
App.loadModule can have the code in tabbed.js wait around for a while until ARIA loads, allowing true async script loading.
The size of your project will determine which is best/needed.
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.