简体   繁体   中英

Slider- Previous button hides first slide instead of previous slide

I created some CSS and JavaScript that turns WordPress's native gallery into a slideshow. For each gallery, I have next and previous buttons that show each slide when clicked.

The problem is that when clicking to show a previous slide, it only shows the first slide. I think this is because the initial counter that lies outside of the click functions is set to 0. Is there any way to keep track of which slide the counter is on between each function, or to adjust the functions themselves?

Here is the JavaScript:

function() {
...
    var gallery = document.querySelectorAll('.single.slider .gallery');

    var galleries = [   document.querySelector('.single.slider #gallery-1'),
                        document.querySelector('.single.slider #gallery-2') ];

    var slides = [  document.querySelectorAll('.single.slider #gallery-1 .gallery-item'),
                    document.querySelectorAll('.single.slider #gallery-2 .gallery-item') ];

    var slides1Count = 0;
    var slides2Count = 0;

    function hideFirstSlide() {
    // slides[0] = first location of the array in the slides variable, slides[1] = second, etc.
    // slides[0][0] = first slide inside of the first array

        for (var iGal = 0, len = galleries.length; iGal < len; iGal++) {
        //console.log('number of galleries: ' + iGal);
            for (var jSlide = 0, len = slides.length; jSlide < len; jSlide++) {
            //console.log('number of slides within gallery: ' + slides[jSlide].length); // for debugging
            //console.log(slides[0][0]); // for debugging

                // We must loop over each slide when using querySelectorAll
                for (var kEachSlide = 0; kEachSlide < slides[jSlide].length; kEachSlide++) {
                //console.log(slides[jSlide].length); // Number of slides within current selected query

                    // Hide all slides within each slides array;
                    if (slides[0][kEachSlide]) {
                        slides[0][kEachSlide].classList.add('hide');
                    }
                    if (slides[1][kEachSlide]) {
                        slides[1][kEachSlide].classList.add('hide');
                    }

                    // Show first slide within each slides array
                    if (slides[0][0]) {
                        slides[0][0].classList.remove('hide');
                    }
                    if (slides[1][0]) {
                        slides[1][0].classList.remove('hide');
                    }
                }
            }
        }
    }

    window.onload = hideFirstSlide();

    for (var i = 0, len = gallery.length; i < len; i++) {
        // Add slider controls to each gallery
        gallery[i].insertAdjacentHTML('afterend', '<div class="slider-button-panel"><button class="slider-previous"></button><button class="slider-startshow">Start Slideshow</button><button class="slider-next"></button></div>');
        //console.log(gallery.length);
    }

    var sliderButtonPrevious = document.querySelectorAll('.single.slider .slider-previous');
    var sliderButtonNext = document.querySelectorAll('.single.slider .slider-next');

    var sliderNext = [  document.querySelector('.single.slider #gallery-1 + .slider-button-panel .slider-next'),
                        document.querySelector('.single.slider #gallery-2 + .slider-button-panel .slider-next') ];

    var sliderPrevious = [  document.querySelector('.single.slider #gallery-1 + .slider-button-panel .slider-previous'),
                                document.querySelector('.single.slider #gallery-2 + .slider-button-panel .slider-previous') ];

    // Show each subsequent slide one at a time by clicking the next and previous buttons
    // checking if each button exists on the page first
    if (sliderNext[0]) {
        sliderNext[0].addEventListener('click', showNext(slides[0], slides1Count));
    }
    if (sliderNext[1]) {
        sliderNext[1].addEventListener('click', showNext(slides[1], slides2Count));
    }

    if (sliderPrevious[0]) {
        sliderPrevious[0].addEventListener('click', showPrevious(slides[0], slides1Count));
    }
    if (sliderPrevious[1]) {
        sliderPrevious[1].addEventListener('click', showPrevious(slides[1], slides2Count));
    }

    // Next slide function
    function showNext(obj, counter) {
        return function() {
            obj[counter].classList.add('hide');
            counter++;
            if (counter === obj.length) {
                counter = obj.length - 1;
            }
            obj[counter].classList.remove('hide');
            //console.log(counter);
        }
    }

    // Previous slide function
    function showPrevious(obj, counter) {
        return function() {
            obj[counter].classList.add('hide');
            counter--;
            if (counter === -1) {
                counter = 0;
            }
            obj[counter].classList.remove('hide');
            console.log(counter);
        }
    }

)();

Here is the relevant HTML and CSS:

<div id="gallery-1" class="gallery galleryid-555 gallery-columns-3 gallery-size-large">
    <figure class="gallery-item">
        <div class="gallery-icon landscape">
            <a href="#"><img src= ... /></a>
        </div>
        <figcaption class="wp-caption-text gallery-caption" ...>A Caption</figcaption>
    </figure>
    <figure class="gallery-item hide">
        <div class="gallery-icon landscape">
            <a href="#"><img src= ... /></a>
        </div>
    </figure>
    ...
    each slide thereafter has .hide class attached
</div>
<div id="gallery-2" class="gallery galleryid-555 gallery-columns-3 gallery-size-large">
    <figure class="gallery-item">
        <div class="gallery-icon landscape">
            <a href="#"><img src= ... /></a>
        </div>
    </figure>
    <figure class="gallery-item hide">
        <div class="gallery-icon landscape">
            <a href="#"><img src= ... /></a>
        </div>
    </figure>
    ...
</div>
...

.gallery-item {
    margin: 0 auto;
}

.single.slider .gallery {
    position: relative;
    min-width: 100%;
}

.single.slider .gallery-item {
    max-width: none;
    position: absolute;
    top: 0;
    width: 100%;
}

.hide {
    display: none;
}

I am including a stripped down version in the JSFiddle here as well: https://jsfiddle.net/jgpws/fkbrbkLa/ .

Thanks.

Okay, so after months of fiddling around with this and reading several tutorials and other SO posts, I finally found what appears to be a solution.

I changed each separate function that increases or decreases the slides (hiding and showing) to one function that handles only counting up and down. This function returns two objects that count up or down. Then, the click handlers were modified to add and remove the hide class. Then, in the click handler, the count function needed to be called again. That part only worked through trial and error. Thus, I only know that it worked, but not why. Maybe it resets the nodelist location after hiding/showing?

Also, for instance, when I click to go forward then immediately click to go back, I have to click twice. On the second click, the slide goes back.

Since this solution was close enough to what I was looking for, I'm okay with it. Here is the updated code:

function() {

...

    var slides = [  document.querySelectorAll('.single.slider #gallery-1 .gallery-item'),
                document.querySelectorAll('.single.slider #gallery-2 .gallery-item') ];

    //var slides1Count = 0;
    //var slides2Count = 0;

    ...

    // Next slide function
    function showSlide(obj) {
        var counter = 0;
        return {
            showNext: function() {
                counter++;
                if (counter === obj.length) {
                    counter = obj.length - 1;
                }
                console.log('Next slide: ' + counter);
                return counter;
            },
            showPrevious: function() {
                counter--;
                if (counter < 0) {
                    counter = 0;
                }
                console.log('Previous slide: ' + counter);
                return counter;
            }
        }
    }

    // Show each subsequent slide one at a time by clicking the next and previous buttons
    // checking if each button exists on the page first
    function addClickEvents() {
        var currentSlide1 = showSlide(slides[0]);
        var currentSlide2 = showSlide(slides[1]);

        if (sliderNext[0]) {
            sliderNext[0].addEventListener('click', function() {
                slides[0][currentSlide1.showPrevious()].classList.add('hide');
                slides[0][currentSlide1.showNext()].classList.remove('hide');
                slides[0][currentSlide1.showNext()];
            });
        }
        if (sliderNext[1]) {
            sliderNext[1].addEventListener('click', function () {
                slides[1][currentSlide2.showPrevious()].classList.add('hide');
                slides[1][currentSlide2.showNext()].classList.remove('hide');
                slides[1][currentSlide2.showNext()];
            });
        }

        if (sliderPrevious[0]) {
            sliderPrevious[0].addEventListener('click', function() {
                slides[0][currentSlide1.showPrevious()].classList.remove('hide');
                slides[0][currentSlide1.showNext()].classList.add('hide');
                slides[0][currentSlide1.showPrevious()];
            });
        }
        if (sliderPrevious[1]) {
            sliderPrevious[1].addEventListener('click', function () {
                slides[1][currentSlide2.showPrevious()].classList.remove('hide');
                slides[1][currentSlide2.showNext()].classList.add('hide');
                slides[1][currentSlide2.showPrevious()];
            });
        }
    }
    window.onload = addClickEvents();

)();

Some of the function names can be changed to better describe what they do, but this worked for me.

The code examples found in the article Understand JavaScript Closures With Ease helped me a lot, as it was the adapting of some of the article's code that helped me figure out a counter that can be shared between each button's click event.

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