Andrea Turri
Andrea Turri

Reputation: 6500

jQuery cycle pugin and infinite loop

I'm using THIS plugin to show "n" strings that scroll up every 5 seconds.

In particular you can see the example at the bottom HERE.

This plugin show just one element each time so I did this splitup function that show 7 element:

$.fn.splitUp = function (splitBy, wrapper) {
    $all = $(this).find('>*');
    var fragment = Math.ceil($all.length / splitBy);
    for (i = 0; i < fragment; i++)
        $all.slice(splitBy * i, splitBy * (i + 1)).wrapAll(wrapper);
    return $(this);
}

$('#list').splitUp(7, '<li><li/>').cycle({
    fx: 'scrollUp',
    pause: 1,
    timeout: 5000,
    speed: 2000
});

it works fine.

The problem is: if I have 9 strings it show the first 7 and than only 2 strings... I'd like to show 7 strings and than 2 + 5. An infinite loop.

How can be possible to do that?

Thanks

EDIT http://jsfiddle.net/QZu2Z/

Upvotes: 1

Views: 1292

Answers (1)

Jeff Wilbert
Jeff Wilbert

Reputation: 4520

Here's a solution using the before event and the addSlide() method available to the options property passed by the event. I added comments to the code to explain what's going on.

CODE (Fiddle Demo: http://jsfiddle.net/QZu2Z/4/)

var pos = 0;
var count = 1;
var maxItems = 7;
var items = [];

function createSlide()
{
    // This function takes the array of items we have and builds a new ul
    // list based on maxitems and last pos, the result is multiple calls
    // to this function produces output like so:

    //  First pass returns: 1 2 3 4 5 6 7
    // Second pass returns: 8 9 1 2 3 4 5
    //  Third pass returns: 6 7 8 9 1 2 3
    //  Forth pass returns: 4 5 6 7 8 9 1
    // and so forth...

    var elem = $('<ul class="list"></ul>');

    for(i = 1; i <=9; i++)
    {
        if (pos >= 9)
        {
            pos = 0;
        }

        if(count <= maxItems)
        {
            count = count + 1;

            $(elem).append(items[pos]);

            pos = pos + 1;
        }
    }

    count = 1;

    return elem;
}

function onBefore(curr, next, opts) {
    // This is the onBefore slide event; we're simply checking if the addSlide
    // method is available on the opts object as apparently on the first pass,
    // addSlide is undefined (plugin hasn't yet created the function);

    if (!opts.addSlide)
    {
        return;
    }

    // addSlide function is available so generate the next slide and add it
    opts.addSlide(createSlide());
}

$(document).ready(function() {
    // Generate an array of items to use in our cycle
    $(".wrapper li").each(function(i) {
        items[i] = $(this).clone().wrap('<div>').parent().html();
    });

    // Grab the slideshow object
    var $ss = $('.wrapper');

    // Erase the contents, we have the data stored in the array [items]
    $ss.empty();

     // Create new slide and append it to our object, results in 1 2 3 4 5 6 7
    $ss.append(createSlide());

    // Create another slide and append it to our object, results 8 9 1 2 3 4 5
    $ss.append(createSlide());

    // start the slideshow (a slideshow can't be started unless there's 2 
    // slides hence why we created two slides above to start with).  The
    // before/onBefore event will add a new slide every cycle of the slideshow.
    $ss.cycle({
        fx: 'scrollUp',
        pause: 1,
        timeout: 5000,
        speed: 2000,
        before: onBefore
    });
});

Extra Note:

One thing to keep in mind although it shouldn't be a problem for most people is since this does add a new slide every cycle, having your browser open on the page for a long period of time will start to suck up more and more resources as new elements are constantly being added to the DOM. There is however a fix too it figure out when you've looped through to cycle them back to original starting point then no new slides need to be added and it can loop them; visually this is easier to see then to explain

 -> createSlide() = 1 2 3 4 5 6 7 (store this first results to compare with rest)
|   createSlide() = 8 9 1 2 3 4 5
|   createSlide() = 6 7 8 9 1 2 3
|   createSlide() = 4 5 6 7 8 9 1
|   createSlide() = 2 3 4 5 6 7 8
|   createSlide() = 9 1 2 3 4 5 6
|   createSlide() = 7 8 9 1 2 3 4
|   createSlide() = 5 6 7 8 9 1 2
 -< createSlide() = 3 4 5 6 7 8 9
    createSlide() = 1 2 3 4 5 6 7 (this value equals the first result so no new 
slides need to be added, let the process use the slides that are already added
and loop back to the beginning

Extra Extra Note:

Another thing I just realized is if you use the technique above then technically you can get rid of the before event callback and simply generate all the needed slides before you even start the slideshow.

Upvotes: 3

Related Questions