/*
** To Do!
** - Fix _removeEvent for Mac IE, Array.deleteKeyByValue skips functions
**
**/

function debug(msg, clear)
{
	if (clear)
	{
		document.getElementById("debug").innerHTML = "";
	}
	document.getElementById("debug").innerHTML += msg + "\n";
}

// c9 - The basis of all modules.
function c9()
{
	//
}

c9.flags = new Array();
c9.flags.NONE = 0;
c9.flags.ALERT = 1;
c9.flags.CALLBACK = 2;
c9.flags.DEBUG = 4;

c9.options = new Array();

c9.options.strings = new Array();
c9.options.strings.error = "%s";
c9.setDefaultErrorString = function(s)
{
	c9.options.strings.error = s;
}
c9.options.strings.warning = "%s";
c9.setDefaultWarningString = function(s)
{
	c9.options.strings.warning = s;
}
c9.options.strings.success = "%s";
c9.setDefaultSuccessString = function(s)
{
	c9.options.strings.success = s;
}

c9.options.flags = c9.flags.NONE;
c9.setDefaultFlags = function(flags)
{
	c9.options.flags = flags;
}

c9.options.callback = null;
c9.setDefaultCallback = function(callback)
{
	c9.options.callback = callback;
}

// Default our script root to the current Directory
c9.root = ".";
// Our method for setting the root, strips of trailing '/'
c9.setRoot = function(root)
{
	c9.root = root.replace(/\/$/, "");
}

// Find all the script objects on the page and loop through them
// until we find ourself, then set our own root.
var scriptObjs = document.getElementsByTagName("script");
for (var i = 0; i < scriptObjs.length; i++)
{
	if (scriptObjs[i].src.match(/c9\.js$/))
	{
		c9.setRoot(scriptObjs[i].src.replace(/js\/c9\.js$/, ""));
		// In IE, the src is exactly what it was in the tag, not
		// prepended with the full path, so it can be blank in
		// which case we set it to the current directory to prevent
		// errors.
		if (!c9.root.length)
		{
			c9.setRoot(".");
		}
		break;
	}
}

/*******************
** Module Loading **
********************/

// Declare our array of previously loaded modules
// so we don't load anything twice.
c9.loadedModules = new Array();

// Our require method, takes an arbitrary number of arguments.
// arguments must be the name of the module to load
//     eg: c9.require("c9xml", "c9Table", ...);
c9.require = function()
{
	var script;
	var ret;
	for (var i = 0; i < arguments.length; i++)
	{
		if (c9.loadedModules[arguments[i]] != true)
		{
			type = "text/javascript";
			src = c9.root + "/" + arguments[i] + "/js/" + arguments[i] + ".js";
			if ((document.all && !window.print) || navigator.userAgent.match(/Safari/))
			{
				document.write("<script type=\"" + type + "\" src=\"" + src + "\"></script>");
			}
			else
			{
				script = document.createElement("script");
				script.type = type;
				script.src = src;
				document.getElementsByTagName("head")[0].appendChild(script);
			}
			c9.loadedModules[arguments[i]] = true;
		}
	}
}

// Declare our array of previous loaded stylesheets
// so we don't load anything twice.
c9.loadedStyleSheets = new Array();

// Our requireStyleSheet method, takes the name of a module, and loads
// it's stylesheet, generally should only be called by the module itself.
c9.requireStyleSheet = function(module)
{
	var type = "text/css";
	var rel = "stylesheet";
	var href = c9.root + "/" + module + "/css/" + module + ".css";
	if ((document.all && !window.print) || navigator.userAgent.match(/Safari/))
	{
		document.write("<link type=\"" + type + "\" rel=\"" + rel + "\" media=\"screen\" href=\"" + href + "\" />");
	}
	else
	{
		var linkObj = document.createElement("link");
		linkObj.type = "text/css";
		linkObj.rel = "stylesheet";
		linkObj.href = c9.root + "/" + module + "/css/" + module + ".css";
		document.getElementsByTagName("head")[0].appendChild(linkObj);
	}
}

c9.progressObj = null;
c9.progressTextObj = null;
c9.setProgressObject = function(obj, textObj)
{
	var obj = getObject(obj);
	var textObj = getObject(textObj);
	if (obj)
	{
		c9.progressObj = obj;
		if (textObj)
		{
			c9.progressTextObj = textObj;
		}
		c9.hideProgress();
	}
}
c9.showProgress = function(s)
{
	if (c9.progressObj)
	{
		if (c9.progressTextObj)
		{
			c9.progressTextObj.innerHTML = s;
		}
		c9.progressObj.style.display = "block";
	}
}
c9.hideProgress = function()
{
	if (c9.progressObj)
	{
		c9.progressObj.style.display = "none";
	}
}


c9._isMessage = function(myClass, obj, code)
{
	if (obj && typeof(obj.type) != "undefined" && (obj.type == myClass.prototype.type))
	{
		if (code == null)
		{
			return true;
		}
		return (obj.code == code);
	}
	return false;
}
c9.isError = function(obj, code)
{
	return c9._isMessage(_c9_error, obj, code);
}
c9.isWarning = function(obj, code)
{
	return c9._isMessage(_c9_warning, obj, code);
}
c9.isSuccess = function(obj, code)
{
	return c9._isMessage(_c9_success, obj, code);
}

c9.raiseError = function(message, code, ret, backtrace, flags, options)
{
	return new _c9_error(message, code, ret, backtrace, flags, options);
}
c9.raiseWarning = function(message, code, ret, backtrace, flags, options)
{
	return new _c9_warning(message, code, ret, backtrace, flags, options);
}
c9.raiseSuccess = function(message, code, ret, backtrace, flags, options)
{
	return new _c9_success(message, code, ret, backtrace, flags, options);
}

function _c9_message(message, code, ret, backtrace, flags, options)
{
	this.message	= message;
	this.code		= code;
	this.ret		= ret;
	this.backtrace	= backtrace;
	this._backtrace	= new Array();
	this.flags		= flags;
	this.options	= options;

	if (_c9_message.caller)
	{
		var tmp = _c9_message.caller.caller;
		while(tmp = tmp.caller)
		{
			this._backtrace.push(tmp.getName());
		}
	}

	this.getMessage = function(backtrace)
	{
		var msg = "";
		if (this.backtrace || backtrace)
		{
			for (var i = 0; i < this._backtrace.length; i++)
			{
				msg = this._backtrace[i] + "(): " + msg;
			}
		}
		msg += this.message;
		return msg;
	}

	if (this.flags & c9.flags.ALERT == c9.flags.ALERT)
	{
		var msg = "%s";
		if (options && options[c9.flags.ALERT])
		{
			msg = options[c9.flags.ALERT];
		}
		alert(msg.replace(/%s/, this.getMessage()));
	}
	if (this.flags & c9.flags.CALLBACK)
	{
		if (options && options[c9.flags.CALLBACK])
		{
			options[c9.flags.CALLBACK](this);
		}
	}
}
function _c9_error(message, code, ret, backtrace, flags, options)
{
	this.inheritFrom = _c9_message;
	this.inheritFrom(message, code, ret, backtrace, flags, options);
}
_c9_error.prototype.type = 1;
function _c9_warning(message, code, ret, backtrace, flags, options)
{
	this.inheritFrom = _c9_message;
	this.inheritFrom(message, code, ret, backtrace, flags, options);
}
_c9_warning.prototype.type = 2;
function _c9_success(message, code, ret, backtrace, flags, options)
{
	this.inheritFrom = _c9_message;
	this.inheritFrom(message, code, ret, backtrace, flags, options);
}
_c9_success.prototype.type = 3;

/**********************
** String Extensions **
**********************/

String.prototype.lTrim = lTrim;
function lTrim()
{
	return this.replace(/^[\t\r\n\s]+/, "");
}
String.prototype.rTrim = rTrim;
function rTrim()
{
	return this.replace(/[\t\r\n\s]+$/, "");
}
String.prototype.trim = trim;
function trim(s)
{
	return this.lTrim().rTrim();
}

/*********************
** Array Extensions **
*********************/

if (!Array.prototype.push)
{
	Array.prototype.push = function()
	{
		for (var i = 0; i < arguments.length; i++)
		{
			this[this.length] = arguments[i];
		}
		return this.length;
	}
}

if (!Array.prototype.pop)
{
	Array.prototype.pop = function ()
	{
		var lastIndexValue = this[this.length - 1];
		this.length--;
		return this.length;
	}
}

Array.prototype.findKeyByValue = function(value)
{
	for (i in this)
	{
		if (typeof(this[i]) == "function")
		{
			continue;
		}

		if (this[i] == value)
		{
			return i;
		}
	}

	return -1;
}

Array.prototype.deleteKeyByKey = function(key)
{
	var newThis = new Array();

	if (typeof(key) == "number")
	{
		var j = 0;
		for (var i = 0; i < this.length; i++)
		{
			if (i != key)
			{
				newThis[j++] = this[i];
			}
		}
	}
	else
	{
		for (i in this)
		{
			if (i != key)
			{
				newThis[i] = this[i];
			}
		}
	}
	return newThis;
}

Array.prototype.deleteKeyByValue = function(value)
{
	var newThis = new Array();

	for (i in this)
	{
		if (typeof(this[i]) == "function")
		{
			continue;
		}

		if (this[i] != value)
		{
			newThis.push(this[i]);
		}
	}

	return newThis;
}

/************************
** Function Extensions **
************************/

Function.prototype.getName = function()
{
	return (s=/function (\w+)/.exec(this.toString())) ? s[1] : 'Anonymous';
}


function getObject(obj)
{
	if (typeof(obj) == "object")
	{
		return obj;
	}

	var myObj = null

	if(document.layers)
	{
		myObj = eval("document." + obj);
		if (!myObj)
		{
			for (var index = 0; index < document.layers.length; index++)
			{
				if (eval("document." + document.layers[index].id) && eval("document." + document.layers[index].id + ".document." + obj))
				{
					myObj = eval("document." + document.layers[index].id + ".document." + obj);
					break;
				}
			}
		}
	}
	else if (document.getElementById) 
	{
		myObj = document.getElementById(obj);
	}
	else
	{
		myObj = document.all[obj];
	}

	return myObj;
}
function getEventObject(evt)
{
	if (typeof(event) != "undefined")
	{
		obj = event.srcElement;
	}
	else
	{
		var obj = evt.target || evt.srcElement;
	}
	if (obj.nodeType == 3)
	{
		// Safari is once again borked and returns the text node as the event object.
		obj = obj.parentNode;
	}
	return obj;
}

function getObjectX(obj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}
return obj.offsetLeft;
	var objX = 0;
	var tmp = obj;
	while(tmp.nodeName != "#document")
	{

		objX += tmp.offsetLeft;
		tmp = tmp.parentNode;
	}

	return objX;
}

function getObjectY(obj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}
return obj.offsetTop;
	var objY = 0;
	var tmp = obj;
	while(tmp.nodeName != "#document")
	{
		objY += tmp.offsetTop;
		tmp = tmp.parentNode;
	}

	return objY;
}

function saveCookie(name, value, days)
{
	if (days)
	{
		var d = new Date();
		d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
		var ex = "; expires=" + date.toGMTString();
	}
	else
	{
		var ex = "";
	}
	document.cookie = name + "=" + value + ex + "; path=/";
}

function readCookie(name)
{
	var eq = name + "=";
	var ca = document.cookie.split(";");
	for (var i = 0; i < ca.length; i++)
	{
		var c = ca[i];
		while (c.charAt(0) == " ")
		{
			c = c.substring(1, c.length);
		}
		if (c.indexOf(eq) == 0)
		{
			return c.substring(eq.length, c.length);
		}
	}

	return null;
}

function deleteCookie(name)
{
	saveCookie(name, "", -1);
}

function addEvent(obj, evt, callback, useCapture)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}

	if (obj.addEventListener)
	{
		obj.addEventListener(evt, callback, useCapture);
		return true;
	}
	else if (obj.attachEvent)
	{
		return obj.attachEvent("on" + evt, callback);
	}
	else
	{
		_c9_addEvent(obj, evt, callback);
		obj["on" + evt] = function()
		{
			_c9_fireEvent(obj, evt);
		}
		return false;
	}
}
function _c9_addEvent(obj, evt, callback)
{
	if (!obj._events)
	{
		obj._events = new Array();
	}
	if (!obj._events[evt])
	{
		obj._events[evt] = new Array()
	}
	obj._events[evt][obj._events[evt].length] = callback;
}
function _c9_fireEvent(obj, evt)
{
	if (!obj || !obj._events || !obj._events[evt])
	{
		return;
	}
	for (var i = 0; i < obj._events[evt].length; i++)
	{
		obj._events[evt][i]()
	}
}
function _c9_removeEvent(obj, evt, callback)
{
	if (!obj._events || !obj._events[evt])
	{
		return false;
	}
	obj._events[evt].deleteKeyByValue(callback);
}

function removeEvent(obj, evt, callback, useCapture)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}

	if (obj.removeEventListener)
	{
		obj.removeEventListener(evt, callback, useCapture);
		return true;
	}
	else if (obj.detachEvent)
	{
		return obj.detachEvent("on" + evt, callback);
	}
	else
	{
		_c9_removeEvent(obj, evt, callback);
		return true;
	}
}

function hasClass(testClass, obj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}

	if (obj.className.split(" ").findKeyByValue(testClass) != -1)
	{
		return true;
	}

	return false;
}

function addClass(newClasses, obj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}

	if (typeof(newClasses) != "array")
	{
		newClasses = newClasses.split(" ");
	}

	var existingClasses = obj.className.split(" ");

	for (var i = 0; i < newClasses.length; i++)
	{
		if (!hasClass(newClasses[i], obj))
		{
			existingClasses.push(newClasses[i]);
		}
	}

	obj.className = existingClasses.join(" ");

	return true;
}

function removeClass(classes, obj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}

	if (typeof(classes) != "array")
	{
		classes = classes.split(" ");
	}

	var existingClasses = obj.className.split(" ");

	for (var i = 0; i < classes.length; i++)
	{
		existingClasses = existingClasses.deleteKeyByValue(classes[i]);
	}

	obj.className = existingClasses.join(" ");

	return true;
}

document.getElementsByClass = function(tag, cl4ss)
{
	var objs = new Array();
	var tags = document.getElementsByTagName(tag);
	for (var i = 0; i < tags.length; i++)
	{
		if (hasClass(cl4ss, tags[i]))
		{
			objs.push(tags[i]);
		}
	}
	return objs;
}

function isDescendentOf(small, big, includeSelf)
{
	small = getObject(small);
	if (!small)
	{
		return false;
	}
	big = getObject(big);
	if (!big)
	{
		return false;
	}
	var ret = false;
	if (includeSelf && (small == big))
	{
		return true;
	}
	for (var i = 0; i < big.childNodes.length; i++)
	{
		if (isDescendentOf(small, big.childNodes[i], includeSelf))
		{
			ret = true;
			break;
		}
	}
	return ret;
}

function getElementsByNodeType(nodeType, obj, depth)
{
	obj = getObject(obj);
	if (!obj)
	{
		return c9.raiseError("Could not find parrent Object");
	}
	var elements = new Array();
	for (var i = 0; i < obj.childNodes.length; i++)
	{
		if (obj.childNodes[i].nodeType == nodeType)
		{
			elements.push(obj.childNodes[i]);
		}
		if ((depth == null || depth > 0) && obj.childNodes[i].childNodes.length)
		{
			childElements = getElementsByNodeType(nodeType, obj.childNodes[i], (depth == null ? depth : depth - 1));
			for (var j = 0; j < childElements.length; j++)
			{
				elements.push(childElements[j]);
			}
		}
	}
	return elements;
}

function getChildrenByTagName(tagName, obj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return c9.raiseError("Could not find parent Object");
	}
	tagName = tagName.toLowerCase();
	var ret = new Array();
	for (var i = 0; i < obj.childNodes.length; i++)
	{
		if (obj.childNodes[i].nodeName.toLowerCase() == tagName)
		{
			ret.push(obj.childNodes[i]);
		}
	}
	return ret;
}

function insertAfter(obj, siblingObj)
{
	obj = getObject(obj);
	if (!obj)
	{
		return false;
	}
	siblingObj = getObject(siblingObj);
	if (!siblingObj)
	{
		return false;
	}
	if (siblingObj.nextSibling)
	{
		siblingObj.parentNode.insertBefore(obj, siblingObj.nextSibling);
	}
	else
	{
		siblingObj.parentNode.appendChild(obj);
	}
}

// define qForm validate(); prototype
function _c9_q_validateGiven(ignore){
	// if validation library hasn't been loaded, then return true
	if( !qFormAPI.packages.validation || this._skipValidation ) return true;

	// check the form for errors
	this.checkForErrors(ignore);

	// if there are no errors then return true
	if( this._queue.errors.length == 0 ) return true;

	// run the custom onError event, if it returns false, cancel request
	var result = this.onError();
	if( result == false ) return true;

	var strError = "The following error(s) occurred:\n";
	for( var i=0; i < this._queue.errors.length; i++ ) strError += " - " + this._queue.errors[i] + "\n";

	var result = false;
	// check to see if the user is allowed to submit the form even if an error occurred
	if( this._allowSubmitOnError && this._showAlerts ) result = confirm(strError + "\nAre you sure you want to continue?");
	// if the form can be submitted with errors and errors should not be alerted set a hidden field equal to the errors
	else if( this._allowSubmitOnError && !this._showAlerts ) result = true;
	// otherwise, just display the error
	else alert(strError);

	return result;
}

function _c9_q_checkForErrorsGiven(ignore){
	var status = this._status; // copy the current form's status
	this._status = "validating"; // set form's status to validating
	this._queue.errors = new Array(); // clear the current error queue
	aryQueue = new Array(); // create a local queue for the required fields
	this._queue.errorFields = ",";

	if (ignore != null) { ignore = ignore.split(" "); } // DANP

	// loop through form elements
	for( var j=0; j < this._fields.length; j++ ){
		/* BEGIN DANP */
		if (ignore != null)
		{
			ok = false;
			for (k = 0; k < ignore.length; k++)
			{
				if (this._fields[j].toLowerCase() == ignore[k].toLowerCase())
				{
					ok = true;
					break;
				}
			}
		}
		else
		{
			ok = true;
		}
		if (!ok) continue;
		/* END DANP */
		// if the current field is required, then check to make sure it's value isn't blank
		if( this[this._fields[j]].required ) aryQueue[aryQueue.length] = new Array(this._fields[j], this._pointer + "['" + this._fields[j] + "'].isNotEmpty(\"The " + this[this._fields[j]].description + " field is required.\");");
		// reset the CSS settings on the field
		if( qFormAPI.useErrorColorCoding && this[this._fields[j]].obj.style ) this[this._fields[j]].obj.style[qFormAPI.styleAttribute] = this[this._fields[j]].styleValue;
	}

	// loop through the required fields queue, if the field throws an error, don't validate later
	for( var i=0; i < aryQueue.length; i++ ) this[aryQueue[i][0]].throwError(eval(aryQueue[i][1]));

	// loop through the validation queue and validation each item, if the item has already been validated, don't validate again
	for( var i=0; i < this._queue.validation.length; i++ ) this[this._queue.validation[i][0]].throwError(eval(this._queue.validation[i][1]));

	// run the custom validation routine
	this.onValidate();

	// set form's status back to it's last status
	this._status = status;

	return true;
}

function c9Event(eventObj, windowEventObj, currentTargetObj)
{
	if (windowEventObj)
	{
		this.event = windowEventObj;
	}
	else
	{
		this.event = eventObj;
	}

	this.type = this.event.type;

	this.target = this.event.srcElement || this.event.target;
	if (this.target.nodeType == 3)
	{
		this.target = this.target.parentNode;
	}

	this.currentTarget = this.event.currentTarget || currentTargetObj;

	this.relatedTarget = this.event.relatedTarget || this.event.fromElement;

	this.clientX = this.event.pageX || this.event.clientX;
	this.clientY = this.event.pageY || this.event.clientY;

	this.keyCode = this.event.keyCode;
	if (!this.keyCode)
	{
		this.keyCode = this.event.charCode;
	}
	this.shiftKey = this.event.shiftKey;
	this.ctrlKey = this.event.ctrlKey;
	this.altKey = this.event.altKey;
	this.metaKey = this.event.metaKey;

	this.stopPropagation = function()
	{
		if (this.event.stopPropagation)
		{
			this.event.stopPropagation();
		}
		else
		{
			this.event.cancelBubble = true;
		}
	}
	this.preventDefault = function()
	{
		if (this.event.preventDefault)
		{
			this.event.preventDefault();
		}
		else
		{
			this.event.returnValue = false;
		}
	}
}



/***********************
** JC's old functions **
***********************/
function arrayFind(arrayToSearch,valueToFind,ignoreCase)
   	{
	
   		for(var index = 0; index <  arrayToSearch.length; index++)
			{
				var valueToMatch = new RegExp("^" + arrayToSearch[index] + "$", ignoreCase? "i": "");
				
				if(valueToMatch.test(valueToFind))
					{
						
						return index;
						
					}

			}
			
		return -1;
			
   	}