/**************************************************

	CycleShow 2.0.4 r20110122
	by Jeremy Marquis
	
	Copyright (C) 2010 Jeremy Marquis
	
	This program is distributed under the GPLv3.
	Please see the included LICENSE file for more
	information.

**************************************************/

// Array of CycleShow objects
var CycleShow_objects = new Array();

// Main class
function CycleShow(divID)
{
	// Get the <div>
	this.container = document.getElementById(divID);
	
	// Initialize data members
	this.images = new Array();	// Image list
	this.currentImage = -1;	// Current image index (-1 because nothing is loaded yet)
	this.fadeStep = 0.05;	// Amount of opacity to adjust for each frame of fade
	this.fadeFrame = 50;	// Number of milliseconds between frames
	this.fadeInterval = 6000;	// Number of milliseconds between images
	this.interval = null;	// Interval object
	
	// Initialize object properties
	this.id = this.container.id;	// Identifier
	this.width = parseInt(this.container.style.width);	// The width of the entire fading banner
	this.height = parseInt(this.container.style.height);	// The height of the entire fading banner
	
	// Preloader
	this.preloader = document.createElement('div');
	this.preloader.style.display = 'none';
	this.container.appendChild(this.preloader);
	
	// Each object uses two faders
	this.fader1 = new CycleShow_Fader(this.id+'_fader1',this);
	this.fader2 = new CycleShow_Fader(this.id+'_fader2',this);
	
	// Add the faders to the container
	this.container.appendChild(this.fader1.imgElement);
	this.container.appendChild(this.fader2.imgElement);
	
	// Set the container to be the zero of the faders' positioning
	this.container.style.position = 'relative';
	
	// Now everything is initialized. The following methods take care of actual operations.
	
	// Begin
	this.start = function()
	{
		this.nextImg();
		
		var obj = this;
		this.interval = setInterval(function() { obj.nextImg(); },this.fadeInterval);
	}
	
	// Transition to the next image
	this.nextImg = function()
	{
		this.fadeOut();
		
		this.currentImage++;
		
		if(this.currentImage >= this.images.length)
			this.currentImage = 0;
		
		this.fadeIn();
	}
	
	// Fades out the active fader (if there is one)
	this.fadeOut = function()
	{
		if(this.fader1.isDisplaying())
			this.fader1.fadeOut();
		if(this.fader2.isDisplaying())
			this.fader2.fadeOut();
	}
	
	// Fades in the next image
	this.fadeIn = function()
	{
		var fader = this.getFader();
		fader.fadeIn(this.images[this.currentImage]);
	}
	
	// Returns a reference to the available fader
	this.getFader = function()
	{
		return this.fader1.isDisplaying() ? this.fader2 : this.fader1;
	}
	
	// Add file to image list and preload it
	this.addFile = function(filename)
	{
		this.images[this.images.length] = filename;
		this.preload(filename);
	}
	
	// Preload an object
	this.preload = function(filename)
	{
		var preloadImg = document.createElement('img');
		preloadImg.src = filename;
		this.preloader.appendChild(preloadImg);
	}
	
	// Set new fade frame value
	this.setFadeFrame = function(newFadeFrame)
	{
		this.fadeFrame = newFadeFrame;
		this.fader1.fadeFrame = newFadeFrame;
		this.fader2.fadeFrame = newFadeFrame;
	}
	
	// Set new fade step value
	this.setFadeStep = function(newFadeStep)
	{
		this.fadeStep = newFadeStep;
		this.fader1.fadeStep = newFadeStep;
		this.fader2.fadeStep = newFadeStep;
	}
	
	// Set new fade interval value
	this.setFadeInterval = function(newFadeInterval)
	{
		this.fadeInterval = newFadeInterval
	}
}

// Fader class
function CycleShow_Fader(newID,BFObj)
{
	// A fader is really just an <img>
	this.imgElement = document.createElement('img');
	
	// Initialize data members
	this.currentOpacity = 0;
	this.fadeStep = BFObj.fadeStep;
	this.fadeFrame = BFObj.fadeFrame;
	
	// Initialize properties
	this.imgElement.style.display = 'none';
	this.imgElement.style.opacity = '0.0';
	this.imgElement.style.MsFilter = 'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)';
	this.imgElement.style.position = 'absolute';
	this.imgElement.style.zIndex = '10';
	
	// Set ID
	this.id = newID;
	this.imgElement.id = this.id;
	
	/* For some reason this causes errors in IE. Disabling it doesn't seem to hurt anything
	// Set width and height
	this.imgElement.style.width = BFObj.width + "px";
	this.imgElement.style.height = BFObj.height + "px";
	*/
	
	// See if this fader is currently displaying
	this.isDisplaying = function()
	{
		return this.imgElement.style.display == 'block';
	}
	
	// Begin the fade out process
	this.fadeOut = function()
	{
		this.fadeOutStep();
	}
	
	// Perform one fade out frame
	this.fadeOutStep = function()
	{
		this.setOpacity(this.currentOpacity - this.fadeStep);
		if(this.currentOpacity <= 0)
		{
			this.setOpacity(0);
			this.imgElement.style.display = 'none';
		}
		else
		{
			var obj = this;
			setTimeout(function() { obj.fadeOutStep(); }, this.fadeFrame);
		}
	}
	
	// Begin the fade in process
	this.fadeIn = function(filename)
	{
		this.setOpacity(0);
		this.imgElement.src = filename;
		this.imgElement.style.display = 'block';
		this.fadeInStep();
	}
	
	// Perform one fade in frame
	this.fadeInStep = function()
	{
		this.setOpacity(this.currentOpacity + this.fadeStep);
		if(this.currentOpacity >= 1)
		{
			this.setOpacity(1);
		}
		else
		{
			var obj = this;
			setTimeout(function() { obj.fadeInStep(); }, this.fadeFrame);
		}
	}
	
	// Set fader opacity
	this.setOpacity = function(newOpacity)
	{
		this.currentOpacity = newOpacity;
		this.imgElement.style.opacity = this.currentOpacity;	// Non-IE
		this.imgElement.style.filter = 'alpha(opacity='+(this.currentOpacity*100)+')';	// IE5-7
		this.imgElement.style.MsFilter = 'progid:DXImageTransform.Microsoft.Alpha(Opacity='+(this.currentOpacity*100)+')';	// IE8
	}
	
	return this;
}
