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

Inconsistencies observed during the native JSON import process in JavaScript

Encountered a strange behavior when loading a JSON file into JavaScript while working on a React project. Seeking an explanation and guidance on properly accessing data from the JSON data store. The JSON file contains product data: { "product ...

What is the best way to create hover effects on buttons in Vue.js 3?

I'm currently developing a calculator to practice my Vue.js 3 skills (I am new to vue). I've successfully implemented the basic features, but now I'm exploring how to incorporate hover animations on the buttons. Specifically, I want to diffe ...

How can I run an ajax request in a loop where it only proceeds to the next loop value upon successful completion?

I'm facing a simple but important issue: running 3 Google Maps place URLs and displaying the results after each one is successful. Here's my current approach: var values = ["url1", "url2", "url3"]; values.forEach(function(value, i) { var ...

Creating new form fields dynamically using JavaScript (triggered by onClick event)

I want to dynamically add fields based on user interaction. For instance, when the checkbox or radio button is clicked, additional fields like buttons and textfields should appear. Is it possible to achieve this using onClick? If so, can you please provide ...

Ways to delete a CSS attribute with jquery

Is there a way to eliminate a CSS property from a class without setting it to null? Let's say I have a class called myclass with the property right:0px. I want to completely remove right:0px from my class, not just set it to null. How can I achieve th ...

Is there a method to access the output of getStaticProps function from NextJS API routes?

Is there a method to compute and cache new data during build time that is essential for both the front-end and back-end API routes? I'm looking for a way to access the static properties generated by API routes at build time since the routes are access ...

Error message: An error occurred while executing the AJAX PHP code due to a TypeError, specifically stating that the property 'status' cannot be

For some reason, I keep receiving an undefined return for my response. The event handler in index.php triggers the following code: $.post("getData.php", onNewPost()); function onNewPost (response){ if (response.status == "OK") { console.log(resp ...

gulp-open not functioning properly following the use of createWriteStream

I am utilizing gulp, gulp-eslint, and gulp-open to generate a report detailing ESLint outcomes. The linting and file creation processes function correctly; however, the task aimed at opening the file containing my report encounters issues. gulp.task(&apos ...

The br tag in HTML cannot be utilized in conjunction with JavaScript

I am currently working on a project involving HTML and JavaScript. I have a "textarea" where data is inserted into the database upon pressing the "Enter key." However, I am encountering two issues: Currently unable to save data like "Lorem Ipsum" (the ...

Form an array using the values that are returned

As I iterate through an object and extract elements, my console.log displays: ["item 1"] ["item 2"] ["item 3"] and so on. All I want is to create a new array formatted like this: ["item 1","item 2","item 3"]; ...

Achieving dynamic population of a second dropdown menu based on selection from the first dropdown menu using PHP

In my current project, I am faced with the task of populating three different menus. The first menu is generated using a MySQL query in PHP and displays TV shows like "Modern Family" or "Dexter". What I want to achieve is that once a TV show is selected fr ...

Having trouble with the updateOne() method in MongoDB - it's not updating my document nor displaying any errors. What could be the issue?

I'm currently facing an issue where I am attempting to update a user's document in the database with a value obtained from a calculator. However, despite not encountering any errors, the document does not seem to be updating and the page just con ...

The process of enabling NPM packages for use with ES6 and ECMAScript

Currently, I am working on developing an NPM package using TypeScript. My main concern is how to ensure that this package can be made available for both ES and Node modules. To achieve this, I have configured Rollup along with a few settings: rollup.conf ...

Conceal the div by clicking outside of it

Is there a way to conceal the hidden div with the "hidden" class? I'd like for it to slide out when the user clicks outside of the hidden div. HTML <!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.c ...

Performing a simulated click on a dynamically inserted element using pure JavaScript

I am faced with the challenge of programmatically navigating a ReactJS-based website in a looped workflow. The process involves clicking on Element1, dynamically altering the web page to add Element2, then clicking on Element2, and so on until eventually r ...

Having trouble changing my array state in react?

I'm having trouble understanding why my React state isn't updating with the following code: state = { popUpMessages:[] } popUpMessage(id,name) { console.log("id ",id,"name ",name) const addUserObject = { id, name }; const new ...

Commitment without anticipation of a resolution or rejection

While testing one of my AngularJs Services, I decided to write some Unit tests. Below is a sample code snippet that I have come up with: it('', function(done) { aDocument.retrieveServiceFile(extractedFileFeature) .then(function() { ...

Display a tooltip for ever-changing content

My HTML code displays dynamic rows with information, along with an image link that reveals specific details about the clicked row using the compentence_ID field. echo "<td>".$compi['Competence_ID']."</td>"; ec ...

Collaboratively accessing a shared constant in two separate JavaScript files

I am diving into the world of JavaScript and Node.js. I am currently experimenting with Puppeteer to extract the text value of a tag and store it in a constant variable. However, I am encountering difficulties when trying to integrate this value into my ...

Dynamically assigning column values based on object properties

I am currently utilizing the Ionic Framework along with its grid system that is reminiscent of Bootstrap. However, I believe my query leans more towards AngularJS than specific Ionic components. Here is what I have: <ion-col *ngFor="let col of row ...