mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 21:48:20 +02:00
Extend behaviorHover to support multiple pointers
This commit is contained in:
@@ -308,8 +308,8 @@ export function behaviorDrawWay(context, wayID, mode, startGraph) {
|
||||
.classed('nope-disabled', false);
|
||||
|
||||
d3_select(window)
|
||||
.on('keydown.hover', null)
|
||||
.on('keyup.hover', null);
|
||||
.on('keydown.drawWay', null)
|
||||
.on('keyup.drawWay', null);
|
||||
|
||||
context.history()
|
||||
.on('undone.draw', null);
|
||||
|
||||
+73
-67
@@ -23,10 +23,9 @@ export function behaviorHover(context) {
|
||||
var _selection = d3_select(null);
|
||||
var _newNodeId = null;
|
||||
var _initialNodeID = null;
|
||||
var _buttonDown;
|
||||
var _altDisables;
|
||||
var _ignoreVertex;
|
||||
var _target;
|
||||
var _targets = [];
|
||||
|
||||
// use pointer events on supported platforms; fallback to mouse events
|
||||
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
|
||||
@@ -55,7 +54,7 @@ export function behaviorHover(context) {
|
||||
_selection
|
||||
.classed('hover-disabled', false);
|
||||
|
||||
dispatch.call('hover', this, _target ? _target.id : null);
|
||||
dispatch.call('hover', this, _targets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +62,8 @@ export function behaviorHover(context) {
|
||||
function behavior(selection) {
|
||||
_selection = selection;
|
||||
|
||||
_targets = [];
|
||||
|
||||
if (_initialNodeID) {
|
||||
_newNodeId = _initialNodeID;
|
||||
_initialNodeID = null;
|
||||
@@ -73,38 +74,43 @@ export function behaviorHover(context) {
|
||||
_selection
|
||||
.on(_pointerPrefix + 'over.hover', pointerover)
|
||||
.on(_pointerPrefix + 'out.hover', pointerout)
|
||||
.on(_pointerPrefix + 'down.hover', pointerdown);
|
||||
// treat pointerdown as pointerover for touch devices
|
||||
.on(_pointerPrefix + 'down.hover', pointerover);
|
||||
|
||||
d3_select(window)
|
||||
.on(_pointerPrefix + 'up.hover', pointerout, true)
|
||||
.on('keydown.hover', keydown)
|
||||
.on('keyup.hover', keyup);
|
||||
|
||||
|
||||
function pointerover() {
|
||||
if (_buttonDown) return;
|
||||
var target = d3_event.target;
|
||||
enter(target ? target.__data__ : null);
|
||||
function eventTarget() {
|
||||
var datum = d3_event.target && d3_event.target.__data__;
|
||||
if (typeof datum !== 'object') return null;
|
||||
if (!(datum instanceof osmEntity) && datum.properties && (datum.properties.entity instanceof osmEntity)) {
|
||||
return datum.properties.entity;
|
||||
}
|
||||
return datum;
|
||||
}
|
||||
|
||||
function pointerover() {
|
||||
// ignore mouse hovers with buttons pressed
|
||||
if ((!d3_event.pointerType || d3_event.pointerType === 'mouse') && d3_event.buttons) return;
|
||||
|
||||
var target = eventTarget();
|
||||
if (target && _targets.indexOf(target) === -1) {
|
||||
_targets.push(target);
|
||||
updateHover(_targets);
|
||||
}
|
||||
}
|
||||
|
||||
function pointerout() {
|
||||
if (_buttonDown) return;
|
||||
var target = d3_event.relatedTarget;
|
||||
enter(target ? target.__data__ : null);
|
||||
}
|
||||
|
||||
|
||||
function pointerdown() {
|
||||
_buttonDown = true;
|
||||
d3_select(window)
|
||||
.on(_pointerPrefix + 'up.hover', pointerup, true);
|
||||
}
|
||||
|
||||
|
||||
function pointerup() {
|
||||
_buttonDown = false;
|
||||
d3_select(window)
|
||||
.on(_pointerPrefix + 'up.hover', null, true);
|
||||
var target = eventTarget();
|
||||
var index = _targets.indexOf(target);
|
||||
if (index !== -1) {
|
||||
_targets.splice(index);
|
||||
updateHover(_targets);
|
||||
}
|
||||
}
|
||||
|
||||
function allowsVertex(d) {
|
||||
@@ -120,65 +126,64 @@ export function behaviorHover(context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function enter(datum) {
|
||||
if (datum === _target) return;
|
||||
_target = datum;
|
||||
function updateHover(targets) {
|
||||
|
||||
var mode = context.mode();
|
||||
|
||||
_selection.selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
_selection.selectAll('.hover-suppressed')
|
||||
.classed('hover-suppressed', false);
|
||||
|
||||
// What are we hovering over?
|
||||
var entity, selector;
|
||||
if (datum && datum.__featurehash__) {
|
||||
entity = datum;
|
||||
selector = '.data' + datum.__featurehash__;
|
||||
var selector = '';
|
||||
|
||||
} else if (datum instanceof QAItem) {
|
||||
entity = datum;
|
||||
selector = '.' + datum.service + '.itemId-' + datum.id;
|
||||
for (var i in targets) {
|
||||
var datum = targets[i];
|
||||
|
||||
} else if (datum instanceof osmNote) {
|
||||
entity = datum;
|
||||
selector = '.note-' + datum.id;
|
||||
// What are we hovering over?
|
||||
if (datum.__featurehash__) {
|
||||
// hovering custom data
|
||||
selector += ', .data' + datum.__featurehash__;
|
||||
|
||||
} else if (datum instanceof osmEntity) {
|
||||
entity = datum;
|
||||
selector = '.' + entity.id;
|
||||
if (entity.type === 'relation') {
|
||||
entity.members.forEach(function(member) { selector += ', .' + member.id; });
|
||||
}
|
||||
} else if (datum && datum.properties && (datum.properties.entity instanceof osmEntity)) {
|
||||
entity = datum.properties.entity;
|
||||
selector = '.' + entity.id;
|
||||
if (entity.type === 'relation') {
|
||||
entity.members.forEach(function(member) { selector += ', .' + member.id; });
|
||||
} else if (datum instanceof QAItem) {
|
||||
selector += ', .' + datum.service + '.itemId-' + datum.id;
|
||||
|
||||
} else if (datum instanceof osmNote) {
|
||||
selector += ', .note-' + datum.id;
|
||||
|
||||
} else if (datum instanceof osmEntity) {
|
||||
|
||||
// If drawing a way, don't hover on a node that was just placed. #3974
|
||||
if ((mode.id === 'draw-line' || mode.id === 'draw-area') &&
|
||||
!_newNodeId &&
|
||||
datum.type === 'node') {
|
||||
|
||||
_newNodeId = datum.id;
|
||||
|
||||
} else if (datum.id !== _newNodeId &&
|
||||
(datum.type !== 'node' || !_ignoreVertex || allowsVertex(datum)) &&
|
||||
modeAllowsHover(datum)) {
|
||||
|
||||
selector += ', .' + datum.id;
|
||||
if (datum.type === 'relation') {
|
||||
for (var j in datum.members) {
|
||||
selector += ', .' + datum.members[j].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mode = context.mode();
|
||||
if (selector.trim().length) {
|
||||
// remove the first comma
|
||||
selector = selector.slice(1);
|
||||
|
||||
// Update hover state and dispatch event
|
||||
if (entity && entity.id !== _newNodeId) {
|
||||
// If drawing a way, don't hover on a node that was just placed. #3974
|
||||
|
||||
if ((mode.id === 'draw-line' || mode.id === 'draw-area') && !_newNodeId && entity.type === 'node') {
|
||||
_newNodeId = entity.id;
|
||||
return;
|
||||
}
|
||||
|
||||
var suppressed = (_altDisables && d3_event && d3_event.altKey) ||
|
||||
(entity.type === 'node' && _ignoreVertex && !allowsVertex(entity)) ||
|
||||
!modeAllowsHover(entity);
|
||||
var suppressed = _altDisables && d3_event && d3_event.altKey;
|
||||
_selection.selectAll(selector)
|
||||
.classed(suppressed ? 'hover-suppressed' : 'hover', true);
|
||||
|
||||
dispatch.call('hover', this, !suppressed && entity);
|
||||
|
||||
} else {
|
||||
dispatch.call('hover', this, null);
|
||||
}
|
||||
|
||||
dispatch.call('hover', this, !suppressed && targets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +202,7 @@ export function behaviorHover(context) {
|
||||
.on(_pointerPrefix + 'down.hover', null);
|
||||
|
||||
d3_select(window)
|
||||
.on(_pointerPrefix + 'up.hover', null, true)
|
||||
.on('keydown.hover', null)
|
||||
.on('keyup.hover', null);
|
||||
};
|
||||
|
||||
@@ -457,8 +457,8 @@ export function modeDragNode(context) {
|
||||
context.install(edit);
|
||||
|
||||
d3_select(window)
|
||||
.on('keydown.drawWay', keydown)
|
||||
.on('keyup.drawWay', keyup);
|
||||
.on('keydown.dragNode', keydown)
|
||||
.on('keyup.dragNode', keyup);
|
||||
|
||||
context.history()
|
||||
.on('undone.drag-node', cancel);
|
||||
@@ -471,8 +471,8 @@ export function modeDragNode(context) {
|
||||
context.uninstall(edit);
|
||||
|
||||
d3_select(window)
|
||||
.on('keydown.hover', null)
|
||||
.on('keyup.hover', null);
|
||||
.on('keydown.dragNode', null)
|
||||
.on('keyup.dragNode', null);
|
||||
|
||||
context.history()
|
||||
.on('undone.drag-node', null);
|
||||
|
||||
@@ -153,15 +153,15 @@ export function uiSidebar(context) {
|
||||
.append('div')
|
||||
.attr('class', 'inspector-hidden inspector-wrap fr');
|
||||
|
||||
var hoverModeSelect = function(datum) {
|
||||
var hoverModeSelect = function(targets) {
|
||||
context.container().selectAll('.feature-list-item').classed('hover', false);
|
||||
|
||||
if (context.selectedIDs().length > 1 &&
|
||||
datum instanceof osmEntity){
|
||||
targets && targets.length) {
|
||||
|
||||
var elements = context.container().selectAll('.feature-list-item')
|
||||
.filter(function (node) {
|
||||
return node.id === datum.id;
|
||||
return targets.indexOf(node) !== -1;
|
||||
});
|
||||
|
||||
if (!elements.empty()) {
|
||||
@@ -172,7 +172,8 @@ export function uiSidebar(context) {
|
||||
|
||||
sidebar.hoverModeSelect = _throttle(hoverModeSelect, 200);
|
||||
|
||||
function hover(datum) {
|
||||
function hover(targets) {
|
||||
var datum = targets && targets.length && targets[0];
|
||||
if (datum && datum.__featurehash__) { // hovering on data
|
||||
_wasData = true;
|
||||
sidebar
|
||||
|
||||
Reference in New Issue
Block a user