var reWhitespace = /^\s+$/;
var reLetter = /^[a-zA-Z]$/;
var reAlphabetic = /^[a-zA-Z]+$/;
var reAlphanumeric = /^[a-zA-Z0-9]+$/;
var reDigit = /^\d/;
var reLetterOrDigit = /^([a-zA-Z]|\d)$/;
var reInteger = /^\d+$/;
var reSignedInteger = /^(\+|\-)?\d+$/;
var reFloat = /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/;
var reSignedFloat = /^(((\+|\-)?\d+(\.\d*)?)|((\+|\-)?(\d*\.)?\d+))$/;
var reEmail = /^.+\@.+\..+$/;
var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz";
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var whitespace = " \t\n\r";
var phoneNumberDelimiters = "()- ";
var validUSPhoneChars = digits + phoneNumberDelimiters;
var validWorldPhoneChars = digits + phoneNumberDelimiters + "+";
var SSNDelimiters = ".- ";
var validSSNChars = digits + SSNDelimiters;
var digitsInSocialSecurityNumber = 9;
var digitsInUSPhoneNumber = 10;
var ZIPCodeDelimiters = "-";
var ZIPCodeDelimeter = "-"
var validZIPCodeChars = digits + ZIPCodeDelimiters;
var digitsInZIPCode1 = 5;
var digitsInZIPCode2 = 9;
var creditCardDelimiters = ".- ";

var defaultEmptyOK = false;

var daysInMonth = new Array(12);
daysInMonth[1] = 31;
daysInMonth[2] = 29;
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;

var theDate = new Date();
var thisMonth = theDate.getMonth();
var thisYear = theDate.getFullYear();

var months = "January,February,March,April,May,June,July,August,September,October,November,December";

var codeDelimiter = ",";

var defaultPrefix = " ";
var prefixes = " ,Mr,Mrs,Ms,Miss,Sir,Dr,Rev,Lord,Lady";

var defaultSuffix = " ";
var suffixes = " ,Jr,Sr";

var iErrorCount = 0;
var aError;
aError = new Array();

var eFirstName = "Please enter a first name.";
var eLastName = "Please enter a last name.";
var eAddress = "Please enter an address.";
var eCity = "Please enter a city.";
var eEMail = "Please enter a valid email address.";
var eBirthday = "Please enter a valid birth date.";

function isEmpty(s) {
	return ((s == null) || (s.length == 0));
}

function isWhitespace(s) {
	return (isEmpty(s) || reWhitespace.test(s));
}

function stripCharsInRE(s, bag) {
	return s.replace(bag, "");
}

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;
}

function stripCharsNotInBag(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;
}

function stripWhitespace(s) {
    return stripCharsInBag (s, whitespace);
}

function stripInitialWhitespace(s) {
	var i = 0;

	while ((i < s.length) && indexOf(s.charAt(i), whitespace))
		i++;
    
	return s.substring (i, s.length);
}

function isLetter(c) {
	return reLetter.test(c);
}

function isDigit(c) {
	return reDigit.test(c);
}

function isLetterOrDigit(c) {
	return reLetterOrDigit.test(c);
}

function isInteger(s) {
	var i;

	if (isEmpty(s))
		if (isInteger.arguments.length == 1) return defaultEmptyOK;
		else return (isInteger.arguments[1] == true);

	return reInteger.test(s);
}

function isSignedInteger(s) {
	if (isEmpty(s))
		if (isSignedInteger.arguments.length == 1) return defaultEmptyOK;
		else return (isSignedInteger.arguments[1] == true);

	else {
		return reSignedInteger.test(s);
	}
}

function isPositiveInteger(s) {
	var secondArg = defaultEmptyOK;

	if (isPositiveInteger.arguments.length > 1)
		secondArg = isPositiveInteger.arguments[1];

	return (isSignedInteger(s, secondArg)
		&& ( (isEmpty(s) && secondArg)  || (parseInt (s) > 0) ) );
}

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) ) );
}

function isNegativeInteger(s) {
	var secondArg = defaultEmptyOK;

	if (isNegativeInteger.arguments.length > 1)
		secondArg = isNegativeInteger.arguments[1];

	return (isSignedInteger(s, secondArg)
		&& ( (isEmpty(s) && secondArg)  || (parseInt (s) < 0) ) );
}

function isNonpositiveInteger(s) {
	var secondArg = defaultEmptyOK;

	if (isNonpositiveInteger.arguments.length > 1)
		secondArg = isNonpositiveInteger.arguments[1];

	return (isSignedInteger(s, secondArg)
		&& ( (isEmpty(s) && secondArg)  || (parseInt (s) <= 0) ) );
}

function isFloat(s) {
	if (isEmpty(s)) 
		if (isFloat.arguments.length == 1) return defaultEmptyOK;
		else return (isFloat.arguments[1] == true);

	return reFloat.test(s)
}

function isSignedFloat(s) {
	if (isEmpty(s)) 
		if (isSignedFloat.arguments.length == 1) return defaultEmptyOK;
		else return (isSignedFloat.arguments[1] == true);
	else {
		return reSignedFloat.test(s)
	}
}

function isAlphabetic(s) {
	var i;

	if (isEmpty(s))
		if (isAlphabetic.arguments.length == 1) return defaultEmptyOK;
		else return (isAlphabetic.arguments[1] == true);
	else {
		return reAlphabetic.test(s);
	}
}

function isAlphanumeric(s) {
	var i;

	if (isEmpty(s))
		if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK;
		else return (isAlphanumeric.arguments[1] == true);
	else {
		return reAlphanumeric.test(s)
	}
}

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;
}


function isEmail(s) {
	if (isEmpty(s)) 
	if (isEmail.arguments.length == 1) return defaultEmptyOK;
	else return (isEmail.arguments[1] == true);

	else {
		return reEmail.test(s)
	}
}

function isYear(s) {
	if (isEmpty(s)) 
	if (isYear.arguments.length == 1) return defaultEmptyOK;
	else return (isYear.arguments[1] == true);
	if (!isNonnegativeInteger(s)) return false;
	return ((s.length == 2) || (s.length == 4));
}

function isIntegerInRange(s, a, b) {
	if (isEmpty(s)) 
	if (isIntegerInRange.arguments.length == 1) return defaultEmptyOK;
	else return (isIntegerInRange.arguments[1] == true);

	if (!isInteger(s, false)) return false;

	var num = parseInt (s);
	return ((num >= a) && (num <= b));
}

function isMonth(s) {
        alert("In ismonth");
	if (isEmpty(s)) 
	if (isMonth.arguments.length == 1) return defaultEmptyOK;
	else return (isMonth.arguments[1] == true);
        alert(s);
	return isIntegerInRange (s, 1, 12);
}

function isDay(s) {
	if (isEmpty(s)) 
	if (isDay.arguments.length == 1) return defaultEmptyOK;
	else return (isDay.arguments[1] == true);   
	return isIntegerInRange (s, 1, 31);
}

function daysInFebruary(year) {
	return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}

function isDate(year, month, day) {

	if (day > daysInMonth[month]) return false; 

	if ((month == 2) && (day > daysInFebruary(year))) return false;

	return true;
}

// Functions to call in validation script begin here


function checkString(theField, error, emptyOK) {
	if (! emptyOK) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (isWhitespace(theField.value)) {
		addError(error);
		return false;
	} else {
		return true;
	}
}

function checkCheckboxChecked(theField, error, emptyOK) {
	if (checkCheckboxChecked.arguments.length == 2) emptyOK = defaultEmptyOK;
	if (! emptyOK) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (theField.checked!=true) {
		addError(error);
		return false;
	} else {
		return true;
	}
}

function checkStringLength(theField, minLength, maxLength, error, emptyOK) {
        var iMin = parseInt(minLength);
        var iMax = parseInt(maxLength);
	if (checkStringLength.arguments.length == 4) emptyOK = defaultEmptyOK;
        emptyOK = true;
	if (! emptyOK) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (isWhitespace(theField.value)) {
		addError(error);
		return false;
        }
        if (theField.value.length < iMin) {
		addError(error);
		return false;
        }
        if (theField.value.length > iMax) {
		addError(error);
		return false;
        }
              
	return true;
}

function checkIntegerRange(theField, lowVal, highVal, error, emptyOK) {
	if (checkIntegerRange.arguments.length == 4) emptyOK = defaultEmptyOK;
	if (! emptyOK) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	else if (!isIntegerInRange(theField.value, lowVal, highVal)) {
		addError(error);
		return false;
	} else {
		return true;
	}
}

function checkEmail(theField, error, emptyOK) {
	if (! error) error = eEMail;
	if (! emptyOK) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	else if (!isEmail(theField.value, false)) {
		addError(error);
		return false;
	} else {
		return true;
	}
}


function checkYear(theField, emptyOK) {
	if (checkYear.arguments.length == 1) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isYear(theField.value, false)) 
		return false;
	else return true;
}

function checkMonth(theField, emptyOK) {
	if (checkMonth.arguments.length == 1) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isMonth(theField.value, false)) 
		return false;
	else return true;
}

function checkDay(theField, emptyOK) {
	if (checkDay.arguments.length == 1) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isDay(theField.value, false)) 
		return false;
	else return true;
}

function checkDate(yearField, monthField, dayField, error, OKtoOmitDay) { 
	if (checkDate.arguments.length == 4) OKtoOmitDay = false;
	if (!isYear(yearField.value)) addError(error); return false;
	if (!isMonth(monthField.value)) addError(error); return false;
	if ( (OKtoOmitDay == true) && isEmpty(dayField.value) ) return true;
	else if (!isDay(dayField.value)) {
		addError(error);
		return false;
	}
	if (isDate (yearField.value, monthField.value, dayField.value))
		return true;

	addError(error);
	return false
}

function checkUKDate(dateField, error, emptyOK) { 
        var ddmmyyyy = dateField.value;

        var wyear = ddmmyyyy.substr(6,4);
        var wmonth = ddmmyyyy.substr(3,2);
        var wday = ddmmyyyy.substr(0,2);

	if (checkUKDate.arguments.length == 2) emptyOK = defaultEmptyOK;
	if ((emptyOK == true) && (isEmpty(dateField.value))) return true;
	if ((emptyOK == true) && (dateField.value == "00/00/0000")) return true;

	if (dateField.value.length != 10) {
           addError(error); 
           return false;
        }

        var iday = parseInt(wday, 10);
        var imonth = parseInt(wmonth, 10);
        var iyear = parseInt(wyear, 10);

        if (iday < 1 || iday > 31) {
           addError(error);
           return false;
        }
        if (imonth < 1 || imonth > 12) {
           addError(error);
           return false;
        }
        if (iyear < 1) {
           addError(error);
           return false;
        }

	if (isDate (iyear, imonth, iday)) return true;

        addError(error);
	return false
}

function writeMonths(group) {
	var selected = (writeMonths.arguments.length == 2) ? writeMonths.arguments[1] : thisMonth;
	
	document.write('<select name=months_'+ group +' onChange=\"updateDays(\''+ group +'\', this.form)\">');
	
	aMonths = months.split(codeDelimiter);
	for ( var x = 0; x < aMonths.length; x++ ) {
		if (x == selected) {
			document.write('<option value=\"'+ x + '\" selected>'+ aMonths[x]);
		} else {
			document.write('<option value=\"'+ x + '\">'+ aMonths[x]);
		}
	}
	
	document.write('</select>');
}

function writeDays(group) {
	var OKtoOmitDay = (writeDays.arguments.length == 2) ? true : false;
	var selected = (writeDays.arguments.length == 3) ? writeDays.arguments[2] : theDate.getDate();

	document.write('<select name=\"days_'+ group +'\">');
	if (OKtoOmitDay) {
		document.write('<option value=\"\">none');
	}

	for ( var x = 1; x < (daysInMonth[thisMonth] + 1); x++ ) {
		if (x == selected) {
			document.write('<option value=\"'+ x + '\" selected>'+ x);
		} else {
			document.write('<option value=\"'+ x + '\">'+ x);
		}
	}
	
	document.write('</select>');
}

function writeYears(group, start, end) {
	var selected = (writeYears.arguments.length == 4) ? writeYears.arguments[3] : theDate.getFullYear();

	document.write('<select name=\"years_'+ group +'\" onChange=\"updateDays(\''+ group +'\', this.form)\">');
	
	for (x = start; x <= end; x++) {
		if (x == selected) {
			document.write('<option value=\"'+ x + '\" selected>'+ x);
		} else {
			document.write('<option value=\"'+ x + '\">'+ x);
		}
	}
	
	document.write('</select>');
}

function updateDays(group, form) {
	var curYearField = eval(form.elements['years_' + group]);
	var curYear = curYearField.options[curYearField.selectedIndex].value;

	var curField = eval(form.elements['months_' + group]);
	var curMonth = (parseInt(curField.options[curField.selectedIndex].value) + 1);
	var totDays = (curMonth == 2) ? daysInFebruary(curYear): daysInMonth[curMonth];
	
	var curDayField = eval(form.elements['days_' + group]);
	var curSelectedDay = curDayField.options[curDayField.selectedIndex].value;
	
	var days = new Array();
	
	for (x = 0; x < (totDays + 1); x++) {
		days[x] = x;
	}
	
	curDayField.length = 0;
	for (x = 1; x < days.length; x++) {
		curDayField.options[x - 1] = new Option(days[x], days[x]);
	}
	
	var selected = (curSelectedDay <= days.length) ? (curSelectedDay - 1) : (days.length - 2);
	selected = (selected > 0 ) ? selected : 0;
	curDayField.selectedIndex = selected;
}

function writeSalutations() {
	var selected = (writeSalutations.arguments.length == 1) ? writeSalutations.arguments[0] : defaultPrefix;
	var aPrefixes = prefixes.split(codeDelimiter);
	
	document.write('<select name=\"salutation\">');
	
	for (x = 0; x <= aPrefixes.length - 1; x++) {
		if (x == selected) {
			document.write('<option value=\"'+ aPrefixes[x] + '\" selected>'+ aPrefixes[x]);
		} else {
			document.write('<option value=\"'+ aPrefixes[x] + '\">'+ aPrefixes[x]);
		}
	}
	
	document.write('</select>');
}

function writeSuffixes() {
	var selected = (writeSuffixes.arguments.length == 1) ? writeSuffixes.arguments[0] : defaultSuffix;
	var aSuffixes = suffixes.split(codeDelimiter);
	
	document.write('<select name=\"suffix\">');
	
	for (x = 0; x <= aSuffixes.length - 1; x++) {
		if (x == selected) {
			document.write('<option value=\"'+ aSuffixes[x] + '\" selected>'+ aSuffixes[x]);
		} else {
			document.write('<option value=\"'+ aSuffixes[x] + '\">'+ aSuffixes[x]);
		}
	}
	
	document.write('</select>');
}

function addError(s) {
	aError[iErrorCount] = s;
	iErrorCount++;
}

function returnError(newLine) {
	if (! newLine)
		newLine = '\n'; //can also be '<br>' or anything else you might need
	
	var sError = '';
	for (x=0; x < aError.length; x++) {
		sError += aError[x] + newLine;
	}
	
	aError = null;
	aError = new Array;
	iErrorCount = 0;
	
	return sError;
}

function hasErrors() {
	return (aError.length == 0) ? false : true;
}

function errorWindow(error, width, height, startHTML, endHTML) {
	if (! error) error = returnError();
	if (! width) width = 300;
	if (! height) height = 300;
	
	var posY = ( screen.availHeight - height ) / 2;
	var posX = ( screen.availWidth - width ) / 2;
	var features = 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,width='+ width +',height='+ height + ',top=' + posY + ',left=' + posX;
	var newWindow = window.open ("", "newWindow", features);
	
	if (startHTML) newWindow.document.write(startHTML);
	newWindow.document.write(error);
	if (endHTML) newWindow.document.write(endHTML);
}


function errorAlert(error) {
	if (! error) error = returnError();
	
	alert('The following require your attention:\n\n' + error + '\nOnce you have corrected the above, please resubmit the form.');
}