/* ryofade - a function that allows to fade HTML elements.
 *
 * $Id$
 * Copyright (C) 2005 IrYoKu
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * IrYoKu (iryoku@terra.es)
 */


/* Implements a color fade using the W3 DOM Level 1
   Note: "newNIterations" y "newIterationTime" are optional (see default values below). */
fadeElement.ccId = 0;
fadeElement.tasks = new Array();
function fadeElement(element, newColor, property, newNIterations, newIterationTime, end)
{
	/* Default configuration */
	var nIterations = 20;
	var iterationTime = 20;
	property = property? property : 'color';

	if (document.getElementById && window) {
		if (element.id == '') {
			fadeElement.ccId++;
			while (document.getElementById('ccId' + fadeElement.ccId)) {
				fadeElement.ccId++;
			}
			element.id = 'ccId' + fadeElement.ccId;
		}
		var taskId = element.id + property; /* This allows to simultaneously change various properties in the same element */
		if (typeof fadeElement.tasks[taskId] == 'undefined') {
			fadeElement.tasks[taskId] = new fadeElementTask(element, property);
			fadeElement.tasks[taskId].change(newColor, newNIterations, newIterationTime, end);
		} else {
			fadeElement.tasks[taskId].change(newColor, newNIterations, newIterationTime, end);
		}
	}

	function fadeElementTask(element, property)
	{
		function change(newColor, newNIterations, newIterationTime, end)
		{
			this.nIterations = newNIterations? newNIterations : this.nIterations;
			this.iterationTime = newIterationTime? newIterationTime : this.iterationTime;
			this.end = end? end : null;
			this.targetRed = parseInt(newColor.substring(1,3), 16);
			this.targetGreen = parseInt(newColor.substring(3,5), 16);
			this.targetBlue  = parseInt(newColor.substring(5,7), 16);
			this.redStep = (this.targetRed  - this.red) / this.nIterations;
			this.greenStep = (this.targetGreen - this.green) / this.nIterations;
			this.blueStep = (this.targetBlue  - this.blue) / this.nIterations;
			if (this.working == false) {
				this.working = true;
				this.start();
			}
		}


		function start()
		{
			if ((this.redStep > 0 && this.red + this.redStep < this.targetRed) || (this.redStep < 0 && this.red + this.redStep > this.targetRed)) {
				this.red += this.redStep;
			} else {
				this.red = this.targetRed;
			}
			if ((this.greenStep > 0 && this.green + this.greenStep < this.targetGreen) || (this.greenStep < 0 && this.green + this.greenStep  > this.targetGreen)) {
				this.green += this.greenStep;
			} else {
				this.green = this.targetGreen;
			}
			if ((this.blueStep > 0 && this.blue + this.blueStep < this.targetBlue) || (this.blueStep < 0 && this.blue + this.blueStep > this.targetBlue)) {
				this.blue += this.blueStep;
			} else {
				this.blue = this.targetBlue;
			}
			var newColor = '#' + pad(Math.floor(this.red).toString(16)) + pad(Math.floor(this.green).toString(16)) + pad(Math.floor(this.blue).toString(16));
			this.element.style[this.property] = newColor;
			if (this.red  != this.targetRed || this.green != this.targetGreen || this.blue  != this.targetBlue) {
				window.setTimeout("fadeElement.tasks['" + this.taskId + "'].start()", this.iterationTime);
			} else {
				this.working = false;
				if (this.end) {
					if (typeof(this.end) == 'function') {
						this.end();
					} else {
						eval(this.end);
					}
				}
			}
		}


		this.element = element;
		this.property = property;
		this.taskId = element.id + property;
		this.start = start;
		this.change = change;
		this.working = false;
		this.nIterations = nIterations;
		this.iterationTime = iterationTime;
		var reHex = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;
		var reRgb = /^rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)$/i;
		var color;
		if ((color = reHex.exec(this.element.style[this.property])) != null) {
			this.red  = parseInt(color[1], 16);
			this.green = parseInt(color[2], 16);
			this.blue  = parseInt(color[3], 16);
		} else if ((color = reRgb.exec(this.element.style[this.property])) != null) {
			this.red  = parseInt(color[1]);
			this.green = parseInt(color[2]);
			this.blue  = parseInt(color[3]);
		}
	}


	function pad(number)
	{
		if (number.length == 1) {
			number = '0' + number;
		}
		return number;
	}
}


/* Changes the color and background color of an element */
function swapFadeElement(element, backgroundColor, color, newNIterations, newIterationTime)
{
	fadeElement(element, backgroundColor, 'backgroundColor', newNIterations, newIterationTime);
	fadeElement(element, color, 'color', newNIterations, newIterationTime);
}

