/*------------------------------------------------------*/
/* Objects:												*/
/* -formValidator										*/
/* -validationContainer									*/
/* -validatedElement									*/
/* -validationObject									*/
/*	Version 1.5											*/
/*------------------------------------------------------*/
var FvVersion = "1.5";

function handleOnFocus(e)
{
	aElm = getSourceElement(e);
	if (aElm != null)
	{
		var aFocusFunc = aElm["p80onfocusfunc"];
		if (aFocusFunc != null)
		{
			aFocusFunc(aElm);
		}
	}
}

function getSourceElement(e)
{
	var aElm = null;
	if (!e)
	{
		aElm = window.event.scrElement;
	}
	else
	{
		if (e.target)
		{
			aElm = e.target;
		}
		else if (e.srcElement)
		{
			aElm = e.srcElement;
		}
	}
	return aElm;
}

function handleOnBlur(e)
{
	if (typeof(handleInvalidOnBlur) != 'undefined')
	{
		aElm = getSourceElement(e);
		if (aElm != null)
		{
			var thisValidation = validator.validateContainer(aElm["p80Container"],true);
			handleInvalidOnBlur(aElm,thisValidation);
		}
	}
}

function formValidator(aName,aForm,aValidator)
{
	this.name = aName;
	this.form = aForm;
	this.elementonfocus = null;
	this.validateonblur = false;
	this.validator = aValidator;
	this.validationContainers = new Array;
	this.testAttr = new Array(3);
	this.testAttr[0] = 'p80fv:required';
	this.testAttr[1] = 'p80fv:dependencieswhen';
	this.testAttr[2] = 'p80fv:domain';
	
	this.initFromForm = function()
	{
		this.elementonfocus = this.setElementOnFocus();
		this.validateonblur = this.setValidationOnBlur();
		for(var i=0,aFrmElm;aFrmElm = this.form.elements[i];i++)
		{
		    
			if (this.isP80fvObject(aFrmElm))
			{
				this.addContainer(aFrmElm);
			}
			var thisOnFocus = this.findOnFocus(aFrmElm);
			aFrmElm["p80onfocusfunc"] = thisOnFocus;
			if (thisOnFocus != null)
			{
				this.attachOnFocusEvent(aFrmElm);
			}
		}
	}
	
	this.getValidationAttribute = function(aIdent)
	{
		var Retval = this.form.getAttribute('p80fv:'+aIdent);
		return Retval;
	}
	
	this.setValidationOnBlur = function()
	{
		var Retval = this.getValidationAttribute('validateonblur');
		return (Retval == 'true');
	}
	
	this.setElementOnFocus = function()
	{
		var aFuncName = this.getValidationAttribute('onfocus');
		if (aFuncName != null)
		{
			try
			{
				return eval("window."+aFuncName);
			}
			catch(e)
			{
				debugTrace(e.toString(),true);
			}
		}
		return null;
	}
	
	this.isP80fvObject = function(aElement)
	{
		var Retval = false;
		for (var i=0,aAttr;aAttr=this.testAttr[i];i++)
		{
			var thisAttr = aElement.getAttribute(aAttr);
			if (thisAttr != null)
			{
				Retval = true;
				break;
			}
		}
		return Retval;
	}
	
	this.addContainer = function(aFormElement)
	{
		var aContainer = null;
		for (var i=0,aContainer;aContainer=this.validationContainers[i];i++)
		{
			if (aContainer.name == aFormElement.name)
			{
				break;
			}
		}
		if (aContainer == null)
		{
			aContainer = new validationContainer(aFormElement.name,this.validateonblur);
			this.validationContainers[this.validationContainers.length] = aContainer;
		}
		newElm = new validatedElement(this.form,aFormElement,aContainer);
		newElm.initialise();
		aContainer.addElement(newElm);
	}
	
	this.attachOnFocusEvent = function(aFormElement)
	{
		var fn = handleOnFocus;
		if (aFormElement.addEventListener) {
			aFormElement.addEventListener("focus", fn, false);
		}
		else if (aFormElement.attachEvent) {
			aFormElement.attachEvent("onfocus", fn);
		}
		else if (typeof aFormElement.onfocus == "function") {
			var fnOld = aFormElement.onfocus;
			aFormElement.onfocus = function(){
				fnOld();
				fn();
			};
		}
		else {
			aFormElement.onfocus = fn;
		}
	}
	
	this.findOnFocus = function(aFormElm)
	{
		var Retval = aFormElm.getAttribute('p80fv:onfocus');
		if (Retval == null)
		{
			Retval = this.elementonfocus;
		}
		else
		{
			debugTrace(this.name+' has onfocus attribute');
			try
			{
				Retval = eval("window."+Retval);
			}
			catch(e)
			{
				debugTrace(e.toString(),true);
			}
		}
		return Retval;
	}

	this.validate = function()
	{
		debugTrace('Form who called onsubmit: '+this.name);
		try
		{
			for (var i=0,aContainer;aContainer=this.validationContainers[i];i++)
			{
				debugTrace('Validating:'+aContainer.name);
				Retval = this.validator.validateContainer(aContainer);
				if (!Retval)
				{
					debugTrace('INVALID!',true);
					return false;
					break;
				}
			}
		}
		catch(e)
		{
			debugTrace(e.toString(),true);
		}
		return true;
	}
}

/*----------------------------------------------------------------------*/

function validationContainer(aName,aValidateonblur)
{
	this.name = aName;
	this.validateonblur = aValidateonblur;
	this.validationElements = new Array();
	this.required = false;
	debugTrace('Container created:'+aName);
	
	this.findRequired = function(aFormElm)
	{
		var Retval = aFormElm.getAttribute('p80fv:required');
		if (Retval != null)
		{
			this.required = true;
			debugTrace(this.name+' is required');
		}
	}

	this.findOnBlur = function(aFormElm)
	{
		var Retval = aFormElm.getAttribute('p80fv:validateonblur');
		if (Retval == null)
		{
			Retval = this.validateonblur;
		}
		else
		{
			debugTrace(this.name+' has onblur attribute');
		}
		return Retval;
	}
	
	this.addElement = function(aElement)
	{
		aElement.formElement["p80Container"] = this;
		this.validationElements[this.validationElements.length] = aElement;
		this.findRequired(aElement.formElement);
		var thisOnBlur = this.findOnBlur(aElement.formElement);
		if ((this.validateonblur) && (this.validateonblur == thisOnBlur) || ((!this.validateonblur) && (this.validateonblur != thisOnBlur)))
		{
			this.attachOnBlurEvent(aElement.formElement);
		}
	}

	this.attachOnBlurEvent = function(aFormElement)
	{
		var fn = handleOnBlur;
		if (aFormElement.addEventListener) {
			aFormElement.addEventListener("blur", fn, false);
		}
		else if (aFormElement.attachEvent) {
			aFormElement.attachEvent("onblur", fn);
		}
		else if (typeof(aFormElement.onblur) == "function") {
			var fnOld = aFormElement.onblur;
			aFormElement.onblur = function(){
				fnOld();
				fn();
			};
		}
		else {
			aFormElement.onblur = fn;
		}
	}
}

/*----------------------------------------------------------------------*/

function validatedElement(aForm,frmElm,aContainer)
{
	this.name = frmElm.name;
	this.container = aContainer;
	this.formElement = frmElm;
	this.parentForm = aForm;
	this.dependedObjects = null;
	this.validateDependenciesWhen = null;
	this.defaultValue = null;
	this.domain = null;
	this.Params = new Array();
	this.required = false;
	this.message = null;
	this.errorMessage = null;
	this.ommissionMessage = null;

	this.initialise = function()
	{
		this.validateDependenciesWhen = this.getValidationAttribute('dependencieswhen');
		if (this.validateDependenciesWhen != null)
		{
			this.validateDependenciesWhen = new Boolean(this.validateDependenciesWhen == 'true');
			this.findDependedElements(this.formElement.id);
		}
		this.defaultValue	= this.setDefault();
		this.required		= this.setRequired();
		this.domain			= this.setDomain();
		this.Params			= this.setParams();
		this.message		= this.setMessage();
		this.errorMessage	= this.setErrorMessage();
		this.ommissionMessage= this.setOmmissionMessage();
		if ((this.required == true) && (this.validateDependenciesWhen != null))
		{
			debugTrace('Required field with dependencies: ' + this.name,true);
		}
	}

	this.setParams = function()
	{
		var RetVal = this.getValidationAttribute('params');
		if (RetVal != null)
		{
			return RetVal.split(',');
		}
	}
	
	this.setDefault = function()
	{
		return this.getValidationAttribute('default');
	}

	this.setRequired = function()
	{
		var RetVal = this.getValidationAttribute('required');
		RetVal = new Boolean(RetVal == 'true');
		return RetVal;
	}
	
	this.setMessage = function()
	{
		var RetVal = this.getValidationAttribute('message');
		if (RetVal != null)
		{
			debugTrace('Custom message found: ' + RetVal);
		}
		return RetVal;
	}

	this.setErrorMessage = function()
	{
		var RetVal = this.getValidationAttribute('errormessage');
		if (RetVal != null)
		{
			debugTrace('Custom error message found: ' + RetVal);
		}
		else
		{
			RetVal = this.message;
		}
		return RetVal;
	}
	
	this.setOmmissionMessage = function()
	{
		var RetVal = this.getValidationAttribute('ommissionmessage');
		if (RetVal != null)
		{
			debugTrace('Custom ommission message found: ' + RetVal);
		}
		else
		{
			RetVal = this.message;
		}
		return RetVal;
	}

	this.setDomain = function()
	{
		var RetVal = this.getValidationAttribute('domain');
		if (RetVal == null)
		{
			RetVal = this.formElement.type;
		}
		else
		{
			debugTrace('custom domain found: ' + RetVal);
		}
		loadDomain(RetVal);
		return RetVal;
	}
	
	this.getValidationAttribute = function(aIdent)
	{
		var Retval = this.formElement.getAttribute('p80fv:'+aIdent);
		return Retval;
	}
	
	this.findDependedElements = function(aID)
	{
		this.dependedObjects = new Array();
		var aValElm = null;
		debugTrace('Looking for depended objects for element with ID: ' + aID);
		for(var i=0,aElm;aElm = this.parentForm.elements[i];i++)
		{
			var thisDependsOnID = aElm.getAttribute('p80fv:dependson');
			if (thisDependsOnID == aID)
			{
				var aValContainer = this.findDependedObjectContainer(aElm);
				aValElm = new validatedElement(this.parentForm,aElm,this.container);
				aValElm.initialise();
				if (aValContainer.required)
				{
					debugTrace('Depended object with required attribute! : '+aElm.name,true);
				}
				aValContainer.addElement(aValElm);
				debugTrace('Found depended object: '+aElm.name);
			}
		}
	}

	this.findDependedObjectContainer = function(aFormElement)
	{
		var retVal = null;
		for (var i,aValElm;aValElm=this.dependedObjects[i];i++)
		{
			if (aValElm.name == aFormElement.name)
			{
				retVal = aValElm;
				break;
			}
		}
		if (retVal == null)
		{
			retVal = new validationContainer(aFormElement.name,this.container.validateonblur);
			this.dependedObjects[this.dependedObjects.length] = retVal;
		}
		return retVal;
	}
}

/*----------------------------------------------------------------------*/

function validationObject(aName)
{
	this.instanceName = aName;
	this.validationFunctions = new Object();

	this.validationResults = new Array();
	this.validationResults[0] = 'valid';
	this.validationResults[1] = 'invalid';
	this.validationResults[2] = 'empty';
	this.validationResults[3] = 'ignore';
}

validationObject.prototype.trim = function(str)
{
  str=str.replace(/^\s*(.*)/, "$1");
  str=str.replace(/(.*)\s*$/, "$1");
  return str;
}

validationObject.prototype.elementHasDefaultValue = function(aElement)
{
	return ((aElement.defaultValue != null) && (aElement.formElement.value == aElement.defaultValue));
}

validationObject.prototype.formElementIsUsed = function(aElement) {
	var aFormElement = aElement.formElement;
	if (aFormElement.type) {
		switch (aFormElement.type) {
			case 'checkbox':
				return aFormElement.checked;
				break;
			case 'radio':
				var elements = document.forms[aFormElement.form.name].elements, name = aElement.name;
				for (var index = 0; index < elements.length; index++) {
					var element = elements[index];
						if (element.name == name && element.checked == true) {
						return true;
					}
				}
				return false;
				break;
			case 'hidden':
				return ((this.trim(aFormElement.value).length > 0) && (!this.elementHasDefaultValue(aElement)));
				break;
			case 'file':
				return ((this.trim(aFormElement.value).length > 0) && (!this.elementHasDefaultValue(aElement)));
				break;
			case 'text':
				return ((this.trim(aFormElement.value).length > 0) && (!this.elementHasDefaultValue(aElement)));
				break;
			case 'textarea':
				return ((this.trim(aFormElement.value).length > 0) && (!this.elementHasDefaultValue(aElement)));
				break;
			case 'select':
				return ((aFormElement.options.selectedIndex > -1) && (!this.elementHasDefaultValue(aElement)));
				break;
			case 'select-one':
				return ((aFormElement.options.selectedIndex > -1) && (!this.elementHasDefaultValue(aElement)));
				break;
			case 'select-multiple':
				return ((aFormElement.options.selectedIndex > -1) && (!this.elementHasDefaultValue(aElement)));
				break;
			default:
				alert("Unknown");
				return false;
				break;
		}
	}
	else {
		var Retval = false;
		for (var i = 0, aBtn; aBtn = aFormElement[i]; i++) {
			if (aBtn.checked) {
				Retval = true;
				break;
			}
		}
		return Retval;
	}
}

validationObject.prototype.validateContainer = function(aContainer,executeSilent)
{
	var thisValidation = 'invalid';

	for (var i=0,aValElm;aValElm=aContainer.validationElements[i];i++)
	{
		thisValidation = this.validateElement(aValElm);
		if (thisValidation == this.validationResults[0]) //valid
		{
			break;
		}
	}

	if (executeSilent == null)
	{
		if (thisValidation ==  this.validationResults[1]) //invalid
		{
			this.reportValidationError(aContainer.validationElements[0]);
		}
		else if (thisValidation ==  this.validationResults[2]) //empty
		{
			this.reportOmmissionError(aContainer.validationElements[0]);
		}
	}

	switch(thisValidation)
	{
		case 'valid': return true;
		case 'ignore': return false;
		case 'invalid': return false;
		case 'empty': return false;
	}
}

validationObject.prototype.dispatchValidation = function(aElement)
{
	try
	{
		var aValidationFunc = this.validationFunctions[aElement.domain];
		if (typeof(aValidationFunc) == 'function')
		{
			return aValidationFunc(aElement);
		}
		else
		{
			debugTrace("No valid function found for "+aElement.domain+" validation!<br/>script file was probably not found, check p80fv:scriptpath attribute",true);
			return false;
		}
	}
	catch(e)
	{
		debugTrace(e.description);
		return false;
	}
}

validationObject.prototype.validateElement = function(aElement)
{
	debugTrace('validating ' + aElement.name + ', type is ' + aElement.domain);
	var thisValidation = false;
	if (aElement.validateDependenciesWhen == null)
	{
		if ((aElement.required == true) && (!this.formElementIsUsed(aElement)))
		{
			return this.validationResults[2]; //empty
		}
		else if ((aElement.required == true) && (this.formElementIsUsed(aElement)))
		{
			 thisValidation = this.dispatchValidation(aElement);
			 return (thisValidation) ? this.validationResults[0] : this.validationResults[1]; // valid/invalid
		}
		else if (this.formElementIsUsed(aElement))
		{
			thisValidation = this.dispatchValidation(aElement);
			return (thisValidation) ? this.validationResults[0] : this.validationResults[1]; // valid/invalid
		}
		else
		{
			return this.validationResults[0];
		}
	}
	else if (aElement.validateDependenciesWhen != null)
	{
		thisValidation = this.dispatchValidation(aElement);
		if (((aElement.validateDependenciesWhen == true) && (thisValidation == true)) || ((aElement.validateDependenciesWhen == false) && (!this.formElementIsUsed(aElement))))
		{
			if (aElement.dependedObjects != null)
			{
				for(var i=0,aElm;aElm=aElement.dependedObjects[i];i++)
				{
					if(this.validateContainer(aElm) == false)
					{
						return this.validationResults[3]; //ignore
						break;
					}
				}
				return this.validationResults[0]; //valid
			}
			else
			{
				debugTrace(aElement.name + ' has no depended object list!',true);
				return this.validationResults[0]; //valid
			}
		}
		else
		{
			return this.validationResults[0]; //valid
		}
	}
	else
	{
		return this.validationResults[0]; //valid
	}
}

validationObject.prototype.reportValidationError = function(aValidationElement)
{
	if (typeof(handleValidationError) == 'undefined')
	{
		if (aValidationElement.errorMessage == null)
		{
			if (typeof(errorMessages[aValidationElement.domain]) != 'undefined')
			{
				if (typeof(errorMessages[aValidationElement.domain]['error']) != 'undefined')
				{
					alert(errorMessages[aValidationElement.domain]['error']);
				}
				else
				{
					alert(errorMessages[aValidationElement.domain]);
				}
			}
			else
			{
				alert('Veld is ongeldig');
			}
		}
		else
		{
			alert(aValidationElement.errorMessage);
		}
		try
		{
			aValidationElement.formElement.focus();
		}
		catch(e)
		{
			debugTrace(e.description,true);
		}
	}
	else
	{
		handleValidationError(aValidationElement);
	}
	return false;
}

validationObject.prototype.reportOmmissionError = function(aValidationElement)
{
	if (typeof(handleOmmissionError) == 'undefined')
	{
		if (aValidationElement.ommissionMessage == null)
		{
			if (typeof(errorMessages[aValidationElement.domain]) != 'undefined')
			{
				if (typeof(errorMessages[aValidationElement.domain]['omitted']) != 'undefined')
				{
					alert(errorMessages[aValidationElement.domain]['omitted']);
				}
				else
				{
					alert(errorMessages[aValidationElement.domain]);
				}
			}
			else
			{
				alert('Veld is verplicht');
			}
		}
		else
		{
			alert(aValidationElement.ommissionMessage);
		}
		try
		{
			aValidationElement.formElement.focus();
		}
		catch(e)
		{
			debugTrace(e.description,true);
		}
	}
	else
	{
		handleOmmissionError(aValidationElement);
	}
	return false;
}

validationObject.prototype.registerValidationFunction = function(aKey,funcPtr)
{
	this.validationFunctions[aKey] = funcPtr;
}