// ==ClosureCompiler==
// @compilation_level SIMPLE_OPTIMIZATIONS
// @output_file_name jquery.contentCarousel-0.1.min.js
// ==/ClosureCompiler==

/*============================================================
	Content Carousel
	
	new ContentCarouselClass('#bannerContainer', {options});
	
	Options:
		width: 		width of banner (default: to container's outer width)
		height:		height of banner (default: container's outer height)
		panelClass: class name of banner panels (default: 'ccPanel')
		delayTime:	time to delay on each panel in seconds, not used for continuous slides (default: 5)
		transitionTime: time for one panel to transition in seconds (default: 1)
		transitionType: style of transition, 'step' or 'continuous' (default: 'step')
		direction:  direction of transition, 'horizontal' or 'vertical' (default: 'horizontal')

	<div id="bannerContainer">
		<div class="ccPanel">
			Any html content here.
		</div>
		<div class="ccPanel">
			HTML content for the next panel.
		</div>	
	</div>
	
	
============================================================*/
function ContentCarouselClass(container, optionObj) {

	
	this.container = $(container);
	this.container_name = (this.container.attr('id') !== undefined)?this.container.attr('id'):'carousel'+ new Date().getTime();
	
	this.option = $.extend({
		height: this.container.outerHeight(),
		width: this.container.outerWidth(),
		panelClass: 'ccPanel',
		delayTime: 7,
		transitionTime: 0.5,
		animationType: 'slide', // 'slide'|'fade'
		transitionType: 'step', // 'step'|'continuous'
		direction: 'horizontal', // 'horizontal'|'vertical'
		autoSlide: true,
		showControl: true,
		showSlideNumbers: true,
		showArrows: true,
		slideStart:function(carousel){},
		slideComplete: function (carousel, currentSlide) { },
		isSyncronised: false,
		
		controlCSS:{position:'absolute',right:30,bottom:10,height:30},
		controlButtonCSS:{width:18,height:24,margin:3,padding:'0 3px','float':'left',background:'#FFF',cursor:'pointer','text-align':'right',color:'#1583C8','font-weight':'bold',
					'border-radius':3, '-moz-border-radius':3, '-webkit-border-radius':3 },
		controlButtonSelectCSS:{background:'#1583C8',color:'#FFF'},
		controlArrowLeftCSS:{position:'absolute', left:-18, top:6, height:18, width:18,
					 background:"url('media/images/banner_arrows.png') left center no-repeat", cursor:'pointer'},
		controlArrowRightCSS:{position:'absolute', right:-18, top:6, height:18, width:18,
					 background:"url('media/images/banner_arrows.png') right center no-repeat", cursor:'pointer'}
	}, optionObj || {}, true);
	
	this.slideCount = 0;
	this.slideCurrent = 0;
	this.slidePrevious = 0;
	this.slideRotateIID = -1;
	this.height = this.option.height;
	this.width = this.option.width;
	this.isSyncronised = this.option.isSyncronised;
	this.animating = false;
	
	/*===================================================
		Build Carousel
	===================================================*/

	this.buildCarousel = function () {
		if (this.isSyncronised && $) {
			var isExisting = false;
			if (!$.syncronisedCarousels)
				$.syncronisedCarousels = [];
			for (var i = 0; i < $.syncronisedCarousels.length; i++) {
				if ($.syncronisedCarousels[i] == this) {
					var isExisting = true;
					break;
				}
			}
			if (!isExisting)
				$.syncronisedCarousels.push(this);
		}

		var i, ilen;

		this.container.css({ height: this.height, width: this.width, 'z-index': 1 }); //overflow:'hidden'
		if (this.container.css('position') !== 'relative' && this.container.css('position') !== 'absolute') { this.container.css('position', 'relative'); }
		$('.' + this.option.panelClass + ':first', this.container).clone().appendTo(this.container);

		this.containerMask = $('<div id="' + this.container_name + '_mask"></div>')
									.css({ position: 'relative', height: this.height, width: this.width, overflow: 'hidden' })
									.prependTo(this.container);

		this.panelContainer = $('<div id="' + this.container_name + '_pane"></div>')
									.css({ position: 'relative', overflow: 'hidden', height: this.height, width: this.width })
									.prependTo(this.containerMask);
		this.$panels = $('.' + this.option.panelClass, this.container)
									.css({ position: 'absolute', display: 'block', overflow: 'hidden', height: this.height, width: this.width })
									.appendTo(this.panelContainer);
		this.slideCount = this.$panels.length - 1;
		this.correctPanelsForPadding();

		if (this.option.transitionType !== 'continuous' && this.option.showControl) {
			this.controls = $('<div id="' + this.container_name.substr(1) + '_controls"></div>')
				.css(this.option.controlCSS)
			//.width(this.slideCount * 30)
				.appendTo(this.container);
			for (i = 0, ilen = this.slideCount; i < ilen; i++) {
				$('<div class="control control_' + i + '">' + ((this.option.showSlideNumbers) ? (i + 1) : '&nbsp;') + '</div>')
					.data('index', i)
					.css(this.option.controlButtonCSS)
					.bind('mouseenter', { cc: this }, function (e) { $(this).css(e.data.cc.option.controlButtonSelectCSS); })
					.bind('mouseleave', { cc: this }, function (e) { if (!$(this).hasClass('selected')) { $(this).css(e.data.cc.option.controlButtonCSS); } })
					.bind('click', { cc: this }, function (e) { e.data.cc.nextSlide($(this).data('index')); })
					.appendTo(this.controls);
			}

			if (this.option.showArrows) {
				this.arrowLeft = $('<div id="' + this.container_name.substr(1) + '_arrowLeft"></div>')
					.css(this.option.controlArrowLeftCSS)
					.hover(function () { $(this).css('opacity', 1); }, function () { $(this).css('opacity', 0.7); })
					.bind('click', { hcv: this }, function (e) { e.data.hcv.slidePrevious(); })
					.prependTo(this.controls);
				this.arrowRight = $('<div id="' + this.container_name.substr(1) + '_arrowRight"></div>')
					.css(this.option.controlArrowRightCSS)
					.hover(function () { $(this).css('opacity', 1); }, function () { $(this).css('opacity', 0.7); })
					.bind('click', { hcv: this }, function (e) { e.data.hcv.slideNext(); })
					.appendTo(this.controls);
			}
		}

		if (this.option.animationType == 'fade') {
			this.initFade();
		} else {
			this.initSlide();
		}

		this.setControls();

		this.container
			.bind('nextSlide', { cc: this }, function (e) { e.data.cc.slideNext(); })
			.bind('previousSlide', { cc: this }, function (e) { e.data.cc.slidePrevious(); });
	};
	
	
	this.initSlide = function() {

		if (this.option.direction == 'vertical') {
			this.panelContainer.width(this.width).height(this.height * (this.slideCount+1));
			this.$panels.each(function(i){ $(this).css({top:i*$(this).outerHeight(), left:0}); });
		} else {
			this.panelContainer.width(this.width * (this.slideCount+1)).height(this.height);
			this.$panels.each(function(i){ $(this).css({top:0, left:i*$(this).outerWidth()}); });
		}

		if (this.option.transitionType == 'step') {
			this.container
				.bind('mouseenter', {carousel:this}, function(e){ e.data.carousel.stopStepTimer(); })
				.bind('mouseleave', {carousel:this}, function(e){ e.data.carousel.startStepTimer(); });
			if (this.option.showArrows) {
				this.arrowLeft
					.bind('mouseenter', {carousel:this}, function(e){ e.data.carousel.stopStepTimer(); })
					.bind('mouseleave', {carousel:this}, function(e){ e.data.carousel.startStepTimer(); });
				this.arrowRight
					.bind('mouseenter', {carousel:this}, function(e){ e.data.carousel.stopStepTimer(); })
					.bind('mouseleave', {carousel:this}, function(e){ e.data.carousel.startStepTimer(); });
			}
			if (this.option.autoSlide) { this.startStepTimer(); }
		} else {
			if (this.option.autoSlide) { 
				this.startContinuousSlide(true); 
				this.container
					.bind('mouseenter', { carousel: this }, function (e) {
						e.data.carousel.pauseContinuousSlide();
					})
					.bind('mouseleave', { carousel: this }, function (e) {
						e.data.carousel.startContinuousSlide(false);
					});	
			}
		}
		

	};

	this.initFade = function() {
		this.container
			.bind('mouseenter', {carousel:this}, function(e){ e.data.carousel.stopStepTimer(); })
			.bind('mouseleave', {carousel:this}, function(e){ e.data.carousel.startStepTimer(); });
		if (this.option.showArrows) {
			this.arrowLeft
				.bind('mouseenter', {carousel:this}, function(e){ e.data.carousel.stopStepTimer(); })
				.bind('mouseleave', {carousel:this}, function(e){ e.data.carousel.startStepTimer(); });
			this.arrowRight
				.bind('mouseenter', {carousel:this}, function(e){ e.data.carousel.stopStepTimer(); })
				.bind('mouseleave', {carousel:this}, function(e){ e.data.carousel.startStepTimer(); });
		}
		if (this.option.autoSlide) { this.startStepTimer(); }
	};

	this.correctPanelsForPadding = function(){
		this.$panels.each(function(){
			var $this = $(this);
			$this.css({
				'width':(parseInt($this.css('width')) - parseInt($this.css('padding-left')) - parseInt($this.css('padding-right'))),
				'height':(parseInt($this.css('height')) - parseInt($this.css('padding-top')) - parseInt($this.css('padding-bottom')))
			  });
		});
	};
	
	/*===================================================
		Step Slide Functions
	===================================================*/
	
	this.nextSlide = function(newID, wrap) {
		if (this.animating) { return; }
		if (wrap === undefined) { wrap = true; }
		if (newID !== undefined && newID !== null && newID === this.slideCurrent) { return; }
		
		if (!wrap) {
			if (this.slideCurrent === 0 && newID < 0) { return; }
			if (this.slideCurrent == this.slideCount-1 && newID >= this.slideCount) { return; }
		}
		
		this.slideStart();
		this.slidePrevious = this.slideCurrent;
		this.slideCurrent = (newID === undefined)?this.slideCurrent+1:newID;
		
		if (this.slideCurrent < 0) {
			this.slideCurrent = this.slideCount-1;
		} else if (this.slideCurrent > this.slideCount) {
			this.slideCurrent = 0;
		}
		
		if (this.option.animationType == 'fade') { this.animateFade(); } else { this.animateSlide(); }
		
		this.startStepTimer();
		
	};
	
	this.slideNext = function() {
		this.nextSlide(this.slideCurrent + 1, true);
	};
	
	this.slidePrevious = function() {
		this.nextSlide(this.slideCurrent - 1, true);
	};

	this.startStepTimer = function () {
		if (this.isSyncronised && this.isDependent)
			return;
		clearInterval(this.slideRotateIID);
		var ss = this;
		if (this.isSyncronised) {
			this.slideRotateIID = setInterval(function () {
				if ($ && $.syncronisedCarousels && $.syncronisedCarousels.length) {
					for (var i = 0; i < $.syncronisedCarousels.length; i++)
						$.syncronisedCarousels[i].nextSlide();
				}
			}, (this.option.transitionTime + this.option.delayTime) * 1000);
			if ($ && $.syncronisedCarousels && $.syncronisedCarousels.length) {
				for (var i = 0; i < $.syncronisedCarousels.length; i++) {
					var carsl = $.syncronisedCarousels[i];
					if (carsl != this) {
						carsl.isDependent = true;
						if (this.slideRotateIID != carsl.slideRotateIID)
							clearInterval(carsl.slideRotateIID);
						carsl.slideRotateIID = this.slideRotateIID;
					}
				}
			}
		}
		else {
			this.slideRotateIID = setInterval(function () {
				ss.nextSlide();
			}, (this.option.transitionTime + this.option.delayTime) * 1000);
		}
	};

	this.stopStepTimer = function () {
		if (this.isSyncronised)
			this.isDependent = false;
		clearInterval(this.slideRotateIID);
	};
	
	this.animateSlide = function () {
		var ss = this;
		if (this.slideCurrent === this.slideCount-1) {
			if (this.option.direction == 'vertical') {
				this.panelContainer.css({ 'margin-top':-1*this.slideCount*this.height });
			} else {
				this.panelContainer.css({ 'margin-left':-1*this.slideCount*this.width });
			}
		} else if (this.slideCurrent === 0) {
			if (this.option.direction == 'vertical') {
				this.panelContainer.css({ 'margin-top':0 });
			} else {
				this.panelContainer.css({ 'margin-left':0 });
			}
		}
		if (this.option.direction == 'vertical') {
			this.panelContainer.animate(
				{ marginTop: ( -1 * this.slideCurrent * this.height) }, 
				this.option.transitionTime * 1000, 
				'linear', 
				function(){ ss.slideComplete(); }
			);
		} else {
			this.panelContainer.animate(
				{ marginLeft: ( -1 * this.slideCurrent * this.width) }, 
				this.option.transitionTime * 1000, 
				'linear', 
				function(){ ss.slideComplete(); } 
			);
		}
	};
	
	this.animateFade = function () {
		var ss = this;
		$(this.$panels[this.slideCurrent])
			.css({opacity:0})
			.appendTo(this.panelContainer)
			.animate(
				{ opacity: 1 }, 
				this.option.transitionTime * 1000, 
				'linear', 
				function(){ ss.slideComplete(); } 
			);	
	};
	
	/*===================================================
		Continuous Slide Functions
	===================================================*/		
	
	this.startContinuousSlide = function(fromstart) {
		var span, ratio;
		var ss = this;
		var $last  = $('.'+this.option.panelClass+':last', this.container);
		if(fromstart == undefined || fromstart == null) { fromstart = false; }
		
		if (this.option.direction == 'vertical') {
			span = parseInt($last.css('top'));
			if (fromstart) { 
				ratio = 1; 
				this.panelContainer.css( 'margin-top', 0 );
			} else { 
				ratio = Math.abs((span + parseInt(this.panelContainer.css('margin-top'))) / span); 
			}
			this.panelContainer.animate( {	'margin-top': ( -1 * parseInt($last.css('top')) ) }, 
											this.option.transitionTime * 1000 * ratio * this.slideCount, 
											'linear', 
											function(){ ss.startContinuousSlide(true); } );
		} else {
			span = parseInt($last.css('left'));
			if (fromstart) { 
				ratio = 1; 
				this.panelContainer.css( 'margin-left', 0 );
			} else {
				ratio = Math.abs((span + parseInt(this.panelContainer.css('margin-left'))) / span); 
			}
			this.panelContainer.animate( { 	marginLeft: ( -1 * parseInt($last.css('left')) ) }, 
											this.option.transitionTime * 1000 * ratio * this.slideCount, 
											'linear', 
											function(){	ss.startContinuousSlide(true); } );
		}
		
	};

	this.pauseContinuousSlide = function () {
		this.panelContainer.stop();
	};
	
	/*===================================================
		Fade Functions
	===================================================*/
	
	/*===================================================
		Slide Start/Complete
	===================================================*/
	this.slideStart = function(){
		this.clearControls();
		this.animating = true;
		this.option.slideStart(this);
	};
	
	this.slideComplete = function(){
		if (this.slideCurrent >= this.slideCount) {
			this.slideCurrent = 0;
			if (this.option.direction == 'vertical') {
				this.panelContainer.css('margin-top',0);
			} else {
				this.panelContainer.css({ 'margin-left':0 });
			}
		}
		
		this.setControls();
		this.animating = false;
		this.option.slideComplete(this,this.slideCurrent);
	};
	
	/*===================================================
		Controls Functions
	===================================================*/
	this.clearControls = function(){
		if (!this.option.showControl) { return; }
		$('div.control', this.container)
			.removeClass('selected')
			.css(this.option.controlButtonCSS);
	};
	
	this.setControls = function(){
		if (!this.option.showControl) { return; }
		this.clearControls();
		var selectedControl = (this.slideCurrent === this.slideCount)?0:this.slideCurrent;
		$('div.control_'+selectedControl, this.container)
			.addClass('selected')
			.css(this.option.controlButtonSelectCSS);
	};
	
	/*===================================================
		Fire it up
	===================================================*/

	this.buildCarousel();

}
