/* # Carousel 1.8 [jQuery plugin for 1.3+] # # Copyright (C) 2010 - Snapper Net Solutions | www.snapper.no # # Usage: # $('#yourcarousel').carousel() # # > where #yourcarousel points to your ul containing one li per item to be displayed # # 1.2 adds fade as a transition mode # 1.3 is rewritten to be more robust when used with other plugins # 1.4 adds optional < and > (prev, next) # 1.5 adds new mode, circle, which just circles around (slide) # 1.6 adds new mode, noloop, as well as possibility of using custom functions for buttons/tickbox # 1.7 adds new transition, dissolve # 1.8 adds play() function # Modes: # noloop > 1, 2, 3, 4 (doesn't loop) # restart > 1, 2, 3, 4 < 1, 2, 3, 4 (snaps rapidly back to first when finished) # circle > 1, 2, 3, 4, 1, 2, 3, 4 */ (function($) { $.fn.carousel = function(options) { var self = this; self.current = 0; self.previous = 0; self.items = []; self.itemw = 0; self.fullw = 0; self.timer = null; self.locked = false; self.animating = false; var obj = $(this); var defaults = { auto: 0, pos: 0, mode: 'restart', transmode: 'slide', transition: 1.0, tickbox: false, buttons: '' }; // Get parameters self.options = $.extend({}, defaults, options); self.options.auto = self.options.auto * 1000; self.options.transition = self.options.transition * 1000; // // Public methods // this.prev = function() { if (self.locked == true || self.animating == true) return false; // Remember previous object id self.previous = self.current; self.current--; self._animate(self.current); }; this.next = function() { if (self.locked == true || self.animating == true) return false; // Remember previous object id self.previous = self.current; self.current++; self._animate(self.current); }; this.goto = function(n, noanim) { if (self.locked == true || self.animating == true || self.current == n) return false; // Remember previous object id self.previous = self.current; self.current = n; self._animate(self.current, noanim); }; this.stop = function() { clearInterval(self.timer); self.timer = null; }; this.play = function() { clearInterval(self.timer); self.timer = setInterval(function(){self.next()}, self.options.auto); } this.clicked = function(el) { self.stop(); if ($(el).hasClass('prev')) self.prev(); else self.next(); }; this.update_tickbox = function() { var ticknum = self.current; if (self.options.mode == 'circle' && self.current >= self.shownum) ticknum = 0; if (self.tickbox_method) { self.tickbox_method() } else { var tb = $('.tickbox', self.master); var ti = $('li', tb); ti.removeClass('active'); $(ti[ticknum]).addClass('active'); } }; // // Private methods // var _finished = function() { self.animating = false; if (self.options.tickbox) self.update_tickbox(); if (self.options.mode == 'circle') { if (self.current >= self.shownum) { self.current = 0; self.goto(0, true); } else if (self.current < 0) { self.current = self.shownum-1; self.goto(self.shownum-1, true); } } }; // Transition mode slide (default) var _slide = function(i, noanim) { _track_control(i); var cp = (self.options.mode == 'circle') ? self.current+1 : self.current; var pos = cp * self.itemw * -1; if (noanim == true) { var x = 0; self.css({left: pos}); _finished(); } else { self.animating = true; self.animate({left: pos, easing: 'swing'}, self.options.transition, function(){_finished()}); } }; var _fade = function(i, noanim) { _track_control(i); //if (self.current == self.previous) // return; if (noanim == true) var x = 0; else { self.animating = true; var pel = self.items[self.previous]; var nel = self.items[self.current]; $(pel).fadeOut(self.options.transition, function(){ $(nel).fadeIn(self.options.transition, function(){_finished()}) }); } }; var _dissolve = function(i, noanim) { _track_control(i); if (noanim == true) var x = 0; else { self.animating = true; var pel = self.items[self.previous]; var nel = self.items[self.current]; $(pel).css('z-index', 2); $(nel).css('z-index', 1).show(); $(pel).fadeOut(self.options.transition, function(){_finished()}); } } var _track_control = function(i) { if (self.options.mode == 'restart') { if (self.current >= self.items.length) self.current = 0; else if (self.current < 0) self.current = self.items.length - 1; } else if (self.options.mode == 'circle') { if (self.current >= self.items.length) self.current = self.items.length - 1; else if (self.current < -1) self.current = -1; } else if (self.options.mode == 'noloop') { if (self.current <= 0) self.current = 0; else if (self.current >= self.items.length) self.current = self.current-1; } else { if (self.current >= self.items.length) self.current = self.items.length - 1; else if (self.current < 0) self.current = 0; } }; // Set up return this.each( function() { self.master = $(this).parent(); self.items = $('ul:first-child > li', self.master); self.itemw = $(self.items[0]).width(); self.fullw = self.items.length * self.itemw; self.shownum = self.items.length; var li_css = {width: self.itemw}; // Adjust to circle mode if (self.options.mode == 'circle') { var pref = $(self.items[0]).clone(); var suff = $(self.items[self.items.length-1]).clone(); pref.appendTo(this); suff.prependTo(this); self.items.push(pref[0]); self.items.push(suff[0]); self.fullw += (self.itemw*2); } // Set transition mode switch (self.options.transmode) { case "fade": self.fullw = self.itemw; li_css.position = 'absolute'; li_css.display = 'none'; self._animate = _fade; break; case "dissolve": self.fullw = self.itemw; li_css.position = 'absolute'; li_css.display = 'none'; self._animate = _dissolve; $.each(self.items, function(n){$(this).css('z-index', 1+n)}); break; default: self._animate = _slide; if (self.options.mode == 'circle') self.css({left: self.itemw*-1}); break; } $.each(self.items, function(){$(this).css(li_css)}); $('li:first-child', this).css('display', 'block') $(this).addClass('lime_carousel').css('width', self.fullw); if (self.options.auto && self.items.length > 1) self.timer = setInterval(function(){self.next()}, self.options.auto); // Do we need to add any buttons? if (self.options.buttons) { if (typeof(self.options.buttons) == 'function') { self.options.buttons(self); } else { self.master.append(''); $('.button', self.master).click(function(){self.clicked(this)}); } } if (typeof(self.options.tickbox) == 'function') { self.options.tickbox(self); self.options.tickbox = true; } // Do we need to add status pointers if (self.options.tickbox && !self.tickbox_method) { if (!self.shownum) return; var html = '
  •  
  • '; var il = self.shownum; for (var i=1; i < il; i++) { html += '
  •  
  • '; } self.master.append(''); var tb = $('.tickbox', self.master); $('li', tb).click(function(){self.stop(); self.goto($(this).attr('value'))}); } }); }; })(jQuery);