4

I'm attaching a load event handler on a <track> element. How can I make sure that the handler gets called even if it gets attached after the <track> has already loaded?

E.g.

track.addEventListener('load', function () {
    //this should get called even if the track has already loaded
});
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Yasir
  • 879
  • 5
  • 13
  • 31
  • what are you looking to accomplish? – Daniel A. White Oct 15 '16 at 00:14
  • the goal is to have this function work with content being added dynamically. one case would be, user uses function foo after initial document load – Yasir Oct 15 '16 at 00:21
  • What is the issue though? Is the event listener not being added? – Stephan Genyk Oct 15 '16 at 00:28
  • This would keep adding event listeners to the same element. Not clear at all what problem you are trying to solve. If the element is actually a `
    ` they don't have load events...only a few special elements do
    – charlietfl Oct 15 '16 at 00:28
  • so it turns out, i had this issue specifically with element in HTML. i solved this with using track.readyState == 2 and loading event there when needing to load at a different time. you guys are right with the div. I needed to be clearer! – Yasir Oct 15 '16 at 00:50
  • @Yasir _"i solved this with using track.readyState == 2"_ Is Question resolved? Are you creating a new `track` element or changing the `src` of existing element? – guest271314 Oct 15 '16 at 02:30

4 Answers4

1

If the event was fired when no listener was attached then the event is lost. Hopefully, the HTMLTrackElement has a readyState property which can be inspected to know the loading state.

Something like this should work, it attaches the handler to handle subsequent load events and if the track is currently loaded it calls the callback right away as well.

function whenLoaded(track, callback) {
    const LOADED = 2;

    track.addEventListener('load', callback);
    if (track.readyState === LOADED) callback();
}
plalx
  • 42,889
  • 6
  • 74
  • 90
0

Your code is pretty much working as you can see below. I just changed the event from load to click and added the function word before foo.

function foo(div) {
  div.addEventListener('click', function() {
    console.log('this loads');
  });
};


var div = document.getElementById('main');
  
setTimeout(function() {
  foo(div);
}, 1000);
#main {
  background-color: red;
  width: 100px;
  height: 100px;
}
<div id="main"></div>
Stephan Genyk
  • 177
  • 1
  • 6
0

Note, the load event will not be fired at chromium, chrome if default attribute is not set at <track> element.

Not sure if you are changing the src of existing <track> element or appending a new <track> element to parent <video> element?

The approach below appends a new <track> element to <video> element. Pass src to foo, attach load event to track element before appending to parent <video> element, append to <track> element to <video> element, then set src to the variable passed to foo

window.onload = function() {

  // append next `track` element to `video` in 1 seconds
  setTimeout(function() {
    // pass `src`, `label` to set at `track` element
    addTrack("/path/to/resource2", "track 1") 
  }, 1000);

  function foo(track, src) {  
    track.addEventListener("load", function() {
      console.log("this loads");
    });
    video.appendChild(track);
    track.src = src;
  };

  function addTrack(src, tracklabel) {
    var track = document.createElement("track");
    track.kind = "captions";
    track.srclang = "en";
    track.label = tracklabel;
    // set `default` attribute at `track` element
    track.setAttribute("default", "default");
    // pass `track` element, `src` to set at `track` to `foo`
    foo(track, src);
  }

  addTrack("/path/to/resource1", "track 1");

}
guest271314
  • 1
  • 15
  • 104
  • 177
0

From your followup comment:

the goal is to have this function work with content being added dynamically.

The best solution for making event listeners work with dynamic content is event delegation. Instead of having to worry about adding the event listener to the dynamic element after that element is added, you simply add the event listener to a parent of that element, where that parent element already exists in the document. Or you can use a grandparent, great-grandparent, etc. You can even go all the way up to the body element if there isn't a more specific element you can use.

You can add this event listener before the dynamic content is loaded, because you're adding it on an already existing element.

When your event listener is called, event.target is a reference to the actual element that the event was triggered on. So you check that to see if it is one of the elements you want to actually handle events for.

The answers to this question have some good examples of how to use event delegation. It's really simple and solves every problem with listening for events on dynamically added content.

Community
  • 1
  • 1
Michael Geary
  • 28,450
  • 9
  • 65
  • 75