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
+3
View File
@@ -43,11 +43,14 @@ _Breaking developer changes, which may affect downstream projects or sites that
* Fix bug which made it impossible to change an object's preset from a sub-preset to the respective parents preset (e.g. from Driveway to Service Road) ([#9372]) * Fix bug which made it impossible to change an object's preset from a sub-preset to the respective parents preset (e.g. from Driveway to Service Road) ([#9372])
#### :hourglass: Performance #### :hourglass: Performance
#### :rocket: Presets #### :rocket: Presets
* Clamp degree values in `direction` fields between 0 and 359 degrees ([#9386])
* Disable increment/decrement buttons on number fields if the input value is not numeric or when there is a multi-selection with conflicting values
#### :hammer: Development #### :hammer: Development
* Upgrade to Transifex API v3 ([#9375]) * Upgrade to Transifex API v3 ([#9375])
[#9372]: https://github.com/openstreetmap/iD/issues/9372 [#9372]: https://github.com/openstreetmap/iD/issues/9372
[#9375]: https://github.com/openstreetmap/iD/pull/9375 [#9375]: https://github.com/openstreetmap/iD/pull/9375
[#9386]: https://github.com/openstreetmap/iD/issues/9386
# 2.23.2 # 2.23.2
+4 -2
View File
@@ -99,10 +99,11 @@ export function actionReverse(entityID, options) {
return onewayReplacements[value] || value; return onewayReplacements[value] || value;
} else if (includeAbsolute && directionKey.test(key)) { } else if (includeAbsolute && directionKey.test(key)) {
return value.split(';').map(value => {
if (compassReplacements[value]) return compassReplacements[value]; if (compassReplacements[value]) return compassReplacements[value];
var degrees = parseFloat(value); var degrees = Number(value);
if (typeof degrees === 'number' && !isNaN(degrees)) { if (isFinite(degrees)) {
if (degrees < 180) { if (degrees < 180) {
degrees += 180; degrees += 180;
} else { } else {
@@ -110,6 +111,7 @@ export function actionReverse(entityID, options) {
} }
return degrees.toString(); return degrees.toString();
} }
}).join(';');
} }
return valueReplacements[value] || value; return valueReplacements[value] || value;
+39 -6
View File
@@ -28,6 +28,7 @@ export function uiFieldText(field, context) {
var _entityIDs = []; var _entityIDs = [];
var _tags; var _tags;
var _phoneFormats = {}; var _phoneFormats = {};
const isDirectionField = field.key.split(':').some(keyPart => keyPart === 'direction');
if (field.type === 'tel') { if (field.type === 'tel') {
fileFetcher.get('phone_formats') fileFetcher.get('phone_formats')
@@ -119,16 +120,36 @@ export function uiFieldText(field, context) {
.merge(buttons) .merge(buttons)
.on('click', function(d3_event, d) { .on('click', function(d3_event, d) {
d3_event.preventDefault(); 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 raw_vals = input.node().value || '0';
var vals = raw_vals.split(';'); var vals = raw_vals.split(';');
vals = vals.map(function(v) { vals = vals.map(function(v) {
var num = parseFloat(v.trim(), 10); var num = Number(v);
if (isFinite(num)) return clamped(num + d); if (isDirectionField) {
const compassDir = cardinal[v.trim().toLowerCase()]; const compassDir = cardinal[v.trim().toLowerCase()];
if (compassDir !== undefined) return clamped(compassDir + d); if (compassDir !== undefined) {
num = compassDir;
}
}
return v.trim(); // do nothing if the value is neither a number, nor a cardinal direction if (!isFinite(num)) {
// do nothing if the value is neither a number, nor a cardinal direction
return v.trim();
}
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(';'); input.node().value = vals.join(';');
change()(); change()();
@@ -294,7 +315,7 @@ export function uiFieldText(field, context) {
if (field.type === 'number' && val) { if (field.type === 'number' && val) {
var vals = val.split(';'); var vals = val.split(';');
vals = vals.map(function(v) { vals = vals.map(function(v) {
var num = parseFloat(v.trim(), 10); var num = Number(v);
return isFinite(num) ? clamped(num) : v.trim(); return isFinite(num) ? clamped(num) : v.trim();
}); });
val = vals.join(';'); val = vals.join(';');
@@ -324,6 +345,18 @@ export function uiFieldText(field, context) {
.attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown'))) .attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown')))
.classed('mixed', isMixed); .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.type === 'tel') updatePhonePlaceholder();
if (field.key.split(':').includes('colour')) updateColourPreview(); if (field.key.split(':').includes('colour')) updateColourPreview();