// Initializations...

//Check if the browser use filter on the object
//Local Function.
function opc_object_use_filter(obj)
{
	if (typeof obj.style.opacity != "undefined")
	{
		return false;
	} else {
		return ((typeof obj.style.filter) != "undefined");
	}
}

//return the current opacity value of a given object
//Global Function.
function opcOpacityCurrent(obj)
{
	if (opc_object_use_filter(obj))
	{
		//IE5/IE6
		var filter_string = obj.style.filter;
		//IE will return something like "alpha(opacity=60)" in the above statement
		//The regexp is to obtain the numbers
		var return_value = filter_string.match(/alpha\s*\(\s*opacity\s*=\s*(\d+)\s*\)/i);
		if (return_value == null)
		{
			return 0;
		} else {
			return parseInt(return_value[1]);
		}
	} else {
		return Math.ceil(document.defaultView.getComputedStyle(obj,null).getPropertyValue("opacity")*100);
	}
}

// opcChange, basic browser detecting opacity changing function.
// Global Function.
function opcChange(obj, opacity_value, hide)
{
	//var browser_name = navigator.appName;
	
	if (typeof obj == "object")
	{
		if ((typeof hide) == "undefined" || hide)
			if (opacity_value == 0)
			{
				obj.style.visibility = "hidden";
			} else {
				obj.style.visibility = "visible";
			}
			
		
		if (opc_object_use_filter(obj))
		{
			switch (obj.tagName)
			{
				case "SPAN":
				case "DIV":
					//document.title+=obj.parentNode.tagName;
					if (obj.parentNode.tagName == "TD")
					{
						//if (obj.parentNode.id.match(/^opc_temp_obj_\d+$/))
						//{
							obj = obj.parentNode;
						/*} else {
							var temp_table = document.createElement("table");
							temp_table.cellSpacing = 0;
							temp_table.cellPadding = 0;
							temp_table.border = 0;
							
							var temp_tr = document.createElement("tr");
							var temp_td = document.createElement("td");
							temp_td.id = "opc_temp_obj_"+Math.floor(Math.random()*65535);
							
							var parentObj = obj.parentNode;
							
							temp_td.appendChild(obj);
							temp_tr.appendChild(temp_td);
							temp_table.appendChild(temp_tr);
							
							parentObj.appendChild(temp_table);
							
							obj = temp_td;
						}*/
					}
					break;
			}
			obj.style.filter = "alpha(opacity=" + opacity_value + ")";
			
			//alert(obj.id+"\n"+obj.style.filter+"\n"+obj.style.visibility+"\n\n"+obj.parentNode.parentNode.parentNode.id);
			
			//obj.filters.alpha.opacity = opacity_value;
		} else {
			obj.style.opacity = opacity_value/100;
		}
	}
}



// The core part.
// Defines an object that remembers what to do at each time.
// Local definition function.
function opcSettingInitialize()
{
	this.Timetable = new Array();
	this.TimeOutHnd = new Array();
	this.AddTimechild = function (time_target, obj, opacity_value)
									{
										if (typeof this.Timetable[time_target] == "undefined")
										{
											this.Timetable[time_target] = new Array();
										}
										
										// Find new element ID of the array
										var new_id = this.Timetable[time_target].length;
										this.Timetable[time_target][new_id] = new Object;
										this.Timetable[time_target][new_id].obj = obj;
										this.Timetable[time_target][new_id].opacity_value = opacity_value;
									}
	this.ClearTimechild = function (time_target)
									{
										if (typeof this.Timetable[time_target] != "undefined")
										{
											delete this.Timetable[time_target];
											return true;
										} else {
											return false;
										}
									}
	this.ClearTimetable = function ()
									{
										//for (time_child in this.TimeOutHnd)
										//{
										//	window.clearTimeout(this.TimeOutHnd(time_child));
										//}
										this.Timetable = new Array();
									}
}

var opcSetting = new opcSettingInitialize();

// ---------------------------------------------------------------------------------------------------------
// Main Part.
// This script targets to reduce the number of setTimeout() functions to a minimum.
// It records what the script needs to do at a certain time frame in opcSetting, and setTimeout() for a fixed amount of times to trigger opcTimeoutChange to do whatever required in opcSetting.
// This results in more complex coding, but would give a smoother animation in slower computers.


// At a certain timeout time, call opcTimeoutChange to change opacities of that moment
// Local function.
function opcTimeoutChange(time_now)
{
	if (typeof opcSetting.Timetable[time_now] != "undefined")
	{
		for (TimeChild in opcSetting.Timetable[time_now])
		{
			opcChange(opcSetting.Timetable[time_now][TimeChild].obj, opcSetting.Timetable[time_now][TimeChild].opacity_value);
		}
		
		opcSetting.ClearTimechild(time_now);
		return true;
	} else {
		return false;
	}
}


// Fade a group of objects with randomization available.
// From an array of objects, set the timeout schedule for opcTimeoutChange to happen. Main function to call from page.
// Global function.
function opcArrayAnimation(obj_array, opacity_start, opacity_end, opacity_interval, time_interval, time_initialize, randomize)
{
	var now = new Date();
	
	var time_now = now.getSeconds()*1000 + now.getMilliseconds();
	var obj_number_current =0;
	var time_start_current = 0;
	var time_current =0;
	var opacity_current =0;
	
	//Check if opacity_interval is in the correct direction
	if ((opacity_end - opacity_start) / opacity_interval < 0) 
	{
		time_interval = -1 * time_interval;
	}
	
	for (obj_no in obj_array)
	{
		if (typeof obj_array[obj_no] != "undefined")
		{
			
			if (typeof (randomize) == "undefined" || randomize)
			{
				time_start_current = Math.round(Math.random() * time_initialize / time_interval) * time_interval;
			} else {
				time_start_current = Math.round(obj_number_current * (time_initialize / (obj_array.length - 1) / time_interval)) * time_interval;
			}
			
			time_current =0;
			
			var opacity_direction = Math.abs(opacity_interval)/opacity_interval;
			
			for (opacity_current=opacity_start; opacity_direction*opacity_current < opacity_direction*opacity_end; opacity_current += opacity_interval)
			{
				opcSetting.AddTimechild(time_start_current + time_current + time_now, obj_array[obj_no], opacity_current);
				time_current += time_interval;
			}
			opcSetting.AddTimechild(time_start_current + time_current + time_now, obj_array[obj_no], opacity_end);
			
			obj_number_current++;
		}
	}
	
	
	for (time_child in opcSetting.Timetable)
	{
		opcSetting.TimeOutHnd["time_child"] = window.setTimeout("opcTimeoutChange("+time_child+")", time_child - time_now);
	}
	
	return opcSetting.Timetable.length;
}


// Fading of a single object
function opcGradient(obj, opacity_start, opacity_end, opacity_interval, time_interval)
{
	opcArrayAnimation(new Array(obj), opacity_start, opacity_end, opacity_interval, time_interval, 0, true);
}

// Cross fading of one object into another
// NOTE: final_html_ref is NOT quoted in the output, therefore it is expecting a variable rather than a chunk of HTML codes. Use Textarea.value or a global value for this purpose.
var opcCrossFade_current = new Array();
function opcCrossFade(obj, group, final_html_ref, opacity_end, opacity_interval, time_interval)
{
	if (typeof opcCrossFade_current[group] == "undefined")
		opcCrossFade_current[group] = 0;
	
	opcCrossFade_current[group]++;
	
	var current_opacity = opcOpacityCurrent(obj);
	var required_time_fadeout = (Math.ceil(current_opacity / opacity_interval)+1) * time_interval;
	
	opcGradient(obj, current_opacity, 0, -1*opacity_interval, time_interval);
	window.setTimeout("if (opcCrossFade_current['"+group+"'] == "+opcCrossFade_current[group]+") {document.getElementById('"+obj.id+"').innerHTML = "+final_html_ref+";}", required_time_fadeout);
	window.setTimeout("if (opcCrossFade_current['"+group+"'] == "+opcCrossFade_current[group]+") {opcGradient(document.getElementById('"+obj.id+"'), 0, "+opacity_end+", "+opacity_interval+", "+time_interval+")}", required_time_fadeout+300);
	
	return true;
}
