diff --git a/css/80_app.css b/css/80_app.css index 88b05c3e0..87b725bf8 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -2651,20 +2651,41 @@ img.tile-removing { right: 0; bottom: 30px; width: 240px; - border-radius: 4px 0 0 0; - border-bottom: 1px solid black; -ms-user-select: element; } +.infobox h1, +.infobox h2, +.infobox h3, +.infobox h4, +.infobox h5 { + display: inline-block; + margin-bottom: 0; +} + +.infobox h1, +.infobox h2, +.infobox h3 { + color: #ff8; +} + +.widget-container { + padding-bottom: 10px; +} + +.widget-container:first-of-type, +.widget-container:first-of-type .widget-title { + border-radius: 4px 0 0 0; +} + +.widget-container:last-of-type { + padding-bottom: 0px; +} + .widget-title { padding: 5px 10px; } -.widget-title h3 { - display: inline-block; - margin-bottom: 0; -} - .widget-title button.close { float: right; height: 20px; @@ -2677,16 +2698,15 @@ img.tile-removing { width: 16px; } -.widget-content-measurement .measurement-heading { - display: block; - border-radius: 4px 0 0 0; +.widget-content { padding: 5px 10px; - height: 30px; + position: relative; } -.widget-content-measurement ul { - padding: 5px 10px; -} +.widget-content-measurement .measurement-heading { +/* display: inline-block; + height: 30px; +*/} .widget-content-measurement .button { position: absolute; @@ -2694,7 +2714,7 @@ img.tile-removing { border-radius: 2px; padding: 0 4px; color: white; - top: 40px; + top: 6px; right: 10px; } diff --git a/data/core.yaml b/data/core.yaml index 3c81c9dda..c5219023c 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -274,6 +274,10 @@ en: truncated_list: "Edits by {users} and {count} others" infobox: key: I + location: + key: L + title: Location + pointer: Pointer measurement: key: M title: Measurement diff --git a/dist/locales/en.json b/dist/locales/en.json index fd9719b20..e3140f0f8 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -350,6 +350,11 @@ }, "infobox": { "key": "I", + "location": { + "key": "L", + "title": "Location", + "pointer": "Pointer" + }, "measurement": { "key": "M", "title": "Measurement", diff --git a/modules/ui/info.js b/modules/ui/info.js index b5f7086d1..7c4046477 100644 --- a/modules/ui/info.js +++ b/modules/ui/info.js @@ -7,66 +7,82 @@ import { uiInfoWidgets } from './info/index'; export function uiInfo(context) { - var isHidden = true, - ids = Object.keys(uiInfoWidgets), + var ids = Object.keys(uiInfoWidgets), widgets = {}, - current; + active = {}; // create widgets ids.forEach(function(k) { - current = current || k; if (!widgets[k]) { widgets[k] = uiInfoWidgets[k](context); + active[k] = false; } }); - function info(selection) { function redraw() { - if (isHidden || !current) return; - var widget = widgets[current]; + var activeids = ids.filter(function(k) { return active[k]; }); - var content = selection.selectAll('.widget-content-' + current); - content.call(widget); + var containers = infobox.selectAll('.widget-container') + .data(activeids, function(k) { return k; }); + + containers.exit() + .style('opacity', 1) + .transition() + .duration(200) + .style('opacity', 0) + .on('end', function(d) { + d3.select(this) + .call(widgets[d].off) + .remove(); + }); + + var enter = containers.enter() + .append('div') + .attr('class', function(d) { return 'fillD2 widget-container widget-container-' + d; }); + + enter + .style('opacity', 0) + .transition() + .duration(200) + .style('opacity', 1); + + var title = enter + .append('div') + .attr('class', 'widget-title fillD2'); + + title + .append('h3') + .text(function(d) { return widgets[d].title; }); + + title + .append('button') + .attr('class', 'close') + .on('click', function (d) { toggle(d); }) + .call(svgIcon('#icon-close')); + + enter + .append('div') + .attr('class', function(d) { return 'widget-content widget-content-' + d; }); + + + // redraw the widgets + infobox.selectAll('.widget-content') + .each(function(d) { + d3.select(this).call(widgets[d]); + }); } - function toggle(setCurrent) { - if (setCurrent && current !== setCurrent) { - current = setCurrent; - return; - } + function toggle(which) { + if (d3.event) d3.event.preventDefault(); - if (d3.event) { - d3.event.preventDefault(); - } + if (!which) which = 'measurement'; + active[which] = !active[which]; - isHidden = !isHidden; - - if (isHidden) { - infobox - .classed('hide', false) - .style('opacity', 1) - .transition() - .duration(200) - .style('opacity', 0) - .on('end', function() { - d3.select(this).classed('hide', true); - }); - } else { - infobox - .classed('hide', false) - .style('opacity', 0); - - redraw(); - - infobox - .transition() - .duration(200) - .style('opacity', 1); - } + redraw(); } @@ -75,39 +91,9 @@ export function uiInfo(context) { infobox = infobox.enter() .append('div') - .attr('class', 'infobox fillD2' + (isHidden ? ' hide' : '')) + .attr('class', 'infobox') .merge(infobox); - - var container = infobox.selectAll('.widget-container') - .data(ids); - - container.exit() - .remove(); - - var enter = container.enter() - .append('div') - .attr('class', function(d) { return 'widget-container widget-container-' + d; }); - - var title = enter - .append('div') - .attr('class', 'widget-title fillD2'); - - title - .append('h3') - .text(function(d) { return widgets[d].title; }); - - title - .append('button') - .attr('class', 'close') - .on('click', function () { if (!isHidden) toggle(); }) - .call(svgIcon('#icon-close')); - - enter - .append('div') - .attr('class', function(d) { return 'widget-content widget-content-' + d; }); - - redraw(); var keybinding = d3keybinding('info') diff --git a/modules/ui/info/index.js b/modules/ui/info/index.js index aaa40591c..093f322b6 100644 --- a/modules/ui/info/index.js +++ b/modules/ui/info/index.js @@ -1,7 +1,10 @@ +export * from './location'; export * from './measurement'; +import { uiInfoLocation } from './location'; import { uiInfoMeasurement } from './measurement'; export var uiInfoWidgets = { + location: uiInfoLocation, measurement: uiInfoMeasurement, }; diff --git a/modules/ui/info/location.js b/modules/ui/info/location.js new file mode 100644 index 000000000..fe63eb70b --- /dev/null +++ b/modules/ui/info/location.js @@ -0,0 +1,58 @@ +import * as d3 from 'd3'; +import { t } from '../../util/locale'; + + +export function uiInfoLocation(context) { + var OSM_PRECISION = 7; + + function wrap(x, min, max) { + var d = max - min; + return ((x - min) % d + d) % d + min; + } + + function clamp(x, min, max) { + return Math.max(min, Math.min(x, max)); + } + + + function redraw(selection) { + if (d3.selectAll('.infobox.hide').size()) return; // infobox is hidden + + selection.html(''); + + var list = selection + .append('ul'); + + // Mouse coordinates + var coord = context.map().mouseCoordinates(); + var coordStr = + clamp(coord[1], -90, 90).toFixed(OSM_PRECISION) + ', ' + + wrap(coord[0], -180, 180).toFixed(OSM_PRECISION); + + list + .append('li') + .text(t('infobox.location.pointer') + ': ' + coordStr); + } + + + var widget = function(selection) { + selection.call(redraw); + + context.surface() + .on('mousemove.info-location', function() { + selection.call(redraw); + }); + }; + + widget.off = function() { + context.surface() + .on('mousemove.info-location', null); + }; + + widget.id = 'location'; + widget.title = t('infobox.location.title'); + widget.key = t('infobox.location.key'); + + + return widget; +}