Make sure all combo event listeners can handle accept/cancel w/o datum

(re: #5637, re: #5618)

This can happen if the user enters a value that is not matched to
one of the combo suggestions.

Also make sure to set `this` to the input field.  It might not be
already if the event was triggered from a keypress instead of a click.
This commit is contained in:
Bryan Housel
2019-01-22 23:12:40 -05:00
parent 0c7b9a631e
commit 4583e2d4d7
4 changed files with 56 additions and 28 deletions

View File

@@ -400,6 +400,7 @@ export function uiCombobox(context, klass) {
// Then hides the combobox.
function accept(d) {
_cancelFetch = true;
var thiz = input.node();
if (d) { // user clicked on a suggestion
utilGetSetValue(input, d.value); // replace field contents
@@ -408,10 +409,10 @@ export function uiCombobox(context, klass) {
// clear (and keep) selection
var val = utilGetSetValue(input);
input.node().setSelectionRange(val.length, val.length);
thiz.setSelectionRange(val.length, val.length);
d = datum(val);
dispatch.call('accept', this, d, val);
dispatch.call('accept', thiz, d, val);
hide();
}
@@ -420,6 +421,7 @@ export function uiCombobox(context, klass) {
// Then hides the combobox.
function cancel() {
_cancelFetch = true;
var thiz = input.node();
// clear (and remove) selection, and replace field contents
var val = utilGetSetValue(input);
@@ -427,9 +429,9 @@ export function uiCombobox(context, klass) {
var end = input.property('selectionEnd');
val = val.slice(0, start) + val.slice(end);
utilGetSetValue(input, val);
input.node().setSelectionRange(val.length, val.length);
thiz.setSelectionRange(val.length, val.length);
dispatch.call('cancel', this);
dispatch.call('cancel', thiz);
hide();
}

View File

@@ -147,25 +147,8 @@ export function uiFieldLocalized(field, context) {
input
.call(brandCombo
.fetcher(fetchBrandNames(preset, allSuggestions))
.on('accept', function(d) {
var entity = context.entity(_entity.id); // get latest
var tags = entity.tags;
var geometry = entity.geometry(context.graph());
var removed = preset.unsetTags(tags, geometry);
for (var k in tags) {
tags[k] = removed[k]; // set removed tags to `undefined`
}
tags = d.suggestion.setTags(tags, geometry);
utilGetSetValue(input, tags.name);
dispatch.call('change', this, tags);
})
.on('cancel', function() {
// user hit escape, remove whatever is after the '-'
var name = utilGetSetValue(input);
name = name.split('-', 2)[0].trim();
utilGetSetValue(input, name);
dispatch.call('change', this, { name: name });
})
.on('accept', acceptBrand)
.on('cancel', cancelBrand)
);
}
}
@@ -216,6 +199,34 @@ export function uiFieldLocalized(field, context) {
function acceptBrand(d) {
if (!d) {
cancelBrand();
return;
}
var entity = context.entity(_entity.id); // get latest
var tags = entity.tags;
var geometry = entity.geometry(context.graph());
var removed = preset.unsetTags(tags, geometry);
for (var k in tags) {
tags[k] = removed[k]; // set removed tags to `undefined`
}
tags = d.suggestion.setTags(tags, geometry);
utilGetSetValue(input, tags.name);
dispatch.call('change', this, tags);
}
function cancelBrand() {
// user hit escape, remove whatever is after the ' - '
var name = utilGetSetValue(input);
name = name.split(' - ', 2)[0].trim();
utilGetSetValue(input, name);
dispatch.call('change', this, { name: name });
}
function fetchBrandNames(preset, suggestions) {
var pTag = preset.id.split('/', 2);
var pKey = pTag[0];

View File

@@ -97,6 +97,7 @@ export function uiFormFields(context) {
.call(moreCombo
.data(notShown)
.on('accept', function (d) {
if (!d) return; // user entered something that was not matched
var field = d.field;
field.show();
selection.call(formFields); // rerender

View File

@@ -299,11 +299,8 @@ export function uiRawMembershipEditor(context) {
newMembership.selectAll('.member-entity-input')
.call(nearbyCombo
.on('accept', function (d) {
var role = list.selectAll('.member-row-new .member-role').property('value');
addMembership(d, role);
})
.on('cancel', function() { delete this.value; })
.on('accept', acceptEntity)
.on('cancel', cancelEntity)
);
@@ -341,6 +338,23 @@ export function uiRawMembershipEditor(context) {
});
function acceptEntity(d) {
if (!d) {
cancelEntity();
return;
}
var role = list.selectAll('.member-row-new .member-role').property('value');
addMembership(d, role);
}
function cancelEntity() {
var input = newMembership.selectAll('.member-entity-input');
input.property('value', '');
}
function bindTypeahead(d) {
var row = d3_select(this);
var role = row.selectAll('input.member-role');