Load external javascript file after onload() - javascript

I use this in the head tag:
<script src="js/lightbox.js"></script>
Is it possible to remove this off the header and load this file with onload()?
<body onload="...">...</body>
Note: This is not a function, it's an external js file with several functions.
Thanks!

<script>
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('/script/script.js', function() {
// put your code here to run after script is loaded
});
</script>
I still think its better to load in jQuery and use $.getScript instead as you have lots of goodies there.
Can call this on body load

onload="blabla();"
function blabla()
{
$.getScript( 'url to your js file', function( data, textStatus, jqxhr ) {
// do some stuff after script is loaded
});
}
You can learn more here
Source

If you want to do it without jQuery, use this
function addScript(filename)
{
var scriptBlock=document.createElement('script')
scriptBlock.setAttribute("type","text/javascript")
scriptBlock.setAttribute("src", filename)
document.getElementsByTagName("head")[0].appendChild(scriptBlock)
}
and call it with <body onload="addScript('myFile.js')". If you have multiple files to load, you could put in a wrapper, that adds all the files you want.

Use $(document).ready()
and from this function load javascript. It sounds crazy but can be done. please follow http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml

var JS = {
load: function(src, callback) {
var script = document.createElement('script'),
loaded;
script.setAttribute('src', src);
if (callback) {
script.onreadystatechange = script.onload = function() {
if (!loaded) {
callback();
}
loaded = true;
};
}
document.getElementsByTagName('head')[0].appendChild(script);
}
};
// Example with callback
JS.load("http://www.someawesomedomain.com/some.js", function() {
//Do your thing.
});

Related

Dynamically load several JS files and fire a callback when all are ready

I have several JS and CSS files which need to be appended to the DOM dynamically with JavaScript. The method described here works fine for 1 file. However I have several of them and they should be appended/loaded in certain order:
var resources = {
"jquery" : "jquery.js",
"jqueryui" : "jquery_ui.js",
"customScript" : "script.js"
}
If that matters - the resources can be in an array rather than in an object.
What I think should be done is to load each next resource in the callback of the previous one. And the callback of the last resource should call another function, which, in my case will render the HTML. However I'm not sure how to organize it with the code given in the link above. Another important aspect is that this should be done with pure JavaScript.
Any clues?
Thanks!
I would suggest you to make an array of your resources rather than an object if you care about the order of their loading. I hope this solution will solve your issue.
var urls = ['https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.js',
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.slim.js'
];
var i = 0;
var recursiveCallback = function() {
if (++i < urls.length) {
loadScript(urls[i], recursiveCallback)
} else {
alert('Loading Success !');
}
}
loadScript(urls[0], recursiveCallback);
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);
}
Working Fiddle : https://jsfiddle.net/nikdtu/6uj0t0hp/
I haven't tested but in concept this should work. Loop through your object. Each time you loop through create a script element then add your script to the to the source of the script element you just created. Get the last script of your resource (lastObj) and compare it with resource[key] if they are equivalent call the onload function, this will determine when the last script is loaded.
var resources = {
"jquery": "jquery.js",
"jqueryui": "jquery_ui.js",
"customScript": "script.js"
}
var lastObj = resources[Object.keys(resources)[Object.keys(resources).length - 1]]
var script = [];
index = 0;
for (var key in resources) {
script[index] = document.createElement('script');
if (lastObj === resources[key]) {
script[index].onload = function() {
alert("last script loaded and ready");
};
}
script[index].src = resources[key];
document.getElementsByTagName('head')[0].appendChild(script[index]);
index++;
}
If you don't care about old browsers you can use the following modification to load them.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Stack Overflow</title>
<link rel="stylesheet" type="text/css" href="css/jquery-ui.min.css">
<script type="text/javascript" src="scripts/loader.js" ></script>
</head>
<body>
<h1>Test javascript loading strategy</h1>
<p id="result">Loading...</p>
<p>Date: <input type="text" id="datepicker"></p>
</body>
</html>
loader.js
function loadScript(url){
return new Promise(function(resolve, reject) {
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;
resolve();
}
};
} else { //Others
script.onload = function(){
resolve();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
});
}
var resources = [
"scripts/jquery.js",
"scripts/jquery_ui.js",
"scripts/script.js"
]
function loadAllResources() {
return resources.reduce(function(prev, current) {
return prev.then(function() {
return loadScript(current);
});
}, Promise.resolve());
}
loadAllResources().then(function() {
$('#result').text('Everything loaded');
});
custom script script.js
$( "#datepicker" ).datepicker();
Working JSFiddle

wait for scripts to load that have been added through javascript

I need to add jquery and then another script that relies on jquery.
I then need to have code that uses both assets but my problem is that i don't want my code to run until i know that both assets are loaded.
I think the process would be to load jquery and then wait until jquery is loaded by waiting for window.onload, then load the jquery plugin, then detect that the plugin has loaded, then load my own code that uses functions from the jquery plugin.
code so far:
// load jquery if it is not allready loaded and put it into no conflict mode so the $ is available for other librarys that might be allready on the page.
if(!window.jQuery) {
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(script);
jQuery.noConflict(); // stop jquery eating the $
console.log("added jquery");
}
window.onload = function(e) {
// we know that jquery should be available now as the window has loaded
if ( !jQuery.isFunction(jQuery.fn.serializeObject) ) { // use jquery to ask if the plugins function is allready on the page (don't do this if the website already had the plugin)
// website didn't have the plugin so add it to the page.
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-serialize-object/2.5.0/jquery.serialize-object.min.js";
document.getElementsByTagName('head')[0].appendChild(script);
}
if ( !jQuery.isFunction(jQuery.fn.serializeObject) ) {
// console.log("serializeObject is undefined");
// its going to be undefined here because Its still loading in the script
} else {
// console.log("we have serializeObject");
}
// I now dont know when to call my code that uses .serializeObject() because it could still be loading
// my code
var form_data_object = jQuery('form#mc-embedded-subscribe-form').serializeObject();
};
You have to do like
Include
<script type="text/javascript" id="AssetJS"></script>
Script
$("#AssetJS").attr("src", "Asset.js");
$("#AssetJS").load(function () {
//after loaded jquery asset do your code here
})
OK i managed to find another way that is working for my specific needs so I am answering my own question.
Using this function from http://www.sitepoint.com/dynamically-load-jquery-library-javascript/
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);
}
and usage in my case:
if(!window.jQuery) {
loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js", function () {
jQuery.noConflict(); // stop jquery eating the $
console.log('jquery loaded');
if ( !jQuery.isFunction(jQuery.fn.serializeObject) ) { // use jquery to ask if the plugins function is already on the page
loadScript("https://cdnjs.cloudflare.com/ajax/libs/jquery-serialize-object/2.5.0/jquery.serialize-object.min.js", function () {
console.log('serialize loaded');
SURGE_start(); // both scrips where not on the website but have now been added so lets run my code now.
});
}
});
} else {
if ( !jQuery.isFunction(jQuery.fn.serializeObject) ) { // use jquery to ask if the plugins function is already on the page
loadScript("https://cdnjs.cloudflare.com/ajax/libs/jquery-serialize-object/2.5.0/jquery.serialize-object.min.js", function () {
console.log('serialize loaded');
SURGE_start(); // jquery was on the web page but the plugin was not included. now we have both scripts lets run my code.
});
} else {
SURGE_start(); // web page already had both scripts so just run my code.
}
}
An easy way is using headjs. It's working fine on several projects.

Dynamically loaded jQuery not defined when using inline script

Situation:
jQuery is dynamically loaded together with other scripts by one file javascripts.js in the <head> section of the html file
Each html file has it's own javascript code executed on jQuery(document).ready() in the <body> section of the html file
Problem:
Error: jQuery is not defined for javascript in the <body> section
Modifying the html file is not an option (+1000 files with same problem)
Example html file:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
jQuery(document).ready(function() { // Error: jQuery not defined
jQuery('.date').datepicker();
});
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
});
This is happening, as many in the comments have pointed out, because you are loading jQuery asynchronously. Asynchronous means the rest of the code is executed, and so your document-ready handler (DRH) line is running before jQuery is present in the environment.
Here's a really hacky way of resolving this. It involves making a temporary substitute of jQuery whose job is just to log the DRH callbacks until jQuery has arrived. When it does, we pass them in turn to jQuery.
JS:
//temporary jQuery substitute - just log incoming DRH callbacks
function jQuery(func) {
if (func) drh_callbacks.push(func);
return {ready: function(func) { drh_callbacks.push(func); }};
};
var $ = jQuery, drh_callbacks = [];
//asynchronously load jQuery
setTimeout(function() {
var scr = document.createElement('script');
scr.src = '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js';
document.head.appendChild(scr);
scr.onload = function() {
$.each(drh_callbacks, function(i, func) { $(func); });
};
}, 2000);
HTML:
jQuery(document).ready(function() { alert('jQuery has loaded!'); });
Fiddle: http://jsfiddle.net/y7aE3/
Note in this example drh_callbacks is global, which is obviously bad. Ideally hook it onto a namespace or something, e.g. mynamespace.drh_callbacks.
I believe this simple solution should do the trick. The changed line in the html changes the jquery onload function to a regular function. The jquery onload function will sometimes happen before the jquery is loaded and we can't have that. It's unreliable. We need that function not to execute on page load, but AFTER the jquery has loaded.
To that end, the three lines I've added in the javascript.js are inside the code that is executed immediately after jQuery has finished loading. They test to see if the pageLoaded function has been defined (so you don't have to put one on every page, only the ones that need it) and then execute it if it's there.
Now, because the change to the HTML is simple, you can just do a regex search and replace on those 1000 files to fix them. Tools like Sublime, Eclipse or TextPad are suited for that task.
Cheers!
Example html file:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
function pageLoaded() { // changed
jQuery('.date').datepicker();
} // changed
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
if( typeof(pageLoaded) == "function" ){ // added
pageLoaded(); // added
} // added
});
You should try following workaround to load scripts synchronously:
function loadJS(src, callback) {
document.write('<scr'+'ipt src="'+src+'"><\/scr'+'ipt>');
callback();
}
IMPORTANT to note: this function should be called always before DOM is fully rendered.

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.

Including javascripts not working

I found a little javascript snippet for including javascripts only if they was not included before.
That is working with my own scripts, but with two third-party libraries it's not working and I really don't know why.
var included_files = new Array();
function include_once(script_filename) {
if (!in_array(script_filename, included_files)) {
included_files[included_files.length] = script_filename;
include_dom(script_filename);
}
}
function in_array(needle, haystack) {
for (var i = 0; i < haystack.length; i++) {
if (haystack[i] == needle) {
return true;
}
}
return false;
}
function include_dom(script_filename) {
var html_doc = document.getElementsByTagName('head').item(0);
var js = document.createElement('script');
js.setAttribute('language', 'javascript');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', script_filename);
html_doc.appendChild(js);
return false;
}
function loaded() {
include_once("shared/scripts/jquery.min.js");
include_once("shared/scripts/iscroll.js");
$(document).ready(function () {
alert("hello");
});
}
error: $ is not defined.
If I import jQuery the regular way its working and it says "iScroll" is not defined (because I'm using it later).
Any ideas?
include_dom is asynchronous. It loads the scripts in parallel, and you can't really determine when the scripts will be loaded. You try to use jQuery right after you started the download, which doesn't work.
You need to use a script that allows you to specify a callback for loaded scripts. I would recommend require.js
You are adding the scripts to the DOM, but not letting them load before you try to use the functions they provide.
You need to bind a callback to the load event of the script elements you are adding.
(At least in most browsers, you might have to implement some hacks in others; you may wish to examine the source code for jQuery's getScript method).
Did someone say callback?
function include_once(script_filename, callback) {
if (!in_array(script_filename, included_files)) {
included_files[included_files.length] = script_filename;
include_dom(script_filename, callback);
}
}
function include_dom(script_filename, callback) {
var html_doc = document.getElementsByTagName('head').item(0);
var js = document.createElement('script');
js.setAttribute('language', 'javascript');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', script_filename);
if(callback && callback != 'undefined'){
js.onload = callback;
js.onreadystatechange = function() {
if (this.readyState == 'complete') callback();
}
}
html_doc.appendChild(js);
return false;
}
function loaded() {
include_once("shared/scripts/jquery.min.js", function(){
$(document).ready(function () {
alert("hello");
});
});
include_once("shared/scripts/iscroll.js");
}
Use a script loader. yepnope will do everything you are trying to do and more

Categories

Resources