I have a small mobile page with a few big js files (including jQuery)
The page speed is pretty slow and the google page speed analysis suggests to move the 'render-blocking javascript below the fold'. My page is pretty small to begin with, so everything on it is already above the fold.
I would normally async the javascript, but the javascript needs to run in order
(First jQuery, then the plugin, and finally my own code which is inline)
So async loading on the code would cause it to run out of order, usually jquery loading last and everything else breaking before hand.
Is there an easy way to push everything below the fold? or at least make the browser treat the javascript like it is below the fold all while loading everything in order?
If all of your content is above the fold you should be able to simply put all of your javascript files towards the bottom of your document and above your closing </body> tag.
I ended up fixing the problem by wrapping the code in a callback after the page loads. Here is the code that I used:
function appendScript(src, callback) {
callback = callback || function(){};
var element = document.createElement("script");
element.src = src;
element.async = false;
element.onload = callback;
document.body.appendChild(element);
}
function downloadJSAtOnload() {
appendScript("http://code.jquery.com/jquery-1.11.1.min.js", function(){
appendScript("http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js", doStuff);
});
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
doStuff(){
// MY CODE HERE
}
I forgot to mention in my question that the code embedded on the page isn't much at all. It is just a few snippets but would be much harder without jquery.
I hope this helps out anyone else who is trying what I tried to do
Google said my page was rather slow and showed me some 'techniques' to defer load those JS.
Apparently, after I used the technique, it seems that my site other scripts doesn't load because it's slower than External Script fetching. Specifically:
SCRIPT :
function downloadJSAtOnload() {
var jq = document.createElement("script");
jq.src = "path/to/jquery.min.js";
document.body.appendChild(jq);
var bs = document.createElement("script");
bs.src = "path/to/bootstrap.min.js";
document.body.appendChild(bs);
}
// Check for browser support of event handling capability
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
//Scripts here aren't able to load even though jquery is called above
$('.tips').tooltip();
$(document).ready(function() {/**something here**/
});
How can I solve this problem?
i have the following code in the part of my html and was wondering how i could clean it up to optimize the loading.
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "js/jquery.orbit-1.2.3.min.js";
document.body.appendChild(element);
}
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "http://code.jquery.com/jquery-latest.min.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
If your goal is to allow the page to be displayed before the scripts are loaded, there's a much easier way: Just put the script tags (in the appropriate order) at the very end of the body, just before the closing </body> tag:
<!-- ...content of page... -->
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="js/jquery.orbit-1.2.3.min.js"></script>
</body>
</html>
The load event on the window object happens very late in the page load process, after all other resources have been completely loaded (or failed to load). So all images, both foreground and background, etc.
By putting the scripts right at the end of the body, you get them in the browser's download queue at a reasonable time, but without making the browser wait for the script to arrive before doing the initial page rendering. You also get the ordering (you'd get that with the defer attribute on the script element as well, but not all browsers support it). More: YUI Best Practices for Speeding Up your Website
You've asked in the comments when you would use the load event for script loading. My answer is: I've never had a reason for doing so.
I use this code to load my JS async in the head
<script type='text/javascript'>
// Add a script element as a child of the body
function downloadJSAtOnload() {
var element4= document.createElement("script");
var element5= document.createElement("script");
element4.src="http:///ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"
element5.src="http://yourjavascript.com/301810712121/slidemenu_horiz.js"
element4.async=true;
element5.async=true;
document.body.appendChild(element4);
document.body.appendChild(element5);
}
// Check for browser support of event handling capability
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
In IE and Firefox works fine, but in Chrome I have this error:
"Uncaught ReferenceError: jQuery is not defined "
When I refresh the page for second time (or third) the script works fine in Chrome, please I need to know how to resolve this.
Given your needs, and because I've used it successfully in the past I'd suggest using LABjs - http://labjs.com/
As mentioned, there are loads of script loaders to choose from - LABjs is focused on performance more than anything and doesn't include many of the extra features that others such as requirejs (AMD loader), YepNope (feature detection-based conditional loader) have. If all you need is to load your scripts asynchronously and have control over the execution order, LABjs is a very small script that handles this well.
Using LABjs, you'd do the following to replicate your code above:
<script src="js/libs/LAB.js"></script>
<script>
$LAB
.script('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js').wait()
.script('http://yourjavascript.com/301810712121/slidemenu_horiz.js')
.wait(function () {
// Check jQuery has loaded (could do this for the slider as well)
if (window.jQuery) {
// Do something with your slider
}
});
</script>
In the example above, the .wait() function ensures that jQuery has executed before slidemenu_horiz.js - the last .wait() is passed an anonymous function as a callback - within this you can test that everything has loaded and then do your initialisations.
It's worth checking out all the options as far a script loaders go. There really are loads out there and each has a different feature set that you may find addresses your problem better.
EDIT: Added script reference to LABjs in code example for clarity
I want to run a function when the page is loaded, but I don’t want to use it in the <body> tag.
I have a script that runs if I initialise it in the <body>, like this:
function codeAddress() {
// code
}
<body onLoad="codeAddress()">
But I want to run it without the <body onload="codeAddress()"> and I have tried a lot of things, e.g. this:
window.onload = codeAddress;
But it is not working.
So how do I run it when the page is loaded?
window.onload = codeAddress; should work - here's a demo, and the full code:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
window.onload = codeAddress;
</script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
</script>
</head>
<body onload="codeAddress();">
</body>
</html>
Rather than using jQuery or window.onload, native JavaScript has adopted some great functions since the release of jQuery. All modern browsers now have their own DOM ready function without the use of a jQuery library.
I'd recommend this if you use native Javascript.
document.addEventListener('DOMContentLoaded', function() {
alert("Ready!");
}, false);
Alternate solution. I prefer this for the brevity and code simplicity.
(function () {
alert("I am here");
})();
This is an anonymous function, where the name is not specified.
What happens here is that, the function is defined and executed together.
Add this to the beginning or end of the body, depending on if it is to be executed before loading the page or soon after all the HTML elements are loaded.
Taking Darin's answer but jQuery style. (I know the user asked for javascript).
running fiddle
$(document).ready ( function(){
alert('ok');
});
window.onload = function() { ... etc. is not a great answer.
This will likely work, but it will also break any other functions already hooking to that event. Or, if another function hooks into that event after yours, it will break yours.
So, you can spend lots of hours later trying to figure out why something that was working isn't anymore.
A more robust answer here:
if(window.attachEvent) {
window.attachEvent('onload', yourFunctionName);
} else {
if(window.onload) {
var curronload = window.onload;
var newonload = function(evt) {
curronload(evt);
yourFunctionName(evt);
};
window.onload = newonload;
} else {
window.onload = yourFunctionName;
}
}
Some code I have been using, I forget where I found it to give the author credit.
function my_function() {
// whatever code I want to run after page load
}
if (window.attachEvent) {window.attachEvent('onload', my_function);}
else if (window.addEventListener) {window.addEventListener('load', my_function, false);}
else {document.addEventListener('load', my_function, false);}
Hope this helps :)
Try readystatechange
document.addEventListener('readystatechange', () => {
if (document.readyState == 'complete') codeAddress();
});
where states are:
loading - the document is loading (no fired in snippet)
interactive - the document is parsed, fired before DOMContentLoaded
complete - the document and resources are loaded, fired before window.onload
<script>
document.addEventListener("DOMContentLoaded", () => {
mydiv.innerHTML += `DOMContentLoaded (timestamp: ${Date.now()})</br>`;
});
window.onload = () => {
mydiv.innerHTML += `window.onload (timestamp: ${Date.now()}) </br>` ;
} ;
document.addEventListener('readystatechange', () => {
mydiv.innerHTML += `ReadyState: ${document.readyState} (timestamp: ${Date.now()})</br>`;
if (document.readyState == 'complete') codeAddress();
});
function codeAddress() {
mydiv.style.color = 'red';
}
</script>
<div id='mydiv'></div>
Take a look at the domReady script that allows setting up of multiple functions to execute when the DOM has loaded. It's basically what the Dom ready does in many popular JavaScript libraries, but is lightweight and can be taken and added at the start of your external script file.
Example usage
// add reference to domReady script or place
// contents of script before here
function codeAddress() {
}
domReady(codeAddress);
window.onload will work like this:
function codeAddress() {
document.getElementById("test").innerHTML=Date();
}
window.onload = codeAddress;
<!DOCTYPE html>
<html>
<head>
<title>learning java script</title>
<script src="custom.js"></script>
</head>
<body>
<p id="test"></p>
<li>abcd</li>
</body>
</html>
As soon as the page load the function will be ran:
(*your function goes here*)();
Alternatively:
document.onload = functionName();
window.onload = functionName();
I believe this is the best way to maintain support across different versions of browsers
if (window.addEventListener) {
window.addEventListener("load", myFunction, false);
}
else if (window.attachEvent) {
window.attachEvent("onload", myFunction);
}
else {
window.onload = myFunction; //will override previously attached event listeners.
}
Universal Cross-Browser Web Page Loader
I wrote a JavaScript page loader that should solve your issues loading a function after the page is loaded. This web page loader is 99.9% cross-browser compatible and works in many versions of browsers, old and new, unlike the other posts. Includes support for loading pages in nearly all browsers, including Internet Explorer 3-11, all Firefox and Chrome browsers, early Opera, all mobile browsers, Netscape 4 and 6 series, etc.
It will pick the fastest page load event or state check for a given browser and return a text string indicating JavaScript may safely process the Document Object Model (DOM). Should work in many legacy browsers, but test. Place your JavaScript functions or or library calls inside the "Start()" method below, so they are triggered as soon as the script says the web page or DOM is loaded in the browser.
As a side note, I recommend you place this code either:
In the head of your html page in a embedded <script> block as a synchronous script, which pauses the page to load early.
...or...
In a loaded external <script> tag file with the "async" attribute added so it loads quietly in parallel to your page but pauses html loading when download complete so it gets parsed and processed first.
The script should not render-block much if using these methods. You want this script ready when the web page DOM is first built and not after, especially since later states of the page could get delayed waiting for images, videos, and JavaScript API's to download.
// ======== AFTER PAGE LOADS CALL YOUR SCRIPTS HERE =========
function Start(status) {
// In most modern browsers the console should return:
// "Browser Loader : Document : DOMContentLoaded : interactive"
console.log(status);
// add your script calls here...
};
// ======== JAVASCRIPT PAGE LOADER =========
// Stokely Web Page loader, 2022
if (document.readyState) {
if (document.readyState === "complete" || document.readyState === "loaded") {
Start("Browser Loader : Document : readyState : complete");
} else {
if (window.addEventListener) {
// Never try and call 'DOMContentLoaded' unless the web page is still in an early loading state.
if (document.readyState === 'loading' || document.readyState === 'uninitialized') {
window.addEventListener('DOMContentLoaded', function () {
// Most modern browsers will have the DOM ready after this state.
if (document.readyState === "interactive") {
Start("Browser Loader : Document : DOMContentLoaded : interactive");
} else if (document.readyState === "complete" || document.readyState === "loaded") {
Start("Browser Loader : Document : DOMContentLoaded : complete");
} else {
Start("Browser Loader : Document : DOMContentLoaded : load");
}
}, false);
} else {
// FALLBACK LOADER : If the readyState is late or unknown, go ahead and try and wait for a full page load event. Note: This function below was required for Internet Explorer 9-10 to work because of non-support of some readyState values! IE 4-9 only supports a "readyState" of "complete".
if (document.readyState === 'complete' || document.readyState === "loaded") {
Start("Browser Loader : Document : readyState : complete");
} else {
window.addEventListener('load', function () {
Start('Browser Loader : Window : Event : load');
}, false);
}
}
// If 'addEventListener' is not be supported in the browser, try the 'onreadystate' event. Some browsers like IE have poor support for 'addEventListener'.
} else {
// Note: document.onreadystatechange may have limited support in some browsers.
if (document.onreadystatechange) {
document.onreadystatechange = function () {
if (document.readyState === "complete" || document.readyState === "loaded"){
Start("Browser Loader : Document : onreadystatechange : complete");
}
// OPTIONAL: Because several versions of Internet Explorer do not support "interactive" or get flagged poorly, avoid this call when possible.
//else if (document.readyState === "interactive") {
//Start("Browser Loader : Document : onreadystatechange : interactive");
//}
}
} else {
// Note: Some browsers like IE 3-8 may need this more traditional version of the loading script if they fail to support "addeventlistener" or "onreadystate". "window.load" is a very old and very reliable page loader you should always fall back on.
window.onload = function() {
Start("Browser Loader : Window : window.onload (2)");
};
}
}
}
} else {
// LEGACY FALLBACK LOADER. If 'document.readyState' is not supported, use 'window.load'. It has wide support in very old browsers as well as all modern ones. Browsers Firefox 1-3.5, early Mozilla, Opera < 10.1, old Safari, and some IE browsers do not fully support 'readyState' or its values. "window.load" is a very old and very reliable page loader you should always fall back on.
window.onload = function () {
Start("Browser Loader : Window : window.onload (1)");
};
};
Note: When you run this script in a web browser, be sure to press F12 to pull up the browser tools screen and check the console tab to see the result. It will tell you at what stage the web page loader was triggered and when it called the 'Start()' script.
In most modern browsers (HTML5 or post-2010) it should be triggered as soon as the DOM or Document Object Model of HTML markup is rendered but the rest of the web page resources, CSS, images, video, and other files are still loading. In modern browsers this is usually between a readystate of "interactive" and "complete" and the DOM is built but the browser is still downloading other resource files. This allows your JavaScript to access and start manipulating the HTML tree or DOM very very early.
Older browsers like Internet Explorer v. 3-8 or Netscape, do not understand the advanced DOM checks so would require the full or "complete" load of the DOM and all page resources before calling your JavaScript.