YAHOO.namespace('YAHOO.EU.widget.Carousel');
/**
 *
 * Base Carousel class
 * <p>Usage: new YAHOO.EU.widget.Carousel().init('yeug-ticker', oCarouselConfig);</p>
 * @class Carousel
 * @namespace YAHOO.EU.widget.Carousel
 * @requires YAHOO.util.AnimMgr
 * @requires YAHOO.util.Easing
 * @requires YAHOO.util.Dom
 * @requires YAHOO.util.Event
 * @requires YAHOO.util.CustomEvent
 * @constructor
 * @param {String | HTMLElement} el Reference to the outer container of the Carousel
 * @param {Object} oConfig The config options for the Carousel.
 *   {integer} tag (optional, defaults to ul) nodeName of HTMLElement container
 *   {integer} visiblePanes (optional, defaults to 1) Number of panes visible at any one time
 *   {integer} panesToMove (optional, defaults to 1) Number of panes to move per animation
 *   {number} animDuration (optional, defaults to 0.5 seconds) Length of animation in seconds
 *   {Function} easing (optional, defaults to YAHOO.util.Easing.easeOut) Computes the values that are applied to the animation per frame (generally a YAHOO.util.Easing method)
 *   {Boolean} isVertical (optional, defaults to true) Orientation of the Carousel animation
 *   {Boolean} loop (optional, defaults to false) Loop back to the begining
 *   {String | HTMLElement} buttonCont (optional, defaults to el) element to append buttons to
 */
YAHOO.EU.widget.Carousel = function(){
	return this;
};
YAHOO.EU.widget.Carousel.prototype = {

	init : function(el, oConfig){
		this.oConfig 		= oConfig;
		this.sTag			= oConfig.tag || "ul"
		this.nVisiblePanes	= oConfig.visiblePanes || 1;
		this.nPanesToMove 	= oConfig.panesToMove || this.nVisiblePanes;
		this.bHorizontal	= !oConfig.isVertical;
		this.bLoop			= oConfig.loop || 0;
		this.oCont			= YAHOO.util.Dom.get(el);
		this.oClip			= YAHOO.util.Dom.getElementsByClassName('clip', 'div', this.oCont)[0];	
		this.oPanel	 		= this.oCont.getElementsByTagName(this.sTag)[0];
		this.oButtonCont	= oConfig.buttonCont || this.oCont;
		this.nCurrentPane 	= 0;
		YAHOO.util.Dom.addClass(this.oCont, "js");
		YAHOO.util.Dom.addClass(this.oCont, (this.bHorizontal) ? "horz" : "vert");
		this.assignElements();
		YAHOO.util.Dom.setStyle(this.oClip, "overflow", "hidden");
		YAHOO.util.Dom.setStyle(this.oClip, "clip", "rect(0 " + this.oCont.offsetWidth + "px " + this.oCont.offsetHeight + "px 0)");
		this.createNav();
		this.createEvents();
		this.onAnimStart.fire();
		return this;
	},
	
	assignElements : function(){
		var oPanel 			= this.oPanel;
		this.aPanels 		= YAHOO.util.Dom.getElementsBy(function(o){
								if(o.parentNode == oPanel){
									return true;
								}
								return false;
								}, "li", this.oPanel);
		var nPadding		= this.getPadding(this.aPanels[0]);
		var nPaddingCont	= this.getPadding(this.oCont);
		this.nMoveInc		= Math.floor((this.bHorizontal) ? (this.oCont.offsetWidth - nPaddingCont) / this.nVisiblePanes : (this.oCont.offsetHeight - nPaddingCont) / this.nVisiblePanes) - nPadding;
		for(var i=0, j=this.aPanels.length; i<j; i++){
			if(this.bHorizontal){
				this.aPanels[i].style.width = this.nMoveInc + "px";
			}else{
				this.aPanels[i].style.height = this.nMoveInc + "px";
			}
		}
		this.nMoveInc 	+= nPadding;
		this.nPanes		= this.aPanels.length;
	},
	
	getPadding : function(o){
		return (this.bHorizontal) ? (parseInt(YAHOO.util.Dom.getStyle(o, "paddingRight")) + parseInt(YAHOO.util.Dom.getStyle(o, "paddingLeft")) + parseInt(YAHOO.util.Dom.getStyle(o, "borderRightWidth").replace("medium", 0)) + parseInt(YAHOO.util.Dom.getStyle(o, "borderLeftWidth").replace("medium", 0))) : (parseInt(YAHOO.util.Dom.getStyle(o, "paddingBottom")) + parseInt(YAHOO.util.Dom.getStyle(o, "paddingTop")) + parseInt(YAHOO.util.Dom.getStyle(o, "borderTopWidth").replace("medium", 0)) + parseInt(YAHOO.util.Dom.getStyle(o, "borderBottomWidth").replace("medium", 0)));
	},

	createNav : function(){
		this.oButtonCont = YAHOO.util.Dom.get(this.oButtonCont);
		
		this.oBtnPrev = document.createElement("button");
		YAHOO.util.Dom.addClass(this.oBtnPrev, "btnprev");
		this.oBtnPrev.appendChild(document.createTextNode("<"));
		this.oButtonCont.appendChild(this.oBtnPrev);
		
		this.oBtnNext = document.createElement("button");
		YAHOO.util.Dom.addClass(this.oBtnNext, "btnnext");
		this.oBtnNext.appendChild(document.createTextNode(">"));
		this.oButtonCont.appendChild(this.oBtnNext);
	},

	createEvents : function(){
		this.onAnimStart 	= new YAHOO.util.CustomEvent("onAnimStart");
		this.onAnimEnd		= new YAHOO.util.CustomEvent("onAnimEnd");
		this.onNavigate		= new YAHOO.util.CustomEvent("onNavigate");
		this.onCarouselEnd	= new YAHOO.util.CustomEvent("onCarouselEnd");
		this.onAnimStart.subscribe(this.enableButtons, this, true);	
		this.onAnimEnd.subscribe(this.enableButtons, this, true);
		YAHOO.util.Event.on(this.oBtnPrev, 'click', function(e){this.moveBy(e, -1)}, this, true);
		YAHOO.util.Event.on(this.oBtnNext, 'click', function(e){this.moveBy(e, 1)}, this, true);
	},

	enableButtons : function(){
		this.oBtnPrev.disabled = false;
		this.oBtnNext.disabled = false;
		YAHOO.util.Dom.removeClass(this.oBtnPrev, "btnprevdisabled");
		YAHOO.util.Dom.removeClass(this.oBtnNext, "btnnextdisabled");
		if((!this.nCurrentPane && !this.bLoop) || this.nVisiblePanes > this.nPanes){
			YAHOO.util.Dom.addClass(this.oBtnPrev, "btnprevdisabled");
			this.oBtnPrev.disabled = true;
			this.oBtnNext.disabled = false;
		}
		if((this.nCurrentPane >= this.nPanes - this.nVisiblePanes && !this.bLoop) || (this.bLoop && this.nVisiblePanes > this.nPanes)){
			YAHOO.util.Dom.addClass(this.oBtnNext, "btnnextdisabled");
			this.oBtnPrev.disabled = false;
			this.oBtnNext.disabled = true;
		}
	},

	moveBy : function(e, nPanes){
		if(e){
			YAHOO.util.Event.preventDefault(e);
			this.onNavigate.fire();
		}
		this.nCurrentPane += nPanes * this.nPanesToMove;
		if(this.nCurrentPane + this.nVisiblePanes - this.nPanesToMove >= this.nPanes){
			if(this.bLoop){
				this.nCurrentPane = 0;
			}
			this.onCarouselEnd.fire();
		}else if(this.nCurrentPane <= -this.nPanesToMove){
			if(this.bLoop){
				this.nCurrentPane = this.nPanes + (nPanes * this.nPanesToMove);
			}
			this.onCarouselEnd.fire();
		}
		this.gotoPane(this.nCurrentPane);
	},

	gotoPane : function(nPane){
		if(nPane < 0){
			nPane = 0;
		}
		if(nPane > this.nPanes - this.nVisiblePanes){
			nPane = this.nPanes - this.nVisiblePanes;
		}
		this.nCurrentPane = nPane;
		var oAnim = new YAHOO.util.Anim(this.oPanel, (this.bHorizontal) ? { left : {to : -this.nMoveInc * nPane}} : { top : {to : -this.nMoveInc * nPane}}, this.oConfig.animDuration || 0.5, this.oConfig.easing || YAHOO.util.Easing.easeBoth);
		var onAnimEnd = function(type, args) {
			this.onAnimEnd.fire();
		};
		oAnim.onComplete.subscribe(onAnimEnd, this, true);
		this.onAnimStart.fire();
		oAnim.animate();
	}
};



/**
 *
 * Extends the Carousel Class to add auto-play animations
 * <p>Usage: new YAHOO.EU.widget.Carousel().init('yeug-ticker', oCarouselConfig).autoPlay(oConfig);</p>
 * @param {Object} oConfig The config options for Auto-play.  
 *   {number} autoPlayDelay (optional, defaults to 5 seconds) Length of delay in milliseconds
 *   {Object} btnPause Config for pause/play toggle button, requires buttonLabel
 */
YAHOO.EU.widget.Carousel.prototype.autoPlay = function(oConfig){
	var self = this;
	if(oConfig){
		this.oAutoConfig = oConfig;
		this.oBtnPause = document.createElement("button");
		YAHOO.util.Dom.addClass(this.oBtnPause, "btnpause");
		this.oBtnPause.appendChild(document.createTextNode(this.oAutoConfig.buttonLabel));
		this.oButtonCont.appendChild(this.oBtnPause);
		YAHOO.util.Event.on(this.oBtnPause, 'click', this.pause, this, true);
		this.onNavigate.subscribe(function(){this.pause(true)}, this, true);
	}
	this.bPaused = 0;
	YAHOO.util.Dom.removeClass(this.oBtnPause, "btnpausedisabled");
	this.oTimer = window.setInterval(function(){;self.moveBy(null, 1)}, this.oAutoConfig.autoPlayDelay || 5000);
	return this;
};

YAHOO.EU.widget.Carousel.prototype.pause = function(e){
	if(e && e !== true){
		YAHOO.util.Event.preventDefault(e);
		if(this.bPaused){
			this.moveBy(null, 1);
			return this.autoPlay();
		}
	}
	this.bPaused = 1;
	YAHOO.util.Dom.addClass(this.oBtnPause, "btnpausedisabled");
	clearTimeout(this.oTimer);
};





/**
 *
 * Extends the Carousel Class to add auto-load of content via Ajax
 * <p>Usage: new YAHOO.EU.widget.Carousel().init('yeug-ticker', oCarouselConfig).enableCheckForUpdates(oConfig);</p>
 * @requires YAHOO.util.Connect
 * @param {Object} oConfig The config options for Auto-play.  
 *   {String} url Url for Ajax request
 *   {Number} checkDelay (optional, defaults to 10 seconds) Interval between checking for updates
 */
YAHOO.EU.widget.Carousel.prototype.enableCheckForUpdates = function(oConfig){
	var self = this;
	this.oLoadConfig	 	= oConfig;
	this.nMaxItems			= oConfig.maxItems;
	this.oLoadTimer 		= window.setInterval(function(){self.checkForUpdates()}, this.oLoadConfig.checkDelay || 10000);
	this.onContentChange 	= new YAHOO.util.CustomEvent("onContentChange");
	return this;
};
YAHOO.EU.widget.Carousel.prototype.checkForUpdates = function(){
	YAHOO.util.Connect.asyncRequest("GET", this.oLoadConfig.url, {
			success : this.checkedForUpdates,
			scope	: this
		}
	);
};
YAHOO.EU.widget.Carousel.prototype.checkedForUpdates = function(oResponse){
	var re = /[\S]/g;
	if(!re.test(oResponse.responseText)){
		return;
	}
	var sCurrentHTML = this.oPanel.innerHTML;
	this.oPanel.innerHTML = oResponse.responseText;
	this.assignElements();
	this.gotoPane(0);
	this.enableButtons();
	if(this.oPanel.innerHTML != sCurrentHTML){
		this.onContentChange.fire();
	}
};


/**
 *
 * Extends the Carousel Class to add pagination buttons (Cheers Sam)
 * <p>Usage: new YAHOO.EU.widget.Carousel().init('yeug-ticker', oCarouselConfig).paginate();</p>
 */
YAHOO.EU.widget.Carousel.prototype.paginate = function(){
	var oUL = document.createElement("ul");
	YAHOO.util.Dom.addClass(oUL, "pagination");	
	this.updatePagination = function(){
		for(i=0, j=this.aPage.length; i<j; i++){
			if(i === Math.ceil(this.nCurrentPane / this.nPanesToMove)){
				YAHOO.util.Dom.addClass(this.aPage[i], "current");
				this.aPage[i].getElementsByTagName("button")[0].disabled = true;
			}else{
				YAHOO.util.Dom.removeClass(this.aPage[i], "current");
				this.aPage[i].getElementsByTagName("button")[0].disabled = false;
			}
		}
	};
	for(i=0, j=Math.ceil((this.nPanes-this.nVisiblePanes)/this.nPanesToMove)+1; i<j; i++){
		var oLI = document.createElement("li");
		var oB 	= document.createElement("button");
		oB.appendChild(document.createTextNode(i+1));
		oLI.appendChild(oB);
		oUL.appendChild(oLI);
	}
	this.aPage =  YAHOO.util.Dom.getElementsBy(function(o){
		if(o.parentNode === oUL) {
			return true;
		}
		return false;
	}, "li", oUL);
	YAHOO.util.Event.on(oUL, "click", function(e){
		this.onNavigate.fire();
		this.gotoPane((YAHOO.util.Event.getTarget(e).firstChild.nodeValue-1) * this.nPanesToMove);
		YAHOO.util.Event.preventDefault(e);
	}, this, true);
	this.updatePagination();
	this.onAnimStart.subscribe(this.updatePagination, this, true);	
	this.oButtonCont.appendChild(oUL);
	return this;
};