I want to load a javascript file at the end of jquery.ready so that the code in my ready handler doesn't have to wait to execute until this large javascript file is loaded.
My jquery.ready code doesn't rely on this javascript file at all.
Would this be a good way to do that?
$(function(){
...
...
$('head').append('<script type="text/javascript" src="/largejs.js"></script>');
});
Use .getScript:
http://api.jquery.com/jQuery.getScript/
$(document).ready(function(){
...
...
$.getScript("largejs.js");
});
solution will check jquery already loaded, if not it will check after some time here 500ms and loop until it found jquery
function loadScriptAfterJQueryReady(jsFile) {
setTimeout(function () {
var loadScript=true;
if (typeof jQuery == 'undefined') {
if (typeof window.jQuery == 'undefined') {
/* jQuery is not loaded */
loadScript=false;
loadScriptAfterJQueryReady(jsFile);
}else{
/* jQuery is loaded */
}
} else {
/* jQuery is loaded */
}
if(true==loadScript) jQuery.getScript(jsFile);
}, 500);
}
loadScriptAfterJQueryReady("my.js");
The quoted "</script>" tag will actually end your block of JavaScript prematurely.
I'd use this method:
var newScript = $(document.createElement('script'));
newScript.src="/largejs.js"
If your application is new and not too far along yet, you could get a lot out of using LABjs for that purpose. It allows all your script files to load in parallel or, even, at any other time that you prefer (on demand).
http://labjs.com/
Related
I need to include and run the following from an AJAX callback (native JavaScript, no libraries):
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
So the following works on all web browsers that I tested, except (of course) IE11:
var scrt = document.createElement("script");
scrt.setAttribute('async', '');
scrt.setAttribute('src', 'https://platform.twitter.com/widgets.js');
scrt.setAttribute('charset', 'utf-8');
document.body.appendChild(scrt);
IE shows no errors but the script from widgets.js is not executed.
So is there another way to do it that works with IE?
Try this code to check if (when) twttr is available (loaded):
function checkTwitter() {
if (!twttr.widgets) {
setTimeout(checkTwitter.bind(this), 100);
} else {
// init:
twttr.widgets.load();
}
}
setTimeout(checkTwitter.bind(this), 100);
See twitter initialization
P.S.: I'm not sure if you have to write 'twttr.widgets' or 'window.twttr.widgets'
I'm writing a bookmarklet using jQuery. It looks like javascript:document.write('<script src="path/to/loader.js"></script>'), and loader.js does the initializing stuffs:
check_the_environment();
document.head.innerHTML='<meta charset=utf-8>';
document.body.innerHTML='(the webpage)';
var jq=document.createElement('script');
jq.src='path/to/jquery.min.js';
document.head.appendChild(jq);
function load_core() {
if(window.$)
eval('(core js code)');
else
setTimeout(load_core,50);
}
load_core();
The loader loads the core javascript code after the jQuery is available.
But sometimes I get this error in my core code:
$(...).on is not a function
It seems that jQuery was still initializing itself although $ variable is setted.
So, I need to wait for jQuery to be completely initialized before the loader loads the core code. How can I do that?
The traditional way of using $(document).ready(...) is infeasible, as jQuery is being loaded after the webpage is ready.
Here is a minimal Python code to check whether the solution is working:
import cherrypy
mod='''
var htmlroot=document.getElementsByTagName('html')[0];
function load_core() {
if(window.jQuery)
jQuery(function(){
alert($(document).on);
});
else
setTimeout(load_core,10);
}
if(!document.head)
htmlroot.appendChild(document.createElement('head'));
var jquery=document.createElement('script');
jquery.src='http://libs.useso.com/js/jquery/2.1.1/jquery.min.js';
document.head.appendChild(jquery);
load_core();
'''
class Website:
#cherrypy.expose()
def mod(self,_time):
return mod
#cherrypy.expose()
def index(self):
return '''Mod'''
cherrypy.quickstart(Website(),'/');
The right and foolproof way would be:
jQuery(function(){
// code
});
Since jQuery may be loaded in noConflict mode the $ var may not have been initialized.
For the sake of productivity the following can also be used to have access to $ var inside the jQuery scope.
jQuery(function($){
// you can use $ without worrying about conflicts now
});
You can check type of $ as below
if(typeof $ == "function"){
//Jquery loaded
}
I'm building a small web app with a few other people. I want to allow the other developers to define a couple of functions that are always called when the document is ready.
Our app inserts the following script into the HTML body of every page:
<script type="text/javascript">
(function(){
window.Utils = {
funcs: {}
};
$(document).ready(function(){
alert('Calling funcs...');
var startFunc = Utils.funcs['start'];
if (startFunc != undefined){
startFunc();
}
var finishFunc = Utils.funcs['finish'];
if (finishFunc != undefined){
finishFunc();
}
});
})();
</script>
Then, in a separate .js file, a developer should be able to do the following:
Utils.funcs['start'] = function(){
alert('Starting...');
};
Utils.funcs['finish'] = function(){
alert('Finishing...');
};
But this doesn't work. The functions are never called?
jsFiddle link: http://jsfiddle.net/XvQtF/
jsFiddle's (very surprising) default is to put your code in a window load handler. (You can see this on the left at the top, the second drop-down box says "onload".) That happens very late in the loading process, long after ready has fired. So the functions aren't added until after you've tried to run them.
If the other developers put their functions in Utils.funcs in script elements after your element defining Utils but without waiting for a load event, it's fine: Updated Fiddle
For what it's worth, though, I would lean toward using a pub/sub solution rather than a single function. If you want to have more than one start function, for instance, your current structure doesn't allow it.
jQuery has Deferred and Promise now, which can be used for this. Here's a simple example of that: Live Copy | Live Source
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<meta charset=utf-8 />
<title>Pub/Sub with Deferred and Promise</title>
</head>
<body>
<script>
(function($) {
// Deferred objects for our app states
var start = new $.Deferred(),
finish = new $.Deferred();
window.Utils = {
start: start.promise(), // Only expose the Promise of each
finish: finish.promise() // " " " " " "
};
$(function() {
alert("Calling funcs...");
// Start the app
start.resolve();
// Finish the app (or whatever)
finish.resolve();
});
})(jQuery);
</script>
<script>
// Module 1
Utils.start.then(function() {
alert("Module 1 Started!");
});
Utils.finish.then(function() {
alert("Module 1 Finished!");
});
</script>
<script>
// Module 2
Utils.start.then(function() {
alert("Module 2 Started!");
});
Utils.finish.then(function() {
alert("Module 2 Finished!");
});
</script>
</body>
</html>
Set up Utils in a separate script to be loaded as the very first one. Also, do this unconditionally (not in any callback etc):
/* load as first script, sets up a global container-object for later use */
var Utils = {
funcs: {}
}
Note that it is ok to define a global variable in the global scope.
/* other script */
(function(){
function myFunc() { /*...*/ };
// now store a reference in Utils
Utils.funcs.start = myFunc;
})();
As mentioned in an other answer: Be aware of the loading and calling order of your various scripts / code:
$(document).ready is essentially the "DOMContentLoaded"-event with most browsers (but earlier versions of IE). "DOMContentLoaded" fires, when all inline-resources originally found in the head-section have been loaded and the DOM-structure of the body is present.
Since this does not include any injected content, it is probably granted, that the event is fired before any modular library (which are loading modules by injecting script tags) is fully loaded and present. (Given that these scripts are loading concurrently with images and other inline-stuff using just a handful of network-slots/sockets provided by the browser, they are probably one of the last things to be ready in your whole loading-process.)
Instead of just using
startFunc() and
finishFunc()
try using this
startFunc.apply(this, null) and
finishFunc.apply(this, null)
this will invoke the functions.
also make sure that
Utils.funcs['start']
Utils.funcs['finish']
is getting initialized before they are called.
Is there any way to check if javascript file is already attached to the page by its file name.
For eg :
if ("path-to-script/scriptname.js") already embeded
{
call related function
}
else
{
Append '<script src="path-to-script/scriptname.js" type="text/javascript"> </script> '
call related function
}
Basically I dont want 1 script to be attached twice on the same page.
You might not always know what objects or functions a script contains in advance, in such cases you can search for script tags containing the desired src.
With jquery:
$("script[src*='"+scriptName+"']");
Without jquery:
document.querySelector("script[src*='"+scriptName+"']");
You'd need to test whether the actual function from the script file exists, like this:
if (window.function_name) {
// script loaded
} else {
// script not loaded
}
I agree with #zathrus though I think you should be using requirejs for things like this. The idea is that dependencies must be fetched before executing the code. The above method you are using may work but you can not guarantee anything.
RequireJS will beautifully maintain all the dependency loading. It is very easy to learn as well.
Simply check if the library is defined, otherwise import it:
if ( !jQuery ) {
var s = document.createElement('script');
s.type = 'text/javascript';
document.body.appendChild(s);
s.src = "path-to-script/scriptname.js";
void(0);
}
// call function
you really need a script loader.. because as you said you want it specific with the javascript resource filename and this is sort of your javascript files are depending to each other
www.headjs.com
www.modernizr.com
www.yepnopejs.com
I thought this will help you.
if (typeof scriptname== "undefined") {
var e = document.createElement("script");
e.src = "scriptname.js";
e.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
}
I have a page where I am using jquery/ajax to pull down a chunk of HTML/JS from another component and injecting it into the page. That HTML references additional JS files, and I need those referenced JS files to be loaded before I run my javascript.
The HTML/JS that is being injected looks something like this:
<script type="text/javascript" src="http://myserver/js/ABunchOfStuff.js"></script>
<div>
blah blah blah
</div>
<script type="text/javascript">
//"sourceList" is defined in the ABunchOfStuff.js above, but it's not available by the time this executes.
$("input#autocomplete").autocomplete({
source: sourceList,
minLength: 2
});
</script>
Normally I would just hook into a window load event or a $(document).ready() or whatever, but in this case the window and document have already been completely loaded, and now we're adding additional content after the fact.
One possiblity would be to put a recursive setTimeout call in that would keep firing until the referneced javascript was available, but that's pretty ugly.
So is there any clean way to trap the event of a referenced javascript has been loaded and to execute code at that time?
Thanks
You can also use getScript and do your autoComplete in the success callback:
jQuery.getScript( 'http://myserver/js/ABunchOfStuff.js', function(data, textStatus) {
$("input#autocomplete").autocomplete({
source: sourceList,
minLength: 2
});
} );
The big question is, how do you inject this script ?
If you using "standard" script tag insertion, you can go and watch for the onload event (onreadystatechange in IE).
var scr = document.createElement('script');
scr.type = 'text/javascript';
scr.src = 'somewhere/somename.js';
scr.onload = scr.onreadystatechange = function() {
if( /complete|loaded/.test(scr.readyState) ) {
// do something
}
else {
// do something
}
};
What you are doing wrong here is not waiting for the DOM to load.
If you change your .autocomplete to only execute once the DOM is loaded through $(document).ready it will have executed the ABunchOfStuff.js
Like this:
(function($) {
$(document).ready(function() {
$("input#autocomplete").autocomplete({
source: sourceList,
minLength: 2
});
}
}(jQuery));
If you control the http://myserver/js/ABunchOfStuff.js file, then you can call your other JS from it when it first executes. Since it executes when it first loads and when it's available, you have the perfect timing.
If this JS file is used other places too, you could add some generic functionality to it for calling a callback when it executes by adding something like this to it:
try {
if (aBunchOfStuffCallbacks) {
for (var i = 0; i < aBunchOfStuffCallbacks.length; i++) {
aBunchOfStuffCallbacks[i].call(this); // call callback to announce we're loaded
}
} catch(e) {}
And, then in any web page where you want to be called when aBunchOfStuffCallbacks was loaded, you would just do this:
var aBunchOfStuffCallbacks = [];
aBunchOfStuffCallbacks.push(myFunc);
function myFunc() {
// put my code here for when aBunchOfStuffCallbacks is loaded
}
This would allow for multiple callbacks. The simpler version for just one callback looks like this:
try {
if (aBunchOfStuffCallback) {
aBunchOfStuffCallback.call(this); // call callback to announce we're loaded
}
} catch(e) {}
And, it would look like this to set it:
var aBunchOfStuffCallbacks = function () {
// put my code here for when aBunchOfStuffCallbacks is loaded
}