NOT A DUPLICATE AS I HAVE YET TO FOUND A SATISFYING ANSWER ON OTHER THREADS:
Ok, I think I have now came up with a solution.
The trick is that we keep track of each script to be loaded and their order as we insert them into the dom tree. Each of their callback is then registered accordingly to their element.
Then we keep track of when all has finished loading and when they all have, we go through the stack and fire their callbacks.
var stack = [];
stack.loaded = 0;
function loadScriptNew(path, callback) {
var o = { callback: callback };
stack.push(o);
loadScript(path, function() {
o.callbackArgs = arguments;
stack.loaded++;
executeWhenReady();
});
}
function executeWhenReady() {
if ( stack.length == stack.loaded ) {
while(stack.length) {
var o = stack.pop();
o.callback.apply(undefined, o.callbackArgs);
}
stack.loaded = 0;
}
}
// The above is what has been added to the code in the question.
function loadScript(path, callback) {
var element = document.createElement('script');
element.setAttribute("type", 'text/javascript');
element.setAttribute("src", path);
return loadElement(element, callback);
}
function loadElement(element, callback) {
element.setAttribute("defer", "");
// element.setAttribute("async", "false");
element.loaded = false;
if (element.readyState){ // IE
element.onreadystatechange = function(){
if (element.readyState == "loaded" || element.readyState == "complete"){
element.onreadystatechange = null;
loadElementOnLoad(element, callback);
}
};
} else { // Others
element.onload = function() {
loadElementOnLoad(element, callback);
};
}
(document.head || document.getElementsByTagName('head')[0] || document.body).appendChild(element);
return element;
}
function loadElementOnLoad(element, callback) {
if (element.loaded != true) {
element.loaded = true;
if ( callback ) callback(element);
}
}
loadScriptNew("http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js",function() {
alert(1);
});
loadScriptNew("http://ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js",function() {
alert(2);
});
Ok, some of you might argue that there is missing info in the question, which I will give you and here we are actually just solving the callback. You are right. The code in the script is still executed in the wrong order, but the callback is now.
But for me this is good enough, as I intend to wrap all code that is loaded in a method call, alá AMD, such as a require or define call and will put on stack there, and then fire them in the callback instead.
I am still hoping out for Asad and his iframe solution, which I believe might provide the best answer to this question. For me though, this solution will solve my problems :)