1

I am trying to make a custom video. I can get my functions to work. However when I have two event listeners together:

e.g. video.ontimeupdate

only the bottom one will operate when I play the video. Is there a better way for me to write my functions, so that I do not have this problem?

Event listeners

time.addEventListener("timeupdate", currentTime, true);
video.ontimeupdate = function() {currentTime()};

seek.addEventListener("timeupdate", progressBarUpdate, true);
video.ontimeupdate = function() {progressBarUpdate()};

Function code example

// Updating the progress bar function

function progressBarUpdate() {

            // Calculate the progress bar value
            var value = (100 / video.duration) * video.currentTime;
            // Update the progress bar value
            seek.value = value;
        }
T.XL
  • 149
  • 1
  • 15
  • 1
    use `video.addEventListener('timeupdate', ...)` just like you do with `time.addEventListener` and `seek.addEventListener` - I'm not sure what `time` and `seek` objects are, but the code looks wrong to begin with – Jaromanda X Nov 28 '16 at 01:30

2 Answers2

4

There are two different JavaScript mechanisms for registering event handlers:

time.addEventListener("timeupdate", currentTime, true);  // W3C DOM Standard
video.ontimeupdate = function() { currentTime() };         // Event handling property

When you use a property (ontimeupdate) and you give it a value, that value will be overwritten when you set that property to another value.

So, when you do this:

video.ontimeupdate = function() {currentTime()};

It gets overridden by this later:

video.ontimeupdate = function() { progressBarUpdate() };

To prevent this from happening, use the more modern W3C DOM Level 2 event handling model that uses addEventListener

 video.addEventListener("timeupdate", currentTime);
 video.addEventListener("timeupdate", progressBarUpdate);

This will register both functions as callbacks to the timeupdate event.

Additionally, there is a third parameter for addEventListener (a boolean) which indicates whether you want the callback to fire during the capture phase (true) or the bubbling phase (false). It's rather unusual to need the capture phase (it's not supported in IE until IE 9), so you may want to modify your existing true values to false or just omit the third argument as false is the default.

Here's a working example that actually shows 3 event handlers all tied into the timeupdate event (make sure to scroll down in the snippet window to see the messages):

var videoElement = null;
var current = null
var duration = null;
var div1, div2;

window.addEventListener("DOMContentLoaded", function(){
  // Get DOM References to media element:
  videoElement = document.getElementById('bikeSafe');

  // ...to video span elements:
  current = document.getElementById('current');
  duration = document.getElementById('duration');
  div1 = document.getElementById("timeUpdate1");
  div2 = document.getElementById("timeUpdate2");

  // Wire Up Video to use its API:
  videoElement.addEventListener("play", setCounter);
  videoElement.addEventListener("ended", endVideo);
  videoElement.addEventListener("durationchange", updateStatus);
  videoElement.addEventListener("timeupdate", setCounter);
  videoElement.addEventListener("timeupdate", updateDiv1);
  videoElement.addEventListener("timeupdate", updateDiv2);
});

// Video API:

function updateDiv1(){ div1.innerHTML = "Hello from timeupdate event handler!" }
function updateDiv2(){ div2.innerHTML = "Hello from different timeupdate event handler!" }

// Set the value for the current position in the video
function setCounter() {
  // This function is wired up to the video element's timeupdate event, which
  // fires when the current time value changes.
  current.innerHTML = (videoElement.duration - videoElement.currentTime).toFixed(3);
}

function endVideo() {
  // Reset video back to beginning when it ends
  videoElement.currentTime = 0;
};

function updateStatus() {
  // This will fire when the video's durationchange event fires
  // and that will happen upon the successful loading of the image
  // for the first time when it becomes known how long the duration
  // of the video is.
  current.innerHTML = videoElement.duration.toFixed(3);
  duration.innerHTML = videoElement.duration.toFixed(3);
};
video { width:40%; }
<video id="bikeSafe" width="400" controls>
  <source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
  <p>Your browser does not support HTML5 video.</p>
</video>
<p>
  Time Remaining: <span id="current"></span> | 
  Total Length: <span id="duration"></span>
</p>
      
<div id="timeUpdate1"></div>
<div id="timeUpdate2"></div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Third parameter got updated in latest revs, it is now an option object. – Kaiido Nov 28 '16 at 01:40
  • @Kaiido Interesting, but the DOM Living Standard says that and W3C DOM Level 4 says third arg is boolean. WHATWG vs. W3C – Scott Marcus Nov 28 '16 at 01:46
  • Yes w3c still says it's a boolean, but all browsers except IE start to support it, so even w3C will incorporate it in their version of the specs. – Kaiido Nov 28 '16 at 01:52
  • Yes, but all browsers will continue to support the W3C spec as well, so I see this as a situation where you can pass either. It's no guarantee that W3C will adopt WHATWG. – Scott Marcus Nov 28 '16 at 01:53
  • Thank you Scott Marcus for taking the time to explain the syntax. Your time is much appreciated. – T.XL Nov 28 '16 at 02:34
  • I have taken the 'true' phase from the video.addEventListener("timeupdate", currentTime); but I do not know how to get the eventListener to function when the video is playing without using : video.ontimeupdate = function() {currentTime()}; Do you know what step I am missing? – T.XL Nov 28 '16 at 02:56
  • @T.XL You can hook up multiple event handlers to the same event by adding additional `addEventListener()` calls as I've shown in my answer, but you can also check out this Fiddle I made that does it: https://jsfiddle.net/4p31vegL/4/ – Scott Marcus Nov 28 '16 at 14:44
  • @Scott Marcus. Thank you very much, I understand what you mean now. Thank you for your time, it is much appreciated. – T.XL Nov 28 '16 at 22:16
  • @T.XL No problem. Glad to help! :) – Scott Marcus Nov 28 '16 at 22:18
0

video.ontimeupdate is similar to window.onload. They are properties that are updated. The most recent function definition for them will be executed. Use addEventListener()

video.addEventListener("timeupdate", currentTime, true);
video.addEventListener("timeupdate", progressBarUpdate, true);

Here is a snippet showing the problem with using window.onload syntax.

window.onload = function(){
  console.log('Window loaded #1'); // Will not excecute
}
window.onload = function(){
  console.log('Window loaded #2'); // Window loaded #2
}
Community
  • 1
  • 1
Adam Azad
  • 11,171
  • 5
  • 29
  • 70