/* form.js */

/* public validation functions */
function checkboxChecked(fldName, frm, minBoxes, maxBoxes){
	var chOK = false, c = 0, cnt = 0;
	
	if (frm[fldName][0]){
		for (c = 0; c < frm[fldName].length; c++){
			if (frm[fldName][c].checked){
				cnt++;
			}
		}
		if (cnt >= minBoxes && cnt <= maxBoxes){
			chOK = true;
		}
	}else if (frm[fldName].checked || minBoxes == 0){
		chOK = true;
	}
	
	return chOK;
}

function dateInRange(strVal, earliest, latest){
	var dateReturn = false, testDt = 0, earlyDt = 0, lateDt = 0;
	
	if (isDate(strVal) && (isDate(earliest) || isDate(latest))){
		/* as long as the test val and at least one range cap are int, then continue */
		testDt = new Date(strVal).getTime();
		if (isDate(earliest) && isDate(latest)){
			earlyDt = new Date(earliest).getTime();
			lateDt = new Date(latest).getTime();
			if (testDt >= earlyDt && testDt <= lateDt){
				dateReturn = true;
			}
		}else if (isDate(earliest)){
			earlyDt = new Date(earliest).getTime();
			if (testDt >= earlyDt){
				dateReturn = true;
			}
		}else if (isDate(latest)){
			lateDt = new Date(latest).getTime();
			if (testDt <= lateDt){
				dateReturn = true;
			}
		}
	}
	
	return dateReturn;
}

function integerInRange(strVal, minAllowed, maxAllowed, dollarsOK){
	var intReturn = false;
	
	if (dollarsOK) {
		strVal = numberStrip(strVal);
	}
	if (isInteger(strVal) && (isInteger(minAllowed) || isInteger(maxAllowed))){
		/* as long as the test val and at least one range cap are int, then continue */
		if (isInteger(minAllowed) && isInteger(maxAllowed)){
			if (parseInt(strVal) >= minAllowed && parseInt(strVal) <= maxAllowed){
				intReturn = true;
			}
		}else if (isInteger(minAllowed)){
			if (parseInt(strVal) >= minAllowed){
				intReturn = true;
			}
		}else if (isInteger(maxAllowed)){
			if (parseInt(strVal) <= maxAllowed){
				intReturn = true;
			}
		}
	}
	
	return intReturn;
}

function isColor(strVal){
	/* expects 3- or 6-character RGB value */
	var regexRgb = /^([0-9]|[A-Fa-f]){3}(([0-9]|[A-Fa-f]){3})?$/;
	
	return regexRgb.test(strVal);
}

function isCreditCard(strVal){
	var ccNum = "", prefix = "", evnArr = new Array(), oddArr = new Array();
	var ccOK = false, x = 0, y = 0, z = 0, thisChar = new String();
	var regexInt = /[0-9]/, regexLen = /^1[3456]$/;
	
	for (x = 0; x < strVal.length; x++){
		thisChar = strVal.charAt(x);
		if (regexInt.test(thisChar)){
			ccNum += thisChar;
			if (x < 4){
				prefix += thisChar;
			}
			if (x % 2 == 0){
				evnArr[evnArr.length] = thisChar * 2;
			}else{
				oddArr[oddArr.length] = thisChar;
			}
		}
	}
	if (regexLen.test(ccNum.length)){
		var ccTotal = 0, intFlag = 0, nextInt = 0;
		
		for (x = (ccNum.length - 1); x >= 0; x--){
			if (intFlag == 1){
				nextInt = ccNum.charAt(x) * 2;
				if (nextInt > 9){
					nextInt -= 9;
				}
				ccTotal += nextInt;
				intFlag = 0;
			}else{
				ccTotal += parseInt(ccNum.charAt(x));
				intFlag = 1;
			}
		}
		if ((ccTotal % 10) == 0){
			ccOK = true;
		}
	}
	
	return ccOK;
}

function isCreditCardExp(strVal){
	/* expects format 'MMYYYY', e.g.: '012007' = 01/07 or January 2007 */
	var regexInt = /^\d{6}$/, mth1 = 0, mth2 = 0, mth = 0, yr = 0, today = new Date();
	var expOK = false;
	
	if (!regexInt.test(strVal)){
		/* not six numbers */
		expOK = false;
	}else{
		mth1 = parseInt(strVal.substr(0, 1));
		mth2 = parseInt(strVal.substr(1, 1));
		mth = (mth1 * 10) + mth2;
		yr = parseInt(strVal.substr(2, 4));
		today = new Date();
		if ((yr < today.getYear()) || (today.getYear() == yr && mth < parseInt(today.getMonth()))){
			/* date in the past */
			expOK = false;
		}else if (mth > 12){
			/* month out of range */
			expOK = false;
		}else{
			expOK = true;
		}
	}
	
	return expOK;
}

function isDate(strVal){
	var regexDate = /^((((0?[13578]|1[02])(\/|-|\.)(0?[1-9]|[12][0-9]|3[01]))|((0?[469]|11)(\/|-|\.)(0?[1-9]|[12][0-9]|30))|0?2(\/|-|\.)(0?[1-9]|1[0-9]|2[0-8]))(\/|-|\.)[0-9]{4})|(0?2(\/|-|\.)29(\/|-|\.)(((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/;
	
	return regexDate.test(strVal);
}

function isEmail(strVal){
	var regexEmail = /^([A-Za-z0-9'_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([A-Za-z0-9'\-]+\.)+))([A-Za-z]{2,4}|[0-9]{1,3})(\]?)$/;
	
	return regexEmail.test(strVal);
}

function isEmpty(strVal){
	var regexSpace = /^\s*$/;
	
	if (strVal == "" || regexSpace.test(strVal)){
		return true;
	}else{
		return false;
	}
}

function isInteger(strVal, dollarsOK){
	var regexInt = /^[\-\+]?[0-9]+$/;
	
	if (dollarsOK) {
		strVal = numberStrip(strVal);
	}
	
	return regexInt.test(strVal);
}

function isNumber(strVal, dollarsOK){
	if (dollarsOK) {
		strVal = numberStrip(strVal);
	}
	
	if (isNaN(strVal)){
		return false;
	}else{
		return true;
	}
}

function isSSN(strVal){
	var regexSSN = /^\d{3}\-?\d{2}\-?\d{4}$/;
	
	return regexSSN.test(strVal);
}

function isTime(strVal){
	var regexTime = /^((0?[1-9]|1[0-2]):[0-5][0-9](:[0-5][0-9])?\s([Aa|Pp][Mm])|((0|1)[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?)$/;
	
	return regexTime.test(strVal);
}

function isUSPhone(strVal){
	var regexPhone = /^\(?[1-9][0-9]{2}(\)\s?|[\s\-\.])?[0-9]{3}[\s\-\.]?[0-9]{4}$/;
	
	return regexPhone.test(strVal);
}

function isUSZip(strVal){
	var regexZip = /^\d{5}((\s|\-)?\d{4})?$/;
	
	return regexZip.test(strVal);
}

function multiSelectCheck(fldName, frm, minSel, maxSel){
	var selOK = false, s = 0, cnt = 0;
	
	for (s = 0; s < frm[fldName].options.length; s++){
		if (frm[fldName].options[s].selected){
			cnt++;
		}
	}
	if (cnt >= minSel && cnt <= maxSel){
		selOK = true;
	}
	
	return selOK;
}

function numberInRange(strVal, minAllowed, maxAllowed, dollarsOK){
	var numReturn = false, val = parseFloat(strVal), minVal = parseFloat(minAllowed), maxVal = parseFloat(maxAllowed);
	
	if (dollarsOK) {
		strVal = numberStrip(strVal);
	}
	if (isNumber(val) && (isNumber(minVal) || isNumber(maxVal))){
		/* as long as the test val and at least one range cap are numeric, then continue */
		if (isNumber(minVal) && isNumber(maxVal)){
			if (val >= minVal && val <= maxVal){
				numReturn = true;
			}
		}else if (isNumber(minVal)){
			if (val >= minVal){
				numReturn = true;
			}
		}else if (isNumber(maxVal)){
			if (val <= maxVal){
				numReturn = true;
			}
		}
	}
	
	return numReturn;
}

function numberStrip(strVal) {
	/* strip out '$' and ',' characters to test */
	var regexStrip = /[$,]/;
	
	while (strVal.match(regexStrip) != null) {
		strVal = strVal.replace(regexStrip, "");
	}
	
	return strVal;
}

function numericInRange(strVal, minAllowed, maxAllowed, dollarsOK){
	if (dollarsOK) {
		strVal = numberStrip(strVal);
	}
	
	return numberInRange(strVal, minAllowed, maxAllowed);
}

function radioChecked(fldName, frm){
	var radOK = false, r = 0;
	
	if (frm[fldName][0]){
		for (r = 0; r < frm[fldName].length; r++){
			if (frm[fldName][r].checked){
				radOK = true;
				break;
			}
		}
	}else if (frm[fldName].checked){
		radOK = true;
	}
	
	return radOK;
}

function selectCheck(fldName, frm){
	var selOK = true;
	
	if (isEmpty(frm[fldName].options[frm[fldName].selectedIndex].value)){
		selOK = false;
	}
	
	return selOK;
}

function testRegex(strVal, regExp){
	return eval(regExp).test(strVal)
}

function trim(strVal) {
	var regexSpace = /\W/, c = 0, rtnVal = "";
	
	if (strVal.length > 0) {
		for (c = 0; c < strVal.length; c++) {
			if (!regexSpace.test(strVal.charAt(c))) {
				rtnVal = strVal.substr(c, strVal.length);
				break;
			}
		}
	}
	
	return rtnVal;
}

/* FormValidator object */
/* constructor */
function FormValidator(frm){
	this.frm = frm;
	this.msgArr = new Array();
	this.fldArr = new Array();
}

/* prototypes */
FormValidator.prototype.appendError = appendError;
FormValidator.prototype.validate = validate;

/* methods */
function appendError(field, message){
	this.fldArr[this.fldArr.length] = field;
	this.msgArr[this.msgArr.length] = message;
}

function validate(inlineErrors){
	var f = 0, obj = null, errorPopup = true, errMsg = "";
	
	if(navigator.appName.indexOf("Microsoft") > -1){
		var toggle = 'block';
	} else {
		var toggle = 'table-row';
	}
	
	if (inlineErrors){
		errorPopup = false;
	}
	
	if (this.fldArr != undefined && this.fldArr.length > 0){
		for (f = 0; f < this.fldArr.length; f++){
			obj = this.frm[this.fldArr[f]];
			if (errorPopup){
				errMsg += "\n" + this.msgArr[f];
			}else if (!obj.hasError){
				obj.className += ' error';
				obj.onchange = removeError;
				obj.hasError = true;
				obj.title = this.msgArr[f];
			}
		}
		if (this.frm[this.fldArr[0]]["focus"]){
			this.frm[this.fldArr[0]].focus();
			if (this.frm[this.fldArr[0]]["select"]){
				this.frm[this.fldArr[0]].select();
			}
		}
		if (errorPopup) {
			alert("Please correct the following information.\n" + errMsg);
		} else {
			try{
				document.getElementById("formErrorBar").style.display = toggle;
			}catch(e){
				/* just skip it */
			}
		}
		return false;
	}else{
		return true;
	}
}

/* public object functions */
function removeError() {
	this.className = this.className.substring(0, this.className.lastIndexOf(' '));
	this.hasError = null;
	this.onchange = null;
	this.title = "";
}

function validationClear(frm){
	var e = 0;
	
	frm.reset();
	
	for (e = 0; e < frm.length; e++){
		if (frm[e].hasError){
			frm[e].className = "";
			frm[e].hasError = null;
			frm[e].onchange = null;
			frm[e].title = "";
		}
	}
	try{
		document.getElementById("formErrorBar").style.display = "none";
	}catch(e){
		/* just skip it */
	}
	
	return;
}
