Adding a 3rd container, a 3rd page

What would need to be adjusted in here? https://jsfiddle.net/p8ubq2ro/

Example Code: https://jsfiddle.net/h5vkt3br/

Is another animationend needed to do that, or no?

The 2nd page, .container2 is all messed up now.

I don’t understand what is wrong.

Click on each play button and you will see.

All I touched was the css and the html, where I added .container3

After adding in .container3 now .container2 is messed up.

If I remove .container3 from the html, .container2 is then fine.

Maybe I am missing stuff from the css.

At the end of .container2 I added a 2nd exit button that would take you to .container3

I think I messed up somewhere in there.

<div class="container1"></div>
<div class="container2"></div>
<div class="container3"></div>

You are not thinking this through.

When you exit container1 you add a class of bg1 to the body and that was the trigger to show container2 and hide container1.

Now when you exit container1 you actually show container2 and container3 at the same time. They are absolutely placed so they sit on top of each other.

You would need to put in some logic for multiple containers (which you have removed with your current demos). You would again need to use the hide class and place it on all the main containers except for the current one you want. You already had something like this before you removed all the code for it :slight_smile:

Or you could probably add a class of bg2 to the body when you exit container2 and use that to hide container2 and show container3 (as you have done with bg1 for container1).

That fixed the video issue, where all the play buttons were out of order.

How am I able to exit .container2?

The same way I was able to exit .container1.

https://jsfiddle.net/n7jxd291/1/

This would be initiated a 2nd time.

body.initial-fade {
  animation: initial-fade 1s ease forwards;
}

@keyframes initial-fade {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    pointer-events: none;
  }
}
.container3 {
  display: none;
}

.bg2 .container3 {
  display: flex;
}


body.bg2 {
  animation: bg2 5s ease 0s forwards;
}

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

  100% {
    opacity: 1;
    background: teal;
  }
}

How am I supposed to be able to have body.initial-fade work twice in the code?

It would be initiated each time the exit button is clicked.

In the demo code this is used.

 function animationEndHandler(evt) {

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

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

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

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

You had all this:

 const body = document.body;
  const thewrap = document.querySelector(".container2");
  const cover = document.querySelector(".container1");

  function show(el) {
    //el.classList.remove("hide");
    body.classList.add('initial-fade');
  }

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

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

    if (animationName === "initial-fade") {
      body.classList.remove("initial-fade");
      body.classList.add("bg1");
      hide(cover, thewrap);
    }
  }

  function exitClickHandler() {
    show(thewrap);
  }

Here is a small reproducible code if that helps.

https://jsfiddle.net/3rsawgu2/

Scroll down to see exit button.

Clicking on the exit button initiates the "initial-fade" after clicking the exit button the 1st time.

body.initial-fade {
  animation: initial-fade 1s ease forwards;
}

This initiated the 2nd fade.

/*.fadingOut .isOpen*/
.fadingOut .outer {
  animation: fadingOut 1s ease;
  animation-delay: 11.3s;
}

In the demo code two of these were used:

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

        if (animationName === "initial-fade") {
            body.classList.remove("initial-fade");
            showCover(currentPlayButton);
        }
    }
body.addEventListener("animationend", animationEndHandler);
    function animationEndHandler(evt) {

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

        if (animationName === "fadingOut") {
            fadeReset();
        }
    }
body.addEventListener("animationend", animationEndHandler);

At this code here I am trying to add animation end to both functions.

I’m all confused and stuck: https://jsfiddle.net/swt2aofn/5/

I keep looking at the demo code trying to put it all together.

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

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

  function openCurtain(curtain) {
    curtain.classList.add("slide");
  }

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

    function hideBackground(background) {
      background.classList.add("bg1");
    }
    allBackgrounds.forEach(hideBackground);
  }
  
    function resetBackground2(backgroundSelector) {
    const allBackgrounds = document.querySelectorAll(backgroundSelector);

    function showBackground(background) {
      background.classList.add("bg2");
    }
    allBackgrounds.forEach(showBackground);
  }

  function resetPage() {
    resetBackground("body");
    resetBackground2("body");
  }

  function coverClickHandler(evt) {
    const cover = evt.currentTarget;
    showCover(cover);
    const curtain = evt.currentTarget.parentElement
      .parentElement.parentElement;
    openCurtain(curtain);
  }

  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 addCoverHandler(coverSelector, handler) {
    const cover = document.querySelector(coverSelector);
    cover.addEventListener("click", handler);
  }

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

  function exitClickHandler() {
    body.classList.add('initial-fade');
  }

  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( /*selectors*/ ) {
    //config.containers = document.querySelector(selectors.container);
    // const allContainers = document.querySelector(".container");
    //const playButtons = document.querySelector(selectors.playButton);
    const allPlaybuttons = document.querySelectorAll(".cover");
    //const allPlaybuttons = document.querySelectorAll(".embed-youtube-play");
    addClickToButtons(allPlaybuttons);

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

  return {
   addExitHandlers,
    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 resetBackground2(backgroundSelector) {
    const allBackgrounds = document.querySelectorAll(backgroundSelector);

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

  function animationEndHandler(evt) {

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

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

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

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

  function exitClickHandler() {
    // body.classList.add('initial-fade');
    body.classList.add("fadingOut");
  }

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

In the demo code, only .bg1 was needed, there was never a .bg2, so I’m confused.

That held 9 different backgrounds.

As I said above in the initial demo the bg1 was only used to change the body background. It was not a trigger for hiding and showing the other containers. This was done by adding the hide class as shown in this screenshot.

Screen Shot 2022-11-10 at 13.13.59

The ‘hide’ class was used to hide all the other containers except the one that was showing.

In the other demo also note that all the stripy backgrounds are on the container elements and the code first fades the body background color and then fades in the current container color. You then have some code that does the reverse and fades out the body and container and once all animations are finished removes the bg1 is removed from the body and all the play buttons are once again shown by removing the hide class and results in hiding everything except the play buttons.

Your current demo has little symmetry with that old code so I suggest you start again with your new methods in mind rather than to keep harping back to something that doesn’t do anything close to what you are asking now.

I already detailed what you should be looking at and that would be to add a new class to show the new container and hide the old containers.

Based on the class on the body triggering the showing and hiding of things you would need to have css like this.

.container2 {
  display: none;
}
.container3 {
  display: none;
}
.bg1 .container1 {
  display: none;
}
.bg1 .container2 {
  display: flex;
}
.bg2 .container2 {
  display: none;
}
.bg2 .container3 {
  display: flex;
}

However you would need to update the JS to add the bg1 class to the body which with your current code is too awkward for me as it just looks like spaghetti now.

For example You call resetPage function at the end of the first block here but all that does is call resetBackgroundBody function. What’s the point of that?


function animationEndHandler(evt) {
    const animationName = evt.animationName;
    console.log(animationName);
    if (animationName === "initial-fade") {
      body.classList.remove("initial-fade");
      resetPage();
    }
  }

  function resetPage() {
    resetBackground("body");
  }

I can’t understand the flow of the JS anymore. It was all built for some other functions.

Also if you are going t be adding container 4 and container 5 then you need to go back to looping through the containers rather than setting individually so the js and css also needs to change again.

I need this also, right?

There needs to be 2 animation ends.

    function animationEndHandler(evt) {

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

        if (animationName === "fadingOut") {
            fadeReset();
        }
    }
body.addEventListener("animationend", animationEndHandler);

There needs to be 2 of these in the code, right?

body.addEventListener("animationend", animationEndHandler);

I was going to keep it at 3.

I added your code on here: https://jsfiddle.net/ryqf35hd/

 const thewrap = document.querySelector(".container2");
  const cover = document.querySelector(".container1");

  function show(el) {
    //el.classList.remove("hide");
    body.classList.add('initial-fade');
  }

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

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

    if (animationName === "initial-fade") {
      body.classList.remove("initial-fade");
      body.classList.add("bg1");
      hide(cover, thewrap);
    }
  }

  function exitClickHandler() {
    show(thewrap);
  }

Was just given a link:

You can see if it can be improved:

Answer Code https://jsfiddle.net/vhp8m4r2/

These were the links that were given from me, so we are not going in circles.

Small Reproducible Code: https://jsfiddle.net/reuqancf/

Full Code I am working on: https://jsfiddle.net/pzn98Lw6/

I was just told this, if you’re able to understand it.

There’s a couple of different ways to fix the issues with this, so I’ll mainly point out what the problems are, and show you 1 way to accomplish what you are looking for.

Looking at your css it seems like the class .bg2 is what you want to display the div with the class .container3.

Your css:

    .bg2 .container3 {
      display: flex;
    }

Now you need css to hide the div’s with the classes .container1, and .container2 when that .bg2 class gets applied.

    .bg2 .container1, .bg2 .container2 {
      display: none;
    }

Now the JS Your js that adds the class of .bg1 only gets ran once when the js is initialized. That’s why your class of .bg2 is not getting added. If you want to continue to solve the problem via this path, I would suggest moving the call to resetPage() (which is currently in the animationEndHandler() function), to the exitClickHandler() function. That way it will get called every time the exit button is clicked.

    function animationEndHandler(evt) {
      const animationName = evt.animationName;
      console.log(animationName);
      if (animationName === "initial-fade") {
        body.classList.remove("initial-fade");
        // moving this to exitClickHandler()
        // resetPage();
      }
    }
 
    function exitClickHandler() {
      body.classList.add('initial-fade');
      resetPage();
    }

There’s one more change to make. I did this a quick way because I’m not sure how you’d like to handle the displaying of your containers.

In the resetBackground() function I stated above it’s only adding the class of bg1 to your body tag. We need to modify this because in your css you have a class of bg2 which hides the other 2 containers and shows the third container. I created a counter variable and set it to 1 because your first class to add is bg1. Then I increment the counter after bg1 is added to your body tag. So next time the class added to your body tag is bg2.

    let counter = 1;
    function resetBackground(backgroundSelector) {
      const background = document.querySelector(backgroundSelector);
      background.classList.add("bg" + counter);
      counter++;
    }

Again, there’s multiple ways to accomplish the hiding and displaying of your containers of videos. Hope this helps you.

I don’t know what fade reset was doing.

You are adding bg1 and initial-fade and then removing both when the animation has ended. I think you could do it with just the one animation.

What happens when you go to the third container as the body background is now already teal. There is no background change as there was with the first.

The container logic is also flawed and I think you need to go back to using .hide and finding the parent from the parent of the button that was pressed.

This following example gets the containers showing when you click the exit button. I made it go back to the first container when the exit button on the first container was clicked.

The above was only concerned with the correct containers showing and I have not addressed any issues that would be broken by doing this. The fades are all wrong.

I wouldn’t use any of that code yet as I haven’t had time today to sort it out but it does show how the containers can be shown. I’ll be back tomorrow and have a deeper look.

1 Like

This example is now switching between the three containers and fading each in and out.

Its using the hide class as mentioned to achieve this plus a data attribute on the html to point to the required container.

There are other changes but the main ones are here.

function animationEndHandler(evt) {
    const animationName = evt.animationName;
    if (animationName === "bg1") {
      body.classList.remove("bg1");
      body.classList.add("default-bg");
    }
  }

 function exitClickHandler() {
    var myOuter = this.closest(".outer");
    var myDestination = this.dataset.destination;
    body.classList.add("bg1");
    myOuter.classList.add("hide");
    document.querySelector(myDestination).classList.remove("hide");
  }

<button data-destination=".container2" class="exit" type="button" aria-label="Open"></button>

and

<button data-destination=".container3" class="exit" type="button" aria-label="Open"></button>

and

<button data-destination=".container1" class="exit" type="button" aria-label="Open"></button>

I also reduced the CSS as you had about 150 lines of code instead of 15. The video-one to video-eleven css was exactly the same sand duplicated multiple times so I changed it to just this.

.video-cover {
  position: absolute;
  height: 100%;
  width: 100%;
  top: 0;
  transition: all 8s ease-in 0s;
  transition-delay: 1s;
  background: url("https://via.placeholder.com/264x264");
  background-position: center;
  background-size: 41.25% 73.33%;
  background-repeat: no-repeat;
  z-index: 1;
  animation: fadeInImage 2s ease-in 2s forwards;
  opacity: 0;
}

@keyframes fadeInImage {
  to {
    opacity: 1;
  }
}

.curtain1.slide .video-cover {
  transform: translateY(calc(-100% - 1px));
}

I haven’t looked at your other threads as I can only cope with one thing at a time.:wink:

1 Like

I just noticed that it fades out too quickly when you click exit so I will need to look at that later but away for a couple of hours now.

I believe this version has the fade in and fade outs between containers that were in the original.

1 Like

Is there a way to appear at the top of the screen after clicking the bottom exit button, instead of at the bottom?

Is there an actual way to do that?

I was looking at this: https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo

Yes you could use the js you mentioned to scroll to the top.

Or you could use an anchor instead of a button and send it to the top also.

I suppose the question is whether you want an animated scroll to the top or just immediately be at the top?

Back tomorrow now :;

1 Like

I think this: just immediately be at the top

This will do then:

window.scrollTo(0, 0);

It needs to go in the animationEnd event handler after the class of bg1 is removed otherwise you will see the change taking place.

Demo above updated.

1 Like

Where did I mess up in here in trying to add animationend back in?

I had removed it to make the testing of the code more easy, but when it was working, It was only fading in 1 page, not more than one.

https://jsfiddle.net/a4fendst/3/

When I click on the exit button, there is a fade to the next page to the next color, but the curtains aren’t appearing on the screen.

.bg1 .container1 {
  display: none;
}

body.initial-fade {
  animation: initial-fade 1s ease forwards;
}

@keyframes initial-fade {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    pointer-events: none;
  }
}

body.bg1 {
  animation: bg1 5s ease 0s forwards;
}

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

  100% {
    opacity: 1;
    background: teal;
  }
}

.container3 {
  display: none;
}

.container3.active  {
  display: flex;
}

.container2 {
  display: none;
}

.container2.active  {
  display: flex;
}

.container1.active  {
  display: none;
}
function resetVideos(videoSelector) {
    const allVideos = document.querySelectorAll(videoSelector);

    function showVideo(video) {
      video.classList.remove("active");
    }
    allVideos.forEach(showVideo);
  }

  function hideContainers(containerSelector) {
    const allContainers = document.querySelectorAll(containerSelector);

    function hideContainer(container) {
      container.classList.add("hide");
    }
    allContainers.forEach(hideContainer);
  }

  function showContainers(containerSelector) {
    const allContainers = document.querySelectorAll(containerSelector);

    function showContainer(container) {
      container.classList.remove("hide");
    }
    allContainers.forEach(showContainer);
  }
  
  function resetBackground(backgroundSelector) {
    const allBackgrounds = document.querySelectorAll(backgroundSelector);

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

  function animationEndHandler(evt) {
    const animationName = evt.animationName;
    console.log(animationName);
    if (animationName === "initial-fade") {
      body.classList.remove("initial-fade");
      resetPage();
    }
  }

  function resetPage() {
    resetVideos(".embed-youtube");
    resetBackground("body");

  }

  function exitClickHandler(e) {
    if (e.target.classList.contains("exit")) {
      hideContainers(".container2, .container3");
      showContainers(".container1");
      resetPage();
      console.log('Page1');
    }
    if (e.target.classList.contains("exitPage2")) {
      hideContainers(".container1, .container3");
      showContainers(".container2");
      resetPage();
      console.log('Page2');
    }
    if (e.target.classList.contains("exitPage3")) {
      hideContainers(".container2, .container1");
      showContainers(".container3");
      resetPage();
      console.log('Page3');
    }
    window.scrollTo(0, 0);
    body.classList.add('initial-fade');
  }