function validate_form(form)
{
	var msg = '';
	var missing_fields = new Array();
	var restricted_fields = new Array();
	
	for (var i=0; i<form.elements.length; i++)
	{
		var e = form.elements[i];
		var required, restrict;
		
		if (required = e.getAttribute('required'))
		{
			_remove_class_name(e, 'missing');
			
			if (required == 'true')
			{
				switch (e.type)
				{
					case 'text':
					case 'file':
					case 'password':
						if (e.value.length == 0) missing_fields[missing_fields.length] = e;
					break;
					
					case 'select-one':
						if (e.selectedIndex <= 0) missing_fields[missing_fields.length] = e;
					break;
					
					default:
						alert("add case for " + e.type);
				}
			}		
		}
		
		if (restrict = e.getAttribute('restrict'))
		{
			var r = restrict.split(',');
			switch (r[0])
			{
				case 'currency':
					e.value = e.value.replace('$', '');
					e.value = e.value.replace(',', '');
					e.value = e.value.replace(' ', '');
					if (isNaN(e.value))
						restricted_fields[restricted_fields.length] = [e, 'currency'];
					else 
					{
						if (r.length >= 2 && r[1] != '*' && Number(e.value) < Number(r[1])) restricted_fields[restricted_fields.length] = [e, 'at least '+r[1]];
						if (r.length >= 3 && r[2] != '*' && Number(e.value) > Number(r[2])) restricted_fields[restricted_fields.length] = [e, 'less than '+r[2]];
					}
					break;
					
				case 'aba_routing':
					if (e.value.length != 9)
						restricted_fields[restricted_fields.length] = [e, 'must be nine digits'];
				
					else
					{
						var sum = 0;
						for (var j=0; j != 9; j+=3)
						{
							sum += Number(e.value.substr(j, 1)) * 3;
							sum += Number(e.value.substr(j+1, 1)) * 7;
							sum += Number(e.value.substr(j+2, 1)) * 1;
						}
						if (sum % 10)
							restricted_fields[restricted_fields.length] = [e, 'must be a valid 9 digit routing number'];
					}
					
					break;
					
				default:
					alert("Need to implement " + r[0]);
			}
		}
	}
	
	if (missing_fields.length)
	{
		msg += "The following fields are required:\n\n";
		missing_fields[0].focus();
		for (var i = 0; i < missing_fields.length; i++)
		{
			msg += "* " + _get_friendly_name(missing_fields[i]) + "\n";
			_add_class_name(missing_fields[i], 'missing');
		}
		msg += "\n";
	}
	
	
	if (restricted_fields.length)
	{
		if (msg) msg += "In addition, the following fields need to be corrected:\n\n";
		else msg += "The following fields need to be corrected:\n\n";
	
		restricted_fields[0][0].focus();
		
		for (var i = 0; i < restricted_fields.length; i++)
		{
			msg += "* " + _get_friendly_name(restricted_fields[i][0]) + " (" + restricted_fields[i][1] + ")\n";
			_add_class_name(restricted_fields[i][0], 'missing');
		}
	}
	
	if ((typeof extra_form_validation) == 'function') msg += extra_form_validation(form);
	
	if (msg.length) alert(msg);	
	
	return msg.length == 0 ? true : false;
}

function _get_friendly_name(e)
{
	return e.getAttribute('caption') ? e.getAttribute('caption') : e.getAttribute('name');
}

function _add_class_name(e, name)
{
	if (e.className.length == 0)
		e.className = name;	
	else if (e.className.indexOf(name) >= 0)
		return;
	else
		alert("put code here 0");
}

function _remove_class_name(e, name)
{
	if (e.className == name)
		e.className = '';
	else if (e.className.indexOf(" "+name) >= 0)
	{
		alert("put code here 1");
	}
	else if (e.className.indexOf(name) >= 0)
	{
		alert("put code here 2");
	}
}
