///////////////////////////////////////////////////////////////
// File Name: 	library.js
///////////////////////////////////////////////////////////////

/////////////////////////////////////
// Note that ModernCF automatically sets the following javascript variables to make
// them available to functions:
// MCFResourcesPath
/////////////////////////////////////

/////////////////////////////////////
// popupWindow: To provide consistency in the way popup select windows appear.
/////////////////////////////////////
function popupWindow(windowName,width,height) {
	eval("var " + windowName + " = window.open('','" + windowName + "','width=" + width + ",height=" + height + ",resizable=1,scrollbars=1')");
	eval(windowName + ".focus()");
	return eval(windowName);
}
function popupWindow2(windowName,options) {
	eval("var " + windowName + " = window.open('','" + windowName + "','" + options + "')");
	eval(windowName + ".focus()");
	return eval(windowName);
}

function popupDialog(windowName,width,height,options,url) {
	//Set url
	if (url == null) url = "";


	//Set options
	if (options == null) options = "status=no,toolbar=no,menubar=no,location=no";
	var top = (screen.availHeight - height) / 2;
	var left = (screen.availWidth - width) / 2;
	options = "height=" + height + ",width=" + width + ",top=" + top + ",left=" + left + "," + options;

	//Create window
	eval("var " + windowName + " = window.open('" + url + "','" + windowName + "','" + options + "')");
	eval(windowName + ".focus()");
	return eval(windowName);
}

function upperCase(fieldObj) {
	fieldObj.value = fieldObj.value.toUpperCase();
}

function lowerCase(fieldObj) {
	fieldObj.value = fieldObj.value.toLowerCase();
}

/////////////////////////////////////
// titleCase
/////////////////////////////////////
function titleCase(fieldObj) {
	words = fieldObj.value.split(" ");
	// List of words that remain lower case in titles
	exceptions = ",a,an,the,and,but,or,nor,so,to,as,at,by,for,from,in,into,of,on,onto,to,with,";
	for (var i = 0; i < words.length; i ++) {
		if (i == 0 || exceptions.indexOf("," + words[i].toLowerCase() + ",") == -1) {
			// Get index of first letter
			firstLetterIndex = words[i].search(/\w/);
			words[i] = words[i].substring(0,firstLetterIndex+1).toUpperCase() + words[i].substring(firstLetterIndex+1,words[i].length).toLowerCase()
		} else {
			words[i] = words[i].toLowerCase();
		}
	}
	fieldObj.value = words.join(" ");
}


/////////////////////////////////////
// stripHTML: remove all html tags from a string.
/////////////////////////////////////
function stripHTML(s) {
	s = s.replace(/<[^>]*>/g," ");
	s = s.replace(/&nbsp;/g," ");
	s = trim(s);
	return s;
}

/////////////////////////////////////
// trim: remove leading and trailing white space.
/////////////////////////////////////
function trim(s) {
	s = s.replace(/(^\s|\s$)/g,"");
	return s;
}


/////////////////////////////////////
// setChecked: set multiple checkboxes to checked or unchecked
//   checked = true or false
//   pattern = all checkboxes with ids that match this regular expression will be affected.
//             if omitted all checkboxes will be affected
/////////////////////////////////////
function setChecked(formObj,checked,pattern) {
	if (pattern != null) re = new RegExp("^" + pattern + "$","i");
	var e = formObj.elements;
	for (var i = 0; i < e.length; i ++) {
		if (e[i].type == "checkbox") {
			if (pattern == null || e[i].id.search(re) != -1) {
				e[i].checked = checked;
			}
		}
	}
}




/////////////////////////////////////
// showHide: toggle visibility for an object
/////////////////////////////////////
var zIndex = 100;
function showHide(obj,sh) {
	if (obj) {
		if (sh == null) {
			if (obj.style.visibility == "hidden") {
				sh = "show";
			} else {
				sh = "hide";
			}
		}
		if (sh == "show") {
			_setSelectVisibility("hidden",obj);
			zIndex ++;
			obj.style.zIndex = zIndex;
			obj.style.visibility = "visible";
		} else {
			_setSelectVisibility("visible",obj);
			obj.style.visibility = "hidden";
		}
	}
}

/////////////////////////////////////
// toggleDisplay: toggle display for an object
/////////////////////////////////////
function toggleDisplay(obj,sh,type) {
	if (sh == null) {
		if (obj.style.display != "none") {
			sh = "hide";
		} else {
			sh = "show";
		}
	}
	if (type == null) {
		type = "inline";
	}
	if (sh == "show") {
		obj.style.display = "inline";
	} else {
		obj.style.display = "none";
	}
}



/////////////////////////////////////
// functions to create context menus
/////////////////////////////////////
var dmTimeout = new Array();
var dmTimeoutLength = 500;

// dhtmlMenu object
function dhtmlMenu(id) {
	this.id = id;
}
dhtmlMenu.prototype.exists = function() {
	if (document.getElementById(this.id)) {
		return true;
	} else {
		return false;
	}
}
dhtmlMenu.prototype.create = function(items) {
	// create menu

	if (this.exists()) {
		document.body.removeChild(document.getElementById(this.id));
	}

	var ul = document.createElement("UL");
	ul.id = this.id;
	ul.className = "DHTMLMENU";
	ul.style.visibility = "hidden";
	ul.style.position = "absolute";
	ul.style.left="0px";
	ul.style.top="0px";

	// create items
	for (var i = 0; i < items.length; i ++) {
		var item = items[i];
		var li,a,label,img,input;

		li = document.createElement("LI");
		li.setAttribute("unselectable","on");
		li.setAttribute("menuID",this.id);
		li.onmouseover = dhtmlMenuItemMouseover;
		li.onmouseout = dhtmlMenuItemMouseout;
		ul.appendChild(li);

		switch (item.type) {
			case "link":
				a = document.createElement("A");
				a.setAttribute("unselectable","on");
				li.appendChild(a);

				if (item.image != null && item.image != "") {
					img = document.createElement("IMG");
					img.setAttribute("unselectable","on");
					img.src = item.image;
					img.border = 0;
					img.valign = "middle";
					a.appendChild(img);
				}

				a.href = item.href
				a.innerHTML = a.innerHTML + item.label;
				break;

			case "checkbox":
				input = document.createElement("INPUT");
				input.setAttribute("unselectable","on");
				input.type = "checkbox";
				input.id = item.id;
				input.onclick = item.onclick;
				li.appendChild(input);

				label = document.createElement("LABEL");
				label.setAttribute("unselectable","on");
				label.htmlFor = item.id;
				label.innerHTML = item.label;
				li.appendChild(label);
				break;

		}

	}

	document.body.appendChild(ul);

	//check checkboxes.
	//Seems to be a bug in IE where checkbox can't be set as checked before being appended to the document.
	for (var i = 0; i < items.length; i ++) {
		if (items[i].type == "checkbox" && items[i].checked) {
			document.getElementById(items[i].id).checked = true;
		}
	}
}
dhtmlMenu.prototype.positionUnderElement = function(el) {
	var ul = document.getElementById(this.id);
	ul.style.left = _totalOffsetLeft(el) + "px";
	ul.style.top = _totalOffsetTop(el) + el.offsetHeight + "px";
}
dhtmlMenu.prototype.positionAt = function(left,top) {
	var ul = document.getElementById(this.id);
	ul.style.left = left + "px";
	ul.style.top = top + getScrollHeight(window) + "px";
}
dhtmlMenu.prototype.toggleShow = function(location,params) {
	switch (location) {
		case "underElement":
			this.positionUnderElement(arguments[1]);
			break;
		case "at":
			this.positionAt(arguments[1],arguments[2]);
			break;
	}
	if (dmTimeout[this.id] != null) clearTimeout(dmTimeout[this.id])
	//dmTimeout[this.id] = setTimeout("showHide(document.getElementById('" + this.id + "'),'show')",dmTimeoutLength);
	showHide(document.getElementById(this.id));
}
dhtmlMenu.prototype.show = function(location,el) {
	if (location == "underElement") {
		this.positionUnderElement(el)
	}
	if (dmTimeout[this.id] != null) clearTimeout(dmTimeout[this.id])
	//dmTimeout[this.id] = setTimeout("showHide(document.getElementById('" + this.id + "'),'show')",dmTimeoutLength);
	showHide(document.getElementById(this.id),'show');
}
dhtmlMenu.prototype.hide = function() {
	if (dmTimeout[this.id] != null) clearTimeout(dmTimeout[this.id])
	dmTimeout[this.id] = setTimeout("showHide(document.getElementById('" + this.id + "'),'hide')",dmTimeoutLength);
}
dhtmlMenu.prototype.isVisible = function() {
	if (this.exists()) {
		if (document.getElementById(this.id).style.visibility == "visible") {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

// dhtmlMenuItem object
function dhtmlMenuItem(type,label) {
	this.type = type;
	this.label = label;
	switch (type) {
		case "link":
			this.href = arguments[2];
			this.image = arguments[3];
			break;
		case "checkbox":
			this.id = arguments[2];
			this.checked = arguments[3];
			this.onclick = arguments[4];
			break;
	}
}

function dhtmlMenuItemMouseover(e) {
	var srcEl = getEventSrcElement(e);
	if (srcEl.tagName != "LI") srcEl = getParentByTagName(srcEl,"LI");
	srcEl.className = "DHTMLMENU ITEMHOVER";
	for (var i = 0; i < srcEl.childNodes; i ++) srcEl.childNotes[i].className = "DHTMLMENU ITEMHOVER";
	var ul = getParentByTagName(srcEl,"UL");
	if (dmTimeout[ul.id] != null) clearTimeout(dmTimeout[ul.id])
}
function dhtmlMenuItemMouseout(e) {
	var srcEl = getEventSrcElement(e);
	if (srcEl.tagName != "LI") srcEl = getParentByTagName(srcEl,"LI");
	srcEl.className = "";
	for (var i = 0; i < srcEl.childNodes; i ++) srcEl.childNotes[i].className = "";
	var ul = getParentByTagName(srcEl,"UL");
	dmTimeout[ul.id] = setTimeout("showHide(document.getElementById('" + ul.id + "'),'hide')",dmTimeoutLength);
}




/////////////////////////////////////
//// Some objects are windowed and therefore don't obey the zIndex in IE (at least at the time of this writing)
//// Therefore, they need to be hidden if they are in the way of an object.
/////////////////////////////////////
var _setSelectVisibilityWindowedElements;
function _setSelectVisibility(visibility,obj) {
	// get object position
	if (obj != null) {
		var oTop = _totalOffsetTop(obj);
		var oLeft = _totalOffsetLeft(obj);
		var oBottom = oTop + obj.offsetHeight;
		var oRight = oLeft + obj.offsetWidth;
	}


	if (_setSelectVisibilityWindowedElements == null) {

		// get all windowed objects
		var selectObjs = document.getElementsByTagName("SELECT");
		var specialObjs = document.getElementsByTagName("OBJECT");
		// get array of elements

		_setSelectVisibilityWindowedElements = new Array();
		for (var i = 0; i < selectObjs.length; i ++) _setSelectVisibilityWindowedElements[_setSelectVisibilityWindowedElements.length] = selectObjs[i];
		for (var i = 0; i < specialObjs.length; i ++) _setSelectVisibilityWindowedElements[_setSelectVisibilityWindowedElements.length] = specialObjs[i];
	}

	for (var i = 0; i < _setSelectVisibilityWindowedElements.length; i ++) {
		element = _setSelectVisibilityWindowedElements[i];
		if (visibility == "hidden") {
			// get select object position
			var sTop = _totalOffsetTop(element);
			var sLeft = _totalOffsetLeft(element);
			var sBottom = sTop + element.offsetHeight;
			var sRight = sLeft + element.offsetWidth;

			// If select object overlaps menu, hide it.
			if (((oTop <= sTop && sTop <= oBottom) || (oTop <= sBottom && sBottom <= oBottom) || (sTop <= oTop && sBottom >= oBottom) || (sTop >= oTop && sBottom <= oBottom))
				&& ((oLeft <= sLeft && sLeft <= oRight) || (oLeft <= sRight && sRight <= oRight) || (sLeft <= oLeft && sRight >= oRight) || (sLeft >= oLeft && sRight <= oRight))) {
				element.style.visibility = "hidden";
			}
		} else {

			// Make sure all select objects are visible again.
			element.style.visibility = "visible";
		}
	}
}
function _totalOffsetLeft(el) {
	// Return the true x coordinate of an element relative to the page.
	return el.offsetLeft + (el.offsetParent ? _totalOffsetLeft(el.offsetParent) : 0);
}

function _totalOffsetTop(el) {
	// Return the true y coordinate of an element relative to the page.
	return el.offsetTop + (el.offsetParent ? _totalOffsetTop(el.offsetParent) : 0);
}
/////////////////////////////////////



///////////////////////////////////////////////////////////////
// Functions to swap sibling objects
///////////////////////////////////////////////////////////////
function moveObjUp(o) {
	if (o.previousSibling != null) {
		var p = o.parentNode;
		var s = o.previousSibling;
		var c = p.removeChild(o);
		p.insertBefore(c,s);
	}
}
function moveObjDown(o) {
	if (o.nextSibling != null) {
		var p = o.parentNode;
		var s = p.removeChild(o.nextSibling);
		p.insertBefore(s,o);
	}
}


///////////////////////////////////////////////////////////////
// Functions for select objects
///////////////////////////////////////////////////////////////

// Move selected options up, if there is room
function moveUp(obj) {
	// For Netscape 6, keep array of selected options to select afterwards
	selectedArray = new Array();
	for (i = 1; i < obj.length; i ++) {
		if (obj[i].selected && !obj[i-1].selected) {
			scrollTop = obj[i].scrollTop;
			moveObjUp(obj[i]);
			obj[i].scrollTop = scrollTop - obj[i].offsetHeight;
			selectedArray.push(i-1);
		}
	}
	for (n = 0; n < selectedArray.length; n ++) {
		obj[selectedArray[n]].selected = true;
	}
}
// Move selected options down, if there is room
function moveDown(obj) {
	// For Netscape 6, keep array of selected options to select afterwards
	selectedArray = new Array();
	for (i = obj.length - 2; i > -1; i --) {
		if (obj[i].selected && !obj[i+1].selected) {
			scrollTop = obj[i].scrollTop;
			moveObjDown(obj[i]);
			obj[i].scrollTop = scrollTop + obj[i].offsetHeight;
			selectedArray.push(i+1);
		}
	}
	for (n = 0; n < selectedArray.length; n ++) {
		obj[selectedArray[n]].selected = true;
	}
}
function selectAll (selectObj) {
	for (i=0; i < selectObj.length; i++) {
		selectObj.options[i].selected = true;
	}
}



///////////////////////////////////////////////////////////////
// Form Validation
// Author: 	David Hammond, based on Netscape library
// Description: General form validation functions
///////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////
// VARIABLE DECLARATIONS
///////////////////////////////////////////////////////////////

// regualar expression definitions
var reWhitespace = /^\s+$/
var reEmail = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/i
var reFloat = /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/

// prompts for "missing" information
var mPrefix = "You did not enter a value into the \""
var mSuffix = "\" field. This is a required field. Please enter it now."
var mPrefix2 = "You did not select a value for \""
var mSuffix2 = "\". This information is required. Please select a value now."

// prompts for "invalid" information
var iEmail = "We have detected an invalid e-mail address. Please review the e-mail address you've entered and try again."


///////////////////////////////////////////////////////////////
// BASIC DATA VALIDATION FUNCTIONS
///////////////////////////////////////////////////////////////

// Check whether string s is empty.
function isEmpty(s) {
	return ((s == null) || (s.length == 0))
}

// Returns true if string s is empty or
// whitespace characters only.
function isWhitespace (s) {
    return (isEmpty(s) || reWhitespace.test(s));
}

// isEmail (STRING s)
function isEmail (s) {
	return reEmail.test(s)
}

// general purpose function to see if a suspected numeric input
// is not empty and is a positive integer
function isNumber(s) {
	return reFloat.test(s)
}



///////////////////////////////////////////////////////////////
// FUNCTIONS TO PROMPT USER
///////////////////////////////////////////////////////////////

// Notify user that required field fieldObj is empty.
// String s describes expected contents of fieldObj.value.
// Put focus in fieldObj and return false.
function warnEmpty (fieldObj, s) {
	if (fieldObj.type != "hidden") {
		fieldObj.focus();
	}
    alert(mPrefix + s + mSuffix);
    return false
}

// Notify user that contents of field fieldObj are invalid.
// String s describes expected contents of fieldObj.value.
// Put select fieldObj, pu focus in it, and return false.
function warnInvalid (fieldObj, s) {
	if (fieldObj.type != "hidden") {
		fieldObj.focus();
	    fieldObj.select()
	}
    alert(s)
    return false
}


///////////////////////////////////////////////////////////////
// FUNCTIONS TO INTERACTIVELY CHECK FIELD CONTENTS
///////////////////////////////////////////////////////////////

// checkText (TEXTFIELD fieldObj, STRING s)
//
// Check that string fieldObj.value is not all whitespace.
function checkText (fieldObj, s) {
	if (isWhitespace(fieldObj.value)) return warnEmpty (fieldObj, s);
    else return true;
}


// checkLength (TEXTAREA fieldObj, INT maxlength, STRING s)
//
// Check length of string fieldObj.value
function checkLength(fieldObj,maxLength,s) {
	if (fieldObj.value.length > maxLength) {
		return warnInvalid (fieldObj, "The value in the \"" + s + "\" field cannot have more than " + maxLength + " characters.\nIt currently has " + fieldObj.value.length + " characters");
	} else {
		return true;
	}
}


// checkChecked (RADIO|CHECKBOX fieldObj, STRING s)
//
// Check that at least one radio or checkbox is checked
function checkChecked (fieldObj, s) {
	if (fieldObj.length) {
		for (i=0; i < fieldObj.length; i++) {
			if (fieldObj[i].checked) return true;
		}
		fieldObj[0].focus();
	} else {
		if (fieldObj.checked) return true;
		fieldObj.focus();
	}
	alert(mPrefix2 + s + mSuffix2);
	return false;
}

// checkSelected (SELECT fieldObj, STRING s)
//
// Check that at least one option has been selected, and it has a value
function checkSelected (fieldObj, s) {
	for (i=0; i < fieldObj.length; i++) {
		if (fieldObj.options[i].selected && fieldObj.options[i].value.length > 0)	return true;
	}
	fieldObj.focus();
	alert(mPrefix2 + s + mSuffix2);
	return false;
}


// checkEmail (TEXTFIELD fieldObj)
//
// Check that string fieldObj.value is a valid Email.
// It is assumed that empty is okay. Run checkText first if this is required
function checkEmail (fieldObj) {
	if (fieldObj.value != "") {
		if (!isEmail(fieldObj.value)) return warnInvalid (fieldObj, iEmail);
	}
	return true;
}


// checkNumber (TEXTFIELD fieldObj)
//
// Check that string fieldObj.value is a valid number.
// It is assumed that empty is okay. Run checkText first if this is required
function checkNumber(fieldObj, s) {
	// Strip legitimate characters that will cause SQL problems
	var value = fieldObj.value;
	value = value.replace(/[$,]/g,"");
	if (value == "") {
		fieldObj.value = value;
		return true;
	}
	if (!isNumber(value)) {
		return warnInvalid (fieldObj, "The value in field " + s + " must be a number.");
	} else {
		fieldObj.value = value;
		return true;
	}
}


// checkDate (TEXTFIELD fieldObj)
//
// This function accepts a string variable and verifies if it is a
// proper date or not. It validates format matching either
// mm-dd-yyyy or mm/dd/yyyy. Then it checks to make sure the month
// has the proper number of days, based on which month it is.
//
// It is assumed that empty is okay. Run checkText first if this is required
function checkDate(fieldObj, s) {
	dateStr = fieldObj.value;
	if (isEmpty(dateStr)) return true;

	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)((\d{2}|\d{4}))$/;
	var matchArray = dateStr.match(datePat); // is the format ok?
	if (matchArray == null) {
		return warnInvalid (fieldObj,"Value in field " + s + " must be in the form of mm/dd/yyyy.");
	}
	month = matchArray[1]; // parse date into variables
	day = matchArray[3];
	year = matchArray[5];
	if (month < 1 || month > 12) { // check month range
		return warnInvalid (fieldObj,"Month must be between 1 and 12 for field " + s + ".");
	}
	if (day < 1 || day > 31) {
		return warnInvalid (fieldObj,"Day must be between 1 and 31 for field " + s + ".");
	}
	if ((month==4 || month==6 || month==9 || month==11) && day==31) {
		return warnInvalid (fieldObj,"Month "+month+" doesn't have 31 days for field " + s + ".")
	}
	if (month == 2) { // check for february 29th
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day > 29 || (day==29 && !isleap)) {
			return warnInvalid (fieldObj,"February " + year + " doesn't have " + day + " days for field " + s + ".");
		}
	}
	return true; // date is valid
}

// checkPhone (TEXTFIELD fieldObj)
//
// Check that string fieldObj.value is a valid phone number.
// It is assumed that empty is okay. Run checkText first if this is required
function checkPhone(fieldObj, s) {
	// Strip legitimate characters that will cause SQL problems
	var value = fieldObj.value;
	if (value == "") {
		return true;
	}
	value = value.replace(/\(/g,"");
	value = value.replace(/\)/g,"");
	value = value.replace(/[\s.x-]/g,"");
	if (!isNumber(value)) {
		return warnInvalid (fieldObj, "The value in field " + s + " must be a valid phone number.");
	}
	if (value.length < 10) {
		return warnInvalid (fieldObj, "The value in field " + s + " must be a valid phone number.");
	}
	return true;
}


function checkFile (formObj,colName,s) {
	var uploadFieldObj = formObj.elements[colName];
	if (isWhitespace(uploadFieldObj.value)) {
		if (formObj.elements[colName + "_OldFile"]) {
			var oldfileFieldObj = formObj.elements[colName + "_OldFile"];
			var deleteCheckbox = formObj.elements[colName + "_Delete"];
			if (isWhitespace(oldfileFieldObj.value) || deleteCheckbox.checked) {
				return warnEmpty (uploadFieldObj, s);
			} else {
				return true;
			}
		}
		return warnEmpty (uploadFieldObj, s);
	}
	return true;
}


///////////////////////////////////////////////////////////////
// OTHER UTILITY FUNCTIONS
///////////////////////////////////////////////////////////////


// Escape regular expression special characters in string
function reEscape(s) {
	return s.replace(/[\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g,"\\$&");
}

// Html Encode
function htmlEncode(s) {
	return s.replace(/\&/g,"\&amp;");
}

// Get value of checked radio button or checkbox if multiple are present
function getCheckedValue (fieldObj) {
	for (var i = 0; i < fieldObj.length; i++) {
		if (fieldObj[i].checked) { break }
    }
    return fieldObj[i].value
}

// Get value of selected option
function getSelectedValue (fieldObj) {
	for (var i = 0; i < fieldObj.length; i++) {
		if (fieldObj[i].selected) {
			return fieldObj[i].value
		}
    }
    return "";
}


// Simple non-re replace function
function replace(s,subexpr,replacestring) {
	var i = s.indexOf(subexpr);
	if (i > -1) {
		s = s.substring(0,i) + s.substring(i + subexpr.length, s.length)
	}
	return s;
}
function replaceAll(s,subexpr,replacestring) {
	if (replacestring.indexOf(subexpr) > -1) {
		alert("replacestring contains subexpression.  aborting to avoid infinite loop.\nreplacestring: " + replacestring + "\nsubexpression: " + subexpr);
		return s;
	}
	var i = s.indexOf(subexpr);
	while (i > -1) {
		s = s.substring(0,i) + replacestring + s.substring(i + subexpr.length, s.length)
		i = s.indexOf(subexpr);
	}
	return s;
}

// remove a value from a comma-separated list
function listRemove(list,value,delimiter) {
	if (delimiter == null) delimiter = ",";
	list = list.replace(new RegExp(reEscape(value),"gi"),"");
	list = list.replace(new RegExp(delimiter + delimiter,"g"),delimiter);
	list = list.replace(new RegExp("^" + delimiter + "|" + delimiter + "$","g"),"");
	return list;
}
function listShiftRight(list,value) {
	list = list.replace(new RegExp("(" + reEscape(value) + "),([^$,]+)","gi"),"$2,$1");
	return list;
}
function listShiftLeft(list,value) {
	list = list.replace(new RegExp("([^^,]+),(" + reEscape(value) + ")","gi"),"$2,$1");
	return list;
}

function listFind(list,value,delimiter) {
	if (delimiter == null) delimiter = ",";
	return list.match(new RegExp("[^" + delimiter + "]*(^|" + delimiter + ")" + reEscape(value) + "($|" + delimiter + ")[^" + delimiter + "]*"));
}

function getScrollWidth(win) {
	if (win == null) win = window;
	var w = win.pageXOffset || win.document.body.scrollLeft || win.document.documentElement.scrollLeft;
	return w ? w : 0;
}
function getScrollHeight(win) {
	if (win == null) win = window;
	var h = win.pageYOffset || win.document.body.scrollTop || win.document.documentElement.scrollTop;
	return h ? h : 0;
}


// Populate select box from an array
function populateSelectList(selectObj,valueArray,selectedValue,synchValue) {
	selectObj.options.length = 1;
	var n = 1;

	for (var i = 0; i < valueArray.length; i ++) {
		if (synchValue == null || valueArray[i][2] == synchValue) {
			selectObj.options[n] = new Option(valueArray[i][1],valueArray[i][0]);
			if (valueArray[i][0] == selectedValue) {
				selectObj.options[n].selected = true;
			}
			n ++ ;
		}
	}

}

function arrayContains(arr,val) {
	for (var i = 0; i < arr.length; i ++) {
		if (arr[i] == val) {
			return true;
			break;
		}
	}
	return false;
}

// Get parent element by tagname
function getParentByTagName(el,tagName) {
	return (el.parentNode.tagName == tagName ? el.parentNode : getParentByTagName(el.parentNode,tagName));
}


// Cross-browser support for event handlers
function getEventSrcElement(e) {
	if (window.event) {
		return window.event.srcElement;
	} else {
		return e.currentTarget;
	}
}

