Dynamically load JS inside JS [duplicate]
Solution 1:
My guess is that in your DOM-only solution you did something like:
var script = document.createElement('script');
script.src = something;
//do stuff with the script
First of all, that won't work because the script is not added to the document tree, so it won't be loaded. Furthermore, even when you do, execution of javascript continues while the other script is loading, so its content will not be available to you until that script is fully loaded.
You can listen to the script's load
event, and do things with the results as you would. So:
var script = document.createElement('script');
script.onload = function () {
//do stuff with the script
};
script.src = something;
document.head.appendChild(script); //or something of the likes
Solution 2:
jQuery's $.getScript()
is buggy sometimes, so I use my own implementation of it like:
jQuery.loadScript = function (url, callback) {
jQuery.ajax({
url: url,
dataType: 'script',
success: callback,
async: true
});
}
and use it like:
if (typeof someObject == 'undefined') $.loadScript('url_to_someScript.js', function(){
//Stuff to do after someScript has loaded
});
Solution 3:
I need to do this frequently, so I use this:
var loadJS = function(url, implementationCode, location){
//url is URL of external file, implementationCode is the code
//to be called from the file, location is the location to
//insert the <script> element
var scriptTag = document.createElement('script');
scriptTag.src = url;
scriptTag.onload = implementationCode;
scriptTag.onreadystatechange = implementationCode;
location.appendChild(scriptTag);
};
var yourCodeToBeCalled = function(){
//your code goes here
}
loadJS('yourcode.js', yourCodeToBeCalled, document.body);
For more information, see this site How do I include a JavaScript file in another JavaScript file?, which is the source of my function idea.
Solution 4:
You may dynamically load the js inside the page not another js file.
You have to use the getScript to load the js file.
$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
console.log(data); // data returned
console.log(textStatus); // success
console.log(jqxhr.status); // 200
console.log('Load was performed.');
});
Solution 5:
Necromancing.
I use this to load dependant scripts;
it works with IE8+ without adding any dependency on another library like jQuery !
var cScriptLoader = (function ()
{
function cScriptLoader(files)
{
var _this = this;
this.log = function (t)
{
console.log("ScriptLoader: " + t);
};
this.withNoCache = function (filename)
{
if (filename.indexOf("?") === -1)
filename += "?no_cache=" + new Date().getTime();
else
filename += "&no_cache=" + new Date().getTime();
return filename;
};
this.loadStyle = function (filename)
{
// HTMLLinkElement
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = _this.withNoCache(filename);
_this.log('Loading style ' + filename);
link.onload = function ()
{
_this.log('Loaded style "' + filename + '".');
};
link.onerror = function ()
{
_this.log('Error loading style "' + filename + '".');
};
_this.m_head.appendChild(link);
};
this.loadScript = function (i)
{
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = _this.withNoCache(_this.m_js_files[i]);
var loadNextScript = function ()
{
if (i + 1 < _this.m_js_files.length)
{
_this.loadScript(i + 1);
}
};
script.onload = function ()
{
_this.log('Loaded script "' + _this.m_js_files[i] + '".');
loadNextScript();
};
script.onerror = function ()
{
_this.log('Error loading script "' + _this.m_js_files[i] + '".');
loadNextScript();
};
_this.log('Loading script "' + _this.m_js_files[i] + '".');
_this.m_head.appendChild(script);
};
this.loadFiles = function ()
{
// this.log(this.m_css_files);
// this.log(this.m_js_files);
for (var i = 0; i < _this.m_css_files.length; ++i)
_this.loadStyle(_this.m_css_files[i]);
_this.loadScript(0);
};
this.m_js_files = [];
this.m_css_files = [];
this.m_head = document.getElementsByTagName("head")[0];
// this.m_head = document.head; // IE9+ only
function endsWith(str, suffix)
{
if (str === null || suffix === null)
return false;
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
for (var i = 0; i < files.length; ++i)
{
if (endsWith(files[i], ".css"))
{
this.m_css_files.push(files[i]);
}
else if (endsWith(files[i], ".js"))
{
this.m_js_files.push(files[i]);
}
else
this.log('Error unknown filetype "' + files[i] + '".');
}
}
return cScriptLoader;
})();
var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();
If you are interested in the typescript-version used to create this:
class cScriptLoader {
private m_js_files: string[];
private m_css_files: string[];
private m_head:HTMLHeadElement;
private log = (t:any) =>
{
console.log("ScriptLoader: " + t);
}
constructor(files: string[]) {
this.m_js_files = [];
this.m_css_files = [];
this.m_head = document.getElementsByTagName("head")[0];
// this.m_head = document.head; // IE9+ only
function endsWith(str:string, suffix:string):boolean
{
if(str === null || suffix === null)
return false;
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
for(let i:number = 0; i < files.length; ++i)
{
if(endsWith(files[i], ".css"))
{
this.m_css_files.push(files[i]);
}
else if(endsWith(files[i], ".js"))
{
this.m_js_files.push(files[i]);
}
else
this.log('Error unknown filetype "' + files[i] +'".');
}
}
public withNoCache = (filename:string):string =>
{
if(filename.indexOf("?") === -1)
filename += "?no_cache=" + new Date().getTime();
else
filename += "&no_cache=" + new Date().getTime();
return filename;
}
public loadStyle = (filename:string) =>
{
// HTMLLinkElement
let link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = this.withNoCache(filename);
this.log('Loading style ' + filename);
link.onload = () =>
{
this.log('Loaded style "' + filename + '".');
};
link.onerror = () =>
{
this.log('Error loading style "' + filename + '".');
};
this.m_head.appendChild(link);
}
public loadScript = (i:number) =>
{
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = this.withNoCache(this.m_js_files[i]);
var loadNextScript = () =>
{
if (i + 1 < this.m_js_files.length)
{
this.loadScript(i + 1);
}
}
script.onload = () =>
{
this.log('Loaded script "' + this.m_js_files[i] + '".');
loadNextScript();
};
script.onerror = () =>
{
this.log('Error loading script "' + this.m_js_files[i] + '".');
loadNextScript();
};
this.log('Loading script "' + this.m_js_files[i] + '".');
this.m_head.appendChild(script);
}
public loadFiles = () =>
{
// this.log(this.m_css_files);
// this.log(this.m_js_files);
for(let i:number = 0; i < this.m_css_files.length; ++i)
this.loadStyle(this.m_css_files[i])
this.loadScript(0);
}
}
var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();
If it's to load a dynamic list of scripts, write the scripts into an attribute, such as data-main, e.g.
<script src="scriptloader.js" data-main="file1.js,file2.js,file3.js,etc." ></script>
and do a element.getAttribute("data-main").split(',')
such as
var target = document.currentScript || (function() {
var scripts = document.getElementsByTagName('script');
// Note: this is for IE as IE doesn't support currentScript
// this does not work if you have deferred loading with async
// e.g. <script src="..." async="async" ></script>
// https://web.archive.org/web/20180618155601/https://www.w3schools.com/TAgs/att_script_async.asp
return scripts[scripts.length - 1];
})();
target.getAttribute("data-main").split(',')
to obtain the list.