//-----------------------------------------------------
// Error string definitions:
//-----------------------------------------------------

// {0} is the field label:
NUMBER_ERROR = "{0} is not a number.\n\n";

// {0} is the field label:
PHONE_ERROR = "{0} is not a valid phone number (###-###-#### including area code).\n\n";

// {0} is the field label:
PHONEAREA_ERROR = "{0} is not valid.\n\n";

// {0} is the field label:
PHONEPREFIX_ERROR = "{0} is not valid.\n\n";

// {0} is the field label:
PHONESUFFIX_ERROR = "{0} is not valid.\n\n";

// {0} is the field label:
SSN_ERROR = "{0} is not a valid Social Security Number (###-##-####).\n\n";

// {0} is the field label:
POSTAL_ERROR = "{0} is not a valid US Zip Code.\n\n";

// {0} is the field label:
NO_SPACE_ERROR = "{0} may not have spaces.\n\n"; EMAIL_ERROR = "{0} is not a valid email address (for example: name@domain.com).\n\n";

// {0} is the field label:
DATE_ERROR = "{0} is not a valid date.\n\n";

// {0} is the label, {1} the min and {2} the max
RANGE1_ERROR = "The value for {0} must be between {1} and {2}.\n\n";

// {0} is the label, {1} the min
RANGE2_ERROR = "The value for {0} cannot be less than {1}.\n\n";

// {0} is the label, {1} the max
RANGE3_ERROR = "The value for {0} cannot be more than {1}.\n\n";

// {0} is the label, {1} the maxlength:
LENGTH0_ERROR = "{0} must be exactly {1} characters.\n\n";

// {0} is the label, {1} the minlength and {2} the maxlength:
LENGTH1_ERROR = "{0} must be between {1} and {2} characters.\n\n";

// {0} is the label, {1} the minlength:
LENGTH2_ERROR = "{0} cannot be less than {1} characters.\n\n";

// {0} is the label, {1} the maxlength:
LENGTH3_ERROR = "{0} cannot be more than {1} characters.\n\n";

// {0} is the missingFields list:
REQUIRED_ERROR = "The following required field is missing:\n{0}\n";

// {0} is the field label:
EMAIL_ERROR = "{0} is not valid email.\n\n";


//-----------------------------------------------------
// Validation entry points: entire form or single field
//-----------------------------------------------------
function validateForm(form) {
	var errMsg = "";
	var field;	
	for (var i = 0; i < form.length; i++) {
		field = form.elements[i];
		errMsg = validateField(field);
		//show errorMsg if set
		if (errMsg != "") {
			alert(errMsg);
			field.focus();
			if (field.type == "text") field.select();
			return false;
		}
	}
	return true;
}


function validateField(field) {
	var errMsg = "";
	if (field.label != null && field.label != "" && !field.noValidation) {
		errMsg = chkRequired(field);    //Check required field for data
		if ((errMsg == "") && ((field.type == "text") || (field.type == "textarea"))) {
			errMsg = chkValueFormat(field);  //Check if field data is in desired format
		}
	}
	return errMsg;
}


//-----------------------------------------------------
// Validation functions
//-----------------------------------------------------
function chkRequired(field) {
	var errMsg = "";
	var value = "";
	
	if (field.required) {
		errMsg = REQUIRED_ERROR.replace("{0}", field.label);
		switch (field.type) {
			case "text":			
			case "textarea":
			   value = trim(field.value);
				if (value != "") {
				   if (field.ignoreValue == null) errMsg = "";
				   else if  (value.toLowerCase() != field.ignoreValue.toLowerCase()) errMsg = "";
				}
				break;
			case "checkbox":
			case "radio":
			   var fieldGroup = field.form[field.name];
				for (var i = 0; i < fieldGroup.length; i++) {
					if (fieldGroup[i].checked) {
						errMsg = "";
						break;
					}
				}
				break;
			case "select-one":
			case "select-multiple":
				//must has at least 1 item selected that's not the first item
				var fieldGroup = field.form[field.name];
				for (var i = 1; i < fieldGroup.length; i++) {
					if (fieldGroup[i].selected) {
						errMsg = "";
						break;
					}
				}
				break;
			default:
				errMsg = "";
		}
	}
	return errMsg;
}


function chkValueFormat(field) {
	var errMsg = "";
	//check format only if field has value, value not the same as ignoreValue, and datatype is set
	if ((field.datatype != null) && (field.value != null) && (field.value != "") && (field.ignoreValue == null || trim(field.value).toLowerCase() != field.ignoreValue.toLowerCase())) {
		field.value = trim(field.value);
		switch (field.datatype) {
			case "string":
				if ((field.maxlength != null) && (field.value.length > field.maxlength)) {
					errMsg = LENGTH3_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.maxlength);
				}
				else if ((field.minlength != null) && (field.value.length < field.minlength)) {
					errMsg = LENGTH2_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.minlength);
				}
				break;
			case "phone":
				if (!isPhone(field.value)) {
					errMsg = PHONE_ERROR.replace("{0}", field.label);
				}
				break;
                        case "phonearea":
                                if (isNaN(field.value) || field.value.length != 3) {
					errMsg = PHONEAREA_ERROR.replace("{0}", field.label);
				}
				break;
			case "phoneprefix":
			   if (isNaN(field.value) || field.value.length != 3) {
					errMsg = PHONEPREFIX_ERROR.replace("{0}", field.label);
				}
				break;
			case "phonesuffix":
			   if (isNaN(field.value) || field.value.length != 4) {
					errMsg = PHONESUFFIX_ERROR.replace("{0}", field.label);
				}
				break;
			case "zip":
				if (!isZip(field.value)) {
					errMsg = POSTAL_ERROR.replace("{0}", field.label);
				}
				break;
			case "ssn":
				if (!isSSN(field.value)) {
					errMsg = POSTAL_ERROR.replace("{0}", field.label);
				}
				break;
			case "number":
				if (isNaN(field.value)) {
					errMsg = NUMBER_ERROR.replace("{0}", field.label);
				}				
				else if  ((field.maxrange != null) && (field.minrange != null) && (field.value > field.maxrange || field.value < field.minrange)) {
					errMsg = RANGE1_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.minrange);
					errMsg = errMsg.replace("{2}", field.maxrange);
				}				
				else if ((field.maxrange != null) && (field.value > field.maxrange)) {
					errMsg = RANGE3_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.maxrange);
				}				
				else if ((field.minrange != null) && (field.value < field.minrange)) {
					errMsg = RANGE2_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.minrange);
				}
				break;
			case "email":
				if (!isEmail(field.value)) {
					errMsg = EMAIL_ERROR.replace("{0}", field.label);					
				}
				break;
			case "numericstring": //ex: ssn broken down 222-22-4444
				if (isNaN(field.value)) {
					errMsg = NUMBER_ERROR.replace("{0}", field.label);
				}				
				else if  ((field.maxlength != null) && (field.minlength != null) && (field.value.length > field.maxlength || field.value.length < field.minlength)) {
					if (field.maxlength == field.minlength) {
						errMsg = LENGTH0_ERROR.replace("{0}", field.label);
						errMsg = errMsg.replace("{1}", field.minlength);
						errMsg = errMsg.replace("{2}", field.maxlength);
					}
					else {
						errMsg = LENGTH1_ERROR.replace("{0}", field.label);
						errMsg = errMsg.replace("{1}", field.minlength);
						errMsg = errMsg.replace("{2}", field.maxlength);
					}
				}				
				else if ((field.maxlength != null) && (field.value.length > field.maxlength)) {
					errMsg = LENGTH3_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.maxlength);
				}				
				else if ((field.minlength != null) && (field.value.length < field.minlength)) {
					errMsg = LENGTH2_ERROR.replace("{0}", field.label);
					errMsg = errMsg.replace("{1}", field.minlength);
				}
		}
	}
	return errMsg;
}

function trim(s) { // trim white space
	return s.replace(/^\s+|\s+$/g, '');
}

function isPhone(s) { // telephone, with area code + opt prefixes
	var a = s.replace(/\D+/g, '-');
	a = a.match(/(\d+-?)*(\d{3}-?){2}\d{4}/g);
	var err = (a != null && a.length ? false : true);
	return err;
}

function isZip(s) {
	var filter = /\d{5}(-?\d{4}){0,1}/;
	return filter.test(s);
}

function isSSN(s) {
	var filter = /^(\d{9}|\d{3}-\d{2}-\d{4})$/;
	return filter.test(s);
}

function isEmail(s) {
	var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	return filter.test(s);
}
