Making changes to the CSS now that the play buttons are inside their own container

The problem is that the reset is set to take place when an animation called fadingOut completes.

   if (animationName === "fadingOut") {
      fadeReset();
    }
  }

That animation name called fadingOut (not to be confused with the fadingOut class that is added to the body) is actually taking place on .outer. When you remove .outer the animation never takes place and the animation event handler never gets fired so nothing happens. There will be no error in the js because nothing happened.

If you change the fadeReset to start when the curtain is closed it should work.

   if (animationName === "curtain1-close") {
      fadeReset();
    }
  }

You can then comment out the resetButtons rules in these two blocks.

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

...

  function fadeReset() {
    body.classList.remove("fadingOut");
    resetBackground("body");
    resetCurtains(".with-curtain");
    showAllButtons(".hide");
    //resetButtons(".outer");
  }

You can then delete the resetButtons functions as I think those two are the only places it is used.

/*jslint devel: true */

const manageCover = (function makeManageCover() {
  const config = {};
  const body = document.body;
  let currentPlayButton = {};

  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 resetPage() {
    resetBackground("body");
  }

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

  /*function showCover(playButton) {
    hideAll(config.containers);
    resetPage();
    markAsPlayed(playButton);
    const cover = playButton.parentElement;
    cover.classList.add("active");
    show(cover);
  }*/

  function showCover(playButton) {
    hideAll(config.containers);
    resetPage();
    markAsPlayed(playButton);
    const playButtonContainer = playButton.parentElement;
    const playButtonIndex = Array.from(document.getElementsByClassName('cover')).findIndex(element => element == playButton)
    const container = config.containers[playButtonIndex]
    playButtonContainer.classList.add("active");
    container.classList.add("active");
    show(playButtonContainer);
    show(container);
  }

  function animationEndHandler(evt) {
    const animationName = evt.animationName;

    if (animationName === "initial-fade") {
      body.classList.remove("initial-fade");
      showCover(currentPlayButton);
    }
  }

  function coverClickHandler(evt) {
    currentPlayButton = evt.currentTarget;
    body.classList.add("initial-fade");
  }

  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);
    body.addEventListener("animationend", animationEndHandler);
  }

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

const manageUI = (function makeManageUI() {
  const body = document.body;

  const players = [];

  function findPlayers() {
    const allCovers = document.querySelectorAll(".cover");
    const allWrappers = document.querySelectorAll(".wrap");
    allCovers.forEach(function addToPlayers(cover, index) {
      players.push({
        "cover": cover,
        "wrapper": allWrappers[index]
      });
    });
  }

  // inline arrow function, direct return
  function getWrapper(cover) {
    const index = players.findIndex(
      (player) => player.cover === cover
    );
    return players[index].wrapper;
  }

  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 animationEndHandler(evt) {

    const animationName = evt.animationName;
    console.log(animationName);

    if (animationName === "curtain1-close") {
      fadeReset();
    }
  }

  function fadeReset() {
    body.classList.remove("fadingOut");
    resetBackground("body");
    resetCurtains(".with-curtain");
    showAllButtons(".hide");
  }

  function resetPage() {
    body.classList.add("fadingOut");
  }

  function exitClickHandler() {
    resetPage();
  }

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

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

  function init() {
    findPlayers();
    const exitButtons = document.querySelectorAll(".exit");
    addClickToExit(exitButtons);
    body.addEventListener("animationend", animationEndHandler);
  }

  return {
    addExitHandlers,
    getWrapper,
    init
  };
}());

const videoPlayer = (function makeVideoPlayer() {

  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 onPlayerReady(event) {
    const player = event.target;
    player.setVolume(100);
  }

  function onPlayerStateChange(event) {
    const player = event.target;
    return player;
  }

  function addPlayer(video, playerOptions) {
    playerOptions.videoId = playerOptions.videoId || video.dataset.id;
    playerOptions.events = playerOptions.events || {};
    playerOptions.events.onReady = onPlayerReady;
    playerOptions.events.onStateChange = onPlayerStateChange;

    const player = new YT.Player(video, playerOptions);
    return player;
  }

  return {
    addPlayer
  };
}());

const managePlayer = (function makeManagePlayer() {

  const playerVars = {
    autoplay: 0,
    controls: 1,
    disablekb: 1,
    enablejsapi: 1,
    fs: 0,
    iv_load_policy: 3
  };
  const defaults = {
    height: 360,
    host: "https://www.youtube-nocookie.com",
    playerVars,
    width: 640
  };

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

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

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

  function playerAdder(wrapper, playerOptions) {
    return function addPlayerCallback() {
      initPlayer(wrapper, playerOptions);
    };
  }

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

  function removePlayerHandler(evt) {
    const el = evt.target;
    const container = el.closest(".container");
    const wrapper = container.querySelector(".wrap");
    if (wrapper.player) {
      return removePlayer(wrapper);
    }
  }

  function initPlayer(wrapper, playerOptions) {
    show(wrapper);
    const player = createPlayer(wrapper, playerOptions);
    wrapper.player = player;
  }

  return {
    adder: playerAdder,
    removePlayerHandler
  };
}());

const players = (function coverUIPlayerFacade() {

  function addPlayer(coverSelector, playerOptions) {
    const cover = document.querySelector(coverSelector);
    const wrapper = manageUI.getWrapper(cover);
    const callback = managePlayer.adder(wrapper, playerOptions);
    manageCover.addCoverHandler(coverSelector, callback);
  }

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

    manageUI.init({});
    manageUI.addExitHandlers(managePlayer.removePlayerHandler);
  }

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

players.init();

function onYouTubeIframeAPIReady() {

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

}

Transition from exit to play buttons is much smoother here than
https://jsfiddle.net/k8Letszc/

When removing .outer
Much faster here the transition.
https://jsfiddle.net/8zq3cda7/

See the difference?

Is there a way to adjust that in the code?

Also, to fix the video player from sticking to the ceiling,

I am changing this

.container {
  display: flex;
  justify-content: center;
  position: relative;
}

To this? https://jsfiddle.net/8zq3cda7/3/

.container {
  display: flex;
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
}

And this gets deleted:

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

Visually I notice no difference but there probably is a difference because in the pne with outer you are waiting for the animation on outer to finish before resetting. On the example with outer removed you are waiting for the curtain animation to finish which probably happens sooner than the other animation.

You could extend the keyframe to a little longer like this.

.fadingOut .container.active .curtain .panel-left {
animation: curtain1-close 10s ease forwards;
transform: translateX(calc(-100% - 1px));
animation-delay: 3.3s;
}

@keyframes curtain1-close {
  80% {
    transform: translateX(0);
  }

  100% {
    transform: translateX(0);

  }
}

.fadingOut .container.active .curtain .panel-right {
  animation: curtain2-close 10s ease forwards;
  transform: translateX(calc(100% + 1px));
  animation-delay: 3.3s;
}

@keyframes curtain2-close {
  80% {
    transform: translateX(0);
  }

  100% {
    transform: translateX(0);
  }
}

However, I don’t think that is what you are seeing.

I have both side by side and fail to see a difference other than the timing mentioned.

If there is a difference other than the above then I don’t see where its coming from as the animation that was removed was on .outer which in effect was invisible on the screen and had no effect other than to start the fadeReset actions.

if you can narrow down exactly what you think is different (other than that initial timing) it may give a clue if something was missed.

This works when .outer is in the code.
animation: fadingOut 1s;
With outer removed, changing the number does nothing, has no effect.

.fadingOut .isOpen {
  animation: fadingOut 1s;
  animation-delay: 11.3s;
}

@keyframes fadingOut {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

You’re confusing me with your different versions.

To answer the question regarding the fiddle in the quote you need to remove the outer div which is sitting on its own.

<div class="outer></div>

Then change the two references to .outer in the js to say .container instead.

 function resetPage() {
    resetBackground("body");
    resetButtons(".container");/* changed from .outer*/
  }
  function fadeReset() {
    body.classList.remove("fadingOut");
    resetBackground("body");
    resetCurtains(".with-curtain");
    showAllButtons(".hide");
    resetButtons(".container");/* changed from .outer */
  }

I think that answers your question.

.outer is sitting in the html like this and the code is working fine.

I was wrong.

There is a big difference.

Are you able to show me this working in the code?

Changing the numbers don’t do anything: https://jsfiddle.net/ve65adsn/2/

Unless I did something wrong.

Both delay and fading out do not work.
Changing the numbers doesn’t do anything.

The delay allows you to keep the curtains closed for as long as you want before it changes over to the next page.

With outer removed, this whole thing doesn’t work.

.container .isOpen {
  animation: fadingOut 1222s;
  animation-delay: 11.3s;
}

@keyframes fadingOut {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

I am able to do this: https://jsfiddle.net/v156Lxbe/

  function animationEndHandler(evt) {

    const animationName = evt.animationName;
    console.log(animationName);

    if (animationName === "fadingOut") {
      fadeReset();
    }
  }

  function resetPage() {
    resetButtons(".container");
  }


  function fadeReset() {
    resetButtons(".container");
  }

And this works again:

.fadingOut .isOpen {
  animation: fadingOut 1s;
  animation-delay: 10.3s;
}

@keyframes fadingOut {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

You did not read my post properly.

The animation is on .outer which is where the isOpen class was added to. If you remove outer then there is no animation as already stated because isOpen is not in place anywhere.

I gave you the full solution in post #10 which is the same code you posted back to me!

The isOpen class is now attached to .container which is why it starts working again.

I’m confused, which is the link with the correct code in it?

This one? https://jsfiddle.net/v156Lxbe/

This is good then?

Yes that looks like it. I didn’t look all the way through the code but the animation classes are working on that one and attached to ,container as they should be.

I don’t see an issue but then again I don’t know what you intended.

1 Like

Something I was trying to figure out.

This one is using: data-container: https://jsfiddle.net/mhudtyq9/

I can describe for you what I am trying to do in the code.

But I don’t know how it would be done in the code.

One button visible on the screen, that when clicked on, that will take you to a specific video that will open and play.

After you click the exit button it would take you back to the group of buttons.

Where playButtonContainer2 would stay removed.

There may even be an easier, more simpler way to do this, given how I always make things so complicated.

Another way of doing it I was thinking.

What if there were 10 buttons altogether.

One button is left by itself on page load, where the group of buttons would be left hidden.

Are either or both of those ways able to be done in the code?

What would need to occur in the code.

The things I thought of.

First, playButtonContainer would need to be hidden on page load.

Some of the added css.

.playButtonContainer2{
  display: flex;
  flex-wrap: wrap;
  min-height: 100%;
  margin: auto;
  justify-content: center;
  align-content: center;
  width: 290px;
  gap: 10px;
  animation: fadeInButtons 3s ease 0s forwards;
}

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

  100% {
    opacity: 1;
  }
}

.playButtonContainer,
.playButtonContainer.active {
  display: none;
}

.playButtonContainer2.active {
  display: none;
}

html

<div class="playButtonContainer2 with-curtain">
  <button class="playa cover" type="button" data-container="play1"></button>
or   
<button class="playj cover" type="button" data-container="play10"></button>
</div>

I have to go out but as a start I would do something like this.

.cover:not(.playa){
  animation:hide-cover 0s forwards;
}
@keyframes hide-cover {
  to{
    pointer-events:none;
    opacity:0;
    position:absolute;
  }
  
}

.playa.played{
  animation:hide-cover 0s forwards;
}
.playa.played ~ .cover{
  animation:show-cover 0s forwards;
}
@keyframes show-cover {
  to{
    pointer-events:initial;
    opacity:1;
    position:relative;
  }
}

That allows playa to be on its own and when you return play1 is hidden. No js needed so far.

Back later.

1 Like

I was able to receive help with this: https://jsfiddle.net/tju1v0f6/

You can do it by adding a class “initial” to the .playButtonContainer and to the button which you want to be hidden after being clicked, then adding a CSS selector that makes it so that all children of .playButtonContainer.active are hidden (except the ones with the class “active”)
with the class “initial”*
Then you change exitClickHandler to make it so that the class “initial” is removed from .playButtonContainer, and the button with the class “initial” is removed from the page

.playButtonContainer.initial .cover:not(.initial) {
  display: none;
}

I would just add it into here:

I can have 1 on page load, or as many I think, and 9 buttons come back when the exit is clicked.

<div class="playButtonContainer with-curtain initial">
  <button class="playa cover initial" type="button" data-container="play1"></button>
  <button class="playb cover" type="button" data-container="play2"></button>
  <button class="playh cover" type="button" data-container="play8"></button>
  <button class="playi cover" type="button" data-container="play9"></button>
 <button class="playj cover" type="button" data-container="play10"></button>
</div>

And this piece of javascript:

  function exitClickHandler() {
    resetPage();
    const playButtonContainer = document.getElementsByClassName('playButtonContainer')[0]
    playButtonContainer.classList.remove('initial')
    const initialPlayButton = playButtonContainer.querySelector('.initial')
    if (initialPlayButton) {
      initialPlayButton.remove();
    }
  }

I have an exitSkip button, it is currently visible on the screen. https://jsfiddle.net/vugm26yf/


Where would I put it in the html, how to position it under the play button.

Would it be placed in here, would I place it in its own container?

<div class="playButtonContainer with-curtain initial">
  <button class="playa cover initial" type="button" data-container="play1"></button>
   <button class="exitSkip" type="button"></button>  
</div>

It would be used to skip over to the group of 9 buttons.

Clicking the exitSkip button would unhide the group of 9 buttons, which in-turn will hide the exitSkip along with the play button.

How would I do that in the code?

<button class="exitSkip" type="button"></button>

.exitSkip {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  width: 47px;
  height: 47px;
  cursor: pointer;
  border-radius: 100%;
  background: transparent;
  border: 5px solid blue;
  box-sizing: border-box;
  clip-path: circle(50%);
}

.exitSkip::before,
.exitSkip::after {
  content: "";
  background-color: blue;
  width: 47px;
  height: 5px;
  position: absolute;
  top: 0px;
  left: -5px;
  right: 0;
  bottom: 0;
  margin: auto;
}

.exitSkip::before {
  transform: rotate(45deg);
}

.exitSkip::after {
  transform: rotate(-45deg);
}

I made a container for it here: https://jsfiddle.net/85um36r7/2/

How would I position each closer to each other?

.exitSkipContainer {
  display: flex;
  flex-wrap: wrap;
  min-height: 100%;
  margin: auto;
  justify-content: center;
  align-content: center;
  width: 290px;
  gap: 10px;
  animation: fadeInSkip 3s ease 0s forwards;
}
@keyframes fadeInSkip {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}
<div class="exitSkipContainer">
 <button class="exitSkip" type="button"></button>  
</div>

I gave you the full answer in post #17. You just needed to add the css to the end of the css file in this fiddle. Did you not try it? No JS or html changes were required at all. It is a working example. It was the best answer and as such I won’t be looking at alternatives.

1 Like

I did look at it, after I clicked the play button, there was no video player.

Wait, unless I had put it in wrong the first time.

Yours does work.

When I had put it in the first time, all I saw was a background, no video player.

Using your code, how would I properly position the exitSkip button?

https://jsfiddle.net/t5ume9rz/

It would go underneath the play button.

Would I wrap both containers together in a div?

Clicking the exitSkip button would unhide the group of 9 buttons, which in-turn would hide the exitSkip along with the play button, those two would not be seen again, after getting past that page.

<div class="playButtonContainer with-curtain">
  <button class="playa cover" type="button" data-container="play1"></button>
<button class="playi cover" type="button" data-container="play10"></button>
</div>
<div class="exitSkipContainer">
 <button class="exitSkip" type="button"></button>  
</div>

My attempt, I guess this is wrong then: https://jsfiddle.net/f25wm7yz/

I thought it would be done the same way as the other buttons.

When the window moves, so does the exit.

.exitSkipContainer {
  position:absolute;
  left:0;
  right:0;
  display: flex;
  flex-wrap: wrap;
  margin: 200px  auto 0;
  justify-content: center;
  align-content: center;
  max-width: 150px;
  gap: 50px;
  background: none;
<div class="playButtonContainer with-curtain">
  <button class="playa cover" type="button" data-container="play1"></button>
  <button class="playj cover" type="button" data-container="play10"></button>

  <div class="exitSkipContainer">
    <button class="exitSkip" type="button"></button>
  </div>
</div>

What is the exitSkip button?

My code is based on this fiddle:

There is no exitSkip button and no need for it.

Where did exitSkip come from and what is its purpose?

Why is there a button in the middle of the video?

None of that was in the fiddle that I based my code on. All you needed was the css.

This was an idea I added afterwards.

Clicking the exitSkip button would unhide the group of 9 buttons, which in-turn would hide the exitSkip along with the play button, those two would not be seen again, after getting past that page.

For, if you’ve already seen the video and want to skip to the grid of 9 videos.

You can see here how the js version of it works. https://jsfiddle.net/vmnxqbfu/

I take it there is no way to fade in the group of 9 buttons, after the exitSkip is clicked?

Because they’ve already faded in when the page first loads?

Is there some way to add a transition or animation for when the the exitSkip button is clicked, taking you to the buttons?

Is there a way for the code, how it is currently written, could it be adjusted in a way that would allow for the group of 9 buttons to be able to fade in when the exitSkip button is clicked?

Can’t transition out of a display: none; state.

.playButtonContainer.initial .cover:not(.initial) {
  display: none;
}

Would you know of a way that may work?

What I am trying to do is figure out some way where, when the exitSkip button is pressed, the group of 9 buttons, you’re able to see them fade in.

What would need to be able to occur for that to happen?