/*
* LAYER OBJECT FUNCTIONS
* 
* Layer managment functions 
*
*/


/************************************************* LAYER OBJECT FUNCTIONS **************************************************/		

//var to hold layer objects as associative array
var layer_objs = new Object();

//constructor class for dynamic layer
function objStaticLyr (lyr_id,parent_array) {
	
	//set lyr id to id property
	this.id = lyr_id;
	
	//node path
	if (parent_array != null) this.node_path = parent_array.reverse();
	else this.node_path = null;
	
	//make shortcut to document object
	var d = document;
	
	//get refs to real layers
	if (document.layers) {
		this.layer = this.getLyrRef(lyr_id,parent_array);
	}
	else if (document.all) {
		this.element = d.all[this.id];
		this.style = d.all[this.id].style;
	}
	else if (document.getElementById) {
		this.element = d.getElementById(this.id);
		this.style = d.getElementById(this.id).style;
	}
	
	this.setDefaultProperties();	//call function to set default properties
	
}


//method to setup default properties
objStaticLyr.prototype.setDefaultProperties = function() {
	
	this.event_stack = new Array(0);	//array holding event actions waiting to execute
	this.event_stack_active = 0; //ref to stack activity (0 = off)
	
	this.fadeBgStatus = 8;	//set property holding fade status (initial val = no of fade steps)
	this.fadeArrayOn = null;	//var to hold fade array for layer
	this.fadeArrayOffActive = null;	//var to hold fade array for layer
	this.fadeArrayOffPassive = null;	//var to hold fade array for layer
	
	this.mouseover = false;
	
}

//----------------------------- define methods for objLyr class for NS Navigator 4.7
if (document.layers) {

	//methods for manipulating layer object
	objStaticLyr.prototype.moveTo = function(x,y) { this.layer.moveTo(x,y); }
	objStaticLyr.prototype.moveBy = function(x,y) { this.layer.moveBy(x,y); }
	objStaticLyr.prototype.show = function() { this.layer.visibility = 'show'; }
	objStaticLyr.prototype.hide = function() { this.layer.visibility = 'hide'; }
	objStaticLyr.prototype.setStackingOrder = function(z) { this.layer.zIndex = z; }
	objStaticLyr.prototype.setBgColor = function(color) { this.layer.bgColor = color; }
	objStaticLyr.prototype.setBgImage = function(image) { this.layer.background.src = image; }
	objStaticLyr.prototype.setWidth = function(width) { this.layer.width = width; }
	objStaticLyr.prototype.setHeight = function(height) { this.layer.height = height; }
	
	//method for dynamically writing contents of layer
	objStaticLyr.prototype.setBody = function(content_array) {
		//create regexp object for replacement
		this.layer.document.open();
		for (var i=0;i<content_array.length;i++) this.layer.document.writeln(content_array[i]);
		this.layer.document.close();
	}
	
	//methods for retrieving info on layer object
	objStaticLyr.prototype.getX = function() { return this.layer.left; }
	objStaticLyr.prototype.getY = function() { return this.layer.top; }
	objStaticLyr.prototype.getWidth = function() { return this.layer.clip.right; }
	objStaticLyr.prototype.getHeight = function() { return this.layer.clip.bottom; }
	objStaticLyr.prototype.getStackingOrder = function() { return this.layer.zIndex; }
	objStaticLyr.prototype.isVisible = function() { return this.layer.visibility == 'show'; }
	
	
	//add layer event handler
	objStaticLyr.prototype.addEventHandler = function (event_name, handler) {
		//set layer to capture events
		this.layer.captureEvents(objStaticLyr._eventmasks[event_name]);
		var objstaticlayer = this; //get ref to current obj for use in nested function
		
		//define an event handler that will invoke the specified handler
		this.layer[event_name] = function (e) { return handler(e, objstaticlayer, e.pageX, e.pageY, e.screenX, e.screenY); }
	}
	
	//remove layer event handler
	objStaticLyr.prototype.removeEventHandler = function (event_name) {
		this.layer.releaseEvents(objStaticLyr._eventmasks[event_name]);
		delete this.layer[event_name];
	}
	
	//array for mapping event name to event type
	objStaticLyr._eventmasks = {
	onblur:Event.BLUR, onfocus:Event.FOCUS, onclick:Event.CLICK,
	onmouseover:Event.MOUSEOVER, onmouseout:Event.MOUSEOUT
	}
	
	//function to get reference to layer (for ns4.7 only)
	objStaticLyr.prototype.getLyrRef = function(lyr_id,parent_array) {
		var str_lyr_path = '';
		if (parent_array != null) for (var i=0;i<parent_array.length;i++) str_lyr_path += 'document.layers.' + parent_array[i] + '.';
		return eval(str_lyr_path + 'document.' + lyr_id)
	}
	
}

//----------------------------- define methods for objLyr class for MSIE
else if (document.all) {
		
	//methods for manipulating layer object
	objStaticLyr.prototype.moveTo = function(x,y) {
		this.style.pixelLeft = x;
		this.style.pixelTop = y;
	}
	
	objStaticLyr.prototype.moveBy = function(x,y) {
		this.style.pixelLeft += x;
		this.style.pixelTop += y;
	}
	
	objStaticLyr.prototype.show = function() { this.style.visibility = 'visible'; }
	objStaticLyr.prototype.hide = function() { this.style.visibility = 'hidden'; }
	objStaticLyr.prototype.setStackingOrder = function(z) { this.style.zIndex = z; }
	objStaticLyr.prototype.setBgColor = function(color) { this.style.backgroundColor = color; }
	objStaticLyr.prototype.setBgImage = function(image) { this.style.backgroundImage = image; }
	objStaticLyr.prototype.setWidth = function(width) { this.style.width = width; }
	objStaticLyr.prototype.setHeight = function(height) { this.style.height = height; }
	
	//method for writing content to layer
	objStaticLyr.prototype.setBody = function(content_array) {
		var body = '';
		for (var i=0;i<content_array.length;i++) body += content_array[i] + '\n';
		this.element.innerHTML = body;
		
	}
	
	//methods for retrieving info on layer object
	objStaticLyr.prototype.getX = function() { return parseInt(this.style.pixelLeft); }
	objStaticLyr.prototype.getY = function() { return parseInt(this.style.pixelTop); }
	objStaticLyr.prototype.getWidth = function() { return parseInt(this.style.width); }
	objStaticLyr.prototype.getHeight = function() { return parseInt(this.style.height); }
	objStaticLyr.prototype.getStackingOrder = function() { return this.style.zIndex; }
	objStaticLyr.prototype.isVisible = function() { return this.style.visibility == 'visible'; }
	
	
	//layer event handling
	
	
	objStaticLyr.prototype.addEventHandler = function (event_name, handler) {
		var objstaticlyr = this; //get ref to current obj for use in nested function
		this.element[event_name] = function () {
			var e = window.event;
			//e.cancelBubble = true;
			return handler(e, objstaticlyr, e.clientX, e.clientY, e.screenX, e.screenY);
		}
	}
	
	
	objStaticLyr.prototype.removeEventHandler = function (event_name) {
		delete this.element[event_name];
	}
	
}


//----------------------------- define methods for objLyr class for geko-based browsers (ns6,mozilla)
else if (document.getElementById) {
		
	//methods for manipulating layer object
	objStaticLyr.prototype.moveTo = function(x,y) {
		this.style.left = x;
		this.style.top = y;
	}
	
	objStaticLyr.prototype.moveBy = function(x,y) {
		this.style.left += x;
		this.style.top += y;
	}
	
	objStaticLyr.prototype.show = function() { this.style.visibility = 'visible'; }
	objStaticLyr.prototype.hide = function() { this.style.visibility = 'hidden'; }
	objStaticLyr.prototype.setStackingOrder = function(z) { this.style.zIndex = z; }
	objStaticLyr.prototype.setBgColor = function(color) { this.style.backgroundColor = color; }
	objStaticLyr.prototype.setBgImage = function(image) { this.style.backgroundImage = image; }
	objStaticLyr.prototype.setWidth = function(width) { this.style.width = width; }
	objStaticLyr.prototype.setHeight = function(height) { this.style.height = height; }
	
	//method for writing content to layer
	objStaticLyr.prototype.setBody = function(content_array) {
		var body = '';
		for (var i=0;i<content_array.length;i++)
			body += content_array[i] + '\n';
		this.element.innerHTML = body;
		
	}
	
	//methods for retrieving info on layer object
	objStaticLyr.prototype.getX = function() { return parseInt(this.style.left); }
	objStaticLyr.prototype.getY = function() { return parseInt(this.style.top); }
	objStaticLyr.prototype.getWidth = function() { return parseInt(this.style.width); }
	objStaticLyr.prototype.getHeight = function() { return parseInt(this.style.height); }
	objStaticLyr.prototype.getStackingOrder = function() { return this.style.zIndex; }
	objStaticLyr.prototype.isVisible = function() { return this.style.visibility == 'visible'; }
	

	//layer event handling????????????????????
	
	objStaticLyr.prototype.addEventHandler = function (event_name, handler) {
		var objstaticlayer = this; //get ref to current obj for use in nested function
		//define an event handler that will invoke the specified handler
		this.element[event_name] = function (e) { 
			//e.cancelBubble = true;
			return handler(e, objstaticlayer, e.pageX, e.pageY, e.screenX, e.screenY); 
		}
	}
	
	objStaticLyr.prototype.removeEventHandler = function (event_name) {
		delete this.element[event_name];
	}
	
	//array for mapping event name to event type
	objStaticLyr._eventmasks = {
	onblur:Event.BLUR, onfocus:Event.FOCUS, onclick:Event.CLICK,
	onmouseover:Event.MOUSEOVER, onmouseout:Event.MOUSEOUT
	}	
	
}


//------------------------------ additional object methods

/***************************** 	EVENT STACK METHODS AND PROPERTIES ***************************************/

//function to add an event action to execution stack
objStaticLyr.prototype.addEvent = function (exec_string, exec_type, remove_group) {
	this.pauseEventStack();
	//window.alert(this.event_stack.length);
	//remove group events if set
	if (remove_group) this.removeEventGroup (exec_type);
	
	//add item to index
	var n = this.event_stack.length;
	this.event_stack[n] = new Object();
	this.event_stack[n].event_exec = exec_string;	//execution string
	this.event_stack[n].event_type = exec_type;	//event type (allows for group cancelling)
	
	this.startEventStack();
}

//function to remove event from event stack
objStaticLyr.prototype.RemoveEvent = function (pos) {
	this.pauseEventStack();
	
	var temp_array = new Array();	//create temporary array
	//loop through event stack array
	var i, n =0;
	for (i=0;i<this.event_stack.length;i++) {
		//if not selected event, then add to temp array
		if (i != pos) { temp_array[n] = this.event_stack[i]; n++; }
	}
	this.event_stack = temp_array;	//set event stack to temp array
	
	this.startEventStack();
}

objStaticLyr.prototype.removeEventGroup = function (exec_type) {
	this.pauseEventStack();
	
	var temp_array = new Array();	//create temporary array
	//loop through event stack array
	var i, n =0;
	for (i=0;i<this.event_stack.length;i++) {
		//if not selected event, then add to temp array
		if (this.event_stack[i].event_type != exec_type) { temp_array[n] = this.event_stack[i]; n++; }
	}
	this.event_stack = temp_array;	//set event stack to temp array
	
	this.startEventStack();
}

//function to start event stack monitoring
objStaticLyr.prototype.startEventStack = function () {
	if (this.event_stack_active == 0) this.event_stack_active = window.setInterval('layer_objs["'+this.id+'"].EventStackController()',15);
}

//function to pause event stack monitoring
objStaticLyr.prototype.pauseEventStack = function () {
	if (this.event_stack_active != 0) window.clearTimeout(this.event_stack_active);
	//window.alert (this.event_stack_active);
	this.event_stack_active = 0;
}

//function to execute events in event stack (started the first time event added to stack)
objStaticLyr.prototype.EventStackController = function () {
	//if there are any events in the stack then execute top event
	if (this.event_stack.length > 0) {
		eval(this.event_stack[0].event_exec);	//execute item
		this.RemoveEvent(0);	//remove item from event stack
	}
}



/***************************** 	FADING EFFECTS  ***************************************/

//function to fade layer background
objStaticLyr.prototype.fadeBg = function(state) {
	
	this.removeEventGroup('bg_fade');	//remove any fades that are waiting to return
	
	//set fade array if script running for first time
	if (this.fadeArrayOn == null) {
		//get dec values from hex strings
		var color1 = makeDecArray(this.off_color);
		var color2 = makeDecArray(this.roll_color);
		var color3 = makeDecArray(this.on_color);
		this.fadeArrayOn = setFadeArray(this.fadeBgStatus,color1,color2);
		this.fadeArrayOffActive = setFadeArray(this.fadeBgStatus,color2,color1);
		this.fadeArrayOffPassive = setFadeArray(this.fadeBgStatus,color3,color1);
	}
	
	//get local reference to fade array (if state is off then reverse fade array)
	//var temp_array = (state == 'on') ? this.fadeArrayOn  : this.fadeArrayOff;
	if (state == 'on') temp_array = this.fadeArrayOn;
	else if (state == 'off_active') temp_array = this.fadeArrayOffActive;
	else if ((state == 'off_passive') || (state == 'on_passive')) temp_array = this.fadeArrayOffPassive;
	
	var exec_str;	//var to hold exec string
	
	if (state == 'on_passive') {
	
		exec_str =  'layer_objs["' + this.id + '"].setBgColor("' + temp_array[0] + '");';	//set bg color
		exec_str += 'layer_objs["' + this.id + '"].fadeBgStatus=' + 0;	//set fadeBgStatus to current color
		this.addEvent(exec_str, 'bg_fade', false);
		
	}
	else {
	
		var start = ((temp_array.length-1) - this.fadeBgStatus);	//sets val to current array pos going opposite direction
		//add fade steps to event stack
		for (var i=start;i<temp_array.length;i++) {
			exec_str =  'layer_objs["' + this.id + '"].setBgColor("' + temp_array[i] + '");';	//set bg color
			exec_str += 'layer_objs["' + this.id + '"].fadeBgStatus=' + i;	//set fadeBgStatus to current color
			this.addEvent(exec_str, 'bg_fade', false);
		}
		
	}
	
}



/***************************** 	MATHEMATICAL CALCULATIONS  ***************************************/

// Defining a few global variables to keep things simpler and to avoid complications
var HexChars = "0123456789ABCDEF";
var RGBHexValue="#FFFFFF";
var RGBDecValue = "255,255,255";


// Created by T.N.W.Hynes - (c) 2002 PalandorZone.com ... Use it freely but leave this line intact
// Conversion function for Hexadecimal to Decimal - FF max
function Hex2Dec(HexVal){
	HexVal=HexVal.toUpperCase();
	var DecVal=0;
	var HV1=HexVal.substring(0,1);
	DecVal=(HexChars.indexOf(HV1)*16);
	HV1=HexVal.substring(1);
	DecVal+=HexChars.indexOf(HV1);
	return DecVal;
}


// Created by T.N.W.Hynes - (c) 2002 PalandorZone.com ... Use it freely but leave this line intact
// Conversion function for Decimal to Hexadecimal - 255 max
function Dec2Hex(DecVal){
	DecVal=parseInt(DecVal);
	if (DecVal > 255 || DecVal < 0){
		DecVal=255;
	}
	var Dig1 = DecVal % 16;
	var Dig2 = (DecVal-Dig1) / 16;
	var HexVal = HexChars.charAt(Dig2)+HexChars.charAt(Dig1);
	return HexVal;
}


//function to make dec array
function makeDecArray(str_hex) {
	if (str_hex.indexOf('#') == 0) str_hex = str_hex.substring(1,str_hex.length);	//remove preceding # if necessary
	var dec_array = new Array();
	dec_array[0] = Hex2Dec(str_hex.substring(0,2));
	dec_array[1] = Hex2Dec(str_hex.substring(2,4));
	dec_array[2] = Hex2Dec(str_hex.substring(4,6));
	return dec_array
}


//function to determine hex colors to get from color a - b
//num_frames = no of steps to get from color a - b; off_col_array = array[r,g,b] of out color; over_col_array = array[r,g,b] of over color
function setFadeArray(num_frames,off_col_array,over_col_array){
	
	//create array
	var i, col_diff_array = new Array(3);
	//calc steps for each part of rgb col array from off - over color
	for (i=0;i<3;i++) col_diff_array[i] = ((off_col_array[i] - over_col_array[i]) / num_frames);

	//create array object to hold returned hex values
	var n, temp_rgb, fade_step_array = new Array();	
	//determine hex colors for each step 
	for(i=0;i<=num_frames;i++){
		fade_step_array[i] = '#';	//start item with # (for css ref + makes string rather than addition)
		//set r/g/b colors
		for (n=0;n<3;n++) {
			temp_rgb = Math.round ( off_col_array[n]-(col_diff_array[n]*i) );	//get r/g/b ref for crnt step
			fade_step_array[i] += Dec2Hex(temp_rgb);	//convert r/g/b value to hexdec
		}
		
	}
	return fade_step_array
}

