Chris Warnes
Chris Warnes

Reputation: 728

JQuery Slider animation only happens for one cycle

Ive been attempting to create my own Javascript slider plugin, (I realise there are many out there, but i wanted to treat it as a learning exercise),

an example can be seen here: http://jsfiddle.net/6GTGU/

the problem I'm having is that the animation goes round once, and then stops, Ive tried to examine this to see what i have done wrong but i can't find any reason for it, if anyone can help me i would be very grateful.

HTML

    <div id="cjwSlider">
        <div style="background-color: #6495ed"></div>
        <div style="background-color: #62ed43"></div>
        <div style="background-color: #ed5943"></div>
    </div>

JAVASCRIPT

    var cjwSlider = $('#cjwSlider');
    var sliderItems = cjwSlider.children('div');

    $(document).ready(function () {
        sliderItems.each(function( index ) {
            $(this).css('z-index', index);
        });

        window.setInterval(function(){

            var maxValue = findMaxZIndex();
            var currentItem = sliderItems.filter(function() {
                return $(this).css('z-index') == maxValue;
            });

            currentItem.addClass("hiddenDiv").delay(1000).queue(function() {
                sliderItems.each(function( index ) {
                    $(this).css('z-index', parseInt($(this).css('z-index')) + 1);
                });

                currentItem.css('z-index', 0);
                currentItem.removeAttr('class');
            });

        }, 4000);


    });

    function findMaxZIndex() {
        var maxValue = undefined;
        $(sliderItems).each(function() {
            var val = $(this).css('z-index');
            val = parseInt(val, 10);
            if (maxValue === undefined || maxValue < val) {
                maxValue = val;
            }
        });
        return maxValue;
    }

Upvotes: 3

Views: 167

Answers (2)

Roko C. Buljan
Roko C. Buljan

Reputation: 205987

PLUGIN DEMO IN ACTION

You said you want a plugin so here you go.
It even stops on mouseenter. (I personally hate when I cannot stop a gallery by just hovering it.)
I don't understand the need of z-index at all, so you can calmly remove it all from your HTML and don't bother at all.

<div class="cjwFader" id="el1">
    <div style="background: red;">   1 </div>
    <div style="background: green;"> 2 </div>
    <div style="background: gold;">  3 </div>
</div>

CSS:
(the only needed, but you can also make jQ apply the children position)

.cjwFader > div {
    position: absolute;
}

And finally the plugin:

(function($){ 
$.fn.cjwFader = function(opts){ 

    // Default Settings
    var S = $.extend({
      fade: 400,
      wait: 2000,
      startAt: 0 
      //, need more? add more.
    },opts);

    return $(this).each(function(){

       var that = $(this),
           child = $('>*',that),
           nOfChildren = child.length,
           sI;

       function animate(){
         child.eq( S.startAt = ++S.startAt % nOfChildren )
              .fadeTo( S.fade,1 )
              .siblings().stop().fadeTo(S.fade,0);
       }     
       function loop(){
         sI=setInterval( animate, S.wait+S.fade );
       }loop();      

       child.hover(function(e){
            return e.type==='mouseenter'? clearInterval(sI) : loop();   
       }).eq(S.startAt).show().siblings().hide();

    });

};
})(jQuery);

Plugin usage:

$(function(){ // DOM ready

  // $('#el1').cjwFader(); // Use default plugin settings

  $('#el1').cjwFader({     // Let's apply some custom stuff
    startAt : 1,
    fade : 1000,
    wait: 700
  });

});

Upvotes: 2

Chandranshu
Chandranshu

Reputation: 3669

Here is the working slideshow: http://jsfiddle.net/6GTGU/7/

I've updated the HTML slightly to remove the initialization code from your JS. You may decide to revert that back

HTML

<div id="cjwSlider">
    <div style="background-color: #6495ed; z-index: 0;"></div>
    <div style="background-color: #62ed43; z-index: 1;"></div>
    <div style="background-color: #ed5943; z-index: 2;"></div>
</div>

I had to remove a lot of JS code to nail down the problem. I think the current JS is all you may need and don't need to go back to your original one:

var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');

$(document).ready(function () {
    window.setInterval(function () {
        var maxValue = $('#cjwSlider').find('div').length - 1;
        var currentItem = sliderItems.filter(function () {
            return $(this).css('z-index') == maxValue;
        });

        currentItem.addClass("hiddenDiv").delay(1000).queue(function () {
            sliderItems.each(function (index) {
                $(this).css('z-index', parseInt($(this).css('z-index')) + 1);
            });

            currentItem.css('z-index', 0);
            currentItem.removeAttr('class');
            $(this).dequeue();
        });
    }, 4000);
});

The crux of the problem was the missing call to dequeue() at the end of the function that was queued up. The function executed fine for the first time but then stayed at the head of the queue and prevented execution of functions queued later on. This is why your animation played for one cycle but not after that.

Upvotes: 1

Related Questions