From 687b7aa0790518551abb7c6e32181f0f6c6a5894 Mon Sep 17 00:00:00 2001 From: Shivang Jaiswal Date: Tue, 3 Feb 2026 13:33:39 +0530 Subject: [PATCH 1/5] added the warning stating only 255 characters are allowed --- CHANGELOG.md | 2 ++ css/80_app.css | 52 ++++++++++++++++++++++++++- data/core.yaml | 1 + modules/ui/sections/raw_tag_editor.js | 22 ++++++++++-- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b75d7af7c1..feea55ff190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ _Breaking developer changes, which may affect downstream projects or sites that * Don't error on features with a sole `note` tag ([#11522]) * Warn when two features cross each other on same `layer`, regardless of `bridge` / `tunnel` tags ([#10999], thanks [@homersimpsons]) #### :bug: Bugfixes +* Show warning in raw tag editor when tag values exceed 255 characters ([#10241], thanks [@JaiswalShivang]) * Fix some gpx/geojson properties not visible, such as numbers or complex data structures ([#11636], thanks [@k-yle]) #### :earth_asia: Localization * Add Moroccan phone number formats ([#11651], thanks [@ilias52730]) @@ -80,6 +81,7 @@ _Breaking developer changes, which may affect downstream projects or sites that [@homersimpsons]: https://github.com/homersimpsons [@omsaraykar]: https://github.com/omsaraykar [@Kaushik4141]: https://github.com/Kaushik4141 +[@JaiswalShivang]: https://github.com/JaiswalShivang # v2.37.3 diff --git a/css/80_app.css b/css/80_app.css index 13f256df46f..06505aa207d 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -2736,6 +2736,56 @@ button.raw-tag-option svg.icon { .tag-row input.value { border-right: 1px solid var(--border-color); } + +.tag-row input.value.warning { + background-color: rgba(221, 85, 51, 0.08) !important; + border: 1px solid transparent !important; + border-bottom: 2px solid #d53 !important; + box-shadow: none !important; +} + +.warning-character-overflow { + position: absolute; + top: 100%; + right: 64px; + margin-top: 8px; + background-color: #d53; + color: #fff; + padding: 6px 12px; + border-radius: 4px; + font-size: 11px; + font-weight: 500; + z-index: 1000; + pointer-events: none; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + white-space: nowrap; + margin-top: 8px; + opacity: 0; + transform: translateY(-4px); + transition: opacity 0.2s ease, transform 0.2s ease; +} + +.warning-character-overflow::before { + content: ''; + position: absolute; + top: -6px; + right: 50%; + transform: translateX(50%); + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #d53; +} + +.warning-character-overflow:not(:empty) { + opacity: 1; + transform: translateY(0); +} + +.ideditor[dir='rtl'] .warning-character-overflow { + right: auto; + left: 40px; +} + .ideditor[dir='rtl'] .tag-row input.value { border-left: 1px solid var(--border-color); } @@ -6077,4 +6127,4 @@ textarea:focus:dir(rtl)::-webkit-resizer { height: 100px; width: 100px; color: var(--link-color); -} +} \ No newline at end of file diff --git a/data/core.yaml b/data/core.yaml index dcbbc2e45c4..a3b84ffd161 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -734,6 +734,7 @@ en: wiki_reference: View documentation wiki_en_reference: View documentation in English key_value: "key=value" + max_char_warning: "only {count} characters are allowed" empty: (empty) multiple_values: Multiple Values multiple_types: Multiple Types diff --git a/modules/ui/sections/raw_tag_editor.js b/modules/ui/sections/raw_tag_editor.js index 21fe7a66626..796ee8c8c41 100644 --- a/modules/ui/sections/raw_tag_editor.js +++ b/modules/ui/sections/raw_tag_editor.js @@ -10,7 +10,7 @@ import { uiTagReference } from '../tag_reference'; import { prefs } from '../../core/preferences'; import { t } from '../../core/localizer'; import { utilArrayDifference, utilArrayIdentical } from '../../util/array'; -import { utilGetSetValue, utilNoAuto, utilRebind, utilTagDiff } from '../../util'; +import { utilGetSetValue, utilNoAuto, utilRebind, utilTagDiff, utilUnicodeCharsCount } from '../../util'; import { allowUpperCaseTagValues } from '../../osm/tags'; import { fileFetcher } from '../../core'; @@ -196,7 +196,20 @@ export function uiSectionRawTagEditor(id, context) { .call(utilNoAuto) .on('focus', interacted) .on('blur', valueChange) - .on('change', valueChange); + .on('change', valueChange) + .on('input', function() { + // Update warning class in real-time as user types + const maxChars = context.maxCharsForTagValue(); + const value = this.value; + const exceedsLimit = value && utilUnicodeCharsCount(value) > maxChars; + d3_select(this).classed('warning', exceedsLimit); + d3_select(this.parentNode.parentNode).select('.warning-character-overflow') + .text(exceedsLimit ? t('inspector.max_char_warning', { count: maxChars }) : ''); + }); + + innerWrap + .append('span') + .attr('class', 'warning-character-overflow'); innerWrap .append('button') @@ -257,6 +270,7 @@ export function uiSectionRawTagEditor(id, context) { (_, newKey) => _pendingChange === null || isEmpty(_pendingChange) || _pendingChange[newKey] // if there are pending changes: skip untouched tags ); + const maxChars = context.maxCharsForTagValue(); items.selectAll('input.value') .attr('title', function(d) { return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : d.value; @@ -264,6 +278,10 @@ export function uiSectionRawTagEditor(id, context) { .classed('mixed', function(d) { return Array.isArray(d.value); }) + .classed('warning', function(d) { + if (Array.isArray(d.value)) return false; + return d.value && utilUnicodeCharsCount(d.value) > maxChars; + }) .attr('placeholder', function(d) { return Array.isArray(d.value) ? t('inspector.multiple_values') : null; }) From b2452bdd4922f39e6949f754afebfe0c5661b4ee Mon Sep 17 00:00:00 2001 From: Shivang Jaiswal Date: Tue, 3 Feb 2026 14:54:09 +0530 Subject: [PATCH 2/5] used uiLengthIndicator for the overflow of 255 characters warning --- css/80_app.css | 50 --------------------------- data/core.yaml | 1 - modules/ui/sections/raw_tag_editor.js | 31 +++++++++++------ 3 files changed, 20 insertions(+), 62 deletions(-) diff --git a/css/80_app.css b/css/80_app.css index 06505aa207d..31d5f4d1048 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -2736,56 +2736,6 @@ button.raw-tag-option svg.icon { .tag-row input.value { border-right: 1px solid var(--border-color); } - -.tag-row input.value.warning { - background-color: rgba(221, 85, 51, 0.08) !important; - border: 1px solid transparent !important; - border-bottom: 2px solid #d53 !important; - box-shadow: none !important; -} - -.warning-character-overflow { - position: absolute; - top: 100%; - right: 64px; - margin-top: 8px; - background-color: #d53; - color: #fff; - padding: 6px 12px; - border-radius: 4px; - font-size: 11px; - font-weight: 500; - z-index: 1000; - pointer-events: none; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - white-space: nowrap; - margin-top: 8px; - opacity: 0; - transform: translateY(-4px); - transition: opacity 0.2s ease, transform 0.2s ease; -} - -.warning-character-overflow::before { - content: ''; - position: absolute; - top: -6px; - right: 50%; - transform: translateX(50%); - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #d53; -} - -.warning-character-overflow:not(:empty) { - opacity: 1; - transform: translateY(0); -} - -.ideditor[dir='rtl'] .warning-character-overflow { - right: auto; - left: 40px; -} - .ideditor[dir='rtl'] .tag-row input.value { border-left: 1px solid var(--border-color); } diff --git a/data/core.yaml b/data/core.yaml index a3b84ffd161..dcbbc2e45c4 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -734,7 +734,6 @@ en: wiki_reference: View documentation wiki_en_reference: View documentation in English key_value: "key=value" - max_char_warning: "only {count} characters are allowed" empty: (empty) multiple_values: Multiple Values multiple_types: Multiple Types diff --git a/modules/ui/sections/raw_tag_editor.js b/modules/ui/sections/raw_tag_editor.js index 796ee8c8c41..b83fefd08de 100644 --- a/modules/ui/sections/raw_tag_editor.js +++ b/modules/ui/sections/raw_tag_editor.js @@ -13,6 +13,7 @@ import { utilArrayDifference, utilArrayIdentical } from '../../util/array'; import { utilGetSetValue, utilNoAuto, utilRebind, utilTagDiff, utilUnicodeCharsCount } from '../../util'; import { allowUpperCaseTagValues } from '../../osm/tags'; import { fileFetcher } from '../../core'; +import { uiLengthIndicator } from '../length_indicator'; export function uiSectionRawTagEditor(id, context) { @@ -48,7 +49,6 @@ export function uiSectionRawTagEditor(id, context) { var _tags; var _entityIDs; var _didInteract = false; - function interacted() { _didInteract = true; } @@ -198,18 +198,18 @@ export function uiSectionRawTagEditor(id, context) { .on('blur', valueChange) .on('change', valueChange) .on('input', function() { - // Update warning class in real-time as user types - const maxChars = context.maxCharsForTagValue(); - const value = this.value; - const exceedsLimit = value && utilUnicodeCharsCount(value) > maxChars; - d3_select(this).classed('warning', exceedsLimit); - d3_select(this.parentNode.parentNode).select('.warning-character-overflow') - .text(exceedsLimit ? t('inspector.max_char_warning', { count: maxChars }) : ''); + var lengthIndicator = d3_select(this.parentNode).datum().__lengthIndicator; + if (lengthIndicator) { + lengthIndicator.update(this.value); + } }); - innerWrap - .append('span') - .attr('class', 'warning-character-overflow'); + innerWrap.select('.value-wrap') + .each(function() { + var lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue()); + d3_select(this).datum().__lengthIndicator = lengthIndicator; + d3_select(this).call(lengthIndicator); + }); innerWrap .append('button') @@ -294,6 +294,15 @@ export function uiSectionRawTagEditor(id, context) { return null; } return Array.isArray(d.value) ? '' : d.value; + }) + .each(function(d) { + if (!Array.isArray(d.value)) { + var valueWrap = d3_select(this.parentNode); + var lengthIndicator = valueWrap.datum().__lengthIndicator; + if (lengthIndicator) { + lengthIndicator.update(d.value || ''); + } + } }); items.selectAll('button.remove') From 33147c6de5902673080ba188f0c366e55f715d86 Mon Sep 17 00:00:00 2001 From: Shivang Jaiswal Date: Fri, 27 Feb 2026 23:12:18 +0530 Subject: [PATCH 3/5] Update 80_app.css --- css/80_app.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css/80_app.css b/css/80_app.css index f59b455b0f6..3a13c17acdd 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -6085,4 +6085,4 @@ textarea:focus:dir(rtl)::-webkit-resizer { height: 100px; width: 100px; color: var(--link-color); -} \ No newline at end of file +} From 337ee1b57107895b7b68ffaa2719b0c6160bc1b0 Mon Sep 17 00:00:00 2001 From: Shivang Jaiswal Date: Fri, 27 Feb 2026 23:14:30 +0530 Subject: [PATCH 4/5] Add interacted function to track user interaction --- modules/ui/sections/raw_tag_editor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ui/sections/raw_tag_editor.js b/modules/ui/sections/raw_tag_editor.js index b83fefd08de..762b04eadeb 100644 --- a/modules/ui/sections/raw_tag_editor.js +++ b/modules/ui/sections/raw_tag_editor.js @@ -49,6 +49,7 @@ export function uiSectionRawTagEditor(id, context) { var _tags; var _entityIDs; var _didInteract = false; + function interacted() { _didInteract = true; } From fa9b7e6f992322cec7332cb78437f8e3793c28cc Mon Sep 17 00:00:00 2001 From: Shivang Jaiswal Date: Fri, 27 Feb 2026 23:16:16 +0530 Subject: [PATCH 5/5] Remove unnecessary blank line in raw_tag_editor.js --- modules/ui/sections/raw_tag_editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui/sections/raw_tag_editor.js b/modules/ui/sections/raw_tag_editor.js index 762b04eadeb..6093ade1435 100644 --- a/modules/ui/sections/raw_tag_editor.js +++ b/modules/ui/sections/raw_tag_editor.js @@ -49,7 +49,7 @@ export function uiSectionRawTagEditor(id, context) { var _tags; var _entityIDs; var _didInteract = false; - + function interacted() { _didInteract = true; }