diff --git a/css/80_app.css b/css/80_app.css
index 39448cc09..5f2d39d8f 100644
--- a/css/80_app.css
+++ b/css/80_app.css
@@ -5269,30 +5269,22 @@ li.hide + li.version .badge .tooltip .popover-arrow {
/* Contextual Edit Menu
------------------------------------------------------- */
-.edit-menu-tooltip {
+.edit-menu {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ background: #fff;
+ border-radius: 4px;
+ /* padding set in code */
+}
+
+.edit-menu .tooltip {
width: 200px;
}
-.edit-menu-background {
- fill: #eee;
-}
-
-.edit-menu-item rect {
- fill: #eee;
- cursor: default;
-}
-
-.edit-menu-item rect:active,
-.edit-menu-item rect:hover {
- fill: #ccc;
-}
-
-.edit-menu-item.disabled rect {
- cursor: not-allowed;
-}
-.edit-menu-item.disabled rect:hover {
- cursor: not-allowed;
- fill: #eee;
+.edit-menu-item {
+ border-radius: 0;
+ /* width and height set in code */
}
.edit-menu-item use {
diff --git a/modules/modes/select.js b/modules/modes/select.js
index 7197905f3..ce7cdf286 100644
--- a/modules/modes/select.js
+++ b/modules/modes/select.js
@@ -147,7 +147,7 @@ export function modeSelect(context, selectedIDs) {
function closeMenu() {
if (editMenu) {
- context.surface().call(editMenu.close);
+ context.map().supersurface.call(editMenu.close);
}
}
@@ -178,13 +178,13 @@ export function modeSelect(context, selectedIDs) {
// disable menu if in wide selection, for example
if (!context.map().editableDataEnabled()) return;
- context.surface().call(editMenu);
+ context.map().supersurface.call(editMenu);
}
}
function toggleMenu() {
- if (context.surface().select('.edit-menu').empty()) {
+ if (context.map().supersurface.select('.edit-menu').empty()) {
positionMenu();
showMenu();
} else {
diff --git a/modules/renderer/map.js b/modules/renderer/map.js
index eddcb2904..22b31ab8e 100644
--- a/modules/renderer/map.js
+++ b/modules/renderer/map.js
@@ -157,7 +157,7 @@ export function rendererMap(context) {
.call(_zoomerPanner.transform, projection.transform())
.on('dblclick.zoom', null); // override d3-zoom dblclick handling
- supersurface = selection.append('div')
+ map.supersurface = supersurface = selection.append('div')
.attr('class', 'supersurface')
.call(utilSetTransform, 0, 0);
@@ -602,7 +602,7 @@ export function rendererMap(context) {
function resetTransform() {
if (!_isTransformed) return false;
- surface.selectAll('.edit-menu').interrupt().remove();
+ supersurface.selectAll('.edit-menu').interrupt().remove();
utilSetTransform(supersurface, 0, 0);
_isTransformed = false;
if (context.inIntro()) {
diff --git a/modules/ui/edit_menu.js b/modules/ui/edit_menu.js
index 1795a5cd2..2d2534d8a 100644
--- a/modules/ui/edit_menu.js
+++ b/modules/ui/edit_menu.js
@@ -1,28 +1,27 @@
import { event as d3_event, select as d3_select } from 'd3-selection';
-import { geoVecAdd, geoVecFloor } from '../geo';
+import { geoVecAdd } from '../geo';
import { textDirection } from '../util/locale';
-import { uiTooltipHtml } from './tooltipHtml';
+import { uiTooltip } from './tooltip';
+import { svgIcon } from '../svg/icon';
export function uiEditMenu(context, operations) {
var menu;
var center = [0, 0];
var offset = [0, 0];
- var tooltip;
- var p = 8; // top padding
- var m = 4; // top margin
- var h = 15; // height of icon
var vpBottomMargin = 45; // viewport bottom margin
var vpSideMargin = 35; // viewport side margin
+
+ // hardcode these values to make menu positioning easier
var buttonWidth = 44;
- var buttonHeight = (2 * p + h);
+ var buttonHeight = 34;
var menuWidth = buttonWidth;
- var menuHeight = (2 * m) + operations.length * buttonHeight;
+ var verticalPadding = 4;
+
+ // offset the menu slightly from the target location
var menuSideMargin = 10;
- var tooltipWidth = 200;
- var tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents
var editMenu = function (selection) {
@@ -33,6 +32,8 @@ export function uiEditMenu(context, operations) {
var isRTL = textDirection === 'rtl';
var viewport = context.surfaceRect();
+ var menuHeight = verticalPadding * 2 + operations.length * buttonHeight;
+
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;
@@ -51,54 +52,39 @@ export function uiEditMenu(context, operations) {
var origin = geoVecAdd(center, offset);
menu = selection
- .append('g')
+ .append('div')
.attr('class', 'edit-menu')
- .attr('transform', 'translate(' + origin + ')')
+ .style('padding', verticalPadding + 'px 0')
+ .style('left', origin[0] + 'px')
+ .style('top', origin[1] + 'px')
.attr('opacity', 0);
menu
.transition()
.attr('opacity', 1);
- menu
- .append('rect')
- .attr('class', 'edit-menu-background')
- .attr('x', 4)
- .attr('rx', 4)
- .attr('ry', 4)
- .attr('width', menuWidth)
- .attr('height', menuHeight)
- .attr('stroke-linecap', 'round');
-
-
var buttons = menu.selectAll('.edit-menu-item')
.data(operations);
// enter
var buttonsEnter = buttons.enter()
- .append('g')
+ .append('button')
.attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; })
- .attr('transform', function(d, i) {
- return 'translate(' + geoVecFloor([0, m + i * buttonHeight]).join(',') + ')';
- });
-
- buttonsEnter
- .append('rect')
- .attr('x', 4)
- .attr('width', buttonWidth)
- .attr('height', buttonHeight)
+ .style('width', buttonWidth + 'px')
+ .style('height', buttonHeight + 'px')
.on('click', click)
- .on('mousedown', mousedown)
- .on('mouseover', mouseover)
- .on('mouseout', mouseout);
+ .on('mousedown', mousedown);
- buttonsEnter
- .append('use')
- .attr('class', 'operation-icon')
- .attr('width', '20')
- .attr('height', '20')
- .attr('transform', function () { return 'translate(' + [2 * p, 5] + ')'; })
- .attr('xlink:href', function (d) { return '#iD-operation-' + d.id; });
+ buttonsEnter.each(function(d) {
+ d3_select(this)
+ .call(svgIcon('#iD-operation-' + d.id, 'operation-icon'))
+ .call(uiTooltip()
+ .heading(d.title)
+ .title(d.tooltip())
+ .keys([d.keys[0]])
+ .placement('right')
+ );
+ });
// update
buttons = buttonsEnter
@@ -106,15 +92,6 @@ export function uiEditMenu(context, operations) {
.classed('disabled', function(d) { return d.disabled(); });
- tooltip = context.container()
- .append('div')
- .attr('class', 'popover tooltip edit-menu-tooltip');
-
- tooltip
- .append('div')
- .attr('class', 'popover-inner');
-
-
function click(operation) {
d3_event.stopPropagation();
if (operation.disabled()) return;
@@ -125,47 +102,6 @@ export function uiEditMenu(context, operations) {
function mousedown() {
d3_event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
}
-
- function mouseover(d, i) {
- 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('left', tipX + 'px')
- .style('top', tipY + 'px')
- .style('display', 'block')
- .selectAll('.popover-inner')
- .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
-
- // update disabled again, just in case tooltip and disabled state disagree
- // https://github.com/openstreetmap/iD/issues/6296#issuecomment-489259027
- d3_select(this.parentNode)
- .classed('disabled', d.disabled());
-
- }
-
- function mouseout() {
- tooltip.style('display', 'none');
- }
};
@@ -177,10 +113,6 @@ export function uiEditMenu(context, operations) {
.attr('opacity', 0)
.remove();
}
-
- if (tooltip) {
- tooltip.remove();
- }
};
diff --git a/modules/ui/feature_info.js b/modules/ui/feature_info.js
index 5cdac21bf..abeeca548 100644
--- a/modules/ui/feature_info.js
+++ b/modules/ui/feature_info.js
@@ -1,7 +1,6 @@
import { event as d3_event } from 'd3-selection';
import { t } from '../util/locale';
-import { uiTooltipHtml } from './tooltipHtml';
import { uiTooltip } from './tooltip';
@@ -22,9 +21,8 @@ export function uiFeatureInfo(context) {
if (hiddenList.length) {
var tooltipBehavior = uiTooltip()
.placement('top')
- .html(true)
.title(function() {
- return uiTooltipHtml(hiddenList.join('
'));
+ return hiddenList.join('
');
});
selection.append('a')
diff --git a/modules/ui/geolocate.js b/modules/ui/geolocate.js
index 97f077db5..32b0bc7d9 100644
--- a/modules/ui/geolocate.js
+++ b/modules/ui/geolocate.js
@@ -7,7 +7,6 @@ import { modeBrowse } from '../modes/browse';
import { svgIcon } from '../svg/icon';
import { uiFlash } from './flash';
import { uiLoading } from './loading';
-import { uiTooltipHtml } from './tooltipHtml';
export function uiGeolocate(context) {
var _geolocationOptions = {
@@ -89,8 +88,8 @@ export function uiGeolocate(context) {
.call(svgIcon('#iD-icon-geolocate', 'light'))
.call(uiTooltip()
.placement((textDirection === 'rtl') ? 'right' : 'left')
- .html(true)
- .title(uiTooltipHtml(t('geolocate.title'), t('geolocate.key')))
+ .title(t('geolocate.title'))
+ .keys([t('geolocate.key')])
);
context.keybinding().on(t('geolocate.key'), click);
diff --git a/modules/ui/index.js b/modules/ui/index.js
index beacd0f76..c1e7abcd5 100644
--- a/modules/ui/index.js
+++ b/modules/ui/index.js
@@ -56,7 +56,6 @@ export { uiSuccess } from './success';
export { uiTagReference } from './tag_reference';
export { uiToggle } from './toggle';
export { uiTooltip } from './tooltip';
-export { uiTooltipHtml } from './tooltipHtml';
export { uiVersion } from './version';
export { uiViewOnOSM } from './view_on_osm';
export { uiViewOnKeepRight } from './view_on_keepRight';
diff --git a/modules/ui/pane.js b/modules/ui/pane.js
index 7b32955be..a07b0e3d4 100644
--- a/modules/ui/pane.js
+++ b/modules/ui/pane.js
@@ -6,7 +6,6 @@ import {
import { svgIcon } from '../svg/icon';
import { textDirection } from '../util/locale';
import { uiTooltip } from './tooltip';
-import { uiTooltipHtml } from './tooltipHtml';
export function uiPane(id, context) {
@@ -74,8 +73,8 @@ export function uiPane(id, context) {
if (!_paneTooltip) {
_paneTooltip = uiTooltip()
.placement((textDirection === 'rtl') ? 'right' : 'left')
- .html(true)
- .title(uiTooltipHtml(_description, _key));
+ .title(_description)
+ .keys([_key]);
}
selection
diff --git a/modules/ui/panes/help.js b/modules/ui/panes/help.js
index b9aace172..163daf212 100644
--- a/modules/ui/panes/help.js
+++ b/modules/ui/panes/help.js
@@ -4,7 +4,6 @@ import { svgIcon } from '../../svg/icon';
import { uiCmd } from '../cmd';
import { uiIntro } from '../intro/intro';
import { uiShortcuts } from '../shortcuts';
-import { uiTooltipHtml } from '../tooltipHtml';
import { uiPane } from '../pane';
import { t, textDirection } from '../../util/locale';
@@ -365,8 +364,8 @@ export function uiPaneHelp(context) {
.append('li')
.attr('class', 'shortcuts')
.call(uiTooltip()
- .html(true)
- .title(uiTooltipHtml(t('shortcuts.tooltip'), '?'))
+ .title(t('shortcuts.tooltip'))
+ .keys(['?'])
.placement('top')
)
.append('a')
diff --git a/modules/ui/sections/background_list.js b/modules/ui/sections/background_list.js
index 3b41011db..3ffef95e1 100644
--- a/modules/ui/sections/background_list.js
+++ b/modules/ui/sections/background_list.js
@@ -12,7 +12,6 @@ import { uiCmd } from '../cmd';
import { uiSettingsCustomBackground } from '../settings/custom_background';
import { uiMapInMap } from '../map_in_map';
import { uiSection } from '../section';
-import { uiTooltipHtml } from '../tooltipHtml';
export function uiSectionBackgroundList(context) {
@@ -56,8 +55,8 @@ export function uiSectionBackgroundList(context) {
.attr('class', 'minimap-toggle-item')
.append('label')
.call(uiTooltip()
- .html(true)
- .title(uiTooltipHtml(t('background.minimap.tooltip'), t('background.minimap.key')))
+ .title(t('background.minimap.tooltip'))
+ .keys([t('background.minimap.key')])
.placement('top')
);
@@ -79,8 +78,8 @@ export function uiSectionBackgroundList(context) {
.attr('class', 'background-panel-toggle-item')
.append('label')
.call(uiTooltip()
- .html(true)
- .title(uiTooltipHtml(t('background.panel.tooltip'), uiCmd('⌘⇧' + t('info_panels.background.key'))))
+ .title(t('background.panel.tooltip'))
+ .keys([uiCmd('⌘⇧' + t('info_panels.background.key'))])
.placement('top')
);
@@ -127,11 +126,8 @@ export function uiSectionBackgroundList(context) {
if (d.id === previousBackgroundID()) {
item.call(uiTooltip()
.placement(placement)
- .html(true)
- .title(function() {
- var tip = '