Having trouble with dots on multiple slideshow


#1

This code - Having Trouble With Multiple Slideshows On One Page

having trouble with dots on multiple slideshows.
How to add proper working dots in this code.


#4

Hi @aswani, one possibility would be to set a data attribute on each dot to the index or selector of the corresponding slide… however I’d probably rather create the dots with JS from the first, so you don’t have to maintain the slide / dot relations in the markup. This way you have a direct mapping to the slides which you can then toggle like so:

.slide {
  display: none;
}

.slide--active {
  display: block;
}
<div class="slideshow-container">
  <div class="mySlides1 fade slide">
    <!--Image here-->
    <div class="image img1">Image 1-1</div>
  </div>
  <div class="mySlides1 fade slide">
    <!--Image here-->
    <div class="image img2">Image 1-2</div>
  </div>
  <div class="mySlides1 fade slide">
    <!--Image here-->
    <div class="image img3">Image 1-3</div>
  </div>
  <a class="prev" >&#10094;</a> <a class="next" >&#10095;</a>
  <div class="dots"></div>
</div>
<etc>
const ACTIVE_CLASS = 'slide--active'
const containers = document.querySelectorAll('.slideshow-container')

containers.forEach(container => {
  const slides = container.querySelectorAll('.slide')
  const dots = container.querySelector('.dots')
  const prev = container.querySelector('.prev')
  const next = container.querySelector('.next')

  let current = 0

  const switchSlide = position => {
    const { length } = slides
    const absolutePosition = (position + length) % length

    slides[current].classList.remove(ACTIVE_CLASS)
    slides[absolutePosition].classList.add(ACTIVE_CLASS)
    current = absolutePosition
  }

  // Map the slides to dots so we can switch the slides by their indices
  Array.from(slides, (_, index) => {
    const dot = document.createElement('span')

    dot.classList.add('dot')
    dot.addEventListener('click', () => switchSlide(index))
    dots.appendChild(dot)
  })

  slides[current].classList.add(ACTIVE_CLASS)
  prev.addEventListener('click', () => switchSlide(current - 1))
  next.addEventListener('click', () => switchSlide(current + 1))
})

It might then be a good idea to extract that functionality to a dedicated component for better code organization (thus making your code more reusable and easier to test) – like e.g.

// slideshow-component.js
const ACTIVE_CLASS = 'slide--active'

export class SlideshowComponent {
  constructor (container) {
    this.slides = container.querySelectorAll('.slide')
    this.dots = container.querySelector('.dots')
    this.prev = container.querySelector('.prev')
    this.next = container.querySelector('.next')
    this.current = 0
  }

  switchSlide (position) {
    const { length } = this.slides
    const absolutePosition = (position + length) % length

    this.slides[this.current].classList.remove(ACTIVE_CLASS)
    this.slides[absolutePosition].classList.add(ACTIVE_CLASS)
    this.current = absolutePosition
  }

  createDot (index) {
    const dot = document.createElement('span')

    dot.classList.add('dot')
    dot.addEventListener('click', () => this.switchSlide(index))
    this.dots.appendChild(dot)
  }

  init () {
    const { slides, prev, next, current } = this

    slides.forEach((_, index) => this.createDot(index))
    slides[current].classList.add(ACTIVE_CLASS)
    prev.addEventListener('click', () => this.switchSlide(this.current - 1))
    next.addEventListener('click', () => this.switchSlide(this.current + 1))

    return this
  }
}
// And somewhere else...
import { SlideshowComponent } from './slideshow-component'

const containers = document.querySelectorAll('.slideshow-container')
const slideshows = Array.from(containers, container => new SlideshowComponent(container).init())
// ...

#5

Thank you @m3g4p0p :blush:


closed #6

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.