Variable names, fix edge avoidance, tooltips placement, RTL

This commit is contained in:
Bryan Housel
2017-02-17 22:51:29 -05:00
parent 9d660076ca
commit d8237fa3eb
2 changed files with 83 additions and 62 deletions

View File

@@ -153,16 +153,15 @@ export function modeSelect(context, selectedIDs) {
suppressMenu = true;
} else {
var point = context.mouse(),
viewport = geoExtent(context.projection.clipExtent()).polygon(),
offset = [
viewport[2][0] - point[0],
(viewport[1][1] - 30) - point[1] // 30 to account for the infoblock
];
viewport = geoExtent(context.projection.clipExtent()).polygon();
// offset = [
// viewport[2][0] - point[0],
// (viewport[1][1] - 30) - point[1] // 30 to account for the infoblock
// ];
if (geoPointInPolygon(point, viewport)) {
editMenu
.center(point)
.offset(offset);
editMenu.center(point);
// .offset(offset);
}
}
}
@@ -446,8 +445,8 @@ export function modeSelect(context, selectedIDs) {
selectElements();
var show = d3.event;
var rtClick = d3.event && d3.event.type === 'contextmenu';
var rtClick = d3.event && d3.event.type === 'contextmenu';
if (show) {
positionMenu();
}

View File

@@ -1,20 +1,27 @@
import * as d3 from 'd3';
import { geoRoundCoords } from '../geo/index';
import { textDirection } from '../util/locale';
import { uiTooltipHtml } from './tooltipHtml';
export function uiEditMenu(context, operations) {
var rect,
menu,
var menu,
center = [0, 0],
offset = [0, 0],
tooltip;
var p = 8, // top padding
l = 10, // left padding
h = 15, // height of icon
m = 4, // top margin
a1 = 2 * m + operations.length * (2 * p + h);
var p = 8, // top padding
m = 4, // top margin
h = 15, // height of icon
vpBottomMargin = 45, // viewport bottom margin
vpSideMargin = 35, // viewport side margin
buttonWidth = 44,
buttonHeight = (2 * p + h),
menuWidth = buttonWidth,
menuHeight = (2 * m) + operations.length * buttonHeight,
menuSideMargin = 10,
tooltipWidth = 200,
tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents
var editMenu = function (selection) {
@@ -22,46 +29,48 @@ export function uiEditMenu(context, operations) {
selection.node().parentNode.focus();
function click(operation) {
d3.event.stopPropagation();
if (operation.disabled()) return;
operation();
editMenu.close();
var isRTL = textDirection === 'rtl',
viewport = context.surfaceRect();
if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) {
// menu is going left-to-right and near right viewport edge, go left instead
isRTL = true;
} else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) {
// menu is going right-to-left and near left viewport edge, go right instead
isRTL = false;
}
offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin);
if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) {
// menu is near bottom viewport edge, shift upwards
offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin);
}
var origin = [ center[0] + offset[0], center[1] + offset[1] ];
menu = selection
.append('g')
.attr('class', 'edit-menu')
.attr('transform', 'translate(' + [center[0] + l, center[1]] + ')')
.attr('transform', 'translate(' + origin + ')')
.attr('opacity', 0);
menu
.transition()
.attr('opacity', 1);
rect = menu
.append('g')
.attr('class', 'edit-menu-rectangle')
.attr('transform', function () {
var pos = [0, 0];
if (offset[1] <= a1) {
pos = [0, offset[1] - a1];
}
return 'translate(' + pos + ')';
});
rect
menu
.append('rect')
.attr('class', 'edit-menu-background')
.attr('x', 4)
.attr('rx', 4)
.attr('ry', 4)
.attr('width', 44)
.attr('height', a1)
.attr('width', menuWidth)
.attr('height', menuHeight)
.attr('stroke-linecap', 'round');
var button = rect.selectAll()
var button = menu.selectAll('.edit-menu-item')
.data(operations)
.enter()
.append('g')
@@ -70,14 +79,15 @@ export function uiEditMenu(context, operations) {
.attr('transform', function (d, i) {
return 'translate(' + geoRoundCoords([
0,
m + i * (2 * p + h)]).join(',') + ')';
m + i * buttonHeight
]).join(',') + ')';
});
button
.append('rect')
.attr('x', 4)
.attr('width', 44)
.attr('height', 2 * p + h)
.attr('width', buttonWidth)
.attr('height', buttonHeight)
.on('click', click)
.on('mousedown', mousedown)
.on('mouseover', mouseover)
@@ -96,27 +106,44 @@ export function uiEditMenu(context, operations) {
.append('div')
.attr('class', 'tooltip-inner edit-menu-tooltip');
function click(operation) {
d3.event.stopPropagation();
if (operation.disabled()) return;
operation();
editMenu.close();
}
function mousedown() {
d3.event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
d3.event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
}
function mouseover(d, i) {
var width = 260;
var rect = context.surfaceRect(),
pos = [
offset[0] < width ? center[0] - 255 : center[0],
offset[1] <= a1 ? m + center[1] - (a1 - offset[1]) : m + center[1]
],
top = rect.top + i * (2 * p + h) + pos[1],
left = rect.left + (64) + pos[0];
var j = i;
// fix tooltip overflow on y axis
while (top - center[1] + 90 > offset[1] && j !== 0) {
top = rect.top + (--j) * (2 * p + h) + pos[1];
}
var tipX, tipY;
if (!isRTL) {
tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
} else {
tipX = viewport.left + origin[0] - 4 - tooltipWidth;
}
if (tipX + tooltipWidth > viewport.right) {
// tip is going left-to-right and near right viewport edge, go left instead
tipX = viewport.left + origin[0] - 4 - tooltipWidth;
} else if (tipX < viewport.left) {
// tip is going right-to-left and near left viewport edge, go right instead
tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
}
tipY = viewport.top + origin[1] + (i * buttonHeight);
if (tipY + tooltipHeight > viewport.bottom) {
// tip is near bottom viewport edge, shift upwards
tipY -= tipY + tooltipHeight - viewport.bottom;
}
tooltip
.style('top', top + 'px')
.style('left', left+ 'px')
.style('left', tipX + 'px')
.style('top', tipY + 'px')
.style('display', 'block')
.html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
}
@@ -148,11 +175,6 @@ export function uiEditMenu(context, operations) {
return editMenu;
};
editMenu.offset = function (_) {
if (!arguments.length) return offset;
offset = _;
return editMenu;
};
return editMenu;
}