Listener for 'timeupdate' event on video doesn't retain values

My html5 video event listener is designed to pause the video at a specific time while the user participates in a quiz. The first 'lesson' works fine, and the second video also appears to add the listener with the correct pause time. However, when playing the second video, it always pauses at 170 seconds, which was the pause time from the FIRST video.

Furthermore, when I check Chrome's dev panel, I notice that the timeCache value immediately reverts back to the previous video's values as soon as the video starts playing. Unless the video has passed the 170-second mark, then it will use the correct 230-second timeCache value. Initially, I suspected that the old event listener might still be attached, but after eliminating that possibility, the problem persists. You can find the link here:

var setPause = function (time) {
   var video = $("video").get(0);
   var timeCache = time;
   video.removeEventListener('timeupdate', timeListener, false);
   function timeListener (){
    if (video.currentTime >= timeCache && video.currentTime < (timeCache + 0.3)) {
        video.pause();
    }}
   video.addEventListener('timeupdate', timeListener);
};

The initial $watch in the directive triggers each time a new lesson is loaded. It binds the ended event as well as the timeupdate listener using setPause() before loading and playing the video. The purpose of setPause is to set the time at which the video will automatically pause, and the second $watch waits until all questions have been answered before playing the remainder of the video (usually a congratulatory message).

app.directive('videoWatcher', function () {
return function (scope, video, attrs) {
    scope.$watch(attrs.videoLoader, function () {
        $(video[0]).bind('ended', function () {
            $(this).unbind('ended');
            if (!this.ended) {
                return;
            }
            scope.tutorialNumber++;
            scope.$apply();
            scope.loadFromMenu();
        });
        setPause(scope.currentTutorial.pause);
        video[0].load();
        video[0].play();
    });
    scope.$watch(attrs.congrats, function(){
        var cT = scope.currentTutorial;
        if (scope.questionNumber === cT.material.length){
            video[0].play();
            setTimeout(function () {
                video[0].play();
            }, 500);
        }
    });
};
})

Answer №1

Whenever the pause function is called, a new instance of the timeListener function is created. Any mention of timeListener refers to the most recently created one. Therefore, when you remove the event listener, you are actually getting rid of the new function, not the original one that was attached previously.

In JavaScript, variables and functions declared within a function are always "hoisted" to the top, regardless of where they are written in the code. So even if you define the timeListener function after calling

removeEventListener</code, the behavior remains as if it were declared at the beginning of <code>pause
. This underscores the importance of declaring all variables and functions before any other code execution (JSLint will enforce this rule). The exception is when a function is explicitly assigned to a variable.

To rectify this issue, declare the timeListener function outside of the pause function so that it consistently references the previous instance. Here's an updated version:

var timeListener;
function pause(time) {
    //timeCache isn't needed
    var video = $("video").get(0),
        end = time + 0.3; //cached for efficiency

    if (timeListener) {
        //remove the previous timeListener function, if present
        video.removeEventListener('timeupdate', timeListener, false);
    }

    //create a new function and store it as timeListener for future use
    timeListener = function () {
        if (video.currentTime >= time && video.currentTime < end) {
            video.pause();
        }
    };
    video.addEventListener('timeupdate', timeListener);
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging Discord.JS to seamlessly transport users in Discord to their designated voice channel by assigning roles

I'm attempting to transfer all users with a specific role from a voice channel using a command like: !summon @role This command should bring only the users with that specific role to the voice channel where the command was entered My current code is ...

Using an Array as an Argument in a JavaScript Function

Currently, I am utilizing a web service to populate a selection list. Now, I need to repeat this process for multiple selection lists, with the goal of minimizing the amount of code duplication. Below is the function I am using to make the web service call ...

Determine if a certain value is present in a JSON data structure

Exploring the depths of NodeJS, I am utilizing a JSON Object for user validation. JSON content (users.json): { "users": [{ "fname": "Robert", "lname": "Downey Jr.", "password": "ironman" }, { "fname": "Chris", ...

What is the method for triggering the output of a function's value with specified parameters by clicking in an HTML

I am struggling to display a random number output below a button when it is clicked using a function. <!DOCTYPE html> <html> <body> <form> <input type="button" value="Click me" onclick="genRand()"> </form> <scri ...

Is there a way to improve scrolling speed on Mobile Safari?

I'm currently working on a project utilizing angularjs and bootstrap, aiming to replicate iOS's navigationController feature. However, I'm encountering speed issues, particularly when scrolling between views on mobile safari iOS. The transi ...

I am encountering an issue with importing modules from the public folder in Next.js when using TypeScript, as I am

I've been running into an issue with importing files in Next.js using TypeScript. I'm trying to use regular imports with custom absolute paths, but I keep getting a module not found error. Oddly enough, my IDE is able to locate the file when I cl ...

Leveraging the Meteor Framework for Application Monitoring

Exploring the potential of utilizing Meteor Framework in a Monitoring Application. Scenario: A Java Application operating within a cluster produces data, which is then visualized by a Web Application (charts, etc.) Currently, this process involves using ...

Position object in the middle using jQuery and CSS

Trying to center an absolutely positioned object horizontally using CSS and jQuery is proving to be a challenge. The use of jQuery is necessary due to the varying widths of the objects. Hover over the icons in my jsFiddle to see the issue. Check out the j ...

Angular-schema-form utilizes computed values to dynamically generate form fields based on

I am facing an issue with a form where users input values and I want to display dynamic calculations based on those values. The problem is that the calculation does not update when the numbers are changed. Here is my code snippet: angular.module('cal ...

Upgrading from V4 to React-Select V5 causes form submission to return undefined value

Looking to upgrade from react-select v4 to v5. The form/field currently functions with v4 and Uniform, producing an output like this: { "skill": { "value": "skill1", "label": "Skill 1" } } After attempting the upgrade to V5, I'm getting a ...

The image file that was uploaded to our S3 storage has been detected

I'm attempting to upload an image created by cropperjs to a DigitalOcean space. To achieve this, I am utilizing a pre-signed URL and performing a put request using Axios. The problem arises when I try to open the uploaded image, as it appears to be ...

Every item in my array is replaced by the most recently added element

Take a look at this code snippet on JSFiddle: https://jsfiddle.net/reko91/998woow6/ The issue I am facing with my project is that every time I add an element to an array, it ends up overwriting all the existing elements with the newly added one. To repli ...

What steps should be taken to resolve the error message "EROFS: read-only file system, attempting to open '/var/task/db.json'?"

const jsonServer = require('json-server') const cors = require('cors') const path = require('path') const server = jsonServer.create() const router = jsonServer.router(path.join(__dirname, 'db.json')) const middlewa ...

The Ionic application is experiencing difficulties in loading the JSON file

I am currently delving into the world of Ionic development and utilizing localhost to test my app. My goal is to create a contacts list application where contact details such as name, email, phone number, and avatar are loaded from a JSON file. However, I& ...

A JavaScript async function with a nested call inside

Below is my node function for the API server: router.post('/find', async (req, res) => { try { const firewalls = []; let count = 0; const devices = await Device.find({ ...req.body }); devices.forEach(async (item) => { ...

Combining Mongoose OR conditions with ObjectIDs

After querying my Team schema, I am receiving an array of ids which I have confirmed is correct. The issue seems to lie in the fact that both home_team and away_team are ObjectIDs for the Team Schema within my OR statement. Team.find({ 'conferenc ...

Showing information from a table for editing purposes with the use of HTML input tags

As I navigate my way through the complexities of HTML and PHP coding, I’m faced with a challenge in displaying database content on an editable table within my web page. Clicking the edit button should lead to a separate page where data can be modified. ...

Problems with displaying Wordpress content on your web browser

I am having trouble getting my website content to display properly in a web browser, even though I built it using Wordpress. It appears that only the logo and the 'Services' bar are showing up on the page, while the rest seems to be missing. I s ...

The matter concerning the intricacies of Rails, JQuery, Prototype, and RJS

I am exploring the integration of Jquery and ajax in rails 3.0.7, but I'm unclear on the current landscape regarding their usage together. There seems to be an abundance of hacks, plugins, and scripts available for utilizing JQuery. So: Is there an ...

Is there a sweet TypeScript class constructor that can take in its own instance as an argument?

I have a scenario where I need to read in instances of Todo from a CSV file. The issue is that Papaparse does not handle dynamic conversion on dates, so I'm currently dropping the object into its own constructor to do the conversion: class Todo { ...