diff --git a/modules/ui/entity_highlight.js b/modules/ui/entity_highlight.js deleted file mode 100644 index cc92a0250..000000000 --- a/modules/ui/entity_highlight.js +++ /dev/null @@ -1,17 +0,0 @@ -import _forEach from 'lodash-es/forEach'; - -export function highlightEntity(context, entity, highlighted) { - - var selectorPrefix = entity.type === 'node' ? 'g.' : 'path.'; - // set the class for the SVG to add or remove the highlighted styling - context.surface().selectAll(selectorPrefix+entity.id).classed('highlighted', highlighted); - if (entity.members) { - // recursively highlight members so that relations will appear highlighted - _forEach(entity.members, function(member){ - if (member.id && context.hasEntity(member.id)) { - highlightEntity(context, context.entity(member.id), highlighted); - } - }); - } - -} diff --git a/modules/ui/raw_member_editor.js b/modules/ui/raw_member_editor.js index a2a70be89..0d1080dca 100644 --- a/modules/ui/raw_member_editor.js +++ b/modules/ui/raw_member_editor.js @@ -7,7 +7,6 @@ import { d3combobox as d3_combobox } from '../lib/d3.combobox.js'; import { t } from '../util/locale'; import { actionChangeMember, actionDeleteMember } from '../actions'; -import { highlightEntity } from './entity_highlight'; import { modeBrowse, modeSelect } from '../modes'; import { osmEntity } from '../osm'; import { svgIcon } from '../svg'; @@ -16,7 +15,8 @@ import { uiDisclosure } from './disclosure'; import { utilDisplayName, utilDisplayType, - utilNoAuto + utilNoAuto, + utilHighlightEntity } from '../util'; @@ -38,7 +38,7 @@ export function uiRawMemberEditor(context) { context.map().zoomTo(entity); // highlight the feature in case it wasn't previously on-screen - highlightEntity(context, d.member, true); + utilHighlightEntity(d.id, true, context); } @@ -136,10 +136,10 @@ export function uiRawMemberEditor(context) { // highlight the member feature in the map while hovering on the list item d3_select(this).on('mouseover', function() { - highlightEntity(context, d.member, true); + utilHighlightEntity(d.id, true, context); }); d3_select(this).on('mouseout', function() { - highlightEntity(context, d.member, false); + utilHighlightEntity(d.id, false, context); }); var label = d3_select(this).append('label') diff --git a/modules/ui/raw_membership_editor.js b/modules/ui/raw_membership_editor.js index a63c9e668..f856cd7ab 100644 --- a/modules/ui/raw_membership_editor.js +++ b/modules/ui/raw_membership_editor.js @@ -19,13 +19,12 @@ import { actionDeleteMember } from '../actions'; -import { highlightEntity } from './entity_highlight'; import { modeSelect } from '../modes'; import { osmEntity, osmRelation } from '../osm'; import { services } from '../services'; import { svgIcon } from '../svg'; import { uiDisclosure } from './disclosure'; -import { utilDisplayName, utilNoAuto } from '../util'; +import { utilDisplayName, utilNoAuto, utilHighlightEntity } from '../util'; export function uiRawMembershipEditor(context) { @@ -177,10 +176,10 @@ export function uiRawMembershipEditor(context) { enter.each(function(d){ // highlight the relation in the map while hovering on the list item d3_select(this).on('mouseover', function() { - highlightEntity(context, d.relation, true); + utilHighlightEntity(d.relation.id, true, context); }); d3_select(this).on('mouseout', function() { - highlightEntity(context, d.relation, false); + utilHighlightEntity(d.relation.id, false, context); }); }); diff --git a/modules/ui/selection_list.js b/modules/ui/selection_list.js index 0e12a66a6..f7f3a3ee7 100644 --- a/modules/ui/selection_list.js +++ b/modules/ui/selection_list.js @@ -4,11 +4,10 @@ import { } from 'd3-selection'; import { t } from '../util/locale'; -import { highlightEntity } from './entity_highlight'; import { modeSelect } from '../modes'; import { osmEntity } from '../osm'; import { svgIcon } from '../svg'; -import { utilDisplayName } from '../util'; +import { utilDisplayName, utilHighlightEntity } from '../util'; export function uiSelectionList(context, selectedIDs) { @@ -72,10 +71,10 @@ export function uiSelectionList(context, selectedIDs) { .each(function(d) { // highlight the feature in the map while hovering on the list item d3_select(this).on('mouseover', function() { - highlightEntity(context, d, true); + utilHighlightEntity(d.id, true, context); }); d3_select(this).on('mouseout', function() { - highlightEntity(context, d, false); + utilHighlightEntity(d.id, false, context); }); }); diff --git a/modules/util/index.js b/modules/util/index.js index 16460cd14..a0269240f 100644 --- a/modules/util/index.js +++ b/modules/util/index.js @@ -7,12 +7,14 @@ export { utilDisplayType } from './util'; export { utilEditDistance } from './util'; export { utilEntitySelector } from './util'; export { utilEntityOrMemberSelector } from './util'; +export { utilEntityOrDeepMemberSelector } from './util'; export { utilFastMouse } from './util'; export { utilFunctor } from './util'; export { utilGetAllNodes } from './util'; export { utilGetPrototypeOf } from './util'; export { utilGetSetValue } from './get_set_value'; export { utilHashcode } from './util'; +export { utilHighlightEntity } from './util'; export { utilIdleWorker } from './idle_worker'; export { utilNoAuto } from './util'; export { utilPrefixCSSProperty } from './util'; diff --git a/modules/util/util.js b/modules/util/util.js index 6b03c9f4c..5eb821ced 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -34,6 +34,32 @@ export function utilEntityOrMemberSelector(ids, graph) { } +export function utilEntityOrDeepMemberSelector(ids, graph) { + var seen = {}; + var allIDs = []; + function addEntityAndMembersIfNotYetSeen(id) { + // avoid infinite recursion for circular relations by skipping seen entities + if (seen[id]) return; + // mark the entity as seen + seen[id] = true; + // add the id; + allIDs.push(id); + if (graph.hasEntity(id)) { + var entity = graph.entity(id); + if (entity.type === 'relation' && entity.members) { + entity.members.forEach(function(member){ + addEntityAndMembersIfNotYetSeen(member.id); + }); + } + } + } + ids.forEach(function(id) { + addEntityAndMembersIfNotYetSeen(id); + }); + return utilEntitySelector(allIDs); +} + + export function utilGetAllNodes(ids, graph) { var seen = {}; var nodes = []; @@ -282,3 +308,10 @@ export function utilHashcode(str) { } return hash; } + +// Adds or removes highlight styling for the specified entity's SVG elements in the map. +export function utilHighlightEntity(id, highlighted, context) { + context.surface() + .selectAll(utilEntityOrDeepMemberSelector([id], context.graph())) + .classed('highlighted', highlighted); +}