简体   繁体   中英

addEventListener click being fired multiple times within a flickity slider

I'm using flickity , which is a bit irrelevant, and on first load and for each 'change' of a slide I'll search the slide for any videos that have audio enabled (set as a data attribute via PHP via CMS) and then it'll autoplay the video and if the user clicks an unmute button then it'll unmute and vice versa.

This worked fine going forward but going back once the mute button is clicked, the eventListener for the click will fire every time it's existed. I'm guessing the eventListener is being added to each time but I can't work out how to remove the eventListener.

Any help on how to prevent the muteButton.addEventListener('click') from being fired more than once?

//
playVideo = function(index) {
    var videos, video, muteButton = null, hasAudio = false;

    // Pause all other slide video content if it was playing
    flkty.cells.forEach(function(cell, i) {
        videos = cell.element.querySelectorAll('video.--autoplay');
        videos.forEach(function(video) {
            if (video !== null && typeof video !== 'undefined') {
                if (!video.paused) {
                    video.pause();
                }
            }
        });
    });

    // For current slide
    if (index == flkty.selectedIndex) {

        videos = flkty.selectedElement.querySelectorAll('video.--autoplay');
        muteButton = flkty.selectedElement.querySelector('a.button__mute');

        // If videos exist on the current slide
        if (videos.length) {
            videos.forEach(function(video, index) {
                if (video !== null && typeof video !== 'undefined') {
                    video.play();
                    if (muteButton !== null && typeof muteButton !== 'undefined' && index == 0) { // Only fire this once per video (as mute = mute all)
                        console.log(muteButton);
                        muteButton.addEventListener('click', function(e) {
                            e.preventDefault();
                            console.log('clicked'); // TOFIX; fires multiple times
                            muteVideo(videos, video, muteButton, true);
                        });
                    }
                }
                return;
            });
        }

    }

};
flkty.on('select', function(event, index) {
    if (index === 0) {
        playVideo(index);
        return false;
    }
});
flkty.on('change', function(index) {
    playVideo(index);
});

//
muteVideo = function(videos, video, muteButton, hasAudio) {
    console.log('hasAudio');
    if (videos.length > 1) {
        videos.forEach(function(video, index) {
            if (video.muted == true) {
                video.muted = false;
                if (index == 0) {
                    $(muteButton).text('mute');
                }
            } else {
                video.muted = true;
                if (index == 0) {
                    $(muteButton).text('unmute');
                }
            }
        });
    } else {
        if (video.muted == true) {
            $(muteButton).text('mute');
            video.muted = false;
        } else {
            $(muteButton).text('unmute');
            video.muted = true;
        }
    }
};

Just use removeEventListener() .

To remove event handlers, the function specified with the addEventListener() method must be an external function.

Anonymous functions, like yours, will not work.

As for only attaching it once: Just set a flag to be checked before adding the eventhandler in the first place.

JohnnyAwesome's solution sounds good to me. If the playVideo routine is called more than once you are adding Events multiple times. In order to remove them use removeEventListener() like suggested

If you have some Event bubbling going on - the e.preventDefault(); is not enough than you have to use e.stopPropagation(); or e.stopImmediatePropagation(); .

Don't use removeEventListener() in this case. The real problem is that you are adding event listeners each time your playVideo() function is called. So the problem you should solve is to make sure you only add the event listeners once , probably when the page initializes or something.

Here is what I would do:

Extract the "add event listener code" into a separate function, addButtonListeners() by removing that piece of code from the playVideo() . Then call the addButtonListeners() once when your page is loaded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM