I'm trying to handle JQuery not loading.
(this is for a javascript api, frequently the developer consuming it forgets to include jquery, hence I want to instruct them on what is missing)
I have a bunch of code in various files that runs on document.ready
e.g.
(function ($, undefined) {
//stuff
})( jQuery );
If JQuery is not loaded then the code above breaks.
A workaround I've found is to add a check for Jquery instead through a function
e.g.
(function ($, undefined) {
//stuff
})( JQueryCheck() );
function JQueryCheck() {
if (window.jQuery == undefined)
alert("no jquery");
else
return jQuery;
}
I'm not sure if this is strong enough, if theres a better way to do it then let me know.
On top of this I want prevent the other document.readys from running, theres no point as all depend on JQuery being loaded.
This must be common issue but I'm struggling to find a solution.
Don't load script files like this <script src="some-path"></script> in Html
instead do this:
if(window.jQuery){
$.getScript('path to js file');
}
This checks for jquery and if it exists, it loads the script and executes it.
Try this:
function JQueryCheck() {
return !!jQuery;
}
Or:
function JQueryCheck() {
try{
jQuery();
} catch(e){
if(e){
return false;
} else {
return true;
}
}
}
Or:
function JQueryCheck() {
if(window.jQuery){
return true;
}else{
return false;
}
}
Good luck!
Your code should work fine, but you could simplify it a bit:
(function ($, undefined) {
if(!$) {
return alert("no jquery");
}
//stuff
})(window.jQuery);
You could also just load it when it's not loaded already:
(function (undefined) {
if(!window.jQuery) {
var script = document.createElement("SCRIPT");
script.src = 'http://code.jquery.com/jquery-2.1.0.min.js';
script.type = 'text/javascript';
document.getElementsByTagName("head")[0].appendChild(script);
// Poll for jQuery to come into existance
var checkReady = function(callback) {
if (window.jQuery) {
callback();
}
else {
window.setTimeout(function() { checkReady(callback); }, 100);
}
};
// Start polling...
checkReady(main);
} else {
main();
}
}());
function main() {
alert("jquery loaded");
};
Taken from https://stackoverflow.com/a/10113434/941764
Whilst it would be best to solve the issues you are having with it not loading this will do what you want it to:
if(window.jQuery) {
//jQuery Code
}
Alternatively if you're after loading a local file if a hosted one has failed, this would work:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery.min.js"><\/script>')</script>
Related
I try to write a JavaScript function that loads a js script (src) and performs some callback when the script is loaded.
I also look if a script with the same src already exists.
My problem is that if the script already loaded, the callback will not be performed. That is NOK.
How to know if the script was already loaded?
importScript: (function (head) {
function loadError(error) {
throw new URIError("The script " +
error.target.src + " is not accessible.");}
return function (url, callback) {
var existingScript = document.querySelectorAll("script[src='" +
url + "']");
var isNewScript = (existingScript.length == 0);
var script;
if (isNewScript) {
script = document.createElement("script")
script.type = "text/javascript";
}
else {
script = existingScript[0];
}
script.onerror = loadError;
if (script.readyState) { //IE
script.onreadystatechange = function () {
if (script.readyState == "loaded" ||
script.readyState == "complete") {
script.onreadystatechange = null;
if (callback) {
callback(); }
}
};
} else { // others than IE
script.onload = callback; }
if (isNewScript) {
script.src = url;
head.appendChild(script); }
}
})(document.head || document.getElementsByTagName("head")[0])
As I understand, the script.readyState == "loaded" || script.readyState == "complete" could work only for IE, not for other browsers as well...
Usage:
importScript("myScript1.js");
importScript("myScript2.js", /* onload function: */
function () { alert("The script has been OK loaded."); });
I recommend jQuery, it's so easy with that. Life is too short for coding things like that yourself (you will waste hours for supporting all browsers).
$.ajax({
url: "/script.js",
dataType: "script",
success: function() {
console.log("script loaded");
}
});
EDIT:
It's even easier (example from jQuery docs):
$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) {
console.log(data); // Data returned
console.log(textStatus); // Success
console.log(jqxhr.status); // 200
});
You can also chain done and fail to have additional callbacks:
$.getScript("ajax/test.js")
.done(function(script, textStatus) {
console.log(textStatus);
})
.fail(function(jqxhr, settings, exception) {
console.log("loading script failed.");
});
Load jQuery asynchronously
<script src="path/to/jquery"></script>
<script>
function wait(method) {
if (window.$) {
method();
} else {
setTimeout(function () { wait(method); }, 100); // check every 100ms
}
}
// wait for jQuery
wait(function() {
// jQuery has loaded!
$("#foo").doSomething();
// you can now load other scripts with jQuery:
$.getScript("ajax/test.js")
.done(function(script, textStatus) {
console.log(textStatus);
})
.fail(function(jqxhr, settings, exception) {
console.log("loading script failed.");
});
}
</script>
Well the safest way to check if script is loaded is you can add a simple callback at end of script . Which if exist can be called with some data also to be passed.
if(window.loaded){
window.loaded(params);
}
Once the script loads it will execute this method which you can declare in your parent script which will be called.
Also you can trigger an event on body and listen on that event in other parent code.
Based on method from Luca Steeb, I refine the solution to just two script tags, for SPA applications, index.html is very compact with:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Simplified INDEX</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="/bootloader.js"></script>
</head>
<body>
</body>
</html>
bootloader.js, combine ideas from Luca and load css using jquery :
function loadScripts() {
// jQuery has loaded!
console.log("jquery is loaded");
// you can now load other scripts and css files with jQuery:
$.when($.getStylesheet('css/main.css'), $.getScript('js/main.js'))
.then(function () {
console.log('the css and js loaded successfully and are both ready');
}, function () {
console.log('an error occurred somewhere');
});
}
function patchGetStylesheet($) {
$.getStylesheet = function (href) {
var $d = $.Deferred();
var $link = $('<link/>', {
rel: 'stylesheet',
type: 'text/css',
href: href
}).appendTo('head');
$d.resolve($link);
return $d.promise();
};
}
function wait(method) {
if (window.$) {
patchGetStylesheet(window.$);
method();
} else {
setTimeout(function () {
wait(method);
}, 100); // check every 100ms
}
}
// wait for jQuery
wait(loadScripts);
For bootloader.js, it could be minified、obfused.... using webpack, ...
We will not add code to index.html any more through solving runtime dependency using jquery.
Externally loading a script, but my script was placed by the client above jQuery (which is a requirement), as such, my script does not work.
I am trying to make my code wait until jQuery has loaded before executing, but I am having difficulty with nested functions within my code; specifically $(x).hover, or $(x).click etc.
I can separate my functions without much trouble, which include jQuery selectors (but they won't be called unless 'x y or z' is done (i.e. until after jQuery is loaded).
I don't know how to have the hover, click etc implemented as they don't work within my $(document).ready(function(){... which is located within the onload yourFunctionName described below - with thanks to user #chaos
Link to onload hook: https://stackoverflow.com/a/807997/1173155
and a quote of the above link:
if(window.attachEvent) {
window.attachEvent('onload', yourFunctionName);
} else {
if(window.onload) {
var curronload = window.onload;
var newonload = function() {
curronload();
yourFunctionName();
};
window.onload = newonload;
} else {
window.onload = yourFunctionName;
}
}
Thanks in advance for any help with this.
I have also looked into a loop that checks if jQuery is activated before continueing, but did not implement it as I found that JavaScript does not have a sufficient sleep method that sleeps that specific script.
Solution:
if(typeof jQuery === "undefined"){
if(window.attachEvent) {
window.attachEvent('onload', myLoadFunction);
} else {
if(window.onload) {
var curronload = window.onload;
var newonload = function() {
curronload();
myLoadFunction();
};
window.onload = newonload;
} else {
window.onload = myLoadFunction;
}
}
}
else {
myLoadFunction();
}
I have a TextBox and a Button:
If the value inside the Textbox is 1 (just emulating a condition)) I need to load jQuery on the fly and use a document Ready function :
I tried this :
function work() //when button click
{
if (document.getElementById('tb').value == '1')
{
if (typeof jQuery == 'undefined')
{
var script = document.createElement('script');
script.src = "http://code.jquery.com/jquery-git2.js";
document.getElementsByTagName('head')[0].appendChild(script);
$(document).ready(function ()
{
alert('');
});
}
}
}
But it says :
Uncaught ReferenceError: $ is not defined
I assume it's because the line : $(document).ready(function ()....
But I don't understand why there is a problem , since i'm, loading jQuery BEFORE I use $...
Question :
How can I fix my code to work as desired ?
JSBIN
You are missing the script onload handler:
var script = document.createElement('script');
// do something with script
// onload handler
script.onload = function () {
// script was loaded, you can use it!
};
Your function becomes:
function work() {
if (document.getElementById('tb').value != '1') { return; }
if (typeof jQuery != 'undefined') { return; }
// jQuery is undefined, we will load it
var script = document.createElement('script');
script.src = "http://code.jquery.com/jquery-git2.js";
document.getElementsByTagName('head')[0].appendChild(script);
// load handler
script.onload = function () {
// jQuery was just loaded!
$(document).ready(function () {
alert('');
});
};
}
Also, do not forget script.onreadystatechange for IE compatibility.
script.onreadystatechange = function () {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
// script was loaded
}
}
Also seems that YepNope would be a good option, too.
JSBIN DEMO
Using YepNope would probably a good option in this case.
yepnope([
{
test: window.jQuery,
nope: 'path/url-to-jquery.js',
complete: function() {
$(document).ready(function() {
//whatever you need jquery for
});
}
}
]);
You can just put that in the head of your document, and it will only load jquery if window.jQuery isn't defined. It's much more reliable (and simpler) than script.onload or script.onreadystatechange. the callback complete will only be called once jquery is loaded, so you can be sure that $ will be defined at that point.
Note: if you're using Modernizr.js on your site, there's a good chance yepnope is already bundled into that script.
I have a javascript widget that is included in a page by inserting a single script tag (as the application should be easiliy distributable):
<script type="text/javascript" src="loadMyWidget.js"></script>
loadMyWidget.js then needs to load multiple script files, which has to run in a certain sequence. I've tried to load them async by inserting script elements into the DOM, but that doesn't give me control of the sequence.
I also tried using head.js which is great for modern browsers, but I can't get it to work in IE7 and 8.
Minifying the scripts into one file is unfortunately difficult, as it is composed of a number of files from different projects and I wouldn't know when to update the script.
As simple as it seems, I need to load javascript files from javascript code in a certain sequence and get it to work in all browsers, including IE7 and 8.
If you need vanilla JS, something like this could work:
function loadScripts(scripts, complete) {
var loadScript = function( src ) {
var xmlhttp, next;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
try {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
return;
}
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
eval(xmlhttp.responseText);
next = scripts.shift();
if ( next ) {
loadScript(next);
} else if ( typeof complete == 'function' ) {
complete();
}
}
}
xmlhttp.open("GET", src , true);
xmlhttp.send();
};
loadScript( scripts.shift() );
}
loadScripts(['jquery.js','jquery.plugin.js'], function() {
console.log('loaded');
});
Tested in Chrome, should work in IE too.
If you're using jQuery.getScript() you can use it as a $.when() to hold off execution until things have stopped loading.
If by "sequential execution" you mean that you need to load the requisites before execution the following will work
$(function(){
$.when(
$.getScript("/script1"),
$.getScript("/scirpt2"),
$.getScript("/script3")
}).done(function(){
// do stuff with the contents of my new script files
});
If by sequential execution you mean that you need to execute files one after the other try this:
$.Deferred()
.then(function () { return $.getScript("/script1"); })
.then(function () { return $.getScript("/scirpt2"); })
.then(function () { return $.getScript("/script3"); })
.resolve();
Of course, this requires jQuery, which after your edits, this may not work for you.
Suggested Reading
http://api.jquery.com/jQuery.getScript
http://api.jquery.com/category/deferred-object/
http://api.jquery.com/jQuery.when/
I have run into this exact same issue and handled it with:
document.write('<script type="text/javascript" src="other1.js"></script>');
document.write('<script type="text/javascript" src="other2.js"></script>');
runSomeCode();
The code will be loaded and run synchronously. Pros: simple, light, cross browser compliant, no deps. Cons: ugly.
More details: https://stackoverflow.com/a/3292763/235179
Have you tried require.js? http://requirejs.org/
function loadScript(arrayOfUrlStrings, callback) {
var numScripts = arrayOfUrlStrings.length;
var count = 0;
var headElement = document.getElementsByTagName('head')[0]
function onLoad() {
count += 1;
if (count === numScripts) {
callback();
} else {
addScript();
}
}
function addScript() {
var script = document.createElement('script');
script.src = arrayOfUrlStrings[count];
script.onload = onLoad;
headElement.appendChild(script);
}
addScript();
}
I try to load some js files dynamically,for example:
function openInforWindow(){
//check if the InforWinow.js has been loaded or not
if(window.InforWindow){
//do the right thing
}
else {
loadJs('xxxxxx/InforWindow.js');
// do the right thing
//but here ,the infowindow is not definded yet.
}
}
function loadJs(filename){
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
How to make sure that the vars or functions in the js which is dynamically loaded can be add to the javascript execute environment so I can use them ?
adding a script element isn't a blocking operation, this means that your loadJs method returns immediately when your external script isn't even loaded (nor interpreted). You have to wait for it to load.
function openInforWindow(){
//check if the InforWinow.js has been loaded or not
if(window.InforWindow){
//do the right thing
}
else {
var loadHandler = function() {
//do stuff with inforWindow
};
loadJs('xxxxxx/InforWindow.js', loadHandler);
}
}
function loadJs(filename, handler){
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", "js");
fileref.onreadystatechange = function () {
if (this.readyState == 'complete')handler();
};
fileref.onload = handler;
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
One approach could be to load the script using jQuery's AJAX loader. Example below:
function loadJs(filename, functionToCall){
$.getScript(filename, functionToCall);
}
Now, you just need to call loadJs("script.js", callback);, and it will first completely load script.js, and then run callback().
You can dynamically insert a <script/> tag into your document, here is a script that will work in firefox/chrome, you may need a bit of tweaking in IE:
loadJs = function(src) {
var script = document.createElement('SCRIPT');
script.setAttribute('src', src);
document.getElementsByTagName('HEAD')[0].appendChild(script);
}
Then wait for the document.onload event to fire, your window.InforWindow should be loaded at that stage.
document.addEventListener('load', function () {
// Your logic that uses window.InforWindow goes here
}, false);
Note that IE does the load event listener slightly differently:
document.attachEvent('onload', function() {
// Your logic that uses window.InforWindow goes here
});