Why does next function not execute? - javascript

first i want to check if jquery exists or not then move on to next function. But next function abc() is not being executed. Maybe somebody knows why!
window.onload = function () {
if (window.jQuery) {
localStorage.setItem("key", "abc");
} else {
script = document.createElement("script");
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js";
document.head.appendChild(script);
}
};
function abc() {
$(document).keypress(function (e) {
alert(e.key);
});
}

There are a few issues with that code. It sounds like you want to call abc when jQuery has been loaded, and for some reason you're allowing for the possibility it may or may not have been loaded prior to this code running. The issues I see are:
Setting a value in localStorage won't cause the function to be run; in fact, nothing in that code will cause abc to be run.
You're not declaring your script variable, which means the code is falling prey to what I call The Horror of Implicit Globals.
The load event on window happens really, really late in the page load process, after all images and other ancillary items are loaded. It's generally best to do your initialization sooner than that, by either using type="module" on your script element (if you're happy to use modules, which are handy) or by setting the defer attribute, or by putting the script at the very end of the body, just before the closing </body> tag (which is compatible with older browsers).
So here's what I might do instead, if I had to allow for this jQuery loaded/not loaded thing and I wasn't able to use modules (see comments):
// Use a wrapper if not using modules, to avoid creating unnecessary globals
(function() {
// Define your initialization function
function init() {
$(document).keypress(function (e) {
alert(e.key);
});
}
// If jQuery is loaded...
if (window.jQuery) {
// ...init
init();
} else {
// Otherwise, load it and init when it's loaded
var script = document.createElement("script");
// ^^^−−−−−−−−− prevents the horror of implicit globals
script.onload = init; // <=== Calls `init` when the script successfully loads
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js";
document.head.appendChild(script);
}
})();

Related

Can I limit scope of jQuery version I need using noConflict() if other scripts' loading order is unknown?

I want to asynchronously include a specific version of jQuery in a page I don't control (e-commerce platform) and only use it in my script. The page may load other scripts, which may also want to do the same thing, and I don't know the order in which the page includes my script vs others.
Using jQuery.noConflict([removeAll]), can I ensure that:
my script gets the right version of jQuery
I don't overwrite jQuery version for anyone else?
I think this question is different from most other multiple jQuery version questions because people make assumptions about script inclusion order and don't use asynchronous jQuery loading with callbacks.
Thanks!
Here's my attempt at this (could someone confirm this is ok?):
myscript.js
(function() {
var myJQuery;
function loadjQuery(url, callback) {
var runCallbackOnSuccess = function() {
if (typeof jQuery != "undefined") {
myJQuery = jQuery.noConflict(true); // NOTICE THIS LINE
callback();
}
};
var scriptTag = document.createElement("script");
scriptTag.setAttribute("src", url);
scriptTag.onload = runCallbackOnSuccess;
document.getElementsByTagName("head")[0].appendChild(scriptTag);
}
function doSomethingInMyScript() {
myJQuery(document).ready(....);
}
loadjQuery("https://code.jquery.com/jquery-A.B.C.min.js", doSomethingInMyScript);
})();
otherscript.js (outside my control, but assuming it's like this)
(function() {
function loadjQuery(url, callback) {
<same as above, but without the noConflict() call>
}
function doSomethingInOtherScript() {
jQuery(document).ready(....);
}
loadjQuery("https://code.jquery.com/jquery-X.Y.Z.min.js", doSomethingInOtherScript);
})();
Will this code work regardless of:
whether the page includes myscript.js or otherscript.js first
whether the callback functions for myscript.js or otherscript.js is executed first?
I suspect it should be fine as long as the callback functions are executed immediately after each respective jQuery is loaded, with no possibility of code from the other script interleaving between jQuery loaded and callback executed.

provide jquery script that won't interrupt client's page

I've got a script started that I will need to offer my customers. The idea is that they drop a line of code in their web page and my script does what it needs for them. (in this case, all it is doing is loading content into a div; an image with a link)
so..the customer drops in a <div id="name_of_div"></div> and a script tag pointing to this:
if (!window.jQuery) {
var jq = document.createElement('script'); jq.type = 'text/javascript';
jq.src = "//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
}
if ($('#name_of_div').length) {
$('#name_of_div').load('[content url]');
};
}
I'm pretty sure this roughly works how I'd like, however, I've been reading some things about "never do things globally" and something about putting this stuff inside a function so it doesn't encroach on the page's DOM.. do I have that right?
I'm thinking I can enclose in a function to guarantee my own scope...but what other steps should I take to make sure my script, when included into someone else's page, doesn't block or mess with anything already existing?
Secondly, is it better to use jquery.load() or a simple iframe?
thanks
Putting the code into a function is one step toward isolating it. Putting it into an anonymous and immediately-invoked function expression is the next step. Consider this:
(function () {
if (!window.jQuery) {
var jq = document.createElement('script'); jq.type = 'text/javascript';
jq.src = "//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
}
if ($('#name_of_div').length) {
$('#name_of_div').load('[content url]');
}
})();
Nothing outside of that function can see its internals, so it doesn't pollute global scope. (Just be sure not to, for example, create values on the window object within that function.) The function is created and immediately executed (note the parentheses at the end), allowing it to just do its thing and be done.
If there are further interactions that would need to take place, such as exposing an API for your users, then you can return the API object from that function. Something like this:
var yourAPI = (function () {
var someAPIFunction = function () {
// some piece of functionality a user may call later
};
return {
someAPIFunction = someAPIFunction
};
})();
Now the user can create that yourAPI object and put it in whatever scope he would like. It exposes only what you want it to expose, and the rest of your internal work is simply performed and completed that one time when the page loads.

How to add new script and wait for it to execute in Javascript

Let's say I've got my-file.js or some CDN file in different server that has
for (var i = 0; i < 1000; i ++) {
//something really long and hard to execute
}
//after this long execution
window.myObj = {
//initialization of some global object that I need
}
(I cannot change my-file.js...)
I want to add my-file.js asynchronously to page, and then, after it is loaded and EXECUTED I want to call some event like:
//when my my-file.js is loaded I finally use window.myObj
window.myObj.somefunc(); //yaaay
Is it possible? (cross browser for IE9+ is important for me, but any not critical)
Note:
In case file I need is on CDN or somewhere on different server - I need to remember about cross-domain policy, so I think loading content of file in ajax is not possible in such case.
Note 2:
http://www.chromestatus.com/features/5711871906676736 there is exacly what I need, but I bet it'll be few years before you can easly use it globally.
var script = document.createElement('script');
script.onload = function(){
// loaded
}
document.head.appendChild(script);
script.src = "path/to/script";
That's about the simplest example. And yes, the entire thing is async, hence it needed the onload handler.
You could also wrap it up in a function:
function getScript(src,callback){
var script = document.createElement('script');
script.onload = callback;
document.head.appendChild(script);
script.src = src;
}
getScript('path/to/js',function(){
//loaded
});
However, thinking out of the box, it sounds like you need dependency management. Use RequireJS. Should fit your needs.
jQuery getScript has a callback you can use to execute events after a file is loaded, or you can use script.onload as in Joseph's example:
http://api.jquery.com/jquery.getscript/
If you want to wait until a certain property is available (ie after some work has finished), you can create an interval and then clear it as soon as the property is found in window, ie:
var waitForObj = setInterval(function(){
if(window.myObj && window.myObj.somefunc){
clearInterval(waitForObj);
//Do some stuff you need this object for
}
}, 100);

Calling multiple JS files and functions

I'm trying to do the following:
- from an HTML page I want to call a .js file in the header. I want this file to contain 2 functions, A and B, that I want to call at different times as the page loads.
This first part I have ready, my problem is:
-Function B is supposed to call another .js file, wait for it to complete loading and run some code specific to function B.
This is what I have so far:
<head><script type="text/javascript" src="first.js"></script></head>
I have this to call the different functions that are inside first.js
<script language="JavaScript" type="text/javascript">
functionA ();
</script>
Now inside first.js:
function functionA ()
{
alert("A runs!");
}
function functionB ()
{
alert("B runs!");
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "http://www.URL.com" ;
--some additional code--
}
Suggestions? Thanks!
First off, you don't "call a javascript file". You load the javascript file which causes it to get parsed and any top level code is executed. Once loaded, you can then call any functions in it.
So, to load a javascript file from functionB and then call a function in it, you can finish the dynamically loaded code you started with, but then you need to add a notification for when it is loaded:
function functionB () {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "http://www.URL.com" ;
script.onload = function() {
// call the function in the newly loaded scrip here
};
document.getElementsByTagName("head")[0].appendChild(script);
}
Here's a post with a loadScript function that takes a callback when the script is loaded.
Here's a post with a bit more capable function that can actually load scripts sequentially and also contains support code for older versions of IE (if that is required).
Making sure an external js file has been loaded across browsers requires more than a simple onload event; If you want a well-tested solution with added features, your best bet is using a library such as require.js.
Your code, after you include the require.js file somewhere, will look something like:
function functionA () {
alert("A runs!");
}
function functionB () {
alert("B runs!");
require(['yourotherfile'], function(myfile) { // no js extension, read more in require's docs
// --some additional code--
});
}

Loading jquery after inserting the jquery tag

I insert the jquery tag
var newScript = document.createElement("script");
newScript.id = "grazit_jq";
newScript.type = "text/javascript"
newScript.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js";
script.parentNode.appendChild(newScript);
And after that I want to check if jquery exists.
I do so in a few ways.One way is like this:
var checkJquery=function(){
if(typeof(jQuery) === 'undefined')
{
console.log('jQuery doesnt exist');
window.setTimeout(arguments.callee,1000);
return;
}
else{
sprk_lib=new sprk();
sprk_lib.load(jQuery);
}
};
sprk.prototype.load=function($){
console.log($);
};
UPDATE
Now i updated the code. It will call the function as soon as the jQuery object is availeable.
In that function I will execute my jquery code. Do you think that there will be problems? is it okay to do it that way?
original
I wait there. problem is that in the console log , it returns null and the prints jQuery exists. How can I stop the script till the jquery is loaded,, and then continue executing the script?
Consider using an established JavaScript script loader such as LABjs or LazyLoad which offer reliable callbacks that don't fire until the script has fully loaded.
Check out this summary of 5 JavaScript script loaders.
For example:
LazyLoad.js('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js', function () {
console.log('jQuery exists!');
console.log('Document title: ' + $("title").text());
});
One point of note - if you want to hold off all further script execution until after jQuery has loaded, you could put the rest of your script inside this callback function. However, that would break a whole load of best practices (separation of concerns, loose coupling etc) so your best bet is to pass an existing function as your callback, which can in turn call out to other functions etc. For example:
function doSomething() {
console.log('I am doing something!')
doSomethingElse();
}
function doSomethingElse() {
console.log('I am doing something else!');
}
LazyLoad.js('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js', doSomething);
You could further improve your application architecture (e.g. by introducing PubSub) but that's getting outside the scope of this question so I'll leave it there.

Categories

Resources