// -----------------------------------------------------------------------------------
// ImageSlider v1.6
// by Travis Beck - http://wholewheatcreative.com
// Last Modification: 12/29/08
//
//	
// Requires MooTools v1.2 - http://mootools.net/
//
// =========USAGE=========
// var mySlider = new ImageSlider({
//    objToSlide: 'sliderHolder',            //REQUIRED (String)   - The id of the holder element that will be sliding
//    sliderElements: 'div',                 //REQUIRED (String)   - The type of elements contained within the slider can be any html element(div, p, a, span)
//    numOfElementsToSlide: 2,               //OPTIONAL (Number)   - Number of elements to slide
//    leftBtn: 'slideLeftBtn',               //REQUIRED (String)   - The ID of the element that when clicked will slide your imageslider left
//    rightBtn: 'slideRightBtn',             //REQUIRED (String)   - The ID of the element that when clicked will slide your imageslider right
//    easing: Fx.Transitions.Expo.easeInOut, //OPTIONAL (Function) - The type of easing to use on transition (more info on easing http://mootools.net/docs/Fx/Fx.Transitions#Fx-Transitions)
//    useMouseWheel: true							//OPTIONAL (Boolean)  - Whether or not the mouse wheel scrolls when over the section
//    onSlideComplete: function(index){      //OPTIONAL (Function) - Callback Function to fire once sliding is completed. returns index.
//       //index is the current position
//    },
//		isHorizontal: true							//OPTIONAL (boolean)	 -  Set to false in order to allow vertical functionality.			
// });
// 
// =========PUBLIC FUNCTIONS=========
// mySlider.slideTo(position:Number);
//
// Slides to the position provided. 
// Position is the number of the element you want to slide to
//
// =========CALLBACKS=========
// onSlideComplete(index:Number)
//
// Called after the slide animation has completed
// -----------------------------------------------------------------------------------

var ImageSlider = new Class(
		{
			Implements : [ Options, Events ],
			options : {
				objToSlide :'',
				objContainer :'',
				sliderElements :'', /* can be any html element (div, p, a, span) */
				numOfElementsToSlide :2, /*
											 * this is the number of elements
											 * that slide when the button is hit
											 */
				numOfElementsShown :0, /*
										 * this is the total number of elements
										 * shown at any give time
										 */
				leftBtn :'',
				rightBtn :'',
				isHorizontal :true,
				easing :Fx.Transitions.Expo.easeInOut,
				useMouseWheel :true
			// onSlideComplete: $empty
			},
			initialize : function(options) {
				this.setOptions(options);
				this.options.objToSlide = $(this.options.objToSlide);
				this.options.objContainer = $(this.options.objContainer);
				if (!(this.options.objToSlide)) {
					return false;
				}// do nothing
				this.setup();
			},

			setup : function() {
				var o = this.options;
				o.sliderElements = (o.objToSlide.getElements(o.sliderElements));
				if (!(o.sliderElements.length > 0)) {
					return false;
				}// do nothing
				o.leftBtn = $(o.leftBtn);
				o.rightBtn = $(o.rightBtn);
				if (o.sliderElements.length < o.numOfElementsShown+1) {
					o.leftBtn.hide();
					o.rightBtn.hide();
				}
				o.objToSlide.setStyles( {
					position :'relative',
					left :0
				});
				var element = $(o.sliderElements[0]);
				var margins = parseFloat(element.getStyle('margin-left'))
						+ parseFloat(element.getStyle('margin-right'));
				var marginsV = parseFloat(element.getStyle('margin-top'))
						+ parseFloat(element.getStyle('margin-bottom'));
				var size = element.getSize();
				o.elementWidth = size.x + margins;
				o.elementHeight = size.y + marginsV;
				var maskDim = o.objToSlide.getParent().getSize();
				o.objToSlide.getParent().setStyle('overflow', 'hidden');
				if (o.isHorizontal) {
					o.objToSlide.setStyle('width',
							(o.elementWidth * o.sliderElements.length));
					o.numOfElementsShown = Math.floor(maskDim.x
							/ o.elementWidth);
				} else {
					o.objToSlide.setStyle('height',
							(o.elementHeight * o.sliderElements.length));
					o.numOfElementsShown = Math.ceil(maskDim.y
							/ o.elementHeight);
				}
				o.index = 0;
				o.total = o.sliderElements.length - o.numOfElementsShown;
				o.totalMoves = -(o.total / o.numOfElementsToSlide);
				o.myFx = new Fx.Morph(o.objToSlide, {
					duration :500,
					transition :o.easing,
					link :'chain'
				});
				if (o.leftBtn) {
					o.leftBtn.addEvents({
						'click':function(){
							this.autoSlide = this.leftClick();
						}.bind(this),
						'mousedown':function(){
							this.autoSlide = this.leftClick.periodical(500, this);
						}.bind(this),
						'mouseup':function(){
							$clear(this.autoSlide);					
						}.bind(this)
					});
				}
				if (o.rightBtn) {
					o.rightBtn.addEvents({
						'click':function(){
							this.autoSlide = this.rightClick();
						}.bind(this),
						'mousedown':function(){
							this.autoSlide = this.rightClick.periodical(500, this);
						}.bind(this),
						'mouseup':function(){
							$clear(this.autoSlide);					
						}.bind(this)
					});
				}
				if (o.useMouseWheel) {
					o.objContainer.addEvent('mousewheel', this.mouseWheel
							.bindWithEvent(this));
				}
				this.fireEvent('onSlideComplete', {
					index :this.getAbsIndex(),
					total :this.options.sliderElements.length
				});
			},

			mouseWheel : function(e) {
				e.stop(); // prevent the mousewheel from scrolling the page.
				if (e.wheel < 0) {
					this.rightClick();
				} else {
					this.leftClick();
				}
			},

			leftClick : function(e) {
				if (e) {
					e.stop();
				}
				if (this.sliding) {
					return;
				}
				var o = this.options;
				var newPos;
				o.index += 1;
				if (o.isHorizontal) {
					if (o.index < 0) {
						newPos = (o.elementWidth * o.numOfElementsToSlide)
								* o.index;
					} else {
						o.index = 0;
						newPos = 0;
					}
				} else {
					if (o.index < 0) {
						newPos = (o.elementHeight * o.numOfElementsToSlide)
								* o.index;
					} else {
						o.index = 0;
						newPos = 0;
					}
				}
				this.slide(newPos);
			},

			rightClick : function(e) {
				if (e) {
					e.stop();
				}
				if (this.sliding) {
					return;
				}
				var o = this.options;
				var newPos;
				o.index -= 1;
				if (o.isHorizontal) {
					if (o.index >= o.totalMoves) {
						newPos = (o.elementWidth * o.numOfElementsToSlide)
								* o.index;
					} else {
						o.index = o.totalMoves;
						newPos = (o.elementWidth * o.numOfElementsToSlide)
								* o.index;
					}
				} else {
					if (o.index >= o.totalMoves) {
						newPos = (o.elementHeight * o.numOfElementsToSlide)
								* o.index;
					} else {
						o.index = o.totalMoves;
						newPos = (o.elementHeight * o.numOfElementsToSlide)
								* o.index;
					}
				}
				this.slide(newPos);
			},

			slide : function(newPos) {
				var o = this.options;
				var cur = (o.isHorizontal) ? (o.objToSlide
						.getCoordinates(o.objToSlide.getParent()).left)
						: (o.objToSlide
								.getCoordinates(o.objToSlide.getParent()).top);
				if (cur == newPos) {
					return false;
				}
				this.sliding = true;
				if (this.options.isHorizontal) {
					this.options.myFx.start( {
						'left' :newPos
					}).chain( function() {
						this.sliding = false;
						this.fireEvent('onSlideComplete', {
							index :this.getAbsIndex(),
							total :this.options.sliderElements.length
						});
					}.bind(this));
				} else {
					this.options.myFx.start( {
						'top' :newPos
					}).chain( function() {
						this.sliding = false;
						this.fireEvent('onSlideComplete', {
							index :this.getAbsIndex(),
							total :this.options.sliderElements.length
						});
					}.bind(this));
				}
			},

			slideTo : function(pos) {
				if ($type(pos) != "number") {
					return false;
				}
				var o = this.options;
				pos = pos + 1;
				var newPos;
				if (pos <= o.numOfElementsShown) {
					o.index = 0;
				} else {
					o.index = -(((pos - o.numOfElementsShown) / o.numOfElementsToSlide));
				}
				if (o.isHorizontal) {
					if (o.index >= o.totalMoves) {
						newPos = ((o.elementWidth * o.numOfElementsToSlide) * o.index)
								.round();
					} else {
						o.index = o.totalMoves;
						newPos = ((o.elementWidth * o.numOfElementsToSlide) * o.index)
								.round();
					}
				} else {
					if (o.index >= o.totalMoves) {
						newPos = (o.elementHeight * o.numOfElementsToSlide)
								* o.index;
					} else {
						o.index = o.totalMoves;
						newPos = (o.elementHeight * o.numOfElementsToSlide)
								* o.index;
					}
				}
				this.slide(Math.min(0, newPos));
			},

			getAbsIndex : function() {
				return (Math.abs(this.options.index) + 1);
			}

		});

