Skip to content

Instantly share code, notes, and snippets.

@donut
Created October 21, 2011 05:15
Show Gist options
  • Save donut/1303150 to your computer and use it in GitHub Desktop.
Save donut/1303150 to your computer and use it in GitHub Desktop.
Basic jQuery carousel plugin
/** A carousel plugin
@author Donovan Mueller ([email protected])
@url https://gist.github.com/1303150
------------------------------------------------------------------------ */
;(function donutCarouselPlugin($){
var $methods = {}
, $settings = { frameSelector: '.slides'
, listSelector: 'ul'
// Assumed to be a child of `frameSelctor`.
// The list of slides will be built from the direct
// descendents of this list.
, axis: 'x'
// The axis the slides travel on.
, delay: 10000
// Milliseconds between slides
, transDuration: 600
// Milliseconds used for animating the transition
// between slides.
, transEasing: 'swing'
, hideRestart: true
// Whether or not to hide going back to the first
// slide.
, createPosMarkers: 'pos_markers' };
// The class name to be used for creating position
// markers. If left blank or set to `false` markers
// will not be created.
$methods.init = function(settings)
{
this.each(function forEachElement()
{
var $this = $(this)
, data = $this.data('donutCarousel')
, markers, markerList, first;
if (!data) {
data = {};
if ($.isPlainObject(settings) === false) {
settings = {};
}
data.settings = $.extend({}, $settings, settings);
data.frame = $(data.settings.frameSelector);
data.list = data.frame.children(data.settings.listSelector);
data.items = data.list.children();
if (!data.items.length) {
$this.data('donutCarousel', false);
return;
}
var listWidth = 0;
data.items.each(function addWidth(){
listWidth += $(this).outerWidth(true);
});
data.frame.css({position: 'relative', overflow: 'hidden'});
data.list.css({ position: 'absolute'
, top: 0, left: 0
, width: listWidth });
// Create position markers
if ( data.settings.createPosMarkers &&
data.settings.createPosMarkers.length )
{
markers = $('<nav/>')
.addClass(data.settings.createPosMarkers);
markerList = $('<ol/>').appendTo(markers);
for (var s = 1; s <= data.items.length; ++s) {
$('<li/>')
.append('<button type="button">' + s + '</button>')
.appendTo(markerList);
}
$this.append(markers);
data.posMarkers = markerList.children();
markers.on('click', 'button', function onPosMarkerClick(){
data.list.stop().fadeIn(0);
$this.donutCarousel('goto', $(this).parent().index());
});
data.posMarkers.eq(0).addClass('active');
}
// Pause slideshow on hover
data.frame.hover(
function onMouseOver(){
$this.donutCarousel('stop');
},
function onMouseOut(){
$this.donutCarousel('play');
}
);
$this.data('donutCarousel', data);
first = Math.floor(Math.random() * data.items.length);
$this.donutCarousel('goto', first, true);
}
}); // for each element
this.donutCarousel('stop')
.donutCarousel('play');
return this;
}; // .init()
$methods.play = function()
{
this.each(function forEachElement()
{
var $this = $(this)
, data = $this.data('donutCarousel');
if (!data) {
if (data !== false) $this.donutCarousel();
return;
}
data.interval = setInterval(function gotoNextSlide(){
$this.donutCarousel('next');
}, data.settings.delay);
$this.data('donutCarousel', data);
}); // for each element
return this;
}; // .play()
$methods.stop = function()
{
this.each(function forEachElement()
{
var $this = $(this)
, data = $this.data('donutCarousel');
if (!data) {
if (data !== false) $this.donutCarousel();
return;
}
clearInterval(data.interval);
data.interval = null;
$this.data('donutCarousel', data);
}); // for each element
return this;
}; // .stop()
$methods.next = function()
{ /* Goes to next slide */
this.each(function forEachElement()
{
var $this = $(this)
, data = $this.data('donutCarousel')
, next;
if (!data) {
if (data !== false) $this.donutCarousel();
return;
}
next = (data.activeSlide) ?
data.activeSlide.next() : data.items.eq(1);
next = (next.length) ? next.index() : 0;
if (data.settings.hideRestart && next === 0) {
data.list.fadeOut( (data.settings.transDuration)
, function afterhide(){
$this.donutCarousel('goto', next, true, false);
} )
.fadeIn(data.settings.transDuration);
}
else {
$this.donutCarousel('goto', next);
}
}); // for each element
return this;
}; // .next()
$methods.goto = function(index, instantly, correctOpacity)
{ /* Goes to passed slide */
instantly = instantly || false;
this.each(function forEachElement()
{
var $this = $(this)
, data = $this.data('donutCarousel')
, slide, css;
if (!data) {
if (data !== false) $this.donutCarousel();
return;
}
slide = data.items.eq(index);
if (!slide.length) return;
css = (data.settings.axis === 'x')
? {left: ( -slide.position().left - slide.outerWidth(true) +
data.frame.width() ) + 'px'}
: {top: (-slide.position().top) + 'px'}
if (instantly) {
data.list.css(css);
}
else {
data.list.stop().animate( css, data.settings.transDuration
, data.settings.transEasing );
}
if (correctOpacity !== false) {
data.list.fadeTo(1, 1);
}
// Mark the related position marker as active.
if (data.posMarkers) {
data.posMarkers.not(':eq('+index+')')
.removeClass('active');
data.posMarkers.eq(index)
.addClass('active');
}
data.activeSlide = slide;
$this.data('donutCarousel', data);
// Restart interval timer if already playing. This prevents changing to
// the next slide right after the user chose to go to a specific slide.
if (data.interval !== null) {
$this.donutCarousel('stop').donutCarousel('play');
}
}); // for each element
return this;
}; // .goto()
$.fn.donutCarousel = function(method)
{
// Method calling logic
if ($methods[method]) {
return $methods[method]
.apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return $methods.init.apply(this, arguments);
}
else {
$.error( 'Method `' + method + '` does not exist on ' +
'jQuery.donutCarousel' );
}
}; // $.fn.donutCarousel()
})(jQuery); // (donutCarouselPlugin)()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment