Displaying two slideshows on the same page

I’m using this slideshow as an example, which works perfectly fine. There are shared classes between each slideshow which means that when one finishes only then can the next one begin, I need them to be able to work independently of each other, will classes need to be changed.

Here’s just one slideshow

var slideIndex = 1;
showSlides(slideIndex);

function plusSlides(n) {
  showSlides(slideIndex += n);
}

function currentSlide(n) {
  showSlides(slideIndex = n);
}

function showSlides(n) {
  var i;
  var slides = document.getElementsByClassName("mySlides");
  var dots = document.getElementsByClassName("dot");
  if (n > slides.length) {slideIndex = 1}    
  if (n < 1) {slideIndex = slides.length}
  for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";  
  }
  for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" active", "");
  }
  slides[slideIndex-1].style.display = "block";  
  dots[slideIndex-1].className += " active";
}
</script>
* {box-sizing: border-box}
body {font-family: Verdana, sans-serif; margin:0}

/* Slideshow container */
.slideshow-container {
  position: relative;
  background: #f1f1f1f1;
}

/* Slides */
.mySlides {
  display: none;
  padding: 80px;
  text-align: center;
}

/* Next & previous buttons */
.prev, .next {
  cursor: pointer;
  position: absolute;
  top: 50%;
  width: auto;
  margin-top: -30px;
  padding: 16px;
  color: #888;
  font-weight: bold;
  font-size: 20px;
  border-radius: 0 3px 3px 0;
  user-select: none;
}

/* Position the "next button" to the right */
.next {
  position: absolute;
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover, .next:hover {
  background-color: rgba(0,0,0,0.8);
  color: white;
}

/* The dot/bullet/indicator container */
.dot-container {
    text-align: center;
    padding: 20px;
    background: #ddd;
}

/* The dots/bullets/indicators */
.dot {
  cursor: pointer;
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

/* Add a background color to the active dot/circle */
.active, .dot:hover {
  background-color: #717171;
}

/* Add an italic font style to all quotes */
q {font-style: italic;}

/* Add a blue color to the author */
.author {color: cornflowerblue;}
<div class="slideshow-container">

<div class="mySlides">
  <q>I love you the more in that I believe you had liked me for my own sake and for nothing else</q>
  <p class="author">- John Keats</p>
</div>

<div class="mySlides">
  <q>But man is not made for defeat. A man can be destroyed but not defeated.</q>
  <p class="author">- Ernest Hemingway</p>
</div>

<div class="mySlides">
  <q>I have not failed. I've just found 10,000 ways that won't work.</q>
  <p class="author">- Thomas A. Edison</p>
</div>

<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>

</div>

<div class="dot-container">
  <span class="dot" onclick="currentSlide(1)"></span> 
  <span class="dot" onclick="currentSlide(2)"></span> 
  <span class="dot" onclick="currentSlide(3)"></span> 
</div>

The problem comes when I add a second, they don’t work independently of each other

var slideIndex = 1;
showSlides(slideIndex);

function plusSlides(n) {
  showSlides(slideIndex += n);
}

function currentSlide(n) {
  showSlides(slideIndex = n);
}

function showSlides(n) {
  var i;
  var slides = document.getElementsByClassName("mySlides");
  var dots = document.getElementsByClassName("dot");
  if (n > slides.length) {slideIndex = 1}    
  if (n < 1) {slideIndex = slides.length}
  for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";  
  }
  for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" active", "");
  }
  slides[slideIndex-1].style.display = "block";  
  dots[slideIndex-1].className += " active";
}
</script>
* {box-sizing: border-box}
body {font-family: Verdana, sans-serif; margin:0}

/* Slideshow container */
.slideshow-container {
  position: relative;
  background: #f1f1f1f1;
}

/* Slides */
.mySlides {
  display: none;
  padding: 80px;
  text-align: center;
}

/* Next & previous buttons */
.prev, .next {
  cursor: pointer;
  position: absolute;
  top: 50%;
  width: auto;
  margin-top: -30px;
  padding: 16px;
  color: #888;
  font-weight: bold;
  font-size: 20px;
  border-radius: 0 3px 3px 0;
  user-select: none;
}

/* Position the "next button" to the right */
.next {
  position: absolute;
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover, .next:hover {
  background-color: rgba(0,0,0,0.8);
  color: white;
}

/* The dot/bullet/indicator container */
.dot-container {
    text-align: center;
    padding: 20px;
    background: #ddd;
}

/* The dots/bullets/indicators */
.dot {
  cursor: pointer;
  height: 15px;
  width: 15px;
  margin: 0 2px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  transition: background-color 0.6s ease;
}

/* Add a background color to the active dot/circle */
.active, .dot:hover {
  background-color: #717171;
}

/* Add an italic font style to all quotes */
q {font-style: italic;}

/* Add a blue color to the author */
.author {color: cornflowerblue;}
<h1>Slideshow 1</h1>

<div class="slideshow-container">

<div class="mySlides">
  <q>I love you the more in that I believe you had liked me for my own sake and for nothing else</q>
  <p class="author">- John Keats</p>
</div>

<div class="mySlides">
  <q>But man is not made for defeat. A man can be destroyed but not defeated.</q>
  <p class="author">- Ernest Hemingway</p>
</div>

<div class="mySlides">
  <q>I have not failed. I've just found 10,000 ways that won't work.</q>
  <p class="author">- Thomas A. Edison</p>
</div>

<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>

</div>

<div class="dot-container">
  <span class="dot" onclick="currentSlide(1)"></span> 
  <span class="dot" onclick="currentSlide(2)"></span> 
  <span class="dot" onclick="currentSlide(3)"></span> 
</div>

<h1>Slideshow 2</h1>
<div class="slideshow-container">

<div class="mySlides">
  <q>I love you the more in that I believe you had liked me for my own sake and for nothing else</q>
  <p class="author">- John Keats</p>
</div>

<div class="mySlides">
  <q>But man is not made for defeat. A man can be destroyed but not defeated.</q>
  <p class="author">- Ernest Hemingway</p>
</div>

<div class="mySlides">
  <q>I have not failed. I've just found 10,000 ways that won't work.</q>
  <p class="author">- Thomas A. Edison</p>
</div>

<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>

</div>

<div class="dot-container">
  <span class="dot" onclick="currentSlide(1)"></span> 
  <span class="dot" onclick="currentSlide(2)"></span> 
  <span class="dot" onclick="currentSlide(3)"></span> 
</div>

I’d rather the script be able to do this than have to change every class name and duplicate every CSS class, how would this be addressed in Vanilla JS only. It loops through the first and then the second is looped through, how can these be treated independently?

Thanks in advance 🙂

1 thought on “Displaying two slideshows on the same page”

  1. I changed your code in the following ways:

    1. I changed slideIndex from a shared global variable to a local variable stored as a data- attribute on each .slide-container so they keep track of their own index.
    2. The showSlides function now takes an additional slideshow argument which tells it on which slideshow it should make changes to.
    3. The plusSlides and currentSlide functions determine which slideshow they are in by looking up the DOM tree.
    4. I moved dot-container inside slideshow-container so everything is within 1 DOM node.

    Updated working example:

    document.querySelectorAll('.slideshow-container').forEach(slideshow => {
      slideshow.dataset.slideIndex = 1;
      showSlides(slideshow, 1);
    });
    
    function plusSlides(e, n) {
      var slideshow = e.closest('.slideshow-container');
      var slideIndex = parseInt(slideshow.dataset.slideIndex, 10);
      slideIndex += n;
      slideshow.dataset.slideIndex = slideIndex;
      showSlides(slideshow, slideIndex);
    }
    
    function currentSlide(e, n) {
      var slideshow = e.closest('.slideshow-container');
      var slideIndex = parseInt(slideshow.dataset.slideIndex, 10);
      slideIndex = n;
      slideshow.dataset.slideIndex = slideIndex;
      showSlides(slideshow, slideIndex);
    }
    
    function showSlides(slideshow, n) {
      var i;
      var slideIndex = parseInt(slideshow.dataset.slideIndex, 10);
      var slides = slideshow.querySelectorAll(".mySlides");
      var dots = slideshow.querySelectorAll(".dot");
      if (n > slides.length) {slideIndex = 1}    
      if (n < 1) {slideIndex = slides.length}
      for (i = 0; i < slides.length; i++) {
          slides[i].style.display = "none";  
      }
      for (i = 0; i < dots.length; i++) {
          dots[i].className = dots[i].className.replace(" active", "");
      }
      slides[slideIndex-1].style.display = "block";  
      dots[slideIndex-1].className += " active";
      slideshow.dataset.slideIndex = slideIndex;
    }
    </script>
    * {box-sizing: border-box}
    body {font-family: Verdana, sans-serif; margin:0}
    
    /* Slideshow container */
    .slideshow-container {
      position: relative;
      background: #f1f1f1f1;
    }
    
    /* Slides */
    .mySlides {
      display: none;
      padding: 80px;
      text-align: center;
    }
    
    /* Next & previous buttons */
    .prev, .next {
      cursor: pointer;
      position: absolute;
      top: 50%;
      width: auto;
      margin-top: -30px;
      padding: 16px;
      color: #888;
      font-weight: bold;
      font-size: 20px;
      border-radius: 0 3px 3px 0;
      user-select: none;
    }
    
    /* Position the "next button" to the right */
    .next {
      position: absolute;
      right: 0;
      border-radius: 3px 0 0 3px;
    }
    
    /* On hover, add a black background color with a little bit see-through */
    .prev:hover, .next:hover {
      background-color: rgba(0,0,0,0.8);
      color: white;
    }
    
    /* The dot/bullet/indicator container */
    .dot-container {
        text-align: center;
        padding: 20px;
        background: #ddd;
    }
    
    /* The dots/bullets/indicators */
    .dot {
      cursor: pointer;
      height: 15px;
      width: 15px;
      margin: 0 2px;
      background-color: #bbb;
      border-radius: 50%;
      display: inline-block;
      transition: background-color 0.6s ease;
    }
    
    /* Add a background color to the active dot/circle */
    .active, .dot:hover {
      background-color: #717171;
    }
    
    /* Add an italic font style to all quotes */
    q {font-style: italic;}
    
    /* Add a blue color to the author */
    .author {color: cornflowerblue;}
    <h1>Slideshow 1</h1>
    
    <div class="slideshow-container">
    
    <div class="mySlides">
      <q>I love you the more in that I believe you had liked me for my own sake and for nothing else</q>
      <p class="author">- John Keats</p>
    </div>
    
    <div class="mySlides">
      <q>But man is not made for defeat. A man can be destroyed but not defeated.</q>
      <p class="author">- Ernest Hemingway</p>
    </div>
    
    <div class="mySlides">
      <q>I have not failed. I've just found 10,000 ways that won't work.</q>
      <p class="author">- Thomas A. Edison</p>
    </div>
    
    <a class="prev" onclick="plusSlides(this, -1)">❮</a>
    <a class="next" onclick="plusSlides(this, 1)">❯</a>
    
    <div class="dot-container">
      <span class="dot" onclick="currentSlide(this, 1)"></span> 
      <span class="dot" onclick="currentSlide(this, 2)"></span> 
      <span class="dot" onclick="currentSlide(this, 3)"></span> 
    </div>
    
    </div>
    
    
    
    <h1>Slideshow 2</h1>
    <div class="slideshow-container">
    
    <div class="mySlides">
      <q>I love you the more in that I believe you had liked me for my own sake and for nothing else</q>
      <p class="author">- John Keats</p>
    </div>
    
    <div class="mySlides">
      <q>But man is not made for defeat. A man can be destroyed but not defeated.</q>
      <p class="author">- Ernest Hemingway</p>
    </div>
    
    <div class="mySlides">
      <q>I have not failed. I've just found 10,000 ways that won't work.</q>
      <p class="author">- Thomas A. Edison</p>
    </div>
    
    <a class="prev" onclick="plusSlides(this, -1)">❮</a>
    <a class="next" onclick="plusSlides(this, 1)">❯</a>
    
    <div class="dot-container">
      <span class="dot" onclick="currentSlide(this, 1)"></span> 
      <span class="dot" onclick="currentSlide(this, 2)"></span> 
      <span class="dot" onclick="currentSlide(this, 3)"></span> 
    </div>
    
    </div>

    There are of course better ways of doing this, you should look into modern frontend frameworks like React and Vue.

    Reply

Leave a Comment