diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index f75018fbdaf..ff1a15a806c 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -127,6 +127,19 @@ $langs->trans("FridayMin"), $langs->trans("SaturdayMin") ); + +$dec = ','; +$thousand = ' '; +if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") { + $dec = $langs->transnoentitiesnoconv("SeparatorDecimal"); +} +if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") { + $thousand = $langs->transnoentitiesnoconv("SeparatorThousand"); +} +if ($thousand == 'Space') { + $thousand = ' '; +} + ?> // Javascript libraries for Dolibarr ERP CRM (https://www.dolibarr.org) @@ -136,6 +149,7 @@ var tradMonthsShort = ; var tradDays = ; var tradDaysShort = ; var tradDaysMin = ; +var currencyCache = cache_currencies) ?>; // For JQuery date picker $(document).ready(function() { @@ -1064,22 +1078,95 @@ function getParameterByName(name, valueifnotfound) // Another solution, easier, to build a javascript rounding function function dolroundjs(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); } - /** * Function similar to PHP price() * + * Example use: + * pricejs(13312.448, 'MT+', 'EUR', 'fr_FR') + * // (depending on conf for 'MT'): '13 312.45 €' + * + * pricejs(343000.121, 'MT') + * // assuming on conf for 'MT' is 2 and for $langs->defaultlang is 'en_US': '343,000.12' + * * @param {number|string} amount The amount to show - * @param {string} mode 'MT' or 'MU' + * @param {string} mode 'MT' or 'MU'; an optional trailing '+' enables using the browser's internal + * number formatting features (Intl object) if available + * @param {string} currency_code ISO code of currency (empty by default) + * @param {string} force_locale ISO code locale to use (if empty, will use Dolibarr's current locale code) * @return {string} The amount with digits + * */ -function pricejs(amount, mode) { +function pricejs(amount, mode = 'MT+', currency_code = '', force_locale = '') { var main_max_dec_shown = global->MAIN_MAX_DECIMALS_SHOWN); ?>; var main_rounding_unit = global->MAIN_MAX_DECIMALS_UNIT; ?>; var main_rounding_tot = global->MAIN_MAX_DECIMALS_TOT; ?>; + var main_decimal_separator = ; + var main_thousand_separator = ; + var locale_code = force_locale || defaultlang) ?>; + var amountAsLocalizedString; + var useIntl = false; // true if mode ends with '+' and the browser provides Intl object + var nDigits; + if (currency_code === 'auto') currency_code = currency) ?>; - if (mode == 'MU') return amount.toFixed(main_rounding_unit); - if (mode == 'MT') return amount.toFixed(main_rounding_tot); - return 'Bad value for parameter mode'; + // min($conf->global->MAIN_MAX_DECIMALS_UNIT,$conf->global->MAIN_MAX_DECIMALS_TOT) + + if (mode.endsWith && mode.endsWith('+')) { + mode = mode.slice(0, mode.length - 1); + useIntl = Boolean(Intl && Intl.NumberFormat); + } + + if (mode === 'MU') nDigits = main_rounding_unit; + else if (mode === 'MT') nDigits = main_rounding_tot; + else return 'Bad value for parameter mode'; + + + if (useIntl) { + // let the browser format the number using Dolibarr-provided parameters + var formattingOptions = { + minimumFractionDigits: nDigits, + maximumFractionDigits: nDigits + }; + if (currency_code) { + formattingOptions['style'] = 'currency'; + formattingOptions['currency'] = currency_code; + } + return Intl.NumberFormat(locale_code.replace('_', '-'), formattingOptions).format(amount); + } + + // No Intl -> attempt to format the number in a way similar to Dolibarr PHP's `price()` function + amountAsLocalizedString = amount.toFixed(nDigits).replace( + /((?!^)(?:\d{3})*)(?:\.(\d+))?$/, + (fullMatch, digitsByThree, decimals) => + digitsByThree.replace( + /\d{3}/g, + (groupOfThree) => main_thousand_separator + groupOfThree + ) + (decimals !== undefined ? main_decimal_separator + decimals : '') + ).replace(/ /, ' '); + if (!currency_code) return amountAsLocalizedString; + + // print with currency + var currency_symbol = currency_code; + + // codes of languages / currencies where the symbol must be placed before the amount + var currencyBeforeAmountCodes = { + currency: ['AUD', 'CAD', 'CNY', 'COP', 'CLP', 'GBP', 'HKD', 'MXN', 'PEN', 'USD'], + language: ['nl_NL'] + }; + + if (currencyCache[currency_code] + && currencyCache[currency_code]['unicode'] + && currencyCache[currency_code]['unicode'].length) { + currency_symbol = currencyCache[currency_code]['unicode'].reduce(function (res, cur) {return res + cur}, ''); + } + + if (currencyBeforeAmountCodes.currency.indexOf(currency_code) >= 0 + || currencyBeforeAmountCodes.language.indexOf(locale_code)) { + // if we use a language or a currency where the symbol is placed before the amount + return currency_symbol + amountAsLocalizedString; + } + + // by default: currency symbol after the amount + return amountAsLocalizedString + ' ' + currency_symbol; } /** @@ -1092,20 +1179,8 @@ function pricejs(amount, mode) { function price2numjs(amount) { if (amount == '') return ''; - transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") { - $dec = $langs->transnoentitiesnoconv("SeparatorDecimal"); - } - if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") { - $thousand = $langs->transnoentitiesnoconv("SeparatorThousand"); - } - if ($thousand == 'Space') { - $thousand = ' '; - } - print "var dec='".dol_escape_js($dec)."'; var thousand='".dol_escape_js($thousand)."';\n"; // Set var in javascript - ?> + var dec = ; + var thousand = ; var main_max_dec_shown = global->MAIN_MAX_DECIMALS_SHOWN); ?>; var main_rounding_unit = global->MAIN_MAX_DECIMALS_UNIT; ?>;