Reputation:
Everytime I call the createResetHandler
I bind the video.addEventListener
to the same element.
I need to video.removeEventListener
everytime I destroy the player.
How do I add video.removeEventListener
to the code? https://jsfiddle.net/yb0tn7p9/
const videoPlayer = (function makeVideoPlayer() {
const players = [];
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/player_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function createResetHandler(player) {
const resetVideos = document.querySelectorAll('.exit');
resetVideos.forEach(function resetVideoHandler(video) {
video.addEventListener('click', function resetVideoHandler() {
player.destroy();
console.log('hit')
}
);
}
)
}
function onPlayerReady(event) {
const player = event.target;
player.setVolume(100);
createResetHandler(player);
}
function addPlayer(video, settings) {
const defaults = {
height: 360,
host: "https://www.youtube-nocookie.com",
videoId: video.dataset.id,
width: 640
};
defaults.events = {
"onReady": onPlayerReady
};
const playerOptions = combinePlayerOptions(defaults, settings);
const player = new YT.Player(video, playerOptions);
players.push(player);
return player;
}
return {
addPlayer
};
}());
Upvotes: 4
Views: 541
Reputation: 1855
you are adding event to each element whenever createResetHandler
is called.
What you should do instead is find the button that is related to that video and call add event listener to only that button.
function createResetHandler(player) {
// get the current exit button from the curtain element which's display is set to block
let exitBtn = Array.from(document.querySelectorAll('.exit')).find(e => {
return window.getComputedStyle(e.closest(".curtain")).display === 'block';
});
if(exitBtn){
exitBtn.addEventListener('click', () => {
console.log("hit");
player.destroy();
},{once: true}
);
}
}
let me break it up a little.
The thing we are sure of is there is only one exit button visible at the moment inside only one curtain whose display is block
at the moment.
Array.from
converts the NodeList
into array so we can utilize the find method of array.
From the button we get the closest (towards the parents) .curtain
element and check the display
prop using getComputedStyle
to see if it is block.
If it is block that means this is the curtain that is being viewed and the button at this iteration is the button that needs to have click event listener
.
and lastly the {once: true}
part is to make sure the event is only listened one time. Since you are already using const
keyword that means you are only going for modern browsers so no need to use removeEventListener
seperately {once: true}
will work in all the modern browsers.
updated working fiddle: https://jsfiddle.net/avwonj91/1/
Upvotes: 1
Reputation: 22474
You can modify the createResetHandler
function to something like this:
function createResetHandler(player) {
const resetVideos = document.querySelectorAll('.exit');
resetVideos.forEach(function(video) {
video.addEventListener('click', function resetVideoHandler() {
video.removeEventListener('click', resetVideoHandler);
player.destroy();
console.log('hit')
}
);
}
)
}
What I did is to only use the resetVideoHandler
function name only once for the event handler function and to add the video.removeEventListener('click', resetVideoHandler)
statement.
Upvotes: 1