Search code examples
javascriptsliderqueryselector

Need replace querySelector to querySelectorAll in slider


> sorry for my english)

In a nutshell: need replace querySelector with querySelectorAll and keep the functionality in slider (const sliderItems)

Hi all, I have a slider and it seems to work fine, but only if I use querySelector. For further manipulation - I need to select all elements, (querySelectorAll). It seemed to be no big deal, but the slider stops working when I use querySelectorAll. I'm asking for help, because I have no idea how to fix it, without loss of functionality :)

JavaScript:

const slider = document.querySelectorAll('.slider'),
      sliderItems = document.querySelector('.slider__items'), 
      prev = document.querySelectorAll('.prev'),
      next = document.querySelectorAll('.next');

function slide(wrapper, items, prev, next) {
  let posInitial,
      slides = items.querySelectorAll('.slider__items *'),
      slidesLength = slides.length,
      slideSize = items.querySelectorAll('.slider__items *')[0].offsetWidth,
      firstSlide = slides[0],
      lastSlide = slides[slidesLength - 1],
      cloneFirst = firstSlide.cloneNode(true),
      cloneLast = lastSlide.cloneNode(true),
      index = 0,
      allowShift = true;

  //Set offset to first slide
  const slideWidth =  window.getComputedStyle(firstSlide);
        console.log(slideWidth.width);
        items.style.left = `-${slideWidth.width}`;
  
  // Clone first and last slide
  items.appendChild(cloneFirst);
  items.insertBefore(cloneLast, firstSlide);
  wrapper.forEach(item => {
    item.classList.add('loaded');
  });

  // Click events
  prev.forEach(item => {
    item.addEventListener('click', function () { shiftSlide(-1) });
  })
  next.forEach(item => {
    item.addEventListener('click', function () { shiftSlide(1) });
  })

  // Transition events
  items.addEventListener('transitionend', checkIndex);

  function shiftSlide(dir, action) {
    items.classList.add('shifting');
    
    if (allowShift) {
      if (!action) { posInitial = items.offsetLeft; }

      if (dir == 1) {
        items.style.left = (posInitial - slideSize) + "px";
        index++;     
      } else if (dir == -1) {
        items.style.left = (posInitial + slideSize) + "px";
        index--;  
      }
    };
    
    allowShift = false;
  }
    
  function checkIndex (){
    items.classList.remove('shifting');

    if (index == -1) {
      items.style.left = -(slidesLength * slideSize) + "px";
      index = slidesLength - 1;
    }

    if (index == slidesLength) {
      items.style.left = -(1 * slideSize) + "px";
      index = 0;
    }
    allowShift = true;
  }
}

slide(slider, sliderItems, prev, next);

HTML:

<div class="slider">
  <div class="slider__wrapper">
    <div class="slider__items">
      <span class="slider__slide">Slide 1</span>
      <span class="slider__slide">Slide 2</span>
      <span class="slider__slide">Slide 3</span>
      <span class="slider__slide">Slide 4</span>
      <span class="slider__slide">Slide 5</span>
      <span class="vertical slider__slide vertical">Slide 6</span>
    </div>
  </div>
  
  <a id="prev" class="control prev"></a>
  <a id="next" class="control next"></a>
</div>

CSS:

.slider {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
}

.slider__wrapper {
  position: relative;
  width: 600px;
  height: 400px;
  overflow: hidden;
  z-index: 1;
}

.slider__items {
  display: flex;
  position: absolute;
}

.slider__items.shifting {
  transition: left 0.2s ease-out;
}

.slider__slide {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 600px;
  height: 400px;
  cursor: pointer;
  transition: all 1s;
  background: #FFCF47;
  border-radius: 2px;
}

.slider.loaded .slider__slide:nth-child(2),
.slider.loaded .slider__slide:nth-child(7) {
  background: #FFCF47;
}
.slider.loaded .slider__slide:nth-child(1),
.slider.loaded .slider__slide:nth-child(6) {
  background: #7ADCEF;
}
.slider.loaded .slider__slide:nth-child(3) {
  background: #3CFF96;
}
.slider.loaded .slider__slide:nth-child(4) {
  background: #a78df5;
}
.slider.loaded .slider__slide:nth-child(5) {
  background: #ff8686;
}

.control {
  position: absolute;
  top: 50%;
  width: 50px;
  height: 50px;
  background: #fff;
  border-radius: 50px;
  margin-top: -20px;
  box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.3);
  z-index: 2;
}

.prev,
.next {
  background-size: 22px;
  background-position: center;
  background-repeat: no-repeat;
  cursor: pointer;
}

.prev {
  background-image: url(https://cdn0.iconfinder.com/data/icons/navigation-set-arrows-part-one/32/ChevronLeft-512.png);
  left: -20px;
}

.next {
  background-image: url(https://cdn0.iconfinder.com/data/icons/navigation-set-arrows-part-one/32/ChevronRight-512.png);
  right: -20px;
}

.prev:active,
.next:active {
  transform: scale(0.8);
}

I tried to replace querySelector with querySelectorAll myself, but then I got a bunch of errors and the script didn't work :)


Solution

  • Why do you need to use querySelectorAll()?

    <div class="slider__items"> There are only one of these elements in your code, so querySelector() seems appropriate.

    If you want to use querySelectorAll, remember that it returns a NodeList. (Like an array)

    Change your last line like this to access the first(and only) element of the array.

    slide(slider, sliderItems[0], prev, next);