function fDisallowDefaultValue() { // v2.0.0 2006-09-12; like:; req:;
	if (!gbW3C) return gfW3C_Failed();

	bFormPassed = true;
	for (var i = 0; i < fDisallowDefaultValue.arguments.length; i=+2) {
		sFormField = fDisallowDefaultValue.arguments[i];
		bDisallowBlank = fDisallowDefaultValue.arguments[i+1];
	
		oFormField = document.getElementById(sFormField);
		if (!oFormField) return gfMissingObj(sFormField);

		if (oFormField.value == oFormField.defaultValue) {
			oFormField.className = 'inputFormFieldAlert'; /* could be improved, cuz will overwrite */
			bFormPassed = false;
		} else {
			if (oFormField.value == "" && bDisallowBlank) {
				oFormField.className = 'inputFormFieldAlert';
				bFormPassed = false;
			} else
				oFormField.className = 'inputFormField';
		}
	}
	return bFormPassed;
}
function fEnlargeTextarea(oTextarea, oEvent) { // v1.0.0 2006-08-01; like:; req:;
	var iKeyCode = oEvent.keyCode ? oEvent.keyCode : oEvent.which ? oEvent.which : oEvent.charCode;
	if (iKeyCode == 13) oTextarea.rows += 1; // enter key
}
function fFormFieldMinLen(oFormField, iMinLen) { // v1.0.0 2006-08-21; like:; req:;
	if (oFormField.value.length < iMinLen) {
		alert('Warning: Your ' + oFormField.name + ' is too short!  The minimum length is ' + iMinLen + ' characters.');
		return false;
	}
}
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 fFreshFormField(oFormField) { // v1.0.0 2004-10-04; like:; req:;
	if (oFormField.value == oFormField.defaultValue) oFormField.value = "";
}
function fNonBlankFormField(oFormField) { // v1.4.10 2005-09-22; like:fValidateForm(v2.4),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 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.30 2005-10-05; like:fValidateForm(v2.4),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; Jan 33 = Feb 2
}
function fValidEmail(oFormField) { // v1.2.0 2006-10-20; like:fValidateFormField(v1.3); req:;
	if (!(/^.+@.+\..{2,6}$/.test(oFormField.value))) return false; /* test format; top-level: ca to museum */
	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.30 2005-10-05; like:fValidateForm(v2.4); 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() { // v2.4.3 2006-09-25; like:; req:fValidateFormField(v1.3);
	if (!gbW3C) return gfW3C_Failed();

	oForm = fValidateForm.arguments[0];
	if (!oForm)
		alert('Note to Webmaster: fValidateForm is missing Form object as first parameter!');

	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: JS validation label 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 */

			if (oFormField) {
				var oClarifyLabel = document.getElementById(oFormField.id+"Clarify");
				if (fValidateFormField(oFormField)) {
					oFormField.className = 'inputFormFieldRequired';
					oLabel.className = 'txtFormLabelRequired';
					if (oClarifyLabel) oClarifyLabel.style.display = 'none';
				} else {
					bFormPassed = false;
					oFormField.className = 'inputFormFieldAlert';
					oLabel.className = 'txtFormLabelAlert';
					if (oClarifyLabel) oClarifyLabel.style.display = 'block';
				}
			} else
				alert('Note to Webmaster: ' + oLabel.htmlFor + ' missing ID attribute.');
		}
	}

	if (fValidateForm.arguments.length > 0) { /* check for additional validate functions */
		for (var i = 1; i < fValidateForm.arguments.length; i++) {
			bAdditionalValidationPassed = fValidateForm.arguments[1];
			bFormPassed = (bAdditionalValidationPassed == false) ? false : bFormPassed;
		}
	}

	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;
}