Search code examples
javascriptscopeslidersettimeoutcleartimeout

Multiple javascript image carousels - independent controls and automatic movement


I have attempted to find an answer to my question here on Stack Overflow but have been unsuccessful in finding one.

As part of my JavaScript learning I am trying to create my own carousel slider. The problem is I am trying to allow for X number of sliders on the same page, each with their own automatic timers and controls. This is proving to be an issue when I try to control either one of them. For instance if I manually control one of them, the other one then stops playing as the paused variable is set to true.

I'm pretty sure that my issue is either the scope of the variables or not being more specific with targeting the slider elements (e). I may have been looking at this too long and have somewhat lost perspective on it. I would appreciate any advice with this or even just a nudge in the right direction.

Thanks.

HTML

<div id="slider-1" class="slider-wrap">
    <div class="slider ">
        <div class="slide-wrap" data-slide="0">
            <div class="slider-slide" style="background-image: url(image1.png)">
                <div class="slide-text text-background">
                    <a href="#">Slide 1</a>
                </div>
            </div>
        </div>
        <div class="slide-wrap" data-slide="1">
            <div class="slider-slide" style="background-image: url(image2.png)">
                <div class="slide-text text-background">
                    <a href="#">Slide 2</a>
                </div>
            </div>
        </div>
        <div class="slide-wrap current-slide" data-slide="2">
            <div class="slider-slide" style="background-image: url(image3.png)">
                <div class="slide-text text-background">
                    <a href="#">Slide 3</a>
                </div>
            </div>
        </div>
    </div>
</div>

Javascript

// Setup variables
let helpers = require('./helpers.js')
let sliders = document.getElementsByClassName('slider-wrap')
let paused = false

//Get all sliders on page and start slider function
for (var i = 0; i < sliders.length; i++) {
  let slideIndex = 0
  let e = sliders[i]
  slider(e, slideIndex)
  autoChange(e, slideIndex)
}

// Slider function which adds indicator click listeners
function slider (e, slideIndex) {
  let element = e
  let interval
  let indicators = e.getElementsByClassName('slide-indicator')
  for (var i = 0; i < indicators.length; i++) {
    indicators[i].addEventListener('click', function (e) {
      let slideIndex = Number(e.target.dataset.slide)
      paused = true
      if (helpers.hasClass(e.target, 'current') === false) {
        clearTimeout(interval)
        sliderChange(element, slideIndex)
      }
    })
  }
}

// Change slider based on index and update classes
function sliderChange (e, slideIndex) {
  let slides = e.getElementsByClassName('slide-wrap')
  let indicators = e.getElementsByClassName('slide-indicator')
  let num = slides.length - 1
  let prev = e.querySelector('.current-slide')

  for (var i = 0; i < slides.length; i++) {
    slides[i].classList.remove('current-slide')
      indicators[i].classList.remove('current')
  }

  slides[slideIndex].classList.add('current-slide')
  indicators[slideIndex].classList.add('current-indicator')

  if (paused === false) {
      autoChange(e, slideIndex)
  }

}

// Automatically change slide
function autoChange (e, slideIndex) {
  let slides = e.getElementsByClassName('slide-wrap')
  let num = slides.length - 1
  if (slideIndex === num) {
    slideIndex = 0
  } else {
    slideIndex++
  }
  interval = setTimeout(function () {
    sliderChange(e, slideIndex)
  }, 3000)
}

Solution

  • Having paused as global variable is an issue at least. I would recommend you to create a javascript object for each slider so that each slider would have their own "paused" property.

    let sliders = document.getElementsByClassName('slider-wrap')
    var sliderObjects = []
    for (i = 0; i < sliders.length; i++) {
        var slider = {slider: sliders[i], paused: false}
        sliderObjects[i] = slider
    }
    

    Here some useful reference on JavaScript Objects: https://www.w3schools.com/js/js_objects.asp