

/// FADER OBJECT ///

function Fader()
{
	this.lastFadeFinished = true;
	this.onFadeBeginsCode;
	this.onFadeEndsCode;
	this.fps = 12;
	
	this.setOnFadeBeginsCode = function (codeToRun)
	{
		this.onFadeBeginsCode = codeToRun;
	}
	this.setOnFadeEndsCode = function (codeToRun)
	{
		this.onFadeEndsCode = codeToRun;
	}
	this.setFps = function (fps)
	{
		this.fps = fps;
	}
	
	this.fadeIn = function(elemId, speed, fadeToOpacity)
	{
		//alert("fadeIn: " + elemId + ", " + speed + ", " + opacity);
		//if not done transitioning, try again in a 10th of a second
		if (!this.lastFadeFinished)
		{
			var faderObj = this;
			setTimeout(function() {faderObj.fadeIn(elemId, speed, fadeToOpacity);}, 100);
			return;
		}
		if(fadeToOpacity === undefined || fadeToOpacity === null)
		{
			fadeToOpacity = 100;
		}
		this.fade(elemId, 0, fadeToOpacity, speed, this.fps)
	}
		
	this.fadeOut = function(elemId, speed, fadeToOpacity)
	{
		//alert("fadeOut: " + elemId + ", " + speed + ", " + fadeTo);
		//if not done transitioning, try again in a 10th of a second
		if (!this.lastFadeFinished)
		{
			var faderObj = this;
			setTimeout(function() {faderObj.fadeOut(elemId, speed, fadeToOpacity);}, 100);
			return;
		}
		if(fadeToOpacity === undefined || fadeToOpacity === null)
		{
			fadeToOpacity = 0;
		}
		this.fade(elemId, 100, fadeToOpacity, speed, this.fps)
	}

	this.fade = function(elemId, fromOpacity, toOpacity, time, fps)
	{
		//alert("fade: " + elemId + ", " + fromOpacity + ", " + toOpacity + ", " + time + ", " + fps);
		if (fps === undefined || fps === null)
		{
			fps =  this.fps;
		}
		this.lastFadeFinished = false;
		var steps = Math.ceil(fps * (time / 1000));
		var delta = (toOpacity - fromOpacity) / steps;
		
		this.fadeStep(elemId, 0, steps, fromOpacity, delta, (time / steps));
	}

	this.fadeStep = function(elemId, stepNum, steps, fromOpacity, delta, timePerStep)
	{
	    //alert("fadeStep: " + elemId + ", " + stepNum + ", " + steps + ", " + fromOpacity + ", " + delta + ", " + timePerStep);
	    if (stepNum === 0 && this.onFadeBeginsCode)
	    {
			eval(this.onFadeBeginsCode);
	    }
	    
	    this.setOpacity(elemId, Math.round(parseInt(fromOpacity) + (delta * stepNum)));

	    if (stepNum < steps)
	    {
	        var faderObj = this;
	        setTimeout(function() {faderObj.fadeStep(elemId, (stepNum+1), steps, fromOpacity, delta, timePerStep);}, timePerStep);
	        //alert("fadeStep fading again");
		}
		else
		{
			this.lastFadeFinished = true;
			//alert("fadeStep done fading");
			if (this.onFadeEndsCode)
			{
				eval(this.onFadeEndsCode);
			}
		}
	}
	
	this.setOpacity = function(elemId, opacityAsInt)
	{
		//alert("setOpacity: " + elemId + ", " + opacityAsInt);
		var elem = document.getElementById(elemId);
		var opacityAsDecimal = opacityAsInt;
		
		if (opacityAsInt > 100)
			opacityAsInt = opacityAsDecimal = 100; 
		else if (opacityAsInt < 0)
			opacityAsInt = opacityAsDecimal = 0; 
		
		opacityAsDecimal /= 100;
		if (opacityAsInt < 1)
			opacityAsInt = 1; // IE7 bug, text smoothing cuts out if 0
		elem.style.opacity = opacityAsDecimal;
		elem.style.filter  = "alpha(opacity=" + opacityAsInt + ")";
	}
}




///CYCLER OBJECT///

function Cycler(htmlIds, fadeInOnFirstSlide, speed, delay)
{
	//Set default values for optional contructor parameters
	if (fadeInOnFirstSlide === undefined)
	{
		fadeInOnFirstSlide = false;
	}
	if (speed === undefined)
	{
		speed = 500;
	}
	if (delay === undefined)
	{
		delay = 5000;
	}
	
	//Declare object variables
	this.fader = new Fader();
	this.htmlIds = htmlIds;
	this.currIdIndex = 0;
	this.lastIdIndex;
	this.speed = speed;
	this.delay = delay;
	this.paused = false;
	this.onCycleBeginsCode;
	this.onTransitionEndsCode;
	this.onPauseCode;
	this.fadeInOnFirstSlide = fadeInOnFirstSlide;
	this.cycleTimeOut;
	this.gotoIdIndexCode;
	
	//Display the first slide
	if (this.fadeInOnFirstSlide)
	{
		this.fader.fadeIn(this.htmlIds[0], this.speed, 100);
	}
	else
	{
		this.fader.setOpacity(this.htmlIds[0], 100);
	}
	
	//Setter functions
	this.setSpeed = function(speed)
	{
		this.speed = speed;
	}
	this.setDelay = function(delay)
	{
		this.delay = delay;	
	}
	this.setFadeInOnFirstSlide = function(fadeOrAppear)
	{
		this.fadeInOnFirstSlide = fadeOrAppear;
	}
	this.setOnPauseCode = function(codeToRun)
	{
		this.onPauseCode = codeToRun;
	}
	this.setGotoIdIndexCode = function(codeToRun)
	{
		this.gotoIdIndexCode = codeToRun;
	}
	
	
	//Object functions
	
	this.gotoNextIdIndex = function()
	{
		if(this.htmlIds[this.currIdIndex + 1])
		{
			this.gotoIdIndex(this.currIdIndex + 1);
		}
		else
		{
			this.gotoIdIndex(0);
		}
	}
	this.gotoPreviousIdIndex = function()
	{
		if(this.currIdIndex == 0)
		{
			this.gotoIdIndex(this.htmlIds.length - 1);
		}
		else
		{
			this.gotoIdIndex(this.currIdIndex - 1);
		}
	}	
	this.gotoIdIndex = function(idIndex)
	{
		//if not done transitioning, try again in a 10th of a second
		if (!this.fader.lastFadeFinished)
		{
			var cyclerObj = this;
			setTimeout(function() {cyclerObj.gotoIdIndex(idIndex);}, 100);
			return;
		}
		
		//Make sure the passed idIndex exists
		if (!this.htmlIds[idIndex])
		{
			alert("This id index doesn't exist.  Please notify Instmation Systems of this error so they can fix the problem.'");
			return;
		}
		
		if (this.gotoIdIndexCode)
		{
			eval(this.gotoIdIndexCode);
		}
		
		//move last slide down
		document.getElementById(this.htmlIds[this.currIdIndex]).style.zIndex = "0";
		
		if (this.lastIdIndex)
		{
			this.fader.setOpacity(this.htmlIds[this.lastIdIndex], 0);
		}
		
		this.lastIdIndex = this.currIdIndex;
		this.currIdIndex = idIndex;
		
		//move new slide to top
		document.getElementById(this.htmlIds[idIndex]).style.zIndex = "1";
		
		this.fader.fadeIn(this.htmlIds[idIndex], this.speed);
	}
	this.resetTimer = function()
	{
		if (this.cycleTimeOut)
		{
			clearTimeout(this.cycleTimeOut);
		}
		var cyclerObj = this;
		this.cycleTimeOut = setTimeout(function() {cyclerObj.cycleToNextDiv();}, this.delay);
	}
	this.pause = function()
	{
		this.paused = true;
		if (this.cycleTimeOut)
		{
			clearTimeout(this.cycleTimeOut);
		}
		
		if (this.onPauseCode)
		{
			eval(this.onPauseCode);
		}
	}	
	this.play = function()
	{
		//alert("play");
		
		//if not done transitioning, try again in a 10th of a second
		if (!this.fader.lastFadeFinished)
		{
			var cyclerObj = this;
			setTimeout(function() {cyclerObj.play();}, 100 );
			return;
		}
		this.paused = false;
		
		if (this.lastIdIndex !== undefined)
		{
			this.cycleToNextDiv();
		}
		else
		{
			var cyclerObj = this;
			this.cycleTimeOut = setTimeout(function() {cyclerObj.cycleToNextDiv();}, this.delay);
		}
	}
	this.cycleToNextDiv = function()
	{	
		//alert("cycleToNextDiv");
		var cyclerObj = this;
		//If we paused the cycler, return without setting up another cycle, thus stopping
		if (this.paused)
		{
			return;
		}
		
		//if not done transitioning, try again in a 10th of a second
		if (!this.fader.lastFadeFinished)
		{
			this.cycleTimeOut = setTimeout(function() {cyclerObj.cycleToNextDiv();}, this.delay);
			return;
		}

		//move last slide down
		document.getElementById(this.htmlIds[this.currIdIndex]).style.zIndex = "0";
		
		//get next slide
		var nextIndex = this.currIdIndex + 1;
		if (!this.htmlIds[nextIndex])
		{
			nextIndex = 0;
		}
		if (this.lastIdIndex)
		{
			this.fader.setOpacity(this.htmlIds[this.lastIdIndex], 0);
		}
		this.lastIdIndex = this.currIdIndex;
		this.currIdIndex = nextIndex;
		
		//move new slide to top
		document.getElementById(this.htmlIds[nextIndex]).style.zIndex = "1";
		
		this.fader.fadeIn(this.htmlIds[nextIndex], this.speed);
		
		this.cycleTimeOut = setTimeout(function() {cyclerObj.cycleToNextDiv();}, this.delay);
	}

	this.onTransitionBegins = function (codeToRun)
	{
		this.onTransitionEndsCode = codeToRun;
	}
	
	this.onTransitionEnds = function (codeToRun)
	{
		this.onTransitionEndsCode = codeToRun;
	}
}
