Cada vez que llamo a createResetHandler vinculo video.addEventListener al mismo elemento.
Necesito video.removeEventListener cada vez que destruyo el reproductor.
¿Cómo agrego video.removeEventListener al código? 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 }; }());Puede modificar la función createResetHandler a algo como esto:
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') } ); } ) } Lo que hice fue usar el nombre de la función resetVideoHandler solo una vez para la función del controlador de eventos y agregar la video.removeEventListener('click', resetVideoHandler) .
está agregando un evento a cada elemento cada vez que se llama a createResetHandler . Lo que debe hacer en su lugar es encontrar el botón que está relacionado con ese video y llamar a agregar detector de eventos solo a ese botón.
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} ); } } déjame dividirlo un poco. De lo que estamos seguros es que solo hay un botón de salida visible en este momento dentro de una sola cortina cuya pantalla está block en este momento.
Array.from convierte NodeList en una matriz para que podamos utilizar el método de búsqueda de matriz. Desde el botón, obtenemos el elemento .curtain más cercano (hacia los padres) y verificamos el accesorio de display usando getComputedStyle para ver si está bloqueado.
Si es un bloque, significa que esta es la cortina que se está viendo y el botón en esta iteración es el botón que debe tener un click event listener .
y, por último, la parte {once: true} es asegurarse de que el evento solo se escuche una vez. Dado que ya está utilizando la palabra clave const , eso significa que solo va a buscar navegadores modernos, por lo que no es necesario usar removeEventListener por separado {once: true} funcionará en todos los navegadores modernos.
violín de trabajo actualizado: https://jsfiddle.net/avwonj91/1/