Search code examples
javascripthtmlcssslidercarousel

Javascript slider not work automatically?


I created a simple javascript slider where both controls can work perfectly and also bottom dots can work efficiently but automatically slide functionality do not work. I tried for loop, set timeout method, set interval method but cannot solve this issue.

Here is my code:

const track = document.querySelector(".slideTrack");
const slides = Array.from(track.children);

const prevBtn = document.querySelector(".slideBtnLeft");
const nextBtn = document.querySelector(".slideBtnRight");

const slideNav = document.querySelector(".slideNav");
const navDots = Array.from(slideNav.children);

// Calculate the size of each slide
const slideWidth = slides[0].getBoundingClientRect().width;
// console.log(slideWidth);

// Arrange the slides next to one another
const setSlidePosition = (slide, index) => {
    slide.style.left = slideWidth * index + 'px';
}
slides.forEach(setSlidePosition);

// When I click next button, slide move to the right
const moveToSlide = (track, currentSlide, targetSlide) => {
    track.style.transform = 'translateX(-'+ targetSlide.style.left +')';
    currentSlide.classList.remove("currentSlide");
    targetSlide.classList.add("currentSlide");
}


nextBtn.addEventListener('click', e => {
    // Check current slide and next slide
    const currentSlide = track.querySelector('.currentSlide');
    const nextSlide = currentSlide.nextElementSibling;
    const currentDot = slideNav.querySelector('.currentSlide');
    const nextDot = currentDot.nextElementSibling;
    const nextIndex = slides.findIndex(slide => slide === nextSlide);
    // Move that slide
    moveToSlide(track, currentSlide, nextSlide);
    updateDots(currentDot, nextDot);
    hideShowArrows(slides, prevBtn, nextBtn, nextIndex);
});

// When I click previous button, slide move to the left
prevBtn.addEventListener('click', e => {
    // Check current slide and prvious slide
    const currentSlide = track.querySelector('.currentSlide');
    const prevSlide = currentSlide.previousElementSibling;
    const currentDot = slideNav.querySelector('.currentSlide');
    const prevDot = currentDot.previousElementSibling;
    const prevIndex = slides.findIndex(slide => slide === prevSlide);
    // Move that slide
    moveToSlide(track, currentSlide, prevSlide);
    updateDots(currentDot, prevDot);
    hideShowArrows(slides, prevBtn, nextBtn, prevIndex);
});

const updateDots = (currentDot, targetDot) => {
    currentDot.classList.remove('currentSlide');
    targetDot.classList.add('currentSlide');
}
const hideShowArrows = (slides, prevBtn, nextBtn, targetIndex) => {
    if(targetIndex === 0) {
        prevBtn.classList.add("hidenBtn");
        nextBtn.classList.remove("hidenBtn");
    } else if(targetIndex === slides.length - 1) {
        prevBtn.classList.remove("hidenBtn");
        nextBtn.classList.add("hidenBtn");
    } else {
        prevBtn.classList.remove("hidenBtn");
        nextBtn.classList.remove("hidenBtn");
    }
}

// When I click Slide Nav Dots, slide move to that slide
slideNav.addEventListener('click', e => {
    // What slide dot clicked on
    const targetDot = e.target.closest('span');
    
    if(!targetDot) return;

    const currentSlide = track.querySelector('.currentSlide');
    const currentDot = slideNav.querySelector('.currentSlide');
    const targetIndex = navDots.findIndex(dot => dot === targetDot)
    const targetSlide = slides[targetIndex];

    moveToSlide(track, currentSlide, targetSlide);
    updateDots(currentDot, targetDot);
    hideShowArrows(slides, prevBtn, nextBtn, targetIndex);
});
.slider {
    position: relative;
    width: 82%;
    height: 500px;
    padding: 15px 15px 0 15px;
}
.slider .slideContainer {
    position: relative;
    height: 92%;
    overflow: hidden;
}
.slider .slideContainer .slideTrack {
    margin: 0;
    padding: 0;
    list-style: none;
    position: relative;
    height: 100%;
    transition: transform 1s ease-in;
}
.slider .slideContainer .slideTrack .slideImage {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    border: 1px solid #dddddd;
    border-radius: 10px 10px 0 0;
    border-bottom: 0;
}
.slider .slideContainer .slideTrack .slideImage img { border-radius: 10px 10px 0 0; }

.slider .slideBtn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 38px;
    height: 38px;
    padding: 8px;
    border: 1px solid #dddddd;
    border-radius: 100%;
    background-color: #ffffff;
    box-shadow: 0 1px 4px 1px rgba(0,0,0,0.1);
    transition: 0.2s ease-in-out;
    cursor: pointer;
    z-index: 1;
}
.slider .slideBtn:hover { background-color: #f0f2f5; }

.slider .slideBtn:active { background-color: #e4e6e9; }

.slider .slideBtnLeft { left: 30px; }

.slider .slideBtnRight { right: 30px; }

.slider .hidenBtn { display: none; }

.slider .slideNav {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px 0;
    border: 1px solid #dddddd;
    border-radius: 0 0 10px 10px;
    background-color: #f0f2f5;
}
.slider .slideNav .slideIndicator {
    width: 15px;
    height: 15px;
    margin-right: 10px;
    border: 2px solid #007d2f;
    border-radius: 100%;
    transition: 0.2s ease-in-out;
    cursor: pointer;
}
.slider .slideNav .slideIndicator.currentSlide { background-color: #007d2f; }
<div class="slider">
                <div class="slideBtn slideBtnLeft hidenBtn">
                    <svg viewBox="0 0 24 24">
                        <path d="M8 4l8 8l-8 8" transform="translate(24 0) scale(-1 1)" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>
                </div>
                <div class="slideContainer">
                    <ul class="slideTrack">
                        <li class="slideImage currentSlide">
                            <img src="./images/slider/1.jpg" alt="">
                        </li>
                        <li class="slideImage">
                            <img src="./images/slider/2.jpg" alt="">
                        </li>
                        <li class="slideImage">
                            <img src="./images/slider/3.jpg" alt="">
                        </li>
                    </ul>
                </div>
                <div class="slideBtn slideBtnRight">
                    <svg viewBox="0 0 24 24">
                        <path d="M8 4l8 8l-8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
                    </svg>
                </div>

                <div class="slideNav">
                    <span class="slideIndicator currentSlide"></span>
                    <span class="slideIndicator"></span>
                    <span class="slideIndicator"></span>
                </div>
            </div>


Solution

  • I would not suggest the way you use since it is too messy, so I rebuild your code by using for loop and array.

    *I doesn't apply your Css code, but I think it is easy to apply.

    The code:

    let arr = ['https://blogs.stthomas.edu/english/files/2016/04/Wikipedia-Logo.jpg','https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSvyhm32s-UFL5RT94ozSkQdLrjWiVGd4sogw&usqp=CAU',"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKJMsaA28A32PrOKnj_PqUF1PezvB1bAygtQ&usqp=CAU"];
    let img = document.querySelector('img')
    let index = 0;
    let interval;
    document.querySelector('#previous').addEventListener('click',function(){
          window.clearInterval(interval)
    index-=1;
        if(index<0){
            index = arr.length-1
        }
        img.src = arr[index]
         interval = setInterval(start,3000);
    })
    document.querySelector('#next').addEventListener('click',function(){
          window.clearInterval(interval)
          console.log(index)
                index+=1;
          if(index >= arr.length){
            index=0
        }
        img.src = arr[index]
             interval = setInterval(start,3000);
    })
    for(let i =0;i<arr.length;i++){
        let button = document.createElement('button')
        document.body.appendChild(button)
        button.id = `button${i}`
        button.addEventListener('click',changeimage)
    
    }
    function start(){
        img.src = arr[index]
    
        index++;
        if(index<0){
            index = arr.length-1
        }
        if(index >= arr.length){
            index=0
        }
    }
    interval = setInterval(start,3000);
    
    function changeimage(){
             window.clearInterval(interval)
        //get the index of which button being clicked
         let id = this.id.replace(/\D/g,'')
         img.src =arr[id]
         i=parseInt(id)
         interval = setInterval(start,3000);
    }
    img{
        width: 200px;
        height: 100px;
    }
    <img src="https://blogs.stthomas.edu/english/files/2016/04/Wikipedia-Logo.jpg">
                    <button id='previous'>&#10094;</button>
                   <button id='next'>&#10095;</button>