Sloan
Sloan

Reputation: 11

How do I create a carousel of select images inside multiple modals?

I'm trying to create carousels of images for each modal that displays only the images relevant to that modal. The goal is to have three images to cycle through with next and previous buttons for each project modal that exists on the page. I'm using vanilla JS and can't figure it out. Please help!

Here is the relevant html for the first modal:

<div class="modal-container" id="weather">
  <div class="modal">
    <div class="modal-column-left">
      <div class="modal-image-container">
        <div class="modal-image-box weather-slides">
          <div class="slide">
            <img
              class="slide-img"
              src="./images/compressed/WeatherPro-screenshot-1-c.png"
              alt="WeatherPro App 1"
            />
          </div>
          <div class="slide">
            <img
              class="slide-img"
              src="./images/compressed/WeatherPro-screenshot-2-c.png"
              alt="WeatherPro App 2"
            />
          </div>
          <div class="slide">
            <img
              class="slide-img"
              src="./images/compressed/WeatherPro-screenshot-3-c.png"
              alt="WeatherPro App 3"
            />
          </div>
        </div>
        <div class="modal-image-nav">
          <button type="button" class="prevBtn">
            <i
              class="fa fa-arrow-circle-left"
              aria-hidden="true"
            ></i>
          </button>
          <button type="button" class="nextBtn">
            <i
              class="fa fa-arrow-circle-right"
              aria-hidden="true"
            ></i>
          </button>
        </div>
      </div>
    </div>
    
<!-- modal column right info... -->

    <button class="close-button close">
      <i class="fas fa-window-close"></i>
    </button>
  </div>
</div>

The other modals are the same other than the id of the modal div.

And here is the javascript code for the modals:

// Project Section Modals
function showModal(id) {
  let m = document.getElementById(id);
  m.classList.add('visible');
}

function hideModals() {
  modals.forEach(m => {
    m.classList.remove('visible');
  });
}

buttons.forEach(b => {
  b.addEventListener('click', event => {
    hideModals();
    showModal(b.dataset.modal);
    showSlides(b.dataset.modal);
  });
});

modals.forEach(m => {
  let x = m.querySelector('button.close');
  x.addEventListener('click', hideModals);
});


// // --------------------My attempt----------------------:
let slideShow = slides;
console.log(slideShow);

// Modal slider (for screenshots)
function showSlides(id) {
  let m = document.getElementById(id);
  console.log(m);
  m.classList.add('currentModal');
  slideShow = document.querySelector('.currentModal').getElementsByClassName("slide");
  console.log(slideShow.length);
  console.log(slideShow);
  return slideShow;
  

}

slideShow.forEach(function(slide, index){
 slide.style.left = `${index * 100}%`; // translate slide 100% left
});

let counter = 0;
nextBtn.addEventListener('click', function(){
 counter++;
 carousel();
});

prevBtn.addEventListener('click', function(){
 counter--;
  carousel();
});

// Here's the problem...
// maybe make a promise to render this after opening modal?...
function carousel(){

 // working with slideShow
 if(counter === slideShow.length){
  counter=0;
 }
 if(counter < 0){
  counter = slideShow.length - 1;
 }

 // working with slider buttons
 slides.forEach(function(slide){
  slide.style.transform = `translateX(-${counter * 100}%)`
 });
}

Upvotes: 1

Views: 498

Answers (1)

Sloan
Sloan

Reputation: 11

I got it! The key was to select all the buttons and use the forEach method on both the prev and next buttons to wrap the click event listeners!

So, broken down into steps:

  1. Use querySelectorAll to work with the two buttons in each of the modals:
const nextBtn = document.querySelectorAll('.nextBtn');
const prevBtn = document.querySelectorAll('.prevBtn');
  1. Adjust the functions that show and hide the modals slightly:
function showModal(id) {
  let m = document.getElementById(id);
  m.classList.add('visible');
  slideShow = document.querySelector('.visible').getElementsByClassName("slide");
  slidesArray = [...slideShow];
}

function hideModals() {
  modals.forEach(m => {
    m.classList.remove('visible');
    slidesArray = [];
    counter = 0;
  });
}
  1. Wrap the button event listeners in forEach methods:
let counter = 0;
nextBtn.forEach(button => {
  button.addEventListener('click', event => {
   counter++;
  carousel();
})
});

prevBtn.forEach(button => {
button.addEventListener('click', function(){
  counter--;
  carousel();
})
});
  1. Tidy up the carousel function to reset the positions each time a modal is opened:
function carousel(){
  slidesArray.forEach(function(slide, index){
  slide.style.left = `${index * 100}%`; // translate slide 100% left
});

 // working with slideShow
 if(counter === slidesArray.length){
  counter=0;
 }
 if(counter < 0){
  counter = slidesArray.length - 1;
 }

 // working with slider buttons
 slidesArray.forEach(function(slide){
  slide.style.transform = `translateX(-${counter * 100}%)`
 });
}

I'm sure this can be cleaned up and optimized better. If you see ways to do this better please let me know!

Upvotes: 0

Related Questions