
/*=======================================================
validateform() function
Compatible with NS4+, IE4+
Developed by: effective-e (http://www.effective-e.com)

Arguments:	argForm (form object)
			argFieldList (string indicating required and/or especially formatted fields)

Usage:		High-level validation of form fields.
			Pass into the function the form to validate and the fields within it to validate.
			If the form does not pass the validation, then the user is notified and the focus is set to the field.
			The argFieldList argument is a comma-separated list of validated fields, each with this syntax:
				fieldname^validatetype^req
				'fieldname' (required): actual field name of the field.
				'validatetype' (required): type of validation to perform. Acceptable types are:
					1. phone
					2. ssn
					3. zip
					4. email
					5. date
					6. zip5
					7. zip4
					8. number
					9. decimal
					10. minute
					11. text - a "placeholder" if there is no validatetype but the field is required
					12. a number (ie 150, 2200) - this validates length
				'req' (not required): add this if the field is required.
				*Notice that the caret symbol (^) separates each segment of the field validation. This is the required delimiter.
				If you wish to validate a form in more than one way (like a field is an email and also under 20 characters), 
					simply place the field into argFieldList twice (ie fieldname^email,fieldname^20)
			Note: some funny things may happen if you put characters other than alphanumerics in the field and/or form names, 
				depending on the browser. Try avoiding this, even when not using this script!

Example:	Place onsubmit="return validateform(this,'phnum^phone,dob^date^req,info^50^req,title^text^req,contact^email');"
				into the <form> tag. The 'return' keyword is essential when using in the <form> tag.
			This indicates:
				1. The phnum field must be a valid phone format: numeric and 7 or 10 digits. The field is not required.
				2. The dob field must be a valid date: m/d/yyyy. The field is required.
				3. The info field must be 50 or less characters. The field is required.
				4. The title field is not validated against anything, but it is required.
				5. The contact field must be valid email syntax. The field is not required.
=====================================================*/

// Initialize global variables
var digits = "0123456789";
var daysInMonth = new Array();
daysInMonth[1] = 31
daysInMonth[2] = 29   // must programmatically check this
daysInMonth[3] = 31
daysInMonth[4] = 30
daysInMonth[5] = 31
daysInMonth[6] = 30
daysInMonth[7] = 31
daysInMonth[8] = 31
daysInMonth[9] = 30
daysInMonth[10] = 31
daysInMonth[11] = 30
daysInMonth[12] = 31

// validateform() function: "parent" function to validate form fields
function validateform(argForm,argFieldList) {
// Create array of field to validate
var arrFieldList = argFieldList.split(',');
	// Loop through the array of fields
	for (var elementID = 0; elementID<=arrFieldList.length-1; elementID++) {
		// Create array of stuff to validate (ie fieldname, validate type, required)
		var arrName = arrFieldList[elementID].split('^');
		// Define field name
		var vField = arrName[0];
		// If user has supplied more than just the name...
		if (arrName.length > 1) {
			// If the field is required, check the type of form field and perform appropriate action
			if(arrName[2] == 'req') {
				if(argForm[vField].type == 'select-one'){
					if(argForm[vField].selectedIndex == 0){
						fieldalert(argForm,vField,1);
						return false;
					}
				}
				else if(argForm[vField].type == 'text'){
					if(argForm[vField].value.length == 0) {
						fieldalert(argForm,vField,1);
						return false;
					}
				}
				else if(argForm[vField].type == 'textarea'){
					if(argForm[vField].value == '') {
						fieldalert(argForm,vField,1);
						return false;
					}
				}
				else if(argForm[vField].type == 'hidden'){
					if(argForm[vField].value == '') {
						fieldalert(argForm,vField,1);
						return false;
					}
				}
			}
			// Phone validation
			if(arrName[1] == 'phone') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,0);
					if (returnValue == false || returnValue.length != 7 && returnValue.length != 10) {
						fieldalert(argForm,vField,4,'7 or 10');
						return false;
					}
					else
						argForm[vField].value = reformat(returnValue, 'phone');
				}
			}
			// Social Security Number (SSN) validation
			else if (arrName[1] == 'ssn') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,0,9);
					if (returnValue == false) {
						fieldalert(argForm,vField,4,9);
						return false;
					}
					else
						argForm[vField].value = reformat(returnValue, 'ssn');
				}
			}
			// ZIP (12345-6789) validation
			else if (arrName[1] == 'zip') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,0);
					if (returnValue == false) {
						fieldalert(argForm,vField,6);
						return false;
					}
					else if (returnValue.length != 5 && returnValue.length != 9) {
						fieldalert(argForm,vField,6);
						return false;
					}
					else
						if (returnValue.length == 9) 
							returnValue = reformat(returnValue,'zip+4');
						argForm[vField].value = returnValue;
				}
			}
			// Email validation
			else if (arrName[1] == 'email') {
				if (argForm[vField].value.length > 0) {
					returnValue = checkEmail(argForm[vField].value);
					if (returnValue == false) {
						fieldalert(argForm,vField,3);
						return false;
					}
				}
			}
			// Date (m/d/yyyy) validation
			else if (arrName[1] == 'date') {
				if (argForm[vField].value.length > 0) {
					returnValue = checkDate(argForm[vField].value);
					if (returnValue == false) {
						fieldalert(argForm,vField,5);
						return false;
					}
				}
			}
			// ZIP5 (12345) validation
			else if (arrName[1] == 'zip5') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,0,5);
					if (returnValue == false) {
						fieldalert(argForm,vField,4,5);
						return false;
					}
					else
						argForm[vField].value = returnValue;
				}
			}
			// ZIP4 (1234) validation
			else if (arrName[1] == 'zip4') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,0,4);
					if (returnValue == false) {
						fieldalert(argForm,vField,4,4);
						return false;
					}
					else
						argForm[vField].value = returnValue;
				}
			}
			// Numeric validation
			else if (arrName[1] == 'number') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,0);
					if (returnValue == false) {
						fieldalert(argForm,vField,7);
						return false;
					}
					else
						argForm[vField].value = returnValue;
				}
			}
			// Decimal validation
			else if (arrName[1] == 'decimal') {
				if (argForm[vField].value.length > 0) {
					returnValue = stripChars2Num(argForm[vField].value,1);
					if (returnValue == false) {
						fieldalert(argForm,vField,7);
						return false;
					}
					else
						argForm[vField].value = returnValue;
				}
			}
			// Minute (0-60) validation
			else if (arrName[1] == 'minute') {
				if (argForm[vField].value.length > 0) {
					returnValue = validateMinutes(argForm[vField].value);
					if (returnValue == false) {
						fieldalert(argForm,vField,8);
						return false;
					}
				}
			}
			// Length validation
			else if (isNumber(arrName[1])) {
				if (argForm[vField].value.length > 0) {
					textLen = argForm[vField].value.length;
					if (textLen > arrName[1]) {
						fieldalert(argForm,vField,2,textLen,arrName[1]);
						return false;
					}
				}
			}
		}	
	}

	return true
}
// Choose proper alert for validation
// fieldalert(formID,elementID,alertID[,size]) pass size argument for numbers
// fieldalert(formID,elementID,alertID[,length,maxlength]) pass the length of text and the maximum length
function fieldalert(formID,elementID,alertID) {
	switch(alertID) {
	case (1) :
		alert('Please fill in all required fields.');
		break;
	case (2) :
		alert('This field is ' + fieldalert.arguments[3] + ' characters long.\nThe maximum number of characters is ' + fieldalert.arguments[4] +'.');
		break;
	case (3) :
		alert('Not a valid email address.');
		break;
	case (4) :
		alert('Field must be ' + fieldalert.arguments[3] + ' digits long');
		break;
	case (5) :
		alert('Not a valid date.\nMust be in M/D/YYYY format.');
		break;
	case (6) :
		alert('Not a valid US zip code.\nMust be 5 or 9 digits long.');
		break;
	case (7) :
		alert('Field must be numbers only.');
		break;
	case (8) :
		alert('Field must be a valid minute.');
		break;
	default :
		alert('Field did not validate correctly.');
		break;
	}
	// Hidden fields cannot be focused
	if (formID[elementID].type != 'hidden')
		formID[elementID].focus();
}

// validateMinutes() function: checks that input is between 0 and 60
function validateMinutes(fieldvalue) {
	if (parseInt(fieldvalue) >= 0 && parseInt(fieldvalue) < 60) {
		return true;
	}
	else {
		return false;
	}
}


// stripChards2Num() function: Strips out all letters and chars
// stripChars(fieldvalue, decimal[,size])
// Decimal adds '.' to the digits variable; 0=false, 1=true
// Pass size if validating length of number field
// return value false is wrong size or not a number, else returns stripped number
function stripChars2Num(fieldvalue, decimal) {
	var returnString = "";
	
	if (decimal == 1) {
		var stripDigits = "1234567890.";
	}
	else if (decimal == 0){
		var stripDigits = "1234567890";
	}	
	for (var i = 0; i < fieldvalue.length; i++) {
		var c = fieldvalue.charAt(i);
		if (stripDigits.indexOf(c) != -1) returnString += c;
	}

	if (stripChars2Num.arguments.length == 3) {
		if (returnString.length != stripChars2Num.arguments[2])
			return false;
	}
	else if (returnString.length == 0)
		return false;

	return returnString;
}

// reformat() function: reformats number in appropriate fashion
// Example: to format a number for SSN, call reformat("123456789","ssn")
//  would return 123-45-6789
// Unrecognized format returns number
function reformat (number,format) {
	switch(format) {
	case ('ssn') :
		arrFormat = new Array("",3,"-",2,"-",4);
		break;
	case ('phone') :
		if (number.length == 10)
			arrFormat = new Array("(",3,") ",3,"-",4);
		else if (number.length == 7)
			arrFormat = new Array("",3,"-",4);
		break;
	case ('zip+4') :
		arrFormat = new Array("",5,"-",4);
		break;
	default :
		arrFormat = new Array("",number.length);
		break;
	}
	
	var arg
    var numPos = 0
    var returnString = ""

    for (var i = 0; i < arrFormat.length; i++) {
       arg = arrFormat[i];
       if (i % 2 == 0) returnString += arg
       else {
           returnString += number.substring(numPos, numPos + arg);
           numPos += arg;
       }
    }
    return returnString;
}

// isNumber() function: If the value passed in is a number returns true
function isNumber (string){
    for (var i = 0; i < string.length; i++) {   
        var c = string.charAt(i);
        if (digits.indexOf(c) == -1) return false;
    }
    return true;
}

// checkDate() function: "parent" function to validate date, checks if month, day, and year are all supplied
function checkDate (dateValue) {
	arrDate = dateValue.split('/')
	if (arrDate.length < 3 || arrDate.length > 3)
		return false;
	else
		return (isDate(arrDate[0], arrDate[1], arrDate[2]))
}

// isDate() function: validates that numbers passed in for month, day, year evaluates to a valid date
function isDate (month, day, year) {
//	if (parseInt(month) || parseInt(day) || parseInt(year))
    if (year.length != 4 || (year/year) != 1)
		return false;
	if (month < 1 || month > 12 || (month/month) != 1)
		return false;
	if (day < 1 || day > 31 || (day/day) != 1)
		return false;

    // catch invalid days, except for February
    if (day > daysInMonth[month]) return false; 

    if ((month == 2) && (day > daysInFebruary(year))) return false;

    return true;
}

// daysInFebruary() function: "helper" function calculates days in February, considering leap years
function daysInFebruary (year) {
    return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}

// checkEmail() function: evaluates string to valid email syntax
function checkEmail (argEmail)
{
	var tempEmail = argEmail.replace(/^\s*/, '').replace(/\s*$/, '');
	
	var regExpObj = /^[A-Za-z0-9_%\.-]+@([A-Za-z0-9_\-]+\.)+[A-Za-z]+(,[A-Za-z0-9_\%\.-]+@([A-Za-z0-9_-]+\.)+[A-Za-z]+)*$/
	if(regExpObj.exec(tempEmail) == null)
		return false;
	else
		return true;
}

// == Additional helper functions ==========================================

// TrimStr() function: removes leading and trailing spaces
function TrimStr(sToTrim) {
	var s = new String(sToTrim);
	while (s.substring(0,1) == " ") s=s.substring(1);
	while (s.length > 0 && s.substring(s.length-1,s.length) == " ") s=s.substring(0,s.length-1);
	return s;
}

// openNewWindow() function: opens new window
function openWindow(url, w, h) {
	var options = "width=" + w + ",height=" + h + ",";
	options += "resizable=no,scrollbars=yes,status=no,";
	options += "menubar=no,toolbar=no,location=no,directories=no,titlebar=no,";
	options += "screenX=200,screenY=200,top=200,left=200'";
	var newWin = window.open(url, 'newWin', options);
	newWin.focus();
}

