Clicking the X button should remove the player

I am trying to have this work in the code to remove duplication.

Working Code Example: https://jsfiddle.net/w3ctbv1s/1/

In the code below, I was trying to remove at least one player, then I could figure out how to do the others.

I am trying to have this part work in the code:

Code I am working on: https://jsfiddle.net/hxm1y47b/9/

I am thinking it should be able to work in this code.

This is the part from the working code that is responsible for removing the player.

const manageUI = (function makeManageUI() {
  function addExitHandlers(callback) {
    const resetVideo = document.querySelectorAll(".exitA");
    resetVideo.forEach(function resetVideoHandler(video) {
      video.addEventListener("click", callback);
    });
  }

  return {
    addExitHandlers
  };
}());
function removePlayer(wrapper) {
    wrapper.player.destroy();
    delete wrapper.player;
    console.log("removePlayer");
  }

  function removePlayerHandler(evt) {
    const el = evt.target;
    const container = el.closest(".containerA"); // Changed ".container" to ".containerA"
    const wrapper = container.querySelector(".wrap");
    if (wrapper.player) {
      return removePlayer(wrapper);
    }
  }
const loadPlayer = (function uiLoadPlayer() {
  function addPlayer(playerSelector, playerOptions) {
    const parent = document.querySelector(playerSelector).parentElement;
    const callback = managePlayer.adder(parent, playerOptions);
    callback();
  }

  manageUI.addExitHandlers(managePlayer.removePlayerHandler);
 
  return {
    add: addPlayer
  };
}());

Working Code: https://jsfiddle.net/w3ctbv1s/1/

At this code here is my last working code where all videos are visible on the screen:

Code I am working on: https://jsfiddle.net/mxy3qb7w/

This is what I have:

Latest attempt:

html:

      <div class="wrap">
        <div class="video video-frame" data-id="djV11Xbc914"></div>
      </div>
const manageUI = (function makeManageUI() {

  function exitClickHandler(event) {
    // Your code here. For example:
    console.log("Exit button clicked!");
  }


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


  function addExitHandlers(callback) {
    const resetVideo = document.querySelectorAll(".exit");
    resetVideo.forEach(function resetVideoHandler(video) {
      video.addEventListener("click", callback);
    });
  }


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


  return {
    addExitHandlers,
    init
  };
})();
function removePlayer(wrapper) {
    wrapper.player.destroy();
    delete wrapper.player;
    console.log("removePlayer");
  }


  function removePlayerHandler(evt) {
    const el = evt.target;
    const wrapper = document.querySelector(".wrap");
    if (wrapper.player) {
      removePlayer(wrapper);
    }
  }
 
  function initPlayer(wrapper, playerOptions) {
    createPlayer(wrapper, playerOptions);
  }


  return {
    adder: playerAdder,
    removePlayerHandler
  };
}());
const loadPlayer = (function uiLoadPlayer() {
  function addPlayer(playerSelector, playerOptions) {
    const parent = document.querySelector(playerSelector).parentElement;
    const callback = managePlayer.adder(parent, playerOptions);
    callback();
  }
 
   function init() {
   manageUI.init({});
   manageUI.addExitHandlers(managePlayer.removePlayerHandler);
  }


  return {
   add: addPlayer,
   init
  };
})();


 function init() {
  managePlayer.init();
  manageUI.init();
  }
 
loadPlayer.init();

This way seems to be buggy also I have just found.

https://jsfiddle.net/nxudfsyL/7/

  function destroyPlayers() {
    players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) { // Check if playerElement is not null or undefined
        console.log("Destroying player with class: " + playerElement.className);
        player.destroy();
      }
      console.log("playerRemoved"); // Log a message when a player is destroyed
    });
  }

  return {
    addPlayer,
    players,
    destroyPlayers // Add the destroyPlayers function here
  };
}());

Added 3 of these

function removePlayer() {
    videoPlayer.destroyPlayers();
  }

  function resetPage() {
    removePlayer();
  }

Added this so that, videos are destroyed individually instead of,

when clicking the close button, what would happen is,

Only one video would launch, but in console log, after clicking the close button, it would say, buttona, buttonb, buttonc destroyed, even though only one video was launched.

This code fixes that so that does not occur.

    const modalButtons = document.querySelectorAll(".playButton");
    modalButtons.forEach(function(button, index) {
      button.addEventListener("click", function(event) {
        const target = this.dataset.destination;
        openModal(target);
        if (index === 0) {
          loadPlayer.add(".buttonA", {
            videoId: "CHahce95B1g"
          });
        } else if (index === 1) {
          loadPlayer.add(".buttonB", {
            videoId: "CHahce95B1g"
          });
        } else if (index === 2) {
          loadPlayer.add(".buttonC", {
            videoId: "CHahce95B1g"
          });
        }
      });
    });
  }

… you have 700 lines of code for a youtube video player.

I think perhaps you’ve wandered off into the woods.

You’ve got functions whose only purpose is to call other functions, you’ve got functions with the same names, you’ve got functions inside functions for no discernable reason… it looks like this code has been through a code confetti cannon. Thrice.

I would suggest putting that page aside, starting a blank one, and keeping it simple.

3 Likes

He did have a good suite of tests. With that suite he can make all kinds of changes to the structure without fear of breaking anything, because those tests give immediate feedback about anything that broke, making it easy to fix.

Fear is the mind killer.

Without such tests though, I doubt that he has the ability to do anything at all with the code.

A suite of tests without understanding of the code that they’re testing is rather moot.

The sheer number of threads about this same piece of code over the last couple of weeks tells me the OP’s in over their head; this one simply emphasizes the point that the code has grown so complex that when I try to read it to understand, I give up.

You can’t tell me that this function holds any merit:

 function openModalHandler() {
    openModal();
  }

… It’s literally a function that calls another function in the same scope (literally defined above this one), with no parameters in or out. It’s also not being called anywhere in the active code thread…

2 Likes

I am getting better at using console logs.

This code here has no jslint errors: https://jsfiddle.net/es54q2nL/2/

this keyword removed: https://jsfiddle.net/es54q2nL/4/

Improved a drop: https://jsfiddle.net/f2yhtp5r/3/

Another way is can be written: https://jsfiddle.net/f2yhtp5r/10/

    function addPlayerToButtons() {
        const modalButtons = document.querySelectorAll(".playButton");
        modalButtons.forEach(function(button, index) {
            button.addEventListener("click", function(event) {
                //const target = event.currentTarget.dataset.destination;
                //openModal(target);
                openModal(event.currentTarget.dataset.destination);
    function addCloseEventToModals() {
        const closeModals = document.querySelectorAll(".close");
        closeModals.forEach(function(modal) {
            modal.addEventListener("click", function(event) {
                //const currentModal = event.target.closest(".modal");
                //closeModal(currentModal);
                closeModal(event.target.closest(".modal"));
            });
        });
    }

I can do this: https://jsfiddle.net/gjxzq8se/1/

        function removePlayer() {
        videoPlayer.players.forEach(function(player) {
            const playerElement = player.getIframe();
            if (playerElement) {
                const playerClass = playerElement.className;
                console.log("Destroying player with class: " + playerClass);
                player.destroy();
            }
        });
        console.log("playerRemoved");
    }
    
    return {
        addPlayer,
        players,
        removePlayer
    };
}());

inside here:

const videoPlayer = (function makeVideoPlayer() {
// videoPlayer code here...
})();

or I can add this: https://jsfiddle.net/azs8eph4/4/

const playerManager = (function makePlayerManager() {
  function removePlayer() {
    videoPlayer.players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) {
        const playerClass = playerElement.className;
        console.log("Destroying player with class: " + playerClass);
        player.destroy();
      }
    });
    console.log("playerRemoved");
  }
  return {
    removePlayer
  };
}());

Somewhere in here:

const videoPlayer = (function makeVideoPlayer() {
// videoPlayer code here...
})();

const managePlayer = (function makeManagePlayer() {
// managePlayer code here...
})();

const loadPlayer = (function uiLoadPlayer() {
// loadPlayer code here...
})();

More editing: https://jsfiddle.net/9ucrjb0g/3/

I went with the first option.

Not buggy at all.

Removes duplication well.

  function destroyPlayers() {
    videoPlayer.players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) {
        const playerClass = playerElement.className;
        console.log("Destroying player with class: " + playerClass);
        player.destroy();
      }
    });
    console.log("playerRemoved");
  }

  return {
    addPlayer,
    destroyPlayers,
    players
  };
}());
function removePlayer() {
    videoPlayer.destroyPlayers();
  }

  function resetPage() {
    hideContainer(".video-containerA");
    showContainer(".modalA");
    removePlayer();

Full function code:

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 shufflePlaylist(player, shuffle) {
    player.setShuffle(shuffle);
    player.playVideoAt(0);
    player.stopVideo();
  }

  function onPlayerReady(event) {
    const player = event.target;
    player.setVolume(100);
    const isShuffle = player.getIframe().dataset.shuffle === "true";
    shufflePlaylist(player, isShuffle);
  }

  function onPlayerStateChange(event) {
    const eventPlayer = event.target;
    if (event.data === 1) {
      players.forEach(function pauseOtherVideos(player) {
        const hasIframe = player.getIframe();
        const isDifferentPlayer = player !== eventPlayer;
        const isPlaying = player.getPlayerState() === 1;
        if (hasIframe && isDifferentPlayer && isPlaying) {
          player.pauseVideo();
          console.log("pause");
        }
      });
    }
  }

  function addPlayer(video, playerOptions) {
    let id = video.dataset.id;
    playerOptions.playerVars = playerOptions.playerVars || {};
    if (playerOptions.listType && playerOptions.list) {
      playerOptions.playerVars.listType = playerOptions.listType;
      playerOptions.playerVars.list = playerOptions.list;
    } else if (id && id.startsWith("PL")) {
      playerOptions.playerVars.listType = "playlist";
      playerOptions.playerVars.list = id;
    }
    if (Array.isArray(playerOptions.videoId)) {
      const randomNumber = Math.random() * playerOptions.videoId.length;
      const randomIndex = Math.floor(randomNumber);
      playerOptions.videoId = playerOptions.videoId[randomIndex];
    } else if (!playerOptions.videoId && id) {
      playerOptions.videoId = id;
    }
    video.dataset.shuffle = playerOptions.shuffle;
    playerOptions.events = playerOptions.events || {};
    playerOptions.events.onReady = onPlayerReady;
    playerOptions.events.onStateChange = onPlayerStateChange;
    players.push(new YT.Player(video, playerOptions));
  }

  function destroyPlayers() {
    videoPlayer.players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) {
        const playerClass = playerElement.className;
        console.log("Destroying player with class: " + playerClass);
        player.destroy();
      }
    });
    console.log("playerRemoved");
  }

  return {
    addPlayer,
    destroyPlayers,
    players

  };
}());

Should I have done this instead?

const playerManager = (function makePlayerManager() {
  function removePlayer() {
    videoPlayer.players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) {
        const playerClass = playerElement.className;
        console.log("Destroying player with class: " + playerClass);
        player.destroy();
      }
    });
    console.log("playerRemoved");
  }
  return {
    removePlayer
  };
}());

Which way is better?

I can do this: Code 1) https://jsfiddle.net/9ucrjb0g/3/

function destroyPlayers() {
    videoPlayer.players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) {
        const playerClass = playerElement.className;
        console.log("Destroying player with class: " + playerClass);
        player.destroy();
      }
    });
    console.log("playerRemoved");
  }

  return {
    addPlayer,
    destroyPlayers,
    players
  };
}());
function removePlayer() {
    videoPlayer.destroyPlayers();
  }

  function resetPage() {
    removePlayer();
}

or I can do this: Code 2) https://jsfiddle.net/41esd2qz/1/

const playerManager = (function makePlayerManager() {
  function removePlayer() {
    videoPlayer.players.forEach(function(player) {
      const playerElement = player.getIframe();
      if (playerElement) {
        const playerClass = playerElement.className;
        console.log("Destroying player with class: " + playerClass);
        player.destroy();
      }
    });
    console.log("playerRemoved");
  }
  return {
    removePlayer
  };
}());
function removePlayer() {
        playerManager.removePlayer();
    }

    function resetPage() {
         removePlayer();
    }