Question

There was an awesome, super-minimal testimonial rotator that I found here, but I'm curious as to how I might get it to simply randomize the results. Here's the rotator as it now functions:

$('.testimonials div:first').show();

setInterval(function(){ 
    $('.testimonials div:first-child')
        .fadeOut(1000)
        .next('div')
        .delay(1000)
        .fadeIn(1000)
        .end()
        .appendTo('.testimonials') 
},3000);

http://jsfiddle.net/xXRwA/9/

Was it helpful?

Solution 2

Try this:

var $items = $('.testimonials .item');

function getRandomItem(){
    return $items.eq(Math.floor($items.length * Math.random()));
}

getRandomItem().show();

setInterval(function(){ 
    var $outgoing = $items.filter(':visible');
    var $incoming = getRandomItem();
    $outgoing.fadeOut(1000, function(){
        $incoming.fadeIn(1000);
    });
}, 3000);

Demo: http://jsfiddle.net/JWGbz/6/

OTHER TIPS

This code makes sure the same item isn't shown twice and continues to work if you change the amount of testimonials. The first item shown is also random.

Demo

$(document).ready(function() {

    $('.testimonials div').eq(Math.floor((Math.random() * $('.testimonials div').length))).show();

    setInterval(function() {

        var $items = $('.testimonials div');
        if ($items.length < 2) {
            return;
        }

        var $currentItem = $items.filter(':visible');
        var currentIndex = $currentItem.index();
        var nextIndex = currentIndex;
        while (nextIndex == currentIndex) {
            nextIndex = Math.floor((Math.random() * $items.length));
        }
        $currentItem.fadeOut(1000, function() {
            $items.eq(nextIndex).fadeIn(1000);
        });

    }, 3000);

});

This problem kept eating at me, and I realized that the real problem is here is that you want a way to shuffle the testimonials. If you had a way to do that, then your original function would even work as intended. As it turns out, shuffling a list of jQuery elements is not as easy as you might think. I started by implementing a function that allows you to swap two arbitrary jQuery elements (this avoids using jQuery.clone, which has side-effects, like removing event listeners):

function swap($a, $b){
    var $aNext = $a.next(),
        $aParent = $a.parent();
    $a.insertAfter($b);
    if($aNext.length) $b.insertBefore($aNext);
    else $aParent.append($b);
}

Then you can implement a Fisher-Yates shuffle:

function shuffle($items){
    var i, j;
    for(i=$items.length-1; i>1; i--){
        j = Math.floor(Math.random() * (i+1));
        swap($items.eq(i), $items.eq(j));
    }
}

Now you can simply shuffle all of your testimonials:

shuffle($('.testimonials .item'));

Then use your original code:

$('.testimonials div:first').show();

setInterval(function(){ 
    $('.testimonials div:first-child')
        .fadeOut(1000)
        .next('div')
        .delay(1000)
        .fadeIn(1000)
        .end()
        .appendTo('.testimonials') 
},3000);

Of course, once you've gone through all the testimonials, you may want to re-shuffle them to it doesn't keep repeating the same order over and over again.

Demo: http://jsfiddle.net/JWGbz/7/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top