简体   繁体   中英

Text slider in JS doesn't slide properly

I'm trying to write my first text slider in JS, which seemed super easy at first, but it bevahes very stange.

When the 'previous' button is clicked it works fine but ommits the last <li> item, when the 'next' button is clicked all of the <li> s become an empty class="" and that's all, it's doesn't slide to the next item.

Here's my code:

 const slider = document.querySelector('.text-slider'); const sliderItems = slider.querySelectorAll('li'); const sliderNav = slider.querySelector('.slider-nav'); function changeSlide(e) { // if the next button is clicked the direction is true // if the prev button is clicked the direction is false const direction = e.target.classList.contains('nav-next') ? true : false; const itemsInTotal = sliderItems.length; for(let i = 0; i < itemsInTotal; i++) { // if the item is active if(sliderItems[i].classList.contains('active')) { //delete the active class sliderItems[i].classList.remove('active'); //if the NEXT button was clicked if(direction) { //if it's the last slide if(i === itemsInTotal-1) { sliderItems[0].classList.add('active'); } else { sliderItems[i+1].classList.add('active'); } // if the PREV button was clicked } else { //if it's the first element if(i === 0) { sliderItems[itemsInTotal-1].classList.add('active'); } else { sliderItems[i-1].classList.add('active'); } } } }; } sliderNav.addEventListener('click', changeSlide); 
 .hero { background-color: #252525; min-height: 100vh; position: relative; } .hero ul { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } .hero ul li { display: none; color: #fff; text-align: center; font-family: "Frank Ruhl Libre", serif; font-size: 2em; } .hero ul li span { color: #f5989d; text-transform: uppercase; font-family: "Josefin Sans", sans-serif; font-size: 1.3em; font-weight: 700; display: block; } .hero ul li.active { display: block; } .hero .slider-nav a { border:1px solid red; position: absolute; content: ' '; width: 30px; height: 30px; background: url("img/arrow-r.png"); background-size: contain; position: absolute; top: calc( 50% - 15px ); z-index: 10; } .hero .slider-nav a:hover { cursor: pointer; } .hero .slider-nav a.nav-prev { transform: rotate(180deg); left: 7%; } .hero .slider-nav a.nav-next { right: 7%; } 
  <section class="hero"> <div class="text-slider"> <div class="slider-nav"> <a class="slider-nav nav-prev"></a> <a class="slider-nav nav-next"></a> </div> <ul> <li class="active">I like take photos <span>in the woods</span></li> <li>I like observing <span>people and their emotions</span></li> <li>I always take <span>the best of life</span></li> <li>I always take <span>the best of life 2</span></li> <li>I always take <span>the best of life 3</span></li> </ul> </div> </section> 

I will appreciate any help.

In fact, you have a problem with your previous button too because the state "Best of life 3" is never displayed.

I propose you to use a while loop instead a for, because you change always all "li" instead of changing only the concerned 2 (old active and new active).

I think, this will work :

changeSlide(e: any) {
    // if the next button is clicked the direction is true
    // if the prev button is clicked the direction is false
    const direction = e.target.classList.contains('nav-next') ? true : false;

    const itemsInTotal = this.sliderItems.length;
    let isChangeDone = false;
    let i = 0;
    while(!isChangeDone && i < itemsInTotal) {

        // if the item is active
        if(this.sliderItems[i].classList.contains('active')) {

            //delete the active class
            this.sliderItems[i].classList.remove('active');

            //if the NEXT button was clicked
            if(direction) {
                //if it's the last slide
                if(i === itemsInTotal-1) {
                    this.sliderItems[0].classList.add('active');
                    isChangeDone = true;
                }
                else {
                    this.sliderItems[i+1].classList.add('active');
                    isChangeDone = true;
                }
                // if the PREV button was clicked
            } else {
                //if it's the first element
                if(i === 0) {
                    this.sliderItems[itemsInTotal-1].classList.add('active');
                    isChangeDone = true;
                } else {
                    this.sliderItems[i-1].classList.add('active');
                    isChangeDone = true;
                }
            }
        }
        i++;
    };
}

Let me know.

 const slider = document.querySelector('.text-slider'); const sliderItems = slider.querySelectorAll('li'); const sliderNav = slider.querySelector('.slider-nav'); let counter = 0; function changeSlide(e) { // if the next button is clicked the direction is true // if the prev button is clicked the direction is false const direction = e.target.classList.contains('nav-next') ? true : false; const itemsInTotal = sliderItems.length; for(let i = 0; i < itemsInTotal; i++) { // if the item is active if(sliderItems[i].classList.contains('active')) { //delete the active class sliderItems[i].classList.remove('active'); //if the NEXT button was clicked if(direction) { //if it's the last slide if(i === itemsInTotal-1) { sliderItems[0].classList.add('active'); } else { sliderItems[i+1].classList.add('active'); break; } // if the PREV button was clicked } else { //if it's the first element if(i === 0) { sliderItems[itemsInTotal-1].classList.add('active'); break; } else { sliderItems[i-1].classList.add('active'); } } } }; } sliderNav.addEventListener('click', changeSlide); 
 .hero { background-color: #252525; min-height: 100vh; position: relative; } .hero ul { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } .hero ul li { display: none; color: #fff; text-align: center; font-family: "Frank Ruhl Libre", serif; font-size: 2em; } .hero ul li span { color: #f5989d; text-transform: uppercase; font-family: "Josefin Sans", sans-serif; font-size: 1.3em; font-weight: 700; display: block; } .hero ul li.active { display: block; } .hero .slider-nav a { border:1px solid red; position: absolute; content: ' '; width: 30px; height: 30px; background: url("img/arrow-r.png"); background-size: contain; position: absolute; top: calc( 50% - 15px ); z-index: 10; } .hero .slider-nav a:hover { cursor: pointer; } .hero .slider-nav a.nav-prev { transform: rotate(180deg); left: 7%; } .hero .slider-nav a.nav-next { right: 7%; } 
  <section class="hero"> <div class="text-slider"> <div class="slider-nav"> <a class="slider-nav nav-prev"></a> <a class="slider-nav nav-next"></a> </div> <ul> <li class="active">I like take photos <span>in the woods</span></li> <li>I like observing <span>people and their emotions</span></li> <li>I always take <span>the best of life</span></li> <li>I always take <span>the best of life 2</span></li> <li>I always take <span>the best of life 3</span></li> </ul> </div> </section> 

Okay, I added 2 break in the loop to stop the iteration after applying the class on the next element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM