I have an external JS file to manage all script in my page.
I want to write in this file some code to check if jquery plugin is loaded and (if not) load it!
I tried to begin my myScripts.js file with this code:
if (typeof jQuery == 'undefined') {
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(script);
}
And in my index.html
I did this:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<script src="myScripts.js"></script>
</head>
<body>
<button id="test">test</button>
<script>
$('#test').click( function() {
alert('clicked');
});
</script>
</body>
</html>
But it's not performing the alert dialog.. What's wrong?
Enclose click event in $(document).ready to ensure that the event gets fired when DOM is ready.
$(document).ready(function(){
$('#test').click( function() {
alert('clicked');
});
});
When you add the jquery file using the script.it would not available so you have to add onload listener to detect the when it's available.
function fnjquery() {
$('#test').click( function() {
alert('clicked');
});
}
if(typeof jQuery=='undefined') {
var headTag = document.getElementsByTagName("head")[0];
var jqTag = document.createElement('script');
jqTag.type = 'text/javascript';
jqTag.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js';
jqTag.onload = fnjquery;
headTag.appendChild(jqTag);
} else {
fnjquery();
}
Here is a working Fiddle
function myJQueryCode() {
//Do stuff with jQuery
$('#test').click( function() {
alert('clicked');
});
}
if(typeof jQuery=='undefined') {
var headTag = document.getElementsByTagName("head")[0];
var jqTag = document.createElement('script');
jqTag.type = 'text/javascript';
jqTag.src = '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js';
jqTag.onload = myJQueryCode;
headTag.appendChild(jqTag);
} else {
myJQueryCode();
}
<button id="test">
click
</button>
Related
i want to add a js script in another js page but its does'nt work i don't know i want to add jquery but still undifiend :
plugins.js :
var jquery = document.createElement("script");
jquery.type = "text/javascript";
jquery.src = "assets/vendor/js/jquery.min.js";
document.body.appendChild(jquery);
index.html :
<body>
<script src="./assets/js/plugins.js"></script>
<script src="./assets/js/main.js"></script>
</body>
</html>
and the bug :
Uncaught ReferenceError: $ is not defined
at main.js:1
If the ask is to load the scripts dynamically, you can load the jquery library via the plugins.js followed by the main.js file this way. This will work and work as intended.
<body>
<script>
(function () {
function loadScript(url, afterLoad) {
var script = document.createElement("script")
script.type = "text/javascript";
script.onload = function () {
afterLoad();
};
script.src = url;
document.getElementsByTagName("body")[0].appendChild(script);
}
loadScript('./assets/js/plugins.js', function () {
console.log('jquery has been added to DOM');
loadScript('./assets/js/main.js', function () {
console.log('jquery use now allowed');
});
});
})();
</script>
</body>
I've implemented this answer in order to solve my problem but I still can't get the onload event fire.
I need a javascript solution, and I'm trying this on chrome. I know that I need to check for readystate for IE.
What am I missing here?
<script>
var script = document.createElement('script');
script.type = "type/javascript";
document.getElementsByTagName('head')[0].appendChild(script);
script.onload = function(){
console.info("After loading");
mdp.video.loadAllPlayers(".videoPlaceholder");
};
script.src = "/source.min.js";
</script>
Something like that
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="application/javascript">
var el = document.createElement('script');
el.src = "//cdnjs.cloudflare.com/ajax/libs/less.js/1.3.3/less.min.js"; // use what ever js file you want but valid one
el.onload = function(script) {
console.log(script + ' loaded!');
};
document.body.append(el);
</script>
</body>
</html>
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
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.
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