diff --git a/modules/behavior/draw.js b/modules/behavior/draw.js index dd6b9e0a0..81461c4e7 100644 --- a/modules/behavior/draw.js +++ b/modules/behavior/draw.js @@ -27,7 +27,7 @@ export function behaviorDraw(context) { var keybinding = utilKeybinding('draw'); - var hover = behaviorHover(context).altDisables(true).ignoreVertex(true) + var _hover = behaviorHover(context).altDisables(true).ignoreVertex(true) .on('hover', context.ui().sidebar.hover); var tail = behaviorTail(); var edit = behaviorEdit(context); @@ -195,7 +195,7 @@ export function behaviorDraw(context) { function behavior(selection) { - context.install(hover); + context.install(_hover); context.install(edit); if (!context.inIntro() && !_usedTails[tail.text()]) { @@ -225,7 +225,7 @@ export function behaviorDraw(context) { behavior.off = function(selection) { context.ui().sidebar.hover.cancel(); - context.uninstall(hover); + context.uninstall(_hover); context.uninstall(edit); if (!context.inIntro() && !_usedTails[tail.text()]) { @@ -253,6 +253,10 @@ export function behaviorDraw(context) { return behavior; }; + behavior.hover = function() { + return _hover; + }; + return utilRebind(behavior, dispatch, 'on'); } diff --git a/modules/behavior/draw_way.js b/modules/behavior/draw_way.js index 7e5feb2e5..6ca5fc82f 100644 --- a/modules/behavior/draw_way.js +++ b/modules/behavior/draw_way.js @@ -13,14 +13,17 @@ import { modeBrowse, modeSelect } from '../modes'; import { osmNode } from '../osm'; import { utilKeybinding } from '../util'; - export function behaviorDrawWay(context, wayID, index, mode, startGraph) { var origWay = context.entity(wayID); + var annotation = t((origWay.isDegenerate() ? 'operations.start.annotation.' : 'operations.continue.annotation.') + context.geometry(wayID) ); + var behavior = behaviorDraw(context); + behavior.hover().initialNodeId(index ? origWay.nodes[index] : origWay.nodes[origWay.nodes.length - 1]); + var _tempEdits = 0; var end = osmNode({ loc: context.map().mouseCoordinates() }); @@ -67,7 +70,7 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph) { function allowsVertex(d) { - return _isEmpty(d.tags) || context.presets().allowsVertex(d, context.graph()); + return context.presets().allowsVertex(d, context.graph()); } diff --git a/modules/behavior/hover.js b/modules/behavior/hover.js index 4678b2aa5..20f759a22 100644 --- a/modules/behavior/hover.js +++ b/modules/behavior/hover.js @@ -8,8 +8,6 @@ import { import { osmEntity, osmNote, qaError } from '../osm'; import { utilKeybinding, utilRebind } from '../util'; -import _isEmpty from 'lodash-es/isEmpty'; - /* The hover behavior adds the `.hover` class on mouseover to all elements to which the identical datum is bound, and removes it on mouseout. @@ -22,10 +20,11 @@ import _isEmpty from 'lodash-es/isEmpty'; export function behaviorHover(context) { var dispatch = d3_dispatch('hover'); var _selection = d3_select(null); - var _newId = null; + var _newNodeId = null; + var _initialNodeId = null; var _buttonDown; var _altDisables; - var _vertex; + var _ignoreVertex; var _target; @@ -59,7 +58,13 @@ export function behaviorHover(context) { function behavior(selection) { _selection = selection; - _newId = null; + + if (_initialNodeId) { + _newNodeId = _initialNodeId; + _initialNodeId = null; + } else { + _newNodeId = null; + } _selection .on('mouseover.hover', mouseover) @@ -98,10 +103,6 @@ export function behaviorHover(context) { .on('mouseup.hover', null, true); } - function allowsVertex(d) { - return _isEmpty(d.tags) || context.presets().allowsVertex(d, context.graph()); - } - function enter(datum) { if (datum === _target) return; _target = datum; @@ -140,15 +141,16 @@ export function behaviorHover(context) { } // Update hover state and dispatch event - if (entity && entity.id !== _newId) { + if (entity && entity.id !== _newNodeId) { // If drawing a way, don't hover on a node that was just placed. #3974 var mode = context.mode() && context.mode().id; - if ((mode === 'draw-line' || mode === 'draw-area') && !_newId && entity.type === 'node') { - _newId = entity.id; + if ((mode === 'draw-line' || mode === 'draw-area') && !_newNodeId && entity.type === 'node') { + _newNodeId = entity.id; return; } - var suppressed = (_altDisables && d3_event && d3_event.altKey) || (_vertex && !allowsVertex(entity, context.graph())); + var suppressed = (_altDisables && d3_event && d3_event.altKey) || + (entity.type === 'node' && _ignoreVertex && !context.presets().allowsVertex(entity, context.graph())); _selection.selectAll(selector) .classed(suppressed ? 'hover-suppressed' : 'hover', true); @@ -187,10 +189,15 @@ export function behaviorHover(context) { }; behavior.ignoreVertex = function(val) { - if (!arguments.length) return _vertex; - _vertex = val; + if (!arguments.length) return _ignoreVertex; + _ignoreVertex = val; + return behavior; + }; + + behavior.initialNodeId = function(nodeId) { + _initialNodeId = nodeId; return behavior; }; return utilRebind(behavior, dispatch, 'on'); -} \ No newline at end of file +} diff --git a/modules/modes/drag_node.js b/modules/modes/drag_node.js index 533b46aac..d83be0bc5 100644 --- a/modules/modes/drag_node.js +++ b/modules/modes/drag_node.js @@ -96,6 +96,12 @@ export function modeDragNode(context) { } + function shouldSnapToNode(target) { + return _activeEntity.geometry(context.graph()) !== 'vertex' || + context.presets().allowsVertex(target, context.graph()); + } + + function origin(entity) { return context.projection(entity.loc); } @@ -158,6 +164,8 @@ export function modeDragNode(context) { _activeEntity = entity; _startLoc = entity.loc; + hover.ignoreVertex(entity.geometry(context.graph()) === 'vertex'); + context.surface().selectAll('.' + _activeEntity.id) .classed('active', true); @@ -199,7 +207,9 @@ export function modeDragNode(context) { var edge; if (targetLoc) { // snap to node/vertex - a point target with `.loc` - loc = targetLoc; + if (shouldSnapToNode(target)) { + loc = targetLoc; + } } else if (targetNodes) { // snap to way - a line target with `.nodes` edge = geoChooseEdge(targetNodes, context.mouse(), context.projection, end.id); @@ -376,7 +386,7 @@ export function modeDragNode(context) { connectAnnotation(entity, target) ); - } else if (target && target.type === 'node') { + } else if (target && target.type === 'node' && shouldSnapToNode(target)) { context.replace( actionConnect([target.id, entity.id]), connectAnnotation(entity, target) diff --git a/modules/presets/index.js b/modules/presets/index.js index bf2452fae..873cb6579 100644 --- a/modules/presets/index.js +++ b/modules/presets/index.js @@ -1,5 +1,6 @@ import _bind from 'lodash-es/bind'; import _forEach from 'lodash-es/forEach'; +import _isEmpty from 'lodash-es/isEmpty'; import _reject from 'lodash-es/reject'; import _uniq from 'lodash-es/uniq'; @@ -79,6 +80,7 @@ export function presetIndex() { all.allowsVertex = function(entity, resolver) { if (entity.type !== 'node') return false; + if (_isEmpty(entity.tags)) return true; return resolver.transient(entity, 'vertexMatch', function() { var vertexPresets = _index.vertex; var match; diff --git a/modules/ui/preset_list.js b/modules/ui/preset_list.js index d68bbdb29..0f5e43ffe 100644 --- a/modules/ui/preset_list.js +++ b/modules/ui/preset_list.js @@ -408,6 +408,8 @@ export function uiPresetList(context) { function updateForFeatureHiddenState() { + if (!context.hasEntity(_entityID)) return; + var geometry = context.geometry(_entityID); var button = d3_selectAll('.preset-list .preset-list-button');