function fTextareaMaxLen(oFormField, iMaxLen) { // v1.0.0 2005-09-25; like:; req:;
	if (oFormField.value.length > iMaxLen + 1)
		alert('Warning: Your input has been truncated!  Please limit your entry to ' + iMaxLen + ' characters.');
	if (oFormField.value.length > iMaxLen)
		oFormField.value = oFormField.value.substring(0, iMaxLen);
}
function fNonBlankFormField(oFormField) { // CUSTOM v1.4.1 2005-09-22; like:fValidateForm(v2.2),fValidateFormField(v1.3); req:;
	if (oFormField.type) {
		if (/text|file|password|hidden/.test(oFormField.type)) { // text and file and password
			return (oFormField.value.replace(/ /g, "").length != 0); // trim spaces
		} else if (/select/.test(oFormField.type)) { // select dropdown menu; both multiple and single
			if (oFormField.selectedIndex == -1) return false;
			else if (oFormField.selectedIndex == 0 && oFormField.options[oFormField.selectedIndex].value == "") // if first item selected AND blank value (meaning default value often instruction label)
				return false;
			else if (oFormField.selectedIndex == 0 && oFormField.options[oFormField.selectedIndex].value == "-1") // if first item selected AND blank value (meaning default value often instruction label)
				return false;
			else return true;
		} else if (/radio|checkbox/.test(oFormField.type)) { // single radio/checkbox
			return (oFormField.checked);
		} else alert('Note to Webmaster: Form type action not defined.');
	} else if (oFormField.length && oFormField[0].type && /radio|checkbox/.test(oFormField[0].type)) // multiple radio/checkbox
		for (var i=0; i<oFormField.length; i++)
			if (oFormField[i].checked) return true;
	return false;
}
function fValidDate(sDateFormat, oFormField) { // v1.3.3 2005-10-05; like:fValidateForm(v2.2),fValidateFormField(v1.3); req:;
	if (!sDateFormat) { alert('Note to Webmaster: Date format MUST be default value (i.e. yyyy-mm-dd).'); return; }
	sDateFormat_delimiter = sDateFormat.replace(/y|m|d/g, "").charAt(0); // find delimiter
	if (oFormField.value.indexOf(sDateFormat_delimiter) == -1) return false; // delimiters are different
	aDate = oFormField.value.split(sDateFormat_delimiter);
	aDateFormat = sDateFormat.split(sDateFormat_delimiter);

	for (i=0; i<aDateFormat.length; i++) {
		if (isNaN(aDate[i])) // ensure numbers only; if character found then cancel
			return false;
		if (aDateFormat[i].length > aDate[i].length) { // code does NOT remove ZERO, yet
			aDate[i] = (aDate[i].length == 1)?"0"+aDate[i]:aDate[i]; // add zero if single digit
			if (aDateFormat[i].toLowerCase().indexOf('y') != -1) // year length must match
				return false;
		}
		if (aDateFormat[i].toLowerCase().indexOf('y') != -1)
			iYear = parseInt(aDate[i]);
		else if (aDateFormat[i].toLowerCase().indexOf('m') != -1)
			iMonth = parseInt(aDate[i])-1;
		else if (aDateFormat[i].toLowerCase().indexOf('d') != -1)
			iDay = parseInt(aDate[i]);
	}
	var oTestDate=new Date(iYear, iMonth, iDay);
	return (iYear==oTestDate.getFullYear() && iMonth==oTestDate.getMonth() && iDay==oTestDate.getDate()) // prevent month wrap; Sept 32 = Oct 2
}
function fValidEmail(oFormField) { // v1.1.1 2004-10-04; like:fValidateFormField(v1.3); req:;
	if (!(/^.+@.+\..{2,3}$/.test(oFormField.value))) return false; // test format
	else if (oFormField.value.match(/[\(\)\<\>\,\;\:\\\"\[\]]/)) return false; //test for illegal characters
	return true;
}
function fValidPhone(oFormField) { // v2.0.0 2005-09-01; like:fValidateFormField(v1.3); req: fFormatValue(v1.0);
	var sPhoneNumbers = oFormField.value.replace(/[\(\)\.\-\ ]/g, ""); // strip out acceptable non-numeric characters
	if (isNaN(sPhoneNumbers) || (sPhoneNumbers.length != 10)) // contains no letters and check for 10 digits
		return false;
	else {
		oFormField.value = fFormatValue(sPhoneNumbers,"(",3,") ",3,"-",4)
		return true;
	}
}
function fValidateFormField(oFormField) { // v1.3.3 2005-10-05; like:fValidateForm(v2.2); req:fNonBlankFormField(v1.4),fValidDate(v1.2), fValidEmail(v1.1), fValidPhone(v1.0);
	if (!fNonBlankFormField(oFormField)) return false;
	if (oFormField.name) // radio,checkbox nameless
		if (oFormField.name.toLowerCase().indexOf('date') != -1) // check for vailid Date
			return fValidDate(oFormField.defaultValue,oFormField) // date format MUST be hardcoded as value
		else if (oFormField.name.toLowerCase().indexOf('email') != -1) // check for vailid E-Mail
			return fValidEmail(oFormField)
		else if (oFormField.name.toLowerCase().indexOf('phone') != -1) // check for vailid Telephone
			return fValidPhone(oFormField)
	return true;
}
function fValidateForm(oForm) { // v2.2.2 2005-10-13; like:; req:fValidateFormField(v1.3);
	if (!document.getElementById || !document.getElementsByTagName) return true; // old browsers rely on server-side validation
	var bFormPassed = true, oLabel, tLabels = document.getElementsByTagName('label');
	for (var i=0; (oLabel = tLabels[i]); i++) {
		if (oLabel.className == 'txtFormLabelRequired' || oLabel.className == 'txtFormLabelAlert') {
			if (!oLabel.htmlFor) alert('Note to Webmaster: For JS validation all labels MUST have "for" attribute.');
			if (document.getElementById(oLabel.htmlFor))
				var oFormField = oForm[document.getElementById(oLabel.htmlFor).name]; // take ID from label and learn name associated with form element
			else alert('Note to Webmaster: "' + oLabel.htmlFor + '" form field is missing ID attribute.');
			
			if (oFormField) {
				var oClarifyLabel = document.getElementById(oFormField.id+"Clarify");
				if (fValidateFormField(oFormField)) { // passed validation
					oLabel.className = 'txtFormLabelRequired';
					oFormField.className = 'inputFormFieldRequired';
					if (oClarifyLabel) oClarifyLabel.style.display = 'none';
				} else { // failed validation
					bFormPassed = false;
					oLabel.className = 'txtFormLabelAlert';
					oFormField.className = 'inputFormFieldAlert';
					if (oClarifyLabel) oClarifyLabel.style.display = 'block';
				}
			}
		}
	}
	if (!bFormPassed) alert("Required fields are highlighted");
	return bFormPassed;
}
function fFormatValue(sRawString) { // v1.0.0 2005-09-01; like: fValidPhone(v2.0); req:;
	var arg, sPos = 0, sReturn = "";
	for (var i = 1; i < fFormatValue.arguments.length; i++) {
		arg = fFormatValue.arguments[i];
		if (i % 2 == 1) sReturn += arg;
		else {
			sReturn += sRawString.substring(sPos, sPos + arg);
			sPos += arg;
		}
	}
	return sReturn;
}