// #########################################################
// -- KLASSE AbstractValidateableObject --
function AbstractValidateableObject(){}
AbstractValidateableObject.prototype.errorHandler = -1;
AbstractValidateableObject.prototype.validator = -1;
AbstractValidateableObject.prototype.validate = function(){
	var ok = this.validator.validate(this);
	if(this.errorHandler){
		if(!ok) this.errorHandler.onError(this);
		else	this.errorHandler.onNoError(this);
	}
	return ok;
}

// #########################################################
// -- KLASSE Field --
function Field(fieldName, validator, opt_errorHandler, opt_formName){
	this.fieldName = fieldName;
	this.validator = validator;
	this.errorHandler = opt_errorHandler;
	this.formName = opt_formName ? opt_formName : -1;
}Field.prototype = new AbstractValidateableObject();
Field.prototype.getFormObject = function(){
	return self.document.forms[this.formName];
}
Field.prototype.getFieldObject = function(){
	return this.getFormObject().elements[this.fieldName];
}

// #########################################################
// -- KLASSE AbstractFieldCollection --
function AbstractFieldCollection(){}
AbstractFieldCollection.prototype = new AbstractValidateableObject();
AbstractFieldCollection.prototype.validationObjects = -1;

// #########################################################
// -- KLASSE Form --
function Form(formName, valObjects, submitAction, opt_errorHandler){
	this.formName = formName;
	this.submitAction = submitAction;
	this.errorHandler = opt_errorHandler;
	this.validationObjects = valObjects;
	this.validator = new FormValidator();

	// In allen Validations-Objekten vom Typ Field das Formular und den ErrorHandler setzen
	if(valObjects){
		for(var i=0; i<valObjects.length; i++){
			if(valObjects[i].formName == -1) valObjects[i].formName = this.formName;
			if(valObjects[i].errorHandler == -1) valObjects[i].errorHandler = this.errorHandler;
		}
	}
}Form.prototype = new AbstractFieldCollection();
Form.prototype.validate = function(){
	var ok = this.validator.validate(this);
	if(this.errorHandler){
		if(!ok) this.errorHandler.onError(this);
		else	this.errorHandler.onNoError(this);
	}
	if(ok && this.submitAction && this.submitAction.onSuccess)
		this.submitAction.onSuccess();
	return ok;
}
// #########################################################
// -- KLASSE AbstractErrorHandler --
function AbstractErrorHandler(){}
AbstractErrorHandler.prototype.stopOnError = true;
AbstractErrorHandler.prototype.focus = function(valObj){
	var elm = valObj.getFieldObject ? valObj.getFieldObject() : false;
	if(elm){
		if(elm[0] && elm[0].type=='radio') elm[0].focus(); else elm.focus();
	}
}

// #########################################################
// -- KLASSE AlertErrorHandler --
function AlertErrorHandler(errorText){
	this.errorText = errorText;
}AlertErrorHandler.prototype = new AbstractErrorHandler();
AlertErrorHandler.prototype.onError = function(valObj){
	alert(this.errorText);
	this.focus(valObj);
}
AlertErrorHandler.prototype.onNoError = function(valObj){};
AlertErrorHandler.prototype.onEnd = function(valObj){};

// #########################################################
// -- KLASSE CompositeAlertErrorHandler --
function CompositeAlertErrorHandler(errorText){
	this.errorText = errorText;
	this.stopOnError = false;
}CompositeAlertErrorHandler.prototype = new AbstractErrorHandler();
CompositeAlertErrorHandler.prototype.fieldNames = new Array();
CompositeAlertErrorHandler.prototype.onError = function(valObj){
alert("composite-error");
	this.fieldNames.push(valObj.fieldName);
}
CompositeAlertErrorHandler.prototype.onNoError = function(valObj){}
CompositeAlertErrorHandler.prototype.onEnd = function(valObj){
	var text = this.errorText+"\n\n";
	for(var i=0;i<this.fieldNames.length;i++)
		text += this.fieldNames[i]+"\n";

	alert(text);
}

// ####################################
// -- KLASSE OnwSubmitAction --
function OnwSubmitAction(windowSettings, formName){
this.settings = windowSettings;
this.formName = formName;
}
OnwSubmitAction.prototype.onSuccess = function(){
	 // ONW(settings, opt_URL, opt_formName
return ONW(this.settings, '', this.formName) ? true : false;
}
OnwSubmitAction.prototype.setFormName = function(formName){
this.formName = formName;
}
// ####################################
// -- KLASSE TargetSubmitAction --
function TargetSubmitAction(target, opt_doSubmit){
this.target = target;
this.formName = null;
this.doSubmit = opt_doSubmit ? true : false;
}
TargetSubmitAction.prototype.onSuccess = function(){
this.formRef.target = this.target;
return true;
}
TargetSubmitAction.prototype.setFormName = function(formRef){
this.formRef = formRef;
}

// #########################################################
// -- KLASSE FormValidator --
function FormValidator(){}
FormValidator.prototype.validate = function(valObj){
	var noErrors = true;
	for(var i=0;i<valObj.validationObjects.length;i++){
		if(!valObj.validationObjects[i].validate()){
			noErrors = false;
			if(!valObj.errorHandler || (valObj.errorHandler && valObj.errorHandler.stopOnError)) return noErrors;
		}
	}
	if(!noErrors && valObj.errorHandler) valObj.errorHandler.onEnd(valObj);

	return noErrors;
}

// ####################################
// -- KLASSE AbstractFieldValidator --
function AbstractFieldValidator(){}
AbstractFieldValidator.prototype.className = "";
AbstractFieldValidator.prototype.forElementTypes = new Array(0);
AbstractFieldValidator.prototype.testElementType = function(valObj){
	var elementRef = valObj.getFieldObject();
	if(elementRef){
		var type = elementRef.type ? elementRef.type : (elementRef.length && elementRef.length>0 ? elementRef[0].type : null);
		if(type){
			var l = this.forElementTypes.length;
			var typeSupported = false;
			for(var i=0; i<l; i++){
				if(type == this.forElementTypes[i]){
					typeSupported = true;
					break;
				}
			}
			if(!typeSupported){
				alert(this.className+": Element type '"+type+"' is not supported by this validator.");
				return false;
			}
			else return type;
		}else{
			alert(this.className+": Element is not a form-object.");
			return false;
		}
	}else{
		alert(this.className+": Element is null.");
		return false;
	}
}
AbstractFieldValidator.prototype.getClassName = function(){
	return this.className;
}

// ####################################
// -- KLASSE RegExpValidator --
function RegExpValidator(regExpression){
	this.regExpression = regExpression;
}RegExpValidator.prototype = new AbstractFieldValidator();
RegExpValidator.prototype.className = "RegExpValidator";
RegExpValidator.prototype.forElementTypes = new Array("text", "textarea", "password");
RegExpValidator.prototype.regExpression = -1;
RegExpValidator.prototype.validate = function(valObj){
	var elementReference = valObj.getFieldObject();
	if(this.testElementType(valObj)){
		if(elementReference.value == "") return true;
		return this.regExpression.exec(elementReference.value);
	}
}
// ####################################
// -- KLASSE EmailValidator --
function EmailValidator(){
	this.className = "EmailValidator";
	this.regExpression = /^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/;
}EmailValidator.prototype = new RegExpValidator();

// ####################################
// -- KLASSE RequiredValidator --
function RequiredValidator(){
}RequiredValidator.prototype = new AbstractFieldValidator();
RequiredValidator.prototype.className = "RequiredValidator";
RequiredValidator.prototype.forElementTypes = new Array("text", "textarea", "password", "select-one", "select-multiple", "radio", "checkbox");
RequiredValidator.prototype.validate = function(valObj){
	if(this.testElementType(valObj)){
		return requiredFormfieldCheck(valObj.getFieldObject());
	}
	return false;
}

// #########################################################################
// -- KLASSE ChoiceValidator --

function ChoiceValidator(negationSymbol, opt_Value){
	// -- Attribute --
	this.className = "ChoiceValidator";
	this.forElementTypes = new Array("select-one", "select-multiple", "radio", "checkbox");
	this.negationSymbol = negationSymbol;
	this.value = opt_Value;

}ChoiceValidator.prototype = new AbstractFieldValidator();

ChoiceValidator.prototype.validate = function(valObj){
	var type;
	if(type = this.testElementType(valObj)){
		var elementRef = valObj.getFieldObject();
		switch(type){
			case "checkbox":
				return elementRef.checked == this.negationSymbol;
				break;
			case "select-one":
				var value = elementRef.options[elementRef.selectedIndex].value;
				return this.negationSymbol ? value == this.value : !(value == this.value);
				break;
			case "select-multiple":
				return true;
				break;
			case "radio":
				var l = elementRef.length;
				for(var i=0; i<l; i++){
					if(elementRef[i].checked)
						return this.negationSymbol ? elementRef[i].value == this.value : elementRef[i].value != this.value;
				}
				// Keines angekreuzt:
				return !this.negationSymbol;
				break;
		}
	}
}

// #########################################################################
// -- KLASSE NumericValidator --

function NumericValidator(){
	this.className = "NumericValidator";
	this.regExpression = /^\d+$/;
}
NumericValidator.prototype = new RegExpValidator();

// #########################################################################
// -- KLASSE LengthValidator --

function LengthValidator(minCharacters, maxCharacters){
	this.className = "LengthValidator";
	//this.regExpression = /^.{,}$/;
}
LengthValidator.prototype = new RegExpValidator();

// #########################################################################
// -- KLASSE AbstractDateValidator --

function AbstractDateValidator(minCharacters, maxCharacters){
	this.className = "AbstraceDateValidator";
	this.regExpression = /^.*$/;
}
AbstractDateValidator.prototype = new RegExpValidator();

AbstractDateValidator.prototype.isDate = function(day, month, year){
	var isDate = true;
	if(day <= 0 || month <= 0 || year <= 0)
		isDate = false;
	else{
		switch(month)	{
			case 4:	case 6:	case 9:	case 11:
				if(day>30)	isDate = false;
				break;
			case 1:	case 3:	case 5:	case 7: case 8: case 10: case 12:
				if(day>31)	isDate = false;
				break;
			case 2:
				if(day>29)	isDate = false;
				break;
			default: // monat<1 oder > 12 -> Fehler
				isDate = false;
				break;
		}
		// 29.2. - Schaltjahr-Check
		if(day==29 && month==2 && (year%4)!=0) isDate = false;
	}

	return isDate;
}

// #########################################################################
// -- KLASSE DateValidator --

function DateValidator(){
	this.className = "DateValidator";
	this.regExpression = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/;
}
DateValidator.prototype = new AbstractDateValidator();

DateValidator.prototype.validate = function(valObj){
	if(this.testElementType(valObj)){
		var elementReference = valObj.getFieldObject();
		// Leere sind immer erlaubt!
		if(elementReference.value == "")
			return true;
		if(this.regExpression.exec(elementReference.value)){
			if(this.isDate(parseInt(RegExp.$1), parseInt(RegExp.$2), parseInt(RegExp.$3)))
				return true;
		}
		return false;
	}
}
