By looking at the output of console.log(document), I find document has these properties:onload=null;onloadstart=null;onloadend=null;onreadystatechange=null; I write the following code:
<html>
<head><title>test</title></head>
<body>
<script>
document.onload=function(){alert("document.onload");};
document.onloadstart=function(){alert("document.onloadstart");};
document.onloadend=function(){alert("document.onloadend");};
document.onreadystatechange=function(){alert("document.onreadystatechange");};
</script>
<div>hello</div>
</body>
</html>
Interestingly, document.onload,document.onloadstart,document.onloadend are never called, while document.onreadystatechange is called twice, why?
Why isn't document.onload called?
First of all the load events (created by the browser) do not bubble (because that's how it is specified):
document.body.onload = function(e) {
console.dir(e.bubbles)
}
So you can only listen for these load events, on the element for which they occur.
And for Document there is no load event listed that will be triggered based on the standard.
readystatechange on the other hand is listed as an event that can happen for document.
You can however for sure listen for load events on the document and the event callback will be called. But that will only happen if you e.g. manually trigger one on document:
const event = new Event('load');
document.onload = function (e) {
console.log('load document')
}
document.dispatchEvent(event);
Or if you emit a load event that bubbles on a descendant:
const event = new Event('load', {bubbles: true});
document.onload = function (e) {
console.log('load document')
}
document.body.dispatchEvent(event);
So why does onload then appear as a property? That's due to the GlobalEventHandlers and Document includes GlobalEventHandlers), and due to event handler IDL attribute, exposing those as on… event properties.
I'm unsure, but try this:
window.addEventListener('load', () => {
alert("document.onload")
})
I only use window onload event, but if I never saw document onload event, just change window to document.
Like I said´, I'm unsure what to do, because the amount of your code, which you showed is to less.
.onload is part of the window object, not for document.
GlobalEventHandlers.onload
The onload property of the GlobalEventHandlers mixin is an event handler that processes load events on a Window, XMLHttpRequest, <iframe> and <img> elements, etc.
And from what i've seen on MDN .onloadstart and .onloadend are used for resources like images, don't know if they are availiable for document/window. GlobalEventHandlers.onloadstart
But I think with onreadystatechange you should be able to emulate the behavior of onloadstart and onloadend.
Document.readyState
Related
const body = document.querySelector("body");
body.addEventListener("load", () => {
console.log("test");
});
body.onload = () => {
console.log("test");
};
when i use only addEventListener i don't see the message in the console but if i use onload property or use onload attribute in the html it works
This is because the load event is part of what is called the Window-reflecting body element event handler set.
Basically, these events are also accessible as HTML attributes and IDL attributes on the <body> element, even though the primary target is actually the Window object.
This is done because historically we had to use HTML attributes to set event handlers, and setting the load event in the <body> tag was more "natural". Since then we have gotten far better ways to set up event handlers and we can define clearly that this event fires on the Window object, which is more logical.
However browsers still need to support code that was listening to the onload="" HTML attribute, so this reflection thing has been set up.
Note that it's not just adding a new event listener, the event actually only fires on the Window object, but the handler can be set from the <body>, even overriding the ones already set on the Window object.
window.onmessage = (evt) => console.log("handled a message from Window, is Window the currentTarget:", evt.currentTarget === window);
document.body.onmessage = (evt) => console.log("handled a message from body, is Window the currentTarget:", evt.currentTarget === window);
postMessage("hello", "*");
EventTarget#addEventListener() has no means to do this retargetting, so when you do document.body.addEventListener("load", cb), you are really waiting for an event that will go through the <body> element, but as demonstrated above, the event actually only fires on the Window object.
I get an error '.addListener is not a function' upon trying this:
if(document.getElementById("id")){
document.getElementById("id").addListener('click', function(){alert("ok");});
}
This element 'id' comes into picture when the entire document gets loaded, and I am using it in the middle of the documents construction. So, I did this:
window.onload = function(){
if(document.getElementById("id")){
document.getElementById("id").addListener('click', function(){
alert("ok");
});
}
}
The error is gone now, but the element 'id' does nothing upon being clicked.
How to make it clickable?
It sounds like you may be assigning to window.onload more than once. If you do this, only the last callback assigned to it will run. Use addEventListener instead, so that prior assignments to onload do not conflict with later assignments to onload.
You can also listen for DOMContentLoaded instead of load, allowing the listener to be attached faster:
window.addEventListener('DOMContentLoaded', function(){
const elm = document.getElementById("id");
if(!elm){
return;
}
elm.addEventListener('click', function(){
alert("ok");
});
});
Best to never assign to an .on- property unless you're certain it will never be assigned to again (or unless you're certain it should only ever have one listener).
Because the element is added later in the dom, you can not attach a listener this way.
What you should do is to attach a listener on the document that will 'filter' the events, so elements added later on in the dom will still be able to fire your events. Try the code below:
document.addEventListener('click',function(e){
if(e.target && e.target.id== 'id'){
//do something
}
});
Now anytime anything is clicked on the dom, this listener will await for an element with id='id' to execute your code, otherwise it will not do anything. This method is called
"event delegation", look it up for more info!
I am new to JS and found this code section:
<body>
<span id="sp1">
<img src="aurora.gif" onload="ev1(event)">
</span>
</body>
As far I understood, the onload attribute gets triggered if the entire HTML Doc finished "loading". But I don't really understand, whats passed to the ev1 function if the onload attribute is triggered. What is event in this case?
Here is the source code
It's hooking up a handler to the image's load event and passing the event object for the event into the handler. The event object exists reliably cross-browser within the context of the onload attribute-style event handler: On IE, it's a global; on Firefox, it's a local within a synthetic function created for the onload handler; on Chrome, I think it's both. :-)
Note that the ev1 function must be a global, which is one of many reasons not to use onxyz-attribute-style event handlers.
img also has onload attribute & is called when when the image has finished loading. Similarly it also have onerror event handler. event represent the event object.
function ev1(e) {
console.log(e)
console.log('Img loaded')
}
img {
width: 200px;
height: 200px;
}
<img src='https://i.redd.it/xbq78cnv2nr21.jpg' onload='ev1(event)'>
This appears to be an attempt pass the Event Object as an argument to a function called ev1.
Instead of using an inline event, the author developer should have used a JavaScript event, like this.
document.querySelector("img").addEventListener("load", event => {
console.log(event);
});
Good luck.
I have defined this event handler:
document.addEventListener("load", function(){
alert("Called on page load");
}, false);
I noticed it does not get called when the boolean flag is set to false(fire at bubble phase). Could someone help me out on why this is the case.
When an event is being sent to an element, it descends the document tree in the capture phase until it reaches the target. Then, if it’s a bubbling event, it bubbles back up.
From 2.1 Introduction to “DOM Events” in the DOM standard:
When an event is dispatched to an object that participates in a tree (e.g. an element), it can reach event listeners on that object’s ancestors too. First all object’s ancestor event listeners whose capture variable is set to true are invoked, in tree order. Second, object’s own event listeners are invoked. And finally, and only if event’s bubbles attribute value is true, object’s ancestor event listeners are invoked again, but now in reverse tree order.
load isn’t a bubbling event, and – here’s the important part – it doesn’t target document. When you add a capture listener, you’re really getting load events from parts of the document’s content that normally receive the event, like scripts or images. On a page with only the script, you won’t see the listener get called at all:
<iframe srcdoc="<script>document.addEventListener('load', () => { alert('loaded'); }, true);</script>"></iframe>
And on a page with load events that fire after the listener is attached, like this Stack Snippet that includes <style>s, you’ll see it more than once:
let i = 0;
document.addEventListener('load', e => {
console.log(`loaded ${++i}: ${e.target.nodeName}`);
}, true);
You probably meant to add a non-capturing listener to window instead of document, because window is something that receives a load event, unlike document. (Or you might have meant something else. There’s a lot of ways to interpret “page load”. See Window: load event on MDN for details on what the load event means on window and alternatives if it wasn’t what you intended.)
window.addEventListener("load", function() {
alert("Called on page load");
}, false);
I am trying to detect when a div within the entire document is loaded.
but for some reason is this not being detected?
https://codepen.io/noflaco/pen/eoeexM?editors=1111
document.addEventListener("DOMContentLoaded", function() {
const test = document.getElementById("test");
function consent() {
alert("test");
}
test.addEventListener("DOMContentLoaded", Consent);
});
why not?
why not?
Arbitrary DOM elements to not trigger a DOMContentLoaded event, so the event handler is never executed. This event is only triggered on the document element when whole DOM has been parsed and loaded.
You can learn more about this event on MDN.
Ironically, the fact that you can load the div via document.getElementById("test") means that it already exists, so there is no point in adding a handler to wait for it to load.