How to modify Elastislide so it loops infinitely

14,802

Solution 1

Elastislide code has evolved and the above solution does not work. So I have developed my own solution.

This code makes elastislide autoplay and when arrived at last slide it returns to the first slide to be more ergonomic than the infinite loop caroussel.

This code should be added in the _initEvents function after var self = this;

var translation = 0;
// width/height of an item ( <li> )
var itemSpace = this.options.orientation === 'horizontal' ? this.$items.outerWidth( true ) : this.$items.outerHeight( true );
// total width/height of the <ul>
var totalSpace = this.itemsCount * itemSpace;
// visible width/height
var visibleSpace = this.options.orientation === 'horizontal' ? this.$carousel.width() : this.$carousel.height();
//slide auto
window.setInterval(function(){
    //test if we should go to next slide or return to first slide
    if(totalSpace > translation + visibleSpace)
    {
        //go to next slide
        self._slide('next');
        //update translation
        translation += visibleSpace;
    }
    else
    {
        //return to first slide (infinite loop is too bad for ergonomics)
        self._slideTo(0);
        //set translation to 0
        translation = 0;
    }
}, 7000);

Solution 2

This code creates an infinite loop, preserves animations and shows navigation buttons on both sides if there are more elements than displayed on page. The _toggleControls function remains the same as in the original version.

// modified version of _slide
_slide              : function( dir, val, anim, callback ) {

        // if animating return
        if( this.$slider.is(':animated') )
            return false;

        // current margin left
        var ml      = parseFloat( this.$slider.css('margin-left') );

        // val is just passed when we want an exact value for the margin left (used in the _slideToCurrent function)
        if( val === undefined ) {

            // how much to slide?
            var amount  = this.fitCount * this.itemW, val;

            if( amount < 0 ) return false;

            // make sure not to leave a space between the last item / first item and the end / beggining of the slider available width
            if( dir === 'right' && this.sliderW - ( Math.abs( ml ) + amount ) < this.visibleWidth ) {
                for (var i=0;i<this.fitCount;i++) { // add elements
                    this.$slider.css('margin-left', '+=' + this.itemW );
                    this.$slider.append( this.$slider.children('li:first').clone() ) ;
                    this.$slider.children('li:first').remove();
                }
            } else if ( dir === 'left' && Math.abs( ml ) - amount < 0 ) {
                for (var i=0;i<this.fitCount;i++) { // add elements
                    this.$slider.css('margin-left', '-=' + this.itemW );
                    this.$slider.prepend( this.$slider.children('li:last').clone() ) ;
                    this.$slider.children('li:last').remove();
                }
            }

            ( dir === 'right' ) ? val = '-=' + amount : val = '+=' + amount

        }
        else {
            var fml     = Math.abs( val ); // future margin left

            if( Math.max( this.sliderW, this.visibleWidth ) - fml < this.visibleWidth ) {
                val = - ( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth );
                if( val !== 0 )
                    val += this.options.margin; // decrease the margin left if not on the first position

                // show / hide navigation buttons
                this._toggleControls( 'right', -1 );
                fml = Math.abs( val );
            }

            // show / hide navigation buttons
            if( this.fitCount < this.itemsCount )
                this._toggleControls( 'left', 1 );
            else
                this._toggleControls( 'left', -1 );

            if( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth > fml + this.options.margin )   
                this._toggleControls( 'right', 1 );
            else
                this._toggleControls( 'right', -1 );

        }

        $.fn.applyStyle = ( anim === undefined ) ? $.fn.animate : $.fn.css;

        var sliderCSS   = { marginLeft : val };

        var instance    = this;

        this.$slider.applyStyle( sliderCSS, $.extend( true, [], { duration : this.options.speed, easing : this.options.easing, complete : function() {
            if( callback ) callback.call();
        } } ) );

    },

Solution 3

I did it by hacking the toggleControls() function, instead of hiding the navigation to append the first item / prepend the last item. The auto-correction of amount when you are in the beginning / end of the items actually helped to do the trick. Unfortunatelly it breaks the animation, if easing is used.

// modified version of _toggleControls
    _toggleControls     : function( dir, status ) {

        // show / hide navigation buttons
        if( dir && status ) {
            if( status === 1 )
                ( dir === 'right' ) ? this.$navNext.show() : this.$navPrev.show();
            else
                if ( dir === 'right' ) {

                    this.$slider.append( this.$slider.children('li:first').clone() ) ;
                    this.$slider.children('li:first').remove();
                } else {

                    this.$slider.prepend( this.$slider.children('li:last').clone() ) ;
                    this.$slider.children('li:last').remove();
                }
        }
        else if( this.current >= this.itemsCount - 1 || this.fitCount >= this.itemsCount )
                this.$navNext.hide();

    },

Solution 4

I was having the same trouble as the OP, but couldn't get either of the above solutions to work. Not sure if I was doing something wrong or if the Elastislide code had changed since those solutions were written.

I found this plugin, which seems to satisfy all the same criteria that the OP had: responsive carousel with auto-play and infinite loop.

http://caroufredsel.dev7studios.com/

Hopefully this helps someone else that finds this article the same way I did.

Solution 5

Add this code in the _initEvents function after - var instance = this; to make the elastislide autoplay.

window.setInterval(function(){
                instance._slide('right');
            }, 7000);
Share:
14,802
Admin
Author by

Admin

Updated on July 01, 2022

Comments

  • Admin
    Admin almost 2 years

    I've been searching for an image carousel that will display several images at once, is responsive and loops infinitely.

    Elastislide seems to be the most suitable ( http://tympanus.net/Development/Elastislide/index2.html ).

    The only other practical option I've been able to find is Liquid Carousel by John Nikolakis which seems to be a fair bit older and less elegant.

    I've got Elastislide to autoplay (sort of), using a similar method to the The clearTimeout() Method shown at http://www.w3schools.com/js/js_timing.asp, but once it reaches the end it stops, as the timing is just calling the next button (.es-nav-next).

    I'm hoping someone can help me with modifying Elastislide to make it loop infinitely - or I'm open to suggestions for a different solution which meets my 3 requirements (listed above).

    At the moment I'm working on a local installation of OpenCart but I can put up a static sample and provide a link if that helps.

    Any help or advice would be greatly appreciated, have spent many hours on this so far as I'm a complete amateur at javascript :)