Home > front end >  Image slider/carousel - controls are out of sync
Image slider/carousel - controls are out of sync

Time:02-10

I'm trying to develop a 'image carousel slider' for web design, one that can be controlled by

  1. arrow buttons
  2. dot/radio buttons on the bottom (and are in sync with the slider)
  3. automatic slider if none of the above are used

https://jsfiddle.net/19d6vftn/1/

const slideContainer = document.querySelector('.img-container');
const slide = document.querySelector('.slides');
const slidesDot = document.querySelectorAll('.slides_radio');
const nextBtn = document.getElementById('next-btn');
const prevBtn = document.getElementById('prev-btn');
const dotsNav = document.querySelector('.slides_nav');
const dots = Array.from(dotsNav.children);
const interval = 5000;



let slides = document.querySelectorAll('.slide');
let index = 1;
let slideId;

console.log(slidesDot);
console.log(dotsNav);

const firstClone = slides[0].cloneNode(true);
const lastClone = slides[slides.length - 1].cloneNode(true);

firstClone.id = 'first-clone';
lastClone.id = 'last-clone';

slide.append(firstClone);
slide.prepend(lastClone);

const removeFirst = () => {
  document.getElementById('first-clone').classList.remove('current_slide');
}

removeFirst();

const slideWidth = '100';

slide.style.transform = `translateX(${-slideWidth * index}%)`;

const startSlide = () => {
  slideId = setInterval(() => {
    moveToNextSlide();
  }, interval);
};

const getSlides = () => document.querySelectorAll('.slide');

slide.addEventListener('transitionend', () => {
  slides = getSlides();
  if (slides[index].id === firstClone.id) {
    slide.style.transition = 'none';
    index = slides.length - 5;
    slide.style.transform = `translateX(${-slideWidth * index}%)`;
  } if (slides[index].id === lastClone.id) {
    slide.style.transition = 'none';
    index = slides.length - 2;
    slide.style.transform = `translateX(${-slideWidth * index}%)`;
  }
  console.log(getSlides);
});

const moveToNextSlide = () => {
  slides = getSlides();
  if (index >= slides.length - 1) return;
  index  ;
  slide.style.transform = `translateX(${-slideWidth * index}%)`;
  slide.style.transition = '.7s ease-out';
  let currentSlide = slides[index];
  let prevSlide = currentSlide.previousElementSibling;
  if (slides[index].id === 'first-clone') {
    currentSlide = document.getElementById('1');
  }
  if (prevSlide.id === 'first-clone') {
    prevSlide.classList.remove('current_slide');
  }
  currentSlide.classList.add('current_slide');
  prevSlide.classList.remove('current_slide');

  /* teste */
  let currentDot = dotsNav.querySelector('.current_slide');
  let nextDot = currentDot.nextElementSibling;
  // console.log(currentSlide);
  // console.log(currentDot);
  if (currentSlide.id === '1') {
    nextDot = document.getElementById('radio1');
  }
  if (currentDot.id === 'radio4') {
    nextDot = document.getElementById('radio1');
  }
  // console.log(nextDot);
  updateDotsArrowN(currentDot, nextDot);

  // console.log(currentSlide.id);
}
const updateDotsArrowN = (currentDot, nextDot) => {
  currentDot.classList.remove('current_slide');
  nextDot.classList.add('current_slide');


}

const updateDotsArrowP = (currentDot, prevDot) => {
  currentDot.classList.remove('current_slide');
  prevDot.classList.add('current_slide');

}

const updateDots = (currentDot, targetDot) => {
  currentDot.classList.remove('current_slide');
  targetDot.classList.add('current_slide');
}

const slidesNumber = slides.length - 2;

const moveToPreviousSlide = () => {

  if (index <= 0) return;
  index--;
  slide.style.transform = `translateX(${-slideWidth * index}%)`;
  slide.style.transition = '.7s ease-out';
  let currentSlide = slides[index];
  let nextSlide = currentSlide.nextElementSibling;
  if (slides[index].id === 'last-clone') {
    currentSlide = document.getElementById('4');
  }
  if (nextSlide.id === 'last-clone') {
    nextSlide.classList.remove('current_slide');
  }
  currentSlide.classList.add('current_slide');
  nextSlide.classList.remove('current_slide');

  /* teste */
  let currentDot = dotsNav.querySelector('.current_slide');
  let prevDot = currentDot.previousElementSibling;
  console.log(currentSlide);
  console.log(currentDot);
  if (currentSlide.id === '4') {
    prevDot = document.getElementById('radio4');
  }
  if (currentDot.previousElementSibling === null) {
    prevDot = document.getElementById('radio4');

  }
  console.log(prevDot);
  updateDotsArrowP(currentDot, prevDot);
  console.log(currentSlide.id);
}

slideContainer.addEventListener('mouseenter', () => {
  clearInterval(slideId);
});

nextBtn.addEventListener('mouseenter', () => {
  clearInterval(slideId);
});

prevBtn.addEventListener('mouseenter', () => {
  clearInterval(slideId);
});

slideContainer.addEventListener('mouseleave', startSlide);

nextBtn.addEventListener('click', moveToNextSlide);

prevBtn.addEventListener('click', moveToPreviousSlide);


startSlide();


dotsNav.addEventListener('click', e => {
  const targetDot = e.target.closest('button');
  console.log(targetDot);


  if (!targetDot) return;
  let currentSlide = slide.querySelector('.current_slide');
  const currentDot = dotsNav.querySelector('.current_slide');
  console.log(currentDot);
  // const nextSlide = currentSlide.previousElementSibling;
  const targetIndex = (dots.findIndex(dot => dot === targetDot)   1);
  let targetSlide = slides[targetIndex];
  if (slides.length <= 4) {
    targetSlide = slides[targetIndex - 1];
    currentSlide = document.getElementById('4');
  }


  console.log(targetSlide);

  const targetSlideId = parseInt(targetSlide.id);
  const currentSlideId = parseInt(currentSlide.id);
  const diff = targetSlideId;



  // targetDot.classList.add('current_slide');
  /* console.log(targetIndex);
  console.log(targetSlide); */
  console.log(targetSlideId);
  console.log(currentSlideId);
  /* console.log(currentSlideId); 
  console.log(diff); */

  if (index >= slides.length - 1) return;
  const clickOnDot = (currentSlideId, targetSlideId) => {
    let nova = `translateX(${- (diff) * 100}%)`
    currentSlide.classList.add('current_slide');
    console.log(nova);
    slide.style.transform = nova;
    slide.style.transition = '.7s ease-out';
  }
  clickOnDot();

  if (slides[index].id === 'last-clone') {
    currentSlide = document.getElementById('4');
  }
  if (targetSlide.id === 'last-clone', 'first-clone') {
    targetSlide.classList.remove('current_slide');
  }
  if (slides[index].id === 'first-clone') {
    currentSlide = document.getElementById('1');
  }




  currentSlide.classList.remove('current_slide');
  targetSlide.classList.add('current_slide');



  updateDots(currentDot, targetDot);


})

As I'm new to javascript, I initially used some templates on YouTube and tried to use my knowledge to reach my goals. Due to those reasons, the .js code might be a bit dirty/messy. I had many problems that showed up, most of them I found a way to solve.

But there's still a bug that I didn't find a solution for, which happens whenever I click on the dot buttons and use the arrow buttons or let the automatic navigation flow. My guess would be something about the index of the Node list, which seems to be a bit off when it comes to the dot controls.

If you only use dots navigation or arrows automatic, everything works fine. If you try to use dots first and arrows/automatic after, the "next" slider goes to 2 pics before the current, and then 1 picture, and then it doesn't move, so it seems there's something wrong on the sequence.

For this carousel, the code I'm based on creates a clone for the first and the last pictures, so Node list starts with 4 elements and then they become 6 for it to flow.

I know this might be a messy way to work on it, but would anyone guess how to manage this de-sync between the different controls without having to rewrite most of the code?

Thanks

CodePudding user response:

  •  Tags:  
  • Related