diff --git a/modules/ui/sections/raw_tag_editor.js b/modules/ui/sections/raw_tag_editor.js index 7b1eebcee6..ac322fc2c3 100644 --- a/modules/ui/sections/raw_tag_editor.js +++ b/modules/ui/sections/raw_tag_editor.js @@ -486,6 +486,11 @@ export function uiSectionRawTagEditor(id, context) { var kNew = context.cleanTagKey(this.value.trim()); + if (!kNew) { + this.value = kOld; + return; + } + // allow no change if the key should be readonly if (isReadOnly({ key: kNew })) { this.value = kOld; @@ -542,6 +547,7 @@ export function uiSectionRawTagEditor(id, context) { function valueChange(d3_event, d) { if (isReadOnly(d)) return; + if (!d.key) return; // exit if this is a multiselection and no value was entered if (Array.isArray(d.value) && !this.value) return; diff --git a/test/spec/ui/sections/raw_tag_editor.js b/test/spec/ui/sections/raw_tag_editor.js index 0e33e9be3e..548ee41328 100644 --- a/test/spec/ui/sections/raw_tag_editor.js +++ b/test/spec/ui/sections/raw_tag_editor.js @@ -53,4 +53,17 @@ describe('iD.uiSectionRawTagEditor', function() { iD.utilTriggerEvent(element.selectAll('button.remove'), 'mousedown', { button: 0 }); expect(await tags).to.eql({highway: undefined}); }); + + it('does not dispatch change when key is emptied', async () => { + let changeFired = false; + taglist.on('change', () => { changeFired = true; }); + + var keyInput = element.select('.tag-list').select('input.key'); + iD.utilGetSetValue(keyInput, ''); + iD.utilTriggerEvent(keyInput, 'change'); + + // give it a moment to ensure nothing fires + await new Promise(resolve => { window.setTimeout(resolve, 100); }); + expect(changeFired).to.be.false; + }); });