Search code examples
javascriptjquerycsssliders

Add autoplay function to simple jQuery slider


My current slider functions perfect, and also has a working pagination (paginated dots, active state, and control) but I just want to add ONE new feature without breaking anything:

The ability for my slider to autoplay on page load.

Any suggestions, greatly appreciated.

HTML / Markup:

<div class="allslideshow">
    <div class="slideshow-wrapper">
        <div class="slide" id="s1"></div>
        <div class="slide" id="s2"></div>
        <div class="slide" id="s3"></div>
    </div>
    <div class="slideshow-nav"> <a href="#s1">•</a>
 <a href="#s2">•</a>
 <a href="#s3">•</a>
    </div>
</div>

jQuery

jQuery(document).ready(function($) {
var Slideshow = {
    paginate: function () {
        var slides = $('div.slide', '.allslideshow'),
            total = slides.length;
        $('.slideshow-nav-total').text(total);
        slides.each(function (i) {
            $(this).data('index', i + 1);
        });
    },
    navigate: function () {
        $('a', '.slideshow-nav').click(function (e) {
            e.preventDefault();
            var $a = $(this);
            var slide = $($a.attr('href'));
            var wrapper = $('.slideshow-wrapper');
            wrapper.animate({
                left: -slide.position().left
            }, 500, 'linear', function () {
                $('.slideshow-nav-current').text(slide.data('index'));
                $a.addClass('active').siblings('a').removeClass('active');
            });

        });
    },
    init: function () {
        this.paginate();
        this.navigate();
    }
};
$(function () {
    Slideshow.init();
    });
});

Attempt:

// autoplay: function () {
//      .ready(function) { 
//         e.preventDefault();
//         var $a = $(this);
//         var slide = $($a.attr('href'));
//         var wrapper = $('.slideshow-wrapper');
//         wrapper.animate({
//             left: -slide.position().left
//         }, 300, 'linear', function () {
//             $('.slideshow-nav-current').text(slide.data('index'));
//             $a.addClass('active').siblings('a').removeClass('active');
//          });

//     });
// },

Solution

  • The way to move forward is to abstract away the animation function from the "click" event handler on your links. That way you can call the animation function from both a click and a timer event. The tricky thing about this is that you have to capture the this context in order to use it inside a closure. Here's what I mean:

    //...
    moveTo: function($a) {
      var slide = $($a.attr('href'));
      var wrapper = $('.slideshow-wrapper');
      wrapper.animate({
        left: -slide.position().left
      }, 500, 'linear', function () {
        $('.slideshow-nav-current').text(slide.data('index'));
        $a.addClass('active').siblings('a').removeClass('active');
      });
    },
    navigate: function () {
        var self = this;
        $('a', '.slideshow-nav').click(function (e) {
            e.preventDefault();
            if (self.interval) {
              clearInterval(self.interval);
              self.interval = false;
            }
            var $a = $(this);
            self.moveTo($a);
        });
    },
    autoPlay: function() {
      var $alist = $('a', '.slideshow-nav');
      var i = 0;
      var self = this;
      this.interval = setInterval(function() {
        var $a = $alist.eq(i++);
        i %= $alist.length;
        self.moveTo($a);
      }, 1000);
    },
    init: function () {
        this.paginate();
        this.navigate();
        this.autoPlay();
    }
    //...
    

    Try it in a plunker.