// *** BROWSER DETECTION VARIABLES ***
// Requires: None.

// isDOM: W3C-DOM compatible browser? (IE5+, NS6+, others like Opera, Konqueror, etc...)
// isIE: Internet Explorer (v4 and up), also Opera emulating it.
// isIE4, isNS4: Each of the 4-series browsers (not DOM compatible).
// isMoz: Mozilla browsers (Mozilla, Firefox)
// isOp: Any Opera version (useful as Opera emulates IE above).
// isWin: True is Windows, false if Mac/Linux etc.
// isDyn: Any DHTML-capable browser.

var isDOM=document.getElementById?1:0,
	isIE=document.all?1:0,
	isNS4=navigator.appName=='Netscape'&&!isDOM?1:0,
	isSafari = (navigator.appVersion.indexOf('Safari') != -1), 
	isMoz=(navigator.product=='Gecko' && (!isSafari)),
	isIE4=isIE&&!isDOM?1:0,
	isOp=self.opera?1:0,
	isDyn=isDOM||isIE||isNS4,
	isWin=navigator.platform.indexOf('Win')!=-1?1:0;

/* String Functions */
String.prototype.trim = function() {
	//trims whitespace from the beginning and end of a string
	return this.replace(/^\s+/,'').replace(/\s+$/,'');
}


/* DOM Functions */
function getParentNode(thisNode) {
	//returns the parent node of thisNode
	if(isIE)
		return thisNode.parentElement;
	else
		return thisNode.parentNode;
}


/* Event Handler Functions */
try { var trash = HTMLElement; }  // special fix for mac ie
catch (e)  { HTMLElement = false; }

if ((!document.createEventObject) && (HTMLElement)) {
	// mimic the "attachEvent" method
	HTMLElement.prototype.attachEvent = function attachEvent(name, handler) {
		this.addEventListener(name.slice(2), handler, false);
	};
	
	// mimic the "removeEvent" method
	HTMLElement.prototype.removeEvent = function removeEvent(name, handler) {
		this.removeEventListener(name.slice(2), handler, false);
	};
	
	// mimic the "createEventObject" method for the document object
	HTMLDocument.prototype.createEventObject = function createEventObject() {    
		return document.createEvent("Events");
	};
	
	// mimic the "createEventObject" method
	HTMLElement.prototype.createEventObject = function createEventObject() {
		return this.ownerDocument.createEventObject();
	};
	
	// mimic the "fireEvent" method
	HTMLElement.prototype.fireEvent = function fireEvent(name, event) {
		if (!event) event = this.ownerDocument.createEventObject();
		event.initEvent(name.slice(2), false, false);
		this.dispatchEvent(event);
		// not sure that this should be here??
		if (typeof this[name] == "function") this[name]();
		else if (this.getAttribute(name)) eval(this.getAttribute(name));
	};
}

function performEventsInArrayOf(someObject, eventArray) {	
	// if the array doesnt exist
	if (!eventArray)
		return;
		
	var defaultReturnValue = true;
	// otherwise loop through every item in teh array and perform it
	// keeping the returned values so as to return them when we are done
	
	// get the current onmoveend handler in case there really is one
	var onMoveEndEvent = someObject.onmoveend;

	for (var x = 0; x < eventArray.length; x++) {
		someObject.onmoveend = eventArray[x];
		
		if (someObject.fireEvent && (someObject != window) && (someObject != document)) {
			someObject.fireEvent("onmoveend");
		} else {
			//window and document don't support fireEvent function
			if(someObject.onmoveend.call) {
				someInfo = someObject.onmoveend.call();
				//alert("someInfo: " + someInfo);
			} else {
				//since Mac IE really really sucks
				someObject.onmoveend();
			}
		}
		
		// set the onmoveend handler back to what it actually supposed to be
		//clear the onmoveend (added for IE since it doesn't do it automatically like Mozilla)
		someObject.onmoveend = onMoveEndEvent;
		//outputDetails(eventArray[x]);
		//alert("eventArray[x].returnValue: " + eventArray[x].returnValue);
		//alert(eventArray[x]);
		if (eventArray[x].returnValue == false) {
			return false;
		}
	}

	return true;
}

function modifyEventHandler(someObject, eventName, functionPointer, placement) {
	/*
		This function will do one of the following to modify the event handler:
		1. Add a newFunction before the current eventHandler.
		2. Add a newFunction after the current eventHandler.
		3. Replace the current eventHandler with a newFunction.
	*/	
	
	// check to see if this object already has an array for this function 
	var eventArray = someObject[eventName + 'Array'];
			
	if (!eventArray) {
		// if it doesnt, create an array
		eventArray = new Array();
		someObject[eventName + 'Array'] = eventArray;
		// and put anything hard coded on the object to this event in the array
		if(someObject[eventName])
			eventArray[eventArray.length] = someObject[eventName];
	}

	if (placement == "before") {
		// push the event onto the beggining of the array
		if (eventArray.push) {
			eventArray.push(functionPointer);
		} else { // special for mac ie that has no push
			var tempArray = new Array();
			tempArray[0] = functionPointer;
			eventArray = tempArray.concat(eventArray);
			someObject[eventName + 'Array'] = eventArray;
		}
	} else {
		// add the event to the end of the array
		eventArray[eventArray.length] = functionPointer;
	}

	
	// either way set the eventName of the object to call a function which RUNS the elements in the array
	someObject[eventName] = function() { return performEventsInArrayOf(someObject, eventArray); };
}

/*
function modifyEventHandler_old(obj, eventName, newFunction, addToLocation) {
	
	if(typeof newFunction != "function")
		return;
	
	var oldEventHandler = obj[eventName];

	if(window.addEventListener) {
		eventName = eventName.substring(2,1000);

		//alert(g.b.d.e);
		try {
			// if the element didnt exist when we initialized the DOM2 model
			// then add the events listeners to it
			if (! obj.addEventListener) {
				DOM2Event.initRegistration(obj);
			}
			
			//return;	
			if(addToLocation == "replace") {
				//var newEventHandler = newFunction;
				obj.addEventListener(eventName, newFunction, true);
			} else if(addToLocation == "after") {
				//alert(obj.name);
				obj.addEventListener(eventName, newFunction, true);
			} else {
				obj.removeEventListener(eventName, oldEventHandler, true);
				obj.addEventListener(eventName, newFunction, true);
				obj.addEventListener(eventName, oldEventHandler, true);
			}
		} catch (e) { alert(obj.name + " ... " + obj.tagName + " ... " + e.message); }
		//obj[eventName] = newEventHandler;
	} else if (window.attachEvent){ 
		// lard
		//alert(6);
		if(addToLocation == "replace") {
			//var newEventHandler = newFunction;
			obj.attachEvent(eventName, newFunction, false);
		} else if(addToLocation == "after") {
			obj.attachEvent(eventName, newFunction, false);
		} else {
			obj.detachEvent(eventName, oldEventHandler, false);
			obj.attachEvent(eventName, newFunction, false);
			obj.attachEvent(eventName, oldEventHandler, false);
		}
		//eventName = eventName.substring(2,1000);
		//obj[eventName] = newEventHandler;
	} else {
		
		if(!oldEventHandler) 
			addToLocation = "replace";
	
		if(addToLocation == "replace") {
			//set the newEventHandler to the newFunction
			var newEventHandler = newFunction;
		} else if(addToLocation == "after") {
			//make the newEventHandler a function that runs the oldEventHandler first
			//if the oldEventHandler doesn't return false, run and return the value of the newFunction
			var newEventHandler = function() {
				var returnValue = oldEventHandler();
				if(returnValue == false)
					return false;
				return newFunction();
			}
		} else {
			//make the newEventHandler a function that runs the newFunction first
			//if the newFunction doesn't return false, run and return the value of the oldEventHandler
			var newEventHandler = function() {
				var returnValue = newFunction();
				if(returnValue == false)
					return false;
				return oldEventHandler();
			}
		}
		obj[eventName] = newEventHandler;
		
	}
}
*/

/* Form and Element Functions */
function getNameOrId(formObject) {
	//returns the name of the form object
	//if it has no name, it returns the id of the form object
	var nameOrId = formObject.title;

	if(!nameOrId)
		var nameOrId = formObject.name;

	if(!nameOrId)
		nameOrId = formObject.id;

	return nameOrId;
}
	
function getErrorLabel(thisElement) {
	/*
		An errorLabel is the errorLabel defined in the tag.
		If no errorLabel is defined, it is the name of the tag.
		If no name is defined, it is the id of the tag.
	*/
	
	var errorLabel = thisElement.getAttribute("errorLabel");
	if(!errorLabel)
		errorLabel = getNameOrId(thisElement);

	return errorLabel;
}

function getStrictDisabled(thisElement) {
	/*
		Returns whether the element has strict checking disabled.
		This function first checks if disableStrictCheck is defined on the element.
		If it's not defined on the element, it will check the form next.
		If it's not defined on the form, then strict checking is not disabled (it's ON by default).
	*/
	var strictDisabled = thisElement.getAttribute("disableStrictCheck");
	if(!strictDisabled)
		strictDisabled = thisElement.form.getAttribute("disableStrictCheck");
	if(!strictDisabled)
		strictDisabled = false;
	return (strictDisabled == "true");
}

function getElementLength(thisElement, strictDisabled) {
	/*
		Returns a length value depending on the element type.
		Defaults to null if the type is not listed.
		
		TEXT VALUES:
			No Strict Checking - the length of the value of the field
			Strict Checking - the length of the value of the field after trimming it
		
		RADIO/CHECKBOX:
			Checked - 1
			Unchecked - 0
			
		SELECT BOX:
			No Strict Checking - the number of selected options
			Strict Checking - the number of selected options which do not have invalidOption set to true
	*/
	
	//if strictDisabled is not defined, set it
	if(strictDisabled == null)
		strictDisabled = getStrictDisabled(thisElement);
	
	switch(thisElement.type) {
		case ('file'):
		case ('hidden'):
		case ('password'):
		case ('text'):
			if(!strictDisabled)
				return thisElement.value.trim().length;
			else
				return thisElement.value.length;
		
		case ('textarea'):
			if(!strictDisabled)
				return thisElement.value.trim().length;
			
			var carriageReturns = thisElement.value.match(/([\r\n])/g);
			if (!isMoz || !carriageReturns)
				return thisElement.value.length;
			else
				return thisElement.value.length + carriageReturns.length;
		
		case ('radio'):
		case ('checkbox'):
			return thisElement.checked?1:0;
		
		case ('select-one'):
		case ('select-multiple'):
			var numberOfSelectedOptions = 0;
			for(var i=0; i<thisElement.options.length; i++) {
				var selOption = thisElement.options[i];
				var invalidOption = (selOption.getAttribute("invalidOption") == "true");
				if(selOption.selected && (strictDisabled || !invalidOption))
					numberOfSelectedOptions++;
			}
			return numberOfSelectedOptions;
		
		default:
			//return null if the type is not listed
			return null;
			
	}
}

function isFieldEmpty(thisElement, strictDisabled) {
	/*
		Returns whether or not the element's length is equal to 0.
		Defaults to false if the type is not listed.
	*/
			
	switch(thisElement.type) {
		case ('file'):
		case ('hidden'):
		case ('textarea'):
		case ('text'):
		case ('password'):
		case ('radio'):
		case ('checkbox'):
		case ('select-one'):
		case ('select-multiple'):
			return getElementLength(thisElement, strictDisabled) == 0;
			
		default:
			//return false if the type is not listed
			return false;
	}
}
	
function changeElementClass(thisElement, newClass) {
	/*
		This function changes the class of an element (if the constantStyle is not true) or a label (if the element is a checkbox or radio button) if it is not already that class.
	*/
	if(thisElement.getAttribute("constantStyle") == "true")
		return;
	
	if(thisElement.className != newClass) {
		switch(thisElement.type) {
			case ('radio'):
			case ('checkbox'):
				var parentElement = getParentNode(thisElement);
				if((parentElement.tagName.toUpperCase() == 'LABEL') && (parentElement.className != newClass)) {
					parentElement.className = newClass;
				}
				break;
			case ('file'):
			case ('textarea'):
			case ('text'):
			case ('password'):
			case ('select-one'):
			case ('select-multiple'):
				thisElement.className = newClass;
		}
	}
}

function chooseSelectOption(selectBox, optionValue) {
	/*
		This function selects the option with the specific value of the select box.
	*/
	for(var i = 0; i < selectBox.options.length; i++)
		if(selectBox.options[i].value == optionValue)
			selectBox.selectedIndex = i;
}