Let\'s face it, jQuery/jQuery-ui is a heavy download.
Google recommends deferred loading of JavaScript to speed up initial rendering. My page uses jQuery to set up s
There is a simple trick which Google Analytics uses.
1. In the head of your HTML add a tiny script
<script>
window.jQuery_store = [];
window.jQueryReady = function (fn) { jQuery_store.push(fn); }
</script>
The function jQueryReady will just save delegates into an array for future use.
2. Create a new JS script jquery-ready.js
with next content:
// When jQuery is finaly ready
$(function() {
// Replace previous implementation
window.jQueryReady = function(fn) {
// jQuery is loaded call immediately
fn();
}
// Call all saved callbacks
for (var i = 0; i < window.jQuery_store.length; ++i) {
try {
window.jQuery_store[i]();
} catch (err) {
console.log(err);
}
}
})
When this script is loaded, it will:
jQuery
is safe to usejQueryReady
with a new one, which just calls delegate immediately (the jQuery is ready at the given time).jQueryReady
calls.3. Put everything together Make jquery-ready.js load only after the jQuery is loaded. In your footer you will have:
<script defer src=".../jquery.min.js">
<script defer src=".../bootstrap.min.js">
... any other plugins for jQuery you probably need
<script defer src=".../jquery-ready.js">
This makes sure that the jquery-ready.js script will be executed only after the jQuery was executed.
You can now use jQueryReady function whenever you want.
jQueryReady(function() {
// jQuery is safe to use here
$("div.to-be-hidden").hide();
})
Here's my version which supports chaining to be sure the scripts are loaded one after each other, based on ampersand's code:
var deferredJSFiles = ['jquery/jquery', 'file1', 'file2', 'file3'];
function downloadJSAtOnload() {
if (!deferredJSFiles.length)
return;
var deferredJSFile = deferredJSFiles.shift();
var element = document.createElement('script');
element.src = deferredJSFile.indexOf('http') == 0 ? deferredJSFile : '/js/' + deferredJSFile + '.js';
element.onload = element.onreadystatechange = function() {
if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')
downloadJSAtOnload();
};
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener('load', downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent('onload', downloadJSAtOnload);
else
window.onload = downloadJSAtOnload;
As this is a top ranking question on a important subject let me be so bold to provide my own take on this based on a previous answer from @valmarv and @amparsand.
I'm using a multi-dimensional array to load the scripts. Grouping together those that have no dependencies between them:
var dfLoadStatus = 0;
var dfLoadFiles = [
["http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"],
["http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js",
"/js/somespecial.js",
"/js/feedback-widget.js#2312195",
"/js/nohover.js"]
];
function downloadJSAtOnload() {
if (!dfLoadFiles.length) return;
var dfGroup = dfLoadFiles.shift();
dfLoadStatus = 0;
for(var i = 0; i<dfGroup.length; i++) {
dfLoadStatus++;
var element = document.createElement('script');
element.src = dfGroup[i];
element.onload = element.onreadystatechange = function() {
if ( ! this.readyState ||
this.readyState == 'complete') {
dfLoadStatus--;
if (dfLoadStatus==0) downloadJSAtOnload();
}
};
document.body.appendChild(element);
}
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
It loads first jquery after it is loaded it continue to load the other scripts at once. You can add scripts easy by adding to the array anywhere on your page:
dfLoadFiles.push(["/js/loadbeforeA.js"]);
dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
dfLoadFiles.push(["/js/loadafterB.js"]);
The following code should load your scripts after the window is finished loading:
<html>
<head>
<script>
var jQueryLoaded = false;
function test() {
var myScript = document.createElement('script');
myScript.type = 'text/javascript';
myScript.async = true;
myScript.src = jQueryLoaded ? 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js' : 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js';
document.body.appendChild(myScript);
if(!jQueryLoaded){
alert('jquery was loaded');
jQueryLoaded = true;
test();
} else {
alert('jqueryui was loaded');
}
}
if (window.addEventListener){
alert('window.addEventListener');
window.addEventListener("load", test, false);
} else if (window.attachEvent){
alert('window.attachEvent');
window.attachEvent("onload", test);
} else{
alert('window.onload');
window.onload = test;
}
</script>
</head>
<body>
<p>Placeholder text goes here</p>
</body>
</html>
Worked for me in Chrome, FF and IE9 - let me know if that helps