number field: improve +/- buttons

* Clamp degree values in `direction` fields between 0 and 359 degrees, fixes #9386
* Only match cardinal values to numbers in `direction` fields
* Disable increment/decrement buttons on number fields if the input value is not numeric or when there is a multi-selection with conflicting values
* Fix/implement reverse operation for semicolon delimited `direction` values
This commit is contained in:
Martin Raifer
2022-11-24 14:44:28 +01:00
parent ff80501425
commit f573c374c2
3 changed files with 54 additions and 16 deletions
+40 -7
View File
@@ -28,6 +28,7 @@ export function uiFieldText(field, context) {
var _entityIDs = [];
var _tags;
var _phoneFormats = {};
const isDirectionField = field.key.split(':').some(keyPart => keyPart === 'direction');
if (field.type === 'tel') {
fileFetcher.get('phone_formats')
@@ -112,23 +113,43 @@ export function uiFieldText(field, context) {
var which = (d > 0 ? 'increment' : 'decrement');
return 'form-field-button ' + which;
})
.attr('title', function(d){
.attr('title', function(d) {
var which = (d > 0 ? 'increment' : 'decrement');
return t(`inspector.${which}`);
})
.merge(buttons)
.on('click', function(d3_event, d) {
d3_event.preventDefault();
// do nothing if this is a multi-selection with mixed values
var isMixed = Array.isArray(_tags[field.key]);
if (isMixed) return;
var raw_vals = input.node().value || '0';
var vals = raw_vals.split(';');
vals = vals.map(function(v) {
var num = parseFloat(v.trim(), 10);
if (isFinite(num)) return clamped(num + d);
var num = Number(v);
if (isDirectionField) {
const compassDir = cardinal[v.trim().toLowerCase()];
if (compassDir !== undefined) {
num = compassDir;
}
}
const compassDir = cardinal[v.trim().toLowerCase()];
if (compassDir !== undefined) return clamped(compassDir + d);
if (!isFinite(num)) {
// do nothing if the value is neither a number, nor a cardinal direction
return v.trim();
}
return v.trim(); // do nothing if the value is neither a number, nor a cardinal direction
num += d;
// clamp to 0..359 degree range if it's a direction field
// https://github.com/openstreetmap/iD/issues/9386
if (isDirectionField) {
num = ((num % 360) + 360) % 360;
}
// make sure no extra decimals are introduced
const numDecimals = v.includes('.') ? v.split('.')[1].length : 0;
return clamped(num).toFixed(numDecimals);
});
input.node().value = vals.join(';');
change()();
@@ -294,7 +315,7 @@ export function uiFieldText(field, context) {
if (field.type === 'number' && val) {
var vals = val.split(';');
vals = vals.map(function(v) {
var num = parseFloat(v.trim(), 10);
var num = Number(v);
return isFinite(num) ? clamped(num) : v.trim();
});
val = vals.join(';');
@@ -324,6 +345,18 @@ export function uiFieldText(field, context) {
.attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown')))
.classed('mixed', isMixed);
if (field.type === 'number') {
const buttons = wrap.selectAll('.increment, .decrement');
if (isMixed) {
buttons.attr('disabled', 'disabled').classed('disabled', true);
} else {
var raw_vals = tags[field.key] || '0';
const canIncDec = raw_vals.split(';').some(val => isFinite(Number(val))
|| isDirectionField && cardinal[val.trim().toLowerCase()]);
buttons.attr('disabled', canIncDec ? null : 'disabled').classed('disabled', !canIncDec);
}
}
if (field.type === 'tel') updatePhonePlaceholder();
if (field.key.split(':').includes('colour')) updateColourPreview();