Use pointer events for hovering and selecting data on supported platforms (re: #5505)

Fix issue where Apple Pencil stylus could not select map data (close #7396)
Fix issue where features could not be selected in a single tap on iPad (close #7380)
This commit is contained in:
Quincy Morgan
2020-03-04 12:18:43 -08:00
parent 4a9f9bff34
commit c41e0b9937
2 changed files with 29 additions and 24 deletions
+17 -14
View File
@@ -9,8 +9,8 @@ import { osmEntity, osmNote, QAItem } from '../osm';
import { utilKeybinding, utilRebind } from '../util';
/*
The hover behavior adds the `.hover` class on mouseover to all elements to which
the identical datum is bound, and removes it on mouseout.
The hover behavior adds the `.hover` class on pointerover to all elements to which
the identical datum is bound, and removes it on pointerout.
The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
representation may consist of several elements scattered throughout the DOM hierarchy.
@@ -27,6 +27,9 @@ export function behaviorHover(context) {
var _ignoreVertex;
var _target;
// use pointer events on supported platforms; fallback to mouse events
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
function keydown() {
if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
@@ -67,40 +70,40 @@ export function behaviorHover(context) {
}
_selection
.on('mouseover.hover', mouseover)
.on('mouseout.hover', mouseout)
.on('mousedown.hover', mousedown);
.on(_pointerPrefix + 'over.hover', pointerover)
.on(_pointerPrefix + 'out.hover', pointerout)
.on(_pointerPrefix + 'down.hover', pointerdown);
d3_select(window)
.on('keydown.hover', keydown)
.on('keyup.hover', keyup);
function mouseover() {
function pointerover() {
if (_buttonDown) return;
var target = d3_event.target;
enter(target ? target.__data__ : null);
}
function mouseout() {
function pointerout() {
if (_buttonDown) return;
var target = d3_event.relatedTarget;
enter(target ? target.__data__ : null);
}
function mousedown() {
function pointerdown() {
_buttonDown = true;
d3_select(window)
.on('mouseup.hover', mouseup, true);
.on(_pointerPrefix + 'up.hover', pointerup, true);
}
function mouseup() {
function pointerup() {
_buttonDown = false;
d3_select(window)
.on('mouseup.hover', null, true);
.on(_pointerPrefix + 'up.hover', null, true);
}
function allowsVertex(d) {
@@ -188,9 +191,9 @@ export function behaviorHover(context) {
.classed('hover-disabled', false);
selection
.on('mouseover.hover', null)
.on('mouseout.hover', null)
.on('mousedown.hover', null);
.on(_pointerPrefix + 'over.hover', null)
.on(_pointerPrefix + 'out.hover', null)
.on(_pointerPrefix + 'down.hover', null);
d3_select(window)
.on('keydown.hover', null)
+12 -10
View File
@@ -17,6 +17,8 @@ export function behaviorSelect(context) {
var _suppressMenu = true;
var _p1 = null;
// use pointer events on supported platforms; fallback to mouse events
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
function point() {
return d3_mouse(context.container().node());
@@ -53,25 +55,25 @@ export function behaviorSelect(context) {
}
function mousedown() {
function pointerdown() {
if (!_p1) {
_p1 = point();
}
d3_select(window)
.on('mouseup.select', mouseup, true);
.on(_pointerPrefix + 'up.select', pointerup, true);
_suppressMenu = !isShowAlways;
}
function mousemove() {
function pointermove() {
if (d3_event) {
_lastMouse = d3_event;
}
}
function mouseup() {
function pointerup() {
click();
}
@@ -99,7 +101,7 @@ export function behaviorSelect(context) {
function click() {
d3_select(window)
.on('mouseup.select', null, true);
.on(_pointerPrefix + 'up.select', null, true);
if (!_p1) return;
var p2 = point();
@@ -211,8 +213,8 @@ export function behaviorSelect(context) {
});
selection
.on('mousedown.select', mousedown)
.on('mousemove.select', mousemove)
.on(_pointerPrefix + 'down.select', pointerdown)
.on(_pointerPrefix + 'move.select', pointermove)
.on('contextmenu.select', contextmenu);
if (d3_event && d3_event.shiftKey) {
@@ -227,11 +229,11 @@ export function behaviorSelect(context) {
.on('keydown.select', null)
.on('keyup.select', null)
.on('contextmenu.select-window', null)
.on('mouseup.select', null, true);
.on(_pointerPrefix + 'up.select', null, true);
selection
.on('mousedown.select', null)
.on('mousemove.select', null)
.on(_pointerPrefix + 'down.select', null)
.on(_pointerPrefix + 'move.select', null)
.on('contextmenu.select', null);
context.surface()