Avoid creating comboboxes

(closes #5568)

Several strategies in here:
- Move uiCombobox() from inside the render function to class variable
- Don't render stuff like the raw tag editor when it's collapsed
- Don't show as many fields/combos on hover
- Don't instantiate fields (like universal/more) until they're actually shown
- Bind the combo on enter selection not on update selection
This commit is contained in:
Bryan Housel
2018-12-11 16:07:00 -05:00
parent 222b3f1b04
commit 39b3f1df68
16 changed files with 135 additions and 115 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ export function uiFieldAccess(field, context) {
.call(utilNoAuto)
.each(function(d) {
d3_select(this)
.call(uiCombobox(context)
.call(uiCombobox(context, 'access-' + d)
.data(access.options(d))
);
});
+23 -23
View File
@@ -112,13 +112,19 @@ export function uiFieldAddress(field, context) {
}
function initCallback(err, countryCode) {
function countryCallback(err, countryCode) {
if (err) return;
var addressFormat = _find(dataAddressFormats, function (a) {
return a && a.countryCodes && _includes(a.countryCodes, countryCode.toLowerCase());
}) || dataAddressFormats[0];
var dropdowns = addressFormat.dropdowns || [
'city', 'county', 'country', 'district', 'hamlet',
'neighbourhood', 'place', 'postcode', 'province',
'quarter', 'state', 'street', 'subdistrict', 'suburb'
];
var widths = addressFormat.widths || {
housenumber: 1/3, street: 2/3,
city: 2/3, state: 1/4, postcode: 1/3
@@ -126,14 +132,14 @@ export function uiFieldAddress(field, context) {
function row(r) {
// Normalize widths.
var total = _reduce(r, function(sum, field) {
return sum + (widths[field] || 0.5);
var total = _reduce(r, function(sum, key) {
return sum + (widths[key] || 0.5);
}, 0);
return r.map(function (field) {
return r.map(function(key) {
return {
id: field,
width: (widths[field] || 0.5) / total
id: key,
width: (widths[key] || 0.5) / total
};
});
}
@@ -155,31 +161,25 @@ export function uiFieldAddress(field, context) {
})
.attr('class', function (d) { return 'addr-' + d.id; })
.call(utilNoAuto)
.each(addDropdown)
.style('width', function (d) { return d.width * 100 + '%'; });
// Update
// setup dropdowns for common address tags
var dropdowns = addressFormat.dropdowns || [
'city', 'county', 'country', 'district', 'hamlet',
'neighbourhood', 'place', 'postcode', 'province',
'quarter', 'state', 'street', 'subdistrict', 'suburb'
];
function addDropdown(d) {
if (dropdowns.indexOf(d.id) === -1) return; // not a dropdown
// If fields exist for any of these tags, create dropdowns to pick nearby values..
dropdowns.forEach(function(tag) {
var nearValues = (tag === 'street') ? getNearStreets
: (tag === 'city') ? getNearCities
: getNearValues;
var nearValues = (d.id === 'street') ? getNearStreets
: (d.id === 'city') ? getNearCities
: getNearValues;
wrap.selectAll('input.addr-' + tag)
.call(uiCombobox(context)
d3_select(this)
.call(uiCombobox(context, 'address-' + d.id)
.minItems(1)
.fetcher(function(value, callback) {
callback(nearValues('addr:' + tag));
callback(nearValues('addr:' + d.id));
})
);
});
}
wrap.selectAll('input')
.on('blur', change())
@@ -206,7 +206,7 @@ export function uiFieldAddress(field, context) {
if (nominatim && _entity) {
var center = _entity.extent(context.graph()).center();
nominatim.countryCode(center, initCallback);
nominatim.countryCode(center, countryCallback);
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ export function uiFieldCombo(field, context) {
var optarray = field.options;
var snake_case = (field.snake_case || (field.snake_case === undefined));
var caseSensitive = field.caseSensitive;
var combobox = uiCombobox(context)
var combobox = uiCombobox(context, 'combo-' + field.safeid)
.caseSensitive(caseSensitive)
.minItems(isMulti || isSemi ? 1 : 2);
var container = d3_select(null);
+1 -1
View File
@@ -57,7 +57,7 @@ export function uiFieldCycleway(field, context) {
.call(utilNoAuto)
.each(function(d) {
d3_select(this)
.call(uiCombobox(context)
.call(uiCombobox(context, 'cycleway-' + stripcolon(d))
.data(cycleway.options(d))
);
});
+4 -4
View File
@@ -29,11 +29,11 @@ export function uiFieldLocalized(field, context) {
});
// reuse these combos
var langcombo = uiCombobox(context)
var langCombo = uiCombobox(context, 'localized-lang')
.fetcher(fetchLanguages)
.minItems(0);
var brandcombo = uiCombobox(context)
var brandCombo = uiCombobox(context, 'localized-brand')
.canAutocomplete(false)
.minItems(1);
@@ -145,7 +145,7 @@ export function uiFieldLocalized(field, context) {
// Show the suggestions.. If the user picks one, change the tags..
if (allSuggestions.length && goodSuggestions.length) {
input
.call(brandcombo
.call(brandCombo
.fetcher(fetchBrandNames(preset, allSuggestions))
.on('accept', function(d) {
var entity = context.entity(_entity.id); // get latest
@@ -391,7 +391,7 @@ export function uiFieldLocalized(field, context) {
.attr('placeholder', t('translate.localized_translation_language'))
.on('blur', changeLang)
.on('change', changeLang)
.call(langcombo);
.call(langCombo);
wrap
.append('input')
+7 -8
View File
@@ -13,19 +13,18 @@ export function uiFieldMaxspeed(field, context) {
var dispatch = d3_dispatch('change');
var unitInput = d3_select(null);
var input = d3_select(null);
var combobox;
var _entity;
var _isImperial;
var speedCombo = uiCombobox(context, 'maxspeed');
var unitCombo = uiCombobox(context, 'maxspeed-unit')
.data(['km/h', 'mph'].map(comboValues));
var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120];
var imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
function maxspeed(selection) {
combobox = uiCombobox(context);
var unitCombobox = uiCombobox(context)
.data(['km/h', 'mph'].map(comboValues));
var wrap = selection.selectAll('.form-field-input-wrap')
.data([0]);
@@ -45,7 +44,7 @@ export function uiFieldMaxspeed(field, context) {
.attr('id', 'preset-input-' + field.safeid)
.attr('placeholder', field.placeholder())
.call(utilNoAuto)
.call(combobox)
.call(speedCombo)
.merge(input);
input
@@ -73,7 +72,7 @@ export function uiFieldMaxspeed(field, context) {
.append('input')
.attr('type', 'text')
.attr('class', 'maxspeed-unit')
.call(unitCombobox)
.call(unitCombo)
.merge(unitInput);
unitInput
@@ -91,7 +90,7 @@ export function uiFieldMaxspeed(field, context) {
function setSuggestions() {
combobox.data((_isImperial ? imperialValues : metricValues).map(comboValues));
speedCombo.data((_isImperial ? imperialValues : metricValues).map(comboValues));
utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
}
+25 -26
View File
@@ -27,36 +27,35 @@ export function uiFieldWikipedia(field, context) {
var _wikiURL = '';
var _entity;
var langCombo = uiCombobox(context, 'wikipedia-lang')
.fetcher(function(value, cb) {
var v = value.toLowerCase();
function wiki(selection) {
var langcombo = uiCombobox(context)
.fetcher(function(value, cb) {
var v = value.toLowerCase();
cb(dataWikipedia.filter(function(d) {
return d[0].toLowerCase().indexOf(v) >= 0 ||
d[1].toLowerCase().indexOf(v) >= 0 ||
d[2].toLowerCase().indexOf(v) >= 0;
}).map(function(d) {
return { value: d[1] };
}));
});
cb(dataWikipedia.filter(function(d) {
return d[0].toLowerCase().indexOf(v) >= 0 ||
d[1].toLowerCase().indexOf(v) >= 0 ||
d[2].toLowerCase().indexOf(v) >= 0;
}).map(function(d) {
return { value: d[1] };
var titleCombo = uiCombobox(context, 'wikipedia-title')
.fetcher(function(value, cb) {
if (!value && _entity) {
value = context.entity(_entity.id).tags.name || '';
}
var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
searchfn(language()[2], value, function(query, data) {
cb(data.map(function(d) {
return { value: d };
}));
});
var titlecombo = uiCombobox(context)
.fetcher(function(value, cb) {
if (!value) {
value = context.entity(_entity.id).tags.name || '';
}
var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
searchfn(language()[2], value, function(query, data) {
cb(data.map(function(d) {
return { value: d };
}));
});
});
});
function wiki(selection) {
var wrap = selection.selectAll('.form-field-input-wrap')
.data([0]);
@@ -84,12 +83,12 @@ export function uiFieldWikipedia(field, context) {
.attr('class', 'wiki-lang')
.attr('placeholder', t('translate.localized_translation_language'))
.call(utilNoAuto)
.call(langCombo)
.merge(lang);
utilGetSetValue(lang, language()[1]);
lang
.call(langcombo)
.on('blur', changeLang)
.on('change', changeLang);
@@ -111,10 +110,10 @@ export function uiFieldWikipedia(field, context) {
.attr('class', 'wiki-title')
.attr('id', 'preset-input-' + field.safeid)
.call(utilNoAuto)
.call(titleCombo)
.merge(title);
title
.call(titlecombo)
.on('blur', blur)
.on('change', change);