I need to cycle through some divs using jQuery. What I mean by cycle is that I have a series of 7 divs:
Sample text
&
with pause on hover:
// FADESHOW // Simple fade gallery
$(".fadeShow").each(function() {
var $slides = $(this).children(),
tot = $slides.length,
itv = null,
idx = 0;
$slides.eq(idx).show();
function anim() { $slides.fadeOut().eq(++idx % tot).fadeIn(); }
function play() { itv = setInterval(anim, 2000); }
function stop() { clearInterval(itv); }
$(this).hover(stop, play);
play();
});
body{margin:0;}
/* FADESHOW basic CSS */
.fadeShow {
position:relative;
}
.fadeShow > * {
position:absolute;
display:none;
height: inherit;
width: 100%;
}
/* FADESHOW (your styles) */
.gal_1 { height:80px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="fadeShow gal_1">
<div style="background:#0bf;">1 Hover to pause</div>
<div style="background:#fb0;">2 You can have as many slideshows as you want</div>
<div style="background:#b0f;">3</div>
</div>
<div class="fadeShow">
<p>LOREM</p>
<p>IPSUM</p>
<p>DOLOR</p>
<p>SOMETHING</p>
</div>
If you want to convert it to a simpls jQuery plugin in order to allow different fade and pause values and include other options:
// FADESHOW // Simple fade gallery by Roko :)
(function($){
$.fn.fadeShow = function(options) {
var op = $.extend({
pause : 3800,
fade : 600,
pauseHover : true
}, options);
return this.each(function() {
var $slides = $(this).children(),
tot = $slides.length,
itv = null,
idx = 0;
$slides.eq(idx).show();
function anim() { $slides.fadeOut(op.fade).eq(++idx % tot).fadeIn(op.fade); }
function play() { itv = setInterval(anim, op.fade+op.pause); }
function stop() { clearInterval(itv); }
if(op.pauseHover) $(this).hover(stop, play);
play();
});
};
}(jQuery));
// Basic example
$(".gal1").fadeShow();
// With options
$(".gal2").fadeShow({
pause : 4000,
fade : 1000,
pauseHover : false
});
/* FADESHOW basic CSS */
.fadeShow {
position:relative;
}
.fadeShow > * {
position:absolute;
display:none;
height: inherit;
width: 100%;
}
/* FADESHOW (your styles) */
.gal1 { height:80px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="fadeShow gal1">
<div style="background:#0bf;">1 Hover to pause</div>
<div style="background:#fb0;">2 You can have as many slideshows as you want</div>
<div style="background:#b0f;">3</div>
</div>
<div class="fadeShow gal2">
<p>pauseHover : false</p>
<p>IPSUM</p>
<p>DOLOR</p>
<p>SOMETHING</p>
</div>
var divs = $('div[id^="content-"]').hide(),
i = 0;
(function cycle() {
divs.eq(i).fadeIn(400)
.delay(5000)
.fadeOut(400, cycle);
i = ++i % divs.length; // increment i,
// and reset to 0 when it equals divs.length
})();
DEMO: (with a shorter delay) http://jsfiddle.net/eFjnU/
If you don't want the fade animation, use show
and hide
. You still need to give a duration so that the delay
and the callback will work.
var divs = $('div[id^="content-"]').hide(),
i = 0;
(function cycle() {
divs.eq(i).show(0)
.delay(1000)
.hide(0, cycle);
i = ++i % divs.length;
})();
DEMO: (with a shorter delay) http://jsfiddle.net/eFjnU/1/
We need to iterate a set and handle its visibility properties.
First of all, let me show you two libraries I have created. The first is Iterable
, which is designed to handle all kinds of iterations:
function Iterable(params) {
var prevHandlers = [];
var nextHandlers = [];
var that = this;
this.current = params.current;
function ensureArray() {
if (!that.elements) {
that.elements = [];
} else if (!Array.isArray(that.elements)) {
that.elements = $.map(that.elements, function(value, index) {
return [value];
});
}
return that.elements;
}
function calculateCount() {
that.count = ensureArray().length;
}
this.setElements = function(elements) {
this.elements = elements;
calculateCount();
};
this.prev = function(amount) {
if (amount === undefined) {
amount = 1;
}
//Modulo twice to make sure current will be positive
that.current = (((that.current - amount) % that.count) + that.count) % that.count;
while (amount--) {
for (var prevHandler in prevHandlers) {
prevHandlers[prevHandler](params);
}
}
};
this.next = function(amount) {
if (amount === undefined) {
amount = 1;
}
that.current = (that.current + amount) % that.count;
while (amount--) {
for (var nextHandler in nextHandlers) {
nextHandlers[nextHandler](params);
}
}
};
this.getCurrent = function() {
return that.elements[that.current];
};
this.setCurrent = function(current) {
for (var index in that.elements) {
if (that.elements[index] === current) {
that.current = index;
return true;
}
}
return false;
};
this.pushElement = function(element) {
that.elements.push(element);
};
this.pushElements = function(elements) {
for (var element in elements) {
that.pushElement(elements[element]);
}
};
this.insertElement = function(element, index) {
that.elements.splice(index, 0, element);
};
this.insertElements = function(elements, indexes, leftToRight) {
var start = 0;
var end = indexes.length - 1;
if (leftToRight === false) {
var aux = start;
start = end;
end = aux;
}
var leap = (start < end) ? 1 : -1;
while (start - leap !== end) {
that.insertElement[elements[indexes[start]]];
start += leap;
}
};
this.popElement = function() {
that.elements.pop();
};
this.popElements = function(amount) {
that.elements.splice(that.elements.length - amount, amount);
};
this.removeElement = function(index) {
that.elements.splice(index, 1);
};
this.removeElements = function(indexes, leftToRight) {
var start = 0;
var end = indexes.length - 1;
if (leftToRight === false) {
var aux = start;
start = end;
end = aux;
}
var leap = (start < end) ? 1 : -1;
while (start - leap !== end) {
that.removeElement(indexes[start]);
start += leap;
}
};
this.register = {
prev: function(param) {
if (Array.isArray(param)) {
for (var func in param) {
prevHandlers.push(param[func]);
}
} else {
prevHandlers.push(param);
}
},
next: function(param) {
if (Array.isArray(param)) {
for (var func in param) {
nextHandlers.push(param[func]);
}
} else {
nextHandlers.push(param);
}
}
};
this.setElements(params.elements);
if ((!!this.current) && (!Array.isArray(params.elements))) {
this.setCurrent(params.elements[params.current]);
}
}
The second is Visiblary
, which is designed to handle all kinds of visibility events:
/*
* params:
* - selector: jQuery selector
* - init: function which gets the Visiblary object to initialize it
* - events: object/array
* - root: a selector which contain all the affected tags, default is "body"
* - types: array, which contains the string representation of the events
* - selector: inner selector to identify the target set
* - handler: handler function
*/
function Visiblary(params) {
var instance = this;
if (!params.toggleClass) {
params.toggleClass = "invisible";
}
this.hideAll = function() {
$(params.selector).addClass(params.toggleClass);
return instance;
};
this.hideSubset = function(subsetSelector) {
$(params.selector).filter(subsetSelector).addClass(params.toggleClass);
return instance;
};
this.hideOnly = function(subsetSelector) {
$(params.selector).not(subsetSelector).removeClass(params.toggleClass);
$(params.selector).filter(subsetSelector).addClass(params.toggleClass);
return instance;
};
this.showAll = function() {
$(params.selector).removeClass(params.toggleClass);
return instance;
};
this.showSubset = function(subsetSelector) {
$(params.selector).filter(subsetSelector).removeClass(params.toggleClass);
return instance;
};
this.showOnly = function(subsetSelector) {
$(params.selector).not(subsetSelector).addClass(params.toggleClass);
$(params.selector).filter(subsetSelector).removeClass(params.toggleClass);
return instance;
};
this.invert = function() {
$(params.selector).each(function() {
$(this).hasClass(params.toggleClass) ? $(this).removeClass(params.toggleClass) : $(this).addClass(params.toggleClass);
});
return instance;
};
if (!!params.init) {
params.init(this);
}
if (!!params.events) {
for (var event in params.events) {
$(!!params.events[event].root ? params.events[event].root : "body").on(params.events[event].types.join(" "), params.events[event].selector, params.events[event].handler);
}
}
return instance;
}
And, assuming that one uses these tools and the seven elements are already created, this is the script which solves the issue:
var myVisiblary = new Visiblary({
selector: "#content-1, #content-2, #content-3, #content-4, #content-5, #content-6, #content-7"
});
myVisiblary.showOnly("#content-1");
var myIterable = new Iterable({
elements: $("#content-1, #content-2, #content-3, #content-4, #content-5, #content-6, #content-7"),
current: 0
});
myIterable.register.next(function() {myVisiblary.showOnly($(myIterable.getCurrent()))});
setInterval(function(){ myIterable.next(); }, 5000);