Dynamically added Javascript won't reload - javascript

I have a web page with a Javascript file added dynamically.
After changing the script (adding allert or smth like this) I reload the page, and push a trigger button for adding the script, but the browser uses the old one (chached).
Tried it in chrome and IE.
Other scripts (that are not added dynamically) reload well.
Here is the function that loads the script:
function addScript (s)
{
script = document.createElement('script');
script.type = 'text/javascript';
script.src = s;
document.getElementsByTagName('head')[0].appendChild(script);
script.onload=function ()
{
switch (s)
{
case 'some address':
functionInTheNewFile(); break;
default: break;
}
};
}
What is wrong here?

If it is an external script caching, append the current date and time to the end of the script. IE:
var nowDate = new Date();
script.src = s + "?nocache=" + nowDate.getTime();

IE do not fire the load event, you have to use attachEvent instead. And always add the eventlistener before you locate the script.
script = document.createElement('script');
script.type = 'text/javascript';
if(script.attachEvent) {
script.attachEvent('onreadystatechange', callback);
} else {
script.onload = callback;
}
script.src = s;

Related

Use jQuery without Script tag in head

So I want to make jQuery load inside my script. the user doesn't have to add the <script> to the head, but the script adds automatically. I tried using:
(function() {;
var script = document.createElement("SCRIPT");
script.src = '/src/jquery-embed.js';
script.type = 'text/javascript';
document.getElementsByTagName("head")[0].appendChild(script);
var checkReady = function(callback) {
if (window.jQuery) {
callback(jQuery);
} else {
window.setTimeout(function() {
checkReady(callback);
}, 20);
}
};
checkReady(function($) {
//code here
fucntion callbutton {
console.log("i return as not defined when called by a button")
}
when I add it, it works fine but all my functions break. How can I go about this without screwing up more?
edit: Link to the file im working on here
Per discussion, to achieve your goal you must ask your clients to delay their script execution until you've loaded your libraries (jQuery in this case).
Shown below is all that is necessary to accomplish the loading:
var script = document.createElement('SCRIPT');
document.getElementsByTagName('head')[0].appendChild(script);
script.src = 'https://code.jquery.com/jquery-3.5.1.min.js';
script.onload = () => {
document.dispatchEvent(new CustomEvent('doYourThing'));
};
Then, your users would use this code:
document.addEventListener('doYourThing', ()=>{
// End user code that relies on jQuery goes here
});
Here is a plunkr that demonstrates the principle.
You forgot document.body.appendChild() and you also forgot to add the parentheses after callbutton
change it to this:
(function() {
var script = document.createElement("SCRIPT");
document.body.appendChild(script);
script.src = '/src/jquery-embed.js';
script.type = 'text/javascript';
document.getElementsByTagName("head")[0].appendChild(script);
var checkReady = function(callback) {
if (window.jQuery) {
callback(jQuery);
} else {
window.setTimeout(function() {
checkReady(callback);
}, 20);
}
};
checkReady(function($) {
//code here
function callbutton(){
console.log("i return as not defined when called by a button")
}
}
})

Load jQuery First After DOMContentLoaded

I am trying to load some scripts after DOMContentLoaded event and I am trying to use the following script for this. I'm not sure if the following is the best way to do this but I am having an issue with the following code because I need to load jquery first because my other scripts are depend on it. I have no idea how to do this any help would be greatly appreciated. Thank you very much.
<script>
document.addEventListener('DOMContentLoaded', function() {
var script = document.createElement('script');
script.src = 'https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js';
document.getElementsByTagName('body')[0].appendChild(script);
var script1 = document.createElement('script');
script1.src = '/myscript1.js';
document.getElementsByTagName('body')[0].appendChild(script1);
var script2 = document.createElement('script');
script2.src = '/myscript2.js';
document.getElementsByTagName('body')[0].appendChild(script2);
});
</script>
Please know that dynamic scripts behave as async by default, which means that the script that loads first will also run first. So, the issue might be here that myscript1.js & myscript2.js are very small scripts and thus it loads and runs first before jquery script could load. To fix this you can pass script.async=false to each script so that script loads and run in the order they are being added to the document like:
document.addEventListener('DOMContentLoaded', function() {
var script = document.createElement('script');
script.src = 'https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js';
script.async = false;
document.getElementsByTagName('body')[0].appendChild(script);
var script1 = document.createElement('script');
script1.src = '/myscript1.js';
script.async = false;
document.getElementsByTagName('body')[0].appendChild(script1);
var script2 = document.createElement('script');
script2.src = '/myscript2.js';
script.async = false;
document.getElementsByTagName('body')[0].appendChild(script2);
});
and if you want to keep things DRY (Don't repeat yourself), you can use a helper function like:
document.addEventListener('DOMContentLoaded', function() {
function loadScript(src) {
let script = document.createElement('script');
script.src = src;
script.async = false;
document.getElementsByTagName('body')[0].appendChild(script);
}
loadScript('https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js');
loadScript('/myscript1.js');
loadScript('/myscript2.js');
});

Script injected with innerHTML doesn't trigger onload and onerror

I am trying to bind onload and onerror events of script tag. This works fine when loading from src. Given the following function:
function injectJS(src, inline) {
var script = document.createElement("script");
if (inline) {
script.innerHTML = src;
} else {
script.src = src;
}
script.onload = function() {console.log("Success!");};
script.onerror = function() {console.log("Error!");};
document.body.appendChild(script);
}
I can easily know whether script has loaded:
> injectJS("https://code.jquery.com/jquery-3.1.1.min.js");
Success!
> injectJS("https://raw.githubusercontent.com/eligrey/FileSaver.js/master/FileSaver.js");
Error!
But when injecting inline JS, with innerHTML, the script doesn't fire the events:
> injectJS("console.log(\"Yes!\");", true);
Yes!
> injectJS("console.log(\"Loaded but error...\"); error;", true);
Loaded but error...
Success! hasn't been logged in these cases. However, I could just prepend some code that can call a function, for example, once the script is loaded.
The problem comes when there is an error that prevents script from loading in the first place, for example a syntax error:
> injectJS("console.log(\"Success! Or not..\"); syntax error;", true);
Nothing is logged (except the error, of course). How can I detect whether an injected script has loaded or errored out before loading?
Edit:
Oriol's answer has pointed me in the right direction. For reference, here is the final function that works exactly as I wanted and passes the 5 test cases:
function injectJS(src, inline, on_success, on_error) {
var script = document.createElement("script");
script.onload = on_success;
script.onerror = on_error;
if (inline) {
script.innerHTML = "window.script_loaded = true; " + src;
} else {
script.src = src;
}
document.body.appendChild(script);
if (inline) {
var loaded = window["script_loaded"];
window.script_loaded = false;
if (loaded) {
on_success();
} else {
on_error();
}
}
}
Inline scripts are loaded synchronously. So you don't need the events at all.
Just use
function injectJS(src, inline) {
var script = document.createElement("script");
script.onload = function() {console.log("Success!");};
script.onerror = function() {console.log("Error!");};
if (inline) {
script.innerHTML = src;
script.onload();
} else {
script.src = src;
}
document.body.appendChild(script);
}
injectJS("console.log(\"Yes!\");", true);
You won't be able to detect syntax errors, but it's just like with external scripts. The error event only implies the script couldn't be downloaded, not syntax errors.

How do i create a script element to include jquery

Im trying to write a script that will append the jquery cdn script
to the body of the document.
function addJquery() {
url = "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.body.appendChild(script);
}
addJquery();
What am i doing wrong here
You can't add scripts to the body and have them execute. Late-loaded scripts must be loaded through the head element:
(function addJQuery() {
var url = "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
var script = document.createElement('script');
script.url = url;
script.onload = function() { addJQuery(); }
document.head.appendChild(script);
}());
However, this loads jQuery regardless of whether it's already loaded, so that's no good. Here's what you generally want instead:
(function loadMyCode() {
// do we have jquery? if not, load it.
if (typeof jQuery === "undefined") {
var url = "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
var script = document.createElement('script');
script.url = url;
script.onload = function() {
// this will run after jquery gets loaded
loadMyCode();
}
document.head.appendChild(script);
return;
}
// if we get here, we know we have jquery
//
// rest of the code goes here.
}());
This is another way
(function () {
var li = document.createElement('script');
li.type = 'text/javascript';
li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
li.async=true;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(li, s);
})();

Load JS scripts asynchronously in order (waiting the previous one is complete)

I am trying to use GoogleMaps.InfoBox on my project, but before load this script, the GoogleMaps API has to be loaded.
Right now I have this code to load everything:
/**
* Load scripts asynchronously
*/
function loadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=-MY-KEY-&sensor=true&callback=initialize";
document.body.appendChild(script);
var scriptInfoBox = document.createElement("script");
scriptInfoBox.type = "text/javascript";
scriptInfoBox.src = "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox_packed.js";
document.body.appendChild(scriptInfoBox);
}
But not always the GoogleMaps API is loaded before than GoogleMaps.InfoBox one.
How can I load JS sorted, waiting for complete the previous one?
You can use the load event of the scripts:
function loadScript(callback) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=-MY-KEY-&sensor=true&callback=initialize";
document.body.appendChild(script);
script.onload = function() {
var scriptInfoBox = document.createElement("script");
scriptInfoBox.type = "text/javascript";
scriptInfoBox.src = "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox_packed.js";
document.body.appendChild(scriptInfoBox);
scriptInfoBox.onload = callback;
};
}
However, you will need to adapt the code a bit to make it crossbrowser-safe like this.
Just use regular script tags right before </body>.
<script src="http://maps.googleapis.com/maps/api/js?key=-MY-KEY-&sensor=true&callback=initialize"></script>
<script src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox_packed.js"></script>
By default, browsers will execute scripts in the order they appear.

Categories

Resources