100 lines
2.7 KiB
JavaScript
100 lines
2.7 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Formats a number as plain digits with dot as decimal separator.
|
|
* @param {Decimal|string|number} num
|
|
* @param {number} minPrecision - Minimum decimal places
|
|
* @param {number} maxPrecision - Maximum decimal places
|
|
* @returns {string} Formatted number string
|
|
*/
|
|
function prettyNumber(num, minPrecision, maxPrecision) {
|
|
minPrecision = minPrecision || 4;
|
|
maxPrecision = maxPrecision || 10;
|
|
const val = num instanceof Decimal ? num.toNumber() : Number(num);
|
|
if (!Number.isFinite(val)) {
|
|
return '';
|
|
}
|
|
let d;
|
|
try {
|
|
d = new Decimal(num);
|
|
} catch (e) {
|
|
return '';
|
|
}
|
|
const absVal = d.abs();
|
|
// Larger numbers need fewer decimal places for readable output;
|
|
// smaller numbers get more to stay meaningful.
|
|
let precision = maxPrecision;
|
|
if (absVal.gte(10000)) {
|
|
precision = 2;
|
|
} else if (absVal.gte(1000)) {
|
|
precision = 4;
|
|
} else if (absVal.gte(1)) {
|
|
precision = 6;
|
|
} else if (absVal.gte(0.001)) {
|
|
precision = 8;
|
|
}
|
|
precision = Math.max(minPrecision,
|
|
Math.min(precision, maxPrecision));
|
|
let str = d.toFixed(precision);
|
|
if (str.indexOf('.') !== -1) {
|
|
str = str.replace(/0+$/, '');
|
|
str = str.replace(/\.$/, '');
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* Parses a number string for conversion.
|
|
* Accepts both German (1.234,56) and US (1,234.56) notation.
|
|
* The last dot or comma is always the decimal separator;
|
|
* all preceding ones are treated as thousand separators and removed.
|
|
* Invalid or empty input returns Decimal(0).
|
|
* @param {string} input - User input from field
|
|
* @returns {Decimal} Parsed Decimal value
|
|
*/
|
|
function parseNumber(input) {
|
|
if (!input || input.trim() === '') {
|
|
return new Decimal(0);
|
|
}
|
|
const trimmed = input.trim();
|
|
const lastDot = trimmed.lastIndexOf('.');
|
|
const lastComma = trimmed.lastIndexOf(',');
|
|
const lastSep = Math.max(lastDot, lastComma);
|
|
let normalized;
|
|
if (lastSep === -1) {
|
|
normalized = trimmed;
|
|
} else {
|
|
const beforeSep = trimmed.slice(0, lastSep).replace(/[.,]/g, '');
|
|
const afterSep = trimmed.slice(lastSep + 1);
|
|
normalized = beforeSep + '.' + afterSep;
|
|
}
|
|
try {
|
|
return new Decimal(normalized);
|
|
} catch (e) {
|
|
return new Decimal(0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the URL with the current input value.
|
|
* @param {string} value - The input value
|
|
*/
|
|
function updateUrl(value) {
|
|
const normalized = value ? value.replace(/,/g, '.') : '';
|
|
if (normalized && normalized !== '0') {
|
|
history.replaceState(null, '', '?v=' + normalized);
|
|
} else {
|
|
history.replaceState(null, '', '?v=1');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Navigates to a new URL with the current input value as parameter.
|
|
* @param {string} url - Target URL
|
|
* @param {string} value - Current input value
|
|
*/
|
|
function navigate(url, value) {
|
|
const normalized = value ? value.replace(/,/g, '.') : '1';
|
|
window.location.href = url + '?v=' + normalized;
|
|
}
|