mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 21:48:20 +02:00
Fixed incrementing/decrementing formatted numbers
The float formatter function now takes a number of fraction digits to return.
This commit is contained in:
@@ -424,15 +424,28 @@ export function coreLocalizer() {
|
||||
return code; // if not found, use the code
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a function that formats a floating-point number in the given
|
||||
* locale.
|
||||
*/
|
||||
localizer.floatFormatter = (locale) => {
|
||||
if (!('Intl' in window && 'NumberFormat' in Intl &&
|
||||
'formatToParts' in Intl.NumberFormat.prototype)) {
|
||||
return (number) => number.toString();
|
||||
return (number, fractionDigits) => {
|
||||
return fractionDigits === undefined ? number.toString() : number.toFixed(fractionDigits);
|
||||
};
|
||||
} else {
|
||||
return (number) => number.toLocaleString(locale, { maximumFractionDigits: 20 });
|
||||
return (number, fractionDigits) => number.toLocaleString(locale, {
|
||||
minimumFractionDigits: fractionDigits,
|
||||
maximumFractionDigits: fractionDigits === undefined ? 20 : fractionDigits,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a function that parses a number formatted according to the given
|
||||
* locale as a floating-point number.
|
||||
*/
|
||||
localizer.floatParser = (locale) => {
|
||||
// https://stackoverflow.com/a/55366435/4585461
|
||||
const polyfill = (string) => parseFloat(string.trim());
|
||||
@@ -460,5 +473,32 @@ export function coreLocalizer() {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a function that returns the number of decimal places in a
|
||||
* formatted number string.
|
||||
*/
|
||||
localizer.decimalPlaceCounter = (locale) => {
|
||||
var literal, group, decimal;
|
||||
if ('Intl' in window && 'NumberFormat' in Intl) {
|
||||
const format = new Intl.NumberFormat(locale, { maximumFractionDigits: 20 });
|
||||
if (('formatToParts' in format)) {
|
||||
const parts = format.formatToParts(-12345.6);
|
||||
const literalPart = parts.find(d => d.type === 'literal');
|
||||
literal = literalPart && new RegExp(`[${literalPart.value}]`, 'g');
|
||||
const groupPart = parts.find(d => d.type === 'group');
|
||||
group = groupPart && new RegExp(`[${groupPart.value}]`, 'g');
|
||||
const decimalPart = parts.find(d => d.type === 'decimal');
|
||||
decimal = decimalPart && new RegExp(`[${decimalPart.value}]`);
|
||||
}
|
||||
}
|
||||
return (string) => {
|
||||
string = string.trim();
|
||||
if (literal) string = string.replace(literal, '');
|
||||
if (group) string = string.replace(group, '');
|
||||
const parts = string.split(decimal || '.');
|
||||
return parts && parts[1] && parts[1].length || 0;
|
||||
};
|
||||
};
|
||||
|
||||
return localizer;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export function uiFieldText(field, context) {
|
||||
const isDirectionField = field.key.split(':').some(keyPart => keyPart === 'direction');
|
||||
const formatFloat = localizer.floatFormatter(localizer.languageCode());
|
||||
const parseLocaleFloat = localizer.floatParser(localizer.languageCode());
|
||||
const countDecimalPlaces = localizer.decimalPlaceCounter(localizer.languageCode());
|
||||
|
||||
if (field.type === 'tel') {
|
||||
fileFetcher.get('phone_formats')
|
||||
@@ -155,8 +156,7 @@ export function uiFieldText(field, context) {
|
||||
num = ((num % 360) + 360) % 360;
|
||||
}
|
||||
// make sure no extra decimals are introduced
|
||||
const numDecimals = v.includes('.') ? v.split('.')[1].length : 0;
|
||||
return formatFloat(clamped(num).toFixed(numDecimals));
|
||||
return formatFloat(clamped(num), countDecimalPlaces(v));
|
||||
});
|
||||
input.node().value = vals.join(';');
|
||||
change()();
|
||||
|
||||
@@ -6,6 +6,15 @@ describe('iD.coreLocalizer', function() {
|
||||
expect(selection.selectChild().classed('localized-text')).to.be.true;
|
||||
});
|
||||
});
|
||||
describe('#floatFormatter', function () {
|
||||
it('uses the specified number of fraction digits', function () {
|
||||
var localizer = iD.coreLocalizer();
|
||||
var formatFloat = localizer.floatFormatter('en');
|
||||
expect(formatFloat(-0.1)).to.eql('-0.1');
|
||||
expect(formatFloat(-0.1, 0)).to.eql('-0');
|
||||
expect(formatFloat(-0.1, 2)).to.eql('-0.10');
|
||||
});
|
||||
});
|
||||
describe('#floatParser', function () {
|
||||
it('roundtrips English numbers', function () {
|
||||
var localizer = iD.coreLocalizer();
|
||||
@@ -58,4 +67,14 @@ describe('iD.coreLocalizer', function() {
|
||||
expect(parseFloat(formatFloat(3.14159))).to.eql(3.14159);
|
||||
});
|
||||
});
|
||||
describe('#decimalPlaceCounter', function () {
|
||||
it('counts decimal places in English numbers', function () {
|
||||
var localizer = iD.coreLocalizer();
|
||||
var countDecimalPlaces = localizer.decimalPlaceCounter('en');
|
||||
expect(countDecimalPlaces('-0')).to.eql(0);
|
||||
expect(countDecimalPlaces('-0.1')).to.eql(1);
|
||||
expect(countDecimalPlaces('1.234')).to.eql(3);
|
||||
expect(countDecimalPlaces('10')).to.eql(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user