error loading javascript files dynamically - javascript

i am trying to lazy (dynamically) load javascript files in my webpage.
i have used this :
http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
loadjscssfile("myscript1.js", "js") //dynamically load and add this .js file
loadjscssfile("myscript2.js", "js") //dynamically load and add this .js file
loadjscssfile("myscript3.js", "js") //dynamically load and add this .js file
these 3 script are to be loaded in a sequence.
myscript3 is dependent on myscript2
and myscript2 is dependent on myscript1.
trying to load it in this way is behaving wierdly.
Looks like these are not loaded in the sequence intended and hence
undefined errors are thrown at times and at times no error are thrown.
Am i doing something wrong.
Updated :
I am using this code to load the files in the correct sequence
function loadjscssfile(filename, filetype) {
if (filetype == "js") { //if filename is a external JavaScript file
var fileref = document.createElement('script')
fileref.setAttribute("type", "text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype == "css") { //if filename is an external CSS file
var fileref = document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
return fileref;
}
function loadSync(files, types) {
if (typeof (files[0]) === 'undefined') return false;
var script = loadjscssfile(files[0], types[0]);
script.onload = function () {
files.shift();
types.shift();
loadSync(files, types);
}
if (typeof script != "undefined")
document.getElementsByTagName("head")[0].appendChild(script)
}
loadSync(['scripts/module3.base.js', 'scripts/module3.core.js', 'scripts/module3.init.js'], ['js', 'js', 'js']);
console.log('this should get printed when all the three files are loaded');
But the console output is :
this should get printed when all the three files are loaded
scripts/module3.base.js:9 base is initialised
scripts/module3.core.js:6 core is initialised
scripts/module3.init.js:3 app is initialsed
Looks like the first call to loadSync is itself an Asynchronous call

There are open source js which will ease your problem.
You can use LABJS or RequreJS plugins.
Script loaders like LABJS, RequireJS will improve the speed and quality of your code.
You can preserve order of loading your script like this in LABJS.
$LAB.setOptions({AlwaysPreserveOrder:true})
.script("script1.js")
.script("script2.js")
OR
$LAB
.script("script1.js").wait()
.script("script2.js")
script2.js will wait untill script1.js is loaded.
I guess this will solve your problem.

For HTML5 just use async attribute ( info at http://davidwalsh.name/html5-async )
Example of function for loading script with a optional callback option
function loadScript(url, callback) {
if (!callback) callback = function () {};
var script = document.createElement("script")
script.type = "text/javascript";
script.setAttribute("async", "true");
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
For a mixed solution:
function loadjscssfile(url, type, callback) {
if (!type) {
type = "js";
}
var node;
if (type === "js") {
var node = document.createElement("script")
node.setAttribute("async", "true");
node.type = "text/javascript";
if (node.readyState){ //IE
node.onreadystatechange = function(){
if (node.readyState == "loaded" ||
node.readyState == "complete"){
node.onreadystatechange = null;
callback();
}
};
} else { //Others
node.onload = function(){
callback();
};
}
node.src = url;
} else if (type === "css") {
var node = document.createElement("link")
node.type = "text/css";
node.setAttribute("rel", "stylesheet");
node.setAttribute("async", "true");
if (node.readyState){ //IE
node.onreadystatechange = function(){
if (node.readyState == "loaded" ||
node.readyState == "complete"){
node.onreadystatechange = null;
callback();
}
};
} else { //Others
node.onload = function(){
callback();
};
}
node.href = url;
}
if (node) {
document.getElementsByTagName("head")[0].appendChild(node);
} else {
callback(new Error("File not found"));
}
}
Loading a list of files
function loadjscssfileList(arr_original, callback) {
var arr = [];
arr_original.forEach(function (v) {
arr.push(v);
});
var next = function () {
if (arr.length) {
var file = arr.shift();
loadjscssfile(file[0], file[1], function () {
next();
});
} else {
callback();
}
};
next();
};
// use without callback
loadjscssfileList([
["myscript.js","js"],
["style.css","css"],
["myscript2.js","js"]
]);
// use with callback
loadjscssfileList([
["myscript.js","js"],
["style.css","css"],
["myscript2.js","js"]
], function () {
alert("loaded")
});

you can load them synchronously.
function get_contents(file){
var xhr = new XMLHttpRequest();
xhr.open('get', file, false);
xhr.send();
return xhr.responseText;
}
function loadjscssfile(filename, filetype){
var content = get_contents(filename);
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.innerHTML = content;
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.innerHTML = content;
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
To load it externally:
there're 2 ways:
Callback as the another answer.
Or you can do this:
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
return fileref;
}
function loadSync(files,types){
if(files[0] === 'undefined')return false; //if there's no files to load
var script = loadjscssfile(files[0],types[0]); //load first file
script.onload = function(){//after the script is loaded delete them and continue;
files.shift();
types.shift();
loadSync(files,types);
}
if (typeof script !="undefined")
document.getElementsByTagName("head")[0].appendChild(script)
}
loadSync(["myscript1.js","myscript2.js","myscript3.js"],['js','js','js']);

Related

Ajax content not loading in IE throws 'error on page - access is denied' error but works fine on server

I made a tool for my organization which loads html pages into one main html file(through AJAX) on choosing an option from a select list. Each selection loads a different html file.
Things looked good when I tested it from home. When I opened it through IE8 from office (no other browser is allowed - plain stupid) all hell broke loose. First it messed up the layout reason being the organization's intranet. I had to use,
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
This solved the layout problem still the Ajax won't load. Which is the very basic thing for this tool to work. I tried using Msxml2.XMLHTTP / Microsoft.XMLHTTP instead of XMLHttpRequest - it wouldn't work. Would someone be kind enough to help me with this? Here's the code:
<script type="text/javascript">
var loadedobjects = ""
var rootdomain = "http://" + window.location.hostname
function ajaxpage(url, containerid) {
var page_request = false
if (window.XMLHttpRequest) // if Mozilla, Safari etc
page_request = new XMLHttpRequest()
else if (window.ActiveXObject) { // if IE
try {
page_request = new ActiveXObject("Msxml2.XMLHTTP")
}
catch (e) {
try {
page_request = new ActiveXObject("Microsoft.XMLHTTP")
}
catch (e) {}
}
}
else
return false
page_request.onreadystatechange = function() {
loadpage(page_request, containerid)
}
page_request.open('GET', url, true)
page_request.send(null)
}
function loadpage(page_request, containerid) {
if (page_request.readyState == 4 &&
(page_request.status == 200 || window.location.href.indexOf("http") == -1))
document.getElementById(containerid).innerHTML=page_request.responseText
}
function loadobjs() {
if (!document.getElementById)
return
for (i = 0; i < arguments.length; i++) {
var file = arguments[i]
var fileref = ""
if (loadedobjects.indexOf(file) == -1) { // Check to see if this object has not already been added to page before proceeding
if (file.indexOf(".js") != -1) { // If object is a js file
fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", file);
}
else if (file.indexOf(".css") !=-1 ) { // If object is a css file
fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", file);
}
}
if (fileref != "") {
document.getElementsByTagName("head").item(0).appendChild(fileref)
loadedobjects += file + " " // Remember this object as being already added to page
}
}
}
</script>

load external javascript only when needed

I have reference to bunch of javascript file on my page which are used by different functions calls.
When I load the page, first all external JS files get loaded.
Is there anyway so that they get called only when function call occurs for that .js file?
You can add your conditions to this method, which allows you to dynamically add an external javascript file:
function loadScript(url, callback){
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
By using JQuery
$.getScript("//platform.twitter.com/widgets.js")
No simple way for get JS fyle for function "on-fly". Also, for load file for function system need some time. May be good solution will using minification for JS-files?
You may try some as this.
loadExternalScriptFile = function(filename, callback) {
var fileref = document.createElement("script");
if (fileref){
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filename);
fileref.onload = callback;
if (typeof fileref != "undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
}
var functionMap = {
'function1': 'js/f1.js',
'function2': 'js/f1.js',
'function3': 'js/f3.js'
};
function checkFunction(functionName, callback) {
if (typeof window[functionName] !== 'function') {
loadExternalScriptFile(functionMap[functionName], callback);
return;
}
callback();
return;
}
//Using
checkFunction('function1', function(){
function1(params);
});
But i think loading all in minification version and single file is better.

Delay callback until script is added to document?

How can I get the callback to not run until the script is actually appended to the document?
function addScript(filepath, callback){
if (filepath) {
var fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filepath);
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
if (callback) {
callback();
}
}
In the ideal world, you could use the onload property of the <script /> tag;
function addScript(filepath, callback){
if (filepath) {
var fileref = document.createElement('script');
fileref.onload = callback;
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filepath);
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
}
However, this doesn't work in IE, so mega-h4x are required;
function addScript(filepath, callback) {
if (filepath) {
var fileref = document.createElement('script');
var done = false;
var head = document.getElementsByTagName("head")[0];
fileref.onload = fileref.onreadystatechange = function () {
if (!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
done = true;
callback();
// Handle memory leak in IE
fileref.onload = fileref.onreadystatechange = null;
if (head && fileref.parentNode) {
head.removeChild(fileref);
}
}
};
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filepath);
head.appendChild(fileref);
}
}
FWIW, your if (typeof fileref != "undefined") was redundant, as it will always evaluate to true, so you can just do head.appendChild(fileref); directly, as in my example.
what about:
var myParticularCallback = function () {
// do something neat ...
}
..... your code
var fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.onload = myParticularCallback;
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
// after all has set, laod the script and wait for onload event:
fileref.setAttribute("src", filepath);
This tiny script / css loader will do the job
https://github.com/rgrove/lazyload/
LazyLoad.js('/foo.js', function () {
alert('foo.js has been loaded');
});
Easiest way will be define some visible callback() function which will run in your dynamicly included script, at the end.

Check if script is loaded already. If not, load it asynchronously

I'm trying to load the jQuery JS asynchronously and then i want to call some callback methods when it is completely loaded.
I might be using the same code block over and over again. So i want to check if jQuery(or any other script) is already added before actually adding it.If it is already loaded/loading, then the callback of the current call should be appended to that of the previous call. This is what i'm trying to do.
/*BP Asynchronous JavaScript Loader*/
if (typeof bp_onload_queue == 'undefined') var bp_onload_queue = [];
if (typeof bp_dom_loaded == 'boolean') bp_dom_loaded = false;
else var bp_dom_loaded = false;
if (typeof bp_async_loader != 'function') {
function bp_async_loader(src, callback, id) {
var script = document.createElement('script');
script.type = "text/javascript";
script.async = true;
script.src = src;
script.id = id;
//Check if script previously loaded.
var previous_script = document.getElementById(id);
if (previous_script) if (previous_script.readyState == "loaded" || previous_script.readyState == "complete") {
callback();
alert("had already loaded the same script completely");
return;
} else {
script = previous_script;
}
if (script.onload != null) previous_callback = script.onload;
script.onload = script.onreadystatechange = function() {
var newcallback;
if (previous_script && previous_callback) newcallback = function() {
previous_callback();
callback();
};
else newcallback = callback;
if (bp_dom_loaded) {
newcallback();
} else bp_onload_queue.push(newcallback);
// clean up for IE and Opera
script.onload = null;
script.onreadystatechange = null;
};
var head = document.getElementsByTagName('head')[0];
if (!previous_script) head.appendChild(script);
else alert("had already started loading that script but not complete.so we appended to the previous script's callback");
}
}
if (typeof bp_domLoaded != 'function') function bp_domLoaded(callback) {
bp_dom_loaded = true;
var len = bp_onload_queue.length;
for (var i = 0; i < len; i++) {
bp_onload_queue[i]();
}
}
/*JS gets loaded here */
bp_domLoaded();
/*Loading jQuery Asynchronously */
bp_async_loader("http://code.jquery.com/jquery-1.4.4.js", function() {
alert("script has been loaded : 1");
}, "jQueryjs");
bp_async_loader("http://code.jquery.com/jquery-1.4.4.js", function() {
alert("script has been loaded : 2");
}, "jQueryjs");
Can someone please let me know if there are any errors in this code or if there is a better way of doing this?
I was searching for something similar and found this
http://themergency.com/an-alternative-to-jquerys-getscript-function/

Load jQuery, wait

I need to dynamically load jQuery and jQuery UI from a javascript, then check if it has loaded and do something afterwards.
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filename);
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", filename);
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
loadjscssfile("http://localhost/js/jquery-1.3.2.min.js", "js");
loadjscssfile("http://localhost/js/jquery-ui-1.7.2.custom.min.js", "js");
I have done some research and found that I need to either use a callback or a settimeout. Trouble is I'm really new in javascript and it's really giving me a hard time. Can anyone set me in the right direction please?
I've never had to do this myself, but presumably you could just use a repeating timeout to check for presence of the needed objects:
function jqueryLoaded() {
//do stuff
}
function checkJquery() {
if (window.jQuery && jQuery.ui) {
jqueryLoaded();
} else {
window.setTimeout(checkJquery, 100);
}
}
checkJquery();
I'm pretty sure that the window.onload() function should trigger when all scripts are loaded. And you don't need to bind stuff to the 'ready' event in jQuery.
loadjscssfile("http://localhost/js/jquery-1.3.2.min.js", "js");
loadjscssfile("http://localhost/js/jquery-ui-1.7.2.custom.min.js", "js");
window.onload = function() {
if(window.jQuery && jQuery.ui) {
alert('loaded');
}
}

Categories

Resources