// =============================================================================
// Element functions
// =============================================================================

/**
 * Returns an element by its name or by its id.
 */
function getElement(elementname) {
    var input = document.getElementsByName(elementname)[0];
    if(typeof input == 'undefined'){
        input = document.getElementById(elementname);
    }
    return input;
}

/**
 * Returns that parent element, which is specified tag
 *
 * The level specifies which parent with the given tag name (tag_type) should
 * be found; default is 1 -> the first one
 *
 * @param object element    current element whose parent should be searched for
 * @param string tag_type   tag name which the parent should have
 * @param int level         number of levels which the parent should be found in
 */
function getParentElement(element, tag_type, level) {
    if (typeof level == "undefined") { level = 1; }

    var parentElement   = element;

    for (var i = 0; i < level; i++) {
        parentElement   = parentElement.parentNode;

	    while (parentElement.tagName != tag_type.toUpperCase()) {
	        parentElement   = parentElement.parentNode;

	        if (parentElement.tagName == 'BODY') {
	            return false;
	        }
	    }
    }

    return parentElement;
}

// =============================================================================
// Output functions
// =============================================================================

/**
 * Copy the value of an input field to another
 */
function copy(source, target) {
    target.value    = source.value;

    return true;
}

/**
 * Check if input field is empty
 */
function empty(element) {
    if (typeof element == "undefined") {
        return true;
    }

    switch (element.tagName) {
        case 'INPUT': return element.value == "";
        case 'DIV'  : return element.innerHTML == "";
        default:      return true;
    }

    throw (ERROR_UNDEFINED);
}

/**
 * Displays or hide the specified element
 *
 * @param   object element Element which have to be displayed
 * @param   boolean [doShow] default value true
 */
function display(element) {
    var doShow  = arguments.length > 1 ? arguments[1] : true;
    element.style.display   = doShow ? '' : 'none';

    return true;
}

/**
 * Toggles displaying of element
 */
function toggleDisplay(element) {
    doShow = !isDisplayed(element);

    display(element, doShow);

    return true;
}

function isDisplayed(element) {
    return !(element.style.display == 'none');
}

/**
 * Enable/ disable element
 *
 * Accordant to element tag name the right function will be called
 *
 * @param object elmenet Element which have to be enabled
 * @param boolean [doEnable] default value true
 * @param string  [value]    default input value ''
 */
function enable(element, doEnable, defaultValue) {
    if (element == null || typeof element == "undefined") {
        return false;
    }

    if (typeof doEnable == "undefined") { doEnable = true; }
    if (typeof defaultValue == "undefined") { defaultValue = ''; }

    switch (element.tagName) {
        case 'INPUT' :
            enableInput(element, doEnable, defaultValue);
            break;
        case 'SELECT' :
            enableSelect(element, doEnable);
            break;
        case 'A' :
        case 'DIV' :
        case 'TR' :
        case 'TD' :
            enableTag(element, doEnable);
            break;
    }

    return true;
}

/**
 * Enable/ disable input element
 *
 * Attribute "disabled" will be set accordingly.
 * So will be set backgroundcolor.
 *
 * @param object elmenet Element which have to be enabled
 * @param boolean doEnable enable or disable element
 * @param string  value    set value for input field
 */
function enableInput(element, doEnable, value) {
    element.value                 = value;
    element.readOnly              = !doEnable;
    element.style.backgroundColor = doEnable ? '': "#E1E8EC";

    return true;
}

/**
 * Enable/ disable input element
 *
 * Attribute "disabled" will be set accordingly.
 * So will be set backgroundcolor.
 *
 * @param object elmenet Element which have to be enabled
 * @param boolean doEnable enable or disable element
 * @param string  value    set value for input field
 */
function enableSelect(element, doEnable, value) {
    element.disabled              = !doEnable;
    element.style.backgroundColor = doEnable ? '': "#E1E8EC";

    return true;
}

/**
 * Enable/disable tag element.
 *
 * Sets style class disabled accordingly.
 *
 * @param object elmenet Element which have to be enabled
 * @param boolean doEnable enable or disable element
 */
function enableTag(element, doEnable) {
    element.className  = doEnable ? '' : 'disabled';

    return true;
}

function deleteAndLight(element, defaultValue) {
	
	deleteAndSetColor(element, defaultValue, "#4D4D4B");
}

function  deleteAndSetColor(element, defaultValue, cssColor){
    element.style.color=cssColor;

    deleteDefaultValue(element, defaultValue);
}

function deleteDefaultValue(element, defaultValue){
	if(element.value == defaultValue) {
		element.value='';
	}
}
function dullAndDark(element, defaultValue) {
    if(element.value=='' || element.value==defaultValue) {
        element.value=defaultValue;
        element.style.color="#CCCCCC";
    }
}

/**
 * Writes a formatted value to the inner html of an element
 */
function writeinhtml(element, value){
    if (typeof value == "number") {
        value   = formatFloat(mercRound(value));
    }

    element.innerHTML = value;
}

/**
 * creates a logging div and shows it at the end of the form
 */
function log(text) {
    var log = document.createElement("div");
    log.setAttribute('id', 'log');
    var p   = document.createElement("p");
    var textNode    = document.createTextNode(text);
    p.appendChild(textNode);
    log.appendChild(p);
    document.forms[0].appendChild(log);
}

/**
 * sets months (TT.MM.JJJJ) as options for given select box
 *
 * @param object    element     select element which the options will be added to
 * @param int       countMonths Number of months which have to be displayed
 * @param int       dayOfMonth  which day of month should be displayed (optional)
 * @param int       addMonth    additional months at which should be started (optional)
 */
function monthlyOptions(element, countMonths, dayOfMonth, addMonth) {
    var date    = new Date();
    if (typeof dayOfMonth == "undefined") dayOfMonth    = 1;
    if (typeof addMonth   == "undefined") addMonth      = 0;

    date.setDate(dayOfMonth);

    // remove default option (it's only there for valid html)
    removeAllChildNodes(element);

    var curMonth    = date.getMonth() + addMonth;
    for (var i = curMonth; i < curMonth + countMonths; i++) {
        if (date.getMonth() > i%12) {
            date.setYear(date.getFullYear() + 1);
        }

        date.setMonth(i%12);
        var sDate   = getDateString(date);

        var option  = document.createElement("option");
        option.setAttribute("value", sDate);

        var textNode    = document.createTextNode(sDate);
        option.appendChild(textNode);
        element.appendChild(option);
    }


    return;
}

/**
 * removes all child nodes of an element
 */
function removeAllChildNodes(element) {
    while (element.childNodes[0]) {
        element.removeChild(element.childNodes[0]);
    }
}


function redirectToParentWindow(address) {
    if (opener.closed) {
        openNewWindow(address, "X-Selling", 1020, 800, true)
    } else {
        opener.location.href=address;
        window.close();
    }
}


// =============================================================================
// Integer functions
// =============================================================================

function pnParseInt(str)
{
    //avoid 'npe'
    if(str == null) {
        return(0);
    }

  var i;
  for(i=0;i<str.length;i++)   // numeric?
    if(str.charAt(i)<'0' || str.charAt(i)>'9') return(null);
  while(str.charAt(0)=='0')   // trim leading zeros
    str = str.substring(1);
  if(str=="") return(0);      // empty string -> 0
  return(eval(str));          // parse value
}

function malformInt(str) {
    if(str == null) {
        return null;
    }

    //kann sein, dass man hier ein nicht-string bekommt, pnParseInt() benutzt jedoch string-methoden
    //also muss man der methode ein string-objekt geben
    str = pnParseInt(str.toString());

    if(str == null || str.length < 1) {
        return null;
    } else {
        if(str < 10) {
            return ('0' + str);
        } else {
            return str;
        }
    }
}
/**
 * Formats a float for displaying currency in german style (dezimal marker: ",")
 */
function formatFloat(value, thousand) {
    if(typeof value == 'undefined')
        value = "0.0";
    else
        value = ""+value;
    if(typeof thousand == 'undefined')
        thousand = false;
    if(value.indexOf('.') < 0)
        value += ".00";
    else {
        if(value.indexOf('.') == 0)
            value = "0"+value;
        if(value.length > value.indexOf('.')+3)
            value = value.substr(0, value.indexOf('.')+3);
        else
            while(value.length < value.indexOf('.')+3)
                value = value+"0";
    }

    value = value.replace(/\./, ",");

    // Tausender Trennzeichen
    if(thousand == true && value.indexOf(',')-(value.indexOf('-')+1) > 3) {
        do {
            value = value.replace(/([^\.-])(\d{3})(\.|,)/, "$1.$2$3");
        } while(value.indexOf('.')-(value.indexOf('-')+1) > 3);
    }
    return value;
}

/**
 * Kaufmaennsiches Runden auf zwei Nachkommastellen
 */
function mercRound(x) {
  return (Math.round(x * 100) / 100);
}

// =============================================================================
// Date functions
// =============================================================================

/**
 * Delegiert einen String mit Trennzeichen zu
 *  getDateStringFromFormattedString(), einen ohne zu
 *  getDateStringFromUnformattedString()
 *
 * @throws ERROR_EMPTY if empty string
 */
function getDateFromString(string, nextYears) {
    var date;

    if(string == null || string == '') {
        throw ERROR_EMPTY;
    } else if(string.indexOf('.') >= 0) {
        date = getDateFromFormattedString(string, nextYears);
    } else {
        date = getDateFromUnformattedString(string, nextYears);
    }

    if (typeof date != "object") {
        throw ERROR_TYPE;
    }

    return date;
}

/**
 * Returns a string from a Date object.
 * Format: dd.MM.yyyy
 *
 * @throws error code if wrong format or wrong type
 * @param Date o_date Date object
 * @param string date string
 */
function getDateString(o_date) {

    // empty field
    if (o_date == null || o_date == '') { return ''; }
    // error
    if (typeof o_date == "number" && o_date < 0) { throw ERROR_FORMAT; }
    if (typeof o_date != "object") { throw ERROR_TYPE; }

    var day, month;
    day     = o_date.getDate()  < 10 ? "0" + o_date.getDate()       : o_date.getDate();
    month   = o_date.getMonth() < 9  ? "0" + (o_date.getMonth()+1)  : o_date.getMonth()+1;

    return day + "." + (month) + "." + o_date.getFullYear();
}


/**
 * formatiert einen String ohne Trennzeichen in ein Date-Objekt,
 * dabei sind folgende Formate erlaubt:
 *    d, dd, ddmm, ddmmyy, ddmmyyyy
 *
 * Bei zweistelligen Jahreszahlen wird das Jahrhundert automatisch hinzugefügt.
 * Voreingestellt ist, dass bei den nächsten 20 Jahreszahlen das aktuelle
 * Jahrhundert, ansonsten das vorherige gesetzt wird.
 * Z.B. aktuell 2008, Angabe 15 => 2015; Angabe 28 => 2028
 * Mit dem zusätzlichen Parameter kann diese Zahl selbst gesetzt werden.
 *
 * @throws ERROR_FORMAT if not valid string
 * @param string text   unformatiertes Datum
 * @param int nextYears Anzahl der nächsten Jahre, in denen noch das aktuelle
 *                      Jahrhundert vorangestellt wird
 */
function getDateFromUnformattedString(text, nextYears) {
    var day, month, year;
    var currentDate = new Date();

    if (typeof nextYears == "undefined") { nextYears = 20; }

    switch(text.length) {
        case 1: //Format: d
        case 2: //Format: dd
            day = pnParseInt(text);
            month = currentDate.getMonth() + 1;
            year = currentDate.getFullYear();
        break;

        case 4: //Format: ddmm
            day = pnParseInt(text.substring(0, 2));
            month = pnParseInt(text.substring(2, 4));
            year = currentDate.getFullYear();
        break;

        case 6: //Format: ddmmyy
            century = Math.floor(currentDate.getFullYear() / 100) * 100;

            day = pnParseInt(text.substring(0, 2));
            month = pnParseInt(text.substring(2, 4));
            year = pnParseInt(text.substring(4, 6));

            // bestimme Jahrhundert, das hinzugefuegt werden soll
            century =  currentDate.getFullYear() + nextYears - century < year ?
                        century - 100 : century;

            year    =  century + year;

        break;

        case 8: //Format: ddmmyyyy
            day = pnParseInt(text.substring(0, 2));
            month = pnParseInt(text.substring(2, 4));
            year = pnParseInt(text.substring(4, 8));
        break;

        default: //alles andere -> leeres Eingabefeld
            throw ERROR_FORMAT;
    }

    //falls ein Feld nicht gesetzt worden sein sollte (fehlerhafte Eingabe)
    //-> leerer String
    if(day == null || month == null || year == null) {
        return ERROR_FORMAT;
    }

    return new Date(year, month-1, day);
}

/**
 * formatiert einen String mit '.' als Trennzeichen in ein Date-Objekt.
 * 'Wohlformt' diesen also bei Eingaben wie '1.1.05' zu '01.01.2005'. Jegliche
 * andere Zeichen fuehren zur Rueckgabe eines leeren Strings
 *
 * @throws ERROR_FORMAT if not valid string
 * @param string text   formatiertes Datum
 * @param int nextYears Anzahl der nächsten Jahre, in denen noch das aktuelle
 *                      Jahrhundert vorangestellt wird
 */
function getDateFromFormattedString(text, nextYears) {
    var dateFields = new Array('', '', '');
    var currentField = 0;

    if (typeof nextYears == "undefined") { nextYears = 20; }

    //solange laufen, bis currentField 3 erreicht oder der text zuende ist
    for(var i = 0; i < text.length && currentField < 3; i++) {
        //charAt() geht nicht, da pnParseInt() einen String benoetigt
        var currentChar = text.substring(i, i + 1);

        //Zeichen -> . (Trennzeichen bei Datum), ins naechste Feld wechseln
        if(currentChar == '.') {
            currentField++;
        } else {
            var parsedChar = pnParseInt(currentChar); //Zeichen in Zahl umwandeln
            if(parsedChar != null) {
                //zur entsprechenden Zeichenkette hinzufuegen
                dateFields[currentField] += parsedChar;
            } else {
                //Nicht-numerisches/-'.'-Zeichen gefunden -> Ungueltige Eingabe
                throw ERROR_FORMAT;
            }
        }
    }

    // formatiere zweistellige Jahreszahl
    if (dateFields[2].length < 3) {
        var currentDate = new Date();
        var century     = Math.floor(currentDate.getFullYear() / 100) * 100;

        // bestimme Jahrhundert, das hinzugefuegt werden soll
        century     =  currentDate.getFullYear() + nextYears - century < pnParseInt(dateFields[2]) ?
                            century - 100 : century;
        dateFields[2]   = century + pnParseInt(dateFields[2]);
    }

    return new Date(dateFields[2], dateFields[1]-1, dateFields[0]);
}

/**
 * calculates the Diff between two dates.
 * @return array [count_years, count_months, count_days]
 */
function calculateDateDiff(dateBegin, dateEnd) {

    var b_d = dateBegin.getDate(),
        b_M = dateBegin.getMonth()+1,
        b_y = dateBegin.getFullYear();

    var d=M=y=0;

    var e_d = dateEnd.getDate();
    var e_M = dateEnd.getMonth()+1;
    var e_y = dateEnd.getFullYear();

    var monthdays = new Array(31,( (e_y % 4 == 0 && ( e_y % 100 != 0 || e_y % 400 == 0 )) ? 29 : 28 ),31,30,31,30,31,31,30,31,30,31);

    if (e_d < b_d) {
        d += monthdays[(e_M)] + e_d - b_d;
        M--;
    } else { d += e_d - b_d; }
    if (e_M < b_M) {
        M += 12 + e_M - b_M;
        y--;
    } else { M += e_M - b_M; }
    y += e_y - b_y;

    return new Array(y, M, d);
}

// =============================================================================
// Error Handling
// =============================================================================

// error codes (abs(errorcode) < 10)
var ERROR_EMPTY         =   -1; // empty value
var ERROR_NUM           =   -2; // variable contains other chars than numbers
var ERROR_FORMAT        =   -3; // variable has a wrong format (e.g. dates)
var ERROR_MIN_CHARS     =   -4; // minimum 3 chars
var ERROR_TYPE          =   -5; // variable has the wrong type
var ERROR_UNDEFINED     =   -9; // undefined error

/**
 * Returns errorText for spezified errorCode
 *
 * A field name can also be spezified for beautifying the errorText
 *
 * @param int errorCode error code
 * @return string errorText
 */
function errorText(errorCode) {
    var fieldName   = arguments.length == 1 ? '' : arguments[1];

    if (typeof errorCode != "number") {
        return;
    }

    switch (errorCode) {
        case ERROR_EMPTY:
            return 'Bitte füllen Sie das Feld ' + fieldName + ' aus.';
        case ERROR_NUM:
            return 'Bitte verwenden Sie für das Feld ' + fieldName + ' nur Ziffern.';
        case ERROR_FORMAT:
            return 'Das Feld ' +fieldName + ' hat das falsche Format. Bitte korrigieren Sie ihre Eingabe.';
        case ERROR_MIN_CHARS:
            return 'Bitte geben Sie mindestens drei Buchstaben ein.';
        case ERROR_TYPE:
            return 'Der Eingabewert hat den falschen Typ. Bitte korrigieren Sie ihre Eingabe';
        default:
            return 'Ein unbekannter Fehler ist aufgetreten. ErrorCode: ' + errorCode;
    }

    return 'Ein unbekannter Fehler ist aufgetreten.';
}

function removeErrors() {
    var errorNode       = document.getElementById('client-errors');

    display(errorNode, false);
}

function showErrors(errors) {
    if (typeof errors == "undefined") {
        return true;
    }

    var doShow          = false;
    var errorNode       = document.getElementById('client-errors');
    var listNode        = errorNode.getElementsByTagName('ul')[0];

    removeAllChildNodes(listNode);

    for (var error in errors) {
        if (errors[error] == null) continue;

        var node    = document.createElement('li');
        node.setAttribute('id', 'error-' + error);

        // split error text by new lines and add them to node with breaks
        var lines   = errors[error].split("\n");
        node.appendChild(document.createTextNode(lines[0]));
        for (var i = 1; i < lines.length; ++i) {
            node.appendChild(document.createElement('br'));
            node.appendChild(document.createTextNode(lines[i]));
        }

        listNode.appendChild(node);
        doShow      = true;
    }

    display(errorNode, doShow);
}

function focusErrorElement(element) {
    globalElement   = element;

    // if globalElement is radio button
    if (globalElement.name    == undefined && globalElement[0].type == "radio") {
        globalElement  = element[0];
    }

    window.setTimeout('globalElement.focus()', 1);

    if (globalElement.type  == "text") {
        window.setTimeout('globalElement.select()',1);
    }

    return true;
}

function alertError(element, errorText) {
    alert(errorText);
    focusErrorElement(element);
}


function setAddressFromOrtsvorschlag(prefix, value){
	/*This is the Version for the PersonenAngaben NOT!!! the AgencySearch*/
	
	if(value.indexOf("|") == -1) {
		return;
	}

	var sPlz = value.substr(0, value.indexOf("|"));

	var sOrt = value.substr(value.indexOf("|")+1);

	$('#'+prefix+'plz').val(sPlz);
	$('#'+prefix+'ort').val(sOrt);
	
}





// =============================================================================
// Class Rechner for usage in all rechner forms
// =============================================================================

/**
 * Class Rechner validates form data for special Rechners
 */
function Rechner(tarife) {
    // tarife
    var rates       = tarife;

    // registered elements
    var elements    = new Object();

    // validation functions for each registered element
    var validations = new Object();

    // params for validation functions
    var validationParams    = new Object();

    // values of elements, if they're valid
    var validValues = new Object();

    // labels of elements
    var labels      = new Object();

    // errors
    var errors      = new Object();

    // do calculation on the fly
    var doCalculateOnTheFly = true;

    this.setDoCalculateOnTheFly = function(flag) {
        doCalculateOnTheFly = flag;
    }

    /**
     * register an element and its validation function
     *
     * Each element, which has to be validated and taken care of in the
     * calculation, has to be registered with its validation function and label.
     * Optionally you can pass additional parameters to the validation function
     * combined in an array.
     *
     * @param object element    element which has to be registered
     * @param string validationFunction name of function which validates element
     * @param string label      label of form element
     * @param Array  params     optional parameters for validationFunction
     */
    this.register   = function(element, validationFunction, label, params) {
        var name    = elementName(element);

        // set private attributes
        elements[name]      = element;
        validations[name]   = validationFunction;
        labels[name]        = typeof label == "undefined" ? "" : label;

        // set optional parameters for validation functions
        if (typeof params != "undefined") {
            validationParams[name]  = params;
        }

        var rechner = this;

        // set event handler to the elements
        // Caution: you can't add the same event handler in the html source
        switch (element.type) {
            case "text" :
            case "textarea" :
                element.onblur      = function() {
                    doCalculateOnTheFly ?
                    rechner.calculate() : rechner.validate();
                };
                break;
            case "select-one" :
                element.onchange    = function() {
                    doCalculateOnTheFly ?
                    rechner.calculate() : rechner.validate();
                };
                break;
            default :
                if (typeof element[0] != "undefined") {
                    switch (element[0].type) {
                        case "radio" :
                        case "checkbox" :
                            for (var i = 0; i < element.length; ++i) {
                                element[i].onclick =
                                    function() {
					                    doCalculateOnTheFly ?
					                    rechner.calculate() :
					                    rechner.validate();
					                };
                            }
                            break;
                    }
                }
                break;
        }
    }

    /**
     * Returns the element specified by its name
     *
     * @param string name   element's name
     * @return object element
     */
    this.getElement    = function(name) {
        return elements[name];
    }

    /**
     * Validates an element specified by its name using the accordant
     * validation function.
     *
     * If there are additional parameters for the validation function they
     * will be passed to that function.
     *
     * @param   string name name of the element
     * @return mixed return value of validation function
     */
    this.validateElement    = function(name) {
        if (typeof validationParams[name] == "object" &&
                validationParams[name].length > 0) {
            return validations[name](elements[name], validationParams[name]);
        } else {
            return validations[name](elements[name]);
        }
    }

    /**
     * Returns the validated value of the element specified by its name.
     *
     * @param string name element's name
     * @return mixed    validated value
     */
    this.getValidValue = function(name) {
        return validValues[name];
    }

    /**
     * Count all errors which are thrown by validation.
     *
     * @return int number of errors
     */
    this.countErrors = function() {
        var i = 0;

        for (error in errors) ++i;

        return i;
    }

    /**
     * Get the name of the specified element.
     *
     * If the element is an array of radio buttons or checkboxes return the
     * name of the first element in that array.
     *
     * @param object element specified element
     * @return string name of the element
     */
    function elementName(element) {
        var name    = element.name;
        if (element.name    == undefined &&
            (element[0].type == "radio" || element[0].type == "checkbox")) {
            name    = element[0].name;
        }

        return name;
    }


	/**
	 * Returns Tarif value for given Geschlecht and Alter accordant to the
	 * Tarif table
	 */
	this.getRateValue  = function(rate, sex, age) {
	    var sAge        = age + '';
	    var rateValue  = rates[rate][sex][sAge];

	    if (typeof rateValue == "undefined") {
	        rateValue  = 0;
	    }

	    return rateValue;
	}

    /**
     * Do validation for all registered elements using their validation
     * functions.
     *
     * If withEmptyness is set to false, errors of empty elements will not be
     * shown, if they are not shown already. Nonetheless the return flag will
     * be set to false showing that the elements aren't valid.
     *
     * After validation the errors will be shown as specified in showErrors().
     *
     * @todo: Refactoring: move error handling to this class
     * @param boolean withEmptyness flag if errors of empty fields should be shown
     * @return boolean all elements valid?
     */
    this.validate   = function(withEmptyness) {

        var newErrors       = new Object;
        var errorElement    = null;
        // default: withEmptyness = false
        withEmptyness   = typeof withEmptyness == "undefined" ?
            false : withEmptyness;

        // return flag
        var flag    = true;

        for (var name in elements) {
            try {
                // validate element and store valid value
                validValues[name]   = this.validateElement(name);
            } catch (e) {

                // if fields are empty return false, but also validate all other
                // fields
                if (!withEmptyness && e == ERROR_EMPTY) {

                    if (typeof errors[name] != undefined &&
                            typeof newErrors[name] == "undefined") {
                        newErrors[name] = errors[name];
                    }

                    flag = false;
                    continue;
                }

                newErrors[name]        = this.errorText(e, labels[name]);

                // set error element for focusing
                if (errorElement == null) {
                    errorElement        = elements[name];
                }

                flag    = false;
            }
        }

        if (!flag) {
            if (errorElement != null) {
                focusErrorElement(errorElement);
            }

        }

        errors  = newErrors;
        showErrors(errors);

        return flag;
    }

    /**
     * Add error text for given element specified by its name to the errors array.
     */
    this.addError   = function(name, text) {
        errors[name]    = text;
    }

    /**
     * Returns all errors.
     */
    this.getErrors  = function() {
        return errors;
    }

    /**
     * Reset the array of registered elements and the accordant arrays of
     * validation functions and labels.
     */
    this.resetRegisteredElements    = function() {
        elements    = new Object();
        validations = new Object();
        validValues = new Object();
        labels      = new Object();
    }


    this.showRegisteredElements = function() {
        log("Show elements:");
        for (var key in elements) {
            log(key);
        }
        log("End show elements.");
    }

    /**
     * abstract calculation function implemented by special "rechner"
     */
    this.calculate  = function() {}

    /**
     * abstract error text function implemented by special "rechner"
     */
    this.errorText  = function() {}
}

	
   	/**
     * This function generate a popup with an help text.
     * The variable cssfilepath must be set.
     */
    function popupHelp(headline, text, width, height, autoresize){
    	if(autoresize == null) autoresize = true;
    	 
    	popup = window.open('','helpmessage', 'width=' + width + ',height=' + height + ',scrollbars=no');
    	var content = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">' +
				'<html>' +
				'<head><link rel="stylesheet" type="text/css" href="' + cssfilepath + '"/><title>Hilfe</title></head>' +
				'<body style="padding: 10px 5px 10px 5px;">' +
				'<table id="main" cellspacing="0" cellpadding="0">' +
				'<tr><th>' + headline + '</th></tr>' +
				'<tr><td><table cellspacing="0" cellpadding="0"><tr height="100%"><td>' + text + '</td></tr></table></td></tr>' +
				'</table>' +
				'<SCRIPT language="JavaScript">var autoresize='+autoresize+'; if(autoresize){window.resizeTo(' + width + ',document.body.offsetHeight + 60);}</SCRIPT>' + 
				'</body>' +
				'</html>';
								
		popup.document.open();
		popup.document.write(content);
		popup.document.close();
		window.popup.focus();
    }
    
    /**
     * setter method for cssfilepath variable
     */
    function setCssFilePath(formid, mandantid) {
        cssfilepath = '../../css/' + formid.toLowerCase() + '/' + mandantid.toLowerCase() + '.css';
    }
    
    var cssfilepath = "";
