// Peri läd die Exemplarliste neu
var reloadExemplare = false;

// Pattern-Objekt für clientseitige Validierung von Anwendereingaben aufbauen
var m_patterns = {
    Email: /([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})/,

    Integer: /[ ]{0,}[-+]{0,1}[0-9]{1,}[ ]{0,}/,

    Time: /[0-9]{2}\:[0-9]{2}/,

    Float_itIT2: /[-+]{0,1}[0-9]{1,}(\u002c)?/,

    Currency: {
        deDE: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{0,2})?[ ]{0,}/,
        itIT: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{0,2})?[ ]{0,}/,
        enGB: /[ ]{0,}[-+]{0,1}[0-9]{1,}(\.[0-9]{0,2})?[ ]{0,}/
    },

    Float: {
        arSA: /[ ]{0,}[-+]{0,1}[0-9]{1,}(\.[0-9]{1,})?[ ]{0,}/,
        csCZ: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/,
        enGB: /[ ]{0,}[-+]{0,1}[0-9]{1,}(\.[0-9]{1,})?[ ]{0,}/,
        enUS: /[ ]{0,}[-+]{0,1}[0-9]{1,}(\.[0-9]{1,})?[ ]{0,}/,
        deAT: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/,
        deDE: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/,
        deCH: /[ ]{0,}[-+]{0,1}[0-9]{1,}(\.[0-9]{1,})?[ ]{0,}/,
        itIT: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/,
        itCH: /[ ]{0,}[-+]{0,1}[0-9]{1,}(\.[0-9]{1,})?[ ]{0,}/,
        plPL: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/,
        ruRU: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/,
        trTR: /[ ]{0,}[-+]{0,1}[0-9]{1,}(,[0-9]{1,})?[ ]{0,}/
    },

    Date: {
        arSA: /[0-9]{2}\/[0-9]{2}\/[0-9]{4}/,     // dd/MM/yyyy
        csCZ: /[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}/, // d.M.yyyy
        enGB: /[0-9]{2}\/[0-9]{2}\/[0-9]{4}/,     // dd/MM/yyyy
        enUS: /[0-9]{2}\/[0-9]{2}\/[0-9]{4}/,     // MM/dd/yyyy
        deAT: /[0-9]{2}\.[0-9]{2}\.[0-9]{4}/,     // dd.MM.yyyy
        deDE: /[0-9]{2}\.[0-9]{2}\.[0-9]{4}/,     // dd.MM.yyyy
        deCH: /[0-9]{2}\.[0-9]{2}\.[0-9]{4}/,     // dd.MM.yyyy
        itIT: /[0-9]{2}\/[0-9]{2}\/[0-9]{4}/,     // dd/MM/yyyy
        itCH: /[0-9]{2}\.[0-9]{2}\.[0-9]{4}/,     // dd.MM.yyyy
        plPL: /[0-9]{4}\.[0-9]{2}\.[0-9]{2}/,     // yyyy-MM-dd
        ruRU: /[0-9]{2}\.[0-9]{2}\.[0-9]{4}/,     // dd.MM.yyyy
        trTR: /[0-9]{2}\.[0-9]{2}\.[0-9]{4}/,     // dd.MM.yyyy
        year: /[0-9]{4}/
    }
}

function Validate_BDropDownBox(sender, args) {
    /// <summary>Diese Funktion überprüft in der BDropDownBox, ob der ausgewählte Index (SelectedIndex) 
    /// ungleich -1 (nichts ausgewählt) ist; dann ist die BDropDownBox gültig validiert.</summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <returns></returns>
    /// <remarks>
    /// Validierung mit ASP.NET 2.0-Bordmitteln. Selbstgeschriebene Validierungsfunktionen in dieser 
    /// JS-Datei sollten entfernt werden durch Validierungs-Controls. Vorerst nur "RequiredFieldValidation",
    /// d.h. nur Prüfung gegen leere Felder, keine Gültigkeitsprüfung
    /// </remarks>
    args.IsValid = args.Value != -1;
}

// ----------------------------------------------------------------------------
// Zentriert die DialogBox auf dem Anzeigerät
// ----------------------------------------------------------------------------
function centerDialogBox(box) {
    /// <summary>.</summary>
    /// <param name="box" type="String" mayBeNull="false" optional="false">.</param>
    /// <remarks>
    /// ckress: Gefährlich: Microsoft sichert die Unveränderlichkeit von
    /// navigator.appName nicht zu (aber sehr wohl MSIE n.m in appName)!
    /// </remarks>
    var sTop, browser, object;

    object = GetElementById(box);
    if (object == null) return;
    
    sTop = "150px"; // std
    
    // sTop für best. Dialog ändern
    if (object.id == "pg_dlgRechnungDetailpan_dlgRechnungDetailbox") {
        sTop = "50px";
    }

    //browser = navigator.appName;
    ///if (browser == "Microsoft Internet Explorer") {
        object.style.left = parseInt(document.body.clientWidth / 2) - parseInt(object.offsetWidth / 2) + "px";
        //object.style.top = parseInt(document.body.clientHeight / 2) - parseInt(object.offsetHeight / 2) + "px";
        object.style.top = sTop;
    ///}
    ///else {
    ///    object.style.left = "50%";
    ///    object.style.top = "50%";
    ///    object.style.marginLeft = "-" + parseInt(object.offsetWidth / 2) + "px";
    ///    object.style.marginTop = "-" + parseInt(object.offsetHeight / 2) + "px";
    ///}
}

// ----------------------------------------------------------------------------
// Zentriert Dialogbox in Elternelement
// ----------------------------------------------------------------------------
function centerDialogBoxParent(box) {
    /// <summary>.</summary>
    /// <param name="box" type="String" mayBeNull="false" optional="false">.</param>
    /// <remarks>
    /// ckress: Gefährlich: Microsoft sichert die Unveränderlichkeit von
    /// navigator.appName nicht zu (aber sehr wohl MSIE n.m in appName)!
    /// </remarks>
    var browser;

    object = GetElementById(box);
    browser = navigator.appName;

    if ("Microsoft Internet Explorer" == browser) {
        parentObj = object.parentNode;
        object.style.left = parseInt(parentObj.offsetWidth / 2) - parseInt(object.offsetWidth / 2);
        object.style.top = parseInt(parentObj.offsetHeight / 2) - parseInt(object.offsetHeight / 2);

        if ("0px" == object.style.top) {
            object.style.top = "15%";
        }
    }
    else {
        object.style.left = "50%";
        object.style.top = "50%";
        object.style.marginLeft = "-" + parseInt(object.offsetWidth / 2) + "px";
        
        if ("ucAnzeige_InnerContainer" == box) {
            // object.style.marginTop = "-" + parseInt(object.offsetHeight / 2) + "px";
        }
        else {
            object.style.marginTop = "-" + parseInt(object.offsetHeight / 2) + "px";
        }
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function SetControlHeight(ctrl, height) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="height" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = GetElementById(ctrl))) {
        control.style.height = height;
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function SetControlVisibility(ctrl, visible) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="visible" type="String" mayBeNull="true" optional="false">.</param>
    var control;

    if (null != (control = GetElementById(ctrl))) {
        control.style.visibility = "true" == visible ? "visible" : "hidden";
        control.style.display = "true" == visible ? "block" : "none";
    }

    return false;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function ToggleControlVisibility(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = GetElementById(ctrl))) {
        control.style.display = control.style.visibility == "hidden" ? "block" : "none";
        control.style.visibility = control.style.visibility == "hidden" ? "visible" : "hidden";
    }

    return false;
}

// ##############################
// QTHEKE AJAX START
// ##############################
var ajaxBuchung = createRequestObject();
var ThekeLeserRenderer = createRequestObject();

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function createRequestObject() {
    /// <summary>.</summary>
    /// <remarks>
    /// ckress: Gefährlich: Microsoft sichert die Unveränderlichkeit von
    /// navigator.appName nicht zu (aber sehr wohl MSIE n.m in appName)!
    /// </remarks>
    return "Microsoft Internet Explorer" == navigator.appName ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();

    window.alert("createRequestObject");
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function getXMLNodeValue(tag, field) {
    /// <summary>.</summary>
    /// <param name="tag" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="field" type="String" mayBeNull="true" optional="false">.</param>
    var obj = tag[0].getElementsByTagName(field);

    if (null == obj) {
        return "";
    }

    if (null == obj[0]) {
        return "";
    }

    if (null == obj[0].firstChild) {
        return "";
    }

    return obj[0].firstChild.nodeValue;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function getXMLNodeControl(tag, field) {
    /// <summary>.</summary>
    /// <param name="tag" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="field" type="String" mayBeNull="false" optional="false">.</param>
    var obj = tag[0].getElementsByTagName(field);
    var name = obj[0].firstChild.nodeValue;

    return document.getElementById(name);
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function handleThekeLeserRenderer() {
    /// <summary>.</summary>
    var LeserHeaderFieldID, LeserHeaderField, LeserheaderInnerHTML;

    if (4 == ThekeLeserRenderer.readyState) {
        if (200 == ThekeLeserRenderer.status) {
            var data = ThekeLeserRenderer.responseXML.getElementsByTagName("data");

            if (null != data) {
                LeserHeaderFieldID = getXMLNodeValue(data, "field");
                LeserHeaderField = document.getElementById(LeserHeaderFieldID);
                LeserheaderInnerHTML = getXMLNodeValue(data, "temp");
                LeserHeaderField.innerHTML = LeserheaderInnerHTML;
            }
        }
    }
}


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function handleQTVerbuchungResponse() {
    /// <summary>.</summary>
    var info, buchControl, leser, isError, error, success, isStopBuchWarning, iswarnung;

    if (4 == ajaxBuchung.readyState) {
        if (200 == ajaxBuchung.status) {
            info = ajaxBuchung.responseXML.getElementsByTagName("info");
            enableBuchControl(info);

            buchControl = getXMLNodeControl(info, "field");
            buchControl.disabled = false;

            leser = ajaxBuchung.responseXML.getElementsByTagName("leser");
            doShowLeser(leser);

            isError = getXMLNodeValue(info, "iserror");
            error = ajaxBuchung.responseXML.getElementsByTagName("error");
            success = ajaxBuchung.responseXML.getElementsByTagName("success");
            doErrorMessage(error, success, isError);
            doMessage(error, success, isError);

            if ("true" == isError) {
                // Buttons entsprechend anzeigen
                doShowErrorButtons(error);
            }

            // ShortCutLeiste aufbauen
            doShowSCButtons(info, leser);

            if ("true" == isError) {
                isStopBuchWarning = getXMLNodeValue(error, "isBuchWarning");

                if ("true" == isStopBuchWarning) {
                    buchControl = getXMLNodeControl(info, "field");
                    buchControl.disabled = true;
                }

                // Fehler -> Focus nicht auf Buchungsnummer
                // Warnung -> Focus auf Buchungsnummer, wenn eingestellt ist, dass
                // mit 2 maliger Eingabe der Buchnr diese Meldung bestätigt werden kann
                iswarnung = getXMLNodeValue(error, "iswarning");
                if ("true" == iswarnung) {
                    // Warnung
                    // Jetzt pruefen, ob der doppeltModus aktiv ist
                    var isdouble = getXMLNodeValue(error, "isdouble");

                    if ("true" == isdouble) {
                        // Focus setzen auf Buchungsnummer
                        if ("false" == isStopBuchWarning) {
                            qthekesetfocusausweisbuchnr();
                        }
                    }
                }
                else {
                    // Fehler -> nichts tun, weil eine weitere Eingabe der Buchungsnummer hier auch nichts bringt
                }
            }
            else {
                // Focus setzen auf Buchungsnummer
                qthekesetfocusausweisbuchnr();
            }
        }
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function doShowSCButtons(info, leser) {
    /// <summary>.</summary>
    /// <param name="info" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="leser" type="String" mayBeNull="false" optional="false">.</param>
    var scfield = getXMLNodeValue(info, "scfield");
    var show = getXMLNodeValue(leser, "showausweis");

    // Sichtbarkeit definieren
    var value = "true" == show ? "false" : "true";

    // Kein Leser gewählt -> BeendenLeser ausblenden, sonst umgekehrt
    QTSCButtonSichtbar(scfield + "$BBeenden", value);
    QTSCButtonSichtbar(scfield + "$BAlleVerlaengern", value);
    QTSCButtonSichtbar(scfield + "$BLeserDaten", value);
    QTSCButtonSichtbar(scfield + "$BBezahlen", value);
    QTSCButtonSichtbar(scfield + "$BKonto", value);
    QTSCButtonSichtbar(scfield + "$BVormerk", value);
    QTSCButtonSichtbar(scfield + "$BBereit", value);
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function doErrorMessage(error, success, iserror) {
    /// <summary>.</summary>
    /// <param name="error" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="success" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="iserror" type="String" mayBeNull="false" optional="false">.</param>
    // ACHTUNG: NUR der Preffix des Feldes, Rest muss noch angehaengt werden
    var meldungfieldprefix = getXMLNodeValue(error, "field");
    var errorTextField;

    if ("true" == iserror) {
        // Nur wenn ein Fehler aufgetreten ist
        errortext = getXMLNodeValue(error, "message");

        // Meldung anzeigen
        errorTextField = document.getElementById(meldungfieldprefix + "_errortext");
        errorTextField.innerHTML = errortext;
        ControlSichtbar(meldungfieldprefix + "_errorbox", "true");
    }
    else {
        // Fehler leeren
        errorTextField = document.getElementById(meldungfieldprefix + "_errortext");
        errorTextField.innerHTML = "";

        // Wenn kein Fehler aufgetreten ist, Buttons wegnehemen
        ControlSichtbar(meldungfieldprefix + "_errorbox", "false");
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function doShowErrorButtons(error) {
    /// <summary>.</summary>
    /// <param name="error" type="String" mayBeNull="false" optional="false">.</param>
    var meldungfieldprefix = getXMLNodeValue(error, "field");
    var iswarnung = getXMLNodeValue(error, "iswarning");

    if ("true" == iswarnung) {
        // Weiter und Abbrechen
        ControlSichtbar(meldungfieldprefix + "$BWeiter", "true");
        ControlSichtbar(meldungfieldprefix + "$BAbbrechen", "true");
        ControlSichtbar(meldungfieldprefix + "$BOk", "false");
        document.getElementById(meldungfieldprefix + "$BWeiter").focus();
    }
    else {
        // Fehler: Nur OK
        ControlSichtbar(meldungfieldprefix + "$BWeiter", "false");
        ControlSichtbar(meldungfieldprefix + "$BAbbrechen", "false");
        ControlSichtbar(meldungfieldprefix + "$BOk", "true");
        document.getElementById(meldungfieldprefix + "$BOk").focus();
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function doMessage(error, success, iserror) {
    /// <summary>.</summary>
    /// <param name="error" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="success" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="iserror" type="String" mayBeNull="false" optional="false">.</param>
    var lastakttext, lastakttextfield, messagefield;
    var fieldprefix = getXMLNodeValue(success, "field");

    if ("false" == iserror) {
        // Nur wenn kein Fehler ( das ist das Protokoll )
        lastakttext = getXMLNodeValue(success, "message");
        lastakttextfield = document.getElementById(fieldprefix + "_letzteAktionen");
        lastakttextfield.innerHTML = lastakttext + lastakttextfield.innerHTML;
    }

    // BuchInfo anzeigen
    messagefield = document.getElementById(fieldprefix + "_meldungtext");
    messagefield.innerHTML = "" == getXMLNodeValue(success, "buchinfo") ? "" : buchtext;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function doShowLeser(leser) {
    /// <summary>.</summary>
    /// <param name="leser" type="String" mayBeNull="false" optional="false">.</param>
    // Soll das Lesertemplate oder die Ausweisnummerneingabe angezeigt werden
    var show = getXMLNodeValue(leser, "showausweis");
    var ausweisDivID = getXMLNodeValue(leser, "ausweisfield");
    var leserSucheDiv = getXMLNodeValue(leser, "lesersuchediv");
    var leserDetailsFrame = getXMLNodeValue(leser, "leserdetails");
    var leserBelegeDiv = getXMLNodeValue(leser, "leserbelege");

    if ("true" == show) {
        // Ausweisnummernfeld
        ControlSichtbar(ausweisDivID, "true");
        ControlSichtbar(leserSucheDiv, "true");
        ControlSichtbar(leserDetailsFrame, "false");
        ControlSichtbar(leserBelegeDiv, "false");
    }
    else {
        // Lesertemplate
        ControlSichtbar(ausweisDivID, "false");
        ControlSichtbar(leserSucheDiv, "false");
        ControlSichtbar(leserDetailsFrame, "true");
        ControlSichtbar(leserBelegeDiv, "true");
        reloadLeserDetails();
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function enableBuchControl(tag) {
    /// <summary>.</summary>
    /// <param name="tag" type="String" mayBeNull="false" optional="false">.</param>
    var buchControl, sFocus;

    buchControl = getXMLNodeControl(tag, "field");
    buchControl.disabled = false;
    buchControl.value = "";

    sFocus = getXMLNodeValue(tag, "setfocus");
    if (sFocus == "true") {
        buchControl.focus();
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function qthekesetfocusausweisbuchnr() {
    /// <summary>.</summary>
    try {
        setfocusausweisfield();
    }
    catch (e1) {
        try {
            setfocusbuchnrfield();
        }
        catch (e2) {
            try {
                setfocuszahlbetragfield();
            }
            catch (e3) {
            }
        }
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function QTSCButtonSichtbar(divName, sichtbar) {
    /// <summary>.</summary>
    /// <param name="divName" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="sichtbar" type="String" mayBeNull="false" optional="false">.</param>
    if (document.getElementById(divName)) {
        document.getElementById(divName).style.visibility = "true" == sichtbar ? "visible" : "hidden";
    }
    else {
        window.alert(divName);
    }
}

// ##############################
// QTHEKE AJAX ENDE
// ##############################
// ----------------------------------------------------------------------------
//    Prüfen ob Browser gültig.
// ----------------------------------------------------------------------------
function CheckBrowser(errorMsg) {
    /// <summary>.</summary>
    /// <param name="errorMsg" type="String" mayBeNull="false" optional="false">.</param>
    var version, idx;

    if ("Netscape" == navigator.appName) {
        if (parseInt(navigator.appVersion.substring(0, 1)) >= 5) {
            return "Netscape"; // Mozilla 5 oder besser
        }
    }
    else if ("Microsoft Internet Explorer" == navigator.appName) {
        version = navigator.userAgent.toLowerCase();

        if ((version.indexOf("msie 5") != -1 && version.indexOf("msie 5.5") != -1) ||
            version.indexOf("msie 6") != -1 ||
            version.indexOf("msie 7") != -1 ||
            version.indexOf("msie 8") != -1) {
            return "Explorer"; // IE 5.5x oder 6.x
        }
    }

    //window.alert("(CheckBrowser)" + errorMsg);

    return "Unknown"; // IE alt, Netscape alt, andere Browser
}

// ----------------------------------------------------------------------------
//    Tastaturcode holen
// ----------------------------------------------------------------------------
function GetKeyCode(event) {
	/// <summary>.</summary>
	/// <param name="event" domElement="true" mayBeNull="false" optional="false">.</param>
	if (event.which) return event.which;
	else if (event.keyCode) return event.keyCode;
	else return 0;
}

var clicked = false;

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function GetElementById(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = document.getElementById(ctrl))) {
        return control;
    }
    else if (null != (control = window.parent.document.getElementById(ctrl))) {
        return control;
    }
    else {
        // window.alert("GetElementById: Control with ID " + ctrl + " not found");
    }
    
    return null;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function erstesEvent() {
    if (clicked) {
        return false;
    }
    else {
        clicked = true;
        return true;
    }
}

// ----------------------------------------------------------------------------
// BTextBox
// ----------------------------------------------------------------------------
function ExecOnKeypress(ctrl, event, clickedButtonOnReturn) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="event" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="clickedButtonOnReturn" type="String" mayBeNull="false" optional="false">.</param>
    var stopKey, code, obutton;

    code = event.keyCode;

    if (13 == code && "" != clickedButtonOnReturn) {
        // mjs: default aktion(meist ein unbeliebter form-submit) preventen
        if (event.preventDefault) {
            // DOM2: gecko, ...
            event.preventDefault();
        }
        else if (undefined != typeof event.returnValue) {
            // IE
            event.returnValue = false;
        }
        
        obutton = GetElementById(clickedButtonOnReturn);
        if (obutton != null) {
            if (obutton.click) {
                obutton.click();
            }
            else {
                obutton.onclick();
            }
        }
    }

    return;

    stopKey = false;
    if (null != (control = document.getElementById(ctrl))) {
        if (event.altKey || event.shiftKey || event.ctrlKey) {
            event.returnValue = false;
            event.cancelBubble = true;
            0 == code;

            return false;
        }

        if (9 == code) {
            // TAB input
            return true;
        }

        if (code == pKommaCode) {
            // "," == 188 / "." == 190
            stopKey = IsCharInTextBox(ctrl, pKommaKey);
        }
        else if (189 == code) {
            // "-" == 189
            stopKey = IsCharInTextBox(ctrl, "-");
        }
        else if (8 == code || 35 == code || 36 == code || 37 == code || 39 == code || 46 == code) {
            // ENTF, CURSLEFT, CURSRIGHT, BACKSPACE, POS1, END 
        }
        else if (48 <= code && code <= 57) {
            // 0,1,2,3,4,5,6,7,8,9 == 48-57
        }
        else if (96 <= code && code <= 105) {
            // 0,1,2,3,4,5,6,7,8,9 == 48-57 NUMPAD
        }
        else {
            stopKey = true;
        }

        if (stopKey) {
            event.returnValue = false;
            event.cancelBubble = true;
            code = 0;

            return false;
        }
    }

    return true;
}

// ----------------------------------------------------------------------------
// BTextBoxDate
// ----------------------------------------------------------------------------
function CheckTextBoxInputNotEmpty(ctrl, pMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMessage" type="String" mayBeNull="false" optional="false">.</param>
    var control;

    if (null == (control = GetElementById(ctrl))) {
        return true;
    }

    if (control.value.length > 0) {
        return true;
    }
    else {
        // mjs: die pflichtfeldvalidierung soll temporaer
        // deaktiviert werden, bis uns was gscheits einfaellt
        // und wir auch zeit haben das dann umzusetzen
        return true;
        // SetValidationErrorMessage( ctrl, pMessage );
        // return false;
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function CheckTextBoxInputNotEmptyNoMessage(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null == (control = GetElementById(ctrl))) {
        return true;
    }

    return control.value.length > 0;
}

// ----------------------------------------------------------------------------
// BTextBoxDate
// ----------------------------------------------------------------------------
var TageProMonat = new Array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function CheckTextBoxDate(ctrl, pLanguage, pMessage, pOnlyYear) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pLanguage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMessage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pOnlyYear" type="String" mayBeNull="false" optional="false">.</param>
    var control, maxTagMonat, tag, monat, jahr;

    if (null == (control = GetElementById(ctrl))) {
        return true;
    }
    
    if (0 == control.value.length) {
        return true;
    }

    if ("True" == pOnlyYear) {
        jahr = parseInt(control.value, 10);
        return jahr >= 0 && jahr <= 9999;
    }

    if ("de-DE" == pLanguage || "en-GB" == pLanguage || "it-IT" == pLanguage || "tr-TR" == pLanguage) {
        tag = parseInt(control.value.substr(0, 2), 10);
        monat = parseInt(control.value.substr(3, 2), 10);
        jahr = parseInt(control.value.substr(6, 4), 10);
    }
    else if ("en-US" == pLanguage) {
        monat = parseInt(control.value.substr(0, 2), 10);
        tag = parseInt(control.value.substr(3, 2), 10);
        jahr = parseInt(control.value.substr(6, 4), 10);
    }

    maxTagMonat = TageProMonat[monat];
    if (monat == 2) {
        if (jahr % 4 == 0) {
            if (jahr % 100 == 0) {
                if (jahr % 400 == 0) {
                    maxTagMonat = maxTagMonat + 1;
                }
            }
            else {
                maxTagMonat = maxTagMonat + 1;
            }
        }
    }

    if (tag >= 1 && tag <= maxTagMonat && monat >= 1 && monat <= 12) {
        return true;
    }
    else {
        SetValidationErrorMessage(ctrl, pMessage);
    }

    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxTime
// ----------------------------------------------------------------------------
function CheckTextBoxTime(ctrl, pMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMessage" type="String" mayBeNull="false" optional="false">.</param>
    var control, stunden, minuten;

    if (null == (control = GetElementById(ctrl))) {
        return true;
    }

    stunden = parseInt(control.value.substr(0, 2), 10);
    minuten = parseInt(control.value.substr(3, 2), 10);

    if (stunden >= 0 && stunden <= 23 && minuten >= 0 && minuten <= 59) {
        return true;
    }
    else {
        SetValidationErrorMessage(ctrl, pMessage);
    }

    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxTest
// ----------------------------------------------------------------------------
function CheckTextBoxInputLength(ctrl, pMinLen, pMaxLen, pMinMessage, pMaxMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinLen" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxLen" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinMessage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxMessage" type="String" mayBeNull="true" optional="false">.</param>
    var control, length;

    if (null == (control = GetElementById(ctrl))) {
        return true;
    }

    length = control.value.length;

    if (length < pMinLen) {
        SetValidationErrorMessage(ctrl, pMinMessage);
    }
    else if (length > pMaxLen) {
        SetValidationErrorMessage(ctrl, pMaxMessage);
    }
    else if (length == 0) {
        return true;
    }
    else {
        return true;
    }
    
    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxInteger2
// ----------------------------------------------------------------------------
function ValidateInputInteger(ctrl, pLanguage, pMinVal, pMaxVal, pMinMessage, pMaxMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pLanguage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinVal" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxVal" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinMessage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxMessage" type="String" mayBeNull="false" optional="false">.</param>
    var textbox, val, min, max;

    if (null == (textbox = GetElementById(ctrl))) {
        return true;
    }

    if (0 == textbox.value.length) {
        return true;
    }

    val = parseInt(textbox.value, 10);
    min = parseInt(pMinVal, 10);
    max = parseInt(pMaxVal, 10);

    if (min > val) {
        SetValidationErrorMessage(ctrl, pMinMessage);
    }
    else if (val > max) {
        SetValidationErrorMessage(ctrl, pMaxMessage);
    }
    else {
        return true;
    }

    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxCurrency
// ----------------------------------------------------------------------------
var OldCurrencyTextBoxValue;

function ValidateInputCurrency_SaveOldValue(ctrl, pEvent) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pEvent" domElement="true" mayBeNull="false" optional="false">.</param>
    if (null != (control = GetElementById(ctrl))) {
        OldCurrencyTextBoxValue = control.value;
    }
}

function ValidateInputCurrency(ctrl, pEvent, pLanguage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pEvent" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pLanguage" type="String" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = GetElementById(ctrl))) {
        if (control.value.length > 0) {
            if (!ValidateInput(ctrl, pLanguage, "Currency", null)) {
                control.value = OldCurrencyTextBoxValue;
                OldCurrencyTextBoxValue = null;
            }
            else {
                return true;
            }
        }
    }
    
    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxFloat2
// ----------------------------------------------------------------------------
function ValidateInputFloat(ctrl, pLanguage, pMinVal, pMaxVal, pMinMessage, pMaxMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pLanguage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinVal" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxVal" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinMessage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxMessage" type="String" mayBeNull="false" optional="false">.</param>
    var textbox, val, min, max;

    if (null == (textbox = GetElementById(ctrl))) {
        return true;
    }

    if (0 == textbox.value.length) {
        return true;
    }

    if ("de-DE" == pLanguage || "tr-TR" == pLanguage) {
        val = parseFloat(textbox.value.replace(/,/, "."), 10);
        min = parseFloat(pMinVal.replace(/,/, "."), 10);
        max = parseFloat(pMaxVal.replace(/,/, "."), 10);
    }
    else if ("it-IT" == pLanguage || "en-GB" == pLanguage) {
        val = parseFloat(textbox.value, 10);
        min = parseFloat(pMinVal, 10);
        max = parseFloat(pMaxVal, 10);
    }
    else {
        window.alert("pLanguage (" + pLanguage + ") is not supported for ValidateInputFloat.");
    }

    if (min > val) {
        SetValidationErrorMessage(ctrl, pMinMessage);
    }
    else if (val > max) {
        SetValidationErrorMessage(ctrl, pMaxMessage);
    }
    else {
        return true;
    }

    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxTest
// ----------------------------------------------------------------------------
function ValidateInput(ctrl, pLanguage, pPattern, pMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pLanguage" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pPattern" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMessage" type="String" mayBeNull="false" optional="false">.</param>
    var textbox, patterns, pattern, key, regEx, result;

    textbox = GetElementById(ctrl);

    if (null == textbox) {
        return true;
    }

    if (0 == textbox.value.length) {
        return true;
    }

    switch (pPattern) {
        case "Email":
            pattern = m_patterns.Email;
            break;
        case "Time":
            pattern = m_patterns.Time;
            break;
        case "Integer":
            pattern = m_patterns.Integer;
            break;
        case "Currency":
            // Möglichen Bindestrich entfernen
            key = (pLanguage.toString()).replace("-", "");

            if (!m_patterns.Currency[key]) {
                window.alert("pLanguage (" + pLanguage + ") is not supported for Currency.");
            }
            else {
                pattern = m_patterns.Currency[key];
            }

            break;
        case "Date":
            // Möglichen Bindestrich entfernen
            key = (pLanguage.toString()).replace("-", "");

            if (!m_patterns.Date[key]) {
                window.alert("pLanguage (" + pLanguage + ") is not supported for Date");
            }
            else {
                pattern = m_patterns.Date[key];
            }

            break;
        case "Float":
            // Möglichen Bindestrich entfernen
            key = (pLanguage.toString()).replace("-", "");

            if (!m_patterns.Float[key]) {
                window.alert("pLanguage (" + pLanguage + ") is not supported for Float");
            }
            else {
                pattern = m_patterns.Float[key];
            }

            break;
        default:
            window.alert("pPattern (" + pPattern + ") is not supported.");
            break;
    }
    
    if (textbox.value.length > 0) {
        regEx = new RegExp(pattern);
        result = textbox.value.match(regEx);

        if (null == result) {
            SetValidationErrorMessage(ctrl, pMessage);
        }
        else {
            if (result[0].length == textbox.value.length) {
                return true;
            }
            else {
                SetValidationErrorMessage(ctrl, pMessage);
            }
        }
    }
    else {
        SetValidationErrorMessage(ctrl, pMessage);
    }

    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxTest
// ----------------------------------------------------------------------------
function SetValidationErrorMessage(ctrl, pMessage) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMessage" type="String" mayBeNull="false" optional="false">.</param>
    var control, msgNode, brNode, spanNode, textFarbe;

    if (null != pMessage) {
        if (null != (control = GetElementById(ctrl))) {
            brNode = document.createElement("br");
            spanNode = document.createElement("span");
            textFarbe = document.createAttribute("class");
            textFarbe.nodeValue = "Validationfehlermeldung";

            spanNode.innerHTML = "<b>" + pMessage + "</b>";

            control.parentNode.insertBefore(spanNode, control.nextSibling);
            control.nextSibling.setAttributeNode(textFarbe);
            control.nextSibling.setAttribute("id", ctrl + "_err_span");
            control.nextSibling.firstChild.data = pMessage;
            control.parentNode.insertBefore(brNode, control.nextSibling);
            control.nextSibling.setAttribute("id", ctrl + "_err_br");
        }
        else {
            return true;
        }
    }
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
function RemoveValidationErrorMessage(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = GetElementById(ctrl + "_err_br"))) {
        control.parentNode.removeChild(control);
    }
    
    if (null != (control = GetElementById(ctrl + "_err_span"))) {
        control.parentNode.removeChild(control);
    }
    
    if (null != (control = GetElementById(ctrl + "_err_br"))) {
        control.parentNode.removeChild(control);
    }
    
    if (null != (control = GetElementById(ctrl + "_err_span"))) {
        control.parentNode.removeChild(control);
    }
}

// ----------------------------------------------------------------------------
// ErgebnisListeTitel
// ----------------------------------------------------------------------------
function ControlSichtbar(divName, sichtbar) {
    /// <summary>.</summary>
    /// <param name="divName" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="sichtbar" type="String" mayBeNull="false" optional="false">.</param>
    if (document.getElementById(divName)) {
            document.getElementById(divName).style.visibility = "true" == sichtbar ? "visible" : "hidden";
            document.getElementById(divName).style.display = "true" == sichtbar ? "block" : "none";
        }
    else {
        window.alert(pDivName);
    }
}

// ----------------------------------------------------------------------------
// BClickArea
// ----------------------------------------------------------------------------
function OverlaySichtbar(pEvent, pDivName, pSichtbar, pPosX, pPosY) {
    /// <summary>.</summary>
    /// <param name="pEvent" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pDivName" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pSichtbar" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pPosX" type="Nummber" integer="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pPosY" type="Nummber" integer="true" mayBeNull="false" optional="false">.</param>
    var posX, posY, divWidth, divHeight;

    pEvent.returnValue = false;

    if (document.getElementById(pDivName)) {
        var divi = document.getElementById(pDivName);

        if ("true" == pSichtbar) {
            divi.style.display = "block";
            divi.style.position = "absolute";
            divWidth = pEvent.clientX + divi.offsetWidth;
            divHeight = pEvent.clientY + divi.offsetHeight;
            
            if (divWidth > document.body.offsetWidth) {
                divi.style.left = parseInt(pEvent.clientX) + parseInt(document.body.scrollLeft) + 
                                  parseInt(pPosX) - parseInt(divi.offsetWidth) + 10;
            }
            else {
                divi.style.left = parseInt(pEvent.clientX) + parseInt(document.body.scrollLeft) + parseInt(pPosX);
            }
            if (divHeight > document.body.offsetHeight) {
                divi.style.top = parseInt(pEvent.clientY) + parseInt(document.body.scrollTop) + 
                                 parseInt(pPosY) - parseInt(divi.offsetHeight);
            }
            else {
                divi.style.top = parseInt(pEvent.clientY) + parseInt(document.body.scrollTop) + parseInt(pPosY);
            }

            divi.style.visibility = "visible";
        }
        else {
            divi.style.visibility = "hidden";
            divi.style.display = "none";
            divi.style.posLeft = 0;
            divi.style.posTop = 0;
        }
    }
    else {
        // window.alert("Fehler: DIV-Element " + pDivName + " nicht gefunden!");
    }
}

// ----------------------------------------------------------------------------
// BControl
// ----------------------------------------------------------------------------
function ContextMenueMussfeldSichtbar(ctrl, pDivName, pMussfeldBoxName, pSichtbarBoxName, pMussfeldOrg, pSichtbarOrg) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pDivName" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMussfeldBoxName" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pSichtbarBoxName" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMussfeldOrg" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pSichtbarOrg" type="String" mayBeNull="false" optional="false">.</param>
    var mussfeld, sichtbar;

    event.returnValue = false;
    
    if (document.getElementById(pDivName)) {
        if ("hidden" == document.getElementById(pDivName).style.visibility) {
            document.getElementById(pDivName).style.posLeft = parseFloat(event.clientX, 10);
            document.getElementById(pDivName).style.posTop = parseFloat(event.clientY, 10);
            document.getElementById(pDivName).style.visibility = "visible";
        }
        else {
            document.getElementById(pDivName).style.visibility = "hidden";
            mussfeld = document.getElementById(pMussfeldBoxName).checked;
            sichtbar = document.getElementById(pSichtbarBoxName).checked;

            if (String(mussfeld).toLowerCase() != String(pMussfeldOrg).toLowerCase() || 
                String(sichtbar).toLowerCase() != String(pSichtbarOrg).toLowerCase()) {
                return "CHECKED_" + mussfeld + "_" + sichtbar;
            }
            else {
                return null;
            }
        }
    }
    else {
        window.alert("Fehler: DIV-Element nicht gefunden!");
    }
    
    return null;
}

// ----------------------------------------------------------------------------
// BBaseControl
// ----------------------------------------------------------------------------
function SetHelpText(ctrl, pHelpText) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pHelpText" type="String" mayBeNull="false" optional="false">.</param>
    var o = document.getElementById(ctrl);

    if (null != o) {
        if (o.textContent) {
            o.textContent = pHelpText;
        }
        else {
            o.innerHTML = pHelpText;
        }

        // Für den (v)opac
        if ("undefined" != typeof (mutuallyExclusiveHelpAndErrorLabels)) {
            if (mutuallyExclusiveHelpAndErrorLabels) {
                var o2 = document.getElementById("BLabelErrorReplace");

                if (null != o2) {
                    o.style.display = pHelpText == "" ? "none" : "";
                    o2.style.display = pHelpText != "" ? "none" : "";
                }
            }
        }
    }
}

// ----------------------------------------------------------------------------
// BBaseControl
// ----------------------------------------------------------------------------
function SetFocus(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    if (null != document.getElementById(ctrl)) {
        document.getElementById(ctrl).focus();
    }
}

// ----------------------------------------------------------------------------
// BBaseButton
// ----------------------------------------------------------------------------
var FunctionKeyTable = new Array(12);

// ----------------------------------------------------------------------------
// BBaseButton
// ----------------------------------------------------------------------------
function FunctionKey_RegisterKey(pKey, ctrlID) {
    /// <summary>.</summary>
    /// <param name="pKey" type="" mayBeNull="false" optional="false">.</param>
    /// <param name="ctrlID" type="" mayBeNull="false" optional="false">.</param>
    FunctionKeyTable[pKey] = ctrlID;
}

// ----------------------------------------------------------------------------
// BBaseTextBox
// ----------------------------------------------------------------------------
function RemoveCharFromTextBox(ctrl, pPos) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pPos" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    var control, prefix, postfix;

    if (null != (control = document.getElementById(ctrl))) {
        if (pPos < control.value.length) {
            prefix = control.value.substring(0, pPos);
            postfix = control.value.substring(pPos + 1, control.value.length)
            control.value = prefix + postfix;
        }
    }
}

// ----------------------------------------------------------------------------
// BTextBoxBarcode
// ----------------------------------------------------------------------------
function CheckBarcodeInputLength(ctrl, pMinLen) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinLen" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = document.getElementById(ctrl))) {
        return control.value.length >= pMinLen;
    }

    return true;
}

// ----------------------------------------------------------------------------
// BTextBoxBarcode
// BTextBoxFloat
// ----------------------------------------------------------------------------
function IsCharInTextBox(ctrl, pKey) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pKey" type="String" mayBeNull="false" optional="false">.</param>
    var control, n;

    if (null != (control = document.getElementById(ctrl))) {
        if (control.value != null) {
            for (n = 0; n < control.value.length; n++) {
                if (control.value.charAt(n) == pKey) {
                    return true;
                }
            }
        }
    }

    return false;
}

// ----------------------------------------------------------------------------
// BTextBoxBarcode
// ----------------------------------------------------------------------------
function CheckBarcodeMaxLength(ctrl, pMaxLen) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxLen" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    var control;

    if (null != (control = document.getElementById(ctrl))) {
        if (control.value.length == pMaxLen) {
            control.blur();
        }
        else if (control.value.length > pMaxLen) {
            control.value = control.value.substr(0, pMaxLen);
            control.blur();
        }
    }
}

// ----------------------------------------------------------------------------
// BTextBoxInteger
// ----------------------------------------------------------------------------
function CheckIntTextBoxUp(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    var control, n;

    if (null != (control = document.getElementById(ctrl))) {
        for (n = 0; n < control.value.length; n++) {
            if ("-" == control.value.charAt(n)) {
                if (n != 0) {
                    RemoveCharFromTextBox(ctrl, n);
                }
            }
        }
    }
}

// ----------------------------------------------------------------------------
// BTextBoxInteger
// ----------------------------------------------------------------------------
function CheckIntTextBoxDown(ctrl) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    var stopKey = false;
    var code;

    if (null != (control = document.getElementById(ctrl))) {
        if (event.altKey || event.shiftKey || event.ctrlKey) {
            event.returnValue = false;
            event.cancelBubble = true;
            event.keyCode = 0;

            return false;
        }
        else {
            code = event.keyCode;
            
            if (9 == code) {
                // TAB input
                return true;
            }

            if (189 == code) {
                // "-" == 189
                stopKey = IsCharInTextBox(ctrl, "-");
            }
            else if (8 == code || 35 == code || 36 == code || 37 == code || 39 == code || 46 == code) {
                // ENTF, CURSLEFT, CURSRIGHT, BACKSPACE, POS1, END 
            }
            else if (48 <= code && code <= 57) {
                // 0,1,2,3,4,5,6,7,8,9 == 48-57
            }
            else if (96 <= code && code <= 105) {
                // 0,1,2,3,4,5,6,7,8,9 == 48-57 NUMPAD
            }
            else {
                stopKey = true;
            }

            if (stopKey) {
                event.returnValue = false;
                event.cancelBubble = true;
                0 == code;

                return false;
            }
        }
    }

    return true;
}

// ----------------------------------------------------------------------------
// BTextBoxInteger
// ----------------------------------------------------------------------------
function CheckIntMinMax(ctrl, pMinVal, pMaxVal) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinVal" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxVal" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    var control, val, max, min;

    if (null != (control = document.getElementById(ctrl))) {
        if (control.value != null) {
            val = parseInt(control.value);
            min = parseInt(pMinVal);
            max = parseInt(pMaxVal);

            if (val < min) {
                control.value = min.toString(10);
            }
            else if (val > max) {
                control.value = max.toString(10);
            }
            else {
                control.value = val.toString(10)
            }
        }
    }
}

// ----------------------------------------------------------------------------
// BTextBoxFloat
// ----------------------------------------------------------------------------
function CheckFloatTextBoxUp(ctrl, pMinVal, pMaxVal) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinVal" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxVal" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    var control, n;

    if (null != (control = document.getElementById(ctrl))) {
        for (n = 0; n < control.value.length; n++) {
            if ("-" == control.value.charAt(n)) {
                if (n != 0) {
                    RemoveCharFromTextBox(ctrl, n);
                }
            }
        }
    }
}

// ----------------------------------------------------------------------------
// BTextBoxFloat
// ----------------------------------------------------------------------------
function CheckFloatTextBoxDown(ctrl, pKommaCode, pKommaKey) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pKommaCode" type="Number" integer="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pKommaKey" type="String" mayBeNull="false" optional="false">.</param>
    var stopKey = false;
    var code;

    if (null != (control = document.getElementById(ctrl))) {
        if (event.altKey || event.shiftKey || event.ctrlKey) {
            event.returnValue = false;
            event.cancelBubble = true;
            event.keyCode = 0;

            return false;
        }
        else {
            code = event.keyCode;

            if (9 == code) {
                // TAB input 
                return true;
            }

            if (pKommaCode == code) {
                // "," == 188 / "." == 190
                stopKey = IsCharInTextBox(ctrl, pKommaKey);
            }
            else if (189 == code) {
                // "-" == 189
                stopKey = IsCharInTextBox(ctrl, "-");
            }
            else if (8 == code || 35 == code || 36 == code || 37 == code || 39 == code || 46 == code) {
                // ENTF, CURSLEFT, CURSRIGHT, BACKSPACE, POS1, END 
            }
            else if (48 <= code && code <= 57) {
                // 0,1,2,3,4,5,6,7,8,9 == 48-57
            }
            else if (96 <= code && code <= 105) {
                // 0,1,2,3,4,5,6,7,8,9 == 48-57 NUMPAD
            }
            else {
                stopKey = true;
            }
            
            if (stopKey) {
                event.returnValue = false;
                event.cancelBubble = true;
                event.keyCode = 0;
                return false;
            }
        }
    }

    return true;
}

// ----------------------------------------------------------------------------
// BTextBoxFloat
// ----------------------------------------------------------------------------
function StringToFloat(pValStr) {
    /// <summary>.</summary>
    /// <param name="pValStr" type="String" mayBeNull="false" optional="false">.</param>
    return parseFloat(pValStr.replace(/,/, "."), 10);
}

// ----------------------------------------------------------------------------
// BTextBoxFloat
// ----------------------------------------------------------------------------
function CheckFloatMinMax(ctrl, pMinVal, pMaxVal) {
    /// <summary>.</summary>
    /// <param name="ctrl" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="pMinVal" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="pMaxVal" type="String" mayBeNull="false" optional="false">.</param>
    var control, val, max, min;

    if (null != (control = document.getElementById(ctrl))) {
        if (null != control.value) {
            val = StringToFloat(control.value);
            min = StringToFloat(pMinVal);
            max = StringToFloat(pMaxVal);

            if (val < min) {
                control.value = min.toString(10);
            }
            else if (val > max) {
                control.value = max.toString(10);
            }
            else {
                control.value = val.toString(10);
            }
        }
    }
}

// ----------------------------------------------------------------------------
// Page
// onkeydown="Javascript: FunctionKey_Check( event );" onhelp="Javascript: return false;"
// ----------------------------------------------------------------------------
function FunctionKey_Check(event) {
	/// <summary>.</summary>
	/// <param name="pEvent" domElement="true" mayBeNull="false" optional="false">.</param>
	var browser;
	var keyCode = GetKeyCode(event);

	if (keyCode >= 114 && keyCode <= 123) {
		event.returnValue = false;
		event.cancelBubble = true;
		browser = CheckBrowser();

		if ("Netscape" == browser) {
			//wer macht denn so n schmarrn?
			//event.which = 0;
		}
		else if ("Explorer" == browser) {
			event.keyCode = 0;
		}

		if (null != FunctionKeyTable[keyCode - 112]) {
			if (null != document.getElementById(FunctionKeyTable[keyCode - 112])) {
				document.getElementById(FunctionKeyTable[keyCode - 112]).click();

				if (event.stopPropagation) event.stopPropagation();
				if (event.preventDefault) event.preventDefault();

			}
		}

		return false;
	}

	return true;
}

// ----------------------------------------------------------------------------
// BBasePage
// ----------------------------------------------------------------------------
function SetStatusText(pText) {
    /// <summary>.</summary>
    /// <param name="pText" type="String" mayBeNull="false" optional="false">.</param>
    if (null != document.getElementById("BLabelError")) {
        document.getElementById("BLabelError").style.color = "Navy";
        document.getElementById("BLabelError").innerText = pText;
    }
}

// ----------------------------------------------------------------------------
// BBasePage
// ----------------------------------------------------------------------------
function SetErrorText(pText) {
    /// <summary>.</summary>
    /// <param name="pText" type="String" mayBeNull="false" optional="false">.</param>
    if (null != document.getElementById("BLabelError")) {
        document.getElementById("BLabelError").style.color = "Red";
        document.getElementById("BLabelError").innerText = pText;
    }
}

// ----------------------------------------------------------------------------
// BTextBoxDate
// ----------------------------------------------------------------------------
/*  Copyright Mihai Bazon, 2002  |  http://students.infoiasi.ro/~mishoo
* ---------------------------------------------------------------------
*
* The DHTML Calendar, version 0.9.2 "The art of date selection"
*
* Details and latest version at:
* http://students.infoiasi.ro/~mishoo/site/calendar.epl
*
* Feel free to use this script under the terms of the GNU Lesser General
* Public License, as long as you do not remove or alter this notice.
*/
Calendar = function(mondayFirst, dateStr, onSelected, onClose) {
    /// <summary>The Calendar object constructor.</summary>
    /// <param name="mondayFirst" type="" mayBeNull="" optional="false">.</param>
    /// <param name="dateStr" type="String" mayBeNull="" optional="false">.</param>
    /// <param name="onSelected" type="Object" mayBeNull="true" optional="false">.</param>
    /// <param name="onClose" type="Object" mayBeNull="true" optional="false">.</param>
    // member variables
    this.activeDiv = null;
    this.currentDateEl = null;
    this.checkDisabled = null;
    this.timeout = null;
    this.onSelected = onSelected || null;
    this.onClose = onClose || null;
    this.dragging = false;
    this.hidden = false;
    this.minYear = 1970;
    this.maxYear = 2050;
    this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
    this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
    this.isPopup = true;
    this.weekNumbers = true;
    this.mondayFirst = mondayFirst;
    this.dateStr = dateStr;
    this.ar_days = null;
    
    // HTML elements
    this.table = null;
    this.element = null;
    this.tbody = null;
    this.firstdayname = null;
    
    // Combo boxes
    this.monthsCombo = null;
    this.yearsCombo = null;
    this.hilitedMonth = null;
    this.activeMonth = null;
    this.hilitedYear = null;
    this.activeYear = null;

    // one-time initializations
    if (!Calendar._DN3) {
        // table of short day names
        var ar = new Array();

        for (var i = 8; i > 0; ) {
            ar[--i] = Calendar._DN[i].substr(0, 2);
        }

        Calendar._DN3 = ar;

        // table of short month names
        ar = new Array();
        for (var i = 12; i > 0; ) {
            ar[--i] = Calendar._MN[i].substr(0, 3);
        }
        Calendar._MN3 = ar;
    }
};

// ----------------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------------
// "static", needed for event handlers.
Calendar._C = null;

// detect a special case of "web browser"
Calendar.is_ie = -1 != navigator.userAgent.toLowerCase().indexOf("msie") && 
                 -1 == navigator.userAgent.toLowerCase().indexOf("opera");

// short day names array (initialized at first constructor call)
Calendar._DN3 = null;

// short month names array (initialized at first constructor call)
Calendar._MN3 = null;

// ----------------------------------------------------------------------------
// Calendar utility functions
// ----------------------------------------------------------------------------
Calendar.getAbsolutePos = function(el) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    var r = {
        x: el.offsetLeft,
        y: el.offsetTop
    };

    if (el.offsetParent) {
        var tmp = Calendar.getAbsolutePos(el.offsetParent);
        r.x += tmp.x;
        r.y += tmp.y;
    }

    return r;
};

Calendar.isRelated = function(el, evt) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var related = evt.relatedTarget;

    if (!related) {
        var type = evt.type;

        switch (type) {
            case "mouseover":
                related = evt.fromElement;
                break;
            case "mouseout":
                related = evt.toElement;
                break;
            default:
                break;
        }
    }

    while (related) {
        if (related == el) {
            return true;
        }

        related = related.parentNode;
    }

    return false;
};

Calendar.removeClass = function(el, className) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="className" type="String" mayBeNull="false" optional="false">.</param>
    if (!(el && el.className)) {
        return;
    }

    var cls = el.className.split(" ");
    var ar = new Array();

    for (var i = cls.length; i > 0; ) {
        if (cls[--i] != className) {
            ar[ar.length] = cls[i];
        }
    }

    el.className = ar.join(" ");
};

Calendar.addClass = function(el, className) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="className" type="String" mayBeNull="false" optional="false">.</param>
    Calendar.removeClass(el, className);
    el.className += " " + className;
};

Calendar.getElement = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    return Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
};

Calendar.getTargetElement = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    return Calendar.is_ie ? window.event.srcElement : ev.target;
};

Calendar.stopEvent = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    if (Calendar.is_ie) {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
    }
    else {
        ev.preventDefault();
        ev.stopPropagation();
    }
};

Calendar.addEvent = function(el, evname, func) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="evname" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="func" type="" mayBeNull="" optional="false">.</param>
    if (Calendar.is_ie) {
        el.attachEvent("on" + evname, func);
    }
    else {
        el.addEventListener(evname, func, true);
    }
};

Calendar.removeEvent = function(el, evname, func) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    /// <param name="evname" type="String" mayBeNull="false" optional="false">.</param>
    /// <param name="func" type="" mayBeNull="" optional="false">.</param>
    if (Calendar.is_ie) {
        el.detachEvent("on" + evname, func);
    }
    else {
        el.removeEventListener(evname, func, true);
    }
};

Calendar.createElement = function(type, parent) {
    /// <summary>.</summary>
    /// <param name="type" type="" mayBeNull="false" optional="false">.</param>
    /// <param name="parent" domElement="true" mayBeNull="true" optional="false">.</param>
    var el = null;
    
    if (document.createElementNS) {
        // use the XHTML namespace; IE won't normally get here unless
        // _they_ "fix" the DOM2 implementation.
        el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
    }
    else {
        el = document.createElement(type);
    }
    
    if ("undefined" != typeof parent) {
        parent.appendChild(el);
    }
    
    return el;
};

// ----------------------------------------------------------------------------
// Calendar static functions
// ----------------------------------------------------------------------------
Calendar._add_evs = function(el) {
    /// <summary>Internal -- adds a set of events to make some element behave like a button.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    with (Calendar) {
        addEvent(el, "mouseover", dayMouseOver);
        addEvent(el, "mousedown", dayMouseDown);
        addEvent(el, "mouseout", dayMouseOut);
        
        if (is_ie) {
            addEvent(el, "dblclick", dayMouseDblClick);
            el.setAttribute("unselectable", true);
        }
    }
};

Calendar.findMonth = function(el) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    if (typeof el.month != "undefined") {
        return el;
    }
    else if (typeof el.parentNode.month != "undefined") {
        return el.parentNode;
    }

    return null;
};

Calendar.findYear = function(el) {
    /// <summary>.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    if ("undefined" != typeof el.year) {
        return el;
    }
    else if ("undefined" != typeof el.parentNode.year) {
        return el.parentNode;
    }

    return null;
};

Calendar.showMonthsCombo = function() {
    /// <summary>.</summary>
    var cal = Calendar._C;

    if (!cal) {
        return false;
    }

    var cal = cal;
    var cd = cal.activeDiv;
    var mc = cal.monthsCombo;

    if (cal.hilitedMonth) {
        Calendar.removeClass(cal.hilitedMonth, "hilite");
    }

    if (cal.activeMonth) {
        Calendar.removeClass(cal.activeMonth, "active");
    }

    var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
    Calendar.addClass(mon, "active");
    cal.activeMonth = mon;
    mc.style.left = cd.offsetLeft + "px";
    mc.style.top = (cd.offsetTop + cd.offsetHeight) + "px";
    mc.style.display = "block";
};

Calendar.showYearsCombo = function(fwd) {
    /// <summary>.</summary>
    /// <param name="fwd" type="" mayBeNull="" optional="false">.</param>
    var cal = Calendar._C;

    if (!cal) {
        return false;
    }

    var cal = cal;
    var cd = cal.activeDiv;
    var yc = cal.yearsCombo;

    if (cal.hilitedYear) {
        Calendar.removeClass(cal.hilitedYear, "hilite");
    }

    if (cal.activeYear) {
        Calendar.removeClass(cal.activeYear, "active");
    }

    cal.activeYear = null;
    var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
    var yr = yc.firstChild;
    var show = false;

    for (var i = 12; i > 0; --i) {
        if (Y >= cal.minYear && Y <= cal.maxYear) {
            yr.firstChild.data = Y;
            yr.year = Y;
            yr.style.display = "block";
            show = true;
        }
        else {
            yr.style.display = "none";
        }

        yr = yr.nextSibling;
        Y += fwd ? 2 : -2;
    }

    if (show) {
        yc.style.left = cd.offsetLeft + "px";
        yc.style.top = (cd.offsetTop + cd.offsetHeight) + "px";
        yc.style.display = "block";
    }
};

Calendar.tableMouseUp = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var cal = Calendar._C;

    if (!cal) {
        return false;
    }

    if (cal.timeout) {
        clearTimeout(cal.timeout);
    }

    var el = cal.activeDiv;

    if (!el) {
        return false;
    }

    var target = Calendar.getTargetElement(ev);
    Calendar.removeClass(el, "active");

    if (target == el || target.parentNode == el) {
        Calendar.cellClick(el);
    }

    var mon = Calendar.findMonth(target);
    var date = null;

    if (mon) {
        date = new Date(cal.date);
        if (mon.month != date.getMonth()) {
            date.setMonth(mon.month);
            cal.setDate(date);
        }
    }
    else {
        var year = Calendar.findYear(target);
        if (year) {
            date = new Date(cal.date);
            
            if (year.year != date.getFullYear()) {
                date.setFullYear(year.year);
                cal.setDate(date);
            }
        }
    }
    
    with (Calendar) {
        removeEvent(document, "mouseup", tableMouseUp);
        removeEvent(document, "mouseover", tableMouseOver);
        removeEvent(document, "mousemove", tableMouseOver);
        cal._hideCombos();
        stopEvent(ev);
        _C = null;
    }
};

Calendar.tableMouseOver = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var cal = Calendar._C;

    if (!cal) {
        return;
    }

    var el = cal.activeDiv;
    var target = Calendar.getTargetElement(ev);

    if (target == el || target.parentNode == el) {
        Calendar.addClass(el, "hilite active");
        Calendar.addClass(el.parentNode, "rowhilite");
    }
    else {
        Calendar.removeClass(el, "active");
        Calendar.removeClass(el, "hilite");
        Calendar.removeClass(el.parentNode, "rowhilite");
    }
    
    var mon = Calendar.findMonth(target);
    
    if (mon) {
        if (mon.month != cal.date.getMonth()) {
            if (cal.hilitedMonth) {
                Calendar.removeClass(cal.hilitedMonth, "hilite");
            }
            
            Calendar.addClass(mon, "hilite");
            cal.hilitedMonth = mon;
        }
        else if (cal.hilitedMonth) {
            Calendar.removeClass(cal.hilitedMonth, "hilite");
        }
    }
    else {
        var year = Calendar.findYear(target);
        
        if (year) {
            if (year.year != cal.date.getFullYear()) {
                if (cal.hilitedYear) {
                    Calendar.removeClass(cal.hilitedYear, "hilite");
                }
                
                Calendar.addClass(year, "hilite");
                cal.hilitedYear = year;
            }
            else if (cal.hilitedYear) {
                Calendar.removeClass(cal.hilitedYear, "hilite");
            }
        }
    }
    
    Calendar.stopEvent(ev);
};

Calendar.tableMouseDown = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
        Calendar.stopEvent(ev);
    }
};

Calendar.calDragIt = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var cal = Calendar._C;

    if (!(cal && cal.dragging)) {
        return false;
    }

    var posX;
    var posY;

    if (Calendar.is_ie) {
        posY = window.event.clientY + document.body.scrollTop;
        posX = window.event.clientX + document.body.scrollLeft;
    }
    else {
        posX = ev.pageX;
        posY = ev.pageY;
    }

    cal.hideShowCovered();
    var st = cal.element.style;
    st.left = (posX - cal.xOffs) + "px";
    st.top = (posY - cal.yOffs) + "px";
    Calendar.stopEvent(ev);
};

Calendar.calDragEnd = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var cal = Calendar._C;

    if (!cal) {
        return false;
    }

    cal.dragging = false;

    with (Calendar) {
        removeEvent(document, "mousemove", calDragIt);
        removeEvent(document, "mouseover", stopEvent);
        removeEvent(document, "mouseup", calDragEnd);
        tableMouseUp(ev);
    }

    cal.hideShowCovered();
};

Calendar.dayMouseDown = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var el = Calendar.getElement(ev);

    if (el.disabled) {
        return false;
    }

    var cal = el.calendar;
    cal.activeDiv = el;
    Calendar._C = cal;

    if (300 != el.navtype) {
        with (Calendar) {
            addClass(el, "hilite active");
            addEvent(document, "mouseover", tableMouseOver);
            addEvent(document, "mousemove", tableMouseOver);
            addEvent(document, "mouseup", tableMouseUp);
        }
    }
    else if (cal.isPopup) {
        cal._dragStart(ev);
    }

    Calendar.stopEvent(ev);

    if (-1 == el.navtype || 1 == el.navtype) {
        cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
    }
    else if (-2 == el.navtype || 2 == el.navtype) {
        cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
    }
    else {
        cal.timeout = null;
    }
};

Calendar.dayMouseDblClick = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    Calendar.cellClick(Calendar.getElement(ev));

    if (Calendar.is_ie) {
        document.selection.empty();
    }
};

Calendar.dayMouseOver = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    var el = Calendar.getElement(ev);

    if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
        return false;
    }

    if (el.ttip) {
        if ("_" == el.ttip.substr(0, 1)) {
            var date = null;

            with (el.calendar.date) {
                date = new Date(getFullYear(), getMonth(), el.caldate);
            }

            el.ttip = date.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
        }

        el.calendar.tooltips.firstChild.data = el.ttip;
    }

    if (el.navtype != 300) {
        Calendar.addClass(el, "hilite");

        if (el.caldate) {
            Calendar.addClass(el.parentNode, "rowhilite");
        }
    }

    Calendar.stopEvent(ev);
};

Calendar.dayMouseOut = function(ev) {
    /// <summary>.</summary>
    /// <param name="ev" domElement="true" mayBeNull="false" optional="false">.</param>
    with (Calendar) {
        var el = getElement(ev);

        if (isRelated(el, ev) || _C || el.disabled) {
            return false;
        }

        removeClass(el, "hilite");

        if (el.caldate) {
            removeClass(el.parentNode, "rowhilite");
        }

        el.calendar.tooltips.firstChild.data = _TT["SEL_DATE"];
        stopEvent(ev);
    }
};

Calendar.cellClick = function(el) {
    /// <summary>A generic "click" handler :) handles all types of buttons defined in this calendar.</summary>
    /// <param name="el" domElement="true" mayBeNull="false" optional="false">.</param>
    var cal = el.calendar;
    var closing = false;
    var newdate = false;
    var date = null;

    if ("undefined" == typeof el.navtype) {
        Calendar.removeClass(cal.currentDateEl, "selected");
        Calendar.addClass(el, "selected");
        closing = (cal.currentDateEl == el);

        if (!closing) {
            cal.currentDateEl = el;
        }

        cal.date.setDate(el.caldate);
        date = cal.date;
        newdate = true;
    }
    else {
        if (el.navtype == 200) {
            Calendar.removeClass(el, "hilite");
            cal.callCloseHandler();
            return;
        }

        date = (el.navtype == 0) ? new Date() : new Date(cal.date);
        var year = date.getFullYear();
        var mon = date.getMonth();
        
        function setMonth(m) {
            /// <summary></summary>
            var day = date.getDate();
            var max = date.getMonthDays(m);

            if (day > max) {
                date.setDate(max);
            }

            date.setMonth(m);
        };
        
        switch (el.navtype) {
            case -2:
                if (year > cal.minYear) {
                    date.setFullYear(year - 1);
                }
                break;
            case -1:
                if (mon > 0) {
                    setMonth(mon - 1);
                }
                else if (year-- > cal.minYear) {
                    date.setFullYear(year);
                    setMonth(11);
                }
                break;
            case 1:
                if (mon < 11) {
                    setMonth(mon + 1);
                }
                else if (year < cal.maxYear) {
                    date.setFullYear(year + 1);
                    setMonth(0);
                }
                break;
            case 2:
                if (year < cal.maxYear) {
                    date.setFullYear(year + 1);
                }
                break;
            case 100:
                cal.setMondayFirst(!cal.mondayFirst);
                return;
        }
        
        if (!date.equalsTo(cal.date)) {
            cal.setDate(date);
            newdate = el.navtype == 0;
        }
    }
    
    if (newdate) {
        cal.callHandler();
    }
    
    if (closing) {
        Calendar.removeClass(el, "hilite");
        cal.callCloseHandler();
    }
};

// ----------------------------------------------------------------------------
// Calendar object functions
// ----------------------------------------------------------------------------
Calendar.prototype.create = function(_par) {
    /// <summary>
    /// This function creates the calendar inside the given parent. If _par is null
    /// than it creates a popup calendar inside the BODY element. If _par is an element,
    /// be it BODY, then it creates a non-popup calendar (still hidden). 
    /// Some properties need to be set before calling this function.
    /// </summary>
    /// <param name="_par" domElement="true" mayBeNull="true" optional="false">.</param>
    var parent = null;

    if (!_par) {
        // Default parent is the document body, in which case we create a popup calendar.
        parent = document.getElementsByTagName("body")[0];
        this.isPopup = true;
    }
    else {
        parent = _par;
        this.isPopup = false;
    }

    this.date = this.dateStr ? new Date(this.dateStr) : new Date();

    var table = Calendar.createElement("table");
    this.table = table;
    table.cellSpacing = 0;
    table.cellPadding = 0;
    table.calendar = this;
    Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);

    var div = Calendar.createElement("div");
    this.element = div;
    div.className = "calendar";
    
    if (this.isPopup) {
        div.style.position = "absolute";
        div.style.display = "none";
    }
    
    div.appendChild(table);

    var thead = Calendar.createElement("thead", table);
    var cell = null;
    var row = null;

    var cal = this;
    var hh = function(text, cs, navtype) {
        cell = Calendar.createElement("td", row);
        cell.colSpan = cs;
        cell.className = "button";
        Calendar._add_evs(cell);
        cell.calendar = cal;
        cell.navtype = navtype;
        if (text.substr(0, 1) != "&") {
            cell.appendChild(document.createTextNode(text));
        }
        else {
            // FIXME: dirty hack for entities
            cell.innerHTML = text;
        }
        return cell;
    };

    row = Calendar.createElement("tr", thead);
    var title_length = 6;
    (this.isPopup) && --title_length;
    (this.weekNumbers) && ++title_length;

    hh("-", 1, 100).ttip = Calendar._TT["TOGGLE"];
    this.title = hh("", title_length, 300);
    this.title.className = "title";
    
    if (this.isPopup) {
        this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
        this.title.style.cursor = "move";
        hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
    }

    row = Calendar.createElement("tr", thead);
    row.className = "headrow";

    this._nav_py = hh("&#x00ab;", 1, -2);
    this._nav_py.ttip = Calendar._TT["PREV_YEAR"];

    this._nav_pm = hh("&#x2039;", 1, -1);
    this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];

    this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
    this._nav_now.ttip = Calendar._TT["GO_TODAY"];

    this._nav_nm = hh("&#x203a;", 1, 1);
    this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];

    this._nav_ny = hh("&#x00bb;", 1, 2);
    this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"]

    // day names
    row = Calendar.createElement("tr", thead);
    row.className = "daynames";
    if (this.weekNumbers) {
        cell = Calendar.createElement("td", row);
        cell.className = "name wn";
        cell.appendChild(document.createTextNode(Calendar._TT["WK"]));
    }
    
    for (var i = 7; i > 0; --i) {
        cell = Calendar.createElement("td", row);
        cell.appendChild(document.createTextNode(""));
        if (!i) {
            cell.navtype = 100;
            cell.calendar = this;
            Calendar._add_evs(cell);
        }
    }
    
    this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
    this._displayWeekdays();

    var tbody = Calendar.createElement("tbody", table);
    this.tbody = tbody;

    for (i = 6; i > 0; --i) {
        row = Calendar.createElement("tr", tbody);
        if (this.weekNumbers) {
            cell = Calendar.createElement("td", row);
            cell.appendChild(document.createTextNode(""));
        }
        
        for (var j = 7; j > 0; --j) {
            cell = Calendar.createElement("td", row);
            cell.appendChild(document.createTextNode(""));
            cell.calendar = this;
            Calendar._add_evs(cell);
        }
    }

    var tfoot = Calendar.createElement("tfoot", table);

    row = Calendar.createElement("tr", tfoot);
    row.className = "footrow";

    cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
    cell.className = "ttip";
    
    if (this.isPopup) {
        cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
        cell.style.cursor = "move";
    }
    
    this.tooltips = cell;

    div = Calendar.createElement("div", this.element);
    this.monthsCombo = div;
    div.className = "combo";
    
    for (i = 0; i < Calendar._MN.length; ++i) {
        var mn = Calendar.createElement("div");
        mn.className = "label";
        mn.month = i;
        mn.appendChild(document.createTextNode(Calendar._MN3[i]));
        div.appendChild(mn);
    }

    div = Calendar.createElement("div", this.element);
    this.yearsCombo = div;
    div.className = "combo";
    
    for (i = 12; i > 0; --i) {
        var yr = Calendar.createElement("div");
        yr.className = "label";
        yr.appendChild(document.createTextNode(""));
        div.appendChild(yr);
    }

    this._init(this.mondayFirst, this.date);
    parent.appendChild(this.element);
};

Calendar._keyEvent = function(ev) {
    /// <summary>Keyboard navigation, only for popup calendars.</summary>
    /// <param name="ev" domElement="true" optional="false">.</param>
    if (!window.calendar) {
        return false;
    }

    (Calendar.is_ie) && (ev = window.event);

    var cal = window.calendar;
    var act = Calendar.is_ie || "keypress" == ev.type;

    if (ev.ctrlKey) {
        switch (ev.keyCode) {
            case 37: // KEY left
                act && Calendar.cellClick(cal._nav_pm);
                break;
            case 38: // KEY up
                act && Calendar.cellClick(cal._nav_py);
                break;
            case 39: // KEY right
                act && Calendar.cellClick(cal._nav_nm);
                break;
            case 40: // KEY down
                act && Calendar.cellClick(cal._nav_ny);
                break;
            default:
                return false;
        }
    }
    else switch (ev.keyCode) {
        case 32: // KEY space (now)
            Calendar.cellClick(cal._nav_now);
            break;
        case 27: // KEY esc
            act && cal.hide();
            break;
        case 37: // KEY left
        case 38: // KEY up
        case 39: // KEY right
        case 40: // KEY down
            if (act) {
                var date = cal.date.getDate() - 1;
                var el = cal.currentDateEl;
                var ne = null;
                var prev = (ev.keyCode == 37) || (ev.keyCode == 38);
                
                switch (ev.keyCode) {
                    case 37: // KEY left
                        (--date >= 0) && (ne = cal.ar_days[date]);
                        break;
                    case 38: // KEY up
                        date -= 7;
                        (date >= 0) && (ne = cal.ar_days[date]);
                        break;
                    case 39: // KEY right
                        (++date < cal.ar_days.length) && (ne = cal.ar_days[date]);
                        break;
                    case 40: // KEY down
                        date += 7;
                        (date < cal.ar_days.length) && (ne = cal.ar_days[date]);
                        break;
                }
                
                if (!ne) {
                    Calendar.cellClick(prev ? cal._nav_pm : cal._nav_nm);
                    
                    date = prev ? cal.date.getMonthDays() : 1;
                    el = cal.currentDateEl;
                    ne = cal.ar_days[date - 1];
                }
                
                Calendar.removeClass(el, "selected");
                Calendar.addClass(ne, "selected");
                cal.date.setDate(ne.caldate);
                cal.currentDateEl = ne;
            }
            break;
        case 13: // KEY enter
            if (act) {
                cal.callHandler();
                cal.hide();
            }
            break;
        default:
            return false;
    }
    
    Calendar.stopEvent(ev);
};

Calendar.prototype._init = function(mondayFirst, date) {
    /// <summary>
    /// (Re)Initializes the calendar to the given date and style (if mondayFirst is
    /// true it makes Monday the first day of week, otherwise the weeks start on Sunday.
    /// </summary>
    /// <param name="mondayFirst" type="" optional="false">.</param>
    /// <param name="date" type="" optional="false">.</param>
    var today = new Date();
    var year = date.getFullYear();

    if (year < this.minYear) {
        year = this.minYear;
        date.setFullYear(year);
    }
    else if (year > this.maxYear) {
        year = this.maxYear;
        date.setFullYear(year);
    }

    this.mondayFirst = mondayFirst;
    this.date = new Date(date);

    var month = date.getMonth();
    var mday = date.getDate();
    var no_days = date.getMonthDays();

    date.setDate(1);

    var wday = date.getDay();
    var MON = mondayFirst ? 1 : 0;
    var SAT = mondayFirst ? 5 : 6;
    var SUN = mondayFirst ? 6 : 0;

    if (mondayFirst) {
        wday = wday > 0 ? wday - 1 : 6;
    }

    var iday = 1;
    var row = this.tbody.firstChild;
    var MN = Calendar._MN3[month];
    var hasToday = year == today.getFullYear() && month == today.getMonth();
    var todayDate = today.getDate();
    var week_number = date.getWeekNumber();
    var ar_days = new Array();

    for (var i = 0; i < 6; ++i) {
        if (iday > no_days) {
            row.className = "emptyrow";
            row = row.nextSibling;
            continue;
        }

        var cell = row.firstChild;

        if (this.weekNumbers) {
            cell.className = "day wn";
            cell.firstChild.data = week_number;
            cell = cell.nextSibling;
        }

        ++week_number;

        row.className = "daysrow";

        for (var j = 0; j < 7; ++j) {
            cell.className = "day";

            if ((!i && j < wday) || iday > no_days) {
                // cell.className = "emptycell";
                cell.innerHTML = "&nbsp;";
                cell.disabled = true;
                cell = cell.nextSibling;
                continue;
            }

            cell.disabled = false;
            cell.firstChild.data = iday;

            if ("function" == typeof this.checkDisabled) {
                date.setDate(iday);

                if (this.checkDisabled(date)) {
                    cell.className += " disabled";
                    cell.disabled = true;
                }
            }

            if (!cell.disabled) {
                ar_days[ar_days.length] = cell;
                cell.caldate = iday;
                cell.ttip = "_";

                if (iday == mday) {
                    cell.className += " selected";
                    this.currentDateEl = cell;
                }

                if (hasToday && (iday == todayDate)) {
                    cell.className += " today";
                    cell.ttip += Calendar._TT["PART_TODAY"];
                }

                if (wday == SAT || wday == SUN) {
                    cell.className += " weekend";
                }
            }

            ++iday;
            ((++wday) ^ 7) || (wday = 0);
            cell = cell.nextSibling;
        }

        row = row.nextSibling;
    }

    this.ar_days = ar_days;
    this.title.firstChild.data = Calendar._MN[month] + ", " + year;
    // PROFILE
    // this.tooltips.firstChild.data = "Generated in " + ((new Date()) - today) + " ms";
};

Calendar.prototype.setDate = function(date) {
    /// <summary>
    /// Calls _init function above for going to a certain date (but only if the date is 
    /// different than the currently selected one).
    /// </summary>
    /// <param name="date" type="" optional="false">.</param>
    if (!date.equalsTo(this.date)) {
        this._init(this.mondayFirst, date);
    }
};

Calendar.prototype.setMondayFirst = function(mondayFirst) {
    /// <summary>Modifies the "mondayFirst" parameter (EU/US style).</summary>
    /// <param name="mondayFirst" type="" optional="false">.</param>
    this._init(mondayFirst, this.date);
    this._displayWeekdays();
};

Calendar.prototype.setDisabledHandler = function(unaryFunction) {
    /// <summary>Allows customization of what dates are enabled.</summary>
    /// <param name="unaryFunction" type="Object" optional="false">.</param>
    /// <remarks>
    /// The "unaryFunction" parameter must be a function object that receives the date
    /// (as a JS Date object) and returns a boolean value.  If the returned value is true 
    /// then the passed date will be marked as disabled.
    /// </remarks>
    this.checkDisabled = unaryFunction;
};

Calendar.prototype.setRange = function(a, z) {
    /// <summary>Customization of allowed year range for the calendar.</summary>
    /// <param name="a" type="Number" integer="true" optional="false">.</param>
    /// <param name="z" type="Number" integer="true" optional="false">.</param>
    this.minYear = a;
    this.maxYear = z;
};

Calendar.prototype.callHandler = function() {
    /// <summary>Calls the first user handler (selectedHandler).</summary>
    if (this.onSelected) {
        this.onSelected(this, this.date.print(this.dateFormat));
    }
};

Calendar.prototype.callCloseHandler = function() {
    /// <summary>Calls the second user handler (closeHandler).</summary>
    if (this.onClose) {
        this.onClose(this);
    }


    this.hideShowCovered();
};

Calendar.prototype.destroy = function() {
    /// <summary>Removes the calendar object from the DOM tree and destroys it.</summary>
    var el = this.element.parentNode;

    el.removeChild(this.element);
    Calendar._C = null;
    delete el;
};

Calendar.prototype.reparent = function(new_parent) {
    /// <summary>Moves the calendar element to a different section in the DOM tree (changes its parent).</summary>
    /// <param name="new_parent" domElement="true" optional="false">.</param>
    var el = this.element;

    el.parentNode.removeChild(el);
    new_parent.appendChild(el);
};

Calendar._checkCalendar = function(ev) {
    /// <summary>Shows the calendar near a given element.</summary>
    /// <param name="ev" domElement="true" optional="false">.</param>
    /// <remarks>
    /// This gets called when the user presses a mouse button anywhere in the
    /// document, if the calendar is shown.  If the click was outside the open
    /// calendar this function closes it.
    /// </remarks>
    if (!window.calendar) {
        return false;
    }

    var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);

    for (; el != null && el != calendar.element; el = el.parentNode) {
        if (el == null) {
            // calls closeHandler which should hide the calendar.
            window.calendar.callCloseHandler();
            Calendar.stopEvent(ev);
        }
    }
};

Calendar.prototype.show = function() {
    /// <summary>Shows the calendar.</summary>
    var rows = this.table.getElementsByTagName("tr");
    var i, row, cells, j, cell;

    for (i = rows.length; i > 0;) {
        row = rows[--i];
        Calendar.removeClass(row, "rowhilite");
        cells = row.getElementsByTagName("td");

        for (j = cells.length; j > 0;) {
            cell = cells[--j];
            Calendar.removeClass(cell, "hilite");
            Calendar.removeClass(cell, "active");
        }
    }

    this.element.style.display = "block";
    this.hidden = false;

    if (this.isPopup) {
        window.calendar = this;
        Calendar.addEvent(document, "keydown", Calendar._keyEvent);
        Calendar.addEvent(document, "keypress", Calendar._keyEvent);
        Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
    }
    this.hideShowCovered();
};

Calendar.prototype.hide = function() {
    /// <summary>Hides the calendar. Also removes any "hilite" from the class of any TD element.</summary>
    if (this.isPopup) {
        Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
        Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
        Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
    }
    
    this.element.style.display = "none";
    this.hidden = true;
    this.hideShowCovered();
};

Calendar.prototype.showAt = function(x, y) {
    /// <summary>Shows the calendar at a given absolute position.</summary>
    /// <param name="x" type="Number" integer="true" optional="false">.</param>
    /// <param name="y" type="Number" integer="true" optional="false">.</param>
    /// <remarks>
    /// Beware that, depending on the calendar element style -- position property --
    /// this might be relative to the parent's containing rectangle
    /// </remarks>
    var s = this.element.style;
    s.left = x + "px";
    s.top = y + "px";
    this.show();
};

Calendar.prototype.showAtElement = function(el) {
    /// <summary>Shows the calendar near a given element.</summary>
    /// <param name="el" domElement="true" optional="false">.</param>
    var p = Calendar.getAbsolutePos(el);
    this.showAt(p.x, p.y + el.offsetHeight);
};

Calendar.prototype.setDateFormat = function(str) {
    /// <summary>Customizes the date format.</summary>
    /// <param name="str" type="String" optional="false">.</param>
    this.dateFormat = str;
};

Calendar.prototype.setTtDateFormat = function(str) {
    /// <summary>Customizes the tooltip date format.</summary>
    /// <param name="str" type="String" optional="false">.</param>
    this.ttDateFormat = str;
};

Calendar.prototype.parseDate = function(str, fmt) {
    /// <summary>
    /// Tries to identify the date represented in a string. If successful it
    /// also calls this.setDate which moves the calendar to the given date.
    /// </summary>
    /// <param name="str" domElement="true" optional="false">.</param>
    /// <param name="fmt" domElement="true" optional="false">.</param>
    var y = 0;
    var m = -1;
    var d = 0;
    var a = str.split(/\W+/);
    var b, i;

    if (!fmt) {
        fmt = this.dateFormat;
    }

    b = fmt.split(/\W+/);
    i = 0, j = 0;

    for (i = 0; i < a.length; ++i) {
        if ("D" == b[i] || "DD" == b[i]) {
            continue;
        }

        if ("d" == b[i] || "dd" == b[i]) {
            d = parseInt(a[i], 10);
        }

        if ("m" == b[i] || "mm" == b[i]) {
            m = parseInt(a[i], 10) - 1;
        }

        if ("y" == b[i]) {
            y = parseInt(a[i], 10);
        }

        if ("yy" == b[i]) {
            y = parseInt(a[i], 10) + 1900;
        }

        if ("M" == b[i] || "MM" == b[i]) {
            for (j = 0; j < 12; ++j) {
                if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
                    m = j;
                    break;
                }
            }
        }
    }

    if (0 != y && -1 != m && 0 != d) {
        this.setDate(new Date(y, m, d));
        return;
    }

    y = 0;
    m = -1;
    d = 0;
    for (i = 0; i < a.length; ++i) {
        if (a[i].search(/[a-zA-Z]+/) != -1) {
            var t = -1;

            for (j = 0; j < 12; ++j) {
                if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
                    t = j; break;
                }
            }

            if (-1 != t) {
                if (-1 != m) {
                    d = m + 1;
                }

                m = t;
            }
        }
        else if (parseInt(a[i], 10) <= 12 && -1 == m) {
            m = a[i] - 1;
        }
        else if (parseInt(a[i], 10) > 31 && 0 == y) {
            y = a[i];
        }
        else if (0 == d) {
            d = a[i];
        }
    }

    if (0 == y) {
        y = (new Date()).getFullYear();
    }

    if (-1 != m && 0 != d) {
        this.setDate(new Date(y, m, d));
    }
};

Calendar.prototype.hideShowCovered = function() {
    /// <summary>.</summary>
    var tags = new Array("applet", "iframe", "select");
    var el = this.element;

    var p = Calendar.getAbsolutePos(el);
    var EX1 = p.x;
    var EX2 = el.offsetWidth + EX1;
    var EY1 = p.y;
    var EY2 = el.offsetHeight + EY1;
    var i, k, CX1, CX2, CY1, CY2, ar, cc;

    for (k = tags.length; k > 0; ) {
        ar = document.getElementsByTagName(tags[--k]);
        cc = null;

        for (i = ar.length; i > 0; ) {
            cc = ar[--i];

            p = Calendar.getAbsolutePos(cc);
            CX1 = p.x;
            CX2 = cc.offsetWidth + CX1;
            CY1 = p.y;
            CY2 = cc.offsetHeight + CY1;

            cc.style.visibility = (this.hidden || CX1 > EX2 || CX2 < EX1 || CY1 > EY2 || CY2 < EY1) ? "visible" : "hidden";
        }
    }
};

Calendar.prototype._displayWeekdays = function() {
    /// <summary>Displays the bar with the names of the weekday.</summary>
    var MON = this.mondayFirst ? 0 : 1;
    var SUN = this.mondayFirst ? 6 : 0;
    var SAT = this.mondayFirst ? 5 : 6;
    var cell = this.firstdayname;
    var i;

    for (i = 0; i < 7; ++i) {
        cell.className = "day name";

        if (!i) {
            cell.ttip = this.mondayFirst ? Calendar._TT["SUN_FIRST"] : Calendar._TT["MON_FIRST"];
            cell.navtype = 100;
            cell.calendar = this;
            Calendar._add_evs(cell);
        }

        if (i == SUN || i == SAT) {
            Calendar.addClass(cell, "weekend");
        }

        cell.firstChild.data = Calendar._DN3[i + 1 - MON];
        cell = cell.nextSibling;
    }
};

Calendar.prototype._hideCombos = function() {
    /// <summary>Hides all combo boxes that might be displayed.</summary>
    this.monthsCombo.style.display = "none";
    this.yearsCombo.style.display = "none";
};

Calendar.prototype._dragStart = function(ev) {
    /// <summary>Internal function. Starts dragging the element.</summary>
    /// <param name="ev" domElement="true" optional="false">.</param>
    if (this.dragging) {
        return;
    }

    this.dragging = true;

    var posX = Calendar.is_ie ? window.event.clientX + document.body.scrollLeft : ev.clientX + window.scrollX;
    var posY = Calendar.is_ie ? window.event.clientY + document.body.scrollTop : ev.clientY + window.scrollY;
    var st = this.element.style;
    this.xOffs = posX - parseInt(st.left);
    this.yOffs = posY - parseInt(st.top);

    with (Calendar) {
        addEvent(document, "mousemove", calDragIt);
        addEvent(document, "mouseover", stopEvent);
        addEvent(document, "mouseup", calDragEnd);
    }
};

// ----------------------------------------------------------------------------
// Date Object Patches
// ----------------------------------------------------------------------------
// Adds the number of days array to the Date object
Date._MD = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

// Constants used for time computations
Date.SECOND = 1000;  // milliseconds
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR = 60 * Date.MINUTE;
Date.DAY = 24 * Date.HOUR;
Date.WEEK = 7 * Date.DAY;

Date.prototype.getMonthDays = function(month) {
    /// <summary>Returns the number of days in the current month.</summary>
    /// <param name="month" type="Number" integer="true" optional="true">.</param>
    var year = this.getFullYear();

    if ("undefined" == typeof month) {
        month = this.getMonth();
    }

    if ((0 == (year % 4) && (0 != (year % 100) || 0 == (year % 400))) && month == 1) {
        return 29;
    }
    else {
        return Date._MD[month];
    }
};

Date.prototype.getWeekNumber = function() {
    /// <summary>Returns the number of the week.</summary>
    /// <remarks>The algorithm was "stolen" from PPK's website, hope it's correct :) http://www.xs4all.nl/~ppk/js/week.html</remarks>
    var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
    var then = new Date(this.getFullYear(), 0, 1, 0, 0, 0);
    var time = now - then;
    var day = then.getDay();

    (day > 3) && (day -= 4) || (day += 3);

    return Math.round(((time / Date.DAY) + day) / 7);
};

Date.prototype.equalsTo = function(date) {
    /// <summary>Checks dates equality (ignores time).</summary>
    /// <param name="date" type="Date" optional="false">.</param>
    return (date.getFullYear() == this.getFullYear() && date.getMonth() == this.getMonth() && date.getDate() == this.getDate());
};

Date.prototype.print = function(frm) {
    /// <summary>Prints the date in a string according to the given format.</summary>
    /// <param name="frm" type="String" optional="false">.</param>
    var str = new String(frm);
    var m = this.getMonth();
    var d = this.getDate();
    var y = this.getFullYear();
    var wn = this.getWeekNumber();
    var w = this.getDay();
    var s = new Array();

    s["d"] = d;
    s["dd"] = d < 10 ? "0" + d : d;
    s["m"] = 1 + m;
    s["mm"] = m < 9 ? "0" + (1 + m) : 1 + m;
    s["y"] = y;
    s["yy"] = new String(y).substr(2, 2);
    s["w"] = wn;
    s["ww"] = wn < 10 ? "0" + wn : wn;

    with (Calendar) {
        s["D"] = _DN3[w];
        s["DD"] = _DN[w];
        s["M"] = _MN3[m];
        s["MM"] = _MN[m];
    }

    var re = /(.*)(\W|^)(d|dd|m|mm|y|yy|MM|M|DD|D|w|ww)(\W|$)(.*)/;

    while (null != re.exec(str)) {
        str = RegExp.$1 + RegExp.$2 + s[RegExp.$3] + RegExp.$4 + RegExp.$5;
    }
    
    return str;
};
// ----------------------------------------------------------------------------
// Date Object Patches - End
// ----------------------------------------------------------------------------

// global object that remembers the calendar
window.calendar = null;

function closeHandler(cal) {
    /// <summary>.</summary>
    /// <param name="cal" domElement="true" optional="false">.</param>
    cal.hide();
}

function yourHandler(cal, dateStr) {
    /// <summary>.</summary>
    /// <param name="cal" domElement="true" optional="false">.</param>
    /// <param name="dateStr" type="String" optional="false">.</param>
    cal.sel.value = dateStr;
}

function showCalendar(id, format) {
    /// <summary>
    /// Shows the calendar under the element having the given id. Takes care of catching
    /// "mousedown" signals on document and hiding the calendar if the click was outside.
    /// </summary>
    /// <param name="id" type="String" optional="false">.</param>
    /// <param name="format" type="String" optional="false">.</param>
    var el = document.getElementById(id);
    
    if (calendar != null) {
        // we already have some calendar created
        calendar.hide(); // so we hide it first.
    }
    else {
        // first-time call, create the calendar.
        var cal = new Calendar(false, null, yourHandler, closeHandler);

        // uncomment the following line to hide the week numbers
        cal.weekNumbers = true;
        calendar = cal;           // remember it in the global var
        cal.setRange(1900, 2070); // min/max year allowed.
        cal.create();
    }

    calendar.setDateFormat(format); // set the specified date format
    calendar.parseDate(el.value);   // try to parse the text in field
    calendar.sel = el;              // inform it what input field we use
    calendar.showAtElement(el);     // show the calendar below it

    return false;
}

//---------------------------------------------------------------------------------------------
// BTextboxDate
// ----------------------------------------------------------------------------
// ** I18N
Calendar._DN = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"];
Calendar._MN = ["Januar", "Februar", "März", "April", "Mai", "Juni", "July", "August", "September", "Oktober", "November", "Dezember"];

// tooltips
Calendar._TT = {};
Calendar._TT["TOGGLE"] = "Toggle first day of week";
Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)";
Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)";
Calendar._TT["GO_TODAY"] = "Go Today";
Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)";
Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)";
Calendar._TT["SEL_DATE"] = "Datum wählen";
Calendar._TT["DRAG_TO_MOVE"] = "Drag to move";
Calendar._TT["PART_TODAY"] = " (today)";
Calendar._TT["MON_FIRST"] = "Display Monday first";
Calendar._TT["SUN_FIRST"] = "Display Sunday first";
Calendar._TT["CLOSE"] = "Schliessen";
Calendar._TT["TODAY"] = "Heute";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "dd.mm.yyyy";
Calendar._TT["TT_DATE_FORMAT"] = "D, M d";

Calendar._TT["WK"] = "Wo";

// ----------------------------------------------------------------------------
// BTextboxDate
// MarkerDIVs
// ----------------------------------------------------------------------------
function ToggleMarkerDiv(event, ctrl, show) {
    /// <summary>.</summary>
    /// <param name="event" domElement="true" optional="false">.</param>
    /// <param name="ctrl" type="String" optional="false">.</param>
    /// <param name="show" type="Number" integer="true" optional="false">.</param>
    var control;

    if (null != (control = GetElementById(ctrl))) {
        if (1 == show) {
            control.style.visibility = "Visible";
            control.style.left = parseFloat(230, 10) + "px";
            control.style.top = parseFloat(event.clientY - 20, 10) + "px";
            control.style.zindex = 0;
        }
        else {
            control.style.visibility = "Hidden";
            control.style.posLeft = parseFloat(0, 10);
            control.style.posTop = parseFloat(0, 10);
        }
    }
    else {
    }
}

function AddPreis(ctrl, decimalSign) {
    /// <summary>.</summary>
    /// <param name="ctrl" type="String" optional="false">.</param>
    /// <param name="decimalSign" type="String" optional="false">.</param>
    var control, anzahl;
    var einzelNettoPreis, einzelBruttoPreis, gesamtNetto, gesamtBrutto, endNetto, endBrutto;
    var el, insgesamtcrtl;
    var prozrabat, prozrabatctrl, prozfloat;
    var absrabat, absrabatctrl;
    var ustNetto = 0.0;
    var ustBrutto = 0.0;
    var ustctrl;
    var fw;
    
    control = parseFloat(document.getElementById(ctrl).value.replace(/,/, "."));

    // document.getElementById(ctrl).value = control.toString();

    // Einzel-NettoPreis umsetzen        
    el = document.getElementById("_ucBestellPreis$txtNettoPreis");
    einzelNettoPreis = isNullOrEmpty(el) ? parseFloat("0.0") : parseFloat(el.value.replace(/,/, "."));

    // Einzel-BruttoPreis umsetzen        
    el = document.getElementById("_ucBestellPreis$txtBruttoPreis");
    einzelNettoPreis = isNullOrEmpty(el) ? parseFloat("0.0") : parseFloat(el.value.replace(/,/, "."));

    // NettoPreis berechnen        
    el = document.getElementById("_ucBestellPreis$txtAnzahl");
    anzahl = isNullOrEmpty(el) ? 0.0 : parseFloat(el.value);

    endNetto = anzahl * einzelNettoPreis;
    gesamtNetto = document.getElementById("_ucBestellPreis$txtPreisGesamtNetto");
    gesamtNetto.value = endNetto.toFixed(2).toString().replace(/\./, decimalSign);

    // BruttoPreis berechnen        
    el = document.getElementById("_ucBestellPreis$txtAnzahl");
    anzahl = isNullOrEmpty(el) ? 0.0 : parseFloat(el.value);

    endBrutto = anzahl * einzelBruttoPreis;
    gesamtBrutto = document.getElementById("_ucBestellPreis$txtPreisGesamtBrutto");
    gesamtBrutto.value = endBrutto.toFixed(2).toString().replace(/\./, decimalSign);

    // Prozentualer Nettorabatt
    el = document.getElementById("_ucBestellPreis$txtRabattProz");
    if (isNullOrEmpty(el)) {
        prozrabat = 0.0;
    }
    else {
        prozfloat = el.value.replace(/\,/, ".");
        prozrabat = parseFloat(prozfloat) * endNetto / 100;
    }

    prozrabatctrl = document.getElementById("_ucBestellPreis$txtRabattNettoProz");

    // wg. firefox prozrabatctrl.innerText = prozrabat.toFixed(2).toString().replace(/\./,decimalSign);
    prozrabatctrl.value = prozrabat.toFixed(2).toString().replace(/\./, decimalSign);
    endNetto = endNetto - prozrabat;

    // Prozentualer Bruttorabatt
    el = document.getElementById("_ucBestellPreis$txtRabattProz");
    if (isNullOrEmpty(el)) {
        prozrabat = 0.0;
    }
    else {
        prozfloat = el.value.replace(/\,/, ".");
        prozrabat = parseFloat(prozfloat) * endBrutto / 100;
    }

    // wg. firefox prozrabatctrl.innerText= prozrabat.toFixed(2).toString().replace(/\./,decimalSign);
    prozrabatctrl = document.getElementById("_ucBestellPreis$txtRabattBruttoProz");
    prozrabatctrl.value = prozrabat.toFixed(2).toString().replace(/\./, decimalSign);

    endBrutto = endBrutto - prozrabat;

    // Absoluter Nettorabatt
    el = document.getElementById("_ucBestellPreis$txtPortoRabattNetto");
    absrabat = isNullOrEmpty(el) ? 0.0 : parseFloat(el.value.toString().replace(/,/, "."));

    endNetto = endNetto - absrabat;

    // Absoluter Bruttorabatt
    el = document.getElementById("_ucBestellPreis$txtPortoRabattBrutto");
    absrabat = isNullOrEmpty(el) ? 0.0 : parseFloat(el.value.toString().replace(/,/, "."));
    
    endBrutto = endBrutto - absrabat;

    // Umsatzsteuer wird nur in der Netto Spalte berücksichtigt in der Bruttospalte nur ausgeben
    el = document.getElementById("_ucBestellPreis$txtUmsatzsteuer");
    if (isNullOrEmpty(el)) {
        ust = 0.0;
    }
    else {
        ustNetto = parseFloat(el.value) / 100 * endNetto;
        ustBrutto = parseFloat(el.value) / 100 * endBrutto;
    }

    // wg. firefox ustctrl.innerText= ustNetto.toFixed(2).toString().replace(/\./,decimalSign);
    ustctrl = document.getElementById("_ucBestellPreis$txtUmsatzsteuerNetto");
    ustctrl.value = ustNetto.toFixed(2).toString().replace(/\./, decimalSign);

    // wg. firefox ustctrl.innerText= ustBrutto.toFixed(2).toString().replace(/\./,decimalSign);
    ustctrl = document.getElementById("_ucBestellPreis$txtUmsatzsteuerBrutto");
    ustctrl.value = ustBrutto.toFixed(2).toString().replace(/\./, decimalSign);

    endNetto = endNetto + ustNetto;

    if (document.getElementById("_ucBestellPreis$cbBruttoAbziehen")) {
        endBrutto = endBrutto - ustBrutto;
    }

    // wg. firefox insgesamtcrtl.innerText = endNetto.toFixed(2).toString().replace(/\./,decimalSign);
    insgesamtcrtl = document.getElementById("_ucBestellPreis$txtInsgesamtNetto");
    insgesamtcrtl.value = endNetto.toFixed(2).toString().replace(/\./, decimalSign);

    // wg. firefox insgesamtcrtl.innerText = endBrutto.toFixed(2).toString().replace(/\./,decimalSign);
    insgesamtcrtl = document.getElementById("_ucBestellPreis$txtInsgesamtBrutto");
    insgesamtcrtl.value = endBrutto.toFixed(2).toString().replace(/\./, decimalSign);

    // dieses hidden feld wird benötigt um dien netto und brutto Endwerte zurückzugeben 
    insgesamtcrtl = document.getElementById("_ucBestellPreis$txtNettoBrutto");
    insgesamtcrtl.value = endNetto.toFixed(2).toString().replace(/\./, decimalSign) + "/" + 
                          endBrutto.toFixed(2).toString().replace(/\./, decimalSign);

    // die Felder auch mit richtigen Werten setzen
    el = document.getElementById("_ucBestellPreis$txtPreisFWNetto");
    fw = isNullOrEmpty(el) ? 0.0 : parseFloat(el.value.toString().replace(/,/, "."));

    el.value = fw.toString().replace(/\./, decimalSign);
    el = document.getElementById("_ucBestellPreis$txtPreisFWBrutto");

    fw = isNullOrEmpty(el) ? 0.0 : parseFloat(el.value.toString().replace(/,/, "."));
    el.value = fw.toString().replace(/\./, decimalSign);
}

function isNullOrEmpty(s) {
    /// <summary>Tests an object for initialisation and its "value" property for emptiness.</summary>
    /// <param name="s" type="Object" optional="false">The object to test for.</param>
    /// <returns mayBeNull="false"><c>true</c>, if the object is null or its value property is empty; otherwise, <c>false</c>.</returns>
    /// <remarks>It is assumed that s.value is a string property.</remarks>
    return null == s || "" == s.value || s.value.length < 1;
}

function BRadioValChanged(radiobtn) {
    /// <summary>.</summary>
    /// <param name="radiobtn" domElement="true" optional="false">.</param>
    /// <remarks>Wird in BRadioButtonListItem verwendet</remarks>
    var objtypename, oldValName, oldVal, msg;

    try {
        try {
            objtypename = typeof(radiobtn);

            if ("object" != objtypename.toLowerCase()) {
                throw new String("The parameter is not of type 'object'.");
            }

            if (undefined == radiobtn.nodeName) {
                throw new String("The parameter is not a HTML-Element.");
            }

            if ("input" != radiobtn.nodeName.toLowerCase()) {
                throw new String("The parameter is not a HTML-<input>-Element.");
            }

            if ("radio" != radiobtn.type.toLowerCase()) {
                throw new String("The parameter.type property is not 'radio'.");
            }
        }
        catch (exept) {
            throw exept;
        }
    }
    catch (ex) {
        window.alert("Error in function BRadioValChanged: " + ex.toString());
        return undefined;
    }

    oldValName = "MS_Form_" + radiobtn.name + "_OldVal__";
    oldVal = document[oldValName];

    if ("string" != typeof(oldVal)) {
        msg = "Error in function BRadioValChanged: " + 
              "The document porperty: " + oldValName + " doesn't exists.\n\n" +
              "typeof(oldVal) == " + typeof(oldVal) + "\n" +
              "oldVal == " + oldVal;

        window.alert(msg);

        return undefined;
    }

    if (oldVal != radiobtn.value) {
        document[oldValName] = radiobtn.value;
        __doPostBack(radiobtn.name, "SELECTEDINDEXCHANGED")
    }
}

function bslidebox_slide(nr, suffix) {
    /// <summary>quicklist slider.</summary>
    /// <param name="nr" type="Number" integer="true" optional="false">.</param>
    /// <param name="suffix" type="String" integer="true" optional="false">.</param>
    /// <remarks>event.target is a "a"</remarks>
    var MAX_ITEMS = 5;
    var ANZ_ITEMS = BSB_ANZ_ITEMS; // 3
    var OBEN = "_oben";
    var UNTEN = "_unten";
    var PREFIX = "slidebox_group_";
    var itemClicked = document.getElementById(PREFIX + nr + suffix);
    var i, item, translatedNr

    for (i = 1; i <= ANZ_ITEMS; i++) {
        suffix = OBEN;
        item = document.getElementById(PREFIX + i + OBEN);
        translatedNr = ANZ_ITEMS - i + 1;

        if (null == item) {
            item = document.getElementById(PREFIX + translatedNr + UNTEN);
            suffix = UNTEN;
        }

        var itemContent = document.getElementById("slidebox_group_content_" + i);

        if (item != null) {
            if (i < nr) {
                item.id = PREFIX + i + OBEN;
                itemContent.style.left = -500;
                itemContent.style.display = "none";
            }
            else if (i == nr) {
                item.id = PREFIX + i + OBEN;
                itemContent.style.left = 0;
                itemContent.style.display = "";
            }
            else {
                item.id = PREFIX + translatedNr + UNTEN;
                itemContent.style.left = -2000;
                itemContent.style.display = "none";
            }
        }
    }
}

function multipage_switch(event, tabidx) {
    /// <summary>.</summary>
    /// <param name="event" domElement="true" optional="false">.</param>
    /// <param name="tabidx" type="Number" integer="true" optional="false">.</param>
    /// <remarks>event.target is a "a"</remarks>
    var target = event.target || event.srcElement;

    var EpagesContainer = target.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("div")[1];
    var Epages = EpagesContainer.childNodes;
    var Etabs = target.parentNode.parentNode.getElementsByTagName("li");
    var j = 0;
    var i;

    for (i = 0; i < Epages.length; i++) {
        if (!Epages[i].tagName || "div" != Epages[i].tagName.toLowerCase()) {
            continue;
        }

        Epages[i].style.display = j == tabidx ? "" : "none";
        Etabs[j].className = j == tabidx ? "multipage_tab_active" : "";
        j++;
    }
}
//]]>


/*********************
 * ComponentArt Grid *
 ********************/
function get_group_text(grid, idx) {
    return grid.get_table().get_columns()[idx].get_headingText(); 
}

function navbar_toggle(navbarid, contentid) {
	contentDiv = $(navbarid + "_item_" + contentid);

	//contentDiv = $(contentDiv);
	if (contentDiv.className == 'core_navbar_item collapsed') {
		contentDiv.className = 'core_navbar_item expanded';
		theForm[navbarid + "_" + contentid + "_expanded"].value = 'true';
	} else {
		contentDiv.className = 'core_navbar_item collapsed';
		theForm[navbarid + "_" + contentid + "_expanded"].value = 'false';
	}
}
