/*
	Base, version 1.0.2
	Copyright 2006, Dean Edwards
	License: http://creativecommons.org/licenses/LGPL/2.1/
	
	http://dean.edwards.name/weblog/2006/03/base/
	http://dean.edwards.name/base/Base.js
*/

var Base = function() {
	if (arguments.length) {
		if (this == window) { // cast an object to this class
			Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
		} else {
			this.extend(arguments[0]);
		}
	}
};

Base.version = "1.0.2";

Base.prototype = {
	extend: function(source, value) {
		var extend = Base.prototype.extend;
		if (arguments.length == 2) {
			var ancestor = this[source];
			// overriding?
			if ((ancestor instanceof Function) && (value instanceof Function) &&
				ancestor.valueOf() != value.valueOf() && /\bbase\b/.test(value)) {
				var method = value;
			//	var _prototype = this.constructor.prototype;
			//	var fromPrototype = !Base._prototyping && _prototype[source] == ancestor;
				value = function() {
					var previous = this.base;
				//	this.base = fromPrototype ? _prototype[source] : ancestor;
					this.base = ancestor;

					var returnValue = method.apply(this, arguments);
					this.base = previous;
					return returnValue;
				};
				// point to the underlying method
				value.valueOf = function() {
					return method;
				};
				value.toString = function() {
					return String(method);
				};
			}
			return this[source] = value;
		} else if (source) {
			var _prototype = {toSource: null};
			// do the "toString" and other methods manually
			var _protected = ["toString", "valueOf"];
			// if we are prototyping then include the constructor
			if (Base._prototyping) _protected[2] = "constructor";
			for (var i = 0; (name = _protected[i]); i++) {
				if (source[name] != _prototype[name]) {
					extend.call(this, name, source[name]);
				}
			}
			// copy each of the source object's properties to this object
			for (var name in source) {
				if (!_prototype[name]) {
					extend.call(this, name, source[name]);
				}
			}
		}
		return this;
	},

	base: function() {
		// call this method from any other method to invoke that method's ancestor
	}
};

Base.extend = function(_instance, _static) {
	var extend = Base.prototype.extend;
	if (!_instance) _instance = {};
	// build the prototype
	Base._prototyping = true;
	var _prototype = new this;
	extend.call(_prototype, _instance);
	var constructor = _prototype.constructor;
	_prototype.constructor = this;
	delete Base._prototyping;
	// create the wrapper for the constructor function
	var klass = function() {
		if (!Base._prototyping) constructor.apply(this, arguments);
		this.constructor = klass;
	};
	klass.prototype = _prototype;
	// build the class interface
	klass.extend = this.extend;
	klass.implement = this.implement;
	klass.toString = function() {
		return String(constructor);
	};
	extend.call(klass, _static);
	// single instance
	var object = constructor ? klass : _prototype;
	// class initialisation
	if (object.init instanceof Function) object.init();
	return object;
};

Base.implement = function(_interface) {
	if (_interface instanceof Function) _interface = _interface.prototype;
	this.prototype.extend(_interface);
};



/****************************************************************************
 * BaseValidator *
 * Composite-Pattern: FormValidatoren und FieldValidatoren sind BaseValidators
 ****************************************************************************/
 
/*

TODO: 
HugeDepending: validateWithSameCondition wurde gelöscht

====================================
VI-Validator
====================================
Object-Diagramm:
				BaseValidator
				^							^
	FormValidator			FieldValidator
											^
										TextfieldValidator (Sample)
*/

var Constants = new Object();
Constants.FIELD_VALIDATOR = "fieldValidator";
Constants.FORM_VALIDATOR = "formValidator";

/****************************************************************************
 * BaseValidator *
 * Composite-Pattern: FormValidatoren und FieldValidatoren sind BaseValidators
 ****************************************************************************/
 
var BaseValidator = Base.extend({
	constructor: function() {
	 this.result = null;
	},

	/* PRIVATE
	 * Markiere Element als fehlerhaft
	 */
	markInvalid: function(){},

	/* PRIVATE
	 * Setze Fehlermarkierung zurück
	 */
	resetMarks: function(){ this.result = null; },

	/* PROTECTED
	 * Führe Validierung für ein Element durch
	 */
	doValidation: function(){},
	
	/* PRIVATE
	 * Liefere Type für Validator
	 */
	type: function() { return Constants.FIELD_VALIDATOR;},

	/* PROTECTED
	 * Liefere Type für Validator
	 */
	getRootFormValidator: function() { 
		var obj = this;

		while(obj.formValidator)
		{
			obj = obj.formValidator;
		}

		return obj;
	}
});
 

/****************************************************************************
 * FormValidator *
 ****************************************************************************/
var formValidatorNr = 0;

var FormValidator = BaseValidator.extend({

	/* PUBLIC
	 * Constructor
	 */
    constructor: function() {
	this.config = new Object();
	this.config.id = "formValidator"+(formValidatorNr++);
	this.validators = new Object();
	this.fields = new Array();
    },
    
	/* PRIVATE
	 * Liefert Typ
	 */
    type : function() { return Constants.FORM_VALIDATOR;},


	/* PROTECTED
	 * Führt Validierung für Validator durch
	 */
	doValidation : function(markInvalid) {

		debugIn("FormValidator.prototype.doValidation; Fields = " + this.fields+" id="+this.config.id);

		var result = null;
		var rootFormValidator = this.getRootFormValidator();

		for (var i=0;i<this.fields.length;i++)
		{		
			var validator = this.validators[ this.fields[i] ];
			var resultCondition = validator.condition.condition();

			debug("Validate Field: " +  this.fields[i] + "; resultCondition = " + resultCondition);

			// Validierung wird nur vorgenommen, wenn die Condition erfüllt ist
			if(resultCondition)
			{
				validator.result = validator.doValidation(markInvalid);

				debug("Validate Field: " +  this.fields[i] + "; resultCondition = " + resultCondition+" validationResult="+validator.result+" markInvalid="+markInvalid);
				if (validator.result!=null && markInvalid!=false){

					validator.markInvalid(result);

					if (rootFormValidator.summaryIdElement)
					{
						rootFormValidator.summaryMessage += validator.appendSummaryMessage(rootFormValidator.summaryMessage);
					}

					if (rootFormValidator.doShowAlert)
					{
					    rootFormValidator.alertMessage += validator.appendAlertMessage(rootFormValidator.alertMessage);
					}
				}
				result = validator.result ? validator.result : result;


				debug("result = " + result); 
			}

		}

		if (result && this.summaryIdElement) {
			var summaryDiv = document.getElementById(this.summaryIdElement);
			removeCSSClass(summaryDiv, "summary-hidden");
			removeCSSClass(summaryDiv, "summary-shown");
			addCSSClass(summaryDiv, "summary-shown");
		}

		debugOut("FormValidator.prototype.doValidation; return = " + result);
		return result;
	},


	appendSummaryMessage : function(msg)
	{		
		return "";
	},
	
	appendAlertMessage: function()
	{
		return "";
	},

	resetMarks : function()
	{
		this.result = null;
		if (this.summaryIdUl && document.getElementById(this.summaryIdUl)) document.getElementById(this.summaryIdUl).innerHTML = "";

		if (this.alertIntroduction) this.alertMessage = "";

		for (var i=0;i<this.fields.length;i++)
		{
			this.validators[ this.fields[i] ].resetMarks();
		}
	},


	resetMandatory : function(label, span, _char)
	{
		for (var i=0;i<this.fields.length;i++)
		{
			this.validators[ this.fields[i] ].resetMandatory(label, span, _char);
		}
	},

	markMandatory : function (label, span, _char)
	{
		debugIn("FormValidator.prototype.markMandatory");

		for(var i=0; i<this.fields.length; i++){

			var validator = this.validators[ this.fields[i] ];

			validator.resetMandatory(label, span, _char);

			if(validator.condition.condition()){
				validator.markMandatory(label, span, _char);
			}
		}

		debugOut("FormValidator.prototype.markMandatory");
	},


	addValidator : function(fieldValidator)
	{
		this.addConditionalValidator(new ConditionTrue(), fieldValidator);
	},


	addConditionalValidator : function(condition, validator)
	{
		var fieldId = validator.config.id;
		this.validators[fieldId] = validator;
		this.fields[this.fields.length] = fieldId;
		validator.formValidator = this;
		validator.condition = condition;
	},

	addNotMandatoryValidator : function(fieldValidator)
	{
		formValidator.addConditionalValidator(new ConditionIfNotEmpty(fieldValidator.config.id), fieldValidator)
	}

});





/****************************************************************************
 * RootFormValidator 
 *
 * Es gibt genau einen RootFormValidator pro Formular, das validiert werden soll
 ****************************************************************************/
var RootFormValidator = FormValidator.extend({

	/* PUBLIC
	 * Constructor
	 */
	constructor: function()
	{
		this.config = new Object();
		this.config.id = "formValidator"+(formValidatorNr++);

		this.markLabels = false;
		this.showMessageForFields = false;
		this.highlightFields = false;

		this.validators = new Object();
		this.fields = new Array();
	},

	/* PUBLIC
	 * Wenn mit nicht-NULL aufgerufen wird ein Javascript-Alert mit Meldung alertIntroduction
	 * bei Fehlern ausgegeben, prefixForEachError wird vor jeden Fehler gesetzt (z.B. "* ")
	 */
	showSummary : function (idOfULElement)
	{
		this.summaryIdElement = idOfULElement;
		this.summaryIdUl = idOfULElement + "-ul";
	},

	/* PUBLIC
	 * Wenn mit nicht-NULL aufgerufen wird ein Javascript-Alert mit Meldung alertIntroduction
	 * bei Fehlern ausgegeben, prefixEachError wird vor jeden Fehler gesetzt (z.B. "* ")
	 */
	showAlert : function (alertIntroduction, prefixEachError)
	{
		this.doShowAlert = true;
		this.alertIntroduction = alertIntroduction;
		this.prefixEachError = prefixEachError;
		this.alertMessage = "";
	},

	/* PUBLIC
	 * Führt die Validierung durch. Wenn markInvalid undefined oder true ist, dann werden die
	 * invaliden Felder markiert
	 */
	validate : function(markInvalid) {

		debugIn("<b>RootFormValidator.prototype.validate; markInvalid = " + markInvalid + "</b> id="+this.config.id);


		var result = null;
		var rootFormValidator = this;

		this.summaryMessage = "";
		this.alertMessage = "";


		result = this.doValidation(markInvalid);

		if (result && this.summaryIdElement) {
			var summaryDiv = document.getElementById(this.summaryIdElement);
				removeCSSClass(summaryDiv, "summary-hidden");
				removeCSSClass(summaryDiv, "summary-shown");
				addCSSClass(summaryDiv, "summary-shown");
		    var summary = document.getElementById(this.getRootFormValidator().summaryIdUl);	
		    if (summary) summary.innerHTML = this.summaryMessage;
		}

		if(this.doShowAlert && result!=null) {
			var alertIntroduction = this.alertIntroduction ?  this.alertIntroduction + "\n" : "";
			alert(unescape(alertIntroduction + this.alertMessage)); 
		}

		debugOut("<b>RootFormValidator.prototype.validate; return = " + eval(result == null) + "</b>");
		debug("--------------------------------------------------------------------");
		return result;
	},


	/* PRIVATE
	 * Liefert den Typ des Validators
	 */
	type : function() { return Constants.FORM_VALIDATOR;}
});

/****************************************************************************
 * FieldValidator *
 ****************************************************************************/
var FieldValidator = BaseValidator.extend({

	constructor : function(config) {
		this.config = config;
		this.formValidator = null;
		this.errorMessage = null;
		this.summaryMessage = null;
		this.validationResult = null;
	},

	/*
	 * resetMarks
	 * Reset the CSS-Classes
	 */
	resetMarks : function() {

		this.result = null;

		if (document.getElementById(this.config.id + "-error") && this.getRootFormValidator().showMessageForFields)
		{
			var message = document.getElementById(this.config.id + "-error");
			message.innerHTML = "";
			removeCSSClass(message, "validator-error-shown");
		removeCSSClass(message, "validator-error-hidden");
		addCSSClass(message, "validator-error-hidden");
		}

		if (document.getElementById( this.config.id +"-label") && this.getRootFormValidator().markLabels)
		{
			var label = document.getElementById( this.config.id + "-label");
			removeCSSClass(label, "validator-error-shown");
		removeCSSClass(label, "validator-error-hidden");
		addCSSClass(label, "validator-error-hidden");
		}


		if (document.getElementById( this.config.id) && this.getRootFormValidator().highlightFields)
		{
			var highlight = document.getElementById(this.config.id);
			removeCSSClass(highlight, "validator-highlight-shown");
		removeCSSClass(highlight, "validator-highlight-hidden");
		addCSSClass(highlight, "validator-highlight-hidden");
		}

		if (this.summaryIdElement) {
		var summaryDiv = document.getElementById(this.summaryIdElement);
			removeCSSClass(summaryDiv, "summary-shown");
			removeCSSClass(summaryDiv, "summary-hidden");
			addCSSClass(summaryDiv, "summary-hidden");
		}
	},

	/*
	 * markInvalid
	 * Set the Invalid-CSS-Classes
	 */
	markInvalid : function() {

		if (document.getElementById(this.config.id + "-error") && this.getRootFormValidator().showMessageForFields)
		{
			var message = document.getElementById(this.config.id + "-error");
			message.innerHTML = this.getErrorMessage();
			removeCSSClass(message, "validator-error-shown");
			removeCSSClass(message, "validator-error-hidden");
			addCSSClass(message, "validator-error-shown");
		}


		if (document.getElementById( this.config.id +"-label") && this.getRootFormValidator().markLabels)
		{
			var label = document.getElementById(this.config.id + "-label");
			removeCSSClass(label, "validator-error-shown");
			removeCSSClass(label, "validator-error-hidden");
			addCSSClass(label, "validator-error-shown");
		}


		if (document.getElementById(this.config.id) && this.getRootFormValidator().highlightFields)
		{
			var highlight = document.getElementById(this.config.id);
			removeCSSClass(highlight, "validator-highlight-shown");
			removeCSSClass(highlight, "validator-highlight-hidden");
			addCSSClass(highlight, "validator-highlight-shown");
		}
	},

	/*
	 * resetMandatory
	 */
	resetMandatory : function(label, span, _char) {

		if (document.getElementById(this.config.id + "-label") && label==true)
		{
			var mandatoryElem = document.getElementById(this.config.id + "-label");
			removeCSSClass(mandatoryElem, "validator-mandatory-label-shown");
		removeCSSClass(mandatoryElem, "validator-mandatory-label-hidden");
		addCSSClass(mandatoryElem, "validator-mandatory-label-hidden");
		}

		if (document.getElementById(this.config.id + "-mandatory-char") && span==true)
		{
			var mandatoryElem = document.getElementById(this.config.id + "-mandatory-char");
			removeCSSClass(mandatoryElem, "validator-mandatory-char-shown");
		removeCSSClass(mandatoryElem, "validator-mandatory-char-hidden");
		addCSSClass(mandatoryElem, "validator-mandatory-char-hidden");
		}

		if (document.getElementById(this.config.id + "-label") && typeof(_char) == "string")
		{
			var labelElem = document.getElementById(this.config.id + "-label");
			labelElem.innerHTML = labelElem.innerHTML.replace(_char, "");
		}
	},

	/*
	 * markMandatory
	 */
	markMandatory : function(label, span, _char) {

		if (document.getElementById(this.config.id + "-label") && label==true)
		{
			var mandatoryElem = document.getElementById(this.config.id + "-label");
			removeCSSClass(mandatoryElem, "validator-mandatory-label-shown");
			removeCSSClass(mandatoryElem, "validator-mandatory-label-hidden");
			addCSSClass(mandatoryElem, "validator-mandatory-label-shown");
		}

		if (document.getElementById(this.config.id + "-mandatory-char") && span==true)
		{
			var mandatoryElem = document.getElementById(this.config.id + "-mandatory-char");
			removeCSSClass(mandatoryElem, "validator-mandatory-char-shown");
			removeCSSClass(mandatoryElem, "validator-mandatory-char-hidden");
			addCSSClass(mandatoryElem, "validator-mandatory-char-shown");
		}

		if (document.getElementById(this.config.id + "-label") && typeof(_char) == "string")
		{
			var labelElem = document.getElementById(this.config.id + "-label");
			labelElem.innerHTML = labelElem.innerHTML + _char;
		}
	},


	/* PRIVAT
	 * Hängt für jeden untergeordneten Validator die Fehlermeldungen an der Alert Message an
	 */
	appendSummaryMessage : function() 
	{
		var oldString = "";
		for(var i; i<this.fields.length; i++) 	oldString += this.validators[ thisfields [i] ].appendSummaryMessage();
		return oldString;
	},

	/* PRIVAT
	 * Hängt für jeden untergeordneten Validator die Fehlermeldungen an der Alert Message an
	 */
	appendAlertMessage : function() 
	{
		var oldString = "";
		for(var i; i<this.fields.length; i++) oldString += this.validators[ thisfields [i] ].appendAlertMessage();
		return oldString;
	},


	/* PRIVAT
	 * Hängt am Summary Element eine Fehlermessage an, wenn für den aktuellen Validator
	 * eine gespeichert ist
	 */
	appendSummaryMessage : function() {

	    var summary =  this.getSummaryMessage();
	    return summary ? "<li>" + summary + "</li>" : oldSummary;
	},

	/* PRIVAT
	 * Hängt an der Alert Message eine Fehlermessage an, wenn für den aktuellen Validator
	 * eine gespeichert ist
	 */
	appendAlertMessage : function() {

	    var prefix = this.getRootFormValidator().prefixEachError ?  this.getRootFormValidator().prefixEachError : "";

	    var summary =  this.getSummaryMessage();

	    return summary ? prefix + summary+"\n" : "";
	},

	/* PRIVAT
	 * Liefert die Fehlermeldung, die neben dem Textfeld angezeigt werden soll.
	 * Je nach Ergebnis der Validierung kann eine unterschiedliche Message angezeigt werden.
	 * Zuerst wird in der Konfiguration des Validators nach error-${validationResult} gesucht, 
	 * Wenn es dieses nicht gibt, dann wird das Attribut error angezeigt
	 */
	getErrorMessage : function() {

	    if(!this.config) return;

	    if(this.config["error-" + this.result]) return this.config["error-" + this.result];
	    else return this.config["error"];
	},

	/* PRIVAT
	 * Liefert die Fehlermeldung, die im Zusammenfassungsbereich angezeigt werden soll
	 * Je nach Ergebnis der Validierung kann eine unterschiedliche Message angezeigt werden.
	 * Zuerst wird in der Konfiguration des Validators nach summary-${validationResult} gesucht, 
	 * Wenn es dieses nicht gibt, dann wird das Attribut summary angezeigt
	 * Gibt es auch dieses nicht, so wird die zugehörige ErrorMessage ausgegeben.
	 */
	getSummaryMessage : function() {

	    if(!this.config) return;

	    if(this.config["summary-" + this.result]) return this.config["summary-" + this.result];
	    else if (this.config["summary"]) return this.config["summary"];
	    else return this.getErrorMessage();
	}
});

/****************************************************************************
 * Validators *
 ****************************************************************************/

/*
 * TextValidator
 */
 var TextFieldValidator = FieldValidator.extend({
 	constructor: function(config) {
		this.config = config;	
	},

	doValidation : function() {
	
		if(!this.config.minLength) this.config.minLength = 1;
		var inputElement = document.getElementById(this.config.id);
		var val_trimmed = trim( inputElement.value );
		var val = inputElement.value;
		if(this.config.rejectDefault && inputElement.value == inputElement.defaultValue) 
			return "defaultValue";
		else if((val_trimmed.length < this.config.minLength))
			return "minLength";		
		else if (this.config.maxLength && val.length > this.config.maxLength)
			return "maxLength";
		else if(this.config.compareWithId && $(this.config.compareWithId) && inputElement.value != $(this.config.compareWithId).value) 
			return "compareWithId";
		else 
			return null;
	}
});
	

/*
 * OneSelectedValidator
 * Discription at work
 */
 var OneSelectedValidator = FieldValidator.extend({
 	constructor: function(config) {
		this.config = config;	
	},

	doValidation : function() {

		//Select-Boxes, Checkboxes					  {				          fuer IE					   }
		if(document.getElementById(this.config.id) && document.getElementById(this.config.id).type!="radio") {
			inputElement = document.getElementById(this.config.id);

			if(inputElement.type=="checkbox") {
				debug("TYP: Checkbox");
				if(inputElement.checked == true) return null;
			}

			if(inputElement.tagName=="SELECT"){
				debug("TYP: Select");
				if(inputElement.value.length>0) return null;
			}
		}

		//Radio-Butttons
		else
		{
			debug("TYP: Radio");
			inputElements = document.getElementsByTagName("INPUT");

			for(var i=0; i<inputElements.length; i++){

				if(inputElements[i].id &&
					inputElements[i].type=="radio" &&
					inputElements[i].id.indexOf(this.config.id + "-")==0 &&
					inputElements[i].checked == true) {
	
					return null;
				}
			}
		}

		return "error";
	}
});

/*
 * RegexValidator
 * Discription at work
 */
 var RegexValidator = FieldValidator.extend({
  	constructor: function(config) {
 		this.config = config;	
 	},

	doValidation : function() {
		var inputElement = document.getElementById(this.config.id);
		if(this.config.regex.test(inputElement.value)) return null;
		else return "error";
	}
});

 var EmailValidator = RegexValidator.extend({
  	constructor: function(config) {
		this.config = config;
		this.config.regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,9})+$/;
	}
});

/*
 * NumberValidator
 * Returns null, if one thing of Checkbox, Radio-Button or Select-Box is selected
 */
var NumberValidator = FieldValidator.extend({
	constructor: function(config) {
		this.config = config;	
	},

	doValidation : function() {

		var inputElement = document.getElementById(this.config.id);
		var value = inputElement.value;
		var result = null;

		if(isEmpty(value)) return "error";

		var isInteger = /^[\+\-]?\d*\.?[Ee]?[\+\-]?\d*$/.test(trim(value));

		if(!isInteger){
			return "format";
		}

		else{
		    if(this.config.min){
		    if(value<this.config.min){
			result = "min";
		    }
		}

		if(this.config.max){
			if(value>this.config.max){
				result = "max";
			}

			if(this.config.min){
				if(value<this.config.min) result = "minmax";
			}
		}
		}

		return result;
	}
});

/*
 * OneSelectedOutOfGroupValidator
 * Discription at work
 */
 var OneSelectedOutOfGroupValidator = FieldValidator.extend({
 	constructor: function(config) {
		this.config = config;	
	},

	doValidation : function() {

		for(var i = 0; i < this.config.ids.length; i++) {
			//Select-Boxes, Checkboxes					  {				          fuer IE					   }
			if(document.getElementById(this.config.ids[i]) && document.getElementById(this.config.ids[i]).type!="radio") {
				inputElement = document.getElementById(this.config.ids[i]);
	
				if(inputElement.type=="checkbox") {
					debug("TYP: Checkbox");
					if(inputElement.checked == true) return null;
				}
	
				if(inputElement.tagName=="SELECT"){
					debug("TYP: Select");
					if(inputElement.value.length>0) return null;
				}
			}
	
			//Radio-Butttons
			else
			{
				debug("TYP: Radio");
				inputElements = document.getElementsByTagName("INPUT");
	
				for(var i=0; i<inputElements.length; i++){

					if(inputElements[i].id &&
						inputElements[i].type=="radio" &&
						inputElements[i].id.indexOf(this.config.ids[i] + "-")==0 &&
						inputElements[i].checked == true) {
		
						return null;
					}
				}
			}
		}
		return "error";
	}
});


/****************************************************************************
 * Conditions *
 ****************************************************************************/
 var Condition = Base.extend({
 	condition: function() {
 		return false;
 	}
 });

var ConditionTrue = Condition.extend({
  	condition: function() {
  		return true;
  	}
 });

/*
 * ConditionIfOneSelected
 * Returns true, if one thing of Checkbox, Radio-Button or Select-Box is selected
 */
var ConditionIfOneSelected = Condition.extend({
	constructor: function(id) {
		this.id = id;	
	},
  	condition: function() {
		//Select-Boxes, Checkboxes
		if(document.getElementById(this.id) && document.getElementById(this.id).type!="radio") {

			inputElement = document.getElementById(this.id);

			if(inputElement.type=="checkbox") {
				//debug("TYP: Checkbox");
				if(inputElement.checked == true) return true;
			}

			if(inputElement.tagName=="SELECT"){
				///debug("TYP: Select");
				if(inputElement.value.length>0) return true;
			}
		}

		//Radio-Butttons
		else
		{
			//debug("TYP: Radio");
			inputElements = document.getElementsByTagName("INPUT");

			for(var i=0; i<inputElements.length; i++){

			if(inputElements[i].id &&
				inputElements[i].type=="radio" &&
				inputElements[i].id.indexOf(this.id + "-")==0 &&
				inputElements[i].checked == true) {

					return true; 
				}
			}
		}


		return false;
		}
});

/*
 * ConditionIfOneSelected
 * Returns true, if one thing of Checkbox, Radio-Button or Select-Box is selected
 */
var ConditionIfOneSelectedOutOfGroup = Condition.extend({
	constructor: function(ids) {
		this.ids = ids;	
	},
	condition: function() {
		for(var i = 0; i < this.ids.length; i++) {
			//Select-Boxes, Checkboxes
			if(document.getElementById(this.ids[i]) && document.getElementById(this.ids[i]).type!="radio") {

				inputElement = document.getElementById(this.ids[i]);

				if(inputElement.type=="checkbox") {
					//debug("TYP: Checkbox");
					if(inputElement.checked == true) return true;
				}
	
				if(inputElement.tagName=="SELECT"){
					///debug("TYP: Select");
					if(inputElement.value.length>0) return true;
				}
			}

			//Radio-Butttons
			else
			{
				//debug("TYP: Radio");
				inputElements = document.getElementsByTagName("INPUT");

				for(var i=0; i<inputElements.length; i++){

				if(inputElements[i].id &&
					inputElements[i].type=="radio" &&
					inputElements[i].id.indexOf(this.ids[i] + "-")==0 &&
					inputElements[i].checked == true) {

						return true; 
					}
				}
			}
		}


		return false;
		}
});


/*
 * ConditionSelected
 * Returns true, if the Element with the given id is selected / checked
 */

var ConditionIfSelected = Condition.extend({
	constructor: function(id) {
		this.id = id;	
	},
		condition: function() {
		if(document.getElementById(this.id)) {
			if(document.getElementById(this.id).checked == true) return true;
		}
		return false;
	}
});


/*
 * ConditionIfNotEmpty
 * Returns true, if the value of the Element ist not Empty
 */
var ConditionIfNotEmpty = Condition.extend({
	constructor: function(id) {
		this.id = id;	
	},
  	condition: function() {
		return trim(document.getElementById(this.id).value).length > 0
	}
 });



/****************************************************************************
 * Helpers *
 ****************************************************************************/
function trim(val) {
	return val.replace(/\s/g,"");
}

function removeCSSClass(elementMessage, className)
{
	var oldStyle = elementMessage.className;
	eval("var newStyle = oldStyle.replace(/"+className+"/g,'');");
	newStyle.replace(/  /g," ");
	elementMessage.className = newStyle;
}
function addCSSClass(elementMessage, className)
{
	var oldStyle = elementMessage.className;
	var newStyle = oldStyle +" "+className;
	elementMessage.className = newStyle;
}

function existElement(id) {
	if(document.getElementById(id)) return true;
	else return false;
}

function isEmpty(value) {
	return trim(value).length==0;
}

/****************************************************************************
 * Debug *
 ****************************************************************************/
function debug(str) {
	if(document.getElementById("debug"))
		document.getElementById("debug").innerHTML = "&nbsp;&nbsp;&nbsp;" + str + "<br />" + document.getElementById("debug").innerHTML;
}

function debugIn(str) {
	if(document.getElementById("debug"))
		document.getElementById("debug").innerHTML = "<i>INTO: " + str + "</i><br />" + document.getElementById("debug").innerHTML;
}

function debugOut(str) {
	if(document.getElementById("debug"))
		document.getElementById("debug").innerHTML = "<i>OUT: " + str + "</i><br />" + document.getElementById("debug").innerHTML;
}

function error(str) {
	if(document.getElementById("debug"))
		document.getElementById("debug").innerHTML = "<font color='#f00'>" + str + "</font><br />" + document.getElementById("debug").innerHTML;
}


/****************************************************************************
 * Form Submit and Validation *
 ****************************************************************************/

//build validators from array of validatorConstructors
function setValidators()
{
	// loop creates following statement for each validatorConstructor
	// if($('form-id') && validatorConstructors['form-id']) validators['form-id'] = validatorConstructors['form-id']();
	
	for(var i = 0; i < document.forms.length; i++)
	{
		if(document.forms[i].id && validatorConstructors[document.forms[i].id]) {
			validators[document.forms[i].id] = validatorConstructors[document.forms[i].id]();
		}
	}
}

//functions to submit and validate a form
function validateOnSubmit(formId){
	if(formId && validators[formId])
	{
		validators[formId].resetMarks();
		var result = validators[formId].validate();
		return (result == null);
	}
	return true;
}

function submitForm(formId, skipValidation){
	var formSubmit = document.getElementById(formId);
	var skipValidation = (skipValidation === undefined) ? false : skipValidation; //Default to false
	if (!formSubmit || !formSubmit.submit) return false;
	
	if(skipValidation) formSubmit.submit();
	else
	{
		if(validateOnSubmit(formId)){
			formSubmit.submit();
		}	else {
			// setFocus(formId);
			return false;
		}
	}
	return true;
}

function submitFormOnEnter(formId, e)
{
	var keycode;
	if (window.event) keycode = window.event.keyCode;
	else if (e) keycode = e.which;
	else return true;

	if (keycode == 13) {
		submitForm(formId);
		return false;
	} else {
		return true;
	}
}

function clearForm(formId){
	if (!document.getElementById(formId)) return false;
	document.getElementById(formId).reset();
}

//sets focus on first input which did not validate
function setFocus(formId){
	if(!document.getElementById(formId)) return;
	
	var formObj = document.getElementById(formId);
	var inputSelector;

	var inputSelectors = getElementsByClass('validator-highlight-shown', formObj);
	if(inputSelectors.length>0) inputSelector = inputSelectors[0];
	
	//services and tools: check if focused input is on tab-layer and show tab-layer
	if(inputSelector) {
		inputSelector.focus();
	}
}

addEvent(window, 'load', setValidators);
