I'm writing a Chrome extension modifying HTML DOM elements. I want to ask how could I wait for finished loading from websites bundled in webpack?
User window.onload
When do window.onload fires?
By default, it is fired when the entire page loads, including its content (images, css, scripts, etc.)
In some browsers it now takes over the role of document.onload and fires when the DOM is ready as well.
Example:
window.onload = function() {
// ..doSomethingElse..
};
See this: https://stackoverflow.com/a/588048
Related
I found this nice post at kirupa.com, but I'd like to understand in deep the order of load, rendering and execution of elements like DOM, Scripts, CSS, Images, IFrames, etc.
Until now I have understood the next order:
DOM
JS (I am guessing does not matter JS is inline or external, if it is external I guess DOM load is interrupted until the JS is loaded, rendered and executed)
internal CSS? (Or is it rendered together DOM load.)
external CSS
external Images
According the article 'While external style sheets won't get loaded, both inline and external scripts will though.' but according MDM 'Stylesheet loads block script execution'. So scripts are loaded first but they are executed only after all css are available?
I could think that order depends on the browser implementation or is there any standard to make this?
Does some expert would tell us the right order?
Thanks in advance!
I believe the order is something like this:
Download HTML document
Start HTML Parsing
Start downloading external files (JavaScript, CSS, images) as they're encountered in the HTML
Parse external files once they are downloaded (or if they are inline and don't require downloading)
if the files are scripts, then run them in the order they appear in the HTML
if they try to access the DOM right now, they will throw an error
while they run, they will prevent any other rendering, which is why some scripts are put at the bottom of the body
for CSS files, save the style rules in order they appear in the HTML
if they're images then display them
if the loading fails, then proceed without this file
End HTML Parsing
Create the DOM - including all the styles we have so far
Execute the DOMContentLoaded event when the DOM is fully constructed and scripts are loaded and run
happens even if all other external files (images, css) are not done downloading (from step 4)
in the Chrome F12 developer tools this is represented by a blue line on the Network view
will start running anything you've added to this event, e.g. window.addEventListener("DOMContentLoaded", doStuff, true);
Start painting the document to the display window (with any styles that have already loaded)
Execute the window.onload event when all external files have loaded
in the Chrome F12 developer tools this is represented by a red line on the Network view
this will start running the jQuery ready function $(document).ready(function(){ ... });
will start running any code you've added to this event, e.g. window.addEventListener("load", doStuff, true);
Re-paint the document, including any new images and styles
Note that the execution order of scripts that are dynamically added to your page (by other scripts) is complicated and basically indeterminate. (See the answers here load and execute order of scripts)
I was on jsfiddle.net recently and I saw this as a configuration option. This got me to thinking that it might help a problem I'm having as such:
I load multiple images (haven't upgraded to a single sprite yet) so that I can not use my controls until they are all downloaded...the images take most of the download time so that for the first few seconds I can not access my controls.
Currently I'm using one of these two..both work.
window.onload = initialize_page
window.addEventListener('load',initialize_page);
Related
Jquery document ready vs. window.onload
window.onload vs. body.onload vs. document.onready
window.onload vs <body onload=""/>
AFAIK onDomReady() fires once the DOM has loaded. If the page contains external sources, such as images, then it may fire before these have finished loading.
onLoad() fires after the whole page has finished loading, including external sources.
So it's possible for onDomReady() to fire before onLoad() but you'll have to test it on your page.
I'm learning Greasemonkey with the hopes of making some improvements to a webpage.
I think I have a good grasp of JavaScript, but I don't understand at what point in the rendering of the document the Greasemonkey user script is executed.
For instance, what if there is JavaScript natively inside the document that inserts some elements to the page. I want my Greasemonkey script to run only after that JS completes.
Let's say this is the document that I'm trying to modify with Greasemonkey
<html>
<script>
//insert a button with id="mybutton"
</script>
</html>
I want the <script> code to complete before my Greasemonkey script is run, because I want to alter its background color.
Greasemonkey runs at the DOMContentLoaded event by default. This means that everything will be in the page except for possibly large images and stuff added by some javascripts (scripts that fire on the load event or that AJAX-in content).
If you want to wait until even large media has loaded and "onload" scripts have run, use:
window.addEventListener ("load", Greasemonkey_main, false);
function Greasemonkey_main () {
//***** PUT YOUR GREASEMONKEY CODE HERE.
}
Do not use unsafeWindow.onload = function(){ ... } or window.onload = function() { /* logic here */ } as others have suggested. These are not only poor practice/won't work in GM, but the unsafeWindow is an unnecessary security risk in this case.
However, dealing with JS-added content:
Since you indicated that the node you care about is added by javascript, waiting for the load event will often not work. JS can add, remove or edit nodes at any time.
The best approach in cases like these is to poll for the element you are interested in ("#mybutton"). See this answer to "Fire Greasemonkey script on AJAX request".
I'm using a JavaScript upload script that says to run the initialize function as soon as the DOM is ready. I currently have it working just fine with either a call to the function with body.onload or directly after the function is defined. The function builds some HTML in a placeholder div that acts as the file uploader tool.
My question is what is the best practice here? Since it works for now, why would the instructions say to run the init function as soon as the DOM is ready? Should I be adding a <script> tag directly after the placeholder DIV for example?
<script>
window.addEventListener("DOMContentLoaded", function() {
// do stuff
}, false);
</script>
You do that so you know all the parsed elements are available in the DOM etc.
The easiest solution is using jQuery and its $(document).ready(function() { .... }); function. Instead of .... you put your own code.
Note that it basically does the same thing #Shadow2531 suggested, but also works in old browsers not supporting that event.
The DOM is usually ready before onLoad runs. onLoad only runs after everything loads - external scripts, images, stylesheets, etc.
But the DOM, i.e. the HTML structure is ready before that. If you run the code at the bottom of the page (or after the parts of the page the script works with) that will work fine as well.
In 2015 you have two options with modern browsers:
document.onload
this fires when the document is loaded, but other resources (most notably images) have not necessarily finished loading.
window.onload
this fires when the document is loaded, AND all other resources (again, most notably images) are loaded.
Both of the above events would be better utilized with window.addEventListener() of course, as multiple listeners would be allowed.
You could also just move the <script> to the bottom of your page like this:
<html>
<body>
<main></main>
<script>
// code
</script>
</body>
</html>
As you probably know you should not run init functions before the DOM is fully loaded.
The reason you must run the init function as soon as the DOM is ready, is that once the page has loaded the user starts hitting buttons etc. You have to minimize the small inavoidable gap where the page is loaded and the init-functions haven't run yet. If this gap gets too big (ie. too long time) your user might experience inappropiate behaviour... (ie. your upload will not work).
Other users have provided fine examples of how to call the init function, so I will not repeat it here... ;)
Get jQuery and use the following code.
$(document).ready(function(){
// Do stuff
});
var Tette =
{
init: function()
{
/* Your HTML code */
}
};
Core.start(Tette);
You can try in this code, registering "Core.start(your object)" on the last line of the script. This is a way to load in safety your functions after the DOM loading.
What is the difference between DOMContentLoaded and load events?
From the Mozilla Developer Center:
The DOMContentLoaded event is fired when the document has been
completely loaded and parsed, without waiting for stylesheets, images,
and subframes to finish loading (the load event can be used to detect
a fully-loaded page).
The DOMContentLoaded event will fire as soon as the DOM hierarchy has been fully constructed, the load event will do it when all the images and sub-frames have finished loading.
DOMContentLoaded will work on most modern browsers, but not on IE including IE9 and above. There are some workarounds to mimic this event on older versions of IE, like the used on the jQuery library, they attach the IE specific onreadystatechange event.
See the difference yourself:
DEMO
From Microsoft IE
The DOMContentLoaded event fires when parsing of the current page is complete; the load event fires when all files have finished loading from all resources, including ads and images. DOMContentLoaded is a great event to use to hookup UI functionality to complex web pages.
From Mozilla Developer Network
The DOMContentLoaded event is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the load event can be used to detect a fully-loaded page).
DOMContentLoaded==window.onDomReady()
Load==window.onLoad()
A page can't be manipulated safely until the document is "ready." jQuery detects this state of readiness for you. Code included inside $(document).ready() will only run once the page Document Object Model (DOM) is ready for JavaScript code to execute. Code included inside $(window).load(function() { ... }) will run once the entire page (images or iframes), not just the DOM, is ready.
See: Using JQuery Core's document-ready documentation.
For a full understanding I recommend to read the following articles:
What is DOM and CSSOM: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model
What is the render tree: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction
How is everything related to DOMContentLoaded, load and first print:
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/analyzing-crp
In Short:
The DOMContentLoaded event is fired when the DOM is created (see link 1 for more what the DOM is) and the load event is fired when the DOM, CSSOM and all other resources are loaded. If you don't have Javascript, then the order that your webpage is loaded may look like this:
Or in the words of an inspection window, the DOMContentLoaded event will be fired much earlier then the load event (blue line represents DOMContentLoaded, red line represents load event):
However, if you use Javascript (that is not async or defer) then the DOM creation will wait for the JS to load. Since JS also modifies CSS, JS will wait for the CSSOM to load.
Since this is the most common situation, the creation of the DOMContentLoaded event actually has to wait in most scenarios for the style-sheets to be loaded as well.
The loading chain look like this then:
So the main difference between DOMContentLoaded and load is, in this situation, only the loading time of the image, which can be downloaded in parallel to your style-sheets and JS.
Note that this doesn't happen if you use async or defer for your JS:
domContentLoaded: marks the point when both the DOM is ready and
there are no stylesheets that are blocking JavaScript execution -
meaning we can now (potentially) construct the render tree. Many
JavaScript frameworks wait for this event before they start executing their own logic. For this reason the browser captures the EventStart and EventEnd timestamps to allow us to track how long this execution
took.
loadEvent: as a final step in every page load the browser fires
an “onload” event which can trigger additional application logic.
source
Here's some code that works for us. We found MSIE to be hit and miss with DomContentLoaded, there appears to be some delay when no additional resources are cached (up to 300ms based on our console logging), and it triggers too fast when they are cached. So we resorted to a fallback for MISE. You also want to trigger the doStuff() function whether DomContentLoaded triggers before or after your external JS files.
// detect MSIE 9,10,11, but not Edge
ua=navigator.userAgent.toLowerCase();isIE=/msie/.test(ua);
function doStuff(){
//
}
if(isIE){
// play it safe, very few users, exec ur JS when all resources are loaded
window.onload=function(){doStuff();}
} else {
// add event listener to trigger your function when DOMContentLoaded
if(document.readyState==='loading'){
document.addEventListener('DOMContentLoaded',doStuff);
} else {
// DOMContentLoaded already loaded, so better trigger your function
doStuff();
}
}
The answer with the highest number of approvers is wrong, at least in the higher version of Chrome 80+.
1、DOMContentLoaded does not fire until the CSS and JavaScript are executed and the DOM is parsed (the document has been loaded)
2、The window.onload event, which does not fire until all network resources, such as CSS and JavaScript, have been loaded, and the DOM has been parsed (the document has been loaded)
Based on Chrome 80+ test results:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOMContentLoaded , load</title>
<link href="http://localhost/public/css?sleep=5000" rel="stylesheet">
<!-- 5000 milliseconds after the URL request the server begins to respond -->
</head>
<body>
<img src="http://localhost/public/img?sleep=8000">
<!-- 8000 milliseconds after the URL request the server starts responding to the resource -->
<script>
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded OKOK')
})
window.addEventListener('load', () => {
console.log('window load OK')
})
</script>
<script src="http://localhost/public/js?sleep=2000"></script>
<!-- 2000 milliseconds after the URL request the server begins to respond -->
</body>
</html>
Test execution results:
After the page is running for 5 seconds, console.log('domContentLoaded OKOK'), is carried out
console.log(' Window Load OK') starts running at 8 seconds