Code:
/*
* jQuery UI Labs - Carousel
* - for experimental use only -
*
* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* Depends:
* ui.core.js
* effects.core.js
*/
(function($){
if(!window.console){
window.console = {log: function(){}};
}
$.widget("ui.carousel", {
_init: function() {
var self = this, timer, ttop, tleft;
//Prepare animation parameters and needed variables
this.items = $(this.options.items, this.element).css({ position: "absolute", top: 0, left: 0, zIndex: 1 });
this.items.bind('click.carousel', function(){
self.foreItem = self.items.index(this);
var $this = $(this);
clearInterval(timer);
ttop = ttop || self.items.eq(0).position().top + 0.5; //record where the top of an item should be to be in the bottom center
tleft = tleft || self.items.eq(0).position().left; //record a demarcation of which side of the carousel an item is on
if(Math.abs(Math.round($this.position().top) - ttop) < 1){return;} //it's already there, so stop
var direction = $this.position().left < tleft? 'right' : 'left';
timer = setInterval(function(){
if(Math.abs(Math.round($this.position().top) - ttop) < 1){
clearInterval(timer);
console.log($this.position().top +' - '+ttop);//for diagnostics
var count = direction === 'right'? 5 : 4;
timer = setInterval(function(){ //attempt at a fudge to get the item more nearly in its desired place:
if(!--count){
clearInterval(timer);
console.log($this.position().top +' - '+ttop); //for diagnostics
return;
}
self.rotate(direction, self.speed);
}, 1);
return;
}
self.rotate(direction, self.speed);
}, 1);
});
$('#stepList li').css({cursor: 'pointer'}).bind('click.carousel', function(){
var step = $('#stepList li').index(this) + 1, il = self.items.length;
self.items.eq(((self.foreItem || 0) - step + il) % il).trigger('click.carousel');
});
$.extend(this, {
props: this.options.orientation == 'vertical' ? ['height', 'Height', 'top', 'Top'] : ['width', 'Width', 'left', 'Left'],
start: Math.PI/2,
speed: 0.03, //We need a default spead so the initialization works
direction: 'left', //This is a live property, toggled during interaction
step: 2*Math.PI/this.items.length,
paddingX: this.element.outerWidth() / 2,
paddingY: this.element.outerHeight() / 2,
itemHeight: this.options.height || this.items.height(),
itemWidth: this.options.width || this.items.width(),
offset: this.element.offset()
});
//Add pause/resume functionality when you hover a item
if(this.options.pausable) {
this.items
.bind('mouseenter.carousel', function() { self.pause(); })
.bind('mouseout.carousel', function() { self.resume(); });
}
//Little trick to jump to the start position
this.rotate("left"); this.rotate("right");
//Auto animation for the carousel
if(this.options.animate)
self._startAnimation();
$(this.options.handle || this.element)
.bind('mouseenter.carousel', function() {
self.offset = self.element.offset();
})
.bind('mouseleave.carousel', function() {
self.options.animate ? self._startAnimation() : self.interval && clearInterval(self.interval);
})
.bind("mousemove.carousel", function(e) {
if(self.paused || !self.options.animateByMouse) return;
var mod = ((e[self.options.orientation == 'vertical' ? 'pageY' : 'pageX']-self.offset[self.props[2]]) - this['offset'+self.props[1]]/2);
self.speed = Math.abs(mod)/5000;
self.direction = mod < 0 ? "right" : "left";
});
},
_setData: function(key, value) {
$.widget.prototype._setData.apply(this, arguments);
if(key == 'height') this.itemHeight = value;
if(key == 'width') this.itemWidth = value;
},
destroy: function() {
clearInterval(this.interval);
this.element.unbind('.carousel');
var self = this;
window.setTimeout(function() {
self.items.css({ left: '', top: '', position: '', height: '', width: '' }).unbind('.carousel');
self.element.removeData('carousel');
}, 0);
},
_startAnimation: function() {
var self = this;
this.speed = self.options.animate;
this.interval && clearInterval(this.interval);
this.interval = window.setInterval(function() { self.rotate(); }, 13);
},
resume: function() {
this.paused = false;
this.options.animate && this._startAnimation();
this._trigger('resume');
},
pause: function() {
var self = this;
this.paused = true;
this.options.pauseSpeed ? (this.speed = self.options.pauseSpeed) : (this.interval && clearInterval(this.interval));
this._trigger('pause');
},
select: function(item) {
this.currentItem = !isNaN(parseInt(item,10)) ? parseInt(item,10) : this.items.index(item);
this.start = Math.PI/2;
this.rotate('left', this.step * item);
this._trigger('select', null, {
value: item,
item: this.items[item]
});
},
rotate: function(direction, speed) {
var o = this.options, self = this;
direction = direction || this.direction;
this.speed = speed !== undefined ? speed : this.speed;
this.start = this.start + (direction == "right" ? -this.speed : this.speed);
self.items.each(function(i) {
//var x = Math.min(0, self.options.radius * Math.cos(angle)); w00t! this makes a half carousel
var angle = self.start + i * self.step,
x = self.options.radius * Math.cos(angle),
y = self.options.tilt * Math.sin(angle),
width = Math.max(self.itemWidth - (o.distance * self.itemWidth), self.itemWidth * ((self.options.tilt+y) / (2 * self.options.tilt))),
height = parseInt(width * self.itemHeight / self.itemWidth,10);
$.extend(this.style, {
top: self.paddingY + (self.options.orientation == 'vertical' ? x : y) - height/2 + "px",
left: self.paddingX + (self.options.orientation == 'vertical' ? y : x) - width/2 + "px",
width: width + "px",
height: height + "px",
zIndex: parseInt(100 * (self.options.tilt+y) / (2 * self.options.tilt),10)
});
});
}
});
$.extend($.ui.carousel, {
defaults: {
animate: 0, //TODO: Setting animate to false also currently blocks animateByMouse
animateByMouse: false,
distance: 0.7,
handle: false,
items: '> *',
orientation: 'horizontal',
pausable: false,
pauseSpeed: 0, //If you don't want to actually stop the carousel when hovering items, set it to something small, i.e. 0.001
radius: 200,
tilt: 125
}
});
})(jQuery);
Bookmarks