mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-16 22:03:37 +02:00
Merge pull request #4223 from openstreetmap/request_review
Add requesting review
This commit is contained in:
@@ -8,28 +8,32 @@ iD supports several URL parameters. When constructing a URL to a standalone inst
|
||||
of iD (e.g. `http://preview.ideditor.com/release/`), the following parameters are available
|
||||
in the hash portion of the URL:
|
||||
|
||||
* `map` - A slash separated `zoom/latitude/longitude`. Example:
|
||||
`map=20.00/38.90085/-77.02271`
|
||||
* `id` - The character 'n', 'w', or 'r', followed by the OSM ID of a node,
|
||||
* __`map`__ - A slash separated `zoom/latitude/longitude`.<br/>
|
||||
_Example:_ `map=20.00/38.90085/-77.02271`
|
||||
* __`id`__ - The character 'n', 'w', or 'r', followed by the OSM ID of a node,
|
||||
way or relation, respectively. Selects the specified entity, and, unless
|
||||
a `map` parameter is also provided, centers the map on it.
|
||||
* `background` - The value from a `sourcetag` property in iD's
|
||||
* __`background`__ - The value from a `sourcetag` property in iD's
|
||||
[imagery list](https://github.com/openstreetmap/iD/blob/master/data/imagery.json),
|
||||
or a custom tile URL. A custom URL is specified in the format `custom:<url>`,
|
||||
where the URL can contain the standard tile URL placeholders `{x}`, `{y}` and
|
||||
`{z}`/`{zoom}`, `{ty}` for flipped TMS-style Y coordinates, and `{switch:a,b,c}` for
|
||||
DNS multiplexing. Example:
|
||||
`background=custom:https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png`
|
||||
* `gpx` - A custom URL for loading a gpx track. Specifying a `gpx` parameter will
|
||||
automatically enable the gpx layer for display. Example:
|
||||
`gpx=https://tasks.hotosm.org/project/592/task/16.gpx`
|
||||
* `offset` - imagery offset in meters, formatted as `east,north`. Example:
|
||||
`offset=-10,5`
|
||||
* `comment` - Prefills the changeset comment box, for use when integrating iD with
|
||||
external task management or quality assurance tools. Example:
|
||||
`comment=CAR%20crisis%2C%20refugee%20areas%20in%20Cameroon%20%23hotosm-task-592`.
|
||||
* `rtl=true` - Force iD into right-to-left mode (useful for testing).
|
||||
* `walkthrough=true` - Start the walkthrough automatically
|
||||
DNS multiplexing.<br/>
|
||||
_Example:_ `background=custom:https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png`
|
||||
* __`gpx`__ - A custom URL for loading a gpx track. Specifying a `gpx` parameter will
|
||||
automatically enable the gpx layer for display.<br/>
|
||||
_Example:_ `gpx=https://tasks.hotosm.org/project/592/task/16.gpx`
|
||||
* __`offset`__ - imagery offset in meters, formatted as `east,north`.<br/>
|
||||
_Example:_ `offset=-10,5`
|
||||
* __`comment`__ - Prefills the changeset comment. Pass a url encoded string.<br/>
|
||||
_Example:_ `comment=CAR%20crisis%2C%20refugee%20areas%20in%20Cameroon`
|
||||
* __`hashtags`__ - Prefills the changeset hashtags. Pass a url encoded list of event
|
||||
hashtags separated by commas, semicolons, or spaces. Leading '#' symbols are
|
||||
optional and will be added automatically. (Note that hashtag-like strings are
|
||||
automatically detected in the `comment`).<br/>
|
||||
_Example:_ `hashtags=%23hotosm-task-592,%23MissingMaps`
|
||||
* __`rtl=true`__ - Force iD into right-to-left mode (useful for testing).
|
||||
* __`walkthrough=true`__ - Start the walkthrough automatically
|
||||
|
||||
##### iD on openstreetmap.org (Rails Port)
|
||||
|
||||
@@ -37,14 +41,15 @@ When constructing a URL to an instance of iD embedded in the OpenStreetMap Rails
|
||||
Port (e.g. `http://www.openstreetmap.org/edit?editor=id`), the following parameters
|
||||
are available as regular URL query parameters:
|
||||
|
||||
* `map` - same as standalone
|
||||
* `lat`, `lon`, `zoom` - Self-explanatory.
|
||||
* `node`, `way`, `relation` - Select the specified entity.
|
||||
* `background` - same as standalone
|
||||
* `gpx` - same as standalone
|
||||
* `offset` - same as standalone
|
||||
* `comment` - same as standalone
|
||||
* `walkthrough` - same as standalone
|
||||
* __`map`__ - same as standalone
|
||||
* __`lat`__, __`lon`__, __`zoom`__ - Self-explanatory.
|
||||
* __`node`__, __`way`__, __`relation`__ - Select the specified entity.
|
||||
* __`background`__ - same as standalone
|
||||
* __`gpx`__ - same as standalone
|
||||
* __`offset`__ - same as standalone
|
||||
* __`comment`__ - same as standalone
|
||||
* __`hashtags`__ - same as standalone
|
||||
* __`walkthrough`__ - same as standalone
|
||||
|
||||
|
||||
## CSS selectors
|
||||
|
||||
+235
-256
@@ -225,6 +225,12 @@ input[type="radio"] {
|
||||
margin-right: 5px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
[dir='rtl'] input[type="checkbox"],
|
||||
[dir='rtl'] input[type="radio"] {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* remove bottom border radius when combobox is open */
|
||||
.combobox + * textarea:focus,
|
||||
@@ -453,23 +459,37 @@ button.minor:hover {
|
||||
.button-wrap:last-of-type {
|
||||
padding-right: 0;
|
||||
}
|
||||
[dir='rtl'] .button-wrap:last-of-type {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.joined button {
|
||||
border-radius:0;
|
||||
border-right: 1px solid rgba(0,0,0,.5);
|
||||
}
|
||||
[dir='rtl'] .joined button {
|
||||
border-left: 1px solid rgba(0,0,0,.5);
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.fillL .joined button {
|
||||
border-right: 1px solid white;
|
||||
}
|
||||
|
||||
.joined button:first-child {
|
||||
border-radius:4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
[dir='rtl'] .joined button:first-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.joined button:last-child {
|
||||
border-right-width: 0;
|
||||
border-radius:0 4px 4px 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
[dir='rtl'] .joined button:last-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
button.action {
|
||||
@@ -516,6 +536,10 @@ button.save.has-count .count {
|
||||
margin: auto;
|
||||
margin-left: 9.3333%;
|
||||
}
|
||||
[dir='rtl'] button.save.has-count .count {
|
||||
margin-left: auto;
|
||||
margin-right: 8%;
|
||||
}
|
||||
|
||||
button.save.has-count .count::before {
|
||||
content: "";
|
||||
@@ -532,6 +556,12 @@ button.save.has-count .count::before {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
|
||||
@@ -551,6 +581,10 @@ button.save.has-count .count::before {
|
||||
.icon.pre-text {
|
||||
margin-right: 5px;
|
||||
}
|
||||
[dir='rtl'] .icon.pre-text {
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.icon.light {
|
||||
color: #fff;
|
||||
@@ -583,14 +617,20 @@ button.save.has-count .count::before {
|
||||
#bar {
|
||||
position: fixed;
|
||||
padding: 10px 0;
|
||||
left:0;
|
||||
top:0;
|
||||
right:0;
|
||||
height:60px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 60px;
|
||||
z-index: 9;
|
||||
min-width: 768px;
|
||||
}
|
||||
|
||||
[dir='rtl'] #bar .spacer,
|
||||
[dir='rtl'] #bar .button-wrap,
|
||||
[dir='rtl'] #bar .button-wrap button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
/* Header for modals / panes
|
||||
------------------------------------------------------- */
|
||||
@@ -609,6 +649,10 @@ button.save.has-count .count::before {
|
||||
overflow: hidden;
|
||||
padding: 20px 20px 20px 40px;
|
||||
}
|
||||
[dir='rtl'] .header h3 {
|
||||
text-align: right;
|
||||
padding: 20px 40px 20px 20px;
|
||||
}
|
||||
|
||||
.header button,
|
||||
.modal > button {
|
||||
@@ -629,12 +673,21 @@ button.save.has-count .count::before {
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
[dir='rtl'] .entity-editor-pane .header button.preset-close,
|
||||
[dir='rtl'] .preset-list-pane .header button.preset-choose {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.entity-editor-pane .header button.preset-choose {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
[dir='rtl'] .entity-editor-pane .header button.preset-choose {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.preset-choose {
|
||||
font-size: 16px;
|
||||
@@ -649,6 +702,10 @@ button.save.has-count .count::before {
|
||||
height: 60px;
|
||||
z-index: 50;
|
||||
}
|
||||
[dir='rtl'] .modal > button {
|
||||
left: 0;
|
||||
right: unset;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
@@ -680,6 +737,9 @@ button.save.has-count .count::before {
|
||||
background: #f6f6f6;
|
||||
-ms-user-select: element;
|
||||
}
|
||||
[dir='rtl'] #sidebar {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.sidebar-component {
|
||||
position: absolute;
|
||||
@@ -736,6 +796,10 @@ button.save.has-count .count::before {
|
||||
top: 80px;
|
||||
pointer-events: none;
|
||||
}
|
||||
[dir='rtl'] #sidebar .search-header .icon {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#sidebar .search-header input {
|
||||
position: absolute;
|
||||
@@ -789,6 +853,9 @@ button.save.has-count .count::before {
|
||||
overflow: hidden;
|
||||
border-left: 1px solid rgba(0, 0, 0, .1);
|
||||
}
|
||||
[dir='rtl'] .feature-list-item .label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.feature-list-item .label .icon {
|
||||
opacity: .5;
|
||||
@@ -816,6 +883,11 @@ button.save.has-count .count::before {
|
||||
color: #666;
|
||||
padding-left: 10px;
|
||||
}
|
||||
[dir='rtl'] .feature-list-item .entity-name {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* Presets
|
||||
------------------------------------------------------- */
|
||||
@@ -940,6 +1012,19 @@ button.save.has-count .count::before {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button-wrap .preset-icon {
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button-wrap .preset-icon-28 {
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button-wrap .preset-icon-24 {
|
||||
right: 18px;
|
||||
}
|
||||
|
||||
.preset-list-button .label {
|
||||
background-color: #f6f6f6;
|
||||
text-align: left;
|
||||
@@ -955,7 +1040,15 @@ button.save.has-count .count::before {
|
||||
overflow: hidden;
|
||||
border-left: 1px solid rgba(0, 0, 0, .1);
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
}
|
||||
[dir='rtl'] .preset-list-button .label {
|
||||
text-align: right;
|
||||
left: 0;
|
||||
right: 60px;
|
||||
border-left: none;
|
||||
border-right: 1px solid rgba(0, 0, 0, .1);
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.preset-list-button:hover .label {
|
||||
background-color: #ececec;
|
||||
@@ -971,6 +1064,11 @@ button.save.has-count .count::before {
|
||||
width: 32px;
|
||||
background: #fafafa;
|
||||
}
|
||||
[dir='rtl'] .preset-list-item button.tag-reference-button {
|
||||
left: 0;
|
||||
right: auto;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.preset-list-item button.tag-reference-button:hover {
|
||||
background: #f1f1f1;
|
||||
@@ -1033,13 +1131,13 @@ button.save.has-count .count::before {
|
||||
margin: 0 20px 10px 20px;
|
||||
}
|
||||
|
||||
.preset-editor .preset-form {
|
||||
.preset-editor .form-fields-container {
|
||||
padding: 10px;
|
||||
margin: 0 10px 10px 10px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.preset-editor .preset-form:empty {
|
||||
.preset-editor .form-fields-container:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1272,6 +1370,9 @@ button.save.has-count .count::before {
|
||||
padding: 0 20px 20px 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.changeset-editor .more-fields {
|
||||
padding: 15px 20px 0 20px;
|
||||
}
|
||||
|
||||
.more-fields label {
|
||||
display: flex;
|
||||
@@ -1295,6 +1396,9 @@ button.save.has-count .count::before {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-input-wrap .col6 {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
/* preset form access */
|
||||
@@ -1754,6 +1858,10 @@ div.combobox {
|
||||
margin-left: -30px;
|
||||
vertical-align: top;
|
||||
}
|
||||
[dir='rtl'] .combobox-caret {
|
||||
margin-left: 0;
|
||||
margin-right: -30px;
|
||||
}
|
||||
|
||||
.combobox-caret::after {
|
||||
content:"";
|
||||
@@ -1926,18 +2034,17 @@ button.minor.tag-reference-loading {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.tag-reference-body p,
|
||||
.tag-reference-body img {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.tag-reference-body p:last-child {
|
||||
padding-bottom: 10px;
|
||||
.tag-reference-body .tag-reference-description {
|
||||
margin: 10px 5px 0 5px;
|
||||
}
|
||||
|
||||
.tag-reference-body a {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.tag-reference-body .tag-reference-description:last-child,
|
||||
.tag-reference-body a:last-child {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.preset-list .tag-reference-body {
|
||||
@@ -1945,41 +2052,35 @@ button.minor.tag-reference-loading {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.preset-list .tag-reference-body a {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.preset-list .tag-reference-body p,
|
||||
.preset-list .tag-reference-body img {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.raw-tag-editor .tag-reference-body {
|
||||
border-bottom: 1px solid #ccc;
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.raw-tag-editor .tag-reference-body p:last-child {
|
||||
padding-bottom: 20px;
|
||||
.raw-tag-editor .tag-row.readonly .tag-reference-body {
|
||||
background: #f6f6f6;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.raw-tag-editor .tag-reference-body a {
|
||||
padding-bottom: 20px;
|
||||
.raw-tag-editor .tag-row:not(:last-child) .tag-reference-body {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
img.wiki-image {
|
||||
.raw-tag-editor .tag-row.readonly .tag-reference-body.expanded {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
img.tag-reference-wiki-image {
|
||||
float: right;
|
||||
width: 33.3333%;
|
||||
width: -webkit-calc(33.3333% - 10px);
|
||||
width: calc(33.3333% - 10px);
|
||||
margin-left: 20px;
|
||||
margin-right: 10px;
|
||||
border-radius: 4px;
|
||||
max-height: 200px;
|
||||
margin-bottom: 20px;
|
||||
margin: 10px 5px 15px 20px;
|
||||
}
|
||||
|
||||
|
||||
/* Raw relation membership editor */
|
||||
|
||||
.raw-member-editor .member-list li:first-child,
|
||||
@@ -2057,6 +2158,10 @@ div.full-screen > button:hover {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
}
|
||||
[dir='rtl'] .map-controls {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.map-control > button {
|
||||
width: 40px;
|
||||
@@ -2078,6 +2183,9 @@ div.full-screen > button:hover {
|
||||
.zoombuttons button.zoom-in {
|
||||
border-radius: 4px 0 0 0;
|
||||
}
|
||||
[dir='rtl'] .zoombuttons button.zoom-in {
|
||||
border-radius: 0 4px 0 0;
|
||||
}
|
||||
|
||||
/* Background / Map Data Settings */
|
||||
|
||||
@@ -2088,6 +2196,9 @@ div.full-screen > button:hover {
|
||||
.background-control button {
|
||||
border-radius: 4px 0 0 0;
|
||||
}
|
||||
[dir='rtl'] .background-control button {
|
||||
border-radius: 0 4px 0 0;
|
||||
}
|
||||
|
||||
.map-data-control,
|
||||
.background-control {
|
||||
@@ -2151,6 +2262,10 @@ div.full-screen > button:hover {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[dir='rtl'] .list-item-gpx-browse svg {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
/* make sure tooltip fits in map-control panel */
|
||||
/* if too wide, placement will be wrong the first time it displays */
|
||||
.layer-list li.best .tooltip-inner {
|
||||
@@ -2188,9 +2303,13 @@ div.full-screen > button:hover {
|
||||
|
||||
.hide-toggle {
|
||||
display: block;
|
||||
padding-left:12px;
|
||||
padding-left: 12px;
|
||||
position: relative;
|
||||
}
|
||||
[dir='rtl'] .hide-toggle {
|
||||
padding-left: 0;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.hide-toggle:before {
|
||||
content: '';
|
||||
@@ -2204,6 +2323,12 @@ div.full-screen > button:hover {
|
||||
border-bottom: 4px solid transparent;
|
||||
border-left: 8px solid #7092ff;
|
||||
}
|
||||
[dir='rtl'] .hide-toggle:before {
|
||||
left: auto;
|
||||
right: 0;
|
||||
border-left: none;
|
||||
border-right: 8px solid #7092ff;
|
||||
}
|
||||
|
||||
.hide-toggle.expanded:before {
|
||||
border-top: 8px solid #7092ff;
|
||||
@@ -2211,6 +2336,11 @@ div.full-screen > button:hover {
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
[dir='rtl'] .hide-toggle.expanded:before {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
}
|
||||
|
||||
|
||||
/* Adjust Alignment controls */
|
||||
|
||||
@@ -2341,13 +2471,17 @@ div.full-screen > button:hover {
|
||||
|
||||
.opacity-options {
|
||||
background: url(img/background-pattern-opacity.png) 0 0 repeat;
|
||||
height:20px;
|
||||
width:82px;
|
||||
height: 20px;
|
||||
width: 82px;
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 20px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
[dir='rtl'] .opacity-options {
|
||||
left: 50px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.opacity-options li {
|
||||
height: 100%;
|
||||
@@ -2357,8 +2491,8 @@ div.full-screen > button:hover {
|
||||
|
||||
.opacity-options li .select-box{
|
||||
position: absolute;
|
||||
width:20px;
|
||||
height:18px;
|
||||
width: 20px;
|
||||
height: 18px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
@@ -2393,6 +2527,12 @@ div.full-screen > button:hover {
|
||||
border-left: 1px solid #CCC;
|
||||
border-radius: 0;
|
||||
}
|
||||
[dir='rtl'] .map-data-control .layer-list button,
|
||||
[dir='rtl'] .background-control .layer-list button {
|
||||
float: left;
|
||||
border-left: none;
|
||||
border-right: 1px solid #CCC;
|
||||
}
|
||||
|
||||
.map-data-control .layer-list button .icon,
|
||||
.background-control .layer-list button .icon {
|
||||
@@ -2403,6 +2543,10 @@ div.full-screen > button:hover {
|
||||
.background-control .layer-list button:first-of-type {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
[dir='rtl'] .map-data-control .layer-list button:first-of-type,
|
||||
[dir='rtl'] .background-control .layer-list button:first-of-type {
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.map-data-control .map-overlay,
|
||||
.background-control .map-overlay,
|
||||
@@ -2410,7 +2554,6 @@ div.full-screen > button:hover {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
/* Geolocator */
|
||||
|
||||
.geolocate-control {
|
||||
@@ -2420,6 +2563,9 @@ div.full-screen > button:hover {
|
||||
.geolocate-control button {
|
||||
border-radius: 0 0 0 4px;
|
||||
}
|
||||
[dir='rtl'] .geolocate-control button {
|
||||
border-radius: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.map-overlay.content {
|
||||
position: fixed;
|
||||
@@ -2429,12 +2575,20 @@ div.full-screen > button:hover {
|
||||
right: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
[dir='rtl'] .map-overlay.content {
|
||||
padding: 20px 20px 20px 50px;
|
||||
left: 0;
|
||||
right: auto !important;
|
||||
}
|
||||
|
||||
/* Help */
|
||||
|
||||
.help-control button {
|
||||
border-radius: 0 0 0 4px;
|
||||
}
|
||||
[dir='rtl'] .help-control button {
|
||||
border-radius: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.help-wrap p {
|
||||
font-size: 15px;
|
||||
@@ -3348,32 +3502,50 @@ img.tile-removing {
|
||||
float: left;
|
||||
height: 12px;
|
||||
min-width: 12px;
|
||||
font-size:12px;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
border-radius:24px;
|
||||
padding:5px;
|
||||
background:#7092ff;
|
||||
color:#fff;
|
||||
border-radius: 24px;
|
||||
padding: 5px;
|
||||
background: #7092ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mode-save .field-warning {
|
||||
background: #ffb;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.mode-save .field-warning:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mode-save .field-warning,
|
||||
.mode-save .changeset-info,
|
||||
.mode-save .request-review,
|
||||
.mode-save .commit-info {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.mode-save .changeset-list {
|
||||
border:1px solid #ccc;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background:#fff;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.mode-save .warning-section {
|
||||
background: #ffb;
|
||||
}
|
||||
|
||||
.mode-save .warning-section .changeset-list button {
|
||||
border-left: 1px solid #CCC;
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.mode-save .changeset-list li {
|
||||
position: relative;
|
||||
border-top:1px solid #ccc;
|
||||
padding:5px 10px;
|
||||
border-top: 1px solid #ccc;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -3386,8 +3558,8 @@ img.tile-removing {
|
||||
}
|
||||
|
||||
.changeset-list li span.count {
|
||||
font-size:10px;
|
||||
color:#555;
|
||||
font-size: 10px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.mode-save .commit-section .changeset-list button {
|
||||
@@ -3478,8 +3650,12 @@ img.tile-removing {
|
||||
}
|
||||
|
||||
.notice .zoom-to .icon {
|
||||
margin-top:10px;
|
||||
margin-right:10px;
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
[dir='rtl'] .notice .zoom-to .icon {
|
||||
margin-left: 10px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* Tooltips
|
||||
@@ -3691,6 +3867,10 @@ img.tile-removing {
|
||||
.add-point .tooltip {
|
||||
left: 33.3333% !important;
|
||||
}
|
||||
[dir='rtl'] .add-point .tooltip {
|
||||
left: inherit !important;
|
||||
}
|
||||
|
||||
.add-point .tooltip .tooltip-arrow {
|
||||
left: 60px;
|
||||
}
|
||||
@@ -4023,204 +4203,3 @@ li.hide + li.version .badge .tooltip .tooltip-arrow {
|
||||
color: #7092FF;
|
||||
}
|
||||
|
||||
|
||||
/* Right-to-left localization settings */
|
||||
|
||||
[dir='rtl'] #sidebar {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[dir='rtl'] #sidebar .search-header .icon {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
/* header */
|
||||
[dir='rtl'] .header h3 {
|
||||
text-align: right;
|
||||
padding: 20px 40px 20px 20px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .entity-editor-pane .header button.preset-choose {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .entity-editor-pane .header button.preset-close, [dir='rtl'] .preset-list-pane .header button.preset-choose {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
[dir='rtl'] .map-data-control .layer-list button, [dir='rtl'] .background-control .layer-list button {
|
||||
float: left;
|
||||
border-left: none;
|
||||
border-right: 1px solid #CCC;
|
||||
}
|
||||
|
||||
[dir='rtl'] .map-data-control .layer-list button:first-of-type, [dir='rtl'] .background-control .layer-list button:first-of-type {
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
/* search */
|
||||
[dir='rtl'] .feature-list-item .label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
[dir='rtl'] .feature-list-item .entity-name {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
/* preset form */
|
||||
|
||||
[dir='rtl'] .combobox-caret {
|
||||
margin-left: 0;
|
||||
margin-right: -30px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .icon.pre-text {
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .notice .zoom-to .icon {
|
||||
margin-left: 10px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button .label {
|
||||
text-align: right;
|
||||
left: 0;
|
||||
right: 60px;
|
||||
border-left: none;
|
||||
border-right: 1px solid rgba(0, 0, 0, .1);
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-item button.tag-reference-button {
|
||||
left: 0;
|
||||
right: auto;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button-wrap .preset-icon {
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button-wrap .preset-icon-28 {
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-list-button-wrap .preset-icon-24 {
|
||||
right: 18px;
|
||||
}
|
||||
|
||||
[dir='rtl'] input[type="checkbox"], [dir='rtl'] input[type="radio"] {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .preset-input-wrap .col6 {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* map control buttons */
|
||||
[dir='rtl'] .map-controls {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
[dir='rtl'] .background-control button,
|
||||
[dir='rtl'] .zoombuttons button.zoom-in {
|
||||
border-radius: 0 4px 0 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .help-control button,
|
||||
[dir='rtl'] .geolocate-control button {
|
||||
border-radius: 0 0 4px 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .list-item-gpx-browse svg {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
/* map control button overlays */
|
||||
[dir='rtl'] .map-overlay {
|
||||
padding: 20px 20px 20px 50px;
|
||||
left: 0;
|
||||
right: auto !important;
|
||||
}
|
||||
|
||||
[dir='rtl'] .opacity-options {
|
||||
left: 50px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
[dir='rtl'] .hide-toggle {
|
||||
padding-left: 0;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .hide-toggle:before {
|
||||
left: auto;
|
||||
right: 0;
|
||||
border-left: none;
|
||||
border-right: 8px solid #7092ff;
|
||||
}
|
||||
|
||||
[dir='rtl'] .hide-toggle.expanded:before {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
}
|
||||
|
||||
/* navbar */
|
||||
[dir='rtl'] #bar .spacer,
|
||||
[dir='rtl'] #bar .button-wrap,
|
||||
[dir='rtl'] #bar .button-wrap button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[dir='rtl'] .add-point .tooltip {
|
||||
left: inherit !important;
|
||||
}
|
||||
|
||||
[dir='rtl'] .button-wrap:last-of-type {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
[dir='rtl'] button.save.has-count .count {
|
||||
margin-left: auto;
|
||||
margin-right: 8%;
|
||||
}
|
||||
|
||||
[dir='rtl'] button.save.has-count .count::before {
|
||||
border-left: 6px solid rgba(255,255,255,.5);
|
||||
border-right: none;
|
||||
left: auto;
|
||||
right: -6px;
|
||||
}
|
||||
|
||||
[dir='rtl'] .joined button {
|
||||
border-left: 1px solid rgba(0,0,0,.5);
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
[dir='rtl'] .joined button:first-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
[dir='rtl'] .joined button:last-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
/* modal */
|
||||
[dir='rtl'] .modal > button {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: unset;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -254,10 +254,9 @@ en:
|
||||
rateLimit: The API is limiting anonymous connections. You can fix this by logging in.
|
||||
commit:
|
||||
title: Upload to OpenStreetMap
|
||||
description_placeholder: Brief description of your contributions (required)
|
||||
message_label: Changeset Comment
|
||||
upload_explanation: "The changes you upload will be visible on all maps that use OpenStreetMap data."
|
||||
upload_explanation_with_user: "The changes you upload as {user} will be visible on all maps that use OpenStreetMap data."
|
||||
request_review: "I would like someone to review my edits."
|
||||
save: Upload
|
||||
cancel: Cancel
|
||||
changes: "{count} Changes"
|
||||
|
||||
+11
-1
@@ -339,6 +339,11 @@ en:
|
||||
collection_times:
|
||||
# collection_times=*
|
||||
label: Collection Times
|
||||
comment:
|
||||
# comment=*
|
||||
label: Changeset Comment
|
||||
# comment field placeholder
|
||||
placeholder: Brief description of your contributions (required)
|
||||
communication_multi:
|
||||
# 'communication:=*'
|
||||
label: Communication Types
|
||||
@@ -571,6 +576,11 @@ en:
|
||||
handrail:
|
||||
# handrail=*
|
||||
label: Handrail
|
||||
hashtags:
|
||||
# hashtags=*
|
||||
label: Hashtags
|
||||
# hashtags field placeholder
|
||||
placeholder: '#example'
|
||||
height:
|
||||
# height=*
|
||||
label: Height (Meters)
|
||||
@@ -1218,7 +1228,7 @@ en:
|
||||
label: People Served
|
||||
source:
|
||||
# source=*
|
||||
label: Source
|
||||
label: Sources
|
||||
sport:
|
||||
# sport=*
|
||||
label: Sports
|
||||
|
||||
@@ -437,6 +437,12 @@
|
||||
"type": "text",
|
||||
"label": "Collection Times"
|
||||
},
|
||||
"comment": {
|
||||
"key": "comment",
|
||||
"type": "textarea",
|
||||
"label": "Changeset Comment",
|
||||
"placeholder": "Brief description of your contributions (required)"
|
||||
},
|
||||
"communication_multi": {
|
||||
"key": "communication:",
|
||||
"type": "multiCombo",
|
||||
@@ -788,6 +794,12 @@
|
||||
"type": "check",
|
||||
"label": "Handrail"
|
||||
},
|
||||
"hashtags": {
|
||||
"key": "hashtags",
|
||||
"type": "semiCombo",
|
||||
"label": "Hashtags",
|
||||
"placeholder": "#example"
|
||||
},
|
||||
"height": {
|
||||
"key": "height",
|
||||
"type": "number",
|
||||
@@ -1624,10 +1636,17 @@
|
||||
},
|
||||
"source": {
|
||||
"key": "source",
|
||||
"type": "text",
|
||||
"type": "semiCombo",
|
||||
"icon": "source",
|
||||
"universal": true,
|
||||
"label": "Source"
|
||||
"label": "Sources",
|
||||
"options": [
|
||||
"survey",
|
||||
"local knowledge",
|
||||
"gps",
|
||||
"aerial imagery",
|
||||
"streetlevel imagery"
|
||||
]
|
||||
},
|
||||
"sport_ice": {
|
||||
"key": "sport",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"key": "comment",
|
||||
"type": "textarea",
|
||||
"label": "Changeset Comment",
|
||||
"placeholder": "Brief description of your contributions (required)"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"key": "hashtags",
|
||||
"type": "semiCombo",
|
||||
"label": "Hashtags",
|
||||
"placeholder": "#example"
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
{
|
||||
"key": "source",
|
||||
"type": "text",
|
||||
"type": "semiCombo",
|
||||
"icon": "source",
|
||||
"universal": true,
|
||||
"label": "Source"
|
||||
}
|
||||
"label": "Sources",
|
||||
"options": [
|
||||
"survey",
|
||||
"local knowledge",
|
||||
"gps",
|
||||
"aerial imagery",
|
||||
"streetlevel imagery"
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+10
-3
@@ -328,10 +328,9 @@
|
||||
},
|
||||
"commit": {
|
||||
"title": "Upload to OpenStreetMap",
|
||||
"description_placeholder": "Brief description of your contributions (required)",
|
||||
"message_label": "Changeset Comment",
|
||||
"upload_explanation": "The changes you upload will be visible on all maps that use OpenStreetMap data.",
|
||||
"upload_explanation_with_user": "The changes you upload as {user} will be visible on all maps that use OpenStreetMap data.",
|
||||
"request_review": "I would like someone to review my edits.",
|
||||
"save": "Upload",
|
||||
"cancel": "Cancel",
|
||||
"changes": "{count} Changes",
|
||||
@@ -1354,6 +1353,10 @@
|
||||
"collection_times": {
|
||||
"label": "Collection Times"
|
||||
},
|
||||
"comment": {
|
||||
"label": "Changeset Comment",
|
||||
"placeholder": "Brief description of your contributions (required)"
|
||||
},
|
||||
"communication_multi": {
|
||||
"label": "Communication Types"
|
||||
},
|
||||
@@ -1566,6 +1569,10 @@
|
||||
"handrail": {
|
||||
"label": "Handrail"
|
||||
},
|
||||
"hashtags": {
|
||||
"label": "Hashtags",
|
||||
"placeholder": "#example"
|
||||
},
|
||||
"height": {
|
||||
"label": "Height (Meters)"
|
||||
},
|
||||
@@ -2094,7 +2101,7 @@
|
||||
"label": "Type"
|
||||
},
|
||||
"source": {
|
||||
"label": "Source"
|
||||
"label": "Sources"
|
||||
},
|
||||
"sport_ice": {
|
||||
"label": "Sports"
|
||||
|
||||
@@ -37,7 +37,9 @@ export function behaviorHash(context) {
|
||||
var center = map.center(),
|
||||
zoom = map.zoom(),
|
||||
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
|
||||
q = _.omit(utilStringQs(window.location.hash.substring(1)), ['comment', 'walkthrough']),
|
||||
q = _.omit(utilStringQs(window.location.hash.substring(1)),
|
||||
['comment', 'hashtags', 'walkthrough']
|
||||
),
|
||||
newParams = {};
|
||||
|
||||
delete q.id;
|
||||
@@ -99,6 +101,10 @@ export function behaviorHash(context) {
|
||||
context.storage('commentDate', Date.now());
|
||||
}
|
||||
|
||||
if (q.hashtags) {
|
||||
context.storage('hashtags', q.hashtags);
|
||||
}
|
||||
|
||||
if (q.walkthrough === 'true') {
|
||||
hash.startWalkthrough = true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { d3keybinding } from '../lib/d3.keybinding.js';
|
||||
import { t } from '../util/locale';
|
||||
import { JXON } from '../util/jxon';
|
||||
|
||||
@@ -34,6 +35,8 @@ export function modeSave(context) {
|
||||
id: 'save'
|
||||
};
|
||||
|
||||
var keybinding = d3keybinding('select');
|
||||
|
||||
var commit = uiCommit(context)
|
||||
.on('cancel', cancel)
|
||||
.on('save', save);
|
||||
@@ -360,6 +363,12 @@ export function modeSave(context) {
|
||||
context.ui().sidebar.show(commit);
|
||||
}
|
||||
|
||||
keybinding
|
||||
.on('⎋', cancel, true);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
context.container().selectAll('#content')
|
||||
.attr('class', 'inactive');
|
||||
|
||||
@@ -381,6 +390,8 @@ export function modeSave(context) {
|
||||
|
||||
|
||||
mode.exit = function() {
|
||||
keybinding.off();
|
||||
|
||||
context.container().selectAll('#content')
|
||||
.attr('class', 'active');
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { t } from '../util/locale';
|
||||
import { svgIcon } from '../svg';
|
||||
import { uiField } from './field';
|
||||
import { uiFormFields } from './form_fields';
|
||||
import { utilRebind, utilTriggerEvent } from '../util';
|
||||
|
||||
|
||||
export function uiChangesetEditor(context) {
|
||||
var dispatch = d3.dispatch('change'),
|
||||
formFields = uiFormFields(context),
|
||||
fieldsArr,
|
||||
tags,
|
||||
changesetId;
|
||||
|
||||
|
||||
|
||||
function changesetEditor(selection) {
|
||||
render(selection);
|
||||
}
|
||||
|
||||
|
||||
function render(selection) {
|
||||
var initial = false;
|
||||
|
||||
if (!fieldsArr) {
|
||||
initial = true;
|
||||
var presets = context.presets();
|
||||
|
||||
fieldsArr = [
|
||||
uiField(context, presets.field('comment'), null, { show: true, revert: false }),
|
||||
uiField(context, presets.field('source'), null, { show: false, revert: false }),
|
||||
uiField(context, presets.field('hashtags'), null, { show: false, revert: false }),
|
||||
];
|
||||
|
||||
fieldsArr.forEach(function(field) {
|
||||
field
|
||||
.on('change', function(t, onInput) {
|
||||
dispatch.call('change', field, t, onInput);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fieldsArr.forEach(function(field) {
|
||||
field
|
||||
.tags(tags);
|
||||
});
|
||||
|
||||
|
||||
selection
|
||||
.call(formFields.fieldsArr(fieldsArr));
|
||||
|
||||
|
||||
if (initial) {
|
||||
var commentField = selection.select('#preset-input-comment'),
|
||||
commentNode = commentField.node();
|
||||
|
||||
if (commentNode) {
|
||||
commentNode.focus();
|
||||
commentNode.select();
|
||||
}
|
||||
|
||||
// trigger a 'blur' event so that comment field can be cleaned
|
||||
// and checked for hashtags, even if retrieved from localstorage
|
||||
utilTriggerEvent(commentField, 'blur');
|
||||
|
||||
var osm = context.connection();
|
||||
if (osm) {
|
||||
osm.userChangesets(function (err, changesets) {
|
||||
if (err) return;
|
||||
|
||||
var comments = changesets.map(function(changeset) {
|
||||
return {
|
||||
title: changeset.tags.comment,
|
||||
value: changeset.tags.comment
|
||||
};
|
||||
});
|
||||
|
||||
commentField
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.caseSensitive(true)
|
||||
.data(_.uniqBy(comments, 'title'))
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add warning if comment mentions Google
|
||||
var hasGoogle = tags.comment.match(/google/i);
|
||||
var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning')
|
||||
.data(hasGoogle ? [0] : []);
|
||||
|
||||
commentWarning.exit()
|
||||
.transition()
|
||||
.duration(200)
|
||||
.style('opacity', 0)
|
||||
.remove();
|
||||
|
||||
var commentEnter = commentWarning.enter()
|
||||
.insert('div', '.tag-reference-body')
|
||||
.attr('class', 'field-warning comment-warning')
|
||||
.style('opacity', 0);
|
||||
|
||||
commentEnter
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#icon-alert', 'inline'))
|
||||
.attr('href', t('commit.google_warning_link'))
|
||||
.append('span')
|
||||
.text(t('commit.google_warning'));
|
||||
|
||||
commentEnter
|
||||
.transition()
|
||||
.duration(200)
|
||||
.style('opacity', 1);
|
||||
}
|
||||
|
||||
|
||||
changesetEditor.tags = function(_) {
|
||||
if (!arguments.length) return tags;
|
||||
tags = _;
|
||||
// Don't reset fieldsArr here.
|
||||
return changesetEditor;
|
||||
};
|
||||
|
||||
|
||||
changesetEditor.changesetID = function(_) {
|
||||
if (!arguments.length) return changesetId;
|
||||
if (changesetId === _) return changesetEditor;
|
||||
changesetId = _;
|
||||
fieldsArr = null;
|
||||
return changesetEditor;
|
||||
};
|
||||
|
||||
|
||||
return utilRebind(changesetEditor, dispatch, 'on');
|
||||
}
|
||||
+257
-304
@@ -1,187 +1,140 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { t } from '../util/locale';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { osmChangeset } from '../osm';
|
||||
import { modeSelect } from '../modes';
|
||||
import { svgIcon } from '../svg';
|
||||
import { tooltip } from '../util/tooltip';
|
||||
import { uiChangesetEditor } from './changeset_editor';
|
||||
import { uiCommitChanges } from './commit_changes';
|
||||
import { uiCommitWarnings } from './commit_warnings';
|
||||
import { uiRawTagEditor } from './raw_tag_editor';
|
||||
import { utilDetect } from '../util/detect';
|
||||
import {
|
||||
utilDisplayName,
|
||||
utilDisplayType,
|
||||
utilEntityOrMemberSelector,
|
||||
utilRebind,
|
||||
utilTriggerEvent
|
||||
} from '../util';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
|
||||
var changeset;
|
||||
var readOnlyTags = ['created_by', 'imagery_used', 'host', 'locale'];
|
||||
var readOnlyTags = [
|
||||
/^changesets_count$/,
|
||||
/^created_by$/,
|
||||
/^ideditor:/,
|
||||
/^imagery_used$/,
|
||||
/^host$/,
|
||||
/^locale$/
|
||||
];
|
||||
|
||||
|
||||
export function uiCommit(context) {
|
||||
var dispatch = d3.dispatch('cancel', 'save');
|
||||
var dispatch = d3.dispatch('cancel', 'save'),
|
||||
userDetails,
|
||||
_selection;
|
||||
|
||||
var changesetEditor = uiChangesetEditor(context)
|
||||
.on('change', changeTags);
|
||||
var rawTagEditor = uiRawTagEditor(context)
|
||||
.on('change', changeTags);
|
||||
var commitChanges = uiCommitChanges(context);
|
||||
var commitWarnings = uiCommitWarnings(context);
|
||||
|
||||
|
||||
function commit(selection) {
|
||||
_selection = selection;
|
||||
|
||||
var osm = context.connection();
|
||||
if (!osm) return;
|
||||
|
||||
var comment = context.storage('comment') || '',
|
||||
commentDate = +context.storage('commentDate') || 0,
|
||||
hashtags = context.storage('hashtags'),
|
||||
currDate = Date.now(),
|
||||
cutoff = 2 * 86400 * 1000; // 2 days
|
||||
|
||||
// expire stored comment and hashtags after cutoff datetime - #3947
|
||||
if (commentDate > currDate || currDate - commentDate > cutoff) {
|
||||
comment = '';
|
||||
hashtags = undefined;
|
||||
}
|
||||
|
||||
var tags;
|
||||
if (!changeset) {
|
||||
var detected = utilDetect(),
|
||||
tags = {
|
||||
created_by: ('iD ' + context.version).substr(0, 255),
|
||||
imagery_used: context.history().imageryUsed().join(';').substr(0, 255),
|
||||
host: detected.host.substr(0, 255),
|
||||
locale: detected.locale.substr(0, 255)
|
||||
};
|
||||
var detected = utilDetect();
|
||||
tags = {
|
||||
comment: comment,
|
||||
created_by: ('iD ' + context.version).substr(0, 255),
|
||||
imagery_used: context.history().imageryUsed().join(';').substr(0, 255),
|
||||
host: detected.host.substr(0, 255),
|
||||
locale: detected.locale.substr(0, 255)
|
||||
};
|
||||
|
||||
if (hashtags) {
|
||||
tags.hashtags = hashtags;
|
||||
}
|
||||
|
||||
changeset = new osmChangeset({ tags: tags });
|
||||
}
|
||||
|
||||
tags = _.clone(changeset.tags);
|
||||
|
||||
var changes = context.history().changes(),
|
||||
summary = context.history().difference().summary(),
|
||||
rawTagEditor = uiRawTagEditor(context).on('change', changeTags),
|
||||
comment = context.storage('comment') || '',
|
||||
commentDate = +context.storage('commentDate') || 0,
|
||||
currDate = Date.now(),
|
||||
cutoff = 2 * 86400 * 1000; // 2 days
|
||||
var header = selection.selectAll('.header')
|
||||
.data([0]);
|
||||
|
||||
// expire the stored comment if it is too old - #3947
|
||||
if (commentDate > currDate || currDate - commentDate > cutoff) {
|
||||
comment = '';
|
||||
}
|
||||
|
||||
selection
|
||||
header.enter()
|
||||
.append('div')
|
||||
.attr('class', 'header fillL')
|
||||
.append('h3')
|
||||
.text(t('commit.title'));
|
||||
|
||||
var body = selection
|
||||
var body = selection.selectAll('.body')
|
||||
.data([0]);
|
||||
|
||||
body = body.enter()
|
||||
.append('div')
|
||||
.attr('class', 'body');
|
||||
.attr('class', 'body')
|
||||
.merge(body);
|
||||
|
||||
var commentSection = body
|
||||
|
||||
// Changeset Section
|
||||
var changesetSection = body.selectAll('.changeset-editor')
|
||||
.data([0]);
|
||||
|
||||
changesetSection = changesetSection.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section form-field commit-form');
|
||||
.attr('class', 'modal-section changeset-editor')
|
||||
.merge(changesetSection);
|
||||
|
||||
commentSection
|
||||
.append('label')
|
||||
.attr('class', 'form-label')
|
||||
.text(t('commit.message_label'));
|
||||
|
||||
var commentField = commentSection
|
||||
.append('textarea')
|
||||
.attr('class', 'commit-form-comment')
|
||||
.attr('placeholder', t('commit.description_placeholder'))
|
||||
.attr('maxlength', 255)
|
||||
.property('value', comment)
|
||||
.on('input.save', change(true))
|
||||
.on('change.save', change())
|
||||
.on('blur.save', function() {
|
||||
context.storage('comment', this.value);
|
||||
context.storage('commentDate', Date.now());
|
||||
});
|
||||
|
||||
|
||||
commentField.node().select();
|
||||
|
||||
osm.userChangesets(function (err, changesets) {
|
||||
if (err) return;
|
||||
|
||||
var comments = changesets.map(function(changeset) {
|
||||
return {
|
||||
title: changeset.tags.comment,
|
||||
value: changeset.tags.comment
|
||||
};
|
||||
});
|
||||
|
||||
commentField
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.caseSensitive(true)
|
||||
.data(_.uniqBy(comments, 'title'))
|
||||
);
|
||||
});
|
||||
|
||||
var clippyArea = commentSection.append('div')
|
||||
.attr('class', 'clippy-area');
|
||||
|
||||
var changeSetInfo = commentSection.append('div')
|
||||
.attr('class', 'changeset-info');
|
||||
|
||||
changeSetInfo.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#icon-out-link', 'inline'))
|
||||
.attr('href', t('commit.about_changeset_comments_link'))
|
||||
.append('span')
|
||||
.text(t('commit.about_changeset_comments'));
|
||||
|
||||
|
||||
// Warnings
|
||||
var warnings = body.selectAll('div.warning-section')
|
||||
.data([context.history().validate(changes)]);
|
||||
|
||||
warnings = warnings.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section warning-section fillL2')
|
||||
.style('display', function(d) { return _.isEmpty(d) ? 'none' : null; })
|
||||
.style('background', '#ffb')
|
||||
.merge(warnings);
|
||||
|
||||
warnings
|
||||
.append('h3')
|
||||
.text(t('commit.warnings'));
|
||||
|
||||
warnings
|
||||
.append('ul')
|
||||
.attr('class', 'changeset-list');
|
||||
|
||||
var warningLi = warnings.select('ul').selectAll('li')
|
||||
.data(function(d) { return d; });
|
||||
|
||||
warningLi = warningLi.enter()
|
||||
.append('li')
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', warningClick)
|
||||
.merge(warningLi);
|
||||
|
||||
warningLi
|
||||
.call(svgIcon('#icon-alert', 'pre-text'));
|
||||
|
||||
warningLi
|
||||
.append('strong')
|
||||
.text(function(d) { return d.message; });
|
||||
|
||||
warningLi.filter(function(d) { return d.tooltip; })
|
||||
.call(tooltip()
|
||||
.title(function(d) { return d.tooltip; })
|
||||
.placement('top')
|
||||
changesetSection
|
||||
.call(changesetEditor
|
||||
.changesetID(changeset.id)
|
||||
.tags(tags)
|
||||
);
|
||||
|
||||
|
||||
// Upload Explanation
|
||||
var saveSection = body
|
||||
.append('div')
|
||||
.attr('class','modal-section save-section fillL cf');
|
||||
// Warnings
|
||||
body.call(commitWarnings);
|
||||
|
||||
var prose = saveSection
|
||||
|
||||
// Upload Explanation
|
||||
var saveSection = body.selectAll('.save-section')
|
||||
.data([0]);
|
||||
|
||||
saveSection = saveSection.enter()
|
||||
.append('div')
|
||||
.attr('class','modal-section save-section fillL cf')
|
||||
.merge(saveSection);
|
||||
|
||||
var prose = saveSection.selectAll('.commit-info')
|
||||
.data([0]);
|
||||
|
||||
prose = prose.enter()
|
||||
.append('p')
|
||||
.attr('class', 'commit-info')
|
||||
.html(t('commit.upload_explanation'));
|
||||
|
||||
.text(t('commit.upload_explanation'))
|
||||
.merge(prose);
|
||||
|
||||
osm.userDetails(function(err, user) {
|
||||
if (err) return;
|
||||
|
||||
var userLink = d3.select(document.createElement('div'));
|
||||
|
||||
userDetails = user;
|
||||
|
||||
if (user.image_url) {
|
||||
userLink
|
||||
.append('img')
|
||||
@@ -202,217 +155,217 @@ export function uiCommit(context) {
|
||||
});
|
||||
|
||||
|
||||
var requestReview = saveSection.selectAll('.request-review')
|
||||
.data([0]);
|
||||
|
||||
requestReview = requestReview.enter()
|
||||
.append('p')
|
||||
.attr('class', 'request-review')
|
||||
.text(t('commit.request_review'))
|
||||
.merge(requestReview);
|
||||
|
||||
var requestReviewField = requestReview.selectAll('input')
|
||||
.data([0]);
|
||||
|
||||
requestReviewField = requestReviewField.enter()
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.merge(requestReviewField);
|
||||
|
||||
requestReviewField
|
||||
.property('checked', isReviewRequested(changeset.tags))
|
||||
.on('change', toggleRequestReview);
|
||||
|
||||
|
||||
// Buttons
|
||||
var buttonSection = saveSection
|
||||
var buttonSection = saveSection.selectAll('.buttons')
|
||||
.data([0]);
|
||||
|
||||
// enter
|
||||
var buttonEnter = buttonSection.enter()
|
||||
.append('div')
|
||||
.attr('class', 'buttons fillL cf');
|
||||
|
||||
var cancelButton = buttonSection
|
||||
buttonEnter
|
||||
.append('button')
|
||||
.attr('class', 'secondary-action col5 button cancel-button')
|
||||
.on('click.cancel', function() {
|
||||
dispatch.call('cancel');
|
||||
});
|
||||
|
||||
cancelButton
|
||||
.append('span')
|
||||
.attr('class', 'label')
|
||||
.text(t('commit.cancel'));
|
||||
|
||||
var saveButton = buttonSection
|
||||
buttonEnter
|
||||
.append('button')
|
||||
.attr('class', 'action col5 button save-button')
|
||||
.append('span')
|
||||
.attr('class', 'label')
|
||||
.text(t('commit.save'));
|
||||
|
||||
// update
|
||||
buttonSection = buttonSection
|
||||
.merge(buttonEnter);
|
||||
|
||||
buttonSection.selectAll('.cancel-button')
|
||||
.on('click.cancel', function() {
|
||||
dispatch.call('cancel');
|
||||
});
|
||||
|
||||
buttonSection.selectAll('.save-button')
|
||||
.attr('disabled', function() {
|
||||
var n = d3.select('.commit-form textarea').node();
|
||||
var n = d3.select('#preset-input-comment').node();
|
||||
return (n && n.value.length) ? null : true;
|
||||
})
|
||||
.on('click.save', function() {
|
||||
dispatch.call('save', this, changeset);
|
||||
});
|
||||
|
||||
saveButton
|
||||
.append('span')
|
||||
.attr('class', 'label')
|
||||
.text(t('commit.save'));
|
||||
|
||||
|
||||
// Raw Tag Editor
|
||||
var tagSection = body
|
||||
var tagSection = body.selectAll('.tag-section.raw-tag-editor')
|
||||
.data([0]);
|
||||
|
||||
tagSection = tagSection.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section tag-section raw-tag-editor');
|
||||
.attr('class', 'modal-section tag-section raw-tag-editor')
|
||||
.merge(tagSection);
|
||||
|
||||
var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty();
|
||||
tagSection
|
||||
.call(rawTagEditor
|
||||
.expanded(expanded)
|
||||
.readOnlyTags(readOnlyTags)
|
||||
.tags(_.clone(changeset.tags))
|
||||
);
|
||||
|
||||
|
||||
// Changes
|
||||
var changeSection = body
|
||||
.append('div')
|
||||
.attr('class', 'commit-section modal-section fillL2');
|
||||
// Change summary
|
||||
body.call(commitChanges);
|
||||
|
||||
changeSection.append('h3')
|
||||
.text(t('commit.changes', { count: summary.length }));
|
||||
|
||||
var li = changeSection
|
||||
.append('ul')
|
||||
.attr('class', 'changeset-list')
|
||||
.selectAll('li')
|
||||
.data(summary);
|
||||
function toggleRequestReview() {
|
||||
var rr = requestReviewField.property('checked');
|
||||
updateChangeset({ review_requested: (rr ? 'yes' : undefined) });
|
||||
|
||||
li = li.enter()
|
||||
.append('li')
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', zoomToEntity)
|
||||
.merge(li);
|
||||
var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty();
|
||||
|
||||
li.each(function(d) {
|
||||
d3.select(this)
|
||||
.call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
|
||||
tagSection
|
||||
.call(rawTagEditor
|
||||
.expanded(expanded)
|
||||
.readOnlyTags(readOnlyTags)
|
||||
.tags(_.clone(changeset.tags))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function changeTags(changed, onInput) {
|
||||
if (changed.hasOwnProperty('comment')) {
|
||||
if (changed.comment === undefined) {
|
||||
changed.comment = '';
|
||||
}
|
||||
if (!onInput) {
|
||||
context.storage('comment', changed.comment);
|
||||
context.storage('commentDate', Date.now());
|
||||
}
|
||||
}
|
||||
|
||||
updateChangeset(changed, onInput);
|
||||
|
||||
if (_selection) {
|
||||
_selection.call(commit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function findHashtags(tags) {
|
||||
return _.unionBy(commentTags(), hashTags(), function (s) {
|
||||
return s.toLowerCase();
|
||||
});
|
||||
|
||||
li.append('span')
|
||||
.attr('class', 'change-type')
|
||||
.text(function(d) { return t('commit.' + d.changeType) + ' '; });
|
||||
|
||||
li.append('strong')
|
||||
.attr('class', 'entity-type')
|
||||
.text(function(d) {
|
||||
var matched = context.presets().match(d.entity, d.graph);
|
||||
return (matched && matched.name()) || utilDisplayType(d.entity.id);
|
||||
});
|
||||
|
||||
li.append('span')
|
||||
.attr('class', 'entity-name')
|
||||
.text(function(d) {
|
||||
var name = utilDisplayName(d.entity) || '',
|
||||
string = '';
|
||||
if (name !== '') string += ':';
|
||||
return string += ' ' + name;
|
||||
});
|
||||
|
||||
li.style('opacity', 0)
|
||||
.transition()
|
||||
.style('opacity', 1);
|
||||
|
||||
|
||||
// Call change() off the bat, in case a changeset
|
||||
// comment is recovered from localStorage
|
||||
utilTriggerEvent(commentField, 'input');
|
||||
|
||||
|
||||
function mouseover(d) {
|
||||
if (d.entity) {
|
||||
context.surface().selectAll(
|
||||
utilEntityOrMemberSelector([d.entity.id], context.graph())
|
||||
).classed('hover', true);
|
||||
}
|
||||
// Extract hashtags from `comment`
|
||||
function commentTags() {
|
||||
return tags.comment.match(/#[^\s\#]+/g);
|
||||
}
|
||||
|
||||
|
||||
function mouseout() {
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
// Extract and clean hashtags from `hashtags`
|
||||
function hashTags() {
|
||||
var t = tags.hashtags || '';
|
||||
return t
|
||||
.split(/[,;\s]+/)
|
||||
.map(function (s) {
|
||||
if (s[0] !== '#') { s = '#' + s; } // prepend '#'
|
||||
var matched = s.match(/#[^\s\#]+/g); // match valid hashtags
|
||||
return matched && matched[0];
|
||||
}).filter(Boolean); // exclude falsey
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function warningClick(d) {
|
||||
if (d.entity) {
|
||||
context.map().zoomTo(d.entity);
|
||||
context.enter(modeSelect(context, [d.entity.id]));
|
||||
}
|
||||
}
|
||||
function isReviewRequested(tags) {
|
||||
var rr = tags.review_requested;
|
||||
if (rr === undefined) return false;
|
||||
rr = rr.trim().toLowerCase();
|
||||
return !(rr === '' || rr === 'no');
|
||||
}
|
||||
|
||||
|
||||
function zoomToEntity(change) {
|
||||
var entity = change.entity;
|
||||
if (change.changeType !== 'deleted' &&
|
||||
context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
|
||||
context.map().zoomTo(entity);
|
||||
context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph()))
|
||||
.classed('hover', true);
|
||||
}
|
||||
}
|
||||
function updateChangeset(changed, onInput) {
|
||||
var tags = _.clone(changeset.tags);
|
||||
|
||||
_.forEach(changed, function(v, k) {
|
||||
k = k.trim().substr(0, 255);
|
||||
if (readOnlyTags.indexOf(k) !== -1) return;
|
||||
|
||||
function checkComment(comment) {
|
||||
// Save button disabled if there is no comment..
|
||||
d3.selectAll('.save-section .save-button')
|
||||
.attr('disabled', (comment.length ? null : true));
|
||||
|
||||
// Warn if comment mentions Google..
|
||||
var googleWarning = clippyArea
|
||||
.html('')
|
||||
.selectAll('a')
|
||||
.data(comment.match(/google/i) ? [true] : []);
|
||||
|
||||
googleWarning.exit()
|
||||
.remove();
|
||||
|
||||
googleWarning.enter()
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#icon-alert', 'inline'))
|
||||
.attr('href', t('commit.google_warning_link'))
|
||||
.append('span')
|
||||
.text(t('commit.google_warning'));
|
||||
}
|
||||
|
||||
|
||||
function change(onInput) {
|
||||
return function() {
|
||||
var comment = commentField.property('value').trim();
|
||||
if (!onInput) {
|
||||
commentField.property('value', comment);
|
||||
}
|
||||
|
||||
checkComment(comment);
|
||||
|
||||
var changeset = updateChangeset({ comment: comment });
|
||||
var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty();
|
||||
|
||||
tagSection
|
||||
.call(rawTagEditor
|
||||
.expanded(expanded)
|
||||
.readOnlyTags(readOnlyTags)
|
||||
.tags(_.clone(changeset.tags))
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function changeTags(changed) {
|
||||
if (changed.hasOwnProperty('comment')) {
|
||||
if (changed.comment === undefined) {
|
||||
changed.comment = '';
|
||||
}
|
||||
changed.comment = changed.comment.trim();
|
||||
commentField.property('value', changed.comment);
|
||||
}
|
||||
updateChangeset(changed);
|
||||
utilTriggerEvent(commentField, 'input');
|
||||
}
|
||||
|
||||
|
||||
function updateChangeset(changed) {
|
||||
var tags = _.clone(changeset.tags);
|
||||
|
||||
_.forEach(changed, function(v, k) {
|
||||
k = k.trim().substr(0, 255);
|
||||
if (readOnlyTags.indexOf(k) !== -1) return;
|
||||
|
||||
if (k !== '' && v !== undefined) {
|
||||
tags[k] = v.trim().substr(0, 255);
|
||||
if (k !== '' && v !== undefined) {
|
||||
if (onInput) {
|
||||
tags[k] = v;
|
||||
} else {
|
||||
delete tags[k];
|
||||
tags[k] = v.trim().substr(0, 255);
|
||||
}
|
||||
});
|
||||
|
||||
if (!_.isEqual(changeset.tags, tags)) {
|
||||
changeset = changeset.update({ tags: tags });
|
||||
} else {
|
||||
delete tags[k];
|
||||
}
|
||||
});
|
||||
|
||||
return changeset;
|
||||
if (!onInput) {
|
||||
var arr = findHashtags(tags);
|
||||
if (arr.length) {
|
||||
tags.hashtags = arr.join(';').substr(0, 255);
|
||||
context.storage('hashtags', tags.hashtags);
|
||||
} else {
|
||||
delete tags.hashtags;
|
||||
context.storage('hashtags', null);
|
||||
}
|
||||
}
|
||||
|
||||
// always update userdetails, just in case user reauthenticates as someone else
|
||||
if (userDetails && userDetails.changesets_count !== undefined) {
|
||||
tags.changesets_count = String(userDetails.changesets_count);
|
||||
|
||||
// first 100 edits - new user
|
||||
if (parseInt(tags.changesets_count, 10) < 100) {
|
||||
var s;
|
||||
s = context.storage('walkthrough_completed');
|
||||
if (s) {
|
||||
tags['ideditor:walkthrough_completed'] = s;
|
||||
}
|
||||
|
||||
s = context.storage('walkthrough_progress');
|
||||
if (s) {
|
||||
tags['ideditor:walkthrough_progress'] = s;
|
||||
}
|
||||
|
||||
s = context.storage('walkthrough_started');
|
||||
if (s) {
|
||||
tags['ideditor:walkthrough_started'] = s;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
delete tags.changesets_count;
|
||||
}
|
||||
|
||||
if (!_.isEqual(changeset.tags, tags)) {
|
||||
changeset = changeset.update({ tags: tags });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import * as d3 from 'd3';
|
||||
import { t } from '../util/locale';
|
||||
import { svgIcon } from '../svg';
|
||||
import {
|
||||
utilDisplayName,
|
||||
utilDisplayType,
|
||||
utilEntityOrMemberSelector
|
||||
} from '../util';
|
||||
|
||||
|
||||
export function uiCommitChanges(context) {
|
||||
|
||||
function commitChanges(selection) {
|
||||
|
||||
var summary = context.history().difference().summary();
|
||||
|
||||
var container = selection.selectAll('.modal-section.commit-section')
|
||||
.data([0]);
|
||||
|
||||
var containerEnter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'commit-section modal-section fillL2');
|
||||
|
||||
containerEnter
|
||||
.append('h3')
|
||||
.text(t('commit.changes', { count: summary.length }));
|
||||
|
||||
containerEnter
|
||||
.append('ul')
|
||||
.attr('class', 'changeset-list');
|
||||
|
||||
container = containerEnter
|
||||
.merge(container);
|
||||
|
||||
|
||||
var items = container.select('ul').selectAll('li')
|
||||
.data(summary);
|
||||
|
||||
var itemsEnter = items.enter()
|
||||
.append('li')
|
||||
.attr('class', 'change-item');
|
||||
|
||||
itemsEnter
|
||||
.each(function(d) {
|
||||
d3.select(this)
|
||||
.call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
|
||||
});
|
||||
|
||||
itemsEnter
|
||||
.append('span')
|
||||
.attr('class', 'change-type')
|
||||
.text(function(d) { return t('commit.' + d.changeType) + ' '; });
|
||||
|
||||
itemsEnter
|
||||
.append('strong')
|
||||
.attr('class', 'entity-type')
|
||||
.text(function(d) {
|
||||
var matched = context.presets().match(d.entity, d.graph);
|
||||
return (matched && matched.name()) || utilDisplayType(d.entity.id);
|
||||
});
|
||||
|
||||
itemsEnter
|
||||
.append('span')
|
||||
.attr('class', 'entity-name')
|
||||
.text(function(d) {
|
||||
var name = utilDisplayName(d.entity) || '',
|
||||
string = '';
|
||||
if (name !== '') {
|
||||
string += ':';
|
||||
}
|
||||
return string += ' ' + name;
|
||||
});
|
||||
|
||||
itemsEnter
|
||||
.style('opacity', 0)
|
||||
.transition()
|
||||
.style('opacity', 1);
|
||||
|
||||
items = itemsEnter
|
||||
.merge(items);
|
||||
|
||||
items
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', zoomToEntity);
|
||||
|
||||
|
||||
function mouseover(d) {
|
||||
if (d.entity) {
|
||||
context.surface().selectAll(
|
||||
utilEntityOrMemberSelector([d.entity.id], context.graph())
|
||||
).classed('hover', true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function mouseout() {
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
}
|
||||
|
||||
|
||||
function zoomToEntity(change) {
|
||||
var entity = change.entity;
|
||||
if (change.changeType !== 'deleted' &&
|
||||
context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
|
||||
context.map().zoomTo(entity);
|
||||
context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph()))
|
||||
.classed('hover', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return commitChanges;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import { t } from '../util/locale';
|
||||
import { modeSelect } from '../modes';
|
||||
import { svgIcon } from '../svg';
|
||||
import { tooltip } from '../util/tooltip';
|
||||
import { utilEntityOrMemberSelector } from '../util';
|
||||
|
||||
|
||||
export function uiCommitWarnings(context) {
|
||||
|
||||
function commitWarnings(selection) {
|
||||
|
||||
var changes = context.history().changes();
|
||||
var warnings = context.history().validate(changes);
|
||||
|
||||
var container = selection.selectAll('.warning-section')
|
||||
.data(warnings.length ? [0] : []);
|
||||
|
||||
container.exit()
|
||||
.remove();
|
||||
|
||||
var containerEnter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section warning-section fillL2');
|
||||
|
||||
containerEnter
|
||||
.append('h3')
|
||||
.text(t('commit.warnings'));
|
||||
|
||||
containerEnter
|
||||
.append('ul')
|
||||
.attr('class', 'changeset-list');
|
||||
|
||||
container = containerEnter
|
||||
.merge(container);
|
||||
|
||||
|
||||
var items = container.select('ul').selectAll('li')
|
||||
.data(warnings);
|
||||
|
||||
items.exit()
|
||||
.remove();
|
||||
|
||||
var itemsEnter = items.enter()
|
||||
.append('li')
|
||||
.attr('class', 'warning-item');
|
||||
|
||||
itemsEnter
|
||||
.call(svgIcon('#icon-alert', 'pre-text'));
|
||||
|
||||
itemsEnter
|
||||
.append('strong')
|
||||
.text(function(d) { return d.message; });
|
||||
|
||||
itemsEnter.filter(function(d) { return d.tooltip; })
|
||||
.call(tooltip()
|
||||
.title(function(d) { return d.tooltip; })
|
||||
.placement('top')
|
||||
);
|
||||
|
||||
items = itemsEnter
|
||||
.merge(items);
|
||||
|
||||
items
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', warningClick);
|
||||
|
||||
|
||||
function mouseover(d) {
|
||||
if (d.entity) {
|
||||
context.surface().selectAll(
|
||||
utilEntityOrMemberSelector([d.entity.id], context.graph())
|
||||
).classed('hover', true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function mouseout() {
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
}
|
||||
|
||||
|
||||
function warningClick(d) {
|
||||
if (d.entity) {
|
||||
context.map().zoomTo(d.entity);
|
||||
context.enter(modeSelect(context, [d.entity.id]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return commitWarnings;
|
||||
}
|
||||
+25
-16
@@ -10,7 +10,10 @@ import { utilRebind } from '../util';
|
||||
export function uiField(context, presetField, entity, options) {
|
||||
options = _.extend({
|
||||
show: true,
|
||||
wrap: true
|
||||
wrap: true,
|
||||
remove: true,
|
||||
revert: true,
|
||||
info: true
|
||||
}, options);
|
||||
|
||||
var dispatch = d3.dispatch('change'),
|
||||
@@ -24,7 +27,7 @@ export function uiField(context, presetField, entity, options) {
|
||||
dispatch.call('change', field, t, onInput);
|
||||
});
|
||||
|
||||
if (field.impl.entity) {
|
||||
if (entity && field.impl.entity) {
|
||||
field.impl.entity(entity);
|
||||
}
|
||||
|
||||
@@ -34,6 +37,7 @@ export function uiField(context, presetField, entity, options) {
|
||||
|
||||
|
||||
function isModified() {
|
||||
if (!entity) return false;
|
||||
var original = context.graph().base().entities[entity.id];
|
||||
return _.some(field.keys, function(key) {
|
||||
return original ? tags[key] !== original.tags[key] : tags[key];
|
||||
@@ -51,6 +55,7 @@ export function uiField(context, presetField, entity, options) {
|
||||
function revert(d) {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
if (!entity) return false;
|
||||
|
||||
var original = context.graph().base().entities[entity.id],
|
||||
t = {};
|
||||
@@ -96,19 +101,23 @@ export function uiField(context, presetField, entity, options) {
|
||||
.append('div')
|
||||
.attr('class', 'form-label-button-wrap');
|
||||
|
||||
wrap
|
||||
.append('button')
|
||||
.attr('class', 'remove-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#operation-delete'));
|
||||
if (options.remove) {
|
||||
wrap
|
||||
.append('button')
|
||||
.attr('class', 'remove-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#operation-delete'));
|
||||
}
|
||||
|
||||
wrap
|
||||
.append('button')
|
||||
.attr('class', 'modified-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(
|
||||
(textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
|
||||
);
|
||||
if (options.revert) {
|
||||
wrap
|
||||
.append('button')
|
||||
.attr('class', 'modified-icon')
|
||||
.attr('tabindex', -1)
|
||||
.call(
|
||||
(textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +135,7 @@ export function uiField(context, presetField, entity, options) {
|
||||
.classed('modified', isModified())
|
||||
.classed('present', isPresent())
|
||||
.each(function(d) {
|
||||
if (options.wrap) {
|
||||
if (options.wrap && options.info) {
|
||||
var referenceKey = d.key;
|
||||
if (d.type === 'multiCombo') { // lookup key without the trailing ':'
|
||||
referenceKey = referenceKey.replace(/:$/, '');
|
||||
@@ -141,7 +150,7 @@ export function uiField(context, presetField, entity, options) {
|
||||
d3.select(this)
|
||||
.call(d.impl);
|
||||
|
||||
if (options.wrap) {
|
||||
if (options.wrap && options.info) {
|
||||
d3.select(this)
|
||||
.call(reference.body)
|
||||
.select('.form-label-button-wrap')
|
||||
|
||||
@@ -161,12 +161,17 @@ export function uiFieldCombo(field, context) {
|
||||
query = country + ':';
|
||||
}
|
||||
|
||||
taginfo[fn]({
|
||||
var params = {
|
||||
debounce: (q !== ''),
|
||||
key: field.key,
|
||||
geometry: context.geometry(entity.id),
|
||||
query: query
|
||||
}, function(err, data) {
|
||||
};
|
||||
|
||||
if (entity) {
|
||||
params.geometry = context.geometry(entity.id);
|
||||
}
|
||||
|
||||
taginfo[fn](params, function(err, data) {
|
||||
if (err) return;
|
||||
if (hasCountryPrefix) {
|
||||
data = _.filter(data, function(d) {
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
import * as d3 from 'd3';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { t } from '../util/locale';
|
||||
import { utilGetSetValue, utilNoAuto } from '../util';
|
||||
|
||||
|
||||
export function uiFormFields(context) {
|
||||
var fieldsArr;
|
||||
|
||||
|
||||
function formFields(selection, klass) {
|
||||
render(selection, klass);
|
||||
}
|
||||
|
||||
|
||||
function render(selection, klass) {
|
||||
|
||||
var shown = fieldsArr.filter(function(field) { return field.isShown(); }),
|
||||
notShown = fieldsArr.filter(function(field) { return !field.isShown(); });
|
||||
|
||||
var container = selection.selectAll('.form-fields-container')
|
||||
.data([0]);
|
||||
|
||||
container = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'form-fields-container ' + (klass || ''))
|
||||
.merge(container);
|
||||
|
||||
|
||||
var fields = container.selectAll('.wrap-form-field')
|
||||
.data(shown, function(d) { return d.id; });
|
||||
|
||||
fields.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var enter = fields.enter()
|
||||
.append('div')
|
||||
.attr('class', function(d) { return 'wrap-form-field wrap-form-field-' + d.id; });
|
||||
|
||||
// Update
|
||||
fields = fields
|
||||
.merge(enter);
|
||||
|
||||
fields
|
||||
.order()
|
||||
.each(function(d) {
|
||||
d3.select(this)
|
||||
.call(d.render);
|
||||
});
|
||||
|
||||
|
||||
notShown = notShown.map(function(field) {
|
||||
return {
|
||||
title: field.label(),
|
||||
value: field.label(),
|
||||
field: field
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
var more = selection.selectAll('.more-fields')
|
||||
.data((notShown.length > 0) ? [0] : []);
|
||||
|
||||
more.exit()
|
||||
.remove();
|
||||
|
||||
more = more.enter()
|
||||
.append('div')
|
||||
.attr('class', 'more-fields')
|
||||
.append('label')
|
||||
.text(t('inspector.add_fields'))
|
||||
.merge(more);
|
||||
|
||||
|
||||
var input = more.selectAll('.value')
|
||||
.data([0]);
|
||||
|
||||
input.exit()
|
||||
.remove();
|
||||
|
||||
input = input.enter()
|
||||
.append('input')
|
||||
.attr('class', 'value')
|
||||
.attr('type', 'text')
|
||||
.call(utilNoAuto)
|
||||
.merge(input);
|
||||
|
||||
input
|
||||
.call(utilGetSetValue, '')
|
||||
.attr('placeholder', function() {
|
||||
var placeholder = [];
|
||||
for (var field in notShown) {
|
||||
placeholder.push(notShown[field].title);
|
||||
}
|
||||
return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
|
||||
})
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.data(notShown)
|
||||
.minItems(1)
|
||||
.on('accept', function (d) {
|
||||
var field = d.field;
|
||||
field.show = true;
|
||||
render(selection);
|
||||
if (field.type !== 'semiCombo' && field.type !== 'multiCombo') {
|
||||
field.focus();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
formFields.fieldsArr = function(_) {
|
||||
if (!arguments.length) return fieldsArr;
|
||||
fieldsArr = _;
|
||||
return formFields;
|
||||
};
|
||||
|
||||
|
||||
return formFields;
|
||||
}
|
||||
@@ -2,8 +2,11 @@ export { uiInit } from './init';
|
||||
export { uiAccount } from './account';
|
||||
export { uiAttribution } from './attribution';
|
||||
export { uiBackground } from './background';
|
||||
export { uiChangesetEditor } from './changeset_editor';
|
||||
export { uiCmd } from './cmd';
|
||||
export { uiCommit } from './commit';
|
||||
export { uiCommitChanges } from './commit_changes';
|
||||
export { uiCommitWarnings } from './commit_warnings';
|
||||
export { uiConfirm } from './confirm';
|
||||
export { uiConflicts } from './conflicts';
|
||||
export { uiContributors } from './contributors';
|
||||
@@ -15,6 +18,7 @@ export { uiFeatureInfo } from './feature_info';
|
||||
export { uiFeatureList } from './feature_list';
|
||||
export { uiField } from './field';
|
||||
export { uiFlash } from './flash';
|
||||
export { uiFormFields } from './form_fields';
|
||||
export { uiFullScreen } from './full_screen';
|
||||
export { uiGeolocate } from './geolocate';
|
||||
export { uiHelp } from './help';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { t, textDirection } from '../../util/locale';
|
||||
import { localize } from './helper';
|
||||
|
||||
@@ -88,6 +89,13 @@ export function uiIntro(context) {
|
||||
var curtain = uiCurtain();
|
||||
selection.call(curtain);
|
||||
|
||||
// store that the user started the walkthrough..
|
||||
context.storage('walkthrough_started', 'yes');
|
||||
|
||||
// restore previous walkthrough progress..
|
||||
var storedProgress = context.storage('walkthrough_progress') || '';
|
||||
var progress = storedProgress.split(';').filter(Boolean);
|
||||
|
||||
var chapters = chapterFlow.map(function(chapter, i) {
|
||||
var s = chapterUi[chapter](context, curtain.reveal)
|
||||
.on('done', function() {
|
||||
@@ -102,11 +110,25 @@ export function uiIntro(context) {
|
||||
d3.select('button.chapter-' + next)
|
||||
.classed('next', true);
|
||||
}
|
||||
|
||||
// store walkthrough progress..
|
||||
progress.push(chapter);
|
||||
context.storage('walkthrough_progress', _.uniq(progress).join(';'));
|
||||
});
|
||||
return s;
|
||||
});
|
||||
|
||||
chapters[chapters.length - 1].on('startEditing', function() {
|
||||
// store walkthrough progress..
|
||||
progress.push('startEditing');
|
||||
context.storage('walkthrough_progress', _.uniq(progress).join(';'));
|
||||
|
||||
// store if walkthrough is completed..
|
||||
var incomplete = _.difference(chapterFlow, progress);
|
||||
if (!incomplete.length) {
|
||||
context.storage('walkthrough_completed', 'yes');
|
||||
}
|
||||
|
||||
curtain.remove();
|
||||
navwrap.remove();
|
||||
d3.selectAll('#map .layer-background').style('opacity', opacity);
|
||||
|
||||
+12
-103
@@ -1,18 +1,15 @@
|
||||
import * as d3 from 'd3';
|
||||
import { d3combobox } from '../lib/d3.combobox.js';
|
||||
import { t } from '../util/locale';
|
||||
import { modeBrowse } from '../modes';
|
||||
import { uiDisclosure } from './disclosure';
|
||||
import { uiField } from './field';
|
||||
import {
|
||||
utilGetSetValue,
|
||||
utilNoAuto,
|
||||
utilRebind
|
||||
} from '../util';
|
||||
import { uiFormFields } from './form_fields';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
|
||||
export function uiPresetEditor(context) {
|
||||
var dispatch = d3.dispatch('change'),
|
||||
formFields = uiFormFields(context),
|
||||
expandedPreference = (context.storage('preset_fields.expanded') !== 'false'),
|
||||
state,
|
||||
fieldsArr,
|
||||
@@ -80,106 +77,18 @@ export function uiPresetEditor(context) {
|
||||
.tags(tags);
|
||||
});
|
||||
|
||||
var shown = fieldsArr.filter(function(field) { return field.isShown(); }),
|
||||
notShown = fieldsArr.filter(function(field) { return !field.isShown(); });
|
||||
|
||||
selection
|
||||
.call(formFields.fieldsArr(fieldsArr), 'inspector-inner fillL3');
|
||||
|
||||
|
||||
var form = selection.selectAll('.preset-form')
|
||||
.data([0]);
|
||||
|
||||
form = form.enter()
|
||||
.append('div')
|
||||
.attr('class', 'preset-form inspector-inner fillL3')
|
||||
.merge(form);
|
||||
|
||||
|
||||
var fields = form.selectAll('.wrap-form-field')
|
||||
.data(shown, function(d) { return d.id; });
|
||||
|
||||
fields.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var enter = fields.enter()
|
||||
.append('div')
|
||||
.attr('class', function(d) { return 'wrap-form-field wrap-form-field-' + d.id; });
|
||||
|
||||
// Update
|
||||
fields = fields
|
||||
.merge(enter);
|
||||
|
||||
fields
|
||||
.order()
|
||||
.each(function(d) {
|
||||
d3.select(this)
|
||||
.call(d.render)
|
||||
.selectAll('input')
|
||||
.on('keydown', function() {
|
||||
// if user presses enter, and combobox is not active, accept edits..
|
||||
if (d3.event.keyCode === 13 && d3.select('.combobox').empty()) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
notShown = notShown.map(function(field) {
|
||||
return {
|
||||
title: field.label(),
|
||||
value: field.label(),
|
||||
field: field
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
var more = selection.selectAll('.more-fields')
|
||||
.data((notShown.length > 0) ? [0] : []);
|
||||
|
||||
more.exit()
|
||||
.remove();
|
||||
|
||||
more = more.enter()
|
||||
.append('div')
|
||||
.attr('class', 'more-fields')
|
||||
.append('label')
|
||||
.text(t('inspector.add_fields'))
|
||||
.merge(more);
|
||||
|
||||
|
||||
var input = more.selectAll('.value')
|
||||
.data([0]);
|
||||
|
||||
input.exit()
|
||||
.remove();
|
||||
|
||||
input = input.enter()
|
||||
.append('input')
|
||||
.attr('class', 'value')
|
||||
.attr('type', 'text')
|
||||
.call(utilNoAuto)
|
||||
.merge(input);
|
||||
|
||||
input
|
||||
.call(utilGetSetValue, '')
|
||||
.attr('placeholder', function() {
|
||||
var placeholder = [];
|
||||
for (var field in notShown) {
|
||||
placeholder.push(notShown[field].title);
|
||||
selection.selectAll('.wrap-form-field input')
|
||||
.on('keydown', function() {
|
||||
// if user presses enter, and combobox is not active, accept edits..
|
||||
if (d3.event.keyCode === 13 && d3.select('.combobox').empty()) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
|
||||
})
|
||||
.call(d3combobox()
|
||||
.container(context.container())
|
||||
.data(notShown)
|
||||
.minItems(1)
|
||||
.on('accept', function (d) {
|
||||
var field = d.field;
|
||||
field.show = true;
|
||||
render(selection);
|
||||
field.focus();
|
||||
})
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -175,7 +175,12 @@ export function uiRawTagEditor(context) {
|
||||
|
||||
|
||||
function isReadOnly(d) {
|
||||
return readOnlyTags.indexOf(d.key) !== -1;
|
||||
for (var i = 0; i < readOnlyTags.length; i++) {
|
||||
if (d.key.match(readOnlyTags[i]) !== null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+38
-15
@@ -9,8 +9,8 @@ import { svgIcon } from '../svg/index';
|
||||
export function uiTagReference(tag) {
|
||||
var taginfo = services.taginfo,
|
||||
tagReference = {},
|
||||
button,
|
||||
body,
|
||||
button = d3.select(null),
|
||||
body = d3.select(null),
|
||||
loaded,
|
||||
showing;
|
||||
|
||||
@@ -46,7 +46,8 @@ export function uiTagReference(tag) {
|
||||
function load(param) {
|
||||
if (!taginfo) return;
|
||||
|
||||
button.classed('tag-reference-loading', true);
|
||||
button
|
||||
.classed('tag-reference-loading', true);
|
||||
|
||||
taginfo.docs(param, function show(err, data) {
|
||||
var docs;
|
||||
@@ -56,22 +57,23 @@ export function uiTagReference(tag) {
|
||||
|
||||
body.html('');
|
||||
|
||||
|
||||
if (!docs || !docs.title) {
|
||||
if (param.hasOwnProperty('value')) {
|
||||
load(_.omit(param, 'value')); // retry with key only
|
||||
} else {
|
||||
body.append('p').text(t('inspector.no_documentation_key'));
|
||||
body
|
||||
.append('p')
|
||||
.attr('class', 'tag-reference-description')
|
||||
.text(t('inspector.no_documentation_key'));
|
||||
done();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (docs.image && docs.image.thumb_url_prefix) {
|
||||
body
|
||||
.append('img')
|
||||
.attr('class', 'wiki-image')
|
||||
.attr('class', 'tag-reference-wiki-image')
|
||||
.attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
|
||||
.on('load', function() { done(); })
|
||||
.on('error', function() { d3.select(this).remove(); done(); });
|
||||
@@ -81,16 +83,31 @@ export function uiTagReference(tag) {
|
||||
|
||||
body
|
||||
.append('p')
|
||||
.attr('class', 'tag-reference-description')
|
||||
.text(docs.description || t('inspector.documentation_redirect'));
|
||||
|
||||
body
|
||||
.append('a')
|
||||
.attr('class', 'tag-reference-link')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
|
||||
.call(svgIcon('#icon-out-link', 'inline'))
|
||||
.append('span')
|
||||
.text(t('inspector.reference'));
|
||||
|
||||
// Add link to info about "good changeset comments" - #2923
|
||||
if (param.key === 'comment') {
|
||||
body
|
||||
.append('a')
|
||||
.attr('class', 'tag-reference-comment-link')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#icon-out-link', 'inline'))
|
||||
.attr('href', t('commit.about_changeset_comments_link'))
|
||||
.append('span')
|
||||
.text(t('commit.about_changeset_comments'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,9 +115,12 @@ export function uiTagReference(tag) {
|
||||
function done() {
|
||||
loaded = true;
|
||||
|
||||
button.classed('tag-reference-loading', false);
|
||||
button
|
||||
.classed('tag-reference-loading', false);
|
||||
|
||||
body.transition()
|
||||
body
|
||||
.classed('expanded', true)
|
||||
.transition()
|
||||
.duration(200)
|
||||
.style('max-height', '200px')
|
||||
.style('opacity', '1');
|
||||
@@ -109,12 +129,15 @@ export function uiTagReference(tag) {
|
||||
}
|
||||
|
||||
|
||||
function hide(selection) {
|
||||
selection = selection || body.transition().duration(200);
|
||||
|
||||
selection
|
||||
function hide() {
|
||||
body
|
||||
.transition()
|
||||
.duration(200)
|
||||
.style('max-height', '0px')
|
||||
.style('opacity', '0');
|
||||
.style('opacity', '0')
|
||||
.on('end', function () {
|
||||
body.classed('expanded', false);
|
||||
});
|
||||
|
||||
showing = false;
|
||||
}
|
||||
@@ -158,7 +181,7 @@ export function uiTagReference(tag) {
|
||||
.merge(body);
|
||||
|
||||
if (showing === false) {
|
||||
hide(body);
|
||||
hide();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user