function clearForm(formName) {
	var node = document.getElementById(formName);
	node.reset();
	var allDisp = node.getElementsByTagName('span');
	for(var i = 0; i < allDisp.length; i++) {
		if(allDisp[i].className == 'val') {
			var s1 = allDisp[i].id;
			var s2 = s1.substr(0, s1.length - 3);
			if(document.getElementById(s2) != null) showValidated(s2, ''); //document.getElementById(s2).value);
		}
	}
}

function validateForm(i) {
	var inv = true;
	var node = document.getElementById(i);
	var allInputs = node.getElementsByTagName('input');
	for(var i = 0; i < allInputs.length; i++) {
		inv &= validate(allInputs[i], '');
	}
	return inv;
}

function validate(node, display) {
	var b = true;
	switch(node.className) {
		// Form Structures
		case 'hidden':      case 'button':   b = true;                       break;
		
		// Bypass
		case 'noval':       case 'reqnoval': b = valAuto    (node, display); break;
		
		// Text and text-like fields
		case 'reqtext':     case 'text':     b = valText    (node, display); break;
		case 'reqnumber':   case 'number':   b = valNumber  (node, display); break;
		case 'reqpassword': case 'password': b = valPassword(node, display); break;
		case 'reqradio':    case 'radio':    b = valRadio   (node, display); break;
		case 'reqcheckbox': case 'checkbox': b = valCheckBox(node, display); break;
		case 'reqselect':   case 'select':   b = valSelect  (node, display); break;
		case 'reqemail':    case 'email':    b = valEMail   (node, display); break;
		case 'reqyear':     case 'year':     b = valYear    (node, display); break;
		case 'reqzipcode':  case 'zipcode':  b = valZipCode (node, display); break;
		case 'reqphone':    case 'phone':    b = valPhone   (node, display); break;
		case 'reqanumber':  case 'anumber':  b = valANumber (node, display); break;
		case 'reqgpa':      case 'gpa':      b = valGPA     (node, display); break;
		
		// Numerical fields
		
		// Option Groups
		
		// We don't know what we've got!
		default:
			if(node.className == null) b = true;
			else {
				alert('Unknown Data Type: ' + node.className);
				b = false;
			}
			break;
	}
	return b;
}

function onChangeValidate(i) {
	var node = document.getElementById(i);
	if(node == null) node = document.getElementById(i + '1');
	if(window.customOnChangeValidate) {
		return customOnChangeValidate(node, i);
	} else {
		return validate(node, i);
	}
}

function showValidated(i, val) {
	if(i == null || i == false || i == '') return;
	var node = document.getElementById(i + 'Val');
	removeChildren(node);
	if(val != null) addText(node, val);
}

function showAlert(i, str) {
	if(i == null || i == false || i == '') return;
	var node = document.getElementById(i + 'Val');
	removeChildren(node);
	addClassText(node, str, 'alert');
}

function valMatch(i1, i2) {
	var n1 = document.getElementById(i1);
	var n2 = document.getElementById(i2);
	if(n1 == null || n2 == null || n1.value == '' || n2.value == '') return false;
	if(n1.value == n2.value) {
		validate(n1, i1);
		validate(n2, i2);
		return true;
	} else {
		showAlert(i1, 'Does not match!');
		showAlert(i2, 'Does not match!');
		return false;
	}
}

function valAuto(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqnoval') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	return true;
}

function valText(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqtext') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	showValidated(display, s);
	return true;
}

function valRadio(node, display) {
	var s = 0;
	for(var j = 1, n = document.getElementById(display + j); n != null; j++, n = document.getElementById(display + j)) {
		if(n.checked) s = j;
	}
	if(s == 0) { if(node.className == 'reqradio') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var allLabel = document.getElementsByTagName('label');
	var show = '';
	for(var i = 0; i < allLabel.length; i++) {
		if(allLabel[i].getAttribute('for') == display + s) {
			show = allLabel[i].firstChild.nodeValue;
		}
	}
	showValidated(display, show);
	return true;
}

function valCheckBox(node, display) {
	var s = node.checked;
	if(!s) { if(node.className == 'reqcheckbox') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var allLabel = document.getElementsByTagName('label');
	var show = '';
	for(var i = 0; i < allLabel.length; i++) {
		if(allLabel[i].getAttribute('for') == display) {
			show = allLabel[i].firstChild.nodeValue;
		}
	}
	return true;
}

function valPassword(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqpassword') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var l = s.length;
	if(l > 24) {
		showAlert(display, '*** Error ***');
		return false;
	} else {
		showValidated(display, '********');
		return true;
	}
	return false;
}

function valEMail(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqemail') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var a = s.indexOf('@');
	var d = s.lastIndexOf('.');
	var l = s.length;
	if(  ( a < 1                     ) // no @ sign (or no characters before @ sign)
		|| ( d - a < 2                 ) // no characters between @ and last . (or no .)
		|| ( l - d <= 1                ) // no characters after last .
		|| ( s.indexOf('@', a + 1) > 0 ) // second @ sign present
		|| ( s.indexOf(' ') >= 0       ) // Ban specific illegal characters characters
		|| ( s.indexOf(':') >= 0       ) // 
		|| ( s.indexOf('<') >= 0       ) // 
		|| ( s.indexOf('>') >= 0       ) // 
		|| ( s.indexOf('%') >= 0       ) // 
		|| ( s.indexOf('&') >= 0       ) // 
		|| ( s.indexOf('$') >= 0       ) // 
		|| ( s.indexOf('*') >= 0       ) // 
		|| ( s.indexOf('(') >= 0       ) // 
		|| ( s.indexOf(')') >= 0       ) // 
		) {
		showAlert(display, '*** Bad Address ***');
		return false;
	} else {
		s = s.toLowerCase();
		showValidated(display, s);
		node.value = s;
		return true;
	}
	return false;
}

function stripNonNumeric(str) {
	var ret = '';
	var digits = '0123456789';
	for(var i = 0; i < str.length; i++) {
		if(digits.indexOf(str.charAt(i)) >= 0) ret += str.charAt(i);
	}
	return ret;
}

function stripNonFloat(str) {
	var ret = '';
	var digits = '0123456789.';
	for(var i = 0; i < str.length; i++) {
		if(digits.indexOf(str.charAt(i)) >= 0) ret += str.charAt(i);
	}
	return ret;
}

function valZipCode(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqzipcode') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var v = stripNonNumeric(s);
	if(v.length != 5 && v.length != 9) { showAlert(display, '*** Invalid Zip Code ***'); return false; }
	if(v.length == 9) {
		v = v.substring(0, 5) + '-' + v.substring(5, 9);
	}
	showValidated(display, v);
	node.value = v;
	return true;
}

function valPhone(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqzipcode') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var v = stripNonNumeric(s);
	if(v.length != 7 && v.length != 10) { showAlert(display, '*** Invalid Phone Number ***'); return false; }
	if(v.length == 7) {
		v = v.substring(0, 3) + '-' + v.substring(3, 7);
	} else {
		v = '(' + v.substring(0, 3) + ') ' + v.substring(3, 6) + '-' + v.substring(6, 10);
	}
	showValidated(display, v);
	node.value = v;
	return true;
}

function valSelect(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqzipcode') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	showValidated(display, node.options[node.selectedIndex].text);
	return true;
}

function valNumber(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqzipcode') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var v = stripNonNumeric(s);
	showValidated(display, v);
	node.value = v;
	return v != '';
}

function valYear(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqzipcode') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var v = stripNonNumeric(s);
	var i = parseInt(v);
	if(i > 1900 && i < 2200) {
		showValidated(display, v);
		node.value = v;
		return true;
	}
	showAlert(display, '*** Invalid Year ***');
	return false;
}

function valGPA(node, display) {
	var s = node.value;
	if(s == null || s == '') { if(node.className == 'reqzipcode') { showAlert(display, '*** Required ***'); return false; } else { return true; } }
	var v = stripNonFloat(s);
	var i = parseFloat(v);
	if(i >= 0.0 && i <= 4.0) {
		showValidated(display, v);
		node.value = v;
		return true;
	}
	showAlert(display, '*** Invalid GPA ***');
	return false;
}

