/* Minification failed. Returning unminified contents.
(7,9-14): run-time error JS1195: Expected expression: class
(15,20-36): run-time error JS1004: Expected ';': SetLastErrorInfo
(15,68-69): run-time error JS1004: Expected ';': {
(29,20-36): run-time error JS1004: Expected ';': AspNetDataFilter
(29,50-51): run-time error JS1004: Expected ';': {
(61,20-40): run-time error JS1004: Expected ';': PreparePageMethodUrl
(61,56-57): run-time error JS1004: Expected ';': {
(71,20-41): run-time error JS1004: Expected ';': PreparePageServiceUrl
(71,57-58): run-time error JS1004: Expected ';': {
(89,20-24): run-time error JS1004: Expected ';': Ajax
(89,78-79): run-time error JS1004: Expected ';': {
(112,42-43): run-time error JS1195: Expected expression: >
(128,22-23): run-time error JS1195: Expected expression: )
(139,22-23): run-time error JS1195: Expected expression: )
(156,20-30): run-time error JS1004: Expected ';': DateParser
(156,49-50): run-time error JS1004: Expected ';': {
(180,20-39): run-time error JS1004: Expected ';': CallPageMethodAsync
(180,93-94): run-time error JS1004: Expected ';': {
(186,20-36): run-time error JS1004: Expected ';': GetLastErrorInfo
(186,39-40): run-time error JS1004: Expected ';': {
(202,20-40): run-time error JS1004: Expected ';': CallPageServiceAsync
(202,94-95): run-time error JS1004: Expected ';': {
(219,20-36): run-time error JS1004: Expected ';': CallServiceAsync
(219,108-109): run-time error JS1004: Expected ';': {
(222,57-58): run-time error JS1195: Expected expression: >
(222,87-88): run-time error JS1004: Expected ';': )
(224,64-65): run-time error JS1195: Expected expression: >
(224,95-96): run-time error JS1004: Expected ';': )
(237,20-23): run-time error JS1004: Expected ';': Get
(237,52-53): run-time error JS1004: Expected ';': {
(252,20-24): run-time error JS1004: Expected ';': Post
(252,71-72): run-time error JS1004: Expected ';': {
(268,20-28): run-time error JS1004: Expected ';': PostForm
(268,75-76): run-time error JS1004: Expected ';': {
(271,57-58): run-time error JS1195: Expected expression: >
(271,87-88): run-time error JS1004: Expected ';': )
(273,64-65): run-time error JS1195: Expected expression: >
(273,95-96): run-time error JS1004: Expected ';': )
(276,9-10): run-time error JS1002: Syntax error: }
(289,35-36): run-time error JS1197: Too many errors. The file might not be a JavaScript file: (
(253,17-83): run-time error JS1018: 'return' statement outside of function: return CAjaxTool.Ajax(true, strUrl, oParams, oSettings, bPostJson)
(238,17-79): run-time error JS1018: 'return' statement outside of function: return CAjaxTool.Ajax(false, strUrl, oParams, oSettings, true)
(188,17,190,32): run-time error JS1018: 'return' statement outside of function: return CAjaxTool.g_oLastErrorInfo
                    ? JSON.parse(JSON.stringify(CAjaxTool.g_oLastErrorInfo))
                    : undefined
(168,17-32): run-time error JS1018: 'return' statement outside of function: return strValue
(165,25-87): run-time error JS1018: 'return' statement outside of function: return new Date(arrTicks[0] ? +arrTicks[0] : 0 - +arrTicks[1])
(160,25-50): run-time error JS1018: 'return' statement outside of function: return new Date(strValue)
(147,17-43): run-time error JS1018: 'return' statement outside of function: return oDeferred.promise()
(74,17-53): run-time error JS1018: 'return' statement outside of function: return strPath + "/" + strMethodName
(63,17-53): run-time error JS1018: 'return' statement outside of function: return strPath + "/" + strMethodName
(37,25-73): run-time error JS1018: 'return' statement outside of function: return JSON.parse(oJSON.d, CAjaxTool.DateParser)
(40,25-39): run-time error JS1018: 'return' statement outside of function: return oJSON.d
(44,21-41): run-time error JS1018: 'return' statement outside of function: return oJSON.Message
(48,25-71): run-time error JS1018: 'return' statement outside of function: return JSON.parse(oJSON, CAjaxTool.DateParser)
(51,25-37): run-time error JS1018: 'return' statement outside of function: return oJSON
 */
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        /** Class to call service- and page-methods via an ajax-call.
            */
        class CAjaxTool {
            //! STATIC PRIVATE / PROTECTED FUNCTIONS - PROPERTIES 
            //===========================================================================================
            /** Set the last error
              * @param strUrl Url that was called
              * @param strError Error to save
              * @param strErrorMsg ErrorMsg to save
              */
            static SetLastErrorInfo(strUrl, strError, strErrorMsg) {
                // Set the info
                CAjaxTool.g_oLastErrorInfo = {
                    Error: strError,
                    ErrorMsg: strErrorMsg,
                    Url: strUrl,
                    Timestamp: new Date()
                };
            }
            //===========================================================================================
            /** Get the data from the asp.net response string
              * @param strResponse Response from asp.net that contains the data
              * @returns The decoded object from the asp.net answer
              */
            static AspNetDataFilter(strResponse) {
                // This boils the response string down 
                //  into a proper JavaScript Object().
                var oJSON = JSON.parse(strResponse, CAjaxTool.DateParser);
                // If the response has a ".d" top-level property,
                //  return what's below that instead.
                if (oJSON.hasOwnProperty('d')) {
                    if (typeof (oJSON.d) == "string") {
                        return JSON.parse(oJSON.d, CAjaxTool.DateParser);
                    }
                    else {
                        return oJSON.d;
                    }
                }
                else if (oJSON.hasOwnProperty('Message')) {
                    return oJSON.Message;
                }
                else {
                    if (typeof (oJSON) == "string") {
                        return JSON.parse(oJSON, CAjaxTool.DateParser);
                    }
                    else {
                        return oJSON;
                    }
                }
            }
            //===========================================================================================
            /** Prepare the given method name to be used for calling page related
              * ajax-call. The current url is used to build the ajax-url
              * @param strMethodName Name of the page method to be called
              * @returns The page-method-url of the given method for the current url.
              */
            static PreparePageMethodUrl(strMethodName) {
                var strPath = document.location.href.split('?', 1)[0];
                return strPath + "/" + strMethodName;
            }
            //===========================================================================================
            /** Prepare the given method name to be used for calling page related
              * ajax-call. The current url is used to build the ajax-url
              * @param strMethodName Name of the page method to be called
              * @returns The page-method-url of the given method for the current url.
              */
            static PreparePageServiceUrl(strMethodName) {
                var strPath = document.location.href.split('?', 1)[0]
                    .replace(".aspx", ".asmx");
                return strPath + "/" + strMethodName;
            }
            //===========================================================================================
            /** Call a service-url. The call is made asynchronous.
              * @param bPost Use post to send to the server (otherwise get)
              * @param strUrl The url to call
              * @param oParams Params to use when calling to the service
              * @param oSettings Settings to use (optional)
              * @param bPostJson If this boolean is set, the params are serialized within a json object
              * and posted as only one string param (with mimetype application/json)
              * @returns The result of the service call.
              * If no failure that Data part contains the returned result.
              * The Warnings part may contain warnings,
              * and in error-case the Error part is filled accordingly.
              */
            static Ajax(bPost, strUrl, oParams, oSettings, bPostJson = true) {
                // Prepare the settings
                var oAjaxSettings = {
                    cache: false,
                    headers: { "Cache-Control": "no-cache" }
                };
                $.extend(oAjaxSettings, oSettings);
                // We are not allowed to overload some informations
                oAjaxSettings.type = bPost ? "post" : "get";
                oAjaxSettings.url = strUrl;
                oAjaxSettings.data = (bPost && bPostJson) ? JSON.stringify(oParams) : oParams;
                oAjaxSettings.async = true;
                if (bPostJson) {
                    oAjaxSettings.contentType = "application/json; charset=utf-8";
                }
                else {
                    oAjaxSettings.contentType = "application/x-www-form-urlencoded; charset=UTF-8";
                }
                oAjaxSettings.dataType = "text";
                oAjaxSettings.dataFilter = CAjaxTool.AspNetDataFilter;
                var oDeferred = Util.FIDeferred();
                if (oAjaxSettings.url) { // Do the call
                    $.ajax(strUrl, oAjaxSettings)
                        .done(oResponse => {
                        if (oResponse !== null &&
                            oResponse.hasOwnProperty('Data')) { // This is considered as success
                            var strWarnings = oResponse.Warnings;
                            var oData = oResponse.Data;
                            oDeferred.resolve(oData, strWarnings || null);
                        }
                        else if (oResponse !== null &&
                            oResponse.hasOwnProperty('Error')) { // Response contains the thrown error
                            CAjaxTool.SetLastErrorInfo(strUrl, oResponse.Error, oResponse.ErrorMsg);
                            oDeferred.reject(oResponse.Error, oResponse.ErrorMsg);
                        }
                        else { // Use the response as Data-result
                            // This is considered as success
                            oDeferred.resolve(oResponse, null);
                        }
                    })
                        .fail(xhr => {
                        let strError = xhr.responseText;
                        if (!strError && !navigator.onLine) { // Not online
                            strError = CAjaxTool.g_strNotOnline;
                        }
                        if (!strError) { // We need an error string
                            strError = CAjaxTool.g_strGenericError;
                        }
                        CAjaxTool.SetLastErrorInfo(strUrl, strError, strError);
                        oDeferred.reject(strError, strError);
                    });
                }
                else { // Do not call with invalid url (minize trivial error-debugging)
                    var strErrorMsg = "CallServiceAsync: Empty URL not supported. "
                        + "Check for valid url-retrieval! (E.g. correct area to use in Url.Action)";
                    // Fail immediately
                    oDeferred.reject(strErrorMsg, strErrorMsg);
                }
                return oDeferred.promise();
            }
            //! STATIC FUNCTIONS
            //===========================================================================================
            /** ---
              * @param strKey ---
              * @param strValue ---
              * @returns ---
              */
            static DateParser(strKey, strValue) {
                if (typeof strValue === 'string') {
                    var arrResult = CAjaxTool.c_oISORegex.exec(strValue);
                    if (arrResult) { // The key is a date
                        return new Date(strValue);
                    }
                    arrResult = CAjaxTool.c_oMSAjaxRegex.exec(strValue);
                    if (arrResult) {
                        var arrTicks = arrResult[1].split(/[-+,.]/);
                        return new Date(arrTicks[0] ? +arrTicks[0] : 0 - +arrTicks[1]);
                    }
                }
                return strValue;
            }
            //===========================================================================================
            /** Call a webmethod for the current page, the call is made asynchronous,
              * so that the function returns immediately and the result is handed over
              * to the given success-function.
              * @param strMethodName Name of the method to call
              * @param oParams Params to use when calling to the webmethod
              * @param dSuccess Function to call in success-case.
              * @param dError Function to call in error-case. (optional)
              * @param oSettings Settings to use (optional)
              */
            static CallPageMethodAsync(strMethodName, oParams, dSuccess, dError, oSettings) {
                CAjaxTool.CallServiceAsync(CAjaxTool.PreparePageMethodUrl(strMethodName), oParams, dSuccess, dError, oSettings);
            }
            //===========================================================================================
            /** Get the last ajax-error-info or undefined if there was none
              */
            static GetLastErrorInfo() {
                // Return a copy
                return CAjaxTool.g_oLastErrorInfo
                    ? JSON.parse(JSON.stringify(CAjaxTool.g_oLastErrorInfo))
                    : undefined;
            }
            //===========================================================================================
            /** Call a webmethod for the current page, the call is made asynchronous,
              * so that the function returns immediately and the result is handed over
              * to the given success-function.
              * @param strMethodName Name of the method to call
              * @param oParams Params to use when calling to the webmethod
              * @param dSuccess Function to call in success-case.
              * @param dError Function to call in error-case. (optional)
              * @param oSettings Settings to use (optional)
              */
            static CallPageServiceAsync(strMethodName, oParams, dSuccess, dError, oSettings) {
                CAjaxTool.CallServiceAsync(CAjaxTool.PreparePageServiceUrl(strMethodName), oParams, dSuccess, dError, oSettings);
            }
            //===========================================================================================
            /** Call a service-url. The call is made asynchronous,
              * so that the function returns immediately and the result is handed over
              * to the given success-function.
              * @param strServiceUrl The url of the service to call
              * @param oParams Params to use when calling to the service
              * @param dSuccess Function to call in success-case.
              * @param dError Function to call in error-case. (optional)
              * @param oSettings Settings to use (optional)
              * @param bPostJson If this boolean is set, the params are serialized within a json object
              * and posted as only one string param  (with mimetype application/json)
              * else with "application/x-www-form-urlencoded
              * @deprecated Use CAjaxTool.Post or CAjaxTool.Get instead!
              */
            static CallServiceAsync(strServiceUrl, oParams, dSuccess, dError, oSettings, bPostJson = true) {
                var oAjaxPromise = CAjaxTool.Ajax((!oSettings || oSettings.type != "get"), strServiceUrl, oParams, oSettings, bPostJson);
                // Handle the success
                oAjaxPromise.done((oData, strWarnings) => dSuccess(strWarnings, oData));
                if (dError) { // Handle the error
                    oAjaxPromise.fail((strError, strErrorMsg) => dError(strError, strErrorMsg));
                }
            }
            //===========================================================================================
            /** Call a service-url. The call is made asynchronous via GET-request.
              * @param strUrl The url to call
              * @param oParams Params to use when calling to the service
              * @param oSettings Settings to use (optional)
              * @returns The result of the service call.
              * If no failure that Data part contains the returned result.
              * The Warnings part may contain warnings,
              * and in error-case the Error part is filled accordingly.
              */
            static Get(strUrl, oParams, oSettings) {
                return CAjaxTool.Ajax(false, strUrl, oParams, oSettings, true);
            }
            //===========================================================================================
            /** Call a service-url. The call is made asynchronous via POST-request.
              * @param strUrl The url to call
              * @param oParams Params to use when calling to the service
              * @param oSettings Settings to use (optional)
              * @param bPostJson If this boolean is set, the params are serialized within a json object
              * and posted as only one string param (with mimetype application/json)
              * @returns The result of the service call.
              * If no failure that Data part contains the returned result
              * The Warnings part may contain warnings,
              * and in error-case the Error part is filled accordingly.
              */
            static Post(strUrl, oParams, oSettings, bPostJson = true) {
                return CAjaxTool.Ajax(true, strUrl, oParams, oSettings, bPostJson);
            }
            //===========================================================================================
            /** Call a service-url. The call is made asynchronous via POST-request.
             * and application/x-www-form-urlencoded;
            * @param strUrl The url to call
            * @param oParams Params to use when calling to the service
            * @param dSuccess Function to call in success-case.
            * @param dError Function to call in error-case. (optional)
            * @param oSettings Settings to use (optional)
            * @returns The result of the service call.
            * If no failure that Data part contains the returned result
            * The Warnings part may contain warnings,
            * and in error-case the Error part is filled accordingly.
            */
            static PostForm(strUrl, oParams, dSuccess, dError, oSettings) {
                var oAjaxPromise = CAjaxTool.Post(strUrl, oParams, oSettings, false);
                // Handle the success
                oAjaxPromise.done((oData, strWarnings) => dSuccess(strWarnings, oData));
                if (dError) { // Handle the error
                    oAjaxPromise.fail((strError, strErrorMsg) => dError(strError, strErrorMsg));
                }
            }
        }
        //! STATIC / CONST MEMBERS 
        //===========================================================================================
        /** NotOnline
          */
        CAjaxTool.g_strNotOnline = Regional.ErrNotOnline;
        //===========================================================================================
        /** GenericError
          */
        CAjaxTool.g_strGenericError = Regional.ErrGeneric;
        //===========================================================================================
        /** ISO Regex to parse dates correctly
          */
        CAjaxTool.c_oISORegex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;
        //===========================================================================================
        /** MSAjax Regex to parse dates correctly
          */
        CAjaxTool.c_oMSAjaxRegex = /^\/Date\((d|-|.*)\)[\/|\\]$/;
        Util.CAjaxTool = CAjaxTool;
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
//# sourceMappingURL=AjaxTool.js.map;
if (typeof Regional == 'undefined') {
    Regional = {};
    Regionals = {
        CultureCode: {}
    };
}
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        /** Class to localize the javascript part of the application
          */
        class CLocalizationTool {
            /** Localize the html
              */
            static LocalizeApplicationHTML() {
                var oRegionalMap = Regional;
                // Now update the localized texts
                jQuery('*[data-localized-html]').each(function () {
                    var jThis = $(this);
                    var strKey = jThis.attr('data-localized-html');
                    jThis.html(oRegionalMap[strKey]);
                });
            }
            /** Activate the given language to use
              * @param strCultureCode Language to activate
              * @param bLocalizeHTML Localize html too?
              */
            static ActivateLanguage(strCultureCode, bLocalizeHTML) {
                // Now update the regionals (make a copy)
                Regional = jQuery.extend({}, Regional, Regionals.CultureCode[strCultureCode]);
                // Allow to replace pre-defined placeholders
                if (Regional.Copyright) {
                    var dtmNow = new Date();
                    // Update the copyright message
                    Regional.Copyright = Regional.Copyright
                        .replace('__YEAR__', dtmNow.getFullYear().toString());
                }
                // Mark the current active language
                Regionals.Current = strCultureCode;
                if (bLocalizeHTML) { // We must update the HTML too
                    CLocalizationTool.LocalizeApplicationHTML();
                }
            }
            /** Set the application language to the given culture
              * A global variable named "g_strAppPrefix" must point to the path where
              * the "Localization" files are located. If it is not defined an error is shown in the log.
              * @param strCultureCode Language to set
              * @param bLocalizeHTML Localize html too?
              */
            static SetApplicationLanguage(strCultureCode, bLocalizeHTML) {
                bLocalizeHTML = bLocalizeHTML === undefined || bLocalizeHTML === true;
                // Check if the language was already loaded
                if (!Regionals.CultureCode[strCultureCode]) {
                    if (window["g_strAppPrefix"] !== undefined) { // Get the localization
                        var strRegionalUrl = window["g_strAppPrefix"] + "/Localization/" + strCultureCode + "/JS/regional.js";
                        // Now load it and activate it on success
                        jQuery.getScript(strRegionalUrl, function () {
                            CLocalizationTool.ActivateLanguage(strCultureCode, bLocalizeHTML);
                        });
                    }
                    else { // Show an error in the log
                        console.error("Unable to load regional.js. Missing global application path: g_strAppPrefix!");
                    }
                }
                else { // Localize immediately
                    CLocalizationTool.ActivateLanguage(strCultureCode, bLocalizeHTML);
                }
            }
            /** Initialize the regionals
              */
            static Init() {
                var strCultureCode = "de-DE";
                if (jQuery.cookie) { // Do not rely on jQuery.cookie
                    strCultureCode = jQuery.cookie("UICultureCode") || "de-DE";
                }
                // Init the regionals structure (may load the regionals first)
                CLocalizationTool.SetApplicationLanguage(strCultureCode, false);
                $(document).ready(function () {
                    CLocalizationTool.LocalizeApplicationHTML();
                });
            }
            /** Get specific formatting infos for the given locale
              * @param strLocale Locale to get the formatting infos for.
              */
            static GetFormatNumberData(strLocale) {
                var strLowerLocale = strLocale.toLowerCase();
                // Extract and convert to lower-case any language code from a real 'locale' formatted string, if not use as-is
                // (To prevent locale format like : "fr_FR", "en_US", "de_DE", "fr_FR", "en-US", "de-DE")
                if (strLowerLocale.indexOf('_') != -1) {
                    strLowerLocale = strLowerLocale.split('_')[1].toLowerCase();
                }
                else if (strLowerLocale.indexOf('-') != -1) {
                    strLowerLocale = strLowerLocale.split('-')[1].toLowerCase();
                }
                // Calculate the formatting data
                var oFormatData;
                switch (strLowerLocale) {
                    case 'us': // + following similar locales
                    case 'ae':
                    case 'au':
                    case 'ca':
                    case 'cn':
                    case 'eg':
                    case 'gb':
                    case 'hk':
                    case 'il':
                    case 'in':
                    case 'jp':
                    case 'sk':
                    case 'th':
                    case 'tw':
                        oFormatData = { chDec: '.', chGroup: ',', chNeg: '-' };
                        break;
                    case 'de': // + following similar locales
                    case 'at':
                    case 'br':
                    case 'dk':
                    case 'es':
                    case 'gr':
                    case 'it':
                    case 'nl':
                    case 'pt':
                    case 'tr':
                    case 'vn':
                        oFormatData = { chDec: ',', chGroup: '.', chNeg: '-' };
                        break;
                    case 'fr': // + following similar locales
                    case 'cz':
                    case 'fi':
                    case 'ru':
                    case 'se':
                    case 'pl':
                        oFormatData = { chDec: ',', chGroup: ' ', chNeg: '-' };
                        break;
                    case 'ch':
                        oFormatData = { chDec: '.', chGroup: '\'', chNeg: '-' };
                        break;
                }
                return oFormatData;
            }
            //===========================================================================================
            /** Parses a string and returns its value.
              * @param strNumber String of number to parse
              * @param oOptions Options to use (optional)
              */
            static ParseNumber(strNumber, oOptions) {
                // Extend the options
                oOptions = jQuery.extend({
                    strLocale: Regionals.Current
                }, oOptions);
                var oFormatData = CLocalizationTool.GetFormatNumberData(oOptions.strLocale);
                if (oFormatData === undefined) {
                    throw new Error("Internal Exception: Locale not supported for number-formatting ('" + oOptions.strLocale + "') !");
                }
                var chDec = oFormatData.chDec;
                var chGroup = oFormatData.chGroup;
                var chNeg = oFormatData.chNeg;
                var strValid = "1234567890.-";
                // now we need to convert it into a number
                while (strNumber.indexOf(chGroup) > -1) {
                    strNumber = strNumber.replace(chGroup, '');
                }
                strNumber = strNumber.replace(chDec, ".").replace(chNeg, "-");
                var strValidText = "";
                for (var i = 0; i < strNumber.length; i++) {
                    if (strValid.indexOf(strNumber.charAt(i)) > -1) {
                        strValidText = strValidText + strNumber.charAt(i);
                    }
                }
                var dblNumber = +strValidText;
                return dblNumber;
            }
            /** Formats the given number with the given options.
              * @param dblNumber Number to format
              * @param oOptions Options to use (optional)
              */
            static FormatNumber(dblNumber, oOptions) {
                // Extend the options
                oOptions = jQuery.extend({
                    strFormat: "#,###.00",
                    strLocale: Regionals.Current,
                    bNaNForceZero: false,
                    bRound: true
                }, oOptions);
                var oFormatData = CLocalizationTool.GetFormatNumberData(oOptions.strLocale);
                if (oFormatData === undefined) {
                    throw new Error("Internal Exception: Locale not supported for number-formatting ('" + oOptions.strLocale + "') !");
                }
                var chDec = oFormatData.chDec;
                var chGroup = oFormatData.chGroup;
                var chNeg = oFormatData.chNeg;
                var strValidFormat = "0#-,.";
                // strip all the invalid characters at the beginning and the end
                // of the format, and we'll stick them back on at the end
                // make a special case for the negative sign "-" though, so 
                // we can have formats like -$23.32
                var strPrefix = "";
                var bNegativeInFront = false;
                for (var i = 0; i < oOptions.strFormat.length; i++) {
                    if (strValidFormat.indexOf(oOptions.strFormat.charAt(i)) == -1) {
                        strPrefix = strPrefix + oOptions.strFormat.charAt(i);
                    }
                    else {
                        if (i == 0 && oOptions.strFormat.charAt(i) == '-') {
                            bNegativeInFront = true;
                            continue;
                        }
                        else {
                            break;
                        }
                    }
                }
                var strSuffix = "";
                for (var i = oOptions.strFormat.length - 1; i >= 0; i--) {
                    if (strValidFormat.indexOf(oOptions.strFormat.charAt(i)) == -1) {
                        strSuffix = oOptions.strFormat.charAt(i) + strSuffix;
                    }
                    else {
                        break;
                    }
                }
                oOptions.strFormat = oOptions.strFormat.substring(strPrefix.length);
                oOptions.strFormat = oOptions.strFormat.substring(0, oOptions.strFormat.length - strSuffix.length);
                var bForcedToZero = false;
                if (isNaN(dblNumber)) {
                    if (oOptions.bNaNForceZero == true) {
                        dblNumber = 0;
                        bForcedToZero = true;
                    }
                    else {
                        return null;
                    }
                }
                var strReturnString = "";
                if (oOptions.strFormat.indexOf(".") > -1) {
                    var strDecimalPortion = chDec;
                    var strDecimalFormat = oOptions.strFormat.substring(oOptions.strFormat.lastIndexOf(".") + 1);
                    // round or truncate number as needed
                    if (oOptions.bRound == true) {
                        dblNumber = +dblNumber.toFixed(strDecimalFormat.length);
                    }
                    else {
                        var strNumber = dblNumber.toString();
                        strNumber = strNumber.substring(0, strNumber.lastIndexOf('.') + strDecimalFormat.length + 1);
                        dblNumber = +strNumber;
                    }
                    var dblDecimalValue = dblNumber % 1;
                    var strDecimalString = new String(dblDecimalValue.toFixed(strDecimalFormat.length));
                    strDecimalString = strDecimalString.substring(strDecimalString.lastIndexOf(".") + 1);
                    for (var i = 0; i < strDecimalFormat.length; i++) {
                        if (strDecimalFormat.charAt(i) == '#' && strDecimalString.charAt(i) != '0') {
                            strDecimalPortion += strDecimalString.charAt(i);
                            continue;
                        }
                        else if (strDecimalFormat.charAt(i) == '#' && strDecimalString.charAt(i) == '0') {
                            var strNotParsed = strDecimalString.substring(i);
                            if (strNotParsed.match('[1-9]')) {
                                strDecimalPortion += strDecimalString.charAt(i);
                                continue;
                            }
                            else {
                                break;
                            }
                        }
                        else if (strDecimalFormat.charAt(i) == "0") {
                            strDecimalPortion += strDecimalString.charAt(i);
                        }
                    }
                    strReturnString += strDecimalPortion;
                }
                else {
                    dblNumber = Math.round(dblNumber);
                }
                var dblOnes = Math.floor(dblNumber);
                if (dblNumber < 0) {
                    dblOnes = Math.ceil(dblNumber);
                }
                var strOnesFormat = "";
                if (oOptions.strFormat.indexOf(".") == -1) {
                    strOnesFormat = oOptions.strFormat;
                }
                else {
                    strOnesFormat = oOptions.strFormat.substring(0, oOptions.strFormat.indexOf("."));
                }
                var strOnePortion = "";
                if (!(dblOnes == 0 && strOnesFormat.substr(strOnesFormat.length - 1) == '#') || bForcedToZero) { // find how many digits are in the group
                    var strOneText = new String(Math.abs(dblOnes));
                    var nGroupLength = 9999;
                    if (strOnesFormat.lastIndexOf(",") != -1) {
                        nGroupLength = strOnesFormat.length - strOnesFormat.lastIndexOf(",") - 1;
                    }
                    var nGroupCount = 0;
                    for (var i = strOneText.length - 1; i > -1; i--) {
                        strOnePortion = strOneText.charAt(i) + strOnePortion;
                        nGroupCount++;
                        if (nGroupCount == nGroupLength && i != 0) {
                            strOnePortion = chGroup + strOnePortion;
                            nGroupCount = 0;
                        }
                    }
                    // account for any pre-data padding
                    if (strOnesFormat.length > strOnePortion.length) {
                        var nPadStart = strOnesFormat.indexOf('0');
                        if (nPadStart != -1) {
                            var nPadLen = strOnesFormat.length - nPadStart;
                            // pad to left with 0's or group char
                            var nPos = strOnesFormat.length - strOnePortion.length - 1;
                            while (strOnePortion.length < nPadLen) {
                                var chPadChar = strOnesFormat.charAt(nPos);
                                // replace with real group char if needed
                                if (chPadChar == ',') {
                                    chPadChar = chGroup;
                                }
                                strOnePortion = chPadChar + strOnePortion;
                                nPos--;
                            }
                        }
                    }
                }
                if (!strOnePortion && strOnesFormat.indexOf('0', strOnesFormat.length - 1) !== -1) {
                    strOnePortion = '0';
                }
                strReturnString = strOnePortion + strReturnString;
                // handle special case where negative is in front of the invalid characters
                if (dblNumber < 0 && bNegativeInFront && strPrefix.length > 0) {
                    strPrefix = chNeg + strPrefix;
                }
                else if (dblNumber < 0) {
                    strReturnString = chNeg + strReturnString;
                }
                if (strReturnString.lastIndexOf(chDec) == strReturnString.length - 1) {
                    strReturnString = strReturnString.substring(0, strReturnString.length - 1);
                }
                strReturnString = strPrefix + strReturnString + strSuffix;
                return strReturnString;
            }
        }
        Util.CLocalizationTool = CLocalizationTool;
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
// We must ensure the correct language resources are loaded!
FI.Util.CLocalizationTool.Init();
//# sourceMappingURL=Localization.js.map;
if (!String.prototype.isEmpty) { // Support for old browsers IE11
    String.prototype.isEmpty = function () {
        return (this.length === 0);
    };
}
if (!String.prototype.trim) { // Support for trimming in old browsers
    String.prototype.trim = function () {
        return (this.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""));
    };
}
if (!String.prototype.startsWith) { // Support for old browsers IE11
    String.prototype.startsWith = function (strThat) {
        return (this.match("^" + strThat) == strThat);
    };
}
if (!String.prototype.endsWith) { // Support for old browsers IE11
    String.prototype.endsWith = function (strThat) {
        return (this.match(strThat + "$") == strThat);
    };
}
String.prototype.toNode = function (strClass) {
    var jNode = jQuery('<' + this + '></' + this + '>');
    if (strClass) {
        jNode.addClass(strClass);
    }
    return jNode;
};
String.prototype.toInt = function (nRadix = 10) {
    return parseInt(this, nRadix);
};
String.prototype.toBool = function () {
    return !!this.match(/true/i);
};
String.prototype.toRegExp = function (strOptions) {
    return new RegExp(("" + this).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), strOptions);
};
// =======================================================================
// See https://github.com/ThomasR/JSON.sortify for original implementation
// =======================================================================
String.toSortedJSON = function (oObject, replacer, space) {
    var dSortKeys = function (oObject) {
        if (Object.prototype.toString.call(oObject) === '[object Object]') {
            // put numeric keys first
            var numeric = [];
            var nonNumeric = [];
            Object.keys(oObject).forEach(function (key) {
                if (/^(0|[1-9][0-9]*)$/.test(key)) {
                    numeric.push(+key);
                }
                else {
                    nonNumeric.push(key);
                }
            });
            // do the rearrangement
            return numeric.sort().concat(nonNumeric.sort()).reduce(function (result, key) {
                result[key] = dSortKeys(oObject[key]); // recurse!
                return result;
            }, {});
        }
        else if (Array.isArray(oObject)) {
            return oObject.map(dSortKeys);
        }
        return oObject;
    };
    // replacer, toJSON(), cyclic references and other stuff is better handled by native stringifier.
    // So we do JSON.stringify(sortKeys( JSON.parse(JSON.stringify()) )).
    // This approach is slightly slower but much safer than a manual stringification.
    var strObject = JSON.stringify(oObject, replacer, space);
    if (!strObject || strObject[0] !== '{' && strObject[0] !== '[') { // if value is not an Object or Array
        return strObject;
    }
    var oCleanObject = JSON.parse(strObject);
    // Now stringify sorted
    return JSON.stringify(dSortKeys(oCleanObject), null, space);
};
//# sourceMappingURL=StringExtensions.js.map;
Date.prototype.isLeapYear = function () {
    return Date.isLeapYear(this.getFullYear());
};
Date.prototype.getDaysOfMonth = function () {
    return Date.getDaysOfMonth(this.getFullYear(), this.getMonth());
};
Date.prototype.getDayOfYear = function () {
    var nNbDays = this.getDate();
    var nYear = this.getFullYear();
    for (var nMonth = this.getMonth() - 1; nMonth >= 0; nMonth--) {
        nNbDays += Date.getDaysOfMonth(nYear, nMonth);
    }
    return nNbDays;
};
Date.prototype.getWeekOfYear = function () {
    // Mon = 0 to Sun = 6
    var nISODay = (this.getDay() + 6) % 7;
    // Thursday (= 3, for year determination)
    var nYearDate = this.valueOf() + (3 - nISODay) * 86400000;
    // Get the start of this year
    var nYearStart = new Date(new Date(nYearDate).getFullYear(), 0, 1).valueOf();
    // Number of week. The round() eliminates the effect of daylight saving.
    return Math.floor(Math.round((nYearDate - nYearStart) / 86400000) / 7) + 1;
};
Date.prototype.addDateSpan = function (oDateSpan) {
    oDateSpan = jQuery.extend({
        nNbYears: 0,
        nNbMonths: 0,
        nNbDays: 0
    }, oDateSpan);
    if (oDateSpan.nNbYears || oDateSpan.nNbMonths) {
        // adjust year and month, accounting for both directions
        var nMonth = this.getMonth() + oDateSpan.nNbMonths + oDateSpan.nNbYears * 12;
        var nYear = this.getFullYear() + Math.floor(nMonth / 12);
        nMonth %= 12;
        if (nMonth < 0) {
            nMonth += 12;
        }
        var nDate = Math.min(Date.getDaysOfMonth(nYear, nMonth), this.getDate());
        // prevent rollover by setDate logic
        this.setDate(1);
        this.setFullYear(nYear);
        this.setMonth(nMonth);
        this.setDate(nDate);
    }
    if (oDateSpan.nNbDays) {
        // Convert the days to milliseconds and add it to the UNIX timestamp.
        // Taking noon helps to avoid 1 day error due to the daylight saving.
        var dtmNoon = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 12);
        var dtmResult = new Date(dtmNoon.getTime() + oDateSpan.nNbDays * 86400000);
        // prevent rollover by setDate logic
        this.setDate(1);
        this.setFullYear(dtmResult.getFullYear());
        this.setMonth(dtmResult.getMonth());
        this.setDate(dtmResult.getDate());
        // Some browser fail to adjust for DST
        if (this.getDate() != dtmResult.getDate()) {
            this.setUTCHours(this.getUTCHours() + (this.getDate() < dtmResult.getDate() ? 1 : -1));
        }
    }
    return this;
};
Date.prototype.clearTime = function () {
    this.setHours(0);
    this.setMinutes(0);
    this.setSeconds(0);
    this.setMilliseconds(0);
    return this;
};
Date.prototype.IsOnTheSameDate = function (dtmDate) {
    return this.getFullYear() === dtmDate.getFullYear() &&
        this.getMonth() === dtmDate.getMonth() &&
        this.getDate() === dtmDate.getDate();
};
Date.prototype.cloneDate = function (bDontKeepTime) {
    if (bDontKeepTime) {
        return new Date(+this).clearTime();
    }
    return new Date(+this);
};
// Date function (see DateJS project)
Date.isLeapYear = function (year) {
    return year % 4 === 0 &&
        (year % 100 !== 0 || year % 400 === 0);
};
Date.getDaysOfMonth = function (year, month) {
    switch (month) {
        case 1: // Feb
            return Date.isLeapYear(year) ? 29 : 28;
        case 3: // Apr
        case 5: // Jun
        case 8: // Sep
        case 10: // Nov
            return 30;
    }
    return 31;
};
Date.getWeekOfYear = function (nYear, nMonth, nDay) {
    return new Date(nYear, nMonth, nDay)
        .getWeekOfYear();
};
Date.parseISO = function (strISODate) {
    // Create from ISO string
    var dtmDate = new Date();
    var year = dtmDate.getFullYear();
    var month = dtmDate.getMonth() + 1;
    var day = dtmDate.getDate();
    var hour = dtmDate.getHours();
    var minute = dtmDate.getMinutes();
    var second = dtmDate.getSeconds();
    var ms = dtmDate.getMilliseconds();
    var isoMatch = strISODate.match(/^(\d\d\d\d)(?:-(\d\d)(?:-(\d\d)(?:T(\d\d):(\d\d)(?::(\d\d)(?:.(\d+))?)?(?:(?:(Z)|([\+-])(\d\d):(\d\d))?))?)?)?$/);
    if (!isoMatch) {
        return undefined;
    }
    // "2015-12-31T23:00:02.5600-10:00" =>
    // ["2015-12-31T23:00:02.5600-10:00", "2015", "12", "31", "23", "00", "02", "5600", undefined, "-", "10", "00"]
    // Parse date
    year = parseInt(isoMatch[1], 10);
    month = parseInt(isoMatch[2] || "01", 10);
    day = parseInt(isoMatch[3] || "01", 10);
    // Parse time
    hour = parseInt(isoMatch[4] || "00", 10);
    minute = parseInt(isoMatch[5] || "00", 10);
    second = parseInt(isoMatch[6] || "00", 10);
    ms = parseInt(((isoMatch[7] || "0") + "0000").substr(0, 3), 10);
    var offset = undefined;
    if (isoMatch[9] == '+' || isoMatch[9] == '-') {
        offset = (parseInt(isoMatch[10], 10) * 60 + parseInt(isoMatch[11], 10)) *
            (isoMatch[9] == '+' ? 1 : -1);
    }
    else if (isoMatch[8] == 'Z') {
        offset = 0;
    }
    // Return the date
    var dtmDate = new Date(year, month - 1, day, hour, minute, second, ms);
    dtmDate = new Date(dtmDate.getTime() - (offset === undefined ? 0 :
        ((isoMatch[4] ? dtmDate.getTimezoneOffset() : 0) + offset) * 60000));
    return dtmDate;
};
//# sourceMappingURL=DateExtensions.js.map;
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        /** Class to handle timezones and ISO-dates.
          */
        class CDateTimeOffset {
            /** Default constructor */
            constructor(oInit, bUTC) {
                // Holds the date-part
                this.m_dtmDatePart = new Date();
                // Holds the offset to gmt (in Minutes)
                this.m_nNbMinutesOffset = this.m_dtmDatePart.getTimezoneOffset();
                // Should hold the info, whether date was initialized with a valid value
                this.m_bIsValid = false;
                if (typeof oInit == "string") {
                    // Cast to support type-checking
                    var strISODate = oInit;
                    // Create from ISO string
                    var year = this.m_dtmDatePart.getFullYear();
                    var month = this.m_dtmDatePart.getMonth() + 1;
                    var day = this.m_dtmDatePart.getDate();
                    var hour = this.m_dtmDatePart.getHours();
                    var minute = this.m_dtmDatePart.getMinutes();
                    var second = this.m_dtmDatePart.getSeconds();
                    var dateMatch = strISODate.match(/\d\d\d\d-\d\d-\d\d/);
                    if (dateMatch) {
                        var parts = dateMatch[0].match(/\d+/g);
                        year = parseInt(parts[0], 10);
                        month = parseInt(parts[1], 10);
                        day = parseInt(parts[2], 10);
                        // date is sufficient
                        this.m_bIsValid = true;
                    }
                    var timeMatch = strISODate.match(/\d\d:\d\d:\d\d/);
                    if (timeMatch) {
                        var parts = timeMatch[0].match(/\d+/g);
                        hour = parseInt(parts[0], 10);
                        minute = parseInt(parts[1], 10);
                        second = parseInt(parts[2], 10);
                        // time is sufficient
                        this.m_bIsValid = true;
                    }
                    // Set the datepart
                    this.m_dtmDatePart = new Date(year, month - 1, day, hour, minute, second);
                    // Holds the offset to gmt (in Minutes)
                    this.m_nNbMinutesOffset = this.m_dtmDatePart.getTimezoneOffset();
                    // Set the offset
                    var offsetMatch = strISODate.match(/[\+-]\d\d:\d\d/);
                    if (offsetMatch) {
                        var parts = offsetMatch[0].match(/\d+/g);
                        this.m_nNbMinutesOffset = (offsetMatch[0][0] == "+" ? -1 : +1) *
                            (parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10));
                    }
                    else if (strISODate.indexOf("Z") != -1) {
                        this.m_nNbMinutesOffset = 0;
                    }
                }
                else if (oInit instanceof Date) {
                    // Cast to support type-checking
                    var dtmDate = oInit;
                    // Init with a date object
                    this.m_dtmDatePart = new Date();
                    this.m_dtmDatePart.setTime(dtmDate.getTime());
                    this.m_nNbMinutesOffset = this.m_dtmDatePart.getTimezoneOffset();
                    // Set the offset
                    if (bUTC === true) {
                        this.m_nNbMinutesOffset = 0;
                    }
                    this.m_bIsValid = true;
                }
                else if (oInit instanceof (CDateTimeOffset)) {
                    // Cast to support type-checking
                    var oDateOffset = oInit;
                    // Init with a dateoffset object
                    this.m_dtmDatePart = new Date();
                    this.m_dtmDatePart.setTime(oDateOffset.m_dtmDatePart.getTime());
                    this.m_nNbMinutesOffset = oDateOffset.m_nNbMinutesOffset;
                    this.m_bIsValid = oDateOffset.m_bIsValid;
                }
                else if (oInit === undefined) {
                    // Init for now
                    this.m_bIsValid = true;
                }
            }
            /** Access the date part of the instance.
              */
            GetDatePart() {
                return this.m_dtmDatePart;
            }
            /** Access the offset of the instance.
              */
            GetOffset() {
                return this.m_nNbMinutesOffset;
            }
            /** Is the instance valid.
              */
            IsValid() {
                return this.m_bIsValid;
            }
            /** Set the instance valid or invalid.
              */
            SetValid(bValid) {
                this.m_bIsValid = bValid;
            }
            /** Set the date of this instance
              * @param dtmDate Date to set to
              * @param nNbHours Hour to set to (optional)
              * @param nNbMinutes Minute to set to (optional)
              * @param nNbSeconds Second to set to (optional)
              * @returns This datetimeoffset instance
              */
            SetDate(dtmDate, nNbHours, nNbMinutes, nNbSeconds) {
                if (dtmDate) {
                    this.m_nNbMinutesOffset -= this.m_dtmDatePart.getTimezoneOffset();
                    this.m_dtmDatePart.setFullYear(dtmDate.getFullYear(), dtmDate.getMonth(), dtmDate.getDate());
                    if (nNbHours) {
                        // Init to a specific time?
                        this.m_dtmDatePart.setHours(nNbHours, nNbMinutes, nNbSeconds);
                    }
                    this.m_nNbMinutesOffset += this.m_dtmDatePart.getTimezoneOffset();
                }
                else {
                    this.m_bIsValid = false;
                }
                return this;
            }
            /** Set the time of this instance
              * @param nNbHours Hour to set to
              * @param nNbMinutes Minute to set to (optional)
              * @param nNbSeconds Second to set to (optional)
              * @returns This datetimeoffset instance
              */
            SetTime(nNbHours, nNbMinutes, nNbSeconds) {
                if (nNbSeconds === undefined) {
                    nNbSeconds = this.m_dtmDatePart.getSeconds();
                }
                if (nNbMinutes === undefined) {
                    nNbMinutes = this.m_dtmDatePart.getMinutes();
                }
                if (nNbHours !== undefined && (nNbHours >= 0 && nNbHours < 24) &&
                    nNbMinutes != undefined && (nNbMinutes >= 0 && nNbMinutes < 60) &&
                    nNbSeconds != undefined && (nNbSeconds >= 0 && nNbSeconds < 60)) {
                    this.m_nNbMinutesOffset -= this.m_dtmDatePart.getTimezoneOffset();
                    this.m_dtmDatePart.setHours(nNbHours, nNbMinutes, nNbSeconds);
                    this.m_nNbMinutesOffset += this.m_dtmDatePart.getTimezoneOffset();
                }
                else {
                    this.m_bIsValid = false;
                }
                return this;
            }
            /** Set the offset of this instance
              * @param nNbMinutesOffset Offset in minutes to set
              * @returns This datetimeoffset instance
              */
            SetOffset(nNbMinutesOffset) {
                if (nNbMinutesOffset !== undefined) {
                    this.m_nNbMinutesOffset = nNbMinutesOffset;
                }
                else {
                    this.m_bIsValid = false;
                }
                return this;
            }
            /** Set the month of this instance
              * @param dtmDate Date with month to set to
              * @param nNbDays Day to set the month to (optional)
              * @param nNbHours Hour to set to (optional)
              * @param nNbMinutes Minute to set to (optional)
              * @param nNbSeconds Second to set to (optional)
              * @returns This datetimeoffset instance
              */
            SetMonth(dtmDate, nNbDays, nNbHours, nNbMinutes, nNbSeconds) {
                if (dtmDate) {
                    if (nNbDays === undefined) {
                        nNbDays = this.m_dtmDatePart.getDate();
                    }
                    this.m_nNbMinutesOffset -= this.m_dtmDatePart.getTimezoneOffset();
                    do {
                        this.m_dtmDatePart.setFullYear(dtmDate.getFullYear(), dtmDate.getMonth(), nNbDays);
                        // If the day is greater than the maximum day in the month, the month wraps around
                        // Stop this from happining by decreasing the day within the month
                    } while (this.m_dtmDatePart.getMonth() != dtmDate.getMonth() && nNbDays-- > 1);
                    if (nNbHours) {
                        // Init to a specific time?
                        this.m_dtmDatePart.setHours(nNbHours, nNbMinutes, nNbSeconds);
                    }
                    this.m_nNbMinutesOffset += this.m_dtmDatePart.getTimezoneOffset();
                }
                else {
                    this.m_bIsValid = false;
                }
                return this;
            }
            /** Add the given duration to the current date-instance
              * @param iDateSpan Duration to add to the current instance
              */
            AddDateSpan(iDateSpan) {
                if (this.m_bIsValid) {
                    this.m_dtmDatePart.addDateSpan(iDateSpan);
                }
                return this;
            }
            /** Get the timespan between this instance and the given one
              * @param oDateTimeOffsetOther DateTimeOffset to get the timespan to the current instance
              * @returns The number of milliseconds calculated by (this - other)
              */
            GetTimeSpan(oDateTimeOffsetOther) {
                if (!this.m_bIsValid || !oDateTimeOffsetOther.m_bIsValid) {
                    return NaN;
                }
                var nDifference = (this.m_dtmDatePart.valueOf() - oDateTimeOffsetOther.m_dtmDatePart.valueOf()) +
                    (this.m_nNbMinutesOffset - oDateTimeOffsetOther.m_nNbMinutesOffset) * 60 * 1000;
                return nDifference;
            }
            /** Create the ISO representation
              * @returns The ISO representation of the datetimeoffset
              */
            toString() {
                if (this.m_bIsValid) {
                    var strOffset = "Z";
                    if (this.m_nNbMinutesOffset != 0) {
                        var offset = Math.abs(this.m_nNbMinutesOffset);
                        var minutes = offset % 60;
                        var hours = (offset - minutes) / 60;
                        strOffset = (this.m_nNbMinutesOffset > 0 ? "-" : "+") +
                            ("00" + hours).slice(-2) + ":" +
                            ("00" + minutes).slice(-2);
                    }
                    return ("0000" + this.m_dtmDatePart.getFullYear()).slice(-4) + "-" +
                        ("00" + (this.m_dtmDatePart.getMonth() + 1)).slice(-2) + "-" +
                        ("00" + this.m_dtmDatePart.getDate()).slice(-2) + "T" +
                        ("00" + this.m_dtmDatePart.getHours()).slice(-2) + ":" +
                        ("00" + this.m_dtmDatePart.getMinutes()).slice(-2) + ":" +
                        ("00" + this.m_dtmDatePart.getSeconds()).slice(-2) + strOffset;
                }
                return "";
            }
            /** Create the date representation
              * @returns The date portion of the ISO representation of this instance
              */
            toDateString() {
                if (this.m_bIsValid) {
                    return ("0000" + this.m_dtmDatePart.getFullYear()).slice(-4) + "-" +
                        ("00" + (this.m_dtmDatePart.getMonth() + 1)).slice(-2) + "-" +
                        ("00" + this.m_dtmDatePart.getDate()).slice(-2);
                }
                return "";
            }
            /** Create the time representation
              * @returns The time portion of the ISO representation of this instance
              */
            toTimeString() {
                if (this.m_bIsValid) {
                    return ("00" + this.m_dtmDatePart.getHours()).slice(-2) + ":" +
                        ("00" + this.m_dtmDatePart.getMinutes()).slice(-2) + ":" +
                        ("00" + this.m_dtmDatePart.getSeconds()).slice(-2);
                }
                return "";
            }
            /** Create the month representation
              * @returns The month portion of the ISO representation of this instance
              */
            toMonthString() {
                if (this.m_bIsValid) {
                    return ("0000" + this.m_dtmDatePart.getFullYear()).slice(-4) + "-" +
                        ("00" + (this.m_dtmDatePart.getMonth() + 1)).slice(-2);
                }
                return "";
            }
        }
        /** Mapping of IANA timezones to Windows-timezones.
          * IANA: http://www.iana.org/time-zones
          * Windows: http://technet.microsoft.com/de-de/library/cc749073%28v=ws.10%29.aspx
          */
        CDateTimeOffset.tzWindowsMapping = {
            "Africa/Johannesburg": "South Africa Standard Time",
            "Africa/Lagos": "W. Central Africa Standard Time",
            "Africa/Windhoek": "Namibia Standard Time",
            "America/Anchorage": "Alaskan Standard Time",
            "America/Argentina/Buenos_Aires": "Argentina Standard Time",
            "America/Asuncion": "Paraguay Standard Time",
            "America/Bogota": "SA Pacific Standard Time",
            "America/Campo_Grande": "Central Brazilian Standard Time",
            "America/Caracas": "Venezuela Standard Time",
            "America/Chicago": "Central Standard Time",
            "America/Denver": "Mountain Standard Time",
            "America/Godthab": "Greenland Standard Time",
            "America/Guatemala": "Central America Standard Time",
            "America/Halifax": "Atlantic Standard Time",
            "America/Los_Angeles": "Pacific Standard Time",
            "America/Mazatlan": "Mountain Standard Time (Mexico)",
            "America/Mexico_City": "Central Standard Time (Mexico)",
            "America/Montevideo": "Montevideo Standard Time",
            "America/New_York": "Eastern Standard Time",
            "America/Phoenix": "US Mountain Standard Time",
            "America/Santo_Domingo": "SA Western Standard Time",
            "America/Santa_Isabel": "Pacific Standard Time (Mexico)",
            "America/Sao_Paulo": "E. South America Standard Time",
            "America/St_Johns": "Newfoundland Standard Time",
            "Asia/Baghdad": "Arabic Standard Time",
            "Asia/Baku": "Azerbaijan Standard Time",
            "Asia/Beirut": "Middle East Standard Time",
            "Asia/Damascus": "Syria Standard Time",
            "Asia/Dhaka": "Bangladesh Standard Time",
            "Asia/Dubai": "Arabian Standard Time",
            "Asia/Jakarta": "SE Asia Standard Time",
            "Asia/Jerusalem": "Israel Standard Time",
            "Asia/Kabul": "Afghanistan Standard Time",
            "Asia/Karachi": "Pakistan Standard Time",
            "Asia/Kathmandu": "Nepal Standard Time",
            "Asia/Kolkata": "India Standard Time",
            "Asia/Rangoon": "Myanmar Standard Time",
            "Asia/Shanghai": "China Standard Time",
            "Asia/Tehran": "Iran Standard Time",
            "Asia/Tokyo": "Tokyo Standard Time",
            "Asia/Yerevan": "Caucasus Standard Time",
            "Atlantic/Azores": "Azores Standard Time",
            "Atlantic/Cape_Verde": "Cape Verde Standard Time",
            "Australia/Adelaide": "Cen. Australia Standard Time",
            "Australia/Brisbane": "E. Australia Standard Time",
            "Australia/Darwin": "AUS Central Standard Time",
            "Australia/Sydney": "AUS Eastern Standard Time",
            "Etc/GMT-12": "Dateline Standard Time",
            "Etc/UTC": "UTC",
            "Europe/Berlin": "W. Europe Standard Time",
            "Europe/Helsinki": "FLE Standard Time",
            "Europe/Istanbul": "Turkey Standard Time",
            "Europe/London": "GMT Standard Time",
            "Pacific/Apia": "Samoa Standard Time",
            "Pacific/Auckland": "New Zealand Standard Time",
            "Pacific/Fiji": "Fiji Standard Time",
            "Pacific/Honolulu": "Hawaiian Standard Time",
            "Pacific/Noumea": "Central Pacific Standard Time",
            "Pacific/Pago_Pago": "UTC-11",
            "Pacific/Tarawa": "UTC+12",
            "Pacific/Tongatapu": "Tonga Standard Time"
        };
        Util.CDateTimeOffset = CDateTimeOffset;
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
//# sourceMappingURL=DateTimeOffset.js.map;
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        /** Class to handle identifier defines
          */
        class CKey {
            /** Checks whether the given id is valid
              * @param kId The id to be checked
              * @returns True if kId is a valid id
              */
            static IsValid(kId) {
                return kId > 0;
            }
        }
        /** InvalidId
          */
        CKey.Invalid = -1;
        Util.CKey = CKey;
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
//# sourceMappingURL=Key.js.map;
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        //==============================================================================================
        /** Class to analyze and hold an complete url with root and parameter-array
          */
        class CUri {
            //===========================================================================================
            /** Create an instance of CUrlParams for the given URL
              * @param strUri Url to initialize with
              */
            constructor(strUri) {
                if (!strUri) { // We need a valid uri
                    throw new Error("Invalid argument (strUri)");
                }
                var astrUrlParts = strUri.split("?");
                // Save to the members
                this.m_strUrl = strUri;
                this.m_strUrlRoot = astrUrlParts[0];
                this.m_oUrlParams = {};
                // Analyze the params
                if (astrUrlParts.length > 1) {
                    var strUrlParams = strUri
                        .substr(astrUrlParts[0].length + 1);
                    var astrParamsParts = strUrlParams.split("#");
                    if (astrParamsParts.length > 1) {
                        this.m_strUrlHash = strUrlParams
                            .substr(astrParamsParts[0].length + 1);
                        // Now adapt the url-params string
                        strUrlParams = astrParamsParts[0];
                    }
                    var astrUrlParams = strUrlParams.split("&");
                    var oUrlParams = this.m_oUrlParams;
                    $.each(astrUrlParams, function (nIndex, strParam) {
                        var astrUrlParam = strParam.split("=");
                        var strName = "";
                        var strValue = CUri.DecodeParam(astrUrlParam[0]);
                        if (astrUrlParam.length > 1) { // Default parameter structure
                            strName = strValue;
                            strValue = CUri.DecodeParam(astrUrlParam[1]);
                        }
                        oUrlParams[strName] = strValue;
                    });
                }
            }
            //===========================================================================================
            /** Get the url for this params instance.
              * @returns The url of this instance.
              */
            GetUrl() {
                var astrUrlParts = [this.m_strUrlRoot];
                if (this.GetParamCount() > 0) {
                    var astrUrlParams = [];
                    $.each(this.m_oUrlParams, function (strName, strValue) {
                        if (typeof strName === 'string') {
                            astrUrlParams.push(CUri.EncodeParam(strName) + "=" +
                                CUri.EncodeParam(strValue));
                        }
                    });
                    astrUrlParts.push(astrUrlParams.join("&"));
                }
                return astrUrlParts.join("?") +
                    (this.m_strUrlHash ? "#" + this.m_strUrlHash : "");
            }
            //===========================================================================================
            /** Get the value for the param with the name
              * given or undefined if it does not exist.
              * @param strName Name of the param to get the value for
              * @returns The value of the param with the given name
              */
            GetValue(strName) {
                return this.m_oUrlParams[strName];
            }
            //===========================================================================================
            /** Set the value for the param with the given name.
              * @param strName Name of the param to set the value for
              * @param strValue Value to set (null to delete the param)
              */
            SetValue(strName, strValue) {
                if (strValue === null) { // Remove the value.
                    delete this.m_oUrlParams[strName];
                }
                else { // Set the value
                    this.m_oUrlParams[strName] = strValue;
                }
            }
            //===========================================================================================
            /** Remove the param with the given name.
              * @param strName Name of the param to remove
              */
            Remove(strName) {
                delete this.m_oUrlParams[strName];
            }
            //===========================================================================================
            /** Get the value for the hash
              * given or undefined if it does not exist.
              * @returns The value of the param with the given name
              */
            GetHash() {
                return this.m_strUrlHash;
            }
            //===========================================================================================
            /** Set the value for the hash.
              * @param strValue Value to set
              */
            SetHash(strValue) {
                this.m_strUrlHash = strValue;
            }
            //===========================================================================================
            /** Remove the hash.
              */
            RemoveHash() {
                delete this.m_strUrlHash;
            }
            //===========================================================================================
            /** Access the params of this url-instance.
              */
            GetUrlRoot() {
                return this.m_strUrlRoot;
            }
            //===========================================================================================
            /** Access the params of this url-instance.
              */
            GetParamCount() {
                var nCount = 0;
                for (var strName in this.m_oUrlParams) {
                    if (this.m_oUrlParams.hasOwnProperty(strName))
                        nCount++;
                }
                return nCount;
            }
            //===========================================================================================
            /** Access the params of this url-instance.
              */
            GetParams() {
                return this.m_oUrlParams;
            }
            //===========================================================================================
            /** Access the params of this url-instance.
              */
            Param(strName, strValue) {
                if (strValue === undefined) { // Get the value
                    return this.GetValue(strName);
                }
                // Set the value
                this.SetValue(strName, strValue);
            }
            //===========================================================================================
            /** Encode the given value for using within an URI.
              * @param strParam Value to be encoded as URI-component
              * @returns The encoded text to be used within an url
              */
            static EncodeParam(strParam) {
                var strValue = encodeURIComponent(strParam);
                return strValue.replace(/%20/g, "+");
            }
            //===========================================================================================
            /** Decode the given value of the URI-component.
              * @param strParam URI-component to be decoded
              * @returns The decoded text that was use within an url
              */
            static DecodeParam(strParam) {
                strParam = strParam.replace(/\+/g, "%20");
                return decodeURIComponent(strParam);
            }
            //===========================================================================================
            /** Get the param with the given name.
              * @param strName Name to get the value for.
              * @returns The value for the given name.
              */
            static GetCurrentUrlParam(strName) {
                var oUri = new CUri(location.href);
                // Get the value
                return oUri.GetValue(strName);
            }
        }
        Util.CUri = CUri;
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
//# sourceMappingURL=Uri.js.map;
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        /** Class to handle control-behaviour
          */
        class CComboBoxTool {
            //===========================================================================================
            /** Implementation for Options */
            static Options(oParam, oOptions) {
                var jElement = $(oParam);
                var oComboBoxOptions = $.extend({
                    Format: "{Name}",
                    UseGuid: false,
                    EmptyItem: CComboBoxTool.g_oEmptyEntry
                }, jElement.data('options'), oOptions);
                if (oOptions) { // Update the saved options
                    jElement.data('options', oComboBoxOptions);
                }
                // Return the options
                return oComboBoxOptions;
            }
            //===========================================================================================
            /** Implementation for ClearDisableComboBox */
            static ClearDisableComboBox(oParam, bDisable, bAddEmptyItem) {
                var jElement = $(oParam);
                // Remove the options
                jElement.children('option').remove();
                // Update the disabled state
                if (bDisable != jElement.is(':disabled')) { // Disable the control
                    jElement.prop('disabled', bDisable ? 'disabled' : null);
                }
                var oOptions = CComboBoxTool.Options(jElement);
                if (bAddEmptyItem && oOptions.EmptyItem) {
                    jElement.append(CComboBoxTool.CreateOption(oOptions.EmptyItem, oOptions));
                }
            }
            //===========================================================================================
            /** Implementation for LoadComboBox */
            static LoadComboBox(oParam, aoItems, bAddEmptyItem, strSelect) {
                var jElement = $(oParam);
                var oOptions = CComboBoxTool.Options(jElement);
                // Remove the options
                jElement.children('option').remove();
                if (bAddEmptyItem && oOptions.EmptyItem) {
                    jElement.append(CComboBoxTool.CreateOption(oOptions.EmptyItem, oOptions));
                }
                for (var i = 0; i < aoItems.length; i++) {
                    var jOption = CComboBoxTool.CreateOption(aoItems[i], oOptions);
                    // Append it
                    jElement.append(jOption);
                }
                if (strSelect) { // Select the correct entry
                    jElement.val(strSelect);
                }
            }
            //===========================================================================================
            /** Create an option element to be filled into the combobox.
              * @param oEntry Entry to be used for creation of the option element.
              * @param oOptions Options of the combobox to consider.
              * @returns The option element that was created.
              */
            static CreateOption(oEntry, oOptions) {
                var jOption = 'option'.toNode();
                // Format the content
                var strContent = oOptions.Format
                    .replace(/\{Name\}/g, oEntry.Name)
                    .replace(/\{CustId\}/g, oEntry.CustId || "---");
                // Set the content
                jOption.html(strContent);
                // Set the value
                jOption.attr('value', oOptions.UseGuid ? oEntry.Guid : String(oEntry.Id));
                // Set further attributes
                if (oOptions.UseGuid && oEntry.Id) {
                    jOption.attr('data-id', oEntry.Id);
                }
                if (!oOptions.UseGuid && oEntry.Guid) {
                    jOption.attr('data-guid', oEntry.Guid);
                }
                return jOption;
            }
        }
        //===========================================================================================
        /** Empty entry to use with ClearDisableComboBox
          */
        CComboBoxTool.g_oEmptyEntry = { Id: -1, Name: "", CustId: "", Guid: "" };
        Util.CComboBoxTool = CComboBoxTool;
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
//# sourceMappingURL=ComboBoxTool.js.map;
//=================================================================================================
String.prototype.toInt = function (nBase) {
    return parseInt(this, nBase || 10);
};
//=================================================================================================
String.prototype.padLeft = function (strChar, nLength) {
    var strValue = this + '';
    while (strValue.length != nLength) {
        strValue = strChar + strValue;
    }
    return strValue;
};
var FI;
(function (FI) {
    var Util;
    (function (Util) {
        //===========================================================================================
        /** Wrap the jquery promise with our own done, fail and always functions
            */
        function FIDeferred() {
            let oDeferred = $.Deferred();
            let oPromise = oDeferred.promise();
            let oFIPromise = {
                done(dFISuccess) {
                    oPromise.done(oParams => dFISuccess(...oParams));
                    return this;
                },
                fail(dFIError) {
                    oPromise.fail(oParams => dFIError(...oParams));
                    return this;
                },
                always(dAlways) {
                    oPromise.always(dAlways);
                    return this;
                },
                success: () => {
                    const oSuccessPromise = Util.FIDeferred();
                    oPromise
                        .then(() => oSuccessPromise.resolve(true))
                        .fail((strError, strErrorMsg) => oSuccessPromise.reject(strError, strErrorMsg));
                    return oSuccessPromise.promise();
                }
            };
            // Create a new deferred with the correct typings
            const oFIDeferred = {
                resolve: (oData, strWarnings) => {
                    oDeferred.resolve([oData, strWarnings || null]);
                    return oFIDeferred;
                },
                reject: (strError, strErrorMsg) => {
                    oDeferred.reject([strError, strErrorMsg || null]);
                    return oFIDeferred;
                },
                promise: () => oFIPromise
            };
            return oFIDeferred;
        }
        Util.FIDeferred = FIDeferred;
        function WaitFor(oFIPromises) {
            const oFIDeferred = FIDeferred();
            const oValues = [];
            let strAllWarnings = null;
            const dHandlePromises = (oRemaining) => {
                const oNext = oRemaining.shift();
                if (!oNext) { // Resolve at the end of the chain
                    oFIDeferred.resolve(oValues, strAllWarnings);
                    return;
                }
                oNext
                    .done((oValue, strWarnings) => {
                    oValues.push(oValue);
                    if (strWarnings) {
                        strAllWarnings = strAllWarnings ? strAllWarnings + "\r\n" : "";
                        strAllWarnings += strWarnings;
                    }
                    dHandlePromises(oRemaining);
                })
                    .fail(oFIDeferred.reject);
            };
            // Start the recursion
            dHandlePromises(oFIPromises);
            return oFIDeferred.promise();
        }
        function WaitForAll(oFIPromises) {
            return WaitFor(oFIPromises);
        }
        Util.WaitForAll = WaitForAll;
        function WaitForResults(oFIPromiseA, oFIPromiseB, oFIPromiseC, oFIPromiseD, oFIPromiseE, oFIPromiseF, oFIPromiseG) {
            if (oFIPromiseG) {
                return WaitFor([
                    oFIPromiseA,
                    oFIPromiseB,
                    oFIPromiseC,
                    oFIPromiseD,
                    oFIPromiseE,
                    oFIPromiseF,
                    oFIPromiseG
                ]);
            }
            if (oFIPromiseF) {
                return WaitFor([
                    oFIPromiseA,
                    oFIPromiseB,
                    oFIPromiseC,
                    oFIPromiseD,
                    oFIPromiseE,
                    oFIPromiseF
                ]);
            }
            if (oFIPromiseE) {
                return WaitFor([
                    oFIPromiseA,
                    oFIPromiseB,
                    oFIPromiseC,
                    oFIPromiseD,
                    oFIPromiseE
                ]);
            }
            if (oFIPromiseD) {
                return WaitFor([
                    oFIPromiseA,
                    oFIPromiseB,
                    oFIPromiseC,
                    oFIPromiseD
                ]);
            }
            if (oFIPromiseC) {
                return WaitFor([
                    oFIPromiseA,
                    oFIPromiseB,
                    oFIPromiseC
                ]);
            }
            return WaitFor([oFIPromiseA, oFIPromiseB]);
        }
        Util.WaitForResults = WaitForResults;
        //**********************************************************************************************
        // Class CWebTool
        //**********************************************************************************************
        class CWebTool {
            //===========================================================================================
            static ParseInt(strValue) {
                // because it is considered as octal and not base 10!!!
                return parseInt(strValue, 10);
            }
            //===========================================================================================
            static ParseFloat(strValue) {
                if (!strValue) {
                    return 0.0;
                }
                // We replace the coma with points for french floats
                strValue = strValue.replace(",", ".");
                return parseFloat(strValue);
            }
            //===========================================================================================
            static Navigate(strUrl, bForceReload = false) {
                if (location.href != strUrl) {
                    location.href = strUrl;
                }
                else if (bForceReload) { // location.reload(true); // Doesn't work on Chrome, so we use another implementation.
                    strUrl = CUriTool.AddParams(strUrl, "ts=" + new Date().getTime());
                    location.href = strUrl;
                }
            }
        }
        Util.CWebTool = CWebTool;
        //**********************************************************************************************
        // CDateTimeTool
        //**********************************************************************************************
        class CDateTimeTool {
            // CONSTRUCTOR
            //===========================================================================================
            // We have to implent this so because Typescript do not have static constructors. 
            // (only normal instance constructors).
            //===========================================================================================
            static Initialize() {
                this.Invalid.setFullYear(1, 0, 1); // Setting january 1st 0001. We have to set the date 
                // with setFullYear() because the constructor assume an offset of 1900 for the year.
                return true;
            }
            //===========================================================================================
            static ParseDate(strDate) {
                if (strDate == null || strDate.length == 0) {
                    return CDateTimeTool.Invalid;
                }
                var oRegExp = new RegExp("^(\\d+).(\\d+).(\\d+)$", "g");
                var oMatch = oRegExp.exec(strDate);
                if (oMatch == null) {
                    return CDateTimeTool.Invalid;
                }
                var nDay = parseInt(oMatch[1], 10);
                var nMonth = parseInt(oMatch[2], 10);
                var nYear = parseInt(oMatch[3], 10);
                // Perform checks.
                if ((nYear < 0) || (nYear > 9999)) {
                    return CDateTimeTool.Invalid;
                }
                if ((nMonth < 1) || (nMonth > 12)) {
                    return CDateTimeTool.Invalid;
                }
                if ((nDay < 1) || (nDay > 31)) {
                    return CDateTimeTool.Invalid;
                }
                var dtmDate = new Date(0, 0, 0, 0, 0, 0, 0); // All 0 from year up to milliseconds
                dtmDate.setFullYear(nYear, nMonth - 1, nDay); // we have to use setFullYear() because
                // the constructor would assume a year as an offset to 1900.
                return dtmDate;
            }
            //===========================================================================================
            static IsValidDate(dtmDate) {
                if (dtmDate == null) {
                    return false;
                }
                return dtmDate > this.Invalid;
            }
            //===========================================================================================
            static IsValidDateString(strDate) {
                var dtmDate = this.ParseDate(strDate);
                return this.IsValidDate(dtmDate);
            }
            //===========================================================================================
            static IsEqualDate(dtmDate1, dtmDate2) {
                return dtmDate1.getFullYear() == dtmDate2.getFullYear()
                    && dtmDate1.getMonth() == dtmDate2.getMonth()
                    && dtmDate1.getDate() == dtmDate2.getDate();
            }
            //===========================================================================================
            static Today() {
                var dtmNow = new Date();
                return new Date(dtmNow.getFullYear(), dtmNow.getMonth(), dtmNow.getDate());
            }
            //===========================================================================================
            static StdFormat(dtmDate) {
                return dtmDate.getDate().toString().padLeft("0", 2) + "."
                    + (dtmDate.getMonth() + 1).toString().padLeft("0", 2) + "."
                    + dtmDate.getFullYear().toString().padLeft("0", 4);
            }
        }
        //===========================================================================================
        CDateTimeTool.Invalid = new Date(0, 0, 0, 0, 0, 0, 0); // All 0 from year up to milliseconds
        CDateTimeTool.c_bInitialized = CDateTimeTool.Initialize();
        Util.CDateTimeTool = CDateTimeTool;
        //**********************************************************************************************
        // CNameValue
        //**********************************************************************************************
        class CNameValue {
            //===========================================================================================
            constructor(strName, strValue) {
                this.name = strName;
                this.value = strValue;
            }
        }
        Util.CNameValue = CNameValue;
        //**********************************************************************************************
        // CUriTool
        //**********************************************************************************************
        class CUriTool {
            //===========================================================================================
            static GetParam(strParam) {
                strParam = strParam.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
                var strPattern = "[\\?&]" + strParam + "=([^&#]*)";
                var oRegEx = new RegExp(strPattern);
                var astrResults = oRegEx.exec(window.location.href);
                if (astrResults == null) {
                    return "";
                }
                else {
                    return astrResults[1];
                }
            }
            //===========================================================================================
            static AddParamString(strUrl, strParams) {
                var strResult = strUrl;
                if (strParams != null && strParams.length > 0) {
                    if (strResult.indexOf("?") >= 0) {
                        strResult += "&" + strParams;
                    }
                    else {
                        strResult += "?" + strParams;
                    }
                }
                return strResult;
            }
            //===========================================================================================
            static UrlEncode(strParam) {
                // For details about this implementation, see  the corresponding implementation in C#
                var strValue = encodeURIComponent(strParam);
                return strValue.replace(/%20/g, "+").replace("'", "%27");
            }
            //===========================================================================================
            static UrlDecode(strParam) {
                strParam = strParam.replace(/\+/g, "%20");
                return decodeURIComponent(strParam);
            }
            //===========================================================================================
            static BuildParamString(oQueryParams) {
                var strQuery = "";
                var strAnd = "";
                for (var nIdx = 0; nIdx < oQueryParams.length; nIdx++) {
                    var strValue = CUriTool.UrlEncode(oQueryParams[nIdx].value);
                    strQuery += strAnd;
                    strQuery += CUriTool.UrlEncode(oQueryParams[nIdx].name) + "=" + strValue;
                    strAnd = "&";
                }
                return strQuery;
            }
            //===========================================================================================
            // This function every type of params for building an url (string, or NameValue array or 
            // object). NameValue array is now deprecated, we shouldn't use it any more.
            //===========================================================================================
            static AddParams(strPath, oParams) {
                var strParams = null;
                if (typeof oParams === 'string') {
                    strParams = oParams;
                }
                else if ($.isArray(oParams) && oParams.length > 0 && oParams[0].name != "undefined") {
                    strParams = this.BuildParamString(oParams);
                }
                else {
                    strParams = $.param(oParams);
                }
                return this.AddParamString(strPath, strParams);
            }
            //===========================================================================================
            static AddParamObject(strPath, oParams) {
                return this.AddParamString(strPath, $.param(oParams));
            }
            //===========================================================================================
            static FormatDateForUrl(dtmDate) {
                var strDate = dtmDate.getFullYear().toString().padLeft("0", 4) + "-"
                    + (dtmDate.getMonth() + 1).toString().padLeft("0", 2) + "-"
                    + dtmDate.getDate().toString().padLeft("0", 2);
                return strDate;
            }
            //===========================================================================================
            static ParseUrlDate(strDate) {
                return new Date(strDate); // This is the default format that javascript should be able to 
                // parse.
            }
            //===========================================================================================
            static ResolveUrl(strAppPath, strUrl) {
                var strResolvedUrl = "";
                if (strUrl.length == 0 || strUrl.charAt(0) != '~') { // there is no ~ in the first character position, just return the strUrl
                    strResolvedUrl = strUrl;
                }
                else if (strUrl.length == 1) { // there is just the ~ in the URL, return the strAppPath
                    strResolvedUrl = strAppPath;
                }
                else if (strUrl.charAt(1) == '/' || strUrl.charAt(1) == '\\') { // Url looks like ~/ or ~\
                    if (strAppPath.length > 1) {
                        strResolvedUrl = strAppPath + "/" + strUrl.substring(2, strUrl.length);
                    }
                    else {
                        strResolvedUrl = "/" + strUrl.substring(2, strUrl.length);
                    }
                }
                else { // Url looks like ~something
                    if (strAppPath.length > 1) {
                        strResolvedUrl = strAppPath + "/" + strUrl.substring(1, strUrl.length);
                    }
                    else {
                        strResolvedUrl = strAppPath + strUrl.substring(1, strUrl.length);
                    }
                }
                return strResolvedUrl;
            }
        }
        Util.CUriTool = CUriTool;
        //==============================================================================================
        // Util own jquery plugin
        //==============================================================================================
        (function ($) {
            //===========================================================================================
            // A function that only serialize params that have a value. FilterHiddenFields is meant to 
            // fitler out hidden fields that are added by the mvc framework for checkboxes.
            //===========================================================================================
            $.fn.ValueParams = function (bFilterHiddenFields = false, oCondFunc) {
                var strParams = $(":input", this).filter(function () {
                    var $This = $(this);
                    return !!this.value && (!bFilterHiddenFields
                        || $This.attr("type") != "hidden")
                        && ($This.prop("nodeName") != "SELECT" || !$This.prop("multiple"))
                        && (!oCondFunc || oCondFunc($This));
                }).serialize();
                // For multiple select we do not use the default serialization. We do it so in order to 
                // avoid the redirect in SfnRewriter() because of difference in the urls params.
                // Default serialisation would be : "Cities=2&Cities=4&Cities=6". The problem is the 
                // compatibility with NameValueCollection that renders so : "Cities=2,4,6".
                $("select[multiple='multiple'][name]", this).each(function (nIdx, oElem) {
                    var $This = $(this);
                    var strValue = $This.val();
                    if (strValue) {
                        if (strParams) {
                            strParams += "&";
                        }
                        strParams += $This.attr("name") + "=" + CUriTool.UrlEncode(strValue);
                    }
                });
                return strParams;
            };
            //===========================================================================================
            $.fn.IntOnly = function (nLength) {
                var $This = this;
                $This.keypress(function (oEvent) {
                    // First check the length
                    if (nLength && $This.val().length > nLength - 1) {
                        return false;
                    }
                    var cCharCode = oEvent.which;
                    if (cCharCode > 31 && (cCharCode < 48 || cCharCode > 57)) {
                        return false;
                    }
                    return true;
                });
            };
            //===========================================================================================
            $.fn.SafeGetFloat = function () {
                var $This = this;
                var strVal = $This.val();
                return CWebTool.ParseFloat(strVal);
            };
            //===========================================================================================
            $.fn.SafeGetInt = function (nDefault = 0) {
                var $This = this;
                var strVal = $This.val();
                if (!strVal) {
                    return nDefault;
                }
                var nValue = parseInt(strVal, 10);
                if (isNaN(nValue)) {
                    return nDefault;
                }
                return nValue;
            };
            //===========================================================================================
            $.fn.SafeGetId = function () {
                return this.SafeGetInt(Util.CKey.Invalid);
            };
            //===========================================================================================
            $.fn.SafeGetDate = function () {
                return CDateTimeTool.ParseDate(this.val());
            };
        })(jQuery);
    })(Util = FI.Util || (FI.Util = {}));
})(FI || (FI = {}));
//# sourceMappingURL=Util.js.map;
var FI;
(function (FI) {
    var UnitTest;
    (function (UnitTest) {
        //==============================================================================================
        /** All unit-tests for FI
            */
        var c_oSingleton = {};
        //==============================================================================================
        /** Add the given test.
            * @param strName The name of the test.
            * @param dUnitTestRun The test method.
            */
        function Add(strName, dUnitTestRun) {
            c_oSingleton[strName] = dUnitTestRun;
        }
        UnitTest.Add = Add;
        //==============================================================================================
        /** Get the list of unit tests
          */
        function List() {
            var oTests = [];
            for (var strUnitTest in c_oSingleton) {
                oTests.push(strUnitTest);
            }
            return oTests.sort();
        }
        UnitTest.List = List;
        //==============================================================================================
        /** Run the tests.
            * @param strFilterName Only run the test with the given name (optional)
            */
        function Run(strFilterName) {
            var arrTestNames = [];
            // Loop all tests and execute them
            for (var strTestName in c_oSingleton) {
                if (strFilterName !== undefined &&
                    strTestName !== strFilterName) { // Ignore this
                    continue;
                }
                arrTestNames.push(strTestName);
            }
            // Evaluate in a sorted fashion
            arrTestNames.sort();
            // Run the tests
            return RunTests(arrTestNames);
        }
        UnitTest.Run = Run;
        //==============================================================================================
        /** Run the tests.
            * @param strFilterName Only run the test with the given name (optional)
            */
        function RunTests(arrTestNames, jNotify) {
            var jReady = $.Deferred();
            // We are the notifying object if no other was given
            jNotify = jNotify || jReady;
            // Results of the unittests. Is filled during testing.
            var oResults = [];
            if (arrTestNames.length == 0) {
                return jReady.resolve(oResults).promise();
            }
            // Loop all tests and execute them
            var strTestName = arrTestNames.shift();
            var oUnitTestHelper = {
                // ASSERT a specific result (should be true)
                ASSERT: function (strTestName) {
                    return function (strName, bResult, strDescription) {
                        oResults.push({
                            strTestName: strTestName,
                            strName: strName,
                            bSuccess: bResult === true,
                            strDescription: strDescription,
                            strError: bResult !== true ? "ASSERT failed!" : undefined
                        });
                    };
                }(strTestName),
                ASSERT_ASYNC: function (strTestName) {
                    return function (strName, dResult, strDescription) {
                        var jResult = $.Deferred();
                        var oResult = {
                            strTestName: strTestName,
                            strName: strName,
                            bSuccess: undefined,
                            strDescription: strDescription,
                            strError: undefined,
                            jPromise: jResult.promise()
                        };
                        jResult.done((bResult) => {
                            oResult.bSuccess = bResult;
                            oResult.strError = bResult !== true ? "ASSERT failed!" : undefined;
                        });
                        oResults.push(oResult);
                        // Start the call
                        dResult(jResult);
                    };
                }(strTestName),
                THROWS: function (strTestName) {
                    return function (strName, dFunction, strDescription) {
                        try { // Call the function (it should throw an error)
                            dFunction();
                            // No error => failed test
                            oResults.push({
                                strTestName: strTestName,
                                strName: strName,
                                bSuccess: false,
                                strDescription: strDescription,
                                strError: "No Error thrown!"
                            });
                        }
                        catch (oError) { // Error => successful test?!
                            oResults.push({
                                strTestName: strTestName,
                                strName: strName,
                                bSuccess: oError instanceof Error,
                                strDescription: strDescription,
                                strError: oError instanceof Error
                                    ? undefined : ("Thrown error of unexpected type: " + typeof (oError))
                            });
                        }
                    };
                }(strTestName)
            };
            // Do one unit-test and collect all promises that needs to be resolved
            var dDoOneUnitTest = function (dUnitTest) {
                var oPromises = [];
                var nStartIndex = oResults.length;
                dUnitTest(oUnitTestHelper);
                // Now collect the promises
                for (var j = nStartIndex; j < oResults.length; j++) {
                    if (oResults[j].jPromise) { // Add this promise
                        oPromises.push(oResults[j].jPromise);
                    }
                }
                return oPromises;
            };
            var dUnitTest = c_oSingleton[strTestName];
            try { // Do the tests
                var arrPromises = dDoOneUnitTest(dUnitTest);
                // Always have one parameter to when
                arrPromises.push($.Deferred().resolve(true).promise());
                $.when.apply($, arrPromises).then(() => {
                    jNotify.notify("Tests '" + strTestName + "' finished!");
                    var oOtherReady = RunTests(arrTestNames, jNotify);
                    oOtherReady.done((oOtherResults) => {
                        jReady.resolve(oResults.concat(oOtherResults));
                    });
                });
            }
            catch (ex) {
                oResults.push({
                    strTestName: strTestName,
                    strName: "Exception thrown (" + ex.message + ")",
                    bSuccess: false,
                    strDescription: ex.message
                });
                jNotify.notify("Tests '" + strTestName + "' failed!");
                // Error thrown - run the other tests (recursively)
                var oOtherReady = RunTests(arrTestNames, jNotify);
                oOtherReady.done((oOtherResults) => {
                    jReady.resolve(oResults.concat(oOtherResults));
                });
            }
            return jReady.promise();
        }
    })(UnitTest = FI.UnitTest || (FI.UnitTest = {}));
})(FI || (FI = {}));
//# sourceMappingURL=UnitTest.js.map;
