The problem is that the event timeupdate
is not a Bubble Event. This means that you cannot treat it through the parent element, as done in:
$(document).on("timeupdate", "#video", function(){
console.log('video playing');
});
This is because the event is, in this case, associated with document
and not to the element #video
¹. Making the event delegation direct, with pure Javascript, is possible in the way you did:
document.addEventListener('timeupdate', function(e){
if(e.target.id == "video"){
console.log('video playing');
}
}, true);
Both forms nay (possibly not always) are analogs².
That is, the only way (except the above) is to associate the event directly to the element #video
. You can do this at the same time you insert it into the DOM, as explained by Caio, in his reply, in example 2.
Caio’s example 3 worked the way presented because the event click
is a Bubble Event.
$(() => {
const player = '<video id="video" width="400" controls><source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"><source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg"></video>';
$("button").on("click", event => {
$("#container").html(player);
$("#video").on("timeupdate", event => {
console.log("Video playing...");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container"></div>
<button>Adicionar</button>
References
Javascript | Events & Events
Javascript - Event order
Why don’t audio and video Events Bubble?
Understanding Event Delegation
Notes
(1): According to the page Understanding Event Delegation present on jQuery’s official website, when done something like:
$( "#list" ).on( "click", "a", function( event ) {
event.preventDefault();
console.log( $( this ).text() );
});
The event click
is delegated to the element #list
and, when treated, it is checked whether the event target matches the selector passed in the second parameter. Reading:
This Second, selector Parameter Tells the Handler to Listen for the specified Event, and when it Hears it, check to see if the Triggering element for that Event Matches the Second Parameter.
According to the summary on the page:
Event delegation refers to the process of using Event Propagation (Bubbling) to Handle Events at a Higher level in the DOM than the element on which the Event originated. It Allows us to attach a single Event Listener for Elements that exist now or in the Future.
The function on
really makes use of the effect Bubbling, or propagation of the event, for such cases, therefore, for an event that does not propagate, will not work.
(2): Apparently the two forms are analogous when the event in question is propagated by the DOM, because the event fired at the target element will also be fired at its predecessor elements, being fired, therefore, also at the element document
. Use the third parameter in addEventListener
, capture
, as true makes the event in question always be fired also in the element in question, so the form of delegation of event with pure Javascript works as expected. In this case, doing something like the example below is also valid:
const container = document.getElementById("container");
container.addEventListener('timeupdate', function(e) {
if(e.target.id == "video"){
console.log('video playing');
}
}, true);
I haven’t found any documentation that speaks if the function on
treat all events as bubble
or if there is a differentiated behavior for events that are not. In note 1, it is said that the event on
uses, in fact, the effect Bubbling of the event to work, but it is not conclusive whether it does so regardless of the event.
So I was wrong, the . on does not work as Mutationobserver, the event is added to the father and not to the new element :/
– Guilherme Nascimento
When the element is removed, events will remain active?
– Leo Letto
@Leoletto if the event is associated with the element, if it is removed, so will the event. I’m not sure I understand your question correctly.
– Woss
Then I will check this so that I can formulate a better question if it is the case, I think I will have to opt for pure javascript even, is the fastest and feasible solution for me at the moment
– Leo Letto
Better than assigning the event when the video is inserted into the DOM? Are you sure?
– Woss
As far as I know, those two forms are rather analogous. Strange the pure js version has worked, since this event does not bubble...
– bfavaretto
@bfavaretto Worked because of the last parameter
useCapture
by the way. In this case the event is triggered first todocument
before being shot at the element itself, no? As long as the codes are analogous, I believe they are not for all events. In the functionjQuery.event.add
used byjQuery.on
has a comment like this: "Only use addeventlistener if the special Events Handler Returns false" (approx. line 4600, jQuery 2.2.4, uncompress). I still do not understand exactly what happens, but I imagine that the behavior changes according to the event treated.– Woss
Ah, I hadn’t noticed that that code used capture. It makes sense that it would work in this case. And I will look at the jQuery code to try to understand when it uses addeventlistener and when it does not use.
– bfavaretto
Excellent. I had already seen something about the fact that Bubbling did not occur, but I confess that I did not go as deep as I wanted. Good answer
– Caio Felipe Pereira
According to that Dude, the audio and video events don’t bubble up because it doesn’t make sense to them. It shows a way to wrap to use the delegation via jquery. I haven’t tried it, but it looks promising
– Caio Felipe Pereira
@Caiofelipepereira I had seen this answer when I was researching, but I found the solution he presented unviable and I didn’t even mention it. It seemed too much code for little. In my view, assigning the event to the element when it is added to the DOM is much more practical and simple.
– Woss
Since I am only doing an "upgrade" in the code, using pure js in the case would be the easiest option, because the same to be assigned when adding the elements would require a certain change in my current code, in this case I would prefer to start a new code of 0, foreseeing such events in the future.
– Leo Letto
@Andersoncarloswoss, as I said, did not test, hahaha. But so, curious that this has never been dealt with in the core of jquery
– Caio Felipe Pereira
I think because, in fact, it doesn’t make much sense to do so. It’s particular events to the audio/video element, why would you treat them in a
div
. In thedocument
, maybe, but I still think it’s unnecessary.– Woss