function validatePersonalInfo(form)
{
	return (
		checkString(form.elements["FirstName"],sFirstName) &&
		checkString(form.elements["LastName"],sLastName) &&
		checkString(form.elements["Title"],sTitle) &&
		checkString(form.elements["Institution"],sInstitution) &&
		checkString(form.elements["StreetAddress"],sStreetAddress, true) &&
		checkString(form.elements["City"],sCity, true) &&
		checkStateCode(form.elements["StateCode"], true) &&
		checkZIPCode(form.elements["ZIP"], true) &&
		checkPhone(form.elements["Phone"]) &&
		checkPhone(form.elements["Fax"], true) &&
		checkEmail(form.elements["Email"])
	)
}


// CONSTANT STRING DECLARATIONS
// s is an abbreviation for "string"
var sFirstName = "First Name";
var sLastName = "Last Name";
var sTitle = "Title";
var sInstitution = "Institution/Organization";
var sStreetAddress = "Street Address";
var sCity = "City";
var sStateCode = "State";
var sZIPCode = "ZIP Code";
var sPhone = "Phone Number";
var sExtension = "Phone Extension";
var sFax = "Fax Number";
var sEmail = "Email";

// i is an abbreviation for "invalid"
var iStateCode = "This field must be a valid two character U.S. state abbreviation (like CA for California). Please reenter it.";
var iZIPCode = "This field must be a 5 or 9 digit U.S. ZIP Code (like 12345 or 12345-1234).\nPlease reenter it.";
var iPhone = "This field must be a 10 digit U.S. phone number (like 415 555 1212). Please reenter it.";
var iEmail = "This field must be a valid email address (like foo@bar.com). Please reenter it.";
var iWholeNumber = "This field must contain digits only.  Please reenter the number.";
var iChoice = "Select only your top 3 choices (order by 1, 2, 3).";

// p is an abbreviation for "prompt"
var pEntryPrompt = "Please enter a ";
var pStateCode = "2 character code (like CA).";
var pZIPCode = "5 or 9 digit ZIP Code (like 12345 or 12345-1234).";
var pPhone = "10 digit phone number (like 415 555 1212).";
var pEmail = "valid email address (like mail@myplace.com).";
var pRadioButton = "1 selection.";

// VARIABLE DECLARATIONS
// m is an abbreviation for "missing"
var mPrefix = "You did not enter a value into the "
var mSuffix = " field. This is a required field. Please enter it."

var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

// whitespace characters
var whitespace = " \t\n\r";

// decimal point character differs by language and culture
var decimalPointDelimiter = "."

// non-digit characters which are allowed in phone numbers
var phoneNumberDelimiters = "()- ";

// characters which are allowed in phone numbers
var validPhoneChars = digits + phoneNumberDelimiters;

// U.S. phone numbers have 10 digits.
// They are formatted as 123 456 7890 or (123) 456-7890.
var digitsInPhoneNumber = 10;

// non-digit characters which are allowed in ZIP Codes
var ZIPCodeDelimiters = "-";

// our preferred delimiter for reformatting ZIP Codes
var ZIPCodeDelimeter = "-"

// U.S. ZIP codes have 5 or 9 digits.
// They are formatted as 12345 or 12345-6789.
var digitsInZIPCode1 = 5
var digitsInZIPCode2 = 9

// Global variable defaultEmptyOK defines default return value 
var defaultEmptyOK = false

// Valid U.S. Postal Codes for states, territories, armed forces, etc.

var StateCodeDelimiter = "|";
var StateCodes = "AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY|AE|AA|AE|AE|AP"

// Check whether string s is empty.
function isEmpty(s)
{
	return ((s == null) || (s.length == 0))
}

// Returns true if string s is empty or whitespace characters only.
function isWhitespace (s)
{
	var i;
	if (isEmpty(s)) { return true; }
	for (i = 0; i < s.length; i++)
	{   
		var c = s.charAt(i);
		if (whitespace.indexOf(c) == -1) { return false; }
	}
	return true;
}

// Removes all characters which appear in string bag from string s.
function stripCharsInBag (s, bag)
{
	var i;
	var returnString = "";
	for (i = 0; i < s.length; i++)
	{   
		var c = s.charAt(i);
		if (bag.indexOf(c) == -1) { returnString += c; }
	}
	return returnString;
}

// Returns true if single character c is contained within string s.
function charInString (c, s)
{
	for (i = 0; i < s.length; i++)
	{
		if (s.charAt(i) == c) { return true; }
	}
	return false
}

// Returns true if character c is a digit (0 .. 9).
function isDigit (c)
{
	return ((c >= "0") && (c <= "9"))
}

// isInteger (STRING s [, BOOLEAN emptyOK])
function isInteger (s)
{
	var i;
	if (isEmpty(s)) 
	{
		if (isInteger.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isInteger.arguments[1] == true); }
	}
	for (i = 0; i < s.length; i++)
	{   
		var c = s.charAt(i);
		if (!isDigit(c)) { return false; }
	}
	return true;
}

// isSignedInteger (STRING s [, BOOLEAN emptyOK])
function isSignedInteger (s)
{
	if (isEmpty(s)) 
	{
		if (isSignedInteger.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isSignedInteger.arguments[1] == true); }
	}
	else
	{
		var startPos = 0;
		var secondArg = defaultEmptyOK;
		if (isSignedInteger.arguments.length > 1) { secondArg = isSignedInteger.arguments[1]; }
		if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") ) { startPos = 1; }
		return (isInteger(s.substring(startPos, s.length), secondArg))
	}
}

// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK])
function isNonnegativeInteger (s)
{   var secondArg = defaultEmptyOK;
    if (isNonnegativeInteger.arguments.length > 1) { secondArg = isNonnegativeInteger.arguments[1]; }
    return (isSignedInteger(s, secondArg) && ((isEmpty(s) && secondArg)  || (parseInt (s) >= 0)));
}

// isWholeNumber (STRING s [, BOOLEAN emptyOK])
function isWholeNumber (s)
{
	if (isEmpty(s))
	{
		if (isWholeNumber.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isWholeNumber.arguments[1] == true); }
	}
	if (!isNonnegativeInteger(s)) { return false; }
	return true;
}

// reformat (TARGETSTRING, STRING, INTEGER, STRING, INTEGER ... )       
function reformat (s)
{
	var arg;
	var sPos = 0;
	var resultString = "";
	for (var i = 1; i < reformat.arguments.length; i++)
	{
		arg = reformat.arguments[i];
		if (i % 2 == 1) { resultString += arg; }
		else
		{
			resultString += s.substring(sPos, sPos + arg);
			sPos += arg;
		}
	}
	return resultString;
}

// isPhoneNumber (STRING s [, BOOLEAN emptyOK])
function isPhoneNumber (s)
{
	if (isEmpty(s))
	{
		if (isPhoneNumber.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isPhoneNumber.arguments[1] == true); }
	}
	return (isInteger(s) && s.length == digitsInPhoneNumber)
}

// isZIPCode (STRING s [, BOOLEAN emptyOK])
function isZIPCode (s)
{
	if (isEmpty(s))
	{
		if (isZIPCode.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isZIPCode.arguments[1] == true); }
	}
	return (isInteger(s) && ((s.length == digitsInZIPCode1) || (s.length == digitsInZIPCode2)))
}

// isStateCode (STRING s [, BOOLEAN emptyOK])
function isStateCode(s)
{
	if (isEmpty(s))
	{
		if (isStateCode.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isStateCode.arguments[1] == true); }
	}
	return ((StateCodes.indexOf(s) != -1) && (s.indexOf(StateCodeDelimiter) == -1))
}

// isEmail (STRING s [, BOOLEAN emptyOK])
function isEmail (s)
{
	if (isEmpty(s))
	{
		if (isEmail.arguments.length == 1) { return defaultEmptyOK; }
		else { return (isEmail.arguments[1] == true); }
	}
	if (isWhitespace(s)) { return false; }
	var i = 1;
	var sLength = s.length;
	while ((i < sLength) && (s.charAt(i) != "@")) { i++; }
	if ((i >= sLength) || (s.charAt(i) != "@")) { return false; }
	else { i += 2; }
	while ((i < sLength) && (s.charAt(i) != ".")) { i++; }
	if ((i >= sLength - 1) || (s.charAt(i) != ".")) { return false; }
	else { return true; }
}

/* FUNCTIONS TO NOTIFY USER OF INPUT REQUIREMENTS OR MISTAKES. */
// Display data entry prompt string s in status bar.
function promptEntry (s)
{
	window.status = pEntryPrompt + s
}

// Notify user that required field theField is empty.
function warnEmpty (theField, s)
{
	theField.focus();
	alert(mPrefix + s + mSuffix);
	return false;
}

// Notify user that contents of field theField are invalid.
function warnInvalid (theField, s)
{
	theField.focus();
	theField.select();
	alert(s);
	return false;
}

/* FUNCTIONS TO INTERACTIVELY CHECK VARIOUS FIELDS. */
// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
function checkString (theField, s, emptyOK)
{
	if (checkString.arguments.length == 2) { emptyOK = defaultEmptyOK; }
	if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	if (isWhitespace(theField.value)) { return warnEmpty (theField, s); }
	else { return true; }
}

// checkWholeNumber (TEXTFIELD theField [, BOOLEAN emptyOK==false])
function checkWholeNumber (theField, emptyOK)
{
	if (checkWholeNumber.arguments.length == 1) { emptyOK = defaultEmptyOK; }
	if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	if (!isWholeNumber(theField.value, false)) // { return false } 
	{ return warnInvalid (theField, iWholeNumber); }
	else return true;
}

// checkStateCode (TEXTFIELD theField [, BOOLEAN emptyOK==false])
function checkStateCode(theField, emptyOK)
{
	var codestring = "";
	if(checkStateCode.arguments.length == 1) { emptyOK = defaultEmptyOK; }
	codestring = theField.value;
	if(codestring.length == 1) { return warnInvalid(theField, iStateCode); }
	if((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	else
	{
		theField.value = theField.value.toUpperCase();
		if(!isStateCode(theField.value, false)) { return warnInvalid(theField, iStateCode); }
		else { return true; }
	}
}

// Takes ZIPString, a string of 5 or 9 digits, if 9 digits, inserts separator hyphen
function reformatZIPCode (ZIPString)
{
	if (ZIPString.length == 5) { return ZIPString; }
	else { return (reformat (ZIPString, "", 5, "-", 4)); }
}

// checkZIPCode (TEXTFIELD theField [, BOOLEAN emptyOK==false])
function checkZIPCode (theField, emptyOK)
{
	if (checkZIPCode.arguments.length == 1) { emptyOK = defaultEmptyOK; }
	if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	else
	{
		var normalizedZIP = stripCharsInBag(theField.value, ZIPCodeDelimiters)
		if (!isZIPCode(normalizedZIP, false)) { return warnInvalid (theField, iZIPCode); }
		else 
		{
			theField.value = reformatZIPCode(normalizedZIP)
			return true;
		}
	}
}

// takes Phone, a string of 10 digits and reformats as (123) 456-789
function reformatPhone (Phone)
{
	return (reformat (Phone, "(", 3, ") ", 3, "-", 4))
}

// checkPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false])
function checkPhone (theField, emptyOK)
{
	if (checkPhone.arguments.length == 1) { emptyOK = defaultEmptyOK; }
	if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	else
	{
		var normalizedPhone = stripCharsInBag(theField.value, phoneNumberDelimiters)
		if (!isPhoneNumber(normalizedPhone, false)) { return warnInvalid (theField, iPhone); }
		else 
		{
			theField.value = reformatPhone(normalizedPhone)
			return true;
		}
	}
}

// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false])
function checkEmail (theField, emptyOK)
{
	if (checkEmail.arguments.length == 1) { emptyOK = defaultEmptyOK; }
	if ((emptyOK == true) && (isEmpty(theField.value))) { return true; }
	else if (!isEmail(theField.value, false)) { return warnInvalid (theField, iEmail); }
	else { return true; }
}


// Popup Window 
var popWindow = null;
var popURL = "";
var specs = "";
function displayPop(url,w,h) {
	popURL = url + ".html";
	xpos = (screen.availWidth - w) / 2;
	ypos = (screen.availHeight - h) / 2;
// screenX and screenY position the window in Netscape
// left and top position the window in Internet Explorer
	specs = "scrollbars=yes,height=" + h + ",width=" + w + ",screenX=" + xpos + ",left=" + xpos + ",screenY=" + ypos + ",top=" + ypos;
	openWindow = window.open(popURL,"popWindow",specs);
	if (openWindow != null) {
		openWindow.document.close();          // close layout stream
	}
}


// Auto Tab
var isNN = (navigator.appName.indexOf("Netscape")!=-1);
function autoTab(input,len, e)
{
	var keyCode = (isNN) ? e.which : e.keyCode; 
	var filter = (isNN) ? [0,8,9] : [0,8,9,16,17,18,37,38,39,40,46];
	if(input.value.length >= len && !containsElement(filter,keyCode))
	{
		input.value = input.value.slice(0, len);
		input.form[(getIndex(input)+1) % input.form.length].focus();
	}

	function containsElement(arr, ele)
	{
		var found = false, index = 0;
		while(!found && index < arr.length)
		{
			if(arr[index] == ele) { found = true; }
			else { index++; }
		}
		return found;
	}

	function getIndex(input)
	{
		var index = -1, i = 0, found = false;
		while (i < input.form.length && index == -1)
		{
			if (input.form[i] == input) { index = i; }
			else { i++; }
		}
		return index;
	}
	return true;
}


// Check Numbered Choices (At least one must contain a number)
function checkChoices(theField)
{
	var checkValue = "";
	var fieldValue = "";
	var flag1 = 0;
	var flag2 = 0;
	var flag3 = 0;
	var flag4 = 0;
	
// Check for a values of 1, 2 or 3 in the input boxes.
	for(var i = 12; i < 27; i++)
	{
		fieldValue = document.VolunteerOpp.elements[i].value;
		if(fieldValue != "")
		{
			checkValue = parseInt(fieldValue);
			if(checkValue == 1) { flag1++; }
			else if(checkValue == 2) { flag2++; }
			else if(checkValue == 3) { flag3++; }
			else if (checkValue > 3) { flag4++; }
			else { document.VolunteerOpp.elements[i].value = ""; }
		}
	}

// Return true or false
	if((flag1 == 1) && (flag2 == 0 || flag2 == 1) && (flag3 == 0 || flag3 == 1) && (flag4 == 0))
	{
		return true;
	}
	else { return warnInvalid (theField, iChoice); }
}
