简体   繁体   中英

jQuery rotating through list items in a gallery

This has probably been answered before and I already know how this should work, but for some reason it is not. I think it may be how I am looping through the elements.

$(document).ready(function() {
     var element = '#gallery ul#gallery-container';
 var idx=0;
 var timeout = 3000;
 var number =  $(element + ' li').length;

function changeSlide() {

    $(element + ' li:eq(' + idx + ')').fadeOut();

    idx = idx + 1;

    if (idx == number) {
        idx=0;
    }

    $(element + ' li:eq(' + idx + ')').fadeIn().delay(timeout).delay(0,   function() {
        changeSlide();
    });;

}

 $(element + ' li').hide();

 $(element + ' li:first').fadeIn().delay(timeout).delay(0, function() {
    changeSlide();
 });
});

Then the list is like this:

<div id="gallery">
    <ul id="gallery-container">
        <li><img src="media/images/screen-shot-02.jpg" width="173" height="258" alt=" "></li>
        <li><img src="media/images/screen-shot-01.jpg" width="173" height="258" alt=" "></li>
    </ul>   
</div>

I was trying to get it to loop through the elements one by one, after a delay so the list item calls the function and hides itself, then the counter is incremented and then the current index is shown. I suspect the culprit to be this as if I put an alert in the function it is called:

 $(element + ' li:eq(' + idx + ')').fadeOut();

The main problem is, as the comment states, delay does not do what you think it does - you should be looking at the native setTimeout function instead. In addition to that, there are multiple places where this could be made more efficient. Have a look at this:

var element = $('#gallery-container li'),
    length = element.length,
    current = 0,
    timeout = 3000;

function changeSlide() {
    element.eq(current++).fadeOut(300, function(){
        if(current === length){
            current = 0;
        }

        element.eq(current).fadeIn(300);
    });

    setTimeout(changeSlide, timeout);
}

element.slice(1).hide();
setTimeout(changeSlide, timeout);

We try not to evoke the jQuery function with a dynamically generated selector, but instead manipulate a single instance of a jQuery object containing all the slides cached at the start. We also use the callback function provided by the fade functions to fade in the next slide after the current one has faded out.

See http://www.jsfiddle.net/b3Lf5/1/ for a simple demo

I would do it something like this:

$(document).ready(function() {
    var element = '#gallery ul#gallery-container';
    var idx = 0;
    var timeout = 3000;
    var number = $(element + ' li').length;

    setInterval(function () {
        idx = (idx + 1) % number;
        $(element + ' li:visible').fadeOut();
        $(element + ' li:eq(' + idx + ')').fadeIn();
    },timeout);
    $(element + ' li:not(:first)').hide();
});

Or better still, wrap it in a plugin:

(function ($) {
    $.fn.customGallery = function (options) {
        defaults = {
            timeout : 3000
        };
        options = $.extend(defaults, options);
        return this.each(function () {
            var idx = 0, number = $(this).children('li').size(), element = this;
            setInterval(function () {
                idx = (idx + 1) % number;
                $(element).children('li:visible').fadeOut();
                $(element).children('li:eq(' + idx + ')').fadeIn();
            },options.timeout);
            $(element).children('li:not(:first)').hide();
        });
    };
}(jQuery));

jQuery(document).ready(function($) {
    $('#gallery-container').customGallery()
});

edit: Edited the plugin code to bring it into line with good practice.

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