// validate.js 1.99
// a generic form validator 
// by Brian Lalonde http://webcoder.info/downloads/
// Slightly modified by the one and only Ben Balzarini :-)
// This work is licensed under the Creative Commons Attribution-Share Alike 3.0 License. 
// To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ 
// or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.

function formFocus(frm)
{ // convenient way to start the form onLoad
	if(!document.forms.length) return;
	var els= ( frm || document.forms[0] ).elements;
	for(var i= 0; i < els.length; i++)
		if(els[i].type != 'hidden') { els[i].focus(); return; }
}

function formChanged(frm)
{ // determine whether any form fields have changed
	if(!document.forms.length) return;
	var els= ( frm || document.forms[0] ).elements;
	for(var i= 0; i < els.length; i++)
		switch(els[i].type)
		{
			case 'text': 
			case 'textarea': 
			case 'password': 
			case 'hidden':
			case 'file':
				if(els[i].defaultValue!=els[i].value)
				{ status= 'The '+fieldname(els[i])+' field has changed.'; return true; } 
				break;
			case 'checkbox':
				if(els[i].defaultChecked!=els[i].checked)
				{ status= 'The '+fieldname(els[i])+' checkbox has changed.'; return true; }
				break;
			case 'select-one':
				for(var j= 1; j < els[i].options.length; j++)
					if(els[i].options[j].defaultSelected!=els[i].options[j].selected)
					{ status= 'The '+fieldname(els[i])+' selection has changed.'; return true; }
				break;
			case 'select-multiple':
				for(var j= 0; j < els[i].options.length; j++)
					if(els[i].options[j].defaultSelected!=els[i].options[j].selected)
					{ status= 'The '+fieldname(els[i])+' selections have changed.'; return true; }
				break;
			case 'radio':
				if(els[i].length)
					for(var j= 0; j < els[i].length; j++)
						if(els[i][j].defaultChecked!=els[i][j].checked)
						{ status= 'The '+fieldname(els[i])+' choice has changed.'; return true; }
				break;
		}
	return false;
}

function fieldname(fld)
{ // get the field label text or name
	if(fld.id && document.getElementsByTagName)
	{
		for(var i= 0, lbl= document.getElementsByTagName('LABEL'); i < lbl.length; i++)
			if(lbl[i].htmlFor==fld.id) return lbl[i].nodeValue||lbl[i].textContent||lbl[i].innerText;
		for(var i= 0, lbl= document.getElementsByTagName('label'); i < lbl.length; i++)
			if(lbl[i].htmlFor==fld.id) return lbl[i].nodeValue||lbl[i].textContent||lbl[i].innerText;
	}
	return fld.name||fld.type;
}

function requireChecked(fld)
{ // require a checkbox to be checked
	if(fld.disabled) return true;
	if(!fld.checked)
	{ status= 'You must agree to the requirements listed before proceeding.'; return false; }
	return true;
}

function autocheckByName(frm) 
{ // uses names of form elements to determine type 
	for(var index= 0; index < frm.elements.length; index++)
	{
		var el= frm.elements[index];
		if(!el.type) continue;
		if(el.type == 'text' || el.type == 'password')
		{ // text fields 
			if(( el.name.substring(0,1) == el.name.substring(0,1).toUpperCase() || 
				nameContains(el.name,'Required')) && el.value.length == 0)
			{ alert('The '+fieldname(el)+' field cannot be left blank.'); el.focus(); return false; }
			if(nameContains(el.name,'Date') && !fixDate(el))
			{ alert(status); el.focus(); return false; }
			if(nameContains(el.name,'Time24') && !fixTime24(el))
			{ alert(status); el.focus(); return false; }
			if(nameContains(el.name,'Time') && !fixTime(el))
			{ alert(status); el.focus(); return false; }
			if(nameContains(el.name,'SSN') && !fixSSN(el))
			{ alert(status); el.focus(); return false; }
			if(nameContains(el.name,'CC') && !fixCreditCard(el))
			{ alert(status); el.focus(); return false; }
			if(nameContains(el.name,'Email') && !checkEmail(el))
			{ alert(status); el.focus(); return false; }
			if( ( nameContains(el.name,'Phone') ||
				nameContains(el.name,'Fax') || 
				nameContains(el.name,'Pager') ) &&
				!fixPhone(el))
			{ alert(status); el.focus(); return false; }
		}
		// handle required select and select-multiple 
		else if(el.type.substring(0,3) == 'sel' && 
			(el.name.substring(0,1) == el.name.substring(0,1).toUpperCase() || 
			nameContains(el.name,'Required')) && el.selectedIndex == -1)
		{ alert(status); el.focus(); return false; }
		// handle required checkbox
		else if(el.type == 'checkbox' && 
			(el.name.substring(0,1) == el.name.substring(0,1).toUpperCase() || 
			nameContains(el.name,'Required')) && !requireChecked(el))
		{ alert(status); el.focus(); return false; }
		else if(el.type == 'radio' && !requireRadio(frm[el.name]))
		{ alert(status); frm.elements[index].focus(); return false; }
	}
	for(var index= 0; index < frm.elements.length; index++)
		if(frm.elements[index].type == 'submit') frm.elements[index].disabled= true;
	return true;
}

function isMemberOf(elem,classname)
{ // checks to see if elem is a member of the (style) class 
	// trivial cases first: no membership or simple equality
	if(!elem.className)
		return false
	else if(elem.className == classname)
		return true;
	else if(elem.className.indexOf(' ') > -1)
	{ // multiple class names; use split, if avail 
		if(parseInt(navigator.appVersion) >= 4)
		{
			var names= elem.className.split(' ');
			for(var index= 0; index < names.length; index++)
				if(names[index] == classname)
					return true;
		}
		// older browsers can fake it 
		// WARNING: "fine" can be found in "oldRefined"
		else if(elem.className.indexOf(classname) > -1)
			return true;
	}
	return false;
}

function checkClass(el)
{ // validate the field, based on class membership
	if(el.type == 'text' || el.type == 'password')
	{ // text fields 
		if(isMemberOf(el,'required') && !requireValue(el)) return false;
		if(isMemberOf(el,'date') && !fixDate(el)) return false;
		if(isMemberOf(el,'time') && !fixTime(el)) return false;
		if(isMemberOf(el,'time24') && !fixTime24(el)) return false;
		if(isMemberOf(el,'ssn') && !fixSSN(el)) return false;
		if(isMemberOf(el,'cc') && !fixCreditCard(el)) return false;
		if(isMemberOf(el,'phone') && !fixPhone(el)) return false;
		if(isMemberOf(el,'money') && !fixMoney(el)) return false;
		if(isMemberOf(el,'int') && !fixInt(el)) return false;
		if(isMemberOf(el,'float') && !fixFloat(el)) return false;
		if(isMemberOf(el,'email') && !checkEmail(el)) return false;
	} // handle required select and select-multiple 
	else if(el.type == 'checkbox' && 
		isMemberOf(el,'required') && !requireChecked(el)) return false;
	else if(el.type.substring(0,3) == 'sel' && 
		isMemberOf(el,'required') && el.selectedIndex == -1) return false;
	return true;
}

function autocheckByClass(frm) 
{ // uses the CSS class of form elements to determine type 
	for(var index= 0; index < frm.elements.length; index++)
	{
		var el= frm.elements[index];
		if(!el.type) continue;
		if(el.type == 'radio' && !requireRadio(frm[el.name]))
		{ alert(status); frm.elements[index].focus(); return false; }
		else if(!checkClass(frm.elements[index])) 
		{ alert(status); frm.elements[index].focus(); return false; }
	}
	for(var index= 0; index < frm.elements.length; index++)
		if(frm.elements[index].type == 'submit') frm.elements[index].disabled= true;
	return true;
}

function autocheckByBlur(frm)
{ // uses the onBlur handler of form elements to check value 
	status= '';
	for(var index= 0; index < frm.elements.length; index++)
	{
		var el= frm.elements[index];
		if(!el.type) continue;
		if(el.type == 'radio' && !requireRadio(frm[el.name]))
		{ alert(status); frm.elements[index].focus(); return false; }
		else if(el.type != 'hidden' && el.name && el.onblur)
		{
			el.onblur();
			if(status) { alert(status); el.focus(); return false; }
		}
	}
	for(var index= 0; index < frm.elements.length; index++)
		if(frm.elements[index].type == 'submit') frm.elements[index].disabled= true;
	return true;
}

function canCheckByBlur(frm)
{ // determines whether programmatic invocation of form element onblur is available
	for(var index= 0; index < frm.elements.length; index++)
	{
		var el= frm.elements[index];
		if(!el.type) continue;
		if(el.type != 'hidden' && el.name && typeof(el.onblur)=='function') return true;
	}
	return false;
}

function autocheck(frm)
{ // uses the best available method to check form values 
	var bchar= navigator.appName.substring(0,1);
	if(isMemberOf(frm,'autocheck'))
	{ return autocheckByClass(frm); }
	else if(canCheckByBlur(frm))
	{ return autocheckByBlur(frm); }
	else
	{ return autocheckByName(frm); }
}
