From 6cc524a0a0325fe357ef1c263f691c35a2a807e6 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Sat, 25 Mar 2017 00:45:42 -0400 Subject: [PATCH] Improve walkthrough tooltip placement, fix for RTL too (closes #3925) --- css/80_app.css | 19 ++++---- modules/ui/curtain.js | 81 +++++++++++++++++++++++----------- modules/ui/intro/line.js | 5 --- modules/ui/intro/navigation.js | 14 ++++-- modules/ui/intro/point.js | 3 +- modules/ui/splash.js | 1 - 6 files changed, 76 insertions(+), 47 deletions(-) diff --git a/css/80_app.css b/css/80_app.css index e2739f364..1aa0cbed2 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -3235,7 +3235,6 @@ img.tile-removing { position: absolute; display: none; color:#333; - text-align: left; font-size: 12px; } @@ -3253,6 +3252,7 @@ img.tile-removing { .tooltip.right { margin-left: 20px; + text-align: left; } .tooltip.bottom { @@ -3429,12 +3429,11 @@ img.tile-removing { .map-control .tooltip { min-width: 160px; } + /* Move over tooltips that are near the edge of screen */ .add-point .tooltip { left: 33.3333% !important; } - -.curtain-tooltip.intro-points-add .tooltip-arrow, .add-point .tooltip .tooltip-arrow { left: 60px; } @@ -3442,9 +3441,7 @@ img.tile-removing { left: auto; right: 60px; } -[dir='rtl'] .curtain-tooltip.intro-points-add .tooltip-arrow { - left: 50%; -} + /* radial menu (deprecated) */ @@ -3629,7 +3626,6 @@ img.tile-removing { } .intro-nav-wrap button.chapter .status { - margin-left: 3px; display: none; } @@ -3637,14 +3633,17 @@ img.tile-removing { display: inline-block; } - -.curtain-tooltip .tooltip-inner { +.curtain-tooltip.tooltip { text-align: left; - padding: 20px; +} +[dir='rtl'] .curtain-tooltip.tooltip { + text-align: right; } .curtain-tooltip .tooltip-inner { font-size: 15px; + position: relative; + padding: 20px; } .curtain-tooltip .tooltip-inner .bold { diff --git a/modules/ui/curtain.js b/modules/ui/curtain.js index e309b8bf9..8a7e926a3 100644 --- a/modules/ui/curtain.js +++ b/modules/ui/curtain.js @@ -1,5 +1,5 @@ import * as d3 from 'd3'; -import { utilGetDimensions } from '../util/dimensions'; +import { textDirection } from '../util/locale'; import { uiToggle } from './toggle'; @@ -64,14 +64,18 @@ export function uiCurtain() { var html = parts[0] ? '' + parts[0] + '' : ''; if (parts[1]) html += '' + parts[1] + ''; - var selection = tooltip - .classed('in', true) + var classes = 'curtain-tooltip tooltip in ' + (options.tooltipClass || ''); + tooltip + .classed(classes, true) .selectAll('.tooltip-inner') .html(html); - var dimensions = utilGetDimensions(selection, true), + // var dimensions = utilGetDimensions(selection, true), + var tip = tooltip.node().getBoundingClientRect(), w = window.innerWidth, h = window.innerHeight, + tooltipWidth = 200, + tooltipArrow = 5, side, pos; // trim box dimensions to just the portion that fits in the window.. @@ -83,32 +87,42 @@ export function uiCurtain() { } // determine tooltip placement.. - if (box.top + box.height < Math.min(100, box.width + box.left)) { + + if (box.top + box.height < 100) { + // tooltip below box.. side = 'bottom'; - pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height]; + pos = [box.left + box.width / 2 - tip.width / 2, box.top + box.height]; - } else if (box.left + box.width + 300 < w) { - side = 'right'; - pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2]; - - } else if (box.left > 300) { - side = 'left'; - pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2]; + } else if (box.top > h - 140) { + // tooltip above box.. + side = 'top'; + pos = [box.left + box.width / 2 - tip.width / 2, box.top - tip.height]; } else { - // need real tooltip height to calculate "top" placement - tooltip - .attr('class', 'curtain-tooltip tooltip in') - .call(uiToggle(true)); - var tip = tooltip.node().getBoundingClientRect(); - side = 'top'; - pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top - tip.height]; - } + // tooltip to the side of the box.. + var tipY = box.top + box.height / 2 - tip.height / 2; - pos = [ - Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10), - Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10) - ]; + if (textDirection === 'rtl') { + if (box.left - tooltipWidth - tooltipArrow < 70) { + side = 'right'; + pos = [box.left + box.width + tooltipArrow, tipY]; + + } else { + side = 'left'; + pos = [box.left - tooltipWidth - tooltipArrow, tipY]; + } + + } else { + if (box.left + box.width + tooltipArrow + tooltipWidth > w - 70) { + side = 'left'; + pos = [box.left - tooltipWidth - tooltipArrow, tipY]; + } + else { + side = 'right'; + pos = [box.left + box.width + tooltipArrow, tipY]; + } + } + } if (options.duration !== 0 || !tooltip.classed(side)) { tooltip.call(uiToggle(true)); @@ -117,7 +131,22 @@ export function uiCurtain() { tooltip .style('top', pos[1] + 'px') .style('left', pos[0] + 'px') - .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + (options.tooltipClass || '')); + .attr('class', classes + ' ' + side); + + + // shift tooltip-inner if it is very close to the top or bottom edge + // (doesn't affect the placement of the tooltip-arrow) + var shiftY = 0; + if (side === 'left' || side === 'right') { + if (pos[1] < 60) { + shiftY = 60 - pos[1]; + } + else if (pos[1] + tip.height > h - 100) { + shiftY = h - pos[1] - tip.height - 100; + } + } + tooltip.selectAll('.tooltip-inner') + .style('top', shiftY + 'px'); } else { tooltip.call(uiToggle(false)); diff --git a/modules/ui/intro/line.js b/modules/ui/intro/line.js index d4dcdf382..d1e9942e8 100644 --- a/modules/ui/intro/line.js +++ b/modules/ui/intro/line.js @@ -1,7 +1,6 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { t } from '../../util/locale'; -import { actionDeleteMultiple } from '../../actions/index'; import { utilRebind } from '../../util/rebind'; import { utilBindOnce } from '../../util/bind_once'; import { icon, pad } from './helper'; @@ -194,10 +193,6 @@ export function uiIntroLine(context, reveal) { context.on('exit.intro', null); context.map().on('move.intro drawn.intro', null); context.history().on('change.intro', null); - if (drawId) { - context.replace(actionDeleteMultiple([drawId])); - drawId = null; - } }; diff --git a/modules/ui/intro/navigation.js b/modules/ui/intro/navigation.js index 7ca405881..afefbeff3 100644 --- a/modules/ui/intro/navigation.js +++ b/modules/ui/intro/navigation.js @@ -1,5 +1,5 @@ import * as d3 from 'd3'; -import { t } from '../../util/locale'; +import { t, textDirection } from '../../util/locale'; import { utilRebind } from '../../util/rebind'; import { icon, pointBox } from './helper'; @@ -25,11 +25,19 @@ export function uiIntroNavigation(context, reveal) { } + function welcome() { + reveal('.intro-nav-wrap', 'This walkthrough will teach you the basics of editing on OpenStreetMap.'); + timeout(function() { + dragMap(); + }, 5000); + } + + function dragMap() { var dragged = false, rect = context.surfaceRect(), map = { - left: rect.left + 10, + left: rect.left + (textDirection === 'rtl' ? 60 : 10), top: rect.top + 70, width: rect.width - 70, height: rect.height - 170 @@ -129,7 +137,7 @@ export function uiIntroNavigation(context, reveal) { chapter.enter = function() { context.history().reset('initial'); - dragMap(); + welcome(); }; diff --git a/modules/ui/intro/point.js b/modules/ui/intro/point.js index 53c162f68..a03846fd5 100644 --- a/modules/ui/intro/point.js +++ b/modules/ui/intro/point.js @@ -29,8 +29,7 @@ export function uiIntroPoint(context, reveal) { function addPoint() { var tooltip = reveal('button.add-point', - t('intro.points.add', { button: icon('#icon-point', 'pre-text') }), - { tooltipClass: 'intro-points-add' }); + t('intro.points.add', { button: icon('#icon-point', 'pre-text') })); tooltip.selectAll('.tooltip-inner') .insert('svg', 'span') diff --git a/modules/ui/splash.js b/modules/ui/splash.js index e68a5f7fd..6b2eef670 100644 --- a/modules/ui/splash.js +++ b/modules/ui/splash.js @@ -1,4 +1,3 @@ -import * as d3 from 'd3'; import { t } from '../util/locale'; import { uiIntro } from './intro/index'; import { uiModal } from './modal';