//////////////////////////////////////////////////////////////////////////////////

// CloudCarousel V1.0.3

// (c) 2010 by R Cecco. <http://www.professorcloud.com>

// MIT License

//

// Reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>

//

// Please retain this copyright header in all versions of the software

//////////////////////////////////////////////////////////////////////////////////


(function($) {


	// START Reflection object.

	// Creates a reflection for underneath an image.

	// IE uses an image with IE specific filter properties, other browsers use the Canvas tag.	

	// The position and size of the reflection gets updated by updateAll() in Controller.

	function Reflection(img, reflHeight, opacity) {				

		

		var	reflection, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;

	

		parent = $(img.parentNode);

		if ($.browser.msie) {

			this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];					

			reflection.src = img.src;			

			reflection.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (reflHeight / imageHeight * 100) + ")";	

			

	} else {	

			

			this.element = reflection = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];			

			if (!reflection.getContext)

			{

				return;			

			}

			cntx = reflection.getContext("2d");

			try {

				

				

				$(reflection).attr({width: imageWidth, height: reflHeight});

				cntx.save();

				cntx.translate(0, imageHeight-1);

				cntx.scale(1, -1);				

				cntx.drawImage(img, 0, 0, imageWidth, imageHeight);				

				cntx.restore();

				cntx.globalCompositeOperation = "destination-out";

				gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);

				gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");

				gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");

				cntx.fillStyle = gradient;

				cntx.fillRect(0, 0, imageWidth, reflHeight);				

			} catch(e) {			

				return;

			}		

		}

		// Store a copy of the alt and title attrs into the reflection

		$(reflection).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title')} );	

				

	}	//END Reflection object



	// START Item object.

	// A wrapper object for items within the carousel.

	var	Item = function(imgIn, options)

	{								

		this.orgWidth = imgIn.width;			

		this.orgHeight = imgIn.height;		

		this.image = imgIn;

		this.reflection = null;					

		this.alt = imgIn.alt;

		this.title = imgIn.title;

		this.imageOK = false;		

		this.options = options;				

						

		this.imageOK = true;	

		

		if (this.options.reflHeight > 0)

		{													

			this.reflection = new Reflection(this.image, this.options.reflHeight, this.options.reflOpacity);					

		}

		$(this.image).css('position','absolute');	// Bizarre. This seems to reset image width to 0 on webkit!				

	};// END Item object

	

	

	// Controller object.

	// This handles moving all the items, dealing with mouse clicks etc.	

	var Controller = function(container, images, options)

	{						

		var	items = [], funcSin = Math.sin, funcCos = Math.cos, ctx=this;

		this.controlTimer = 0;

		this.stopped = false;

		//this.imagesLoaded = 0;

		this.container = container;

		this.xRadius = options.xRadius;

		this.yRadius = options.yRadius;

		this.showFrontTextTimer = 0;
                
                this.showTextBGTimer = 2;

		if (options.xRadius === 0)

		{

			this.xRadius = ($(container).width()/2.3);

		}

		if (options.yRadius === 0)

		{

			this.yRadius = ($(container).height()/6);

		}



		this.xCentre = options.xPos;

		this.yCentre = options.yPos;

		this.frontIndex = 0;	// Index of the item at the front

		

		// Start with the first item at the front.

		this.rotation = this.destRotation = Math.PI/2;

		this.timeDelay = 1000/options.FPS;

								

		// Turn on the infoBox

		if(options.altBox !== null)

		{


			$(options.altBox).css('display','block');	

			$(options.titleBox).css('display','block');	

		}

		// Turn on relative position for container to allow absolutely positioned elements

		// within it to work.

		$(container).css({ position:'relative', overflow:'hidden'} );

	

		$(options.buttonLeft).css('display','inline');

		$(options.buttonRight).css('display','inline');

		

		// Setup the buttons.

		$(options.buttonLeft).bind('mouseup',this,function(event){

			event.data.rotate(-1);	
                        $('.carousel_info').hide().delay(1100).fadeIn('1000');

			return false;

		});

		$(options.buttonRight).bind('mouseup',this,function(event){															

			event.data.rotate(1);	
                        $('.carousel_info').hide().delay(1100).fadeIn('1000');

			return false;

		});

		

		// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel

		if (options.mouseWheel)

		{

			$(container).bind('mousewheel',this,function(event, delta) {

					 event.data.rotate(delta);

					 return false;

				 });

		}

		$(container).bind('mouseover',this,function(event){

		

			clearInterval(event.data.autoRotateTimer);		// Stop auto rotation if mouse over.

			var	text = $(event.target).attr('alt');		

			// If we have moved over a carousel item, then show the alt and title text.

			//if ( text !== undefined && text !== null )

		//{
                       // $('.carousel_info').hide();

				clearTimeout(event.data.showFrontTextTimer);

			//$('.carousel_info').fadeIn('slow');

			//	$(options.altBox).html( ($(event.target).attr('alt') ));

			//	$(options.titleBox).html( ($(event.target).attr('title') ));							

			//}

		});

		// If we have moved out of a carousel item (or the container itself),

		// restore the text of the front item in 1 second.

		$(container).bind('mouseout',this,function(event){

				var	context = event.data;				

				clearTimeout(context.showFrontTextTimer);				

				context.showFrontTextTimer = setTimeout( function(){context.showFrontText();}, 0);

				context.autoRotate();	// Start auto rotation.
                               



		});



		// Prevent items from being selected as mouse is moved and clicked in the container.

		$(container).bind('mousedown',this,function(event){	

			

			event.data.container.focus();

			return false;

		});

		container.onselectstart = function () { return false; };		// For IE.



		this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];

	

		// Shows the text from the front most item.

		this.showFrontText = function()

		{	

			if ( items[this.frontIndex] === undefined ) { return; }	// Images might not have loaded yet.


			$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));

			$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));				

		};

						

		this.go = function()

		{				

			if(this.controlTimer !== 0) { return; }

			var	context = this;

			this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);					

		};

		

		this.stop = function()

		{

			clearTimeout(this.controlTimer);

			this.controlTimer = 0;				

		};

		

		

		// Starts the rotation of the carousel to the neigbouring item.

		this.rotate = function(direction)

		{	

			this.frontIndex += direction;

			// Keep a note of the item at the front.

			if (this.frontIndex<0) { this.frontIndex = items.length-1; }

			if (this.frontIndex > items.length-1) { this.frontIndex=0; }

			// 

			this.destRotation -= (Math.PI / items.length) * (2*direction);

			this.showFrontText();

			this.go();			

		};

		

		

		this.autoRotate = function()

		{	

			if ( options.autoRotate !== 'no' )

			{

				var	dir = (options.autoRotate === 'right')? 1 : -1;

				this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );

			}

		};

		

		// This is the main loop function that moves everything.

		this.updateAll = function()

		{	$('.carousel_info').hide().delay(600).fadeIn('1000');								

			var	minScale = options.minScale;	// This is the smallest scale applied to the furthest item.

			var smallRange = (1-minScale) *0.5;

			var	w,h,x,y,scale,item,sinVal;

			

			var	change = (this.destRotation - this.rotation);		

			var	absChange = Math.abs(change);

			this.rotation += change * options.speed;

			if ( absChange < 0.001 ) { this.rotation = this.destRotation; }			

			var	itemsLen = items.length;

			var	spacing = (Math.PI / itemsLen) * 2; 

			//var	wrapStyle = null;

			var	radians = this.rotation;

			var	isMSIE = $.browser.msie;

		

			// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.

			// See http://dev.opera.com/articles/view/efficient-javascript/?page=3			

			this.innerWrapper.style.display = 'none';		

			

			var	style;

			var	px = 'px', reflHeight;	

			var context = this;

			for (var i = 0; i<itemsLen ;i++)

			{

				item = items[i];

								

				sinVal = funcSin(radians);

				

				scale = ((sinVal+1) * smallRange) + minScale;

				

				x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);

				y = this.yCentre + (( (sinVal * this.yRadius)  ) * scale);		

		

				if (item.imageOK)

				{

					var	img = item.image;

					w = img.width = item.orgWidth * scale;					

					h = img.height = item.orgHeight * scale;

					img.style.left = x + px ;

					img.style.top = y + px;

					img.style.zIndex = (scale * 100)>>0;	// >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.

					if (item.reflection !== null)

					{																										

						reflHeight = options.reflHeight * scale;						

						style = item.reflection.element.style;

						style.left = x + px;

						style.top = y + h + options.reflGap * scale + px;

						style.width = w + px;								

						if (isMSIE)

						{											

							style.filter.finishy = (reflHeight / h * 100);				

						}else

						{								

							style.height = reflHeight + px;															

						}																													

					}					

				}

				radians += spacing;

			}

			// Turn display back on.					

			this.innerWrapper.style.display = 'block';

$('#homeCarousel').css('visibility','visible');

			// If we have a preceptable change in rotation then loop again next frame.

			if ( absChange >= 0.001 )

			{				

				this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);		

			}else

			{

				// Otherwise just stop completely.				

				this.stop();

			}

		}; // END updateAll		

		

		// Create an Item object for each image	

//		func = function(){return;ctx.updateAll();} ;



		// Check if images have loaded. We need valid widths and heights for the reflections.

		this.checkImagesLoaded = function()

		{

			var	i;

			for(i=0;i<images.length;i++) {

				if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete)  ))

				{

					return;					

				}				

			}

			for(i=0;i<images.length;i++) {				

				 items.push( new Item( images[i], options ) );						

			}

			// If all images have valid widths and heights, we can stop checking.			

			clearInterval(this.tt);

			this.showFrontText();

			this.autoRotate();	

			this.updateAll();

			

		};



		this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);	

	}; // END Controller object

	

	

	

	

	

	

	

	

	

	

	// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.

	$.fn.CloudCarousel = function(options) {

			

		this.each( function() {			

			

			options = $.extend({}, {

							   reflHeight:40,

							   reflOpacity:0.3,

							   reflGap:0,

							   minScale:0.5,

							   xPos:0,

							   yPos:0,

							   xRadius:0,

							   yRadius:40,

							   altBox:null,

							   titleBox:null,

							   FPS: 30,

							   autoRotate: 'yes',

							   autoRotateDelay: 4000,

							   speed:0.1,

							   mouseWheel:false

			},options );									

			// Create a Controller for each carousel.		

			$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );

		});				

		return this;

	};



})(jQuery);



/*! Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)

 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)

 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.

 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.

 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.

 *

 * Version: 3.0.2

 * 

 * Requires: 1.2.2+

 */



(function($) {



var types = ['DOMMouseScroll', 'mousewheel'];



$.event.special.mousewheel = {

	setup: function() {

		if ( this.addEventListener )

			for ( var i=types.length; i; )

				this.addEventListener( types[--i], handler, false );

		else

			this.onmousewheel = handler;

	},

	

	teardown: function() {

		if ( this.removeEventListener )

			for ( var i=types.length; i; )

				this.removeEventListener( types[--i], handler, false );

		else

			this.onmousewheel = null;

	}

};



$.fn.extend({

	mousewheel: function(fn) {

		return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");

	},

	

	unmousewheel: function(fn) {

		return this.unbind("mousewheel", fn);

	}

});





function handler(event) {

	var args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true;

	

	event = $.event.fix(event || window.event);

	event.type = "mousewheel";

	

	if ( event.wheelDelta ) delta = event.wheelDelta/120;

	if ( event.detail     ) delta = -event.detail/3;

	

	// Add events and delta to the front of the arguments

	args.unshift(event, delta);



	return $.event.handle.apply(this, args);

}



})(jQuery);

