/******************************************************************************\

	Class FormHandler

	The FormValidator will check a form on submission. All data is compared to
	certain rules. If some data does not match the criteria, all errors are
	displayed in an alert box, and the form is not submitted.

	1. Classes with their variables and methods:
	---------------------------------------------------------------------------

	- FormHandler
		variables:
		+ frm				(object Form)
		+ frm.frmError		(object FrmError)
		methods:
		+ onsubmit			(fv_handle_submit)
		+ addVal			(fv_add_validation)
	
	- ValidationSet
		variables:
		+ set				(array Validation)
		+ frmField			(object Form.Field)
		methods:
		+ add				(vs_add_validation)
		+ validate			(vs_validate)

	- Validation
		variables:
		+ frmField			(object Form.Field)
		+ validation		(string)
		+ message			(string)
		methods:
		+ validate			(v_validate)

	- FrmError
		variables:
		+ errstr			(string)
		methods:
		+ isError			(fe_is_error : boolean)
		+ add				(fe_add_error)
		+ show				(fe_show_error)
		+ clear				(fe_clear_error)


	functions which are not bind to a class:
		+ v_validate_data	(called Validation.validate)
		+ v_build			(called v_validate_data)
		+ v_check_date_us	(called v_validate_data)


	2. Hierarchy of classes
	---------------------------------------------------------------------------

	- FormHandler
		¬ frm
			¬ FrmError
			¬ frmField
				¬ ValidationSet
					¬ Validation
	
	The Form						has one FrmError, which stores all errors.
	The Form.Field					has zero or one ValidationSet.
	The Form.Field.ValidationSet	has one or more Validations.


	3. Description of program
	---------------------------------------------------------------------------

	There must be a html-page with a form to validate.

	A new FormValidator-object is created with the formname.
	Then all the Validationtypes will be added.

	Normally, the onsubmit-function of the Form will send the form. In this 
	case however, FormValidator overrides the onsubmit-function with an own
	function fv_onsubmit_handler().
	This function loops through all the validationsets, and adds the errors
	to the FrmError-object.
	When there are errors, the FrmError-object gives a warning, and the
	errormessage is displayed.
	When there is an error, the form will not be submitted. Else, the form
	will be submitted

	4. Sample code
	---------------------------------------------------------------------------

	*** First create the form
	<form method=post action=process.html name=nameForm>
	<input type=text name=Name value="" size=20 maxlength=20>
	<select name=selection>
		<option>Choose</option>
		<option>Option 1</option>
		<option>Option 2</option>
	</select>
	<input type=submit value=Store>
	</form>

	*** Add the validator
	<script language="javascript">
	fv			= new FormValidator('nameForm');
	fv.addVal("Name","req","You must enter a name");	//field is required
	fv.addVal("Name","min=10");							//min length of 10
	fv.addVal("selection","dontselect=0");				//first can't be select


	5. Version information and copyright notice
	---------------------------------------------------------------------------

	Version 1.0

	Copyright Vinetix Internet 2003


	6. Changelog
	---------------------------------------------------------------------------
	[no changes were made yet]

\*****************************************************************************/
	

/***** Class FormValidator ***************************************************/
function FormHandler(frmName) {
	//this.frm				= document.forms[frmName];
  this.frm          = document.getElementById(frmName);
	this.frm.frmError		= new FrmError();
	this.frm.onsubmit		= fv_handle_submit;
	this.addVal				= fv_add_validation;
	this.frm.setmd5			= new Array();
	this.addMd5				= fv_add_md5;
}
function fv_handle_submit() {
	for(var x=0;x<this.elements.length;x++) {
		if(this.elements[x].validationSet) {
			this.frmError.add(this.elements[x].validationSet.validate());
		}
	}
	if(this.frmError.isError()) {
		this.frmError.show();
		this.frmError.clear();
		return false;
	} else {
		for(var x=0; x<this.setmd5.length;x++) {
			this.setmd5[x].value = hex_md5(this.setmd5[x].value);
		}
		return true;
	}
}

function fv_add_md5(strName) {
	var frmField	= this.frm[strName];
	var found		= false;
	if(!frmField) {
		this.frmError.add('Veld '+strName+' bestaat niet');
	} else {
		for(var x=0;x<this.frm.setmd5.length;x++) {
			if(this.frm.setmd5[x]==frmField) {
				found = true;
			}
		}
		if(!found) {
			this.frm.setmd5[this.frm.setmd5.length] = frmField;
		}
	}
}

function fv_add_validation(strName,strValidation,strMessage) {
	var	frmField	= this.frm[strName];
	if(!frmField) {
		this.frm.frmError.add('Veld '+ strName +' bestaat niet');
	} else {
		if(!frmField.validationSet) {
			frmField.validationSet = new ValidationSet(frmField,this.frm);
		}
		frmField.validationSet.add(strValidation,strMessage);
	}
}

/***** Class ValidationSet ***************************************************/
function ValidationSet(frmField,frm) {
	this.set		= new Array();
	this.add		= vs_add_validation;
	this.validate	= vs_validate;
	this.frmField	= frmField;
	this.frm		= frm
}
function vs_add_validation(strValidation,strMessage) {
	this.set[this.set.length] = new Validation(this.frmField,strValidation,strMessage,this.frm);
}
function vs_validate() {
	var ret = '';
	for(var x=0;x<this.set.length;x++) {
		ret += this.set[x].validate();
	}
	return ret;
}

/***** Class Validation ******************************************************/
function Validation(frmField,strValidation,strMessage,frm) {
	this.frmField	= frmField;
	this.validation	= strValidation;
	this.message	= strMessage;
	this.frm		= frm;
	this.validate	= v_validate;
}
function v_validate() {
	var ret			= '';
	ret += v_validate_data(this.validation,this.frmField,this.message,this.frm);
	return ret;
}

function v_validate_data(validation,field,message,frm) {
	var ret			= '';
	var ispos		= validation.search("=");
	var cmd			= '';
	var cmdv		= '';
	if(ispos >= 0) { 
		cmd			= validation.substr(0,ispos);
		cmdv		= validation.substr(ispos+1);
	} else {
		cmd			= validation;
	}

	switch(cmd) {
		case 'req':
			if(eval(field.value.length)==0) {
				ret		+= v_build(field.name+' is niet ingevuld',message);
			}
			break;
		case 'maxlength':
    case 'max':
    case 'maxlen':
			var length = (cmdv.length>0)?eval(cmdv):10;
			if(eval(field.value.length) > length) {
				ret		+= v_build(field.name +' is langer dan '+length+' karakters',message);
			}
			break;
		case 'minlength':
		case 'min':
		case 'minlen':
			var length = (cmdv.length>0)?eval(cmdv):10;
			if(field.value.length > 0 && eval(field.value.length) < length) {
				ret		+= v_build(field.name +' is korter dan '+length+' karakters',message);
			}
			break;
		case 'alphanumeric':
		case 'alfanumeriek':
		case 'alnum':
			if(field.value.length > 0 && field.value.search('[^a-zA-z0-9]') >= 0) {
				ret		+= v_build(field.name +' bevat niet-alfanumerieke karakters',message);
			}
			break;
		case 'num':
		case 'numeriek':
			if(field.value.length > 0 && field.value.search('[^0-9]') >= 0) {
				ret		+= v_build(field.name +' bevat niet alleen cijfers',message);
			}
			break;
    case 'double':
      if(field.value.length > 0 && field.value.search('[^0-9.,]') >= 0) {
        ret   += v_build(field.name +' bevat geen (decimaal) getal',message);
      }
      break;
		case 'alpha':
			if(field.value.length > 0 && field.value.search('[^a-zA-z]') >= 0) {
				ret		+= v_build(field.name +' bevat niet alleen letters',message);
			}
			break;
		case 'alnumhyph':
			if(field.value.length > 0 && field.value.search('[^a-zA-z0-9\-_]') >= 0) {
				ret		+= v_build(field.name +' mag alleen de karakters a-z,A-Z,0-9,- en _ bevatten',message);
			}
			break;
		case 'email':
			if(field.value.length > 0 && field.value.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/)!=0) {
				ret		+= v_build(field.name +' is geen geldig e-mailadres',message);
			}
			break;
		case 'lt':
		case 'lessthan':
			var value = (cmdv.length>0)?eval(cmdv):10;
			if(isNaN(field.value)) {
				ret		+= v_build(field.name +' is geen nummer','');
			} else {
				if(eval(field.value) >= value) {
					ret += v_build(field.name +' moet kleiner zijn dan '+ value,message);
				}
			}
			break;
		case 'gt':
		case 'greaterthan':
			var value	= (cmdv.length>0)?eval(cmdv):10;
			if(isNaN(field.value)) {
				ret		+= v_build(field.name +' is geen nummer','');
			} else {
				if(eval(field.value) <= value) {
					ret	+= v_build(field.name +' moet groter zijn dan '+ value,message);
				}
			}
			break;
		case 'le':
		case 'lessequal':
			var value	= (cmdv.length>0)?eval(cmdv):10;
			if(isNaN(field.value)) {
				ret		+= v_build(field.name +' is geen nummer','');
			} else {
				if(eval(field.value) > value) {
					ret += v_build(field.name +' moet kleiner of gelijk zijn aan '+ value,message);
				}
			}
			break;
		case 'ge':
		case 'greaterequal':
			var value	= (cmdv.length>0)?eval(cmdv):10;
			if(isNaN(field.value)) {
				ret		+= v_build(field.name +' is geen nummer','');
			} else {
				if(eval(field.value) < value) {
					ret	+= v_build(field.name +' moet groter of gelijk zijn aan '+ value,message);
				}
			}
			break;
		case 'regexp':
			if(field.value.length > 0 && !field.value.match(cmdv)) {
				ret		+= v_build(field.name +' voldoet niet aan de filter: '+ cmdv, message);
			}
			break;
		case 'dontselect':
			if(field.selectedIndex==null) {
				ret		+= v_build('Fout in validatie-omschrijving voor veld '+ field.name,'');
			} else {
				if(field.selectedIndex == eval(cmdv)) {
					ret	+= v_build('Geen optie gekozen in selectievak '+ field.name,message);
				}
			}
			break;
		case 'zip':
		case 'postal':
			switch(cmdv) {
				case 'nl':
				default:
					if(field.value.length>0 && field.value.search(/^[1-9][0-9][0-9][0-9] ?[a-zA-z][a-zA-z]$/) != 0) {
						ret += v_build(field.name +' bevat geen geldige Nederlandse postcode',message);
					}
			}
			break;
		case 'date':
			switch(cmdv) {
				case 'us':
				case 'en':
        case 'uk':
					if(field.value.length>0 && !v_check_date_us(field.value)) {
						ret += v_build(field.name +' bevat geen geldige Engelse datum (mm-dd-jjjj)',message);
					}
					break;
				case 'nl':
				default:
					if(field.value.length>0) {
						var correct = true;
						var datum	= field.value.split("-");
						if(datum.length != 3 || !v_check_date_us(datum[1] +'-'+ datum[0] +'-'+ datum[2])) {
							ret	+= v_build(field.name +' bevat geen geldige Nederlandse datum (dd-mm-jjjj)',message);
						}
					}
			}
			break;

		case 'cmp':
		case 'compare':
		case 'comp':
			var found	= false;
			for(var x=0;x<frm.elements.length;x++) {
				if(frm.elements[x].name==cmdv) {
					found = true;
					if(field.value!=frm.elements[x].value) {
						ret+=v_build(field.name +' is niet gelijk aan '+ cmdv);
					}
				}
			}
			if(!found) {
				ret+=v_build(cmdv+' kan niet worden gevonden om te vergelijken met '+ field.name);
			}
			break;
	}
	return ret;
}
function v_build(string,message) {
	var ret				= '';
	ret					+= (!message||message.length==0)?'- '+string+'\n':'- '+message+'\n';
	return ret;
}
function v_check_date_us(dateStr) {
	var arrDate = dateStr.split("-");
	if(arrDate.length!=3) { return false; }
	var strYear		= arrDate[2];
	var numDay		= eval(arrDate[1]);
	var numMonth	= eval(arrDate[0]);
	var numYear		= eval(strYear);

	if(strYear.length!=2&&strYear.length!=4) { return false; }
	if(strYear.length==2&&numYear<=50) { numYear += 2000; }
	if(strYear.length==2&&numYear>50) { numYear += 1900; }
	if(numYear<0||numYear>9999) { return false; }

	if(numMonth<1||numMonth>12) { return false; }

	if(numDay>=32) { return false; }
	if(numDay>=31 && (numMonth==2||numMonth==4||numMonth==6||numMonth==9||numMonth==11)) { return false; }
	if(numDay>=30 && numMonth==2) { return false; }

	if(numMonth==2&&numDay==29) {
		var div4	= numYear % 4;
		var div100	= numYear % 100;
		var div400	= numYear % 400;
		if(div4!=0) { return false; }
		if(div100==0&&div400!=0) { return false; }
	}
	return true;
}

/***** Class FrmError ********************************************************/
function FrmError() {
	this.isError		= fe_is_error;
	this.errstr			= '';
	this.add			= fe_add_error;
	this.show			= fe_show_error;
	this.clear			= fe_clear_error;
}
function fe_add_error(strError) {
	if(strError != '') {
		this.errstr			+= strError;
	}
}
function fe_show_error() {
	if(this.errstr!='') {
		alert('De volgende punten zijn niet juist:\n\n'
			 + this.errstr 
			 +'\n\n'
			 +'Het formulier is niet opgestuurd');
	}
}
function fe_is_error() {
	if (this.errstr=='') {
		return false;
	} else {
		return true;
	}
}
function fe_clear_error() {
	this.errstr='';
}

