diff --git a/css/80_app.css b/css/80_app.css index 73283418a..73a3a288b 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -451,21 +451,24 @@ button[disabled].action:hover { width: 100%; } .tool-group.leading-area { - flex-shrink: 2; justify-content: flex-start; } +.tool-group.leading-area, +.tool-group.trailing-area { + flex-shrink: 2; +} .tool-group.center-area { justify-content: center; } .tool-group.trailing-area { - justify-content: flex-start; + justify-content: flex-end; } .tool-group > div { display: flex; margin: 0 5px; } -.tool-group button { +.tool-group button.bar-button { flex: 1 1 auto; flex-flow: row nowrap; align-items: center; @@ -589,7 +592,7 @@ button.add-note svg.icon { width: unset; } #bar.narrow .spinner, -#bar.narrow button .label { +#bar.narrow button.bar-button .label { display: none; } #bar.narrow button .count { @@ -597,8 +600,17 @@ button.add-note svg.icon { border-right-width: 0; } +/* Add a feature search bar +------------------------------------------------------- */ + +.search-add { + width: 100%; + min-width: 200px; + max-width: 600px; +} .search-add .search-wrap { position: relative; + width: 100%; } .search-add input[type='search'] { position: relative; @@ -607,10 +619,13 @@ button.add-note svg.icon { border: none; border-radius: 20px; font-size: 14px; - min-width: 160px; text-indent: 25px; padding: 5px 10px } +.search-add input[type='search']:focus { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} .search-add .search-icon { color: #333; display: block; @@ -619,7 +634,45 @@ button.add-note svg.icon { top: 10px; pointer-events: none; } - +.search-add .popover { + max-height: 200px; + width: 100%; + position: absolute; + top: 40px; + border-radius: 0 0 4px 4px; + border-top: 2px solid #DCDCDC; + overflow-y: auto; +} +.search-add .list-item { + display: flex; + position: relative; + padding: 2px; +} +.search-add .list-item:not(:last-of-type) { + border-bottom: 1px solid #DCDCDC; +} +.search-add .list-item .label { + font-weight: bold; + font-size: 12px; + padding-left: 2px; + top: 0; + bottom: 0; + position: relative; + display: flex; + align-items: center; + line-height: 1.2em; +} +.search-add .list-item > *:not(button) { + pointer-events: none; +} +.search-add .list-item button { + position: absolute; + border-radius: 0; + height: 100%; + width: 100%; + top: 0; + left: 0; +} /* Header for modals / panes ------------------------------------------------------- */ @@ -1018,9 +1071,10 @@ a.hide-toggle { height: 60px; text-align: center; } -#bar .preset-icon-container { +.preset-icon-container.small { width: 40px; height: 40px; + flex: 0 0 auto; } .preset-icon-line { diff --git a/modules/presets/collection.js b/modules/presets/collection.js index d110ee059..efc439038 100644 --- a/modules/presets/collection.js +++ b/modules/presets/collection.js @@ -34,6 +34,14 @@ export function presetCollection(collection) { })); }, + matchAnyGeometry: function(geometries) { + return presetCollection(this.collection.filter(function(d) { + return geometries.some(function(geometry) { + return d.matchGeometry(geometry); + }); + })); + }, + search: function(value, geometry) { if (!value) return this; @@ -134,8 +142,6 @@ export function presetCollection(collection) { return a.preset; }); - var other = presets.item(geometry); - var results = leading_name.concat( leading_suggestions, leading_terms, @@ -145,7 +151,12 @@ export function presetCollection(collection) { similar_terms ).slice(0, maxSearchResults - 1); - return presetCollection(_uniq(results.concat(other))); + if (geometry) { + var other = presets.item(geometry); + results = results.concat(other); + } + + return presetCollection(_uniq(results)); } }; diff --git a/modules/ui/init.js b/modules/ui/init.js index 472b0484e..c40ce62ea 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -91,7 +91,7 @@ export function uiInit(context) { var sidebarButton = leadingArea .append('div') .append('button') - .attr('class', 'sidebar-toggle') + .attr('class', 'sidebar-toggle bar-button') .attr('tabindex', -1) .on('click', ui.sidebar.toggle) .call(tooltip() diff --git a/modules/ui/modes.js b/modules/ui/modes.js index ea15f1199..111b04578 100644 --- a/modules/ui/modes.js +++ b/modules/ui/modes.js @@ -98,8 +98,6 @@ export function uiModes(context) { var favoritePresets = context.getFavoritePresets(); var favoriteModes = favoritePresets.map(function(d) { var preset = context.presets().item(d.id); - var isMaki = /^maki-/.test(preset.icon); - var icon = '#' + preset.icon + (isMaki ? '-11' : ''); var markerClass = 'add-preset add-' + d.geom + ' add-preset-' + preset.name() .replace(/\s+/g, '_') + '-' + d.geom; //replace spaces with underscores to avoid css interpretation @@ -117,7 +115,6 @@ export function uiModes(context) { title: presetName, description: t(tooltipTitleID, { feature: presetName }), key: '', - icon: icon, preset: preset, geometry: d.geom }; @@ -145,7 +142,7 @@ export function uiModes(context) { var buttonsEnter = buttons.enter() .append('button') .attr('tabindex', -1) - .attr('class', function(d) { return d.id + ' add-button'; }) + .attr('class', function(d) { return d.id + ' add-button bar-button'; }) .on('click.mode-buttons', function(d) { if (!enabled(d)) return; diff --git a/modules/ui/preset_icon.js b/modules/ui/preset_icon.js index f699272e2..0f394c9d2 100644 --- a/modules/ui/preset_icon.js +++ b/modules/ui/preset_icon.js @@ -128,7 +128,7 @@ export function uiPresetIcon() { container = container.enter() .append('div') - .attr('class', 'preset-icon-container') + .attr('class', 'preset-icon-container ' + sizeClass) .merge(container); var p = preset.apply(this, arguments); diff --git a/modules/ui/save.js b/modules/ui/save.js index a818941f7..7bb972914 100644 --- a/modules/ui/save.js +++ b/modules/ui/save.js @@ -77,7 +77,7 @@ export function uiSave(context) { var button = selection .append('button') - .attr('class', 'save disabled') + .attr('class', 'save disabled bar-button') .attr('tabindex', -1) .on('click', save) .call(tooltipBehavior); diff --git a/modules/ui/search_add.js b/modules/ui/search_add.js index 6b3b31522..a4b44242e 100644 --- a/modules/ui/search_add.js +++ b/modules/ui/search_add.js @@ -6,6 +6,12 @@ import { selectAll as d3_selectAll } from 'd3-selection'; +import { + modeAddArea, + modeAddLine, + modeAddPoint +} from '../modes'; + import { t, textDirection } from '../util/locale'; import { actionChangePreset } from '../actions/index'; import { operationDelete } from '../operations/index'; @@ -18,25 +24,142 @@ import { utilKeybinding, utilNoAuto, utilRebind } from '../util'; export function uiSearchAdd(context) { var dispatch = d3_dispatch('choose'); + var presets; + var search = d3_select(null), popover = d3_select(null), list = d3_select(null); function searchAdd(selection) { + presets = context.presets().matchAnyGeometry(['point', 'line', 'area']); + var searchWrap = selection .append('div') .attr('class', 'search-wrap'); - var search = searchWrap + search = searchWrap .append('input') .attr('class', 'search-input') .attr('placeholder', t('modes.add_feature.title')) .attr('type', 'search') - .call(utilNoAuto); - //.on('keydown', initialKeydown) - //.on('keypress', keypress) - //.on('input', inputevent); + .call(utilNoAuto) + .on('focus', function() { + popover.classed('hide', false); + }) + .on('blur', function() { + popover.classed('hide', true); + }) + .on('input', function () { + var value = search.property('value'); + //list.classed('filtered', value.length); + if (value.length) { + var results = presets.search(value); + list.call(drawList, results); + } else { + //list.call(drawList, context.presets().defaults(geometry, 36)); + } + }); searchWrap .call(svgIcon('#iD-icon-search', 'search-icon pre-text')); + + popover = searchWrap + .append('div') + .attr('class', 'popover fillL hide') + .on('mousedown', function() { + // don't blur the search input (and thus close results) + d3_event.preventDefault(); + d3_event.stopPropagation(); + }); + + list = popover + .append('div') + .attr('class', 'list');// + //.call(drawList, context.presets().defaults(geometry, 36)); + } + + function supportedGeometry(preset) { + return preset.geometry.filter(function(geometry) { + return ['point', 'line', 'area'].indexOf(geometry) !== -1; + }); + } + function defaultGeometry(item) { + if (item.geometry.filter) { + var supportedGeom = supportedGeometry(item); + if (supportedGeom.length === 1) { + return supportedGeom[0]; + } + } else { + return item.geometry; + } + return 'point'; + } + + function drawList(list, presets) { + /*var collection = presets.collection.reduce(function(collection, preset) { + if (preset.members) { + collection.push(CategoryItem(preset)); + } else if (preset.visible()) { + collection.push(PresetItem(preset)); + } + return collection; + }, []);*/ + + var items = list.selectAll('.list-item') + .data(presets.collection, function(d) { return d.id; }); + + items.order(); + + items.exit() + .remove(); + + var row = items.enter() + .append('div') + .attr('class', function(item) { return 'list-item preset-' + item.id.replace('/', '-'); }); + + var button = row.append('button') + .on('click', function(d) { + var geom = defaultGeometry(d); + var markerClass = 'add-preset add-' + geom + ' add-preset-' + d.name() + .replace(/\s+/g, '_') + + '-' + geom; //replace spaces with underscores to avoid css interpretation + var modeInfo = { + id: markerClass, + button: markerClass, + preset: d, + geometry: geom + }; + var mode; + switch (geom) { + case 'point': + case 'vertex': + mode = modeAddPoint(context, modeInfo); + break; + case 'line': + mode = modeAddLine(context, modeInfo); + break; + case 'area': + mode = modeAddArea(context, modeInfo); + } + search.node().blur(); + context.enter(mode); + }); + + row.each(function(d) { + d3_select(this).call( + uiPresetIcon() + .geometry(defaultGeometry(d)) + .preset(d) + .sizeClass('small') + ); + }); + row.append('div') + .attr('class', 'label') + .append('div') + .attr('class', 'label-inner') + .text(function(d) { + return d.name(); + }); + + //updateForFeatureHiddenState(); } return utilRebind(searchAdd, dispatch, 'on'); diff --git a/modules/ui/undo_redo.js b/modules/ui/undo_redo.js index eef37b5d2..7222396b9 100644 --- a/modules/ui/undo_redo.js +++ b/modules/ui/undo_redo.js @@ -46,7 +46,7 @@ export function uiUndoRedo(context) { .data(commands) .enter() .append('button') - .attr('class', function(d) { return 'disabled ' + d.id + '-button'; }) + .attr('class', function(d) { return 'disabled ' + d.id + '-button bar-button'; }) .on('click', function(d) { return d.action(); }) .call(tooltipBehavior);