/*
// Title = 			FormValidator.js 	//
// Version =		2.0					//
// Author =			Jon Toribio			//
// Last Updated	=	May 23rd, 2002		//
*/
function FormValidator(form_name) {
	this.f = form_name;
	this.requiredItems = new Array();
	this.itemConstraints = new Array();
	this.anchors = new Array();
	return this;
}


p = FormValidator.prototype;
p.isValidForm = FV_isValidForm;
p.hasValue = FV_hasValue;
p.getValue = FV_getValue;
p.setAnchor = FV_setAnchor;
p.addRequiredItem = FV_addRequiredItem;
p.removeRequiredItem = FV_removeRequiredItem;
p.setMINLength = FV_setMINLength;
p.setMAXLength = FV_setMAXLength;
p.setValidPattern = FV_setValidPattern;
p.setAsValidEmail = FV_setAsValidEmail;
p.setAsValidPostalCode = FV_setAsValidPostalCode;
p.setAsValidZipCode = FV_setAsValidZipCode;
p.setAsMatchingFields = FV_setAsMatchingFields;
p.setInvalidValue = FV_setInvalidValue;
p.setAsValidPhoneNumber = FV_setAsValidPhoneNumber;
p.setAsValidPhoneExtension = FV_setAsValidPhoneExtension;
p.IsANumber = FV_IsANumber;
p.setAsValidEightNumbers = FV_setAsValidEightNumbers;
p.setAsValidDate = FV_setAsValidDate;
p.setAsValidMod10 = FV_setAsValidMod10;
p.setAsValidMod11 = FV_setAsValidMod11;



function FV_isValidForm() {
	var frm = eval(this.f);
	
	// check required fields
	for (itm in this.requiredItems)	{
		if (typeof frm.elements[itm] == "undefined") {
			alert("FormValidator error:\nElement '" + itm + "' doesn't exist.");
			return false;
		}

		// check if required field has input
		if ( _hasInput(frm.elements[itm]) ) {
			// check if input is valid
			if ( _isValidInput(frm.elements[itm], this.itemConstraints, frm) ) {
			} else {
				// complain about invalid input
				_focusItem(frm.elements[itm],this.anchors);
				return false;
			}
		} else {
			// complain about required field
			alert(this.requiredItems[itm].errmsg);
			_focusItem(frm.elements[itm],this.anchors);
			return false;
		}
	}
	
	for (itm in this.itemConstraints) {
		if (typeof frm.elements[itm] == "undefined") {
			alert("FormValidator error:\nElement '" + itm + "' doesn't exist.");
			return false;
		}
		if ( _hasInput(frm.elements[itm]) ) {
			// check if input is valid
			if ( _isValidInput(frm.elements[itm], this.itemConstraints, frm) ) {
			} else {
				// complain about invalid input
				_focusItem(frm.elements[itm],this.anchors);
				return false;
			}
		}
	}
	// check non-required fields

	return true;
}

function FV_hasValue(element_name) {
	var frm = eval(this.f);
	var form_element = frm.elements[element_name];
	return _hasInput(form_element);
}

function FV_getValue(element_name) {
	var frm = eval(this.f);
	var form_element = frm.elements[element_name];
	return _elem_value(form_element);
}

function FV_setAnchor(element_name, anchor_name) {
	this.anchors[element_name] = anchor_name;
}

function FV_addRequiredItem(element_name, errmsg) {
	var newobj = new Object();
	newobj.errmsg = errmsg;
	this.requiredItems[element_name] = newobj;
}

function FV_removeRequiredItem(element_name) {
	delete this.requiredItems[element_name];
}

function FV_setMINLength(element_name, val, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.value = val;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["MIN_LENGTH"] = newobj;
}

function FV_setMAXLength(element_name, val, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.value = val;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["MAX_LENGTH"] = newobj;
}

function FV_setValidPattern(element_name, reg_exp, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = reg_exp;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}


function FV_setAsValidEmail(element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = /^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*@([a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*\.[a-zA-Z]{2,3}|([0-9]|[1-9][0-9]{1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]{1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]{1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]{1}|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$/;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}

function FV_setAsValidPostalCode(element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = /^(([a-zA-Z][0-9]){3}|([a-zA-Z][0-9][a-zA-Z] [0-9][a-zA-Z][0-9]))$/;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}

function FV_setAsValidZipCode(element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = /^[0-9]{5}$/;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}

function FV_setAsValidPhoneNumber(area_code_field, phone_exchange_field, phone_number_field, errmsg) {
	var three_digit = new Object();
	var four_digit = new Object();
	
	if (typeof this.itemConstraints[area_code_field] == "undefined") {
		this.itemConstraints[area_code_field] = new Array();
	}
	if (typeof this.itemConstraints[phone_exchange_field] == "undefined") {
		this.itemConstraints[phone_exchange_field] = new Array();
	}
	if (typeof this.itemConstraints[phone_number_field] == "undefined") {
		this.itemConstraints[phone_number_field] = new Array();
	}

	three_digit.regexp = /^[0-9]{3}$/;
	three_digit.errmsg = errmsg;

	four_digit.regexp = /^[0-9]{4}$/;
	four_digit.errmsg = errmsg;

	this.itemConstraints[area_code_field]["VALID_REGEXP"] = three_digit;
	this.itemConstraints[phone_exchange_field]["VALID_REGEXP"] = three_digit;
	this.itemConstraints[phone_number_field]["VALID_REGEXP"] = four_digit;
}

function FV_setAsValidPhoneExtension(element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = /^[0-9]{4}$/;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}


function FV_IsANumber(element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = /^\d+$/;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}

function FV_setAsValidEightNumbers(element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.regexp = /^[0-9]{8}$/;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_REGEXP"] = newobj;
}


function FV_setAsMatchingFields(element_name, tgt_element_name, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.target = tgt_element_name;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["MATCHING_FIELDS"] = newobj;
}

function FV_setInvalidValue(element_name, val, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.value = val;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["INVALID_VALUE"] = newobj;
}

function FV_setAsValidDate(day_element_name, month_element_name, year_element_name, day_errmsg, month_errmsg, year_errmsg) {
	var newobj;
	var reobj;
	
	if (typeof this.itemConstraints[day_element_name] == "undefined") {
		this.itemConstraints[day_element_name] = new Array();
	}
	if (typeof this.itemConstraints[month_element_name] == "undefined") {
		this.itemConstraints[month_element_name] = new Array();
	}
	if (typeof this.itemConstraints[year_element_name] == "undefined") {
		this.itemConstraints[year_element_name] = new Array();
	}
	
	var day_ptrn = /^([1-9]|0[1-9]|[12][0-9]|3[01])$/;
	reobj = new Object();
	reobj.regexp = day_ptrn;
	reobj.errmsg = day_errmsg;
	this.itemConstraints[day_element_name]["VALID_REGEXP"] = reobj;

	var month_ptrn = /^([1-9]|0[1-9]|1[0-2])$/;
	reobj = new Object();
	reobj.regexp = month_ptrn;
	reobj.errmsg = month_errmsg;
	this.itemConstraints[month_element_name]["VALID_REGEXP"] = reobj;

	var year_ptrn = /^[0-9]{1,4}$/;
	reobj = new Object();
	reobj.regexp = year_ptrn;
	reobj.errmsg = year_errmsg;
	this.itemConstraints[year_element_name]["VALID_REGEXP"] = reobj;
	
	newobj = new Object();
	newobj.day_elem = day_element_name;
	newobj.month_elem = month_element_name;
	newobj.year_elem = year_element_name;
	newobj.errmsg = day_errmsg;
	this.itemConstraints[day_element_name]["VALID_DAY"] = newobj;
}

function FV_setAsValidMod10(element_name, errmsg) {
	var newobj = new Object();
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_MOD10"] = newobj;
}

function FV_setAsValidMod11(element_name, errmsg) {
	var newobj = new Object();
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["VALID_MOD11"] = newobj;
}

function FV_setMINListSize(element_name, val, errmsg) {
	var newobj = new Object();
	
	if (typeof this.itemConstraints[element_name] == "undefined") {
		this.itemConstraints[element_name] = new Array();
	}
	newobj.value = val;
	newobj.errmsg = errmsg;
	this.itemConstraints[element_name]["MIN_LISTSIZE"] = newobj;
}


// helper functions

function _trim(str) {
	var ptrn_ws = /(^\s+)|(\s+$)/g;
	return str.replace(ptrn_ws,"");
}


function _hasInput(form_element) {

	switch(_elem_type(form_element)) {
		case "text":
		case "textarea":
		case "password":
		case "file":
			form_element.value = _trim(form_element.value);
			return (form_element.value.length > 0);
			break;
		case "checkbox":
			if (typeof(form_element.checked) != "boolean") 
			{
				var rtrnval = false;
				for ( i = 0 ; i < form_element.length ; i++ ) {
					var fe = form_element[i];
					if (fe.checked) 
						rtrnval = true;
				}
				return rtrnval;
			}
			else	
				return form_element.checked;
			break;
		case "radio":
			return _isRadioSelected(form_element);
			break;
		case "select-one":
		case "select-multiple":
			return _isOptionSelected(form_element);
			break;
		case "hidden":
		default:
			break;
	}
	return true;
}

function _isValidInput(form_element, rules, frm) {
	var fe_name;
	var itm;

	fe_name = _elem_name(form_element);

	for (itm in rules[fe_name]) {
		switch(itm) {
			case 'MIN_LENGTH':
				if (_elem_value(form_element).length < rules[fe_name]["MIN_LENGTH"].value) {
					alert(rules[fe_name]["MIN_LENGTH"].errmsg);
					return false;
				}
				break;
			case 'MAX_LENGTH':
				if (_elem_value(form_element).length > rules[fe_name]["MAX_LENGTH"].value) {
					alert(rules[fe_name]["MAX_LENGTH"].errmsg);
					return false;
				}
				break;
			case 'VALID_REGEXP':
				if ( _elem_value(form_element).search(rules[fe_name]["VALID_REGEXP"].regexp) == -1 ) {
					alert(rules[fe_name]["VALID_REGEXP"].errmsg);
					return false;
				}
				break;
			case 'VALID_MOD10':
				if ( ! _isValidMod10(_elem_value(form_element)) ) {
					alert(rules[fe_name]["VALID_MOD10"].errmsg);
					return false;
				}
				break;
			case 'VALID_MOD11':
				if ( ! _isValidMod11(_elem_value(form_element)) ) {
					alert(rules[fe_name]["VALID_MOD11"].errmsg);
					return false;
				}
				break;
			case 'MATCHING_FIELDS':
				var tgt_elem = frm.elements[rules[fe_name]["MATCHING_FIELDS"].target];
				if ( _elem_value(form_element) != _elem_value(tgt_elem) ) {
					alert(rules[fe_name]["MATCHING_FIELDS"].errmsg);
					return false;
				}
				break;
			case 'INVALID_VALUE':
				if ( _elem_value(form_element) == rules[fe_name]["INVALID_VALUE"].value ) {
					alert(rules[fe_name]["INVALID_VALUE"].errmsg);
					return false;
				}
				break;
			case 'VALID_DAY':
				var day_elem = frm.elements[rules[fe_name]["VALID_DAY"].day_elem];
				var month_elem = frm.elements[rules[fe_name]["VALID_DAY"].month_elem];
				var year_elem = frm.elements[rules[fe_name]["VALID_DAY"].year_elem];
				
				if (_isValidDateValues(_elem_value(form_element), _elem_value(month_elem), _elem_value(year_elem)) ) {
					var tmp_date = new Date(_elem_value(year_elem),_elem_value(month_elem) - 1,_elem_value(form_element));
					if (tmp_date.getDate() != parseInt(_elem_value(form_element))) {
						alert(rules[fe_name]["VALID_DAY"].errmsg);
						return false;
					}
				}
				break;
			default:
		}
	}

	return true;
}

/*
function _getBadDateElement(form_element, rules, frm) {
	var fe_name;
	var itm;

	fe_name = _elem_name(form_element);

	for (itm in rules[fe_name]) {
		switch(itm) {
			case 'VALID_DAY':
				var day_elem = frm.elements[rules[fe_name]["VALID_DAY"].day_elem];
				var month_elem = frm.elements[rules[fe_name]["VALID_DAY"].month_elem];
				var year_elem = frm.elements[rules[fe_name]["VALID_DAY"].year_elem];
				
				if (_isValidDateValues(_elem_value(form_element), _elem_value(month_elem), _elem_value(year_elem)) ) {
					var tmp_date = new Date(_elem_value(year_elem),_elem_value(month_elem) - 1,_elem_value(form_element));
					if (tmp_date.getDate() != parseInt(_elem_value(form_element))) {
						alert(rules[fe_name]["VALID_DAY"].errmsg);
						return form_element;
					}
				}
				break;
			default:
		}
	}

	return null;
}
*/

function _focusItem(form_element, anchors) {
	
	if ( typeof anchors[_elem_name(form_element)] != "undefined" ) {
		document.location = anchors[_elem_name(form_element)];
	}
	
	switch(_elem_type(form_element)) {
		case "text":
		case "textarea":
		case "password":
		case "file":
			form_element.focus();
			form_element.select();
			break;
		case "checkbox":
			if (typeof form_element[0] == "undefined")
				form_element.focus();
			else
				form_element[0].focus();
			break;			
		case "select-one":
		case "select-multiple":
			form_element.focus();
			break;
		case "radio":
			form_element[0].focus();
			break;
		case "hidden":
		default:
			break;
	}
}

function _isRadioSelected(form_element) {
	for(var i = 0; i < form_element.length ; i++) {
		if (form_element[i].checked) return true;
	}
	return false;
}

function _isOptionSelected(form_element) {
	for(var i = 0; i < form_element.options.length ; i++ ) {
		if (form_element.options[i].selected) return true;
	}
	return false;
}

function _isValidDateValues(day_val, month_val, year_val) {
	var day_ptrn = /^([1-9]|[12][0-9]|3[01])$/;
	var month_ptrn = /^([1-9]|1[0-2])$/;
	var year_ptrn = /^[0-9]{1,4}$/;

	return (day_val.match(day_ptrn) && month_val.match(month_ptrn) && year_val.match(year_ptrn));	
}

function _isValidMod10(val) {
	var sum = 0;
	var num, num0;
	var mult = 1;

	for ( var i = val.length - 1 ; i >= 0 ; i-- )  {
		num = new Number(val.substr(i, 1));
		num = num * mult;
		num = (num > 9) ? num - 9 : num;
		sum += num;
		mult = 3 - mult;
	}
	return (sum % 10 == 0);
}

function _isValidMod11(val) {
	var sum = 0;
	var num, num0;
	var mult = 1;

	for ( var i = val.length - 1 ; i >= 0 ; i-- )  {
		num = new Number(val.substr(i, 1));
		num = num * mult;
		sum += num;
		mult += 1;
	}
	return (sum % 11 == 0);
}

function _elem_type(form_element) {
	if(form_element.type) 			return form_element.type;
	else if (form_element[0].type) 	return form_element[0].type;
	else							return "unknown";	
}

function _elem_name(form_element) {
	if(form_element.name) 			return form_element.name;
	else if (form_element[0].name) 	return form_element[0].name;
	else							return "unknown";	

}

function _elem_value(form_element) {

	switch(_elem_type(form_element)) {
		case "text":
		case "textarea":
		case "password":
		case "file":
		case "hidden":
			return form_element.value;
			break;
		case "checkbox":
			if(form_element.value)	
				return form_element.value;
			else if (form_element[0].value) 
			{
				var chkboxlist = new Array();
				for ( i = 0 ; i < form_element.length ; i++ ) {
					var fe = form_element[i];
					if (fe.checked) 
						chkboxlist[chkboxlist.length] = fe.value;
				}
				return chkboxlist.join(",");
			}
			else	
				return "unknown";
			break;
		case "select-one":
			return form_element.options[form_element.selectedIndex].value;
			break;
		case "select-multiple":
			var tmparr = new Array();
			for (var i = 0 ; i < form_element.options.length ; i++ ) {
				var _o = form_element.options[i];
				if ( _o.selected ) {
					tmparr[tmparr.length] = _o.value;
				}
			}
			return tmparr.join(",");
			break;
		case "radio":
			for(var i = 0; i < form_element.length ; i++) {
				if (form_element[i].checked) return form_element[i].value;
			}
			return null;
			break;
		default:
			return null;
	}
	
}

// custom definitions
var ptrn_sys_name = /^[a-zA-Z_0-9]+$/;

