	/* animation.js contains helper functions for simple animation of objects */

// IE is painfully slow in many aspects when it comes to effects. Especially with larger objects.
// In these cases, try to balance using the IEHandicap property.
//
function animation(obj, fwdStartCSS, bkwdEndCSS)
{
	// Settings
	this.steps = new Array();
	this.obj = obj;
	this.delay = 40;
	this.IEHandicap = 1;
	this.repeat = null;
	this.fwdStartCSS = fwdStartCSS;
	this.bkwdEndCSS = bkwdEndCSS;

	// Progress/State
	this.current_step = null;
	this.running = null;

	// Statistics
	this.stats_stepcount = null;
	this.stats_fps = null;
	this.stats_runtime = null;

	// Internal
	var function_ref = this;
	this.current_timeoutID = null;
	this.adj_delay = 0;
	this.constantCSS = obj.style.cssText;
	this.starttime = null;

	// Internal info for helper functions
	this.is_animation = true;
	
	this.adjust_delay = function adjust_delay(delay)
	{
		if (delay)
		{
			this.delay = delay;
		}
		
		if (this.obj.filters) // IE is painfully slow on larger items, this could help a little.
		{
			this.adj_delay = this.delay/this.IEHandicap;
		}
		else
		{
			this.adj_delay = this.delay;
		}	
	}
	
	this.set_framerate = function set_framerate(rate)
	{
		this.delay = rate / 1000;
		this.adjust_delay();
	} 
	

	this.init_run = function init_run()
	{
		// Abort current run if running
		if (this.current_timeoutID) 
		{
			clearTimeout(this.current_timeoutID)
		}
		// Init stats
		this.starttime = new Date(); 
		this.stats_stepcount = 0;	
		this.stats_runtime = null;
		this.stats_fps = null;
		// If not done, set CSS startoff value
		this.constantCSS = obj.style.cssText;
		// Adjust delay
		this.adjust_delay();
	}
	
	this.end_run = function end_run()
	{
		// Calculate and save stats
		var newtime = new Date();
		function_ref.stats_runtime = Number(newtime.getTime() - function_ref.starttime.getTime());
		function_ref.stats_fps = function_ref.stats_stepcount / function_ref.stats_runtime * 1000;
		function_ref.current_timeoutID = null;
		function_ref.current_step = null;
	}	
	
	this.pause = function pause()
	{
		if (this.current_timeoutID)
		{
			clearTimeout(this.current_timeoutID)
		}
	}
	this.stop = function stop()
	{
		this.pause();
		this.end_run();	
	}

	this.play_fwd = function play_fwd()
	{	
		if (!this.current_step) 
		{
			this.current_step = 0;
			if (this.fwdStartCSS)
			{
				this.obj.style.cssText = this.fwdStartCSS;
			}
		}
		if (this.current_timeoutID)
		{
			clearTimeout(this.current_timeoutID)
		}
		else
		{
			this.init_run();
		}
		this.step_fwd();
		
	}
	
	this.play_rev = function play_rev()
	{
		if (!this.current_step) 
		{
			this.current_step = this.steps.length - 1;
		}
		if (this.current_timeoutID)
		{
			clearTimeout(this.current_timeoutID)
		}
		else
		{
			this.init_run();
		}
		this.step_bkwd();
	}
	
	this.add_step = function add_step(CSS)
	{
		this.steps.push(CSS);		
	}
	
	this.step_fwd = function step_fwd()
	{	
		if (function_ref.current_step < function_ref.steps.length)
		{
			function_ref.obj.style.cssText = function_ref.constantCSS + function_ref.steps[function_ref.current_step];
			function_ref.current_timeoutID = setTimeout(step_fwd, function_ref.adj_delay);
			function_ref.current_step ++;
			function_ref.stats_stepcount++;
		}
		else
		{
			if (function_ref.repeat)
			{
				function_ref.current_step = 0;
				step_fwd();
			}
			else
			{
				function_ref.end_run();
			}
		}
	}
	
	this.step_bkwd = function step_bkwd()
	{	
		
		if (function_ref.current_step > -1)
		{
			function_ref.obj.style.cssText = function_ref.constantCSS + function_ref.steps[function_ref.current_step];
			function_ref.current_timeoutID = setTimeout(step_bkwd, function_ref.adj_delay);
			function_ref.current_step --;
			function_ref.stats_stepcount++;
		}
		else
		{

			if (function_ref.repeat)
			{
				function_ref.current_step = function_ref.steps.length - 1;
				step_bkwd();
			}
			else
			{
				function_ref.end_run();
				if (function_ref.bkwdEndCSS)
				{
					function_ref.obj.style.cssText = function_ref.bkwdEndCSS;
				}
			}
		}
	}

}

function set_opacity(obj, value)
{
	if (obj.filters) 
	{ 
		obj.style.cssText += ';filter:progid:DXImageTransform.Microsoft.Alpha(opacity=' + value + ');';
	}
	else
	{
		obj.style.opacity = Number(value) / 100;
	}	
}

function init_filter(obj) // Init IE filter 
{
	if (obj.filters)
	{
		obj.style.filter = "progid:DXImageTransform.Microsoft.Alpha()";
	}
}

function get_opacity(obj, value)
{
	if (obj.filters) 
	{ 
		init_filter(obj);
		return obj.filters.item( "progid:DXImageTransform.Microsoft.Alpha").opacity;
	}
	else
	{
		if (obj.style.opacity)
		{
			return obj.style.opacity * 100;
		}
		else
		{
			return 100;
		}
	}	
}


function fade_object(obj, from, to, style)
{
	
	if (obj.is_animation)
	{
		var curr_anim = obj;
		var curr_obj = obj.obj;
	}
	else
	{
		var curr_anim = new animation(obj);
		var curr_obj = obj;
	}
	
	if (style==1) // curr_opacity = curr_opacity + 1 + Math.round((to - curr_opacity) * 0.1) fade
	{
		var fade_value;
		if (from == null)
		{
			var from = get_opacity(curr_obj);
		}
		for (var curr_opacity = from; curr_opacity <= to;curr_opacity = curr_opacity + 1 + Math.round((to - curr_opacity) * 0.1) )
		{
			if (curr_obj.filters)
			{
				curr_anim.add_step(';filter: progid:DXImageTransform.Microsoft.Alpha(opacity='+ curr_opacity +')');
			}
			else
			{
				curr_anim.add_step(';opacity:'+(curr_opacity/100));
			}
		}
		if (!obj.is_animation)
		{
			curr_anim.play();
			return curr_anim;
		}
	}
}

function add_step_for_each(anim,from, to, callback)
{
	if (!anim.obj) {alert("The add_step_for_each currently needs the object to be set to determine IE filter existence.")}
	else
	{
		if (anim.obj.filters)
		{
			var hasfilter = true;
		}
		else
		{
			var hasfilter = false;
		}
	}
	var lastval;
	for (i = from;i < to; i++)
	{
		lastval = callback(i, lastval, hasfilter);
		anim.add_step(lastval);
	}
}