Skip to content

Commit

Permalink
Position the edit menu above the anchor point if triggered via touch …
Browse files Browse the repository at this point in the history
…or stylus (re: #7577)

Add additional code safety to behaivorSelect
  • Loading branch information
quincylvania committed May 12, 2020
1 parent 4fede52 commit 23714ba
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 36 deletions.
57 changes: 28 additions & 29 deletions modules/behavior/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ export function behaviorSelect(context) {
var _showMenu = false;
var _p1 = null;
var _downPointerId = null;
var _longPressTimeout;
var _longPressTimeout = null;
var _lastInteractionType = null;

// use pointer events on supported platforms; fallback to mouse events
var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';

function point() {
return utilFastMouse(context.container().node())(d3_event);
function point(event) {
return utilFastMouse(context.container().node())(event || d3_event);
}


Expand All @@ -40,7 +41,6 @@ export function behaviorSelect(context) {

if (e && e.keyCode === 93) { // context menu
e.preventDefault();
e.stopPropagation();
}
}

Expand All @@ -57,7 +57,7 @@ export function behaviorSelect(context) {

if (e && e.keyCode === 93) { // context menu
e.preventDefault();
e.stopPropagation();
_lastInteractionType = 'menukey';
contextmenu();
}
}
Expand All @@ -70,21 +70,7 @@ export function behaviorSelect(context) {
_downPointerId = d3_event.pointerId || 'mouse';

if (_longPressTimeout) window.clearTimeout(_longPressTimeout);

var node = this;

_longPressTimeout = window.setTimeout(function didLongPress() {
// simulate context menu event
if (window.CustomEvent) {
node.dispatchEvent(new CustomEvent('contextmenu'));
} else if (document.createEvent) {
var e = document.createEvent('HTMLEvents');
e.initEvent('contextmenu', true, false);
node.dispatchEvent(e);
} else { // IE
node.fireEvent('oncontextmenu');
}
}, 500);
_longPressTimeout = window.setTimeout(didLongPress, 500, d3_event.pointerType || 'mouse');

_lastMouse = d3_event;

Expand All @@ -95,6 +81,14 @@ export function behaviorSelect(context) {
}


function didLongPress(pointerType) {
_longPressTimeout = null;
_lastInteractionType = 'longdown-' + pointerType;
_showMenu = true;
click();
}


function pointermove() {
if (_downPointerId && _downPointerId !== (d3_event.pointerId || 'mouse')) return;

Expand All @@ -116,14 +110,16 @@ export function behaviorSelect(context) {
function contextmenu() {
var e = d3_event;
e.preventDefault();
e.stopPropagation();

if (!+e.clientX && !+e.clientY) {
if (_lastMouse) {
e.sourceEvent = _lastMouse;
} else {
return;
}
} else {
_lastMouse = d3_event;
_lastInteractionType = 'rightclick';
}

if (!_p1) {
Expand All @@ -138,13 +134,13 @@ export function behaviorSelect(context) {
if (_longPressTimeout) window.clearTimeout(_longPressTimeout);

if (!_p1) return;
var p2 = point();
var p2 = point(_lastMouse);
var dist = geoVecLength(_p1, p2);
_p1 = null;
if (dist > _tolerancePx) return;

var datum = d3_event.target.__data__ || (_lastMouse && _lastMouse.target.__data__);
var isMultiselect = d3_event.shiftKey || context.surface().select('.lasso').node();
var datum = (d3_event && d3_event.target.__data__) || (_lastMouse && _lastMouse.target.__data__);
var isMultiselect = (d3_event && d3_event.shiftKey) || context.surface().select('.lasso').node();

processClick(datum, isMultiselect);
}
Expand All @@ -170,22 +166,22 @@ export function behaviorSelect(context) {
if (!isMultiselect) {
if (selectedIDs.length > 1 && (_showMenu && !_alwaysShowMenu)) {
// multiple things already selected, just show the menu...
mode.reselect().showMenu();
mode.reselect().showMenu(_lastInteractionType);
} else {
// always enter modeSelect even if the entity is already
// selected since listeners may expect `context.enter` events,
// e.g. in the walkthrough
newMode = modeSelect(context, [datum.id]);
context.enter(newMode);
if (_showMenu) newMode.showMenu();
if (_showMenu) newMode.showMenu(_lastInteractionType);
}

} else {
if (selectedIDs.indexOf(datum.id) !== -1) {
// clicked entity is already in the selectedIDs list..
if (_showMenu && !_alwaysShowMenu) {
// don't deselect clicked entity, just show the menu.
mode.reselect().showMenu();
mode.reselect().showMenu(_lastInteractionType);
} else {
// deselect clicked entity, then reenter select mode or return to browse mode..
selectedIDs = selectedIDs.filter(function(id) { return id !== datum.id; });
Expand All @@ -197,7 +193,7 @@ export function behaviorSelect(context) {
selectedIDs = selectedIDs.concat([datum.id]);
newMode = modeSelect(context, selectedIDs);
context.enter(newMode);
if (_showMenu) newMode.showMenu();
if (_showMenu) newMode.showMenu(_lastInteractionType);
}
}

Expand Down Expand Up @@ -234,6 +230,8 @@ export function behaviorSelect(context) {
_showMenu = false;
_p1 = null;
_downPointerId = null;
_longPressTimeout = null;
_lastInteractionType = null;

d3_select(window)
.on('keydown.select', keydown)
Expand All @@ -245,7 +243,6 @@ export function behaviorSelect(context) {
var e = d3_event;
if (+e.clientX === 0 && +e.clientY === 0) {
d3_event.preventDefault();
d3_event.stopPropagation();
}
});

Expand All @@ -262,6 +259,8 @@ export function behaviorSelect(context) {


behavior.off = function(selection) {
if (_longPressTimeout) window.clearTimeout(_longPressTimeout);

d3_select(window)
.on('keydown.select', null)
.on('keyup.select', null)
Expand Down
9 changes: 5 additions & 4 deletions modules/modes/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export function modeSelect(context, selectedIDs) {
.select('.edit-menu').remove();
}

mode.showMenu = function() {
mode.showMenu = function(triggerType) {

// remove any displayed menu
closeMenu();
Expand Down Expand Up @@ -178,16 +178,17 @@ export function modeSelect(context, selectedIDs) {

_editMenu
.anchorLoc(point)
.triggerType(triggerType)
.operations(operations);

// render the menu
context.map().supersurface.call(_editMenu);
};


function toggleMenu() {
function spacebar() { // toggle the menu
if (context.map().supersurface.select('.edit-menu').empty()) {
mode.showMenu();
mode.showMenu('spacebar');
} else {
closeMenu();
}
Expand Down Expand Up @@ -271,7 +272,7 @@ export function modeSelect(context, selectedIDs) {
.on(['}', uiCmd('⌘]'), 'end'], lastVertex)
.on(['\\', 'pause'], nextParent)
.on('⎋', esc, true)
.on('space', toggleMenu);
.on('space', spacebar);

d3_select(document)
.call(keybinding);
Expand Down
30 changes: 27 additions & 3 deletions modules/ui/edit_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ export function uiEditMenu(context) {
var _operations = [];
// the position the menu should be displayed relative to
var _anchorLoc = [0, 0];
// a string indicating how the menu was opened
var _triggerType = '';

var _vpTopMargin = 85; // viewport top margin
var _vpBottomMargin = 45; // viewport bottom margin
var _vpSideMargin = 35; // viewport side margin

Expand All @@ -33,15 +36,30 @@ export function uiEditMenu(context) {
var offset = [0, 0];
var viewport = context.surfaceRect();

// position the menu above the anchor for stylus and finger input
// since the mapper's hand likely obscures the screen below the anchor
var menuTop = _triggerType.includes('touch') || _triggerType.includes('pen');

var menuLeft = displayOnLeft(viewport);

offset[0] = menuLeft ? -1 * (_menuSideMargin + _menuWidth) : _menuSideMargin;

var menuHeight = _verticalPadding * 2 + _operations.length * _buttonHeight;

if (_anchorLoc[1] + menuHeight > (viewport.height - _vpBottomMargin)) {
// menu is near bottom viewport edge, shift upwards
offset[1] = -1 * (_anchorLoc[1] + menuHeight - viewport.height + _vpBottomMargin);
if (menuTop) {
if (_anchorLoc[1] - menuHeight < _vpTopMargin) {
// menu is near top viewport edge, shift downward
offset[1] = -_anchorLoc[1] + _vpTopMargin;
} else {
offset[1] = -menuHeight;
}
} else {
if (_anchorLoc[1] + menuHeight > (viewport.height - _vpBottomMargin)) {
// menu is near bottom viewport edge, shift upwards
offset[1] = -_anchorLoc[1] - menuHeight + viewport.height - _vpBottomMargin;
} else {
offset[1] = 0;
}
}

var origin = geoVecAdd(_anchorLoc, offset);
Expand Down Expand Up @@ -153,6 +171,12 @@ export function uiEditMenu(context) {
return editMenu;
};

editMenu.triggerType = function(val) {
if (!arguments.length) return _triggerType;
_triggerType = val;
return editMenu;
};

editMenu.operations = function(val) {
if (!arguments.length) return _operations;
_operations = val;
Expand Down

0 comments on commit 23714ba

Please sign in to comment.