;(function(factory) {
if(typeof define === 'function' && define.amd) {
define(['jquery'], factory);
}
else if(typeof exports === 'object') {
module.exports = factory(require('jquery'));
}
else {
factory(jQuery);
}
}
(function($) {
var pluginName = "tinycarousel"
, defaults =
{
start: 0
, axis: "Y" /* vertical horizontal */
, buttons: true
, bullets: true
, interval: true /* ativa modo automatico */
, intervalTime: 3000
, animation: true
, animationTime: 1000
, infinite: true
}
;
function Plugin($container, options) {
/**
* The options of the carousel extend with the defaults.
*
* @property options
* @type Object
* @default defaults
*/
this.options = $.extend({}, defaults, options);
/**
* @property _defaults
* @type Object
* @private
* @default defaults
*/
this._defaults = defaults;
/**
* @property _name
* @type String
* @private
* @final
* @default 'tinycarousel'
*/
this._name = pluginName;
var self = this
, $viewport = $container.find(".viewport:first")
, $overview = $container.find(".overview:first")
, $slides = null
, $next = $container.find(".next:first")
, $prev = $container.find(".prev:first")
, $bullets = $container.find(".bullet")
, viewportSize = 0
, contentStyle = {}
, slidesVisible = 0
, slideSize = 0
, slideIndex = 0
, isHorizontal = this.options.axis === 'x'
, sizeLabel = isHorizontal ? "Width" : "Height"
, posiLabel = isHorizontal ? "left" : "top"
, intervalTimer = null
;
/**
* The index of the current slide.
*
* @property slideCurrent
* @type Number
* @default 0
*/
this.slideCurrent = 0;
/**
* The number of slides the carousel is currently aware of.
*
* @property slidesTotal
* @type Number
* @default 0
*/
this.slidesTotal = 0;
/**
* If the interval is running the value will be true.
*
* @property intervalActive
* @type Boolean
* @default false
*/
this.intervalActive = false;
/**
* @method _initialize
* @private
*/
function _initialize() {
self.update();
self.move(self.slideCurrent);
_setEvents();
return self;
}
/**
* You can use this method to add new slides on the fly. Or to let the carousel recalculate itself.
*
* @method update
* @chainable
*/
this.update = function() {
$overview.find(".mirrored").remove();
$slides = $overview.children();
viewportSize = $viewport[0]["offset" + sizeLabel];
slideSize = $slides.first()["outer" + sizeLabel](true);
self.slidesTotal = $slides.length;
self.slideCurrent = self.options.start || 0;
slidesVisible = Math.ceil(viewportSize / slideSize);
$overview.append($slides.slice(0, slidesVisible).clone().addClass("mirrored"));
$overview.css(sizeLabel.toLowerCase(), slideSize * (self.slidesTotal + slidesVisible));
_setButtons();
return self;
};
/**
* @method _setEvents
* @private
*/
function _setEvents() {
if(self.options.buttons) {
$prev.click(function() {
self.move(--slideIndex);
return false;
});
$next.click(function() {
self.move(++slideIndex);
return false;
});
}
$(window).resize(self.update);
if(self.options.bullets) {
$container.on("click", ".bullet", function() {
self.move(slideIndex = +$(this).attr("data-slide"));
return false;
});
}
}
/**
* If the interval is stoped start it.
*
* @method start
* @chainable
*/
this.start = function() {
if(self.options.interval) {
clearTimeout(intervalTimer);
self.intervalActive = true;
intervalTimer = setTimeout(function() {
self.move(++slideIndex);
}, self.options.intervalTime);
}
return self;
};
/**
* If the interval is running stop it.
*
* @method start
* @chainable
*/
this.stop = function() {
clearTimeout(intervalTimer);
self.intervalActive = false;
return self;
};
/**
* Move to a specific slide.
*
* @method move
* @chainable
* @param {Number} [index] The slide to move to.
*/
this.move = function(index) {
slideIndex = isNaN(index) ? self.slideCurrent : index;
self.slideCurrent = slideIndex % self.slidesTotal;
if(slideIndex < 0) {
self.slideCurrent = slideIndex = self.slidesTotal - 1;
$overview.css(posiLabel, -(self.slidesTotal) * slideSize);
}
if(slideIndex > self.slidesTotal) {
self.slideCurrent = slideIndex = 1;
$overview.css(posiLabel, 0);
}
contentStyle[posiLabel] = -slideIndex * slideSize;
$overview.animate(
contentStyle
, {
queue : false
, duration : self.options.animation ? self.options.animationTime : 0
, always : function() {
/**
* The move event will trigger when the carousel slides to a new slide.
*
* @event move
*/
$container.trigger("move", [$slides[self.slideCurrent], self.slideCurrent]);
}
});
_setButtons();
self.start();
return self;
};
/**
* @method _setButtons
* @private
*/
function _setButtons() {
if(self.options.buttons && !self.options.infinite) {
$prev.toggleClass("disable", self.slideCurrent <= 0);
$next.toggleClass("disable", self.slideCurrent >= self.slidesTotal - slidesVisible);
}
if(self.options.bullets) {
$bullets.removeClass("active");
$($bullets[self.slideCurrent]).addClass("active");
}
}
return _initialize();
}
/**
* @class tinycarousel
* @constructor
* @param {Object} options
@param {Number} [options.start=0] The slide to start with.
@param {String} [options.axis=x] Vertical or horizontal scroller? ( x || y ).
@param {Boolean} [options.buttons=true] Show previous and next navigation buttons.
@param {Boolean} [options.bullets=false] Is there a page number navigation present?
@param {Boolean} [options.interval=false] Move to another block on intervals.
@param {Number} [options.intervalTime=3000] Interval time in milliseconds.
@param {Boolean} [options.animate=true] False is instant, true is animate.
@param {Number} [options.animationTime=1000] How fast must the animation move in ms?
@param {Boolean} [options.infinite=true] Infinite carousel.
*/
$.fn[pluginName] = function(options) {
return this.each(function() {
if(!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin($(this), options));
}
});
};
}));
|