// A utility function that returns true if a string is a valid email
function isEmail(s) {
	if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(s)){
		return(true)
	}
	return false;
}

// A utility function that returns true if a string is in correct date format
// or is empty
function isDate(d) {

	if (d.length == 0)
		return true;

	var isplit = d.indexOf('/');
	if (isplit == -1 || isplit == d.length)
		return false;

	// get the month
    sMonth = d.substring(0, isplit);
	fMonth = parseFloat(sMonth);
	if (isNaN(fMonth) || (fMonth < 1) || (fMonth > 12))
		return false;
	isplit = d.indexOf('/', isplit + 1);
	if (isplit == -1 || (isplit + 1 ) == d.length)
		return false;

	// get the day
    sDay = d.substring((sMonth.length + 1), isplit);
	fDay = parseFloat(sDay);
	if (isNaN(fMonth))
		return false;
	
	// get the year
	sYear = d.substring(isplit + 1);
	fYear = parseFloat(sYear);
	if (isNaN(fYear))
		return false;

	// check range of day
	var maxDay = 31;
	if ((fMonth == 4) || (fMonth == 6) || (fMonth == 9) || (fMonth == 11)) {
		maxDay = 30;
	}
	else if (fMonth == 2) {
		if (fYear % 4 > 0)
			maxDay =28;
		else if ((fYear % 100 == 0) && (fYear % 400 > 0))
			maxDay = 28;
		else
			maxDay = 29;
	}
	if ((fDay > maxDay) || (fDay < 1))
		return false;
	
	// check range of the year
//	if ((fYear < 1000) || (fYear > 9999))
//		return false;
	if (fYear > 99) {
		if ((fYear < 1000) || (fYear > 9999))
			return false;
	}
	else if ((fYear < 0) || (fYear > 99))
		return false;

	return true;
}

// A utility function that returns true if a string contains only
// whitespace characters.
function isblank(s) {
	for(var i = 0; i < s.length; i++) {
		var c = s.charAt(i);
		if ((c != ' ') && (c != '\n') && (c != '\t')) {
			return false;
		}
	}
	return true;
}

// This is the function that performs form verification. It will be invoked
// from the onsubmit() event handler.  The handler should return whatever
// value this function returns
function verify(f) {
	var msg;
	var empty_fields = "";
	var errors = "";
	var badEmails = "";
	var badConfirms = "";
	var badCheckbox = "";
	var badDate = "";

	// Loops through all elements of the form to validate each one if need be.
	// It checks for the following:
	//   - incorrectly formatted email
	//   - empty fields
	//   - unchecked checkboxes
	//   - confirmation fields matching the fields they're confirming
	//
	// Whether the fields get validated or not is determined by setting
	// properties in the form tag of the html document.  To apply validation
	// to the form, do the following in the "onsubmit" parameter of the form tag
	//   - empty fields: validated automatically
	//   - optional fields: this.<nameOfField>.optional = true;
	//	 - email: this.<nameofEmailfield>.email = true;
	//   - confirmation: (the name of the confirmation field must be the name
	//		of the field it is confirming, with "confirm" as it's prefix)
	//			this.<nameOfField>.confirmationField = true;
	for(var i = 0; i < f.length; i++) {
		var e = f.elements[i];
		if (((e.type == "text") || (e.type =="textarea") || (e.type == "password")) && !e.optional) {

			// first check if the field is empty
			if ((e.value == null) || (e.value == "") || isblank(e.value)) {
				empty_fields += "\n          " + e.name;
				continue;
			}
			
			// Now check for fields that are supposed to be numeric.
			if (e.numeric || (e.min != null) || (e.max != null)) {
				var v = parseFloat(e.value);
				if (isNaN(v) ||
					((e.min != null) && (v < e.min)) ||
					((e.max != null) && (v > e.max))) {
					errors += "- The field " + e.name + " must be a number";
					if (e.min != null) {
						errors += " that is greater than " + e.min;
					}
					if (e.max != null) {
						errors += " and less than " + e.max;
					}
					else if (e.max != null) {
						errors += " that is less than " + e.max;
					}
					errors += ".\n";
				}
			}
		} // end of if for empty and numeric
			
		// Now check for fields that are confirmation fields.
		// This is done by making sure the field has it's "confirmationField" property
		// set to true.  If so, then the name of the field must begin with "confirm".  The 
		// name of the field it is confirming is whatever follows confirm in it's name.  For
		// example, the "confirmWhatEver" field confirms the "WhatEver" field.
		if ((e.confirmationField) && (e.name.indexOf("confirm") == 0) && (e.name.length > 7)
			&& ((e.type == "text") || (e.type == "password")) ) {
			var confirmValue = "";
			for(var j = 0; j < f.length; j++) {
				var d = f.elements[j];
				if (d.name == e.name.substring(7)) {
					if (d.value != e.value) {
						badConfirms += "\n The value of " + e.name + " did not match ";			
						badConfirms += "the value of " + e.name.substring(7) + ".";
						continue;
					}
				}
			} // end inner for
		} // end if for confirmation
			
		// Now check email fields for formatting
		if ((e.type=="text") && e.email) {
		// if email is optional, don't check unless there is some text
			if (e.optional) {
				if ((e.value != null) && (e.value !="")) {
					if (!isEmail(e.value)) {
						badEmails += "\n \"" + e.value + "\" is an invalid email.\n";
					}
				}
			}

			// if email is NOT optional, check it
			else if (!isEmail(e.value)) {
					badEmails += " \"" + e.value + "\" is an invalid email.\n";
			}
		}
		
		// Now check date fields for formatting
		if ((e.type=="text") && e.date) {
			if (!isDate(e.value)) {
				//badDate += "\n \"" + e.value + "\" is not in MM/DD/YYYY format.\n";
				badDate += "\n The field \"" + e.name + "\" is not in MM/DD/YYYY format.\n";
			}
		}
		
		// Now check that checkboxes are checked if they have to be
		if ((e.type=="checkbox") && (e.mustBeChecked)) {
			if (!e.checked) {
				badCheckbox += " The \"" + e.name + "\" checkbox must be checked.\n";
			}
		}
		
		// Now check for numeric fields that aren't numeric
		if ((e.type=="text") && e.numeric) {
			if ((e.value != null) && (e.value !="")) {
				var v = parseFloat(e.value);
				if (isNaN(v) ||
					((e.min != null) && (v < e.min)) ||
					((e.max != null) && (v > e.max))) {
					errors += "- The field " + e.name + " must be a number";
					if (e.min != null) {
						errors += " that is greater than " + e.min;
					}
					if (e.max != null) {
						errors += " and less than " + e.max;
					}
					else if (e.max != null) {
						errors += " that is less than " + e.max;
					}
					errors += ".\n";
				}
			}
		}

	} // end for
	
	// Now, if there were any errors, display the messages, and
	// return false to prevent the form from being submitted.
	// Otherwise return true.
	if (!empty_fields && !errors && !badEmails && !badConfirms && !badCheckbox && !badDate) {
		return true;
	} // end if
	
	msg = "_________________________________________________________\n\n";
	msg += "The form was not submitted because of the following error(s).\n";
	msg += "Please correct these error(s) and re-submit.\n";
	msg += "_________________________________________________________\n\n";
	
	if (empty_fields) {
		msg += "- The following required field(s) are empty:"
				+ empty_fields + "\n";
		if ((errors) || (badEmails)) {
			msg += "\n";
		}
	} // end if
	msg += errors + badEmails + badConfirms + badCheckbox + badDate;
	alert(msg);
	return false;
} // end function