/*
	Fader class
*/

function fader()
{
	/*
		Initialises the fader object
		@param objectName: The name of the instantiated object - For dealing with setTimeout and the Window scope
		@param faderContainerId: The id of the html element that contains all the fade items
		@param fadeTime: The time in milliseconds it takes to fade an item in or out
		@param fadeItemElementType: The html element type of the fade items (e.g. DIV)
		@param autoTransition: Whether or not to auto transition the fade items, according to the transitionInterval
		@param transitionInterval: If autoTransition is enabled, the time between transitions
		@param compatibleMode: Whether or not in compatible mode
	*/
	this.init = function(objectName, faderContainerId, fadeTime, fadeItemElementType, autoTransition, transitionInterval, compatibleMode)
	{
		// Instance vars
		this.objectName = objectName;
		this.faderContainerId = faderContainerId;
		this.fadeTime = fadeTime;
		this.fadeItemElementType = fadeItemElementType;
		this.autoTransition = autoTransition;
		this.transitionInterval = transitionInterval;
		this.compatibleMode = compatibleMode;

		// Tracking vars
		this.activeFadeItemIdx = 0;
		this.nextOrPrevClicked = false; // if this becomes true later, auto transitions cease until a page refresh occurrs
		this.fadeItems = new Array();
		
		for(var i = 0, tmpItems = document.getElementById(this.faderContainerId).getElementsByTagName(fadeItemElementType); i < tmpItems.length; i++)
		{
			if(tmpItems[i].className == "active" || tmpItems[i].className == "inactive") // is this a fade item?
				this.fadeItems.push(tmpItems[i]);
		}

		// Tuning var
		this.fadeInDelay = 50; // tuning var used to smooth out the transition effect

		// Trigger auto transition if enabled
		if(this.autoTransition)
		{
			setTimeout(this.objectName + ".autoTransitions()", this.transitionInterval);
		}
	};


	/*
		Triggers the auto transition mechanism
	*/
	this.autoTransitions = function()
	{
		if(!this.nextOrPrevClicked) // user hasn't interrupted auto transition by clicking next or previous? Ok to continue? (exit condition for recursive call; see below)
		{
			this.transitionNext(false); // fade to next item, with userClick flag set to false

			setTimeout(this.objectName + ".autoTransitions()", this.transitionInterval); // delayed recursive call
		}
	};


	/*
		Fades in the fader container according to the fadeTime - From 0 opacity to 100
	*/
	this.fadeIn = function()
	{
		this.fade(0, 100, this.fadeTime);
	};


	/*
		Fades out the fader container according to the fadeTime - From 0 opacity to 100
	*/
	this.fadeOut = function()
	{
		this.fade(100, 0, this.fadeTime);
	};


	/*
		Transitions to the previous item
		@param userClick: Whether or not the previous link was clicked by a user
	*/
	this.transitionPrev = function(userClick)
	{
		this.nextOrPrevClicked = userClick; // signalling the user has clicked for the previous item
		this.activeFadeItemIdx = (this.activeFadeItemIdx == 0)? this.fadeItems.length - 1 : this.activeFadeItemIdx - 1;
		this.transition();
	};


	/*
		Transitions to the next item
		@param userClick: Whether or not the nextlink was clicked by a user
	*/
	this.transitionNext = function(userClick)
	{
		this.nextOrPrevClicked = userClick; // signalling the user has clicked for the previous item
		this.activeFadeItemIdx = (this.activeFadeItemIdx == this.fadeItems.length - 1)? 0 : this.activeFadeItemIdx + 1;
		this.transition();
	};


	/*
		Performs the item transition with fade effects
	*/
	this.transition = function()
	{
		this.fadeOut(); // happens immediately

		// These are delayed so they occur after the fade out
		setTimeout(this.objectName + ".updateItemClasses()", this.fadeTime + this.fadeInDelay); // updates the item classnames to reflect the visible item
		setTimeout(this.objectName + ".fadeIn()", this.fadeTime + this.fadeInDelay); // fade in after transitioning classes
	};


	/*
		Updates the item classnames (styles) as part of the transition
	*/
	this.updateItemClasses = function()
	{
		for(var i = 0; i < this.fadeItems.length; i++) // Looping over all the fade items
		{
			if(i == this.activeFadeItemIdx) // active item?
			{
				this.fadeItems[i].className = "active";
			}
			else // not the active item
			{
				this.fadeItems[i].className = "inactive";
			}
		}
	};


	/*
		Changes the opacity value of the fader container
		@param: opacity: The opacity value: range [0,100]
	*/
	this.changeOpacity = function(opacity)
	{
		var fadeContainer = document.getElementById(this.faderContainerId);

		if(!this.compatibleMode)
		{
			fadeContainer.style.opacity = (opacity / 100);
			fadeContainer.style.MozOpacity = (opacity / 100);
			fadeContainer.style.KhtmlOpacity = (opacity / 100);
			fadeContainer.style.filter = "alpha(opacity="+opacity+")";
		}
		else // compatible mode (doesn't filter text, just images - Fakes an alpha filter on text by changing the text color from dark to light and vice versa)
		{
			var containerImages = fadeContainer.getElementsByTagName("IMG");
			var textFadeFactor = 2.5;
			var inverseOpacity = 100 - opacity;

			// Fading the images
			for(var i = 0; i < containerImages.length; i++)
			{
				containerImages[i].style.opacity = (opacity / 100);
				containerImages[i].style.MozOpacity = (opacity / 100);
				containerImages[i].style.KhtmlOpacity = (opacity / 100);
				containerImages[i].style.filter = "alpha(opacity="+opacity+")";
			}

			// Fading the text color if possible (for all text that does not already have a color property)
			document.getElementById(this.faderContainerId).style.color = "rgb(" + textFadeFactor * inverseOpacity + ", " + textFadeFactor * inverseOpacity + ", " + textFadeFactor * inverseOpacity + ")";
		}
	};


	/*
		Fades the fader container
		@param opacityFrom: Starting opacity: range [0,100]
		@param opacityTo: Ending opacity: range [0,100]
		@param time: Duration of the fade in milliseconds
	*/
	this.fade = function(opacityFrom, opacityTo, time)
	{
		// Speed for each frame
		var speed = Math.round(time / 100);
		var timer = 0;

		// Determine the direction for the blending, if opacityFrom and opacityTo are the same nothing happens
		if(opacityFrom > opacityTo)
		{
			for(var i = opacityFrom; i >= opacityTo; i--)
			{
				setTimeout(this.objectName + ".changeOpacity(" + i + ")", (timer * speed));
				timer++;
			}
		}
		else if(opacityFrom < opacityTo)
		{
			for(var i = opacityFrom; i <= opacityTo; i++)
			{
				setTimeout(this.objectName + ".changeOpacity(" + i + ")", (timer * speed));
				timer++;
			}
		}
	};
}
