/*************************************************************************
Name:	element.js
Desc:	element creation/handling

*************************************************************************/
//state values (used in stylesheet)
var ELEMENT_STATE_SELECTED =		'_selected';
var ELEMENT_STATE_OVER = 			'_over';
var ELEMENT_STATE_OVERSELECTED = 	'_overselected';
var ELEMENT_STATE_UP = 				'';
var ELEMENT_STATE_DOWN = 			'_down';
var ELEMENT_STATE_DISABLED = 		'_disabled';
var ELEMENT_STATE_INVALID = 		'_invalid';
	
	
	
	

//calls function on a target
//-should be located somewhere else...
function callFunc(target, func, data) {
	if (target == null) {
		if (func != null) {
			eval(func)(data);
		}
	} else {
		target[func](data);
	}
}




//--------------------------------------------------- SELECT (COMBOBOX)

//fills select with values
function fillSelect(element, nameArray, valueArray, index) {
	//remove existing children from select
	clearElement(element);
	
	//if no values given then just use indexes (0..length)
	if (valueArray == null) {
		valueArray = createNumberedArray(0, nameArray.length-1);
	}
	
	//go thru name array
	for (var i=0; i<nameArray.length; i++) {
		//get the params
		var name =	nameArray[i];
		var value = valueArray[i];
		
		//create option
		var opt = createElement('option', {value:value, innerHTML:name});

		//select if necessary
		if (index == i) {opt.selected = "selected";}
		
		//add options to select
		element.appendChild(opt, i);
	}
}


//---------------------------------------------------STYLESHEET

//apply state suffix to target element
function setStateSuffix(element, stateList) {
	var suffix = 	'';
	
	if (stateList != null) {
		var over = 		stateList['over'];
		var selected = 	stateList['selected'];
		var disabled = 	stateList['disabled'];
		var invalid = 	stateList['invalid'];
	
		if (disabled) {
			suffix = ELEMENT_STATE_DISABLED;
		} else if (over && selected) {
			suffix = ELEMENT_STATE_OVERSELECTED;
		} else if (over) {
			suffix = ELEMENT_STATE_OVER;
		} else if (selected) {
			suffix = ELEMENT_STATE_SELECTED;
		} else if (invalid) {
			suffix = ELEMENT_STATE_INVALID;
		}
	}
	
	var className = element.className;
	var suffix_pos = String(className).lastIndexOf('_');
	if (suffix_pos >= 0) {
		className = String(className).substr(0, suffix_pos);
	}
	element.className = className + suffix;
	return className;
}



//---------------------------------------------------GENERAL



//shortcut - returns a clear div
function clearDiv() {
	return createDiv({className:'clear'});
}





//creates a div - it is faster to clone a template div than to create a new element
var template_div = createElement('div');
function createDiv(propObj) {
	var obj = template_div.cloneNode(false);	//bool(false) = clone child nodes
	setProperties(obj, propObj);
	return obj;
}




//create an element (sets properties also)
function createElement(type, propObj) {
	var obj = document.createElement(type);
	setProperties(obj, propObj);
	return obj;
}

//sets properties of an object
function setProperties(obj, propObj) {
	for (var prop in propObj) {
		obj[prop] =	propObj[prop];
	}
}


//shortcut to get element
function getElement(id) {
	return document.getElementById(id);
}

//removes all children from (and purges) a target element
function clearElement(element) {
	if (element != null) {
		//first purge the element
		//purgeElement(element);
		//while (element.children.length > 0) {
		if (element.childNodes != null) {
			while (element.childNodes.length > 0) {
				clearElement(element.firstChild);
				element.removeChild(element.firstChild);
			}
		}
	}
}



/*
setAttribute(attribute,value) 
Adds a new attribute with the value to the object 
appendChild(child) 
Adds child as a childNode to the object. child needs to be an object, you cannot use a string. 
cloneNode() 
Copies the whole node with all childNodes. 
hasChildNodes() 
Checks if an object has childNodes, and returns true if that is the case. 
insertBefore(newchild,oldchild) 
Adds newchild before oldchild to the document tree. 
removeChild(oldchild) 
Removes the childnode oldchild. 
replaceChild(newchild,oldchild) 
Replaces oldchild with newchild. 
removeAttribute(attribute) 
Removes the attribute from the object. 
/**/




/*
	functions handling with javascript elements



//use this ONLY to add events to elements
// written by Dean Edwards, 2005
// http://dean.edwards.name/

function addEvent(element, type, handler) {
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events = {};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// store the existing event handler (if there is one)
if (element["on" + type]) {
  handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
};
// a counter used to create unique IDs
addEvent.guid = 1;

function removeEvent(element, type, handler) {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
};


function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(window.event);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
  returnValue = false;
}
}
return returnValue;
};

function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
};

/**/




/*
//purges element, removing it from memory
//speed depends on DOM complexity (usually big, usually slow)
//use event handler to prevent having to use this function
function purgeElement(element) {
	purgeAttributes(element);
	purgeChildren(element);
}

//purges all element attributes
function purgeAttributes(element) {
	//clears all elements
	if (element.attributes) {
		for (var i=0; i<element.attributes.length; i++) {
			var n = element.attributes[i].name;
			//set function to NULL so garbage collector can collect
			if (typeof element[n] === 'function') {
				element[n] = null;
			}        
		}
	}
}
//purges all element children
function purgeChildren(element) {
	//process all children
	if (element.childNodes) {
		if (element.childNodes.length > 0) {
			for (var i=0; i<element.childNodes.length; i++) {
				purgeElement(element.childNodes[i]);
			}
		}
	}
}
/**/









/*
//returns first child element found with matching property
function getChildrenByProp(element, prop, value, data) {
	value = String(value).toUpperCase();
	var child = null;
	if (data == null) {
//			alert('init');
		data = new Array();
	}
//		alert('Test ' + prop + ' = ' + element[prop] + ' (' + value + ')');
	if (String(element[prop]).toUpperCase() == value) {
//			alert('found');
		data.push(element);
	}

	//go thru elements children
	for (var i=0; i<element.childNodes.length; i++) {
		//get the child item
		child = element.childNodes[i];
		
		//if prop doesnt match, check the children of this item
		if (String(child[prop]).toUpperCase() != value) {
			data = getChildrenByProp(child, prop, value, data);
		}
		
		//if child NOT null (exists)
		if (child != null) {
			//if MATCH found return the child
			if (String(child[prop]).toUpperCase() == value) {
				data.push(child);
			}
		}
	}
//		alert(data.length);
	return data;
}
/**/


/*
//returns first parent element found with matching property
function getParentByProp(element, prop, value) {
	value = String(value).toUpperCase();
	
	if (String(element[prop]).toUpperCase() == value) {
		return element;
	} else {
		//get parent element
		var parent = element.parentNode;
		
		//if parent doesnt match get its parent
		if (String(parent[prop]).toUpperCase() != value) {
			parent = getParentByProp(parent, prop, value);
		}
		
		//if MATCH return element
		if (String(parent[prop]).toUpperCase() == value) {
			return parent;
		}
		
		return null;
	}
}
/**/