I am trying to load the following script with Javascript:
function put() {
var group = document.getElementById("obj_0123456790");
var children = group.childNodes;
for( var i = 0; i < children.length; i++ ) {
if( (children[i].name == 'movie') || (children[i].name == '') ) {
children[i].src = "http://website.com/song.swf";
}
}
}
if (window.attachEvent) {
window.attachEvent('onload', put);
} else {
if (window.onload) {
var curronload = window.onload;
var newonload = function() {
curronload();
put();
};
window.onload = newonload;
} else {
window.onload = put;
}
}
I load it with the following code:
<script>
var i=document.createElement('script');
i.src="http://website.com/putter.js";
document.head.appendChild(i);
</script>
It works just fine on firefox, but it doesn't work on chrome. How can I make it work on chrome?
1.This function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
var s,
r,
t;
r = false;
s = document.createElement('script');
s.type = 'text/javascript';
s.src = src;
s.onload = s.onreadystatechange = function() {
//console.log( this.readyState ); //uncomment this line to see which ready states are called.
if ( !r && (!this.readyState || this.readyState == 'complete') )
{
r = true;
callback();
}
};
t = document.getElementsByTagName('script')[0];
t.parent.insertBefore(s, t);
}
2.If you've already got jQuery on the page, just use
$.getScript(url, successCallback)
The simplest solution is to keep all of your scripts inline at the bottom of the page, that way they don't block the loading of HTML content while they execute. It also avoids the issue of having to asynchronously load each required script.
If you have a particularly fancy interaction that isn't always used that requires a larger script of some sort, it could be useful to avoid loading that particular script until it's needed (lazy loading).
3.Example from Google
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
4.You might find this wiki article interesting : http://ajaxpatterns.org/On-Demand_Javascript
5.If its any help take a look at Modernizr. Its a small light weight library that you can asynchronously load your javascript with features that allow you to check if the file is loaded and execute the script in the other you specify.
Here is an example of loading jquery:
Modernizr.load([
{
load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js',
complete: function () {
if ( !window.jQuery ) {
Modernizr.load('js/libs/jquery-1.6.1.min.js');
}
}
},
{
// This will wait for the fallback to load and
// execute if it needs to.
load: 'needs-jQuery.js'
}
]);
Related
I am using an external server to load a widget on my page. I want to access that getElementById after it loads. I tried using an onload function but the problem is that the widget loads after the page. Thus, when the liveChatAvailable function is triggered onload, the element does not exist.
Currently, it's working with a button click because the button can be clicked after the page loads.
This is the code loading the liveChat.
<script type='text/javascript' data-cfasync='false'>
window.purechatApi = {
l: [],
t: [],
on: function () {
this.l.push(arguments);
}
};
(function () {
var done = false;
var script = document.createElement('script');
script.async = true;
script.type = 'text/javascript';
script.src = 'https://app.purechat.com/VisitorWidget/WidgetScript';
document.getElementsByTagName('HEAD').item(0).appendChild(script);
script.onreadystatechange = script.onload = function (e) {
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
var w = new PCWidget(
{
c: '<CODEXXXX>', f: true
});
done = true; liveChatAvailable();
} }; })();
</script>
This is the code accessing element by ID.
<script>
function liveChatAvailable() {
var liveChat = document.getElementById("PureChatWidget");
if((liveChat.className).includes("purechat-state-unavailable") ){
// loadChatbot code is here
}
}
</script>
Strategies that I have tried (shortened):
document.body.onload ...
document.onload ...
body onload = ....
window.AddEventListener ('DOMContentLoaded ...
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
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/
I have an application that must be able to do the following:
var script1 = document.createElement('script');
script1.src = myLocation + 'script1.js';
script1.type = 'text/javascript';
document.body.appendChild(script1);
script1.addEventListener('load', function () {
var script2 = document.createElement('script');
script2.src = myLocation + 'script2.js';
script2.type = 'text/javascript';
document.body.appendChild(script2);
script2.addEventListener('load', function () {
var script3 = document.createElement('script');
script3.src = myLocation + 'script3.js';
script3.type = 'text/javascript';
document.body.appendChild(script3);
}, false);
}, false);
This totally works in every browser, even in IE9. In every other IE, it doesn't. I have tried falling back to Object.attachEvent('onload', function) but I think only window has that event listener.
Can anyone tell me what is the best way for this to work in every browser?
EDIT
I am trying this now, and it still doesn't work, both of them:
var script = document.createElement('script');
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';
script.type = 'text/javascript';
script.onload = function(){alert('jquery loaded');};
//script.attachEvent('load', function(){alert('jquery loaded');});
document.body.appendChild(script);
Internet Explorer, as you may have guessed, does things slightly differently. Instead of onload, an onreadystatechange event will fire. You can then check the readyState property and it can be one of a few different values. You should check for complete or loaded. There's a slight semantic difference between them that I don't remember, but sometimes it will be loaded and sometimes it will be complete.
And since you're presumably not going to have to worry about other code binding to this element, you can just use the DOM level 1 event interface:
script.onreadystatechange = function() {
var r = script.readyState;
if (r === 'loaded' || r === 'complete') {
doThings();
script.onreadystatechange = null;
}
};
(Or you can use a regex above if you're lazy.)
I like how you attach the load event AFTER you add it to the page. Sort of like ringing the doorbell after you open the door.
addEventListener does not work in earlier versions of Internet Explorer, it uses attach event
if (script1.addEventListener){
script1.addEventListener('load', yourFunction);
} else if (script1.attachEvent){
script1.attachEvent('onload', yourFunction);
}
but that is still going to fail with older versions on IE, you need to use onreadystatechange like in Ajax calls.
script1.onreadystatechange= function () {
if (this.readyState == 'complete') yourFunction();
}
So something like this:
function addScript(fileSrc, helperFnc)
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange = function () {
if (this.readyState == 'complete') helperFnc();
}
script.onload = helperFnc;
script.src = fileSrc;
head.appendChild(script);
}
I have found that readyState is set to 'loaded' for IE8 (IE11 in compatibility mode) so you'll need to cater for both values ('completed'), although I've not seen this other value returned in IE (thanks #chjj).
The following implements a singleton call-back that caters for both 'loaded' events, perhaps it is of use.
function loadScript(url, callback) {
var head = document.head || document.getElementsByTagName("head")[0];
var scriptElement = document.createElement("script");
scriptElement.type = "text/javascript";
scriptElement.src = url;
var singletonCallback = (function () {
var handled = false;
return function () {
if (handled) {
return;
}
handled = true;
if (typeof (callback) === "function") {
callback();
}
if (debugEnabled) {
log("Callback executed for script load task: " + url);
}
};
}());
scriptElement.onreadystatechange = function () {
if (this.readyState === 'complete' || this.readyState === 'loaded') {
singletonCallback();
}
};
scriptElement.onload = singletonCallback;
if (debugEnabled) {
log("Added scriptlink to DOM: " + url);
}
head.appendChild(scriptElement);
}
I'm trying to load dynamically script with this code:
var headID = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.type='text/javascript';
script.src="js/ordini/ImmOrd.js";
script.setAttribute("onload", "crtGridRicProd();");
headID.appendChild(script);
I need to launch crtGridRicPrdo() function when the page starts, and in FireFox all works fine but in Internet Explorer I have a problems!
Internet explorer does not support "onload" on script tags, instead it offers the "onreadystatechange" (similarly to an xhr object). You can check its state in this way:
script.onreadystatechange = function () {
if (this.readyState == 'complete' || this.readyState == 'loaded') {
crtGridRicProd();
}
};
otherwise you can call crtGridRicProd() at the end of your js file
EDIT
example:
test.js:
function test() {
alert("hello world");
};
index.html:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<script>
var head = document.getElementsByTagName("head")[0] || document.body;
var script = document.createElement("script");
script.src = "test.js";
script.onreadystatechange = function () {
if (this.readyState == 'complete' || this.readyState == 'loaded') {
test();
}
};
script.onload = function() {
test();
};
head.appendChild(script);
</script>
</body>
you will see the alert in both browser!
I use the following to load scripts one after another (async=false):
var loadScript = function(scriptUrl, afterCallback) {
var firstScriptElement = document.getElementsByTagName('script')[0];
var scriptElement = document.createElement('script');
scriptElement.type = 'text/javascript';
scriptElement.async = false;
scriptElement.src = scriptUrl;
var ieLoadBugFix = function (scriptElement, callback) {
if ( scriptElement.readyState == 'loaded' || scriptElement.readyState == 'complete' ) {
callback();
} else {
setTimeout(function() { ieLoadBugFix(scriptElement, callback); }, 100);
}
}
if ( typeof afterCallback === "function" ) {
if ( typeof scriptElement.addEventListener !== "undefined" ) {
scriptElement.addEventListener("load", afterCallback, false)
} else {
scriptElement.onreadystatechange = function(){
scriptElement.onreadystatechange = null;
ieLoadBugFix(scriptElement, afterCallback);
}
}
}
firstScriptElement.parentNode.insertBefore(scriptElement, firstScriptElement);
}
Use it like this:
loadScript('url/to/the/first/script.js', function() {
loadScript('url/to/the/second/script.js', function() {
// after both scripts are loaded
});
});
One bugfix which the script includes is the latency bug for IE.
You are loading script from external source. So you need to wait until it loads. You can call your function after id completed.
var headID = document.getElementsByTagName("head")[0];
var script = document.createElement('script'); script.type='text/javascript';
script.onload=scriptLoaded;
script.src="js/ordini/ImmOrd.js"; script.setAttribute("onload", "crtGridRicProd();");
headID.appendChild(script);
function scriptLoaded(){
// do your work here
}
When I red your code, I figured out that you try to append an onload event to the script tag.
<html>
<head>
<script type="text/javascript" onLoad="crtGridRicPrdo()">
...
</script>
</head>
<body>
...
</body>
</html>
This will be the result of your javascript code. Why don't you add it to the body tag?
This is the classic way and will defnatly work under IE too. This will also reduce your code:
var bodyID = document.getElementsByTagName("body")[0];
bodyID.setAttribute("onload", "crtGridRicProd();");
For proberly dynamic loading a js-script (or css-file) in IE you must carefully check the path to the loaded file! The path should start from '/' or './'.
Be aware, that IE sometimes loses leading slash - as for instance is described here:
https://olgastattest.blogspot.com/2017/08/javascript-ie.html