Home > database >  handler is being called multiple times
handler is being called multiple times

Time:10-13

Inside the code the handler is being called multiple times.

It should only be called once.

How is that fixed in the code, what would need to be adjusted?

In console inside jsfiddle, it says, 1, 3, 6, 10

It should be: 1, 2, 3, 4, I think, right?, or no?

After clicking the exit buttons. enter image description here

Then the numbers appear in the console inside jsfiddle.

enter image description here

const manageUI = (function makeManageUI() {

  function resetBackground(backgroundSelector) {
    const allBackgrounds = document.querySelectorAll(backgroundSelector);

    function showBackground(background) {
      background.classList.remove("bg1");
    }
    allBackgrounds.forEach(showBackground);
  }

  function resetCurtains(curtainSelector) {
    const allCurtains = document.querySelectorAll(curtainSelector);

    function showCurtain(curtain) {
      curtain.classList.remove("active");
    }
    allCurtains.forEach(showCurtain);
  }

  function showAllButtons(buttonSelector) {
    const allButtons = document.querySelectorAll(buttonSelector);

    function showButton(button) {
      button.classList.remove("hide");
    }
    allButtons.forEach(showButton);
  }

  function resetButtons(buttonSelector) {
    const allButtons = document.querySelectorAll(buttonSelector);

    function showButton(button) {
      button.classList.remove("isOpen");
    }
    allButtons.forEach(showButton);
  }

  function resetPage() {
    resetBackground("body");
    resetCurtains(".with-curtain");
    showAllButtons(".container.hide");
    resetButtons(".outer");
  }

  function hideCurtains(exitButtons) {
    const container = exitButtons.closest(".inner-container");
    const curtains = container.querySelector(".sliding-panels");
    curtains.classList.add("hide");
  }

  function exitClickHandler(evt) {
    resetPage();
    hideCurtains(evt.currentTarget);
  }

  function addClickToExit(exitButtons) {
    exitButtons.forEach(function addExitButtonHandler(exitButtons) {
      exitButtons.addEventListener("click", exitClickHandler);
    });
  }

  function init() {
    const exitButtons = document.querySelectorAll(".exit");
    addClickToExit(exitButtons);
  }

  return {
    init
  };
}());

const manageCover = (function makeManageCover() {
  const config = {};

  function show(el) {
    el.classList.remove("hide");
  }

  function hide(el) {
    el.classList.add("hide");
  }

  function hideAll(elements) {
    elements.forEach(hide);
  }

  function resetBackground(backgroundSelector) {
    const allBackgrounds = document.querySelectorAll(backgroundSelector);

    function hideBackground(background) {
      background.classList.add("bg1");
    }
    allBackgrounds.forEach(hideBackground);
  }

  function resetButtons(buttonSelector) {
    const allButtons = document.querySelectorAll(buttonSelector);

    function hideButton(button) {
      button.classList.add("isOpen");
    }
    allButtons.forEach(hideButton);
  }

  function resetPage() {
    resetBackground("body");
    resetButtons(".outer");
  }

  function markAsPlayed(played) {
    played.classList.add("played");
  }

  function showCovers(playButton) {
    const cover = playButton.parentElement;
    cover.classList.add("active");
    show(cover);
  }

  function coverClickHandler(evt) {
    hideAll(config.containers);
    resetPage();
    markAsPlayed(evt.currentTarget);
    const cover = evt.currentTarget;
    showCovers(cover);
  }

  function addClickToButtons(playButtons) {
    playButtons.forEach(function playButtonHandler(playButton) {
      playButton.addEventListener("click", coverClickHandler);
    });
  }

  function addCoverHandler(coverSelector, handler) {
    const cover = document.querySelector(coverSelector);
    cover.addEventListener("click", handler);
  }

  function init(selectors) {
    config.containers = document.querySelectorAll(selectors.container);
    const playButtons = document.querySelectorAll(selectors.playButton);
    addClickToButtons(playButtons);
  }

  return {
    addCoverHandler,
    init
  };
}());

function combinePlayerOptions(options1 = {}, options2 = {}) {
  const combined = Object.assign({}, options1, options2);
  Object.keys(options1).forEach(function checkObjects(prop) {
    if (typeof options1[prop] === "object") {
      combined[prop] = Object.assign({}, options1[prop], options2[prop]);
    }
  });
  return combined;
}

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
  };
}());

const managePlayer = (function makeManagePlayer() {
  const defaults = {
    playerVars: {
      autoplay: 1,
      controls: 1,
      disablekb: 1,
      enablejsapi: 1,
      fs: 0,
      iv_load_policy: 3
    }
  };

  function show(el) {
    el.classList.remove("hide");
  }

  function createPlayer(videoWrapper, settings = {}) {
    const video = videoWrapper.querySelector(".video");
    const playerOptions = combinePlayerOptions(defaults, settings);
    return videoPlayer.addPlayer(video, playerOptions);
  }

  function createCoverClickHandler(playerOptions) {
    return function coverClickHandler(evt) {
      const cover = evt.currentTarget;
      const wrapper = cover.nextElementSibling;
      show(wrapper);
      const player = createPlayer(wrapper, playerOptions);
      wrapper.player = player;
    };
  }

  function addPlayer(coverSelector, playerOptions) {
    const clickHandler = createCoverClickHandler(playerOptions);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }

  return {
    add: addPlayer
  };

}());

function onYouTubeIframeAPIReady() {

  managePlayer.add(".playa", {});
  managePlayer.add(".playb", {});
  managePlayer.add(".playc", {});
  managePlayer.add(".playd", {});
  managePlayer.add(".playe", {
    playerVars: {
      playlist: "0dgNc5S8cLI,mnfmQe8Mv1g,-Xgi_way56U,CHahce95B1g"
    }
  });
  managePlayer.add(".playe", {});
  managePlayer.add(".playf", {});
  managePlayer.add(".playg", {});
  managePlayer.add(".playh", {});
  managePlayer.add(".playi", {});

  manageCover.init({
    container: ".container",
    playButton: ".thePlay"
  });

  manageUI.init({});
}
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  background: #353198;
  animation: fade 2s ease 0s forwards;
}


@keyframes fade {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

.outer {
  display: flex;
  flex-wrap: wrap;
  min-height: 100%;
  width: 290px;
  box-sizing: border-box;
  justify-content: center;
  align-content: center;
  margin: auto;
  gap: 10px;
}

.outer.isOpen {
  display: flex;
  width: auto;
  align-content: stretch;
}

.container {
  display: flex;
  justify-content: center;
  position: relative;
  /*z-index: 2;*/
}

.container.active {
  flex: 1 0 0;
}


.thePlay:hover {
  box-shadow: 0 0 0 5px rgba(43, 179, 20, 0.5);
}

.thePlay:focus {
  outline: 0;
  box-shadow: 0 0 0 5px rgba(0, 255, 255, 0.5);
}

.inner-container {
  display: none;
}

/* when container is active hide the svg and show the inner container*/
.container.active .thePlay {
  display: none;
}

.container.active .inner-container {
  display: flex;
}

.container.active .inner-container.curtain {
  display: block;
}

@keyframes fadebody {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

.thePlay {

  width: 90px;
  height: 90px;
  border-radius: 50%;
  cursor: pointer;
  border: none;
  fill: blue;
  background: transparent;
  padding: 0;
  filter: drop-shadow(3px 3px 3px rgba(0, 0, 0, 0.7));
}

.played {
  fill: green;
}



button.thePlay {
  pointer-events: none;
}

.exit {
  position: absolute;
  top: auto;
  bottom: -47.63px;
  margin: auto;
  right: 0;
  left: 0;
  width: 47.63px;
  height: 47.63px;
  cursor: pointer;
  border: none;
  background: transparent;
  fill: red;
  padding: 0;
}

.exitsvg {
  fill: none;
  fill-rule: evenodd;
  stroke: #ff0000;
  stroke-width: 17.80202103;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  stroke-miterlimit: 4;
  stroke-dasharray: none;
  stroke-opacity: 1;
  border: 4.625px solid #4e4e4e;
  border-radius: 100%;
}

.curtain {
  position: relative;
  max-width: 642px;
  margin: auto;
  flex: 1 0 0%;
  background: #0a0a0a;
  border: 20px solid #000;
  border-radius: 3.2px;
  border-color: #000 #101010 #000 #101010;
}

.panel-left,
.panel-right {
  position: absolute;
  height: 100%;
  width: calc(50%   1px);
  /* rounding error fix */
  top: 0%;
  transition: all ease 10s;

  /*background-image: url("https://picsum.photos/600");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;*/
  overflow: hidden;
}

.panel-left {
  left: 0;
  /*background-color: rgb(91, 96, 106);*/
}

.panel-right {
  right: 0;
  /*background-color: rgb(229, 211, 211);*/
}

.panel-left::before,
.panel-right::before {
  content: "";
  position: absolute;
  height: 100%;
  width: 200%;
  top: 0;
  left: 0;
  background-image: url("data:image/svg xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'> <filter id='filter'> <feTurbulence baseFrequency='0.01 0.0001' numOctaves='5'/> <feColorMatrix values='1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1'/></filter> <rect width='100%' height='100%' filter='url(#filter)'/> </svg>");
  background-size: auto;
  background-repeat: no-repeat;
  background-position: 0 0;
}

.panel-right::before {
  left: -100%;
}

.container.active .curtain .panel-left {
  animation: curtain1 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain1 {
  to {
    transform: translateX(-100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain2 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain2 {
  to {
    transform: translateX(100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain3 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain3 {
  to {
    transform: translateX(100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain4 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain4 {
  to {
    transform: translateX(100%);
  }
}


.container.active .curtain .panel-right {
  animation: curtain5 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain5 {
  to {
    transform: translateX(100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain6 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain6 {
  to {
    transform: translateX(100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain7 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain7 {
  to {
    transform: translateX(100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain8 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain8 {
  to {
    transform: translateX(100%);
  }
}

.container.active .curtain .panel-right {
  animation: curtain9 8s forwards;
  animation-delay: 1s;
}

@keyframes curtain9 {
  to {
    transform: translateX(100%);
  }
}


.ratio-keeper {
  position: relative;
  height: 0;
  padding-top: 56.25%;

  margin: auto;
  overflow: hidden;
  border: 1px solid #333;
}

.video-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.hide {
  display: none;
}
<div class="outer">
  <div class="container with-curtain">
    <button class="playa thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <g id="play">
          <title>Play</title>
          <circle cx="32" cy="32" r="32" fill="transparent" pointer-events="visiblePainted" />
          <path d="M25.6,46.4L44.8,32L25.6,17.6V46.4z M32,0C14.3,0,0,14.3,0,32s14.3,32,32,32s32-14.3,32-32S49.7,0,32,0z
                  M32,57.6C17.9,57.6,6.4,46.1,6.4,32S17.9,6.4,32,6.4S57.6,17.9,57.6,32S46.1,57.6,32,57.6z" />
        </g>
      </svg>
    </button>
    <div class="inner-container curtain curtain1">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="CHahce95B1g"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <g id="exit">
            <title>exit</title>
            <path d="M 6.3895625,6.4195626 C 93.580437,93.610437 93.580437,93.610437 93.580437,93.610437" />
            <path d="M 6.3894001,93.6106 C 93.830213,6.4194003 93.830213,6.4194003 93.830213,6.4194003" />
          </g>
        </svg>
      </button>
    </div>
  </div>
  <div class="container play2 with-curtain">
    <button class="playb thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain2">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play3 with-curtain">
    <button class="playc thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain3">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play4 with-curtain">
    <button class="playd thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain4">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play5 with-curtain">
    <button class="playe thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain5">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play6 with-curtain">
    <button class="playf thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain6">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play7 with-curtain">
    <button class="playg thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain7">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play8 with-curtain">
    <button class="playh thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain8">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
  <div class="container play9 with-curtain">
    <button class="playi thePlay" type="button" aria-label="Open">
      <svg width="100%" height="100%" viewBox="0 0 64 64">
        <use href="#play" />
      </svg>
    </button>
    <div class="inner-container curtain curtain9">
      <div class="ratio-keeper">
        <div class="wrapa">
          <div class="video video-frame" data-id="-Xgi_way56U"></div>
        </div>
        <div class="sliding-panels">
          <div class="panel-left"></div>
          <div class="panel-right"></div>
        </div>
      </div>
      <button class="exit" type="button" aria-label="Close">
        <svg class="exitsvg" width="38.39" height="38.39" viewBox="0 0 100 100">
          <use href="#exit" />
        </svg>
      </button>
    </div>
  </div>
</div>

CodePudding user response:

Everytime you call the createResetHandler you bind the video.addEventListener to the same element. You should video.removeEventListener everytime you destroy the player.

This would be an example of your code:

function createResetHandler(player) {
    const resetVideos = document.querySelectorAll('.exit');
    resetVideos.forEach(function resetVideoHandler(video) {
        video.removeEventListener('click', testFunction);
        video.addEventListener('click', testFunction);
      }
    )
  }
  
  const testFunction = () => {
        console.log('HIT');
  };

CodePudding user response:

The onPlayerReady ready event is fired every time you play a video. With every click on play it adds another listener.

You can:

  • Remove the old listener using node.removeEventListener('click')
    function createResetHandler() {
      const resetVideos = document.querySelectorAll('.exit');
      resetVideos.forEach(function resetVideoHandler(video) {
          video.removeEventListener("click");
          video.addEventListener('click', function resetVideoHandler() {
              player.destroy();
              console.log('hit')
            }
          );
        }
      )
    }
    
  • Use the once option for events and only assign the event to the video currently displayed using a single event on a higher level (body or document) - You don't have to to assign it multiple times.
    function createResetHandler(player) {
      document.addEventListener("click", ({ path }) => { 
        path.forEach(node => { 
          if (node.classList && node.classList.contains("exit")) {
            player.destroy();
            console.log("hit");
          }
        })
      }, { once: true });
    }
    

CodePudding user response:

Every time createResetHandler function is called, it assigns a new event listener to all buttons.

Also inside the createResetHandler function, player parameter should be used for creating event listener of related button, not all buttons.

Just delete the createResetHandler function and put the below code into the makeVideoPlayer function

  document.querySelectorAll(".exit").forEach((button) => {
    button.onclick = (e) => {
      const _iframe = e.currentTarget.parentElement.querySelector("iframe");
      if (_iframe) {
        players.map((player) => {
          if (player.h == _iframe) {
            player.destroy();
            console.log("hit");
          }
        });
      }
    };
  });
  • Related