/** 
* @author   $Author: martijn $
* @revision $Revision: 2 $
* @date     $Date: 2009-02-11 15:58:55 +0100 (Wed, 11 Feb 2009) $
*
* this fotofader class can be used to fade images in and out
* it works with a div and an image inside it.
* - the div this.as the back and has a image as background, from now on called : back
* - the image in it works like the front, from now on called : front
*
* the back never fades in or out, only the front fades in and out.
* when the front is 100% visible, the back is not visible (because the front is overlapping it), thus the back image can be changed without notice 
* other way around, when the front is 0% visible (thus hidden), the back is shown and the front can be changed without notice
*/


/**
* fotoFader class
*/

fotoFader = function()
{
	
	// This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.
	var self = this;

	this.fotoFaderBack         = 'carousel_image1'; // todo make this configurable/settable 
	this.fotoFaderFront        = 'carousel_image2'; // todo make this configurable/settable
	this.imageCollection       = Array();           // array which holds the images which will fade
	this.aLinks                = Array();			// array which holds the links for the images
	this.aTabNames             = Array();			// array which holds the names for the tabs
	this.imageCollectionSize   = 0;                 // will be filled automatically
	this.imageToDisplay        = 0;                 // holds the image to fade in/out. the initial displayed image is 0
	this.imageAlpha            = 100;               // the initial alhpa value of initial image
	this.displayTime           = 5000;              // nr of millisecs that a image is displayed before fading. todo make this publicaly configurable/settable
	this.fadeSpeed             = 50;                // the smaller the faster the fading. todo make this publicaly configurable/settable

	// the fadebuttons get created from the image titles
	this.showFadePosition      = true;              // create "buttons" to show and override the current position
	this.fadeButtonClassActive = "buttonactive";    // which class must the buttons have when it is highlighted
	this.addFadeButtonsTo      = "carousel_buttons";// ID of the object in which the buttons should be placed

	this.oTimeout;
	this.overRideTo;

	/**
	* Does some inital testing and setting up
	*/
	this.initFotoFader = function(sFadeObject, sButtonsObject)
	{
		// object to place images in is not found - exiting
		if(!document.getElementById(sFadeObject)) return;

		this.sFadeObject = sFadeObject;

		if(sButtonsObject) this.addFadeButtonsTo = sButtonsObject;

		this.loadImages();
		this.buildHTML();

		// are there more then 1 image?
		if(this.imageCollectionSize <= 1) 
		{
			// no, there is just 1 image, don't do anything
			return;
		}

		// build the buttons for the different slides
		if(this.showFadePosition == true)
		{
			bShowNumbers = false;
			if(this.aTabNames.length != this.imageCollectionSize)
			{
				bShowNumbers = true;
			}

			oButtonContainer = document.getElementById(this.addFadeButtonsTo);

			for(i = 0; i < this.imageCollectionSize; i++)
			{
				var tag = document.createElement("div");
				tag.id = "carouselbutton_" + i;
				tag.onclick = function () { fotoFader.overrideFader(this.id); }

				var tabbegin = document.createElement("div");
				tabbegin.className = "tabbegin";

				var tabcontent = document.createElement("div");
				tabcontent.className = "tabcontent";

				var tabend = document.createElement("div");
				tabend.className = "tabend";

				if(bShowNumbers)
					tabcontent.innerHTML = (i + 1);
				else
					tabcontent.innerHTML = this.aTabNames[i];

				tag.appendChild(tabbegin);
				tag.appendChild(tabcontent);
				tag.appendChild(tabend);

				oButtonContainer.appendChild(tag);
			}
		}


		// there is more then 1 image, assume there already is a front image, so start with fading out		
		// start with fading in, but because the front alpha already is 100, 
		// a new back will be loaded and fading the front out will start after display time
		fotoFader.fadeInFront();
	}


	this.loadImages = function()
	{
		oFadeObject = document.getElementById(this.sFadeObject);
		aChildren = oFadeObject.getElementsByTagName("a");

		iNumLinks = aChildren.length;
		this.imageCollectionSize = iNumLinks;

		for(i = 0; i < iNumLinks; i++)
		{
			oChild = aChildren[0];

			this.aLinks[i] = oChild.href;
			oImage = oChild.getElementsByTagName("img");

			this.aTabNames[i] = oImage[0].title;
			this.imageCollection[i] = oImage[0].src;

			oFadeObject.removeChild(oChild);
		}

		return true;
	}

	this.buildHTML = function()
	{
		oFadeObject = document.getElementById(this.sFadeObject);

		oBackDiv = document.createElement("div");
		oBackDiv.id = this.fotoFaderBack;
		oBackDiv.style.position = 'absolute';
		oBackDiv.style.zIndex = 1;
		oBackDiv.style.backgroundImage = 'url('+this.imageCollection[1]+')';
		// this onclick is propably not necessary
		oBackDiv.onclick = function() { fotoFader.click(); };

		oFadeObject.appendChild(oBackDiv);

		oFrontDiv = document.createElement("div");
		oFrontDiv.id = this.fotoFaderFront;
		oFrontDiv.style.position = 'absolute';
		oFrontDiv.style.zIndex = 2;
		oFrontDiv.style.backgroundImage = 'url('+this.imageCollection[0]+')';
		oFrontDiv.onclick = function() { fotoFader.click(); };

		oFadeObject.appendChild(oFrontDiv);
	}

	
	/**
	* Sets the back, background image expect urls without spaces
	*/
	this.setBack = function(backImageUrl)
	{
		document.getElementById(this.fotoFaderBack).style.backgroundImage = 'url(' + backImageUrl + ')';
	}

	
	/**
	* Set the front, front image
	*/
	this.setFront = function (frontImageUrl)
	{
		// set a nwe background image into the front
		document.getElementById(this.fotoFaderFront).style.backgroundImage = 'url(' + frontImageUrl + ')';
	}
	
	
	/**
	* Handles the fading in of the front (from 0 to 100%)
	* Sets a new back image and starts the fading out (again)
	*/
	this.fadeInFront = function() 
	{
		// increase the alpha of the front image
		this.imageAlpha += 5;
		this.setFrontOpacity(this.imageAlpha);
		
		if(this.imageAlpha >= 100)
		{
			// when fading in is 100% done, load the next photo into the back


			if(this.showFadePosition == true)
			{
				// when using buttons to show the current fade position, highlight the current button
				this.delightButtons();
				oButtonObject = document.getElementById("carouselbutton_" + this.imageToDisplay);
				oButtonObject.className = this.fadeButtonClassActive;
			}

			// increment the image to display
			this.imageToDisplay++;

			if(this.imageToDisplay >= this.imageCollectionSize) 
			{
				// when there is no more next image restart
				this.imageToDisplay = 0;
			}
		

			this.setBack(this.imageCollection[this.imageToDisplay])
			
			// start fading out the front after dipslay time
			this.oTimeout = setTimeout( function() { fotoFader.fadeOutFront(); }, this.displayTime);
			
		}
		else
		{
			// continue fading in
			setTimeout( function() { fotoFader.fadeInFront(); }, this.fadeSpeed);
			
		}
	}
	
	/**
	* Handles the fading out of the front image (from 100 to 0)
	* Sets a new front image and starts the fading in (again)
	*/
	this.fadeOutFront = function()
	{
		// decrease the alpha for the front image
		this.imageAlpha -= 5;
		this.setFrontOpacity(this.imageAlpha);
		
		if(this.imageAlpha <= 0)
		{
			// when the front image is invisible, set a new front image


			if(this.showFadePosition == true)
			{
				// when using buttons to show the current fade position, highlight the current button
				this.delightButtons();
				oButtonObject = document.getElementById("carouselbutton_" + this.imageToDisplay);
				oButtonObject.className = this.fadeButtonClassActive;
			}

			// increment image to display
			this.imageToDisplay++;

			if(this.imageToDisplay >= this.imageCollectionSize) 
			{
				// when there is no more next image restart
				this.imageToDisplay = 0;
			}
	
			// set the next image into the front
			this.setFront(this.imageCollection[this.imageToDisplay]);
			
			// start fading in after display time
			this.oTimeout = setTimeout( function() { fotoFader.fadeInFront(); }, this.displayTime);
		}
		else
		{
			// continue fading out
			setTimeout( function() { fotoFader.fadeOutFront() }, this.fadeSpeed);
		}
	}
	
	/**
	* Sets the opacity of the front
	*/
	this.setFrontOpacity = function(iAlpha)
	{
		//alert('setFrontOpacity(' + iAlpha + ')');
		
		oObject = document.getElementById(this.fotoFaderFront);
		oObject.style.filter = 'alpha(opacity = ' + iAlpha + ')'; // for IE
		oObject.style.opacity = (iAlpha / 100);                   // for every other decent browser
	}

	/**
	* delights all buttons, when using buttons to display the current image
	*/
	this.delightButtons = function()
	{
		for(i = 0; i < this.imageCollectionSize; i++)
		{
			oCurrentButton = document.getElementById("carouselbutton_" + i);
			oCurrentButton.className = '';
		}
	}

	/**
	* manually overrides the current position
	*/
	this.overrideFader = function(sFadeTo)
	{
		// need to call the fotoFader object, instead of this, because it is called from outside the object (by onclick)

		iFadeTo = sFadeTo.replace("carouselbutton_", "");
		fotoFader.imageToDisplay = iFadeTo;
		// stop fading
		clearTimeout(fotoFader.oTimeout);

		if(fotoFader.imageAlpha >= 100 || fotoFader.imageAlpha <= 0)
		{
			// currently not fading, safe to load new image
			if(fotoFader.imageAlpha >= 100)
			{
				// front is being displayed, load back image and start fading
				fotoFader.setBack(fotoFader.imageCollection[iFadeTo]);
				// wait 250ms to load the image
				setTimeout( function() { fotoFader.fadeOutFront(); }, 250);
			}
			else
			{
				// background is being displayed, load front image and start fading
				fotoFader.setFront(fotoFader.imageCollection[iFadeTo]);
				// wait 250ms to load the image
				setTimeout( function() { fotoFader.fadeInFront(); }, 250);
			}
		}
		else
		{
			// currenty in the process of fading, calculate the maximum time it will take to finish, and try again
			if(fotoFader.imageAlpha >= 50)
				iMaxStepsRemaining = (fotoFader.imageAlpha / 5);
			else
				iMaxStepsRemaining = ((100 - fotoFader.imageAlpha) / 5);

			iTimeToWait = (iMaxStepsRemaining * fotoFader.fadeSpeed);
			setTimeout( function() { fotoFader.overrideFader(sFadeTo); }, iMaxStepsRemaining);
		}
	}


	this.click = function()
	{
		iLink = (this.imageToDisplay - 1);
		if(iLink == -1) iLink = (this.imageCollectionSize - 1);

		if(typeof(this.aLinks[iLink]) == "string") window.location = this.aLinks[iLink];
	}
}

