mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 05:30:35 +02:00
- The sidebar can be now be resized by dragging the divider (closes #3447)
- Dragging the sidebar below a minimum size collapses it - A button in the top toolbar lets you uncollapse the sidebar, complete with icon and tooltip - Double-clicking the divider toggles the sidebar collapse - Collapse-toggling is animated - Selecting a feature or ending an add-feature mode auto-opens the sidebar - Photoviewer UI has been moved from init.js to photoviewer.js - The photoviewer now has a slight margin to set it away from the sidebar - The undo/redo, save, and progress indicator controls are now floated to the right - The save count has been redesigned to visually integrate with the save button - When the sidebar is collapsed, the mode buttons are centered - Full right-to-left layout support for all of the above
This commit is contained in:
+6
-2
@@ -1,12 +1,17 @@
|
||||
/* photo viewer div */
|
||||
#photoviewer {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
bottom: 40px;
|
||||
left: 10px;
|
||||
width: 330px;
|
||||
height: 250px;
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
[dir='rtl'] #photoviewer {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1600px) {
|
||||
#photoviewer {
|
||||
@@ -345,4 +350,3 @@ label.streetside-hires {
|
||||
background: rgba(0,0,0,0.85);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
+103
-67
@@ -83,17 +83,9 @@ body {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.limiter {
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
opacity: .5;
|
||||
float: right;
|
||||
}
|
||||
[dir='rtl'] .spinner {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.spinner img {
|
||||
@@ -446,6 +438,13 @@ button.minor:hover {
|
||||
padding-right: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
[dir='rtl'] .button-wrap {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.button-wrap button {
|
||||
white-space: nowrap;
|
||||
padding: 0px 8px;
|
||||
}
|
||||
|
||||
.button-wrap button:only-child {
|
||||
width: 100%;
|
||||
@@ -456,7 +455,6 @@ button.minor:hover {
|
||||
}
|
||||
[dir='rtl'] .button-wrap:last-of-type {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.joined button {
|
||||
@@ -511,51 +509,38 @@ button.secondary-action:focus,
|
||||
button.secondary-action:hover {
|
||||
background: #cccccc;
|
||||
}
|
||||
.button-wrap.sidebar-collapse,
|
||||
.button-wrap.save-wrap {
|
||||
min-width: 33.3333%;
|
||||
}
|
||||
.button-wrap.modes {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button.undo-button,
|
||||
button.redo-button {
|
||||
width: 44px;
|
||||
}
|
||||
button.save {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
}
|
||||
button.save .save-inner-wrap {
|
||||
flex: 1;
|
||||
}
|
||||
button.save .count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button.save.has-count .count {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
background: #fff;
|
||||
border-color: #fff;
|
||||
opacity: 0.5;
|
||||
display: inline-block;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
height: 30px;
|
||||
line-height: 12px;
|
||||
border-radius: 4px;
|
||||
margin: auto;
|
||||
margin-left: 9.3333%;
|
||||
border: 0px solid rgba(51, 51, 51, 0.2);
|
||||
border-left-width: 1px;
|
||||
padding: 0px 12px;
|
||||
}
|
||||
[dir='rtl'] button.save.has-count .count {
|
||||
margin-left: auto;
|
||||
margin-right: 8%;
|
||||
}
|
||||
|
||||
button.save.has-count .count::before {
|
||||
content: "";
|
||||
margin: auto;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
border-top: 6px solid transparent;
|
||||
border-bottom: 6px solid transparent;
|
||||
border-right-width: 6px;
|
||||
border-right-style: solid;
|
||||
border-right-color: inherit;
|
||||
}
|
||||
[dir='rtl'] button.save.has-count .count::before {
|
||||
border-left: 6px solid rgba(255,255,255,.5);
|
||||
border-right: none;
|
||||
left: auto;
|
||||
right: -6px;
|
||||
border-left-width: 0px;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
.help-wrap svg.icon.pre-text.add-note,
|
||||
@@ -637,21 +622,58 @@ button.add-note svg.icon {
|
||||
/* Toolbar / Persistent UI Elements
|
||||
------------------------------------------------------- */
|
||||
#bar {
|
||||
position: fixed;
|
||||
padding: 10px 0;
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 60px;
|
||||
z-index: 9;
|
||||
min-width: 768px;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
[dir='rtl'] #bar .spacer,
|
||||
[dir='rtl'] #bar .button-wrap,
|
||||
[dir='rtl'] #bar .button-wrap button {
|
||||
float: right;
|
||||
}
|
||||
#bar .center-area,
|
||||
#bar .trailing-area {
|
||||
min-width: 50%;
|
||||
}
|
||||
.sidebar-collapsed #bar .leading-area,
|
||||
.sidebar-collapsed #bar .center-area,
|
||||
.sidebar-collapsed #bar .trailing-area {
|
||||
min-width: 33.3333%;
|
||||
}
|
||||
#bar .center-area {
|
||||
float: left;
|
||||
}
|
||||
[dir='rtl'] #bar .center-area {
|
||||
float: right;
|
||||
}
|
||||
.sidebar-collapsed #bar .center-area {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
float: none;
|
||||
}
|
||||
#bar .leading-area {
|
||||
float: left;
|
||||
display: none;
|
||||
}
|
||||
[dir='rtl'] #bar .leading-area {
|
||||
float: right;
|
||||
}
|
||||
.sidebar-collapsed #bar .leading-area {
|
||||
display: inline-block;
|
||||
}
|
||||
#bar .trailing-area {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
[dir='rtl'] #bar .trailing-area {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
/* Header for modals / panes
|
||||
@@ -779,6 +801,26 @@ a.hide-toggle {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#sidebar-resizer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -6px;
|
||||
height: 100%;
|
||||
width: 6px;
|
||||
cursor: col-resize;
|
||||
}
|
||||
.sidebar-collapsed #sidebar-resizer {
|
||||
/* make target wider to avoid the user accidentally resizing window */
|
||||
width: 10px;
|
||||
right: -10px;
|
||||
}
|
||||
[dir='rtl'] #sidebar-resizer {
|
||||
right: auto;
|
||||
left: -6px;
|
||||
}
|
||||
.sidebar-collapsed[dir='rtl'] #sidebar-resizer {
|
||||
left: -10px;
|
||||
}
|
||||
|
||||
/* Sidebar / Inspector
|
||||
------------------------------------------------------- */
|
||||
@@ -786,13 +828,16 @@ a.hide-toggle {
|
||||
position: relative;
|
||||
float: left;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
background: #f6f6f6;
|
||||
-ms-user-select: element;
|
||||
border: 0px solid #ccc;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
[dir='rtl'] #sidebar {
|
||||
float: right;
|
||||
border-right-width: 0px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.sidebar-component {
|
||||
@@ -828,6 +873,8 @@ a.hide-toggle {
|
||||
.inspector-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inspector-hidden {
|
||||
@@ -2620,9 +2667,10 @@ input.key-trap {
|
||||
/* Fullscreen Button (disabled)
|
||||
------------------------------------------------------- */
|
||||
div.full-screen {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
margin-right: 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.full-screen .tooltip {
|
||||
@@ -4261,6 +4309,7 @@ svg.mouseclick use.right {
|
||||
display: none;
|
||||
color: #333;
|
||||
font-size: 12px;
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
.tooltip.in {
|
||||
@@ -4459,13 +4508,6 @@ svg.mouseclick use.right {
|
||||
}
|
||||
|
||||
/* Move over tooltips that are near the edge of screen */
|
||||
.add-point .tooltip {
|
||||
left: 33.3333% !important;
|
||||
}
|
||||
[dir='rtl'] .add-point .tooltip {
|
||||
left: inherit !important;
|
||||
}
|
||||
|
||||
.add-point .tooltip .tooltip-arrow {
|
||||
left: 60px;
|
||||
}
|
||||
@@ -4590,10 +4632,6 @@ li.hide + li.version .badge .tooltip .tooltip-arrow {
|
||||
|
||||
/* Media Queries
|
||||
------------------------------------------------------- */
|
||||
@media only screen and (max-width: 840px) {
|
||||
/* override hide for save button */
|
||||
#bar .save .label { display: block;}
|
||||
}
|
||||
@media screen and (max-width: 1200px) {
|
||||
.user-list { display: none !important; }
|
||||
}
|
||||
@@ -4797,5 +4835,3 @@ li.hide + li.version .badge .tooltip .tooltip-arrow {
|
||||
width: 100px;
|
||||
color: #7092ff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -294,6 +294,9 @@ en:
|
||||
loading_auth: "Connecting to OpenStreetMap..."
|
||||
report_a_bug: Report a bug
|
||||
help_translate: Help translate
|
||||
sidebar_button:
|
||||
title: Sidebar
|
||||
tooltip: Open the sidebar.
|
||||
feature_info:
|
||||
hidden_warning: "{count} hidden features"
|
||||
hidden_details: "These features are currently hidden: {details}"
|
||||
|
||||
Vendored
+4
@@ -373,6 +373,10 @@
|
||||
"loading_auth": "Connecting to OpenStreetMap...",
|
||||
"report_a_bug": "Report a bug",
|
||||
"help_translate": "Help translate",
|
||||
"sidebar_button": {
|
||||
"title": "Sidebar",
|
||||
"tooltip": "Open the sidebar."
|
||||
},
|
||||
"feature_info": {
|
||||
"hidden_warning": "{count} hidden features",
|
||||
"hidden_details": "These features are currently hidden: {details}"
|
||||
|
||||
+52
-136
@@ -2,7 +2,6 @@ import {
|
||||
event as d3_event,
|
||||
select as d3_select
|
||||
} from 'd3-selection';
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
|
||||
import { d3keybinding as d3_keybinding } from '../lib/d3.keybinding.js';
|
||||
|
||||
@@ -11,10 +10,8 @@ import { tooltip } from '../util/tooltip';
|
||||
|
||||
import { behaviorHash } from '../behavior';
|
||||
import { modeBrowse } from '../modes';
|
||||
import { services } from '../services';
|
||||
import { svgDefs, svgIcon } from '../svg';
|
||||
import { utilGetDimensions } from '../util/dimensions';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
import { uiAccount } from './account';
|
||||
import { uiAttribution } from './attribution';
|
||||
@@ -31,6 +28,7 @@ import { uiMapData } from './map_data';
|
||||
import { uiMapInMap } from './map_in_map';
|
||||
import { uiModes } from './modes';
|
||||
import { uiNotice } from './notice';
|
||||
import { uiPhotoviewer } from './photoviewer';
|
||||
import { uiRestore } from './restore';
|
||||
import { uiSave } from './save';
|
||||
import { uiScale } from './scale';
|
||||
@@ -47,8 +45,6 @@ import { uiCmd } from './cmd';
|
||||
|
||||
export function uiInit(context) {
|
||||
var uiInitCounter = 0;
|
||||
var dispatch = d3_dispatch('photoviewerResize');
|
||||
|
||||
|
||||
function render(container) {
|
||||
container
|
||||
@@ -71,7 +67,6 @@ export function uiInit(context) {
|
||||
container
|
||||
.append('div')
|
||||
.attr('id', 'sidebar')
|
||||
.attr('class', 'col4')
|
||||
.call(ui.sidebar);
|
||||
|
||||
var content = container
|
||||
@@ -95,38 +90,55 @@ export function uiInit(context) {
|
||||
.call(uiInfo(context))
|
||||
.call(uiNotice(context));
|
||||
|
||||
var leadingArea = bar
|
||||
.append('div')
|
||||
.attr('class', 'leading-area');
|
||||
|
||||
var sidebarButton = leadingArea
|
||||
.append('div')
|
||||
.attr('class', 'button-wrap sidebar-collapse')
|
||||
.append('button')
|
||||
.attr('class', 'col12')
|
||||
.attr('tabindex', -1)
|
||||
.on('click', ui.sidebar.toggleCollapse)
|
||||
.call(tooltip().title(t('sidebar_button.tooltip')).placement('bottom'));
|
||||
var iconSuffix = textDirection === 'rtl' ? 'right' : 'left';
|
||||
sidebarButton
|
||||
.call(svgIcon('#iD-icon-sidebar-'+iconSuffix, 'pre-text'))
|
||||
.append('span')
|
||||
.attr('class', 'label')
|
||||
.text(t('sidebar_button.title'));
|
||||
|
||||
bar
|
||||
.append('div')
|
||||
.attr('class', 'spacer col4');
|
||||
|
||||
var limiter = bar.append('div')
|
||||
.attr('class', 'limiter');
|
||||
|
||||
limiter
|
||||
.attr('class', 'center-area')
|
||||
.append('div')
|
||||
.attr('class', 'button-wrap joined col3')
|
||||
.call(uiModes(context), limiter);
|
||||
.attr('class', 'modes button-wrap joined')
|
||||
.call(uiModes(context), bar);
|
||||
|
||||
limiter
|
||||
var trailingArea = bar
|
||||
.append('div')
|
||||
.attr('class', 'button-wrap joined col1')
|
||||
.call(uiUndoRedo(context));
|
||||
.attr('class', 'trailing-area');
|
||||
|
||||
limiter
|
||||
.append('div')
|
||||
.attr('class', 'button-wrap col1')
|
||||
.call(uiSave(context));
|
||||
|
||||
bar
|
||||
trailingArea
|
||||
.append('div')
|
||||
.attr('class', 'full-screen')
|
||||
.call(uiFullScreen(context));
|
||||
|
||||
bar
|
||||
trailingArea
|
||||
.append('div')
|
||||
.attr('class', 'spinner')
|
||||
.call(uiSpinner(context));
|
||||
|
||||
trailingArea
|
||||
.append('div')
|
||||
.attr('class', 'button-wrap joined')
|
||||
.call(uiUndoRedo(context));
|
||||
|
||||
trailingArea
|
||||
.append('div')
|
||||
.attr('class', 'button-wrap save-wrap')
|
||||
.call(uiSave(context));
|
||||
|
||||
var controls = bar
|
||||
.append('div')
|
||||
@@ -242,46 +254,12 @@ export function uiInit(context) {
|
||||
.call(uiContributors(context));
|
||||
|
||||
|
||||
var photoviewer = content
|
||||
content
|
||||
.append('div')
|
||||
.attr('id', 'photoviewer')
|
||||
.classed('al', true) // 'al'=left, 'ar'=right
|
||||
.classed('hide', true);
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'thumb-hide')
|
||||
.on('click', function () {
|
||||
if (services.streetside) { services.streetside.hideViewer(); }
|
||||
if (services.mapillary) { services.mapillary.hideViewer(); }
|
||||
if (services.openstreetcam) { services.openstreetcam.hideViewer(); }
|
||||
})
|
||||
.append('div')
|
||||
.call(svgIcon('#iD-icon-close'));
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-xy')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnX: true, resizeOnY: true })
|
||||
);
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-x')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnX: true })
|
||||
);
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-y')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnY: true })
|
||||
);
|
||||
.classed('hide', true)
|
||||
.call(ui.photoviewer);
|
||||
|
||||
var mapDimensions = map.dimensions();
|
||||
|
||||
@@ -295,10 +273,9 @@ export function uiInit(context) {
|
||||
};
|
||||
|
||||
d3_select(window)
|
||||
.on('resize.editor', onResize);
|
||||
|
||||
onResize();
|
||||
.on('resize.editor', ui.onResize);
|
||||
|
||||
ui.onResize();
|
||||
|
||||
var pa = 80; // pan amount
|
||||
var keybinding = d3_keybinding('main')
|
||||
@@ -350,83 +327,12 @@ export function uiInit(context) {
|
||||
}
|
||||
|
||||
|
||||
function onResize() {
|
||||
mapDimensions = utilGetDimensions(content, true);
|
||||
map.dimensions(mapDimensions);
|
||||
|
||||
// shrink photo viewer if it is too big
|
||||
// (-90 preserves space at top and bottom of map used by menus)
|
||||
var photoDimensions = utilGetDimensions(photoviewer, true);
|
||||
if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > (mapDimensions[1] - 90)) {
|
||||
var setPhotoDimensions = [
|
||||
Math.min(photoDimensions[0], mapDimensions[0]),
|
||||
Math.min(photoDimensions[1], mapDimensions[1] - 90),
|
||||
];
|
||||
|
||||
photoviewer
|
||||
.style('width', setPhotoDimensions[0] + 'px')
|
||||
.style('height', setPhotoDimensions[1] + 'px');
|
||||
|
||||
dispatch.call('photoviewerResize', photoviewer, setPhotoDimensions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function pan(d) {
|
||||
return function() {
|
||||
d3_event.preventDefault();
|
||||
context.pan(d, 100);
|
||||
};
|
||||
}
|
||||
|
||||
function buildResizeListener(target, eventName, dispatch, options) {
|
||||
var resizeOnX = !!options.resizeOnX;
|
||||
var resizeOnY = !!options.resizeOnY;
|
||||
var minHeight = options.minHeight || 240;
|
||||
var minWidth = options.minWidth || 320;
|
||||
var startX;
|
||||
var startY;
|
||||
var startWidth;
|
||||
var startHeight;
|
||||
|
||||
function startResize() {
|
||||
var mapSize = context.map().dimensions();
|
||||
|
||||
if (resizeOnX) {
|
||||
var maxWidth = mapSize[0];
|
||||
var newWidth = clamp((startWidth + d3_event.clientX - startX), minWidth, maxWidth);
|
||||
target.style('width', newWidth + 'px');
|
||||
}
|
||||
|
||||
if (resizeOnY) {
|
||||
var maxHeight = mapSize[1] - 90; // preserve space at top/bottom of map
|
||||
var newHeight = clamp((startHeight + startY - d3_event.clientY), minHeight, maxHeight);
|
||||
target.style('height', newHeight + 'px');
|
||||
}
|
||||
|
||||
dispatch.call(eventName, target, utilGetDimensions(target, true));
|
||||
}
|
||||
|
||||
function clamp(num, min, max) {
|
||||
return Math.max(min, Math.min(num, max));
|
||||
}
|
||||
|
||||
function stopResize() {
|
||||
d3_select(window)
|
||||
.on('.' + eventName, null);
|
||||
}
|
||||
|
||||
return function initResize() {
|
||||
startX = d3_event.clientX;
|
||||
startY = d3_event.clientY;
|
||||
startWidth = target.node().getBoundingClientRect().width;
|
||||
startHeight = target.node().getBoundingClientRect().height;
|
||||
|
||||
d3_select(window)
|
||||
.on('mousemove.' + eventName, startResize, false)
|
||||
.on('mouseup.' + eventName, stopResize, false);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -461,5 +367,15 @@ export function uiInit(context) {
|
||||
|
||||
ui.sidebar = uiSidebar(context);
|
||||
|
||||
return utilRebind(ui, dispatch, 'on');
|
||||
ui.photoviewer = uiPhotoviewer(context);
|
||||
|
||||
ui.onResize = function() {
|
||||
var content = d3_select('#content');
|
||||
var mapDimensions = utilGetDimensions(content, true);
|
||||
context.map().dimensions(mapDimensions);
|
||||
|
||||
ui.photoviewer.onMapResize();
|
||||
};
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
@@ -91,10 +91,6 @@ export function uiModes(context) {
|
||||
var showNotes = notesEnabled();
|
||||
var data = showNotes ? modes : modes.slice(0, 3);
|
||||
|
||||
selection
|
||||
.classed('col3', !showNotes) // 25%
|
||||
.classed('col4', showNotes); // 33%
|
||||
|
||||
var buttons = selection.selectAll('button.add-button')
|
||||
.data(data, function(d) { return d.id; });
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
event as d3_event,
|
||||
select as d3_select
|
||||
} from 'd3-selection';
|
||||
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
import { svgIcon } from '../svg';
|
||||
import { utilGetDimensions } from '../util/dimensions';
|
||||
import { utilRebind } from '../util';
|
||||
import { services } from '../services';
|
||||
|
||||
export function uiPhotoviewer(context) {
|
||||
|
||||
var dispatch = d3_dispatch('photoviewerResize');
|
||||
|
||||
function photoviewer(selection) {
|
||||
selection
|
||||
.append('button')
|
||||
.attr('class', 'thumb-hide')
|
||||
.on('click', function () {
|
||||
if (services.streetside) { services.streetside.hideViewer(); }
|
||||
if (services.mapillary) { services.mapillary.hideViewer(); }
|
||||
if (services.openstreetcam) { services.openstreetcam.hideViewer(); }
|
||||
})
|
||||
.append('div')
|
||||
.call(svgIcon('#iD-icon-close'));
|
||||
|
||||
selection
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-xy')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(selection, 'photoviewerResize', dispatch, { resizeOnX: true, resizeOnY: true })
|
||||
);
|
||||
|
||||
selection
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-x')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(selection, 'photoviewerResize', dispatch, { resizeOnX: true })
|
||||
);
|
||||
|
||||
selection
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-y')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(selection, 'photoviewerResize', dispatch, { resizeOnY: true })
|
||||
);
|
||||
|
||||
|
||||
function buildResizeListener(target, eventName, dispatch, options) {
|
||||
var resizeOnX = !!options.resizeOnX;
|
||||
var resizeOnY = !!options.resizeOnY;
|
||||
var minHeight = options.minHeight || 240;
|
||||
var minWidth = options.minWidth || 320;
|
||||
var startX;
|
||||
var startY;
|
||||
var startWidth;
|
||||
var startHeight;
|
||||
|
||||
function startResize() {
|
||||
var mapSize = context.map().dimensions();
|
||||
|
||||
if (resizeOnX) {
|
||||
var maxWidth = mapSize[0];
|
||||
var newWidth = clamp((startWidth + d3_event.clientX - startX), minWidth, maxWidth);
|
||||
target.style('width', newWidth + 'px');
|
||||
}
|
||||
|
||||
if (resizeOnY) {
|
||||
var maxHeight = mapSize[1] - 90; // preserve space at top/bottom of map
|
||||
var newHeight = clamp((startHeight + startY - d3_event.clientY), minHeight, maxHeight);
|
||||
target.style('height', newHeight + 'px');
|
||||
}
|
||||
|
||||
dispatch.call(eventName, target, utilGetDimensions(target, true));
|
||||
}
|
||||
|
||||
function clamp(num, min, max) {
|
||||
return Math.max(min, Math.min(num, max));
|
||||
}
|
||||
|
||||
function stopResize() {
|
||||
d3_select(window)
|
||||
.on('.' + eventName, null);
|
||||
}
|
||||
|
||||
return function initResize() {
|
||||
startX = d3_event.clientX;
|
||||
startY = d3_event.clientY;
|
||||
startWidth = target.node().getBoundingClientRect().width;
|
||||
startHeight = target.node().getBoundingClientRect().height;
|
||||
|
||||
d3_select(window)
|
||||
.on('mousemove.' + eventName, startResize, false)
|
||||
.on('mouseup.' + eventName, stopResize, false);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
photoviewer.onMapResize = function() {
|
||||
var photoviewer = d3_select('#photoviewer');
|
||||
var content = d3_select('#content');
|
||||
var mapDimensions = utilGetDimensions(content, true);
|
||||
// shrink photo viewer if it is too big
|
||||
// (-90 preserves space at top and bottom of map used by menus)
|
||||
var photoDimensions = utilGetDimensions(photoviewer, true);
|
||||
if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > (mapDimensions[1] - 90)) {
|
||||
var setPhotoDimensions = [
|
||||
Math.min(photoDimensions[0], mapDimensions[0]),
|
||||
Math.min(photoDimensions[1], mapDimensions[1] - 90),
|
||||
];
|
||||
|
||||
photoviewer
|
||||
.style('width', setPhotoDimensions[0] + 'px')
|
||||
.style('height', setPhotoDimensions[1] + 'px');
|
||||
|
||||
dispatch.call('photoviewerResize', photoviewer, setPhotoDimensions);
|
||||
}
|
||||
};
|
||||
|
||||
return utilRebind(photoviewer, dispatch, 'on');
|
||||
}
|
||||
+3
-3
@@ -69,9 +69,7 @@ export function uiSave(context) {
|
||||
.style('background', background);
|
||||
|
||||
button.select('span.count')
|
||||
.text(numChanges)
|
||||
.style('background', background)
|
||||
.style('border-color', background);
|
||||
.text(numChanges);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +86,8 @@ export function uiSave(context) {
|
||||
.call(tooltipBehavior);
|
||||
|
||||
button
|
||||
.append('div')
|
||||
.attr('class', 'save-inner-wrap')
|
||||
.call(svgIcon('#iD-icon-save', 'pre-text'))
|
||||
.append('span')
|
||||
.attr('class', 'label')
|
||||
|
||||
+97
-1
@@ -1,6 +1,11 @@
|
||||
import _throttle from 'lodash-es/throttle';
|
||||
|
||||
import { selectAll as d3_selectAll } from 'd3-selection';
|
||||
import { drag as d3_drag } from 'd3-drag';
|
||||
import {
|
||||
select as d3_select,
|
||||
event as d3_event,
|
||||
selectAll as d3_selectAll
|
||||
} from 'd3-selection';
|
||||
|
||||
import {
|
||||
osmEntity,
|
||||
@@ -14,6 +19,8 @@ import {
|
||||
uiNoteEditor
|
||||
} from './index';
|
||||
|
||||
import { textDirection } from '../util/locale';
|
||||
|
||||
|
||||
export function uiSidebar(context) {
|
||||
var inspector = uiInspector(context);
|
||||
@@ -25,6 +32,46 @@ export function uiSidebar(context) {
|
||||
|
||||
|
||||
function sidebar(selection) {
|
||||
|
||||
var resizer = selection
|
||||
.append('div')
|
||||
.attr('id', 'sidebar-resizer');
|
||||
|
||||
// set the initial width constraints
|
||||
selection.style('min-width', '280px');
|
||||
selection.style('max-width', '400px');
|
||||
selection.style('width', '33.3333%');
|
||||
|
||||
var container = d3_select('#id-container');
|
||||
resizer.call(d3_drag()
|
||||
.container(container.node())
|
||||
.on('drag', function() {
|
||||
|
||||
var containerWidthPx = container.node().getBoundingClientRect().width;
|
||||
|
||||
var xMarginProperty = textDirection === 'rtl' ? 'margin-right' : 'margin-left';
|
||||
|
||||
// subtact 1px so the mouse stays in the div and maintains the col-resize cursor
|
||||
var newWidthPx = textDirection === 'rtl' ? containerWidthPx - d3_event.x-1 : d3_event.x-1;
|
||||
|
||||
var shouldCollapse = newWidthPx < 280;
|
||||
container.classed('sidebar-collapsed', shouldCollapse);
|
||||
// allow large widths
|
||||
selection.style('max-width', '85%');
|
||||
if (shouldCollapse) {
|
||||
selection.style(xMarginProperty,'-400px')
|
||||
.style('width', '400px');
|
||||
}
|
||||
else {
|
||||
|
||||
var newWidthPercent = (newWidthPx / containerWidthPx) * 100;
|
||||
selection.style(xMarginProperty, null)
|
||||
.style('width', newWidthPercent+'%');
|
||||
}
|
||||
context.ui().onResize();
|
||||
})
|
||||
);
|
||||
|
||||
var featureListWrap = selection
|
||||
.append('div')
|
||||
.attr('class', 'feature-list-pane')
|
||||
@@ -93,6 +140,9 @@ export function uiSidebar(context) {
|
||||
|
||||
sidebar.select = function(id, newFeature) {
|
||||
if (!_current && id) {
|
||||
// uncollapse the sidebar to show the editor
|
||||
sidebar.toggleCollapse(false);
|
||||
|
||||
featureListWrap
|
||||
.classed('inspector-hidden', true);
|
||||
|
||||
@@ -144,6 +194,51 @@ export function uiSidebar(context) {
|
||||
if (_current) _current.remove();
|
||||
_current = null;
|
||||
};
|
||||
|
||||
sidebar.toggleCollapse = function(shouldCollapse) {
|
||||
|
||||
if (d3_event) {
|
||||
d3_event.preventDefault();
|
||||
}
|
||||
|
||||
var container = d3_select('#id-container');
|
||||
var collapsing;
|
||||
var isCollapsed = container.classed('sidebar-collapsed');
|
||||
if (typeof shouldCollapse !== 'undefined') {
|
||||
if (shouldCollapse === isCollapsed) {
|
||||
return;
|
||||
}
|
||||
collapsing = shouldCollapse;
|
||||
} else {
|
||||
collapsing = !isCollapsed;
|
||||
}
|
||||
var sidebar = d3_select('#sidebar');
|
||||
var xMarginProperty = textDirection === 'rtl' ? 'margin-right' : 'margin-left';
|
||||
if (collapsing) {
|
||||
var preSidebarWidthInPx = sidebar.node().getBoundingClientRect().width;
|
||||
sidebar.style('width', preSidebarWidthInPx+'px');
|
||||
sidebar.transition()
|
||||
.style('width', '400px')
|
||||
.style(xMarginProperty,'-400px')
|
||||
.on('end',function(){
|
||||
context.ui().onResize();
|
||||
});
|
||||
container.classed('sidebar-collapsed', true);
|
||||
} else {
|
||||
var containerWidthPx = container.node().getBoundingClientRect().width;
|
||||
var postSidebarWidthInPx = Math.max(containerWidthPx*0.333333, 280);
|
||||
sidebar.transition()
|
||||
.style('width', postSidebarWidthInPx)
|
||||
.style(xMarginProperty, '0px')
|
||||
.on('end',function(){
|
||||
sidebar.style('width', '33.3333%');
|
||||
context.ui().onResize();
|
||||
});
|
||||
container.classed('sidebar-collapsed', false);
|
||||
}
|
||||
};
|
||||
// toggle the sidebar collapse when double-clicking the resizer
|
||||
resizer.on('dblclick', sidebar.toggleCollapse);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +247,7 @@ export function uiSidebar(context) {
|
||||
sidebar.select = function() {};
|
||||
sidebar.show = function() {};
|
||||
sidebar.hide = function() {};
|
||||
sidebar.toggleCollapse = function() {};
|
||||
|
||||
return sidebar;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<rect stroke="currentColor" x="0.5" y="3.5" width="19" height="13" rx="2"></rect>
|
||||
<rect fill="currentColor" x="2" y="5" width="5" height="10"></rect>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 437 B |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<rect stroke="currentColor" x="0.5" y="3.5" width="19" height="13" rx="2"></rect>
|
||||
<rect fill="currentColor" x="13" y="5" width="5" height="10"></rect>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 438 B |
Reference in New Issue
Block a user