The code below successfully fades in one testimonial for 6 seconds, waits 3 seconds, and then fades it out and moves on to the next. Once it reaches the third testimonial it jumps back to the first. This is exactly what I want but on my actual site I have more than three testimonials and in the future may be adding more. I don't want to have to go back and add a new function every time I add a new testimonial. I tried for some time to get this to work using "this" and .next() but failed. I'm hoping someone could make this much more efficient by looping it and getting it to move to the next p tag within the container without calling a new function every time. Any help is appreciated, thank you.
Note: I know there are similar questions but none of them were quite the same and the answers are sub par.
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<style>
#tml-container p { display: none; }
</style>
</head>
<body>
<div id="tml-container">
<p id="one">Testimonial 1</p>
<p id="two">Testimonial 2</p>
<p id="three">Testimonial 3</p>
</div>
<script>
$(document).ready(function() {
function doFade() {
$("#one").fadeIn(6000,function() {
$("#one").fadeOut(6000).delay(3000);
setTimeout(fadeTwo,6000);
});
}
function fadeTwo() {
$("#two").fadeIn(6000,function() {
$("#two").fadeOut(6000).delay(3000);
setTimeout(fadeThree,6000);
});
}
function fadeThree() {
$("#three").fadeIn(4000,function() {
$("#three").fadeOut(6000).delay(3000);
setTimeout(doFade,6000);
});
}
doFade();
});
</script>
</body>
</html>
This is a very simple solution:
function fade($ele) {
$ele.fadeIn(6000).delay(3000).fadeOut(6000, function() {
var $next = $(this).next('p');
// if there is a following `p` element, it is faded in
// otherwise start from the beginning by taking
// the parent's first child
fade($next.length > 0 ? $next : $(this).parent().children().first());
});
};
fade($('#tml-container > p').first());
DEMO
Reusable plugin version:
Instead of iterating over the children of a certain element, it iterates over the selected elements.
(function($) {
var default_config = {
fadeIn: 3000,
stay: 3000,
fadeOut: 3000
};
function fade(index, $elements, config) {
$elements.eq(index)
.fadeIn(config.fadeIn)
.delay(config.stay)
.fadeOut(config.fadeOut, function() {
fade((index + 1) % $elements.length, $elements, config);
});
}
$.fn.fadeLoop = function(config) {
fade(0, this, $.extend({}, default_config, config));
return this;
};
}(jQuery));
Usable as:
$('#tml-container > p').fadeLoop({fadeIn: 6000, stay: 3000, fadeOut: 6000});
DEMO
Changed a self developed Plugin to meet your requirements,
didn't test it fully though.
Should at least show you how to set something like this up properly.
Hope this helps :)
(function($){
$(function(){
$('#tml-container').testimonialFader();
});
$.fn.testimonialFader = function(){
return this.each(function(){
var $par = $(this),
$testimonials = $par.children('p'),
$current = $testimonials.first();
$testimonials.not(':first').hide();
$testimonials.on('testimonialReady.testimonialFader', wait);
$testimonials.on('waitComplete.testimonialFader', showNext);
$current.trigger('testimonialReady.testimonialFader');
function wait(e){
$current.trigger('waitStart.testimonialFader');
setTimeout(
function(){
$current.trigger('waitComplete.testimonialFader');
},
6000
);
}
function showNext(){
$current.trigger('testimonialChange.testimonialFader');
if($testimonials.length > 1){
var $next = $current.next();
if($next.length == 0){
$next = $testimonials.first();
}
$current.fadeOut(800);
$next.fadeIn(800,
function(){
$next.trigger('testimonialReady.testimonialFader');
}
);
$current = $next;
}
}
});
};
}(jQuery));