Merge pull request #6010 from openstreetmap/add-feature-search-bar

Select feature type before drawing
This commit is contained in:
Quincy Morgan
2019-03-06 15:54:39 -05:00
committed by GitHub
62 changed files with 1416 additions and 488 deletions
+225 -77
View File
@@ -308,29 +308,29 @@ button.disabled {
cursor: not-allowed;
}
.joined button {
.joined > * {
border-radius: 0;
border-right: 1px solid rgba(0,0,0,.5);
}
[dir='rtl'] .joined button {
[dir='rtl'] .joined > * {
border-left: 1px solid rgba(0,0,0,.5);
border-right: none;
}
.fillL .joined button {
.fillL .joined > * {
border-right: 1px solid #fff;
}
.joined button:first-child {
.joined > *:first-child {
border-radius: 4px 0 0 4px;
}
[dir='rtl'] .joined button:first-child {
[dir='rtl'] .joined > *:first-child {
border-radius: 0 4px 4px 0;
}
.joined button:last-child {
.joined > *:last-child {
border-right-width: 0;
border-radius: 0 4px 4px 0;
}
[dir='rtl'] .joined button:last-child {
[dir='rtl'] .joined > *.bar-button:last-child {
border-radius: 4px 0 0 4px;
}
@@ -451,22 +451,25 @@ button[disabled].action:hover {
width: 100%;
}
.tool-group.leading-area {
flex-shrink: 2;
justify-content: flex-start;
}
.tool-group.leading-area,
.tool-group.trailing-area {
flex-shrink: 2;
}
.tool-group.center-area {
justify-content: center;
}
.tool-group.trailing-area {
justify-content: flex-start;
justify-content: flex-end;
}
.tool-group > div {
.tool-group > div:not(:empty) {
display: flex;
margin: 0 5px;
}
.tool-group button {
flex: 1 1 auto;
.tool-group button.bar-button {
flex: 0 0 auto;
flex-flow: row nowrap;
align-items: center;
padding: 0 10px;
@@ -474,38 +477,31 @@ button[disabled].action:hover {
white-space: nowrap;
display: flex;
}
[dir='ltr'] .tool-group button.add-preset.add-point,
[dir='ltr'] .tool-group button.add-preset.add-point .label {
padding-left: 0px;
.tool-group button.add-preset:not(.add-generic-preset) {
padding: 0;
}
[dir='ltr'] .tool-group button.add-preset:not(.add-point) {
padding-left: 5px;
.tool-group button.add-preset.disabled .preset-icon-container {
opacity: 0.5;
}
[dir='ltr'] .tool-group button.add-preset:not(.add-point) .label {
padding-left: 3px;
}
[dir='rtl'] .tool-group button.add-preset.add-point,
[dir='rtl'] .tool-group button.add-preset.add-point .label {
padding-right: 0px;
}
[dir='rtl'] .tool-group button.add-preset:not(.add-point) {
padding-right: 5px;
}
[dir='rtl'] .tool-group button.add-preset:not(.add-point) .label {
padding-right: 3px;
}
.narrow .tool-group button.add-preset {
padding-right: 0 !important;
padding-left: 0 !important;
}
.tool-group button > .icon {
.tool-group button.bar-button .icon {
flex: 0 0 20px;
}
.tool-group button .label {
.tool-group button.bar-button .label {
flex: 0 1 auto;
padding: 0 5px;
}
.tool-group button.dragging {
opacity: 0.75;
z-index: 200;
}
.tool-group button.dragging .tooltip {
display: none;
}
.tool-group button.dragging.removing {
cursor: url(img/cursor-select-remove.png), pointer;
}
button.save .count {
display: inline-block;
border: 0px solid #ccc;
@@ -565,15 +561,15 @@ button.add-note svg.icon {
.spinner {
opacity: .5;
display: flex;
flex-shrink: 2;
justify-content: flex-end;
position: absolute;
right: 4px;
bottom: 26px;
}
.spinner img {
height: 40px;
width: 40px;
border-radius: 4px;
background: black;
height: 20px;
width: 20px;
background: transparent;
border-radius: 100%;
}
[dir='rtl'] .spinner img {
-moz-transform: scaleX(-1);
@@ -589,7 +585,7 @@ button.add-note svg.icon {
width: unset;
}
#bar.narrow .spinner,
#bar.narrow button .label {
#bar.narrow button.bar-button .label {
display: none;
}
#bar.narrow button .count {
@@ -597,7 +593,148 @@ button.add-note svg.icon {
border-right-width: 0;
}
/* Add a feature search bar
------------------------------------------------------- */
.search-add {
width: 100%;
justify-content: center;
position: relative;
}
.search-add .search-wrap {
position: relative;
width: 100%;
min-width: 200px;
max-width: 250px;
border-radius: 20px 0 0 20px;
background: #fff;
}
.search-add .search-wrap.focused .tooltip {
display: none;
}
.search-add .search-wrap:nth-last-child(2) {
border-radius: 20px;
border: none;
}
.search-add input[type='search'] {
position: relative;
width: 100%;
height: 100%;
border: none;
font-size: 14px;
text-indent: 25px;
padding: 5px 10px;
border-radius: inherit;
}
.search-add .search-icon {
color: #333;
display: block;
position: absolute;
left: 10px;
top: 10px;
pointer-events: none;
}
[dir='rtl'] .search-add .search-icon {
left: auto;
right: 10px;
}
.search-add .popover {
max-height: 250px;
width: 100%;
position: absolute;
top: 44px;
border: none;
border-radius: 6px;
overflow-y: auto;
max-width: 350px;
/* ensure corners are rounded in Chrome */
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
}
.search-add .popover::-webkit-scrollbar {
/* don't overlap rounded corners */
background: transparent;
}
.search-add .popover .list {
max-height: 70vh;
}
.search-add .list-item {
display: flex;
position: relative;
padding: 2px;
}
.search-add .list-item:not(:last-of-type),
.search-add .subsection .list-item {
border-bottom: 1px solid #DCDCDC;
}
.search-add .list-item .label {
font-weight: bold;
font-size: 12px;
padding-left: 2px;
top: 0;
bottom: 0;
position: relative;
display: flex;
align-items: center;
line-height: 1.3em;
width: 100%;
}
.search-add .list-item .label .namepart:nth-child(2) {
font-weight: normal;
}
.search-add .list-item.disabled .preset-icon-container,
.search-add .list-item.disabled .label {
opacity: 0.55;
}
[dir='ltr'] .search-add .list-item .label .icon.inline {
margin-left: 0;
}
[dir='rtl'] .search-add .list-item .label .icon.inline {
margin-right: 0;
}
.search-add .list-item > *:not(button) {
pointer-events: none;
}
.search-add .list-item button.choose {
position: absolute;
border-radius: 0;
height: 100%;
width: 100%;
top: 0;
left: 0;
}
.search-add .list-item button.choose:hover,
.search-add .list-item button.choose:focus {
background: #fff;
}
.search-add .list-item.focused:not(.disabled) button.choose {
background: #e8ebff;
}
.search-add .list-item button.choose.disabled {
background-color: #ececec;
}
.search-add .subsection .list-item button.choose {
opacity: 0.85;
}
.search-add .list-item button.accessory {
position: relative;
flex: 0 0 auto;
color: #808080;
background: transparent;
padding-right: 3px;
padding-left: 3px;
}
.search-add .list-item button.accessory:hover {
color: #666;
}
.search-add .subsection {
background-color: #CBCBCB;
}
[dir='ltr'] .search-add .subsection {
padding-left: 6px;
}
[dir='rtl'] .search-add .subsection {
padding-right: 6px;
}
/* Header for modals / panes
------------------------------------------------------- */
.header {
@@ -995,9 +1132,16 @@ a.hide-toggle {
height: 60px;
text-align: center;
}
#bar .preset-icon-container {
.preset-icon-container.small {
width: 40px;
height: 40px;
flex: 0 0 auto;
}
.preset-icon-point-border path {
stroke: #333;
stroke-width: 1.2;
fill: transparent;
}
.preset-icon-line {
@@ -1034,7 +1178,6 @@ a.hide-toggle {
}
.preset-icon-fill {
cursor: inherit;
margin: auto;
position: absolute;
width: 100%;
@@ -1042,6 +1185,10 @@ a.hide-toggle {
left: 0;
top: 0;
}
.preset-icon-container svg,
.preset-icon-container svg > * {
cursor: inherit !important;
}
.preset-icon-fill path.area.stroke {
fill: transparent;
}
@@ -1058,41 +1205,34 @@ a.hide-toggle {
height:100%;
position: absolute;
z-index: 1;
transform: scale(0.48);
}
.preset-icon .icon {
position: absolute;
margin: auto;
top: 26%;
left: 26%;
width: 48%;
height: 48%;
}
.preset-icon.framed .icon {
top: 30%;
left: 30%;
width: 40%;
height: 40%;
}
.preset-icon.framed.line-geom .icon {
top: 20%;
}
.preset-icon-iD .icon {
top: 0;
left: 0;
height: 100%;
right: 0;
width: 100%;
height: 100%;
}
.preset-icon-iD.framed .icon {
top: 13%;
left: 13%;
width: 74%;
height: 74%;
.preset-icon-container.small .preset-icon.point-geom {
transform: translateY(-7%) scale(0.27);
}
.preset-icon-iD.framed.line-geom .icon {
top: 3%;
.preset-icon.framed {
transform: scale(0.4);
}
.preset-icon.framed.line-geom {
top: 20%;
transform: translateY(-30%) scale(0.4);
}
.preset-icon-iD {
transform: scale(1);
}
.preset-icon-iD.framed {
transform: scale(0.74);
}
.preset-icon-iD.framed.line-geom {
transform: translateY(-30%) scale(0.74);
}
.preset-list-button .label {
@@ -1144,7 +1284,8 @@ a.hide-toggle {
.preset-list-item button.tag-reference-button {
height: 100%;
border: 1px solid #ccc;
flex: 32px;
width: 32px;
flex: 0 0 auto;
background: #f6f6f6;
}
[dir='ltr'] .preset-list-item button.preset-favorite-button,
@@ -1173,11 +1314,11 @@ a.hide-toggle {
opacity: .5;
}
.preset-list-item button.preset-favorite-button .icon {
button.preset-favorite-button .icon {
fill-opacity: 0;
stroke-width: 1.6;
stroke-width: 1;
}
.preset-list-item button.preset-favorite-button.active .icon {
button.preset-favorite-button.active .icon {
fill-opacity: inherit;
}
@@ -4775,22 +4916,29 @@ svg.mouseclick use.right {
}
/* dark tooltips for sidebar / panels */
.tooltip.dark.top .tooltip-arrow,
.map-pane .tooltip.top .tooltip-arrow,
#sidebar .tooltip.top .tooltip-arrow {
border-top-color: #000;
}
.tooltip.dark.bottom .tooltip-arrow,
.map-pane .tooltip.bottom .tooltip-arrow,
#sidebar .tooltip.bottom .tooltip-arrow {
border-bottom-color: #000;
}
.tooltip.dark.left .tooltip-arrow,
.map-pane .tooltip.left .tooltip-arrow,
#sidebar .tooltip.left .tooltip-arrow {
border-left-color: #000;
}
.tooltip.dark.right .tooltip-arrow,
.map-pane .tooltip.right .tooltip-arrow,
#sidebar .tooltip.right .tooltip-arrow {
border-right-color: #000;
}
.tooltip.dark .tooltip-inner,
.tooltip.dark .tooltip-heading,
.tooltip.dark .keyhint-wrap,
.map-pane .tooltip-inner,
.map-pane .tooltip-heading,
.map-pane .keyhint-wrap,
+13
View File
@@ -9,6 +9,10 @@ en:
open_wikidata: open on wikidata.org
favorite: favorite
modes:
add_feature:
title: Add a feature
description: "Search for features to add to the map."
key: Tab
add_area:
title: Area
description: "Add parks, buildings, lakes or other areas to the map."
@@ -21,10 +25,13 @@ en:
title: Point
description: "Add restaurants, monuments, postal boxes or other points to the map."
tail: Click on the map to add a point.
add_vertex:
title: Vertex
add_note:
title: Note
description: "Spotted an issue? Let other mappers know."
tail: Click on the map to add a note.
key: N
add_preset:
title: "Add {feature}"
point:
@@ -33,6 +40,10 @@ en:
title: "Add {feature} as a line"
area:
title: "Add {feature} as an area"
building:
title: "Add {feature} as a building"
vertex:
title: "Add {feature} as a vertex"
browse:
title: Browse
description: Pan and zoom the map.
@@ -1643,10 +1654,12 @@ en:
title: "Editing"
drawing:
title: "Drawing"
focus_add_feature: "Focus the feature search field"
add_point: "'Add point' mode"
add_line: "'Add line' mode"
add_area: "'Add area' mode"
add_note: "'Add note' mode"
add_favorite: "Add a favorite feature"
place_point: "Place a point or note"
disable_snap: "Hold to disable point snapping"
stop_line: "Finish drawing a line or area"
+20 -18
View File
@@ -5,34 +5,32 @@ en:
name: Barrier Features
category-building:
name: Building Features
category-golf-area:
name: Golf Features
category-golf-line:
category-golf:
name: Golf Features
category-landuse:
name: Land Use Features
category-natural-area:
name: Natural Features
category-natural-line:
name: Natural Features
category-natural-point:
category-natural:
name: Natural Features
category-path:
name: Path Features
name: Paths
category-rail:
name: Rail Features
name: Rails
category-restriction:
name: Restriction Features
category-road:
name: Road Features
category-road_major:
name: Major Roads
category-road_minor:
name: Minor Roads
category-road_service:
name: Service Roads
category-route:
name: Route Features
category-utility:
name: Utility Features
category-water-area:
name: Water Features
category-water-line:
name: Water Features
category-water:
name: Water Bodies
category-waterway:
name: Waterways
fields:
access:
# 'access=*, foot=*, motor_vehicle=*, bicycle=*, horse=*'
@@ -3518,6 +3516,9 @@ en:
# building=warehouse
name: Warehouse
terms: '<translate with synonyms or related terms for ''Warehouse'', separated by commas>'
building_point:
# building=*
name: Building
camp_site/camp_pitch:
# camp_site=camp_pitch
name: Camp Pitch
@@ -6953,8 +6954,9 @@ en:
name: Waterway
terms: '<translate with synonyms or related terms for ''Waterway'', separated by commas>'
vertex:
name: Other
terms: '<translate with synonyms or related terms for ''Other'', separated by commas>'
name: Vertex
# 'terms: other'
terms: '<translate with synonyms or related terms for ''Vertex'', separated by commas>'
waterway:
# waterway=*
name: Waterway
+60 -66
View File
@@ -2,7 +2,6 @@
"categories": {
"category-barrier": {
"icon": "maki-roadblock",
"geometry": "line",
"name": "Barrier Features",
"members": [
"barrier/fence",
@@ -16,7 +15,6 @@
},
"category-building": {
"icon": "maki-building",
"geometry": "area",
"name": "Building Features",
"members": [
"building",
@@ -29,9 +27,8 @@
"building/residential"
]
},
"category-golf-area": {
"category-golf": {
"icon": "maki-golf",
"geometry": "area",
"name": "Golf Features",
"members": [
"golf/fairway",
@@ -41,14 +38,7 @@
"golf/bunker",
"golf/tee",
"golf/water_hazard",
"golf/driving_range"
]
},
"category-golf-line": {
"icon": "maki-golf",
"geometry": "line",
"name": "Golf Features",
"members": [
"golf/driving_range",
"golf/hole",
"golf/cartpath",
"golf/cartpath_service",
@@ -57,7 +47,6 @@
},
"category-landuse": {
"icon": "maki-landuse",
"geometry": "area",
"name": "Land Use Features",
"members": [
"landuse/residential",
@@ -74,9 +63,8 @@
"landuse/religious"
]
},
"category-natural-area": {
"category-natural": {
"icon": "maki-natural",
"geometry": "area",
"name": "Natural Features",
"members": [
"natural/water",
@@ -88,20 +76,9 @@
"natural/bare_rock",
"natural/beach",
"natural/cave_entrance",
"natural/glacier"
]
},
"category-natural-line": {
"icon": "maki-natural",
"geometry": "line",
"name": "Natural Features",
"members": ["natural/coastline", "natural/tree_row"]
},
"category-natural-point": {
"icon": "maki-natural",
"geometry": "point",
"name": "Natural Features",
"members": [
"natural/glacier",
"natural/coastline",
"natural/tree_row",
"natural/peak",
"natural/cliff",
"natural/beach",
@@ -109,36 +86,35 @@
]
},
"category-path": {
"icon": "iD-category-path",
"geometry": "line",
"name": "Path Features",
"icon": "temaki-pedestrian",
"name": "Paths",
"members": [
"highway/path",
"highway/footway",
"highway/footway/marked",
"highway/footway/sidewalk",
"highway/steps",
"highway/path",
"highway/footway",
"highway/cycleway",
"highway/bridleway",
"highway/pedestrian_line"
]
},
"category-rail": {
"icon": "iD-category-rail",
"geometry": "line",
"name": "Rail Features",
"icon": "iD-railway-rail",
"name": "Rails",
"members": [
"railway/rail",
"railway/subway",
"railway/tram",
"railway/monorail",
"railway/disused",
"railway/abandoned"
"railway/tram",
"railway/subway",
"railway/narrow_gauge",
"railway/light_rail",
"railway/monorail",
"railway/funicular"
]
},
"category-restriction": {
"icon": "iD-restriction",
"geometry": "relation",
"name": "Restriction Features",
"members": [
"type/restriction/no_left_turn",
@@ -152,32 +128,48 @@
"type/restriction"
]
},
"category-road": {
"icon": "iD-category-roads",
"geometry": "line",
"name": "Road Features",
"category-road_major": {
"icon": "iD-highway-unclassified",
"name": "Major Roads",
"members": [
"highway/residential",
"highway/motorway",
"highway/trunk",
"highway/primary",
"highway/secondary",
"highway/tertiary",
"highway/living_street",
"highway/unclassified",
"highway/service",
"highway/track",
"highway/motorway_link",
"highway/trunk_link",
"highway/primary_link",
"highway/secondary_link",
"highway/tertiary_link",
"highway/tertiary_link"
]
},
"category-road_minor": {
"icon": "iD-highway-unclassified",
"name": "Minor Roads",
"members": [
"highway/unclassified",
"highway/residential",
"highway/living_street",
"highway/service",
"highway/track",
"highway/road"
]
},
"category-road_service": {
"icon": "iD-highway-service",
"name": "Service Roads",
"members": [
"highway/service",
"highway/service/parking_aisle",
"highway/service/driveway",
"highway/service/alley",
"highway/service/emergency_access",
"highway/service/drive-through"
]
},
"category-route": {
"icon": "iD-route",
"geometry": "relation",
"name": "Route Features",
"members": [
"type/route/road",
@@ -200,8 +192,7 @@
]
},
"category-utility": {
"icon": "iD-category-utility",
"geometry": "line",
"icon": "iD-power-line",
"name": "Utility Features",
"members": [
"power/line",
@@ -210,27 +201,30 @@
"power/cable/underground"
]
},
"category-water-area": {
"category-water": {
"icon": "maki-water",
"geometry": "area",
"name": "Water Features",
"name": "Water Bodies",
"members": [
"natural/water/lake",
"natural/water",
"natural/water/pond",
"natural/water/basin",
"natural/water/lake",
"natural/water/reservoir",
"natural/water"
"natural/bay"
]
},
"category-water-line": {
"icon": "iD-category-water",
"geometry": "line",
"name": "Water Features",
"category-waterway": {
"icon": "iD-waterway-stream",
"name": "Waterways",
"members": [
"waterway/river",
"waterway/stream",
"waterway/drain",
"waterway/river",
"waterway/canal",
"waterway/ditch",
"waterway/drain"
"natural/water/stream",
"natural/water/river",
"natural/water/canal"
]
}
}
-1
View File
@@ -1,6 +1,5 @@
{
"icon": "maki-roadblock",
"geometry": "line",
"name": "Barrier Features",
"members": [
"barrier/fence",
-1
View File
@@ -1,6 +1,5 @@
{
"icon": "maki-building",
"geometry": "area",
"name": "Building Features",
"members": [
"building",
-11
View File
@@ -1,11 +0,0 @@
{
"icon": "maki-golf",
"geometry": "line",
"name": "Golf Features",
"members": [
"golf/hole",
"golf/cartpath",
"golf/cartpath_service",
"golf/path"
]
}
@@ -1,6 +1,5 @@
{
"icon": "maki-golf",
"geometry": "area",
"name": "Golf Features",
"members": [
"golf/fairway",
@@ -10,6 +9,10 @@
"golf/bunker",
"golf/tee",
"golf/water_hazard",
"golf/driving_range"
"golf/driving_range",
"golf/hole",
"golf/cartpath",
"golf/cartpath_service",
"golf/path"
]
}
-1
View File
@@ -1,6 +1,5 @@
{
"icon": "maki-landuse",
"geometry": "area",
"name": "Land Use Features",
"members": [
"landuse/residential",
@@ -1,9 +0,0 @@
{
"icon": "maki-natural",
"geometry": "line",
"name": "Natural Features",
"members": [
"natural/coastline",
"natural/tree_row"
]
}
@@ -1,11 +0,0 @@
{
"icon": "maki-natural",
"geometry": "point",
"name": "Natural Features",
"members": [
"natural/peak",
"natural/cliff",
"natural/beach",
"natural/cave_entrance"
]
}
@@ -1,6 +1,5 @@
{
"icon": "maki-natural",
"geometry": "area",
"name": "Natural Features",
"members": [
"natural/water",
@@ -12,6 +11,12 @@
"natural/bare_rock",
"natural/beach",
"natural/cave_entrance",
"natural/glacier"
"natural/glacier",
"natural/coastline",
"natural/tree_row",
"natural/peak",
"natural/cliff",
"natural/beach",
"natural/cave_entrance"
]
}
+4 -5
View File
@@ -1,13 +1,12 @@
{
"icon": "iD-category-path",
"geometry": "line",
"name": "Path Features",
"icon": "temaki-pedestrian",
"name": "Paths",
"members": [
"highway/path",
"highway/footway",
"highway/footway/marked",
"highway/footway/sidewalk",
"highway/steps",
"highway/path",
"highway/footway",
"highway/cycleway",
"highway/bridleway",
"highway/pedestrian_line"
+8 -7
View File
@@ -1,13 +1,14 @@
{
"icon": "iD-category-rail",
"geometry": "line",
"name": "Rail Features",
"icon": "iD-railway-rail",
"name": "Rails",
"members": [
"railway/rail",
"railway/subway",
"railway/tram",
"railway/monorail",
"railway/disused",
"railway/abandoned"
"railway/tram",
"railway/subway",
"railway/narrow_gauge",
"railway/light_rail",
"railway/monorail",
"railway/funicular"
]
}
-1
View File
@@ -1,6 +1,5 @@
{
"icon": "iD-restriction",
"geometry": "relation",
"name": "Restriction Features",
"members": [
"type/restriction/no_left_turn",
@@ -1,23 +1,16 @@
{
"icon": "iD-category-roads",
"geometry": "line",
"name": "Road Features",
"icon": "iD-highway-unclassified",
"name": "Major Roads",
"members": [
"highway/residential",
"highway/motorway",
"highway/trunk",
"highway/primary",
"highway/secondary",
"highway/tertiary",
"highway/living_street",
"highway/unclassified",
"highway/service",
"highway/track",
"highway/motorway_link",
"highway/trunk_link",
"highway/primary_link",
"highway/secondary_link",
"highway/tertiary_link",
"highway/road"
"highway/tertiary_link"
]
}
+12
View File
@@ -0,0 +1,12 @@
{
"icon": "iD-highway-unclassified",
"name": "Minor Roads",
"members": [
"highway/unclassified",
"highway/residential",
"highway/living_street",
"highway/service",
"highway/track",
"highway/road"
]
}
+12
View File
@@ -0,0 +1,12 @@
{
"icon": "iD-highway-service",
"name": "Service Roads",
"members": [
"highway/service",
"highway/service/parking_aisle",
"highway/service/driveway",
"highway/service/alley",
"highway/service/emergency_access",
"highway/service/drive-through"
]
}
-1
View File
@@ -1,6 +1,5 @@
{
"icon": "iD-route",
"geometry": "relation",
"name": "Route Features",
"members": [
"type/route/road",
+1 -2
View File
@@ -1,6 +1,5 @@
{
"icon": "iD-category-utility",
"geometry": "line",
"icon": "iD-power-line",
"name": "Utility Features",
"members": [
"power/line",
-12
View File
@@ -1,12 +0,0 @@
{
"icon": "iD-category-water",
"geometry": "line",
"name": "Water Features",
"members": [
"waterway/river",
"waterway/stream",
"waterway/canal",
"waterway/ditch",
"waterway/drain"
]
}
@@ -1,11 +1,12 @@
{
"icon": "maki-water",
"geometry": "area",
"name": "Water Features",
"name": "Water Bodies",
"members": [
"natural/water/lake",
"natural/water",
"natural/water/pond",
"natural/water/basin",
"natural/water/lake",
"natural/water/reservoir",
"natural/water"
"natural/bay"
]
}
+14
View File
@@ -0,0 +1,14 @@
{
"icon": "iD-waterway-stream",
"name": "Waterways",
"members": [
"waterway/stream",
"waterway/drain",
"waterway/river",
"waterway/canal",
"waterway/ditch",
"natural/water/stream",
"natural/water/river",
"natural/water/canal"
]
}
+7 -6
View File
@@ -3,8 +3,8 @@
"area": [
"category-landuse",
"category-building",
"category-water-area",
"category-natural-area",
"category-water",
"category-natural",
"leisure/park",
"amenity/hospital",
"amenity/place_of_worship",
@@ -13,17 +13,18 @@
"area"
],
"line": [
"category-road",
"category-road_major",
"category-road_minor",
"category-rail",
"category-path",
"category-water-line",
"category-waterway",
"category-barrier",
"category-natural-line",
"category-natural",
"category-utility",
"line"
],
"point": [
"category-natural-point",
"category-natural",
"leisure/park",
"amenity/hospital",
"amenity/place_of_worship",
+6 -5
View File
@@ -5,6 +5,7 @@
"amenity": {"fields": ["amenity"], "geometry": ["point", "vertex", "line", "area"], "tags": {"amenity": "*"}, "searchable": false, "name": "Amenity"},
"attraction": {"icon": "maki-star", "fields": ["name", "attraction", "operator", "opening_hours"], "moreFields": ["opening_hours", "fee", "payment_multi", "address", "website", "phone", "email", "fax"], "geometry": ["point", "vertex", "line", "area"], "tags": {"attraction": "*"}, "searchable": false, "name": "Attraction"},
"boundary": {"fields": ["boundary"], "geometry": ["line"], "tags": {"boundary": "*"}, "searchable": false, "name": "Boundary"},
"building_point": {"icon": "maki-home", "fields": ["{building}"], "moreFields": ["{building}"], "geometry": ["point"], "tags": {"building": "*"}, "matchScore": 0.6, "searchable": false, "terms": [], "name": "Building"},
"circular": {"geometry": ["vertex", "line"], "fields": ["name"], "tags": {"junction": "circular"}, "name": "Traffic Circle", "searchable": false},
"embankment": {"geometry": ["line"], "tags": {"embankment": "yes"}, "name": "Embankment", "matchScore": 0.2, "searchable": false},
"highway": {"fields": ["name", "highway"], "geometry": ["point", "vertex", "line", "area"], "tags": {"highway": "*"}, "searchable": false, "name": "Highway"},
@@ -264,7 +265,7 @@
"boundary/administrative": {"name": "Administrative Boundary", "geometry": ["line"], "tags": {"boundary": "administrative"}, "fields": ["name", "admin_level"]},
"bridge/support": {"icon": "fas-archway", "fields": ["bridge/support"], "moreFields": ["material", "seamark/type"], "geometry": ["point", "vertex", "area"], "tags": {"bridge:support": "*"}, "name": "Bridge Support"},
"bridge/support/pier": {"icon": "fas-archway", "fields": ["bridge/support"], "moreFields": ["material", "seamark/type"], "geometry": ["point", "vertex", "area"], "tags": {"bridge:support": "pier"}, "name": "Bridge Pier"},
"building": {"icon": "maki-home", "fields": ["name", "building", "levels", "height", "address"], "moreFields": ["architect", "building/material", "layer", "roof/colour", "smoking", "wheelchair"], "geometry": ["point", "area"], "tags": {"building": "*"}, "matchScore": 0.6, "terms": [], "name": "Building"},
"building": {"icon": "maki-home", "fields": ["name", "building", "levels", "height", "address"], "moreFields": ["architect", "building/material", "layer", "roof/colour", "smoking", "wheelchair"], "geometry": ["area"], "tags": {"building": "*"}, "matchScore": 0.6, "terms": [], "name": "Building"},
"building/bunker": {"geometry": ["area"], "tags": {"building": "bunker"}, "matchScore": 0.5, "name": "Bunker", "searchable": false},
"building/entrance": {"icon": "maki-entrance-alt1", "fields": [], "moreFields": [], "geometry": ["vertex"], "tags": {"building": "entrance"}, "name": "Entrance/Exit", "searchable": false},
"building/train_station": {"icon": "maki-building", "geometry": ["point", "vertex", "area"], "tags": {"building": "train_station"}, "matchScore": 0.5, "name": "Train Station Building", "searchable": false},
@@ -677,12 +678,12 @@
"natural/volcano": {"icon": "maki-volcano", "fields": ["name", "elevation", "volcano/status", "volcano/type"], "geometry": ["point", "vertex"], "tags": {"natural": "volcano"}, "terms": ["mountain", "crater"], "name": "Volcano"},
"natural/water": {"icon": "maki-water", "fields": ["name", "water", "intermittent"], "moreFields": ["salt", "tidal"], "geometry": ["area"], "tags": {"natural": "water"}, "name": "Water"},
"natural/water/basin": {"icon": "maki-water", "fields": ["name", "basin", "intermittent_yes"], "geometry": ["area"], "tags": {"natural": "water", "water": "basin"}, "reference": {"key": "water", "value": "basin"}, "terms": ["detention", "drain", "overflow", "rain", "retention"], "name": "Basin"},
"natural/water/canal": {"icon": "maki-water", "fields": ["{natural/water}", "salt"], "geometry": ["area"], "tags": {"natural": "water", "water": "canal"}, "reference": {"key": "water", "value": "canal"}, "name": "Canal"},
"natural/water/canal": {"icon": "iD-waterway-canal", "fields": ["{natural/water}", "salt"], "geometry": ["area"], "tags": {"natural": "water", "water": "canal"}, "reference": {"key": "water", "value": "canal"}, "name": "Canal"},
"natural/water/lake": {"icon": "maki-water", "fields": ["{natural/water}", "salt", "tidal"], "geometry": ["area"], "tags": {"natural": "water", "water": "lake"}, "reference": {"key": "water", "value": "lake"}, "terms": ["lakelet", "loch", "mere"], "name": "Lake"},
"natural/water/pond": {"icon": "maki-water", "fields": ["{natural/water}", "salt"], "geometry": ["area"], "tags": {"natural": "water", "water": "pond"}, "reference": {"key": "water", "value": "pond"}, "terms": ["lakelet", "millpond", "tarn", "pool", "mere"], "name": "Pond"},
"natural/water/reservoir": {"icon": "maki-water", "geometry": ["area"], "tags": {"natural": "water", "water": "reservoir"}, "reference": {"key": "water", "value": "reservoir"}, "name": "Reservoir"},
"natural/water/river": {"icon": "maki-water", "fields": ["{natural/water}", "tidal"], "geometry": ["area"], "tags": {"natural": "water", "water": "river"}, "reference": {"key": "water", "value": "river"}, "terms": ["beck", "branch", "brook", "course", "creek", "estuary", "rill", "riverbank", "rivulet", "run", "runnel", "stream", "tributary", "watercourse"], "name": "River"},
"natural/water/stream": {"icon": "maki-water", "fields": ["{natural/water}"], "geometry": ["area"], "tags": {"natural": "water", "water": "stream"}, "reference": {"key": "water", "value": "stream"}, "terms": ["beck", "branch", "brook", "burn", "course", "creek", "current", "drift", "flood", "flow", "freshet", "race", "rill", "rindle", "rivulet", "run", "runnel", "rush", "spate", "spritz", "surge", "tide", "torrent", "tributary", "watercourse"], "name": "Stream"},
"natural/water/river": {"icon": "iD-waterway-river", "fields": ["{natural/water}", "tidal"], "geometry": ["area"], "tags": {"natural": "water", "water": "river"}, "reference": {"key": "water", "value": "river"}, "terms": ["beck", "branch", "brook", "course", "creek", "estuary", "rill", "riverbank", "rivulet", "run", "runnel", "stream", "tributary", "watercourse"], "name": "River"},
"natural/water/stream": {"icon": "iD-waterway-stream", "fields": ["{natural/water}"], "geometry": ["area"], "tags": {"natural": "water", "water": "stream"}, "reference": {"key": "water", "value": "stream"}, "terms": ["beck", "branch", "brook", "burn", "course", "creek", "current", "drift", "flood", "flow", "freshet", "race", "rill", "rindle", "rivulet", "run", "runnel", "rush", "spate", "spritz", "surge", "tide", "torrent", "tributary", "watercourse"], "name": "Stream"},
"natural/wetland": {"icon": "maki-wetland", "fields": ["wetland"], "geometry": ["point", "area"], "tags": {"natural": "wetland"}, "terms": ["bog", "marsh", "reedbed", "swamp", "tidalflat"], "name": "Wetland"},
"natural/wood": {"icon": "maki-park-alt1", "fields": ["name", "leaf_type", "leaf_cycle"], "geometry": ["point", "area"], "tags": {"natural": "wood"}, "terms": ["tree"], "name": "Wood"},
"noexit/yes": {"icon": "maki-barrier", "geometry": ["vertex"], "terms": ["no exit", "road end", "dead end"], "tags": {"noexit": "yes"}, "reference": {"key": "noexit", "value": "*"}, "name": "No Exit"},
@@ -1060,7 +1061,7 @@
"type/route/tram": {"icon": "iD-route-tram", "fields": ["name", "ref_route", "operator", "network", "to", "from"], "geometry": ["relation"], "tags": {"type": "route", "route": "tram"}, "name": "Tram Route"},
"type/site": {"icon": "iD-relation", "fields": ["name", "site"], "geometry": ["relation"], "tags": {"type": "site"}, "name": "Site"},
"type/waterway": {"icon": "iD-route-water", "fields": ["name", "waterway", "ref"], "geometry": ["relation"], "tags": {"type": "waterway"}, "name": "Waterway"},
"vertex": {"moreFields": ["name"], "geometry": ["vertex"], "tags": {}, "name": "Other", "matchScore": 0.1},
"vertex": {"moreFields": ["name"], "geometry": ["vertex"], "terms": ["other"], "tags": {}, "name": "Vertex", "matchScore": 0.1},
"waterway/riverbank": {"icon": "maki-water", "geometry": ["area"], "tags": {"waterway": "riverbank"}, "name": "Riverbank", "searchable": false},
"waterway/boatyard": {"icon": "maki-harbor", "fields": ["name", "operator"], "moreFields": ["address", "website", "phone", "email", "fax", "wheelchair"], "geometry": ["area", "vertex", "point"], "tags": {"waterway": "boatyard"}, "name": "Boatyard"},
"waterway/canal": {"icon": "iD-waterway-canal", "fields": ["name", "width", "intermittent"], "moreFields": ["salt"], "geometry": ["line"], "tags": {"waterway": "canal"}, "name": "Canal"},
+19
View File
@@ -0,0 +1,19 @@
{
"icon": "maki-home",
"fields": [
"{building}"
],
"moreFields": [
"{building}"
],
"geometry": [
"point"
],
"tags": {
"building": "*"
},
"matchScore": 0.6,
"searchable": false,
"terms": [],
"name": "Building"
}
-1
View File
@@ -16,7 +16,6 @@
"wheelchair"
],
"geometry": [
"point",
"area"
],
"tags": {
@@ -1,5 +1,5 @@
{
"icon": "maki-water",
"icon": "iD-waterway-canal",
"fields": [
"{natural/water}",
"salt"
@@ -1,5 +1,5 @@
{
"icon": "maki-water",
"icon": "iD-waterway-river",
"fields": [
"{natural/water}",
"tidal"
@@ -1,5 +1,5 @@
{
"icon": "maki-water",
"icon": "iD-waterway-stream",
"fields": [
"{natural/water}"
],
+4 -1
View File
@@ -5,7 +5,10 @@
"geometry": [
"vertex"
],
"terms": [
"other"
],
"tags": {},
"name": "Other",
"name": "Vertex",
"matchScore": 0.1
}
+7 -9
View File
@@ -157,19 +157,17 @@
"text": "shortcuts.editing.drawing.title"
},
{
"shortcuts": ["1"],
"text": "shortcuts.editing.drawing.add_point"
"shortcuts": ["modes.add_feature.key"],
"text": "shortcuts.editing.drawing.focus_add_feature"
},
{
"shortcuts": ["2"],
"text": "shortcuts.editing.drawing.add_line"
"shortcuts": ["1", "2", "3"],
"text": "shortcuts.editing.drawing.add_favorite",
"separator": ",",
"suffix": "…"
},
{
"shortcuts": ["3"],
"text": "shortcuts.editing.drawing.add_area"
},
{
"shortcuts": ["4"],
"shortcuts": ["modes.add_note.key"],
"text": "shortcuts.editing.drawing.add_note"
},
{
+4 -4
View File
@@ -8,6 +8,7 @@
{"key": "amenity", "description": "🄿 Amenity (unsearchable), 🄵 Type", "object_types": ["node", "way", "area"]},
{"key": "attraction", "description": "🄿 Attraction (unsearchable), 🄵 Type", "object_types": ["node", "way", "area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/star-15.svg?sanitize=true"},
{"key": "boundary", "description": "🄿 Boundary (unsearchable), 🄵 Type", "object_types": ["way"]},
{"key": "building", "description": "🄿 Building (unsearchable), 🄿 Building, 🄵 Building", "object_types": ["node"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/home-15.svg?sanitize=true"},
{"key": "junction", "value": "circular", "description": "🄿 Traffic Circle (unsearchable), 🄵 Junction", "object_types": ["node", "way"]},
{"key": "embankment", "value": "yes", "description": "🄿 Embankment (unsearchable)", "object_types": ["way"]},
{"key": "highway", "description": "🄿 Highway (unsearchable), 🄵 Type", "object_types": ["node", "way", "area"]},
@@ -261,7 +262,6 @@
{"key": "boundary", "value": "administrative", "description": "🄿 Administrative Boundary", "object_types": ["way"]},
{"key": "bridge:support", "description": "🄿 Bridge Support, 🄵 Type", "object_types": ["node", "area"], "icon_url": "https://raw.githubusercontent.com/openstreetmap/iD/master/svg/fontawesome/fas-archway.svg?sanitize=true"},
{"key": "bridge:support", "value": "pier", "description": "🄿 Bridge Pier", "object_types": ["node", "area"], "icon_url": "https://raw.githubusercontent.com/openstreetmap/iD/master/svg/fontawesome/fas-archway.svg?sanitize=true"},
{"key": "building", "description": "🄿 Building, 🄵 Building", "object_types": ["node", "area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/home-15.svg?sanitize=true"},
{"key": "building", "value": "bunker", "description": "🄿 Bunker (unsearchable)", "object_types": ["area"]},
{"key": "building", "value": "entrance", "description": "🄿 Entrance/Exit (unsearchable)", "object_types": ["node"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/entrance-alt1-15.svg?sanitize=true"},
{"key": "building", "value": "train_station", "description": "🄿 Train Station Building (unsearchable)", "object_types": ["node", "area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/building-15.svg?sanitize=true"},
@@ -655,12 +655,12 @@
{"key": "natural", "value": "tree", "description": "🄿 Tree", "object_types": ["node"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/park-15.svg?sanitize=true"},
{"key": "natural", "value": "volcano", "description": "🄿 Volcano", "object_types": ["node"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/volcano-15.svg?sanitize=true"},
{"key": "water", "value": "basin", "description": "🄿 Basin", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "canal", "description": "🄿 Canal", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "canal", "description": "🄿 Canal", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/openstreetmap/iD/master/svg/iD-sprite/presets/waterway-canal.svg?sanitize=true"},
{"key": "water", "value": "lake", "description": "🄿 Lake", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "pond", "description": "🄿 Pond", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "reservoir", "description": "🄿 Reservoir", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "river", "description": "🄿 River", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "stream", "description": "🄿 Stream", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/water-15.svg?sanitize=true"},
{"key": "water", "value": "river", "description": "🄿 River", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/openstreetmap/iD/master/svg/iD-sprite/presets/waterway-river.svg?sanitize=true"},
{"key": "water", "value": "stream", "description": "🄿 Stream", "object_types": ["area"], "icon_url": "https://raw.githubusercontent.com/openstreetmap/iD/master/svg/iD-sprite/presets/waterway-stream.svg?sanitize=true"},
{"key": "natural", "value": "wetland", "description": "🄿 Wetland", "object_types": ["node", "area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/wetland-15.svg?sanitize=true"},
{"key": "natural", "value": "wood", "description": "🄿 Wood", "object_types": ["node", "area"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/park-alt1-15.svg?sanitize=true"},
{"key": "noexit", "value": "yes", "description": "🄿 No Exit", "object_types": ["node"], "icon_url": "https://raw.githubusercontent.com/mapbox/maki/master/icons/barrier-15.svg?sanitize=true"},
+40 -22
View File
@@ -11,6 +11,11 @@
"favorite": "favorite"
},
"modes": {
"add_feature": {
"title": "Add a feature",
"description": "Search for features to add to the map.",
"key": "Tab"
},
"add_area": {
"title": "Area",
"description": "Add parks, buildings, lakes or other areas to the map.",
@@ -26,10 +31,14 @@
"description": "Add restaurants, monuments, postal boxes or other points to the map.",
"tail": "Click on the map to add a point."
},
"add_vertex": {
"title": "Vertex"
},
"add_note": {
"title": "Note",
"description": "Spotted an issue? Let other mappers know.",
"tail": "Click on the map to add a note."
"tail": "Click on the map to add a note.",
"key": "N"
},
"add_preset": {
"title": "Add {feature}",
@@ -41,6 +50,12 @@
},
"area": {
"title": "Add {feature} as an area"
},
"building": {
"title": "Add {feature} as a building"
},
"vertex": {
"title": "Add {feature} as a vertex"
}
},
"browse": {
@@ -1982,10 +1997,12 @@
"title": "Editing",
"drawing": {
"title": "Drawing",
"focus_add_feature": "Focus the feature search field",
"add_point": "'Add point' mode",
"add_line": "'Add line' mode",
"add_area": "'Add area' mode",
"add_note": "'Add note' mode",
"add_favorite": "Add a favorite feature",
"place_point": "Place a point or note",
"disable_snap": "Hold to disable point snapping",
"stop_line": "Finish drawing a line or area"
@@ -2063,35 +2080,32 @@
"category-building": {
"name": "Building Features"
},
"category-golf-area": {
"name": "Golf Features"
},
"category-golf-line": {
"category-golf": {
"name": "Golf Features"
},
"category-landuse": {
"name": "Land Use Features"
},
"category-natural-area": {
"name": "Natural Features"
},
"category-natural-line": {
"name": "Natural Features"
},
"category-natural-point": {
"category-natural": {
"name": "Natural Features"
},
"category-path": {
"name": "Path Features"
"name": "Paths"
},
"category-rail": {
"name": "Rail Features"
"name": "Rails"
},
"category-restriction": {
"name": "Restriction Features"
},
"category-road": {
"name": "Road Features"
"category-road_major": {
"name": "Major Roads"
},
"category-road_minor": {
"name": "Minor Roads"
},
"category-road_service": {
"name": "Service Roads"
},
"category-route": {
"name": "Route Features"
@@ -2099,11 +2113,11 @@
"category-utility": {
"name": "Utility Features"
},
"category-water-area": {
"name": "Water Features"
"category-water": {
"name": "Water Bodies"
},
"category-water-line": {
"name": "Water Features"
"category-waterway": {
"name": "Waterways"
}
},
"fields": {
@@ -3916,6 +3930,10 @@
"name": "Boundary",
"terms": ""
},
"building_point": {
"name": "Building",
"terms": ""
},
"circular": {
"name": "Traffic Circle",
"terms": ""
@@ -8137,8 +8155,8 @@
"terms": ""
},
"vertex": {
"name": "Other",
"terms": ""
"name": "Vertex",
"terms": "other"
},
"waterway/riverbank": {
"name": "Riverbank",
+6 -2
View File
@@ -127,11 +127,13 @@ export function behaviorDraw(context) {
var d = datum();
var target = d && d.properties && d.properties.entity;
var mode = context.mode();
if (target && target.type === 'node' && allowsVertex(target)) { // Snap to a node
dispatch.call('clickNode', this, target, d);
return;
} else if (target && target.type === 'way') { // Snap to a way
} else if (target && target.type === 'way' && (mode.id !== 'add-point' || mode.preset.matchGeometry('vertex'))) { // Snap to a way
var choice = geoChooseEdge(
context.childNodes(target), context.mouse(), context.projection, context.activeID()
);
@@ -140,8 +142,10 @@ export function behaviorDraw(context) {
dispatch.call('clickWay', this, choice.loc, edge, d);
return;
}
} else if (mode.id !== 'add-point' || mode.preset.matchGeometry('point')) {
dispatch.call('click', this, context.map().mouseCoordinates(), d);
}
dispatch.call('click', this, context.map().mouseCoordinates(), d);
}
+2 -1
View File
@@ -350,7 +350,8 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph, baselin
window.setTimeout(function() {
context.map().dblclickEnable(true);
}, 1000);
var isNewFeature = !mode.isContinuing && mode.button.indexOf('add-preset-') === -1;
var isNewFeature = !mode.isContinuing && context.presets().match(origWay, context.graph()).isFallback();
context.enter(modeSelect(context, [wayID]).newFeature(isNewFeature));
if (isNewFeature) {
context.validator().validate();
+15 -3
View File
@@ -107,6 +107,15 @@ export function behaviorHover(context) {
return d.geometry(context.graph()) === 'vertex' || context.presets().allowsVertex(d, context.graph());
}
function modeAllowsHover(target) {
var mode = context.mode();
if (mode.id === 'add-point') {
return mode.preset.matchGeometry('vertex') ||
(target.type !== 'way' && target.geometry(context.graph()) !== 'vertex');
}
return true;
}
function enter(datum) {
if (datum === _target) return;
_target = datum;
@@ -144,17 +153,20 @@ export function behaviorHover(context) {
}
}
var mode = context.mode();
// Update hover state and dispatch event
if (entity && entity.id !== _newNodeId) {
// If drawing a way, don't hover on a node that was just placed. #3974
var mode = context.mode() && context.mode().id;
if ((mode === 'draw-line' || mode === 'draw-area') && !_newNodeId && entity.type === 'node') {
if ((mode.id === 'draw-line' || mode.id === 'draw-area') && !_newNodeId && entity.type === 'node') {
_newNodeId = entity.id;
return;
}
var suppressed = (_altDisables && d3_event && d3_event.altKey) ||
(entity.type === 'node' && _ignoreVertex && !allowsVertex(entity));
(entity.type === 'node' && _ignoreVertex && !allowsVertex(entity)) ||
!modeAllowsHover(entity);
_selection.selectAll(selector)
.classed(suppressed ? 'hover-suppressed' : 'hover', true);
+18 -10
View File
@@ -316,6 +316,12 @@ export function coreContext() {
context.getFavoritePresets = function() {
return JSON.parse(context.storage('favorite_presets')) || [];
};
function setFavoritePresets(favs) {
context.storage('favorite_presets', JSON.stringify(favs));
//and call update on modes
dispatch.call('favoritePreset');
}
context.favoritePreset = function(preset, geom) {
var favs = context.getFavoritePresets();
@@ -325,26 +331,28 @@ export function coreContext() {
return !(d.id === preset.id && d.geom === geom);
});
} else {
// only allow 3 favorites
if (favs.length === 3) {
// remove the last favorite (first in, first out)
// only allow 10 favorites
if (favs.length === 10) {
// remove the last favorite (last in, first out)
favs.pop();
}
// prepend array
favs.unshift({id: preset.id, geom: geom});
// append array
favs.push({id: preset.id, geom: geom});
}
context.storage('favorite_presets', JSON.stringify(favs));
//and call update on modes
dispatch.call('favoritePreset');
setFavoritePresets(favs);
};
context.isFavoritePreset = function(preset, geom) {
var favs = context.getFavoritePresets();
return favs.some(function(d) {
return d.id === preset.id && d.geom === geom;
});
};
context.moveFavoritePreset = function(fromIndex, toIndex) {
var favs = context.getFavoritePresets();
favs.splice(toIndex, 0, favs.splice(fromIndex, 1)[0]);
setFavoritePresets(favs);
};
/* Map */
var map;
+2 -8
View File
@@ -10,14 +10,8 @@ import { modeDrawArea } from './index';
import { osmNode, osmWay } from '../osm';
export function modeAddArea(context, customMode) {
var mode = customMode || {
id: 'add-area',
button: 'area',
title: t('modes.add_area.title'),
description: t('modes.add_area.description'),
key: '3'
};
export function modeAddArea(context, mode) {
mode.id = 'add-area';
var behavior = behaviorAddWay(context)
.tail(t('modes.add_area.tail'))
+2 -8
View File
@@ -10,14 +10,8 @@ import { modeDrawLine } from './index';
import { osmNode, osmWay } from '../osm';
export function modeAddLine(context, customMode) {
var mode = customMode || {
id: 'add-line',
button: 'line',
title: t('modes.add_line.title'),
description: t('modes.add_line.description'),
key: '2'
};
export function modeAddLine(context, mode) {
mode.id = 'add-line';
var behavior = behaviorAddWay(context)
.tail(t('modes.add_line.tail'))
+1 -1
View File
@@ -11,7 +11,7 @@ export function modeAddNote(context) {
button: 'note',
title: t('modes.add_note.title'),
description: t('modes.add_note.description'),
key: '4'
key: t('modes.add_note.key')
};
var behavior = behaviorDraw(context)
+29 -14
View File
@@ -1,19 +1,16 @@
import _clone from 'lodash-es/clone';
import { t } from '../util/locale';
import { actionAddEntity } from '../actions';
import { actionAddEntity, actionChangeTags } from '../actions';
import { behaviorDraw } from '../behavior';
import { modeBrowse, modeSelect } from './index';
import { osmNode } from '../osm';
import { actionAddMidpoint } from '../actions';
export function modeAddPoint(context, customMode) {
var mode = customMode || {
id: 'add-point',
button: 'point',
title: t('modes.add_point.title'),
description: t('modes.add_point.description'),
key: '1'
};
export function modeAddPoint(context, mode) {
mode.id = 'add-point';
var behavior = behaviorDraw(context)
.tail(t('modes.add_point.tail'))
@@ -35,9 +32,7 @@ export function modeAddPoint(context, customMode) {
t('operations.add.annotation.point')
);
context.enter(
modeSelect(context, [node.id]).newFeature(!mode.preset)
);
enterSelectMode(node);
}
@@ -49,14 +44,34 @@ export function modeAddPoint(context, customMode) {
t('operations.add.annotation.vertex')
);
enterSelectMode(node);
}
function enterSelectMode(node) {
context.enter(
modeSelect(context, [node.id]).newFeature(!mode.preset)
modeSelect(context, [node.id]).newFeature(mode.preset.isFallback())
);
}
function addNode(node) {
add(node.loc);
if (Object.keys(defaultTags).length === 0) {
enterSelectMode(node);
return;
}
var tags = _clone(node.tags);
for (var key in defaultTags) {
tags[key] = defaultTags[key];
}
context.perform(
actionChangeTags(node.id, tags),
t('operations.add.annotation.point')
);
enterSelectMode(node);
}
+11
View File
@@ -14,6 +14,17 @@ export function presetCategory(id, category, all) {
}));
category.geometry = category.members.collection.reduce(function(geometries, preset) {
for (var index in preset.geometry) {
var geometry = preset.geometry[index];
if (geometries.indexOf(geometry) === -1) {
geometries.push(geometry);
}
}
return geometries;
}, []);
category.matchGeometry = function(geometry) {
return category.geometry.indexOf(geometry) >= 0;
};
+19 -3
View File
@@ -34,6 +34,14 @@ export function presetCollection(collection) {
}));
},
matchAnyGeometry: function(geometries) {
return presetCollection(this.collection.filter(function(d) {
return geometries.some(function(geometry) {
return d.matchGeometry(geometry);
});
}));
},
search: function(value, geometry) {
if (!value) return this;
@@ -134,8 +142,6 @@ export function presetCollection(collection) {
return a.preset;
});
var other = presets.item(geometry);
var results = leading_name.concat(
leading_suggestions,
leading_terms,
@@ -145,7 +151,17 @@ export function presetCollection(collection) {
similar_terms
).slice(0, maxSearchResults - 1);
return presetCollection(_uniq(results.concat(other)));
if (geometry) {
if (typeof geometry === 'string') {
results.push(presets.item(geometry));
} else {
geometry.forEach(function(geom) {
results.push(presets.item(geom));
});
}
}
return presetCollection(_uniq(results));
}
};
+4
View File
@@ -268,6 +268,10 @@ export function presetIndex() {
return presetCollection(_uniq(rec.concat(def).concat(all.item(geometry))));
};
all.recent = function(geometries, n) {
return presetCollection(_recent.matchAnyGeometry(geometries).collection.slice(0, n - 1));
};
all.choose = function(preset) {
if (preset.searchable !== false) {
_recent = presetCollection(_uniq([preset].concat(_recent.collection)));
+6 -5
View File
@@ -249,11 +249,12 @@ export function presetPreset(id, preset, fields, visible, rawPresets) {
}
}
}
for (var f in preset.fields) {
var field = preset.fields[f];
if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
tags[field.key] = field.default;
if (geometry) {
for (var f in preset.fields) {
var field = preset.fields[f];
if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
tags[field.key] = field.default;
}
}
}
+19 -13
View File
@@ -26,6 +26,7 @@ import { uiLoading } from './loading';
import { uiMapData } from './map_data';
import { uiMapInMap } from './map_in_map';
import { uiModes } from './modes';
import { uiNotes } from './notes';
import { uiNotice } from './notice';
import { uiPhotoviewer } from './photoviewer';
import { uiRestore } from './restore';
@@ -36,6 +37,7 @@ import { uiSidebar } from './sidebar';
import { uiSpinner } from './spinner';
import { uiSplash } from './splash';
import { uiStatus } from './status';
import { uiSearchAdd } from './search_add';
import { uiTooltipHtml } from './tooltipHtml';
import { uiUndoRedo } from './undo_redo';
import { uiVersion } from './version';
@@ -90,7 +92,7 @@ export function uiInit(context) {
var sidebarButton = leadingArea
.append('div')
.append('button')
.attr('class', 'sidebar-toggle')
.attr('class', 'sidebar-toggle bar-button')
.attr('tabindex', -1)
.on('click', ui.sidebar.toggle)
.call(tooltip()
@@ -110,12 +112,19 @@ export function uiInit(context) {
// Center area button group (Point/Line/Area/Note mode buttons)
bar
var centerArea = bar
.append('div')
.attr('class', 'tool-group center-area')
.append('div')
.attr('class', 'modes joined')
.call(uiModes(context), bar);
.attr('class', 'tool-group center-area');
var addArea = centerArea.append('div')
.attr('class', 'search-add joined');
addArea.call(uiSearchAdd(context), bar);
addArea.call(uiModes(context), bar);
centerArea.append('div')
.attr('class', 'notes')
.call(uiNotes(context), bar);
// Trailing area button group (Undo/Redo save buttons)
@@ -134,13 +143,6 @@ export function uiInit(context) {
.call(uiSave(context));
// For now, just put spinner at the end of the #bar
bar
.append('div')
.attr('class', 'spinner')
.call(uiSpinner(context));
// Map controls (appended to #bar, but absolutely positioned)
var controls = content
.append('div')
@@ -184,6 +186,10 @@ export function uiInit(context) {
.call(help.renderToggleButton);
content.call(help.renderPane);
content
.append('div')
.attr('class', 'spinner')
.call(uiSpinner(context));
// Add attribution and footer
var about = content
+148 -74
View File
@@ -1,36 +1,26 @@
import _debounce from 'lodash-es/debounce';
import { select as d3_select } from 'd3-selection';
import { drag as d3_drag } from 'd3-drag';
import { event as d3_event, select as d3_select } from 'd3-selection';
import {
modeAddArea,
modeAddLine,
modeAddPoint,
modeAddNote,
modeBrowse
} from '../modes';
import { svgIcon } from '../svg';
import { t } from '../util/locale';
import { t, textDirection } from '../util/locale';
import { tooltip } from '../util/tooltip';
import { uiPresetIcon } from './preset_icon';
import { uiTooltipHtml } from './tooltipHtml';
export function uiModes(context) {
var modes = [
modeAddPoint(context),
modeAddLine(context),
modeAddArea(context),
modeAddNote(context)
];
function enabled(d) {
if (d.id === 'add-note') {
return notesEnabled() && notesEditable();
} else {
return osmEditable();
}
function enabled() {
return osmEditable();
}
function osmEditable() {
@@ -38,16 +28,6 @@ export function uiModes(context) {
return context.editable() && mode && mode.id !== 'save';
}
function notesEnabled() {
var noteLayer = context.layers().layer('notes');
return noteLayer && noteLayer.enabled();
}
function notesEditable() {
var mode = context.mode();
return context.map().notesEditable() && mode && mode.id !== 'save';
}
return function(selection) {
context
@@ -64,19 +44,6 @@ export function uiModes(context) {
.classed('mode-' + exited.id, false);
});
modes.forEach(function(mode) {
context.keybinding().on(mode.key, function() {
if (!enabled(mode)) return;
if (mode.id === context.mode().id) {
context.enter(modeBrowse(context));
} else {
context.enter(mode);
}
});
});
var debouncedUpdate = _debounce(update, 500, { leading: true, trailing: true });
context.map()
@@ -91,51 +58,96 @@ export function uiModes(context) {
function update() {
var showNotes = notesEnabled();
var data = showNotes ? modes : modes.slice(0, 3);
// add favorite presets to modes
for (var i = 0; i <= 9; i++) {
context.keybinding().off(i.toString());
}
var favoritePresets = context.getFavoritePresets();
var favoriteModes = favoritePresets.map(function(d) {
var favoriteModes = favoritePresets.map(function(d, index) {
var preset = context.presets().item(d.id);
var isMaki = /^maki-/.test(preset.icon);
var icon = '#' + preset.icon + (isMaki ? '-11' : '');
var markerClass = 'add-preset add-' + d.geom + ' add-preset-' + preset.name()
.replace(/\s+/g, '_')
+ '-' + d.geom; //replace spaces with underscores to avoid css interpretation
var presetName = t('presets.presets.' + preset.id + '.name');
var relevantMatchingGeometry = preset.geometry.filter(function(geometry) {
return ['point', 'line', 'area'].indexOf(geometry) !== -1;
var presetName = preset.name().split(' ')[0];
var markerClass = 'add-preset add-' + d.geom + ' add-preset-' + presetName.replace(/\s+/g, '_')
+ '-' + d.geom; // replace spaces with underscores to avoid css interpretation
if (preset.isFallback()) {
markerClass += ' add-generic-preset';
}
var supportedGeometry = preset.geometry.filter(function(geometry) {
return ['vertex', 'point', 'line', 'area'].indexOf(geometry) !== -1;
});
var vertexIndex = supportedGeometry.indexOf('vertex');
if (vertexIndex !== -1 && supportedGeometry.indexOf('point') !== -1) {
// both point and vertex allowed, just combine them
supportedGeometry.splice(vertexIndex, 1);
}
var tooltipTitleID = 'modes.add_preset.title';
if (relevantMatchingGeometry.length !== 1) {
tooltipTitleID = 'modes.add_preset.' + d.geom + '.title';
if (supportedGeometry.length !== 1) {
if (preset.setTags({}, d.geom).building) {
tooltipTitleID = 'modes.add_preset.building.title';
} else {
tooltipTitleID = 'modes.add_preset.' + d.geom + '.title';
}
}
var favoriteMode = {
id: markerClass,
button: markerClass,
title: presetName,
description: t(tooltipTitleID, { feature: presetName }),
key: '',
icon: icon,
description: t(tooltipTitleID, { feature: '<strong>' + presetName + '</strong>' }),
preset: preset,
geometry: d.geom
};
var keyCode;
if (textDirection === 'ltr') {
// use number row order: 1 2 3 4 5 6 7 8 9 0
if (index === 9) {
keyCode = 0;
} else if (index < 10) {
keyCode = index + 1;
}
} else {
// use number row order from right to left
if (index === 0) {
keyCode = 0;
} else if (index < 10) {
keyCode = 10 - index;
}
}
if (keyCode !== null) {
favoriteMode.key = keyCode.toString();
}
var mode;
switch (d.geom) {
case 'point':
case 'vertex':
return modeAddPoint(context, favoriteMode);
mode = modeAddPoint(context, favoriteMode);
break;
case 'line':
return modeAddLine(context, favoriteMode);
mode = modeAddLine(context, favoriteMode);
break;
case 'area':
return modeAddArea(context, favoriteMode);
mode = modeAddArea(context, favoriteMode);
}
if (mode.key) {
context.keybinding().on(mode.key, function() {
if (!enabled(mode)) return;
if (mode.button === context.mode().button) {
context.enter(modeBrowse(context));
} else {
context.enter(mode);
}
});
}
return mode;
});
data = data.concat(favoriteModes);
var data = favoriteModes;
var buttons = selection.selectAll('button.add-button')
.data(data, function(d) { return d.id; });
.data(data, function(d, index) { return d.button + index; });
// exit
buttons.exit()
@@ -145,7 +157,7 @@ export function uiModes(context) {
var buttonsEnter = buttons.enter()
.append('button')
.attr('tabindex', -1)
.attr('class', function(d) { return d.id + ' add-button'; })
.attr('class', function(d) { return d.button + ' add-button bar-button'; })
.on('click.mode-buttons', function(d) {
if (!enabled(d)) return;
@@ -167,33 +179,95 @@ export function uiModes(context) {
buttonsEnter
.each(function(d) {
if (d.preset) {
if (d.preset.isFallback()) {
d3_select(this)
.call(svgIcon('#iD-icon-' + d.preset.id));
} else {
d3_select(this)
.call(uiPresetIcon()
.geometry(d.geometry)
.preset(d.preset)
.sizeClass('small')
);
} else {
d3_select(this)
.call(svgIcon(d.icon || '#iD-icon-' + d.button));
}
});
buttonsEnter
.append('span')
.attr('class', 'label')
.text(function(mode) { return mode.title; });
var dragOrigin, targetIndex;
// if we are adding/removing the buttons, check if toolbar has overflowed
if (buttons.enter().size() || buttons.exit().size()) {
context.ui().checkOverflow('#bar', true);
}
buttonsEnter.call(d3_drag()
.on('start', function() {
dragOrigin = {
x: d3_event.x,
y: d3_event.y
};
targetIndex = null;
})
.on('drag', function(d, index) {
var x = d3_event.x - dragOrigin.x,
y = d3_event.y - dragOrigin.y;
d3_select(this)
.classed('dragging', true)
.classed('removing', y > 50);
targetIndex = null;
selection.selectAll('button.add-preset')
.style('transform', function(d2, index2) {
var node = d3_select(this).node();
if (index === index2) {
return 'translate(' + x + 'px, ' + y + 'px)';
} else if (y > 50) {
if (index2 > index) {
return 'translateX(' + (textDirection === 'rtl' ? '' : '-') + '100%)';
}
} else if (index2 > index && (
(d3_event.x > node.offsetLeft && textDirection === 'ltr') ||
(d3_event.x < node.offsetLeft + node.offsetWidth && textDirection === 'rtl')
)) {
if (targetIndex === null || index2 > targetIndex) {
targetIndex = index2;
}
return 'translateX(' + (textDirection === 'rtl' ? '' : '-') + '100%)';
} else if (index2 < index && (
(d3_event.x < node.offsetLeft + node.offsetWidth && textDirection === 'ltr') ||
(d3_event.x > node.offsetLeft && textDirection === 'rtl')
)) {
if (targetIndex === null || index2 < targetIndex) {
targetIndex = index2;
}
return 'translateX(' + (textDirection === 'rtl' ? '-' : '') + '100%)';
}
return null;
});
})
.on('end', function(d, index) {
d3_select(this)
.classed('dragging', false)
.classed('removing', false);
selection.selectAll('button.add-preset')
.style('transform', null);
var y = d3_event.y - dragOrigin.y;
if (y > 50) {
// dragged out of the top bar, remove the favorite
context.favoritePreset(d.preset, d.geometry);
} else if (targetIndex !== null) {
// dragged to a new position, reorder
context.moveFavoritePreset(index, targetIndex);
}
})
);
// update
buttons = buttons
.merge(buttonsEnter)
.classed('disabled', function(d) { return !enabled(d); });
// check if toolbar has overflowed
context.ui().checkOverflow('#bar', true);
}
};
}
+128
View File
@@ -0,0 +1,128 @@
import _debounce from 'lodash-es/debounce';
import { select as d3_select } from 'd3-selection';
import {
modeAddNote,
modeBrowse
} from '../modes';
import { svgIcon } from '../svg';
import { tooltip } from '../util/tooltip';
import { uiTooltipHtml } from './tooltipHtml';
export function uiNotes(context) {
var mode = modeAddNote(context);
function enabled() {
return notesEnabled() && notesEditable();
}
function notesEnabled() {
var noteLayer = context.layers().layer('notes');
return noteLayer && noteLayer.enabled();
}
function notesEditable() {
var mode = context.mode();
return context.map().notesEditable() && mode && mode.id !== 'save';
}
return function(selection) {
context
.on('enter.editor.notes', function(entered) {
selection.selectAll('button.add-button')
.classed('active', function(mode) { return entered.button === mode.button; });
context.container()
.classed('mode-' + entered.id, true);
});
context
.on('exit.editor.notes', function(exited) {
context.container()
.classed('mode-' + exited.id, false);
});
context.keybinding().on(mode.key, function() {
if (!enabled(mode)) return;
if (mode.id === context.mode().id) {
context.enter(modeBrowse(context));
} else {
context.enter(mode);
}
});
var debouncedUpdate = _debounce(update, 500, { leading: true, trailing: true });
context.map()
.on('move.notes', debouncedUpdate)
.on('drawn.notes', debouncedUpdate);
context
.on('enter.notes', update);
update();
function update() {
var showNotes = notesEnabled();
var data = showNotes ? [mode] : [];
var buttons = selection.selectAll('button.add-button')
.data(data, function(d) { return d.id; });
// exit
buttons.exit()
.remove();
// enter
var buttonsEnter = buttons.enter()
.append('button')
.attr('tabindex', -1)
.attr('class', function(d) { return d.id + ' add-button bar-button'; })
.on('click.notes', function(d) {
if (!enabled(d)) return;
// When drawing, ignore accidental clicks on mode buttons - #4042
var currMode = context.mode().id;
if (/^draw/.test(currMode)) return;
if (d.id === currMode) {
context.enter(modeBrowse(context));
} else {
context.enter(d);
}
})
.call(tooltip()
.placement('bottom')
.html(true)
.title(function(d) { return uiTooltipHtml(d.description, d.key); })
);
buttonsEnter
.each(function(d) {
d3_select(this)
.call(svgIcon(d.icon || '#iD-icon-' + d.button));
});
buttonsEnter
.append('span')
.attr('class', 'label')
.text(function(mode) { return mode.title; });
// if we are adding/removing the buttons, check if toolbar has overflowed
if (buttons.enter().size() || buttons.exit().size()) {
context.ui().checkOverflow('#bar', true);
}
// update
buttons = buttons
.merge(buttonsEnter)
.classed('disabled', function(d) { return !enabled(d); });
}
};
}
+13 -13
View File
@@ -6,7 +6,7 @@ import {
import { t } from '../util/locale';
import { svgIcon } from '../svg';
export function uiPresetFavorite(preset, geom, context) {
export function uiPresetFavorite(preset, geom, context, klass) {
var presetFavorite = {};
@@ -15,7 +15,7 @@ export function uiPresetFavorite(preset, geom, context) {
presetFavorite.button = function(selection) {
var canFavorite = geom !== 'vertex' && geom !== 'relation' && !preset.isFallback();
var canFavorite = geom !== 'relation';
_button = selection.selectAll('.preset-favorite-button')
.data(canFavorite ? [0] : []);
@@ -24,31 +24,31 @@ export function uiPresetFavorite(preset, geom, context) {
_button = _button.enter()
.insert('button', '.tag-reference-button')
.attr('class', 'preset-favorite-button')
.attr('class', 'preset-favorite-button ' + klass)
.attr('title', t('icons.favorite'))
.attr('tabindex', -1)
.call(svgIcon('#iD-icon-favorite'))
.merge(_button);
_button
.classed('active', function() {
return context.isFavoritePreset(preset, geom);
})
.on('click', function () {
d3_event.stopPropagation();
d3_event.preventDefault();
//update state of favorite icon
d3_select(this)
.classed('active', function() {
return !d3_select(this).classed('active');
});
context.favoritePreset(preset, geom);
context.favoritePreset(preset, geom);
update();
});
update();
};
function update() {
_button
.classed('active', context.isFavoritePreset(preset, geom));
}
context.on('favoritePreset.button-' + preset.id.replace(/[^a-zA-Z\d:]/g, '-') + '-' + geom, update);
return presetFavorite;
}
+31 -4
View File
@@ -23,10 +23,26 @@ export function uiPresetIcon() {
return 'iD-other-line';
else if (geom === 'vertex')
return p.isFallback() ? '' : 'temaki-vertex';
else if (isSmall() && geom === 'point')
return '';
else
return 'maki-marker-stroked';
}
function renderPointBorder(enter) {
var w = 40, h = 40;
enter = enter
.append('svg')
.attr('class', 'preset-icon-fill preset-icon-point-border')
.attr('width', w)
.attr('height', h)
.attr('viewBox', '0 0 ' + w + ' ' + h);
enter.append('path')
.attr('transform', 'translate(11.5, 8)')
.attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
}
function renderCircleFill(fillEnter) {
var w = 60, h = 60, d = 40;
fillEnter = fillEnter
@@ -128,11 +144,11 @@ export function uiPresetIcon() {
container = container.enter()
.append('div')
.attr('class', 'preset-icon-container')
.attr('class', 'preset-icon-container ' + sizeClass)
.merge(container);
var p = preset.apply(this, arguments);
var geom = geometry.apply(this, arguments);
var geom = geometry ? geometry.apply(this, arguments) : null;
var picon = getIcon(p, geom);
var isMaki = /^maki-/.test(picon);
var isTemaki = /^temaki-/.test(picon);
@@ -151,6 +167,16 @@ export function uiPresetIcon() {
}
var tagClasses = svgTagClasses().getClassesString(tags, '');
var pointBorder = container.selectAll('.preset-icon-point-border')
.data(geom === 'point' && isSmall() ? [0] : []);
pointBorder.exit()
.remove();
var pointBorderEnter = pointBorder.enter();
renderPointBorder(pointBorderEnter);
pointBorder = pointBorderEnter.merge(pointBorder);
var vertexFill = container.selectAll('.preset-icon-fill-vertex')
.data(geom === 'vertex' ? [0] : []);
@@ -206,7 +232,7 @@ export function uiPresetIcon() {
.merge(icon);
icon
.attr('class', 'preset-icon ' + geom + '-geom')
.attr('class', 'preset-icon ' + (geom ? geom + '-geom' : ''))
.classed('framed', isFramed)
.classed('preset-icon-iD', isiDIcon);
@@ -216,7 +242,8 @@ export function uiPresetIcon() {
});
icon.selectAll('use')
.attr('href', '#' + picon + (isMaki ? '-15' : ''));
.attr('href', '#' + picon + (isMaki ? (isSmall() && geom === 'point' ? '-11' : '-15') : ''));
}
+4 -3
View File
@@ -91,7 +91,7 @@ export function uiPresetList(context) {
var value = search.property('value');
if (d3_event.keyCode === 13 && value.length) {
list.selectAll('.preset-list-item:first-child')
.each(function(d) { d.choose.call(d3_select(this).node()); });
.each(function(d) { d.choose.call(this); });
}
}
@@ -339,11 +339,12 @@ export function uiPresetList(context) {
.style('padding-bottom', '0px');
} else {
shown = true;
sublist.call(drawList, preset.members);
var members = preset.members.matchGeometry(context.geometry(_entityID));
sublist.call(drawList, members);
box.transition()
.duration(200)
.style('opacity', '1')
.style('max-height', 200 + preset.members.collection.length * 190 + 'px')
.style('max-height', 200 + members.collection.length * 190 + 'px')
.style('padding-bottom', '10px');
}
};
+1 -1
View File
@@ -77,7 +77,7 @@ export function uiSave(context) {
var button = selection
.append('button')
.attr('class', 'save disabled')
.attr('class', 'save disabled bar-button')
.attr('tabindex', -1)
.on('click', save)
.call(tooltipBehavior);
+469
View File
@@ -0,0 +1,469 @@
import { dispatch as d3_dispatch } from 'd3-dispatch';
import {
event as d3_event,
select as d3_select,
selectAll as d3_selectAll
} from 'd3-selection';
import {
modeAddArea,
modeAddLine,
modeAddPoint
} from '../modes';
import { t, textDirection } from '../util/locale';
import { svgIcon } from '../svg/index';
import { tooltip } from '../util/tooltip';
import { uiTooltipHtml } from './tooltipHtml';
import { uiPresetFavorite } from './preset_favorite';
import { uiPresetIcon } from './preset_icon';
import { utilKeybinding, utilNoAuto, utilRebind } from '../util';
export function uiSearchAdd(context) {
var dispatch = d3_dispatch('choose');
var presets;
var search = d3_select(null), popover = d3_select(null), list = d3_select(null);
var shownGeometry = ['area', 'line', 'point', 'vertex'];
function searchAdd(selection) {
presets = context.presets().matchAnyGeometry(shownGeometry);
var key = t('modes.add_feature.key');
var searchWrap = selection
.append('div')
.attr('class', 'search-wrap')
.call(tooltip()
.placement('bottom')
.html(true)
.title(function() { return uiTooltipHtml(t('modes.add_feature.description'), key); })
);
search = searchWrap
.append('input')
.attr('class', 'search-input')
.attr('placeholder', t('modes.add_feature.title'))
.attr('type', 'search')
.call(utilNoAuto)
.on('mousedown', function() {
search.attr('clicking', true);
})
.on('mouseup', function() {
search.attr('clicking', null);
})
.on('focus', function() {
searchWrap.classed('focused', true);
if (search.attr('clicking')) {
search.attr('focusing', true);
search.attr('clicking', null);
} else {
search.node().setSelectionRange(0, search.property('value').length);
}
popover.classed('hide', false);
})
.on('blur', function() {
searchWrap.classed('focused', false);
popover.classed('hide', true);
})
.on('click', function() {
if (search.attr('focusing')) {
search.node().setSelectionRange(0, search.property('value').length);
search.attr('focusing', null);
}
})
.on('keypress', keypress)
.on('keydown', keydown)
.on('input', searchInput);
searchWrap
.call(svgIcon('#iD-icon-search', 'search-icon pre-text'));
popover = selection
.append('div')
.attr('class', 'popover fillL hide')
.on('mousedown', function() {
// don't blur the search input (and thus close results)
d3_event.preventDefault();
d3_event.stopPropagation();
});
list = popover
.append('div')
.attr('class', 'list');//
//.call(drawList, context.presets().defaults(geometry, 36));
context.features().on('change.search-add', updateForFeatureHiddenState);
context.keybinding().on(key, function() {
search.node().focus();
d3_event.preventDefault();
d3_event.stopPropagation();
});
}
function keypress() {
if (d3_event.keyCode === utilKeybinding.keyCodes.enter) {
popover.selectAll('.list .list-item.focused button.choose')
.each(function(d) { d.choose.call(this); });
d3_event.preventDefault();
d3_event.stopPropagation();
}
}
function keydown() {
var nextFocus,
priorFocus,
parentSubsection;
if (d3_event.keyCode === utilKeybinding.keyCodes['↓'] ||
d3_event.keyCode === utilKeybinding.keyCodes.tab && !d3_event.shiftKey) {
d3_event.preventDefault();
d3_event.stopPropagation();
priorFocus = popover.selectAll('.list .list-item.focused');
if (priorFocus.empty()) {
nextFocus = popover.selectAll('.list > .list-item:first-child');
} else {
nextFocus = popover.selectAll('.list .list-item.focused + .list-item');
if (nextFocus.empty()) {
nextFocus = d3_select(priorFocus.nodes()[0].nextElementSibling)
.selectAll('.list-item:first-child');
}
if (nextFocus.empty()) {
parentSubsection = priorFocus.nodes()[0].closest('.list .subsection');
if (parentSubsection && parentSubsection.nextElementSibling) {
nextFocus = d3_select(parentSubsection.nextElementSibling);
}
}
}
if (!nextFocus.empty()) {
focusListItem(nextFocus);
priorFocus.classed('focused', false);
}
} else if (d3_event.keyCode === utilKeybinding.keyCodes['↑'] ||
d3_event.keyCode === utilKeybinding.keyCodes.tab && d3_event.shiftKey) {
d3_event.preventDefault();
d3_event.stopPropagation();
priorFocus = popover.selectAll('.list .list-item.focused');
if (!priorFocus.empty()) {
nextFocus = d3_select(priorFocus.nodes()[0].previousElementSibling);
if (!nextFocus.empty() && !nextFocus.classed('list-item')) {
nextFocus = nextFocus.selectAll('.list-item:last-child');
}
if (nextFocus.empty()) {
parentSubsection = priorFocus.nodes()[0].closest('.list .subsection');
if (parentSubsection && parentSubsection.previousElementSibling) {
nextFocus = d3_select(parentSubsection.previousElementSibling);
}
}
if (!nextFocus.empty()) {
focusListItem(nextFocus);
priorFocus.classed('focused', false);
}
}
} else if (d3_event.keyCode === utilKeybinding.keyCodes.esc) {
search.node().blur();
d3_event.preventDefault();
d3_event.stopPropagation();
}
}
function searchInput() {
popover.selectAll('.subsection').remove();
var value = search.property('value');
var results;
if (value.length) {
results = presets.search(value, shownGeometry);
} else {
results = context.presets().recent(shownGeometry, 36);
}
list.call(drawList, results);
popover.selectAll('.list .list-item.focused')
.classed('focused', false);
focusListItem(popover.selectAll('.list > .list-item:first-child'));
}
function focusListItem(selection) {
if (!selection.empty()) {
selection.classed('focused', true);
// scroll to keep the focused item visible
scrollPopoverToShow(selection);
}
}
function scrollPopoverToShow(selection) {
if (selection.empty()) return;
var node = selection.nodes()[0];
var popoverNode = popover.node();
if (node.offsetTop < popoverNode.scrollTop) {
popoverNode.scrollTop = node.offsetTop;
} else if (node.offsetTop + node.offsetHeight > popoverNode.scrollTop + popoverNode.offsetHeight &&
node.offsetHeight < popoverNode.offsetHeight) {
popoverNode.scrollTop = node.offsetTop + node.offsetHeight - popoverNode.offsetHeight;
}
}
function itemForPreset(preset) {
if (preset.members) {
return CategoryItem(preset);
}
var supportedGeometry = preset.geometry.filter(function(geometry) {
return shownGeometry.indexOf(geometry) !== -1;
}).sort();
var vertexIndex = supportedGeometry.indexOf('vertex');
if (vertexIndex !== -1 && supportedGeometry.indexOf('point') !== -1) {
// both point and vertex allowed, just show point
supportedGeometry.splice(vertexIndex, 1);
}
if (supportedGeometry.length === 1) {
return AddablePresetItem(preset, supportedGeometry[0]);
}
return MultiGeometryPresetItem(preset, supportedGeometry);
}
function drawList(list, presets) {
var collection = presets.collection.map(function(preset) {
return itemForPreset(preset);
});
var items = list.selectAll('.list-item')
.data(collection, function(d) { return d.preset.id; });
items.order();
items.exit()
.remove();
items.enter();
drawItems(items.enter());
updateForFeatureHiddenState();
}
function drawItems(selection) {
var row = selection
.append('div')
.attr('class', 'list-item')
.attr('id', function(d) {
var id = 'search-add-list-item-preset-' + d.preset.id.replace(/[^a-zA-Z\d:]/g, '-');
if (d.geometry) {
id += '-' + d.geometry;
}
return id;
})
.on('mouseover', function() {
list.selectAll('.list-item.focused')
.classed('focused', false);
d3_select(this)
.classed('focused', true);
})
.on('mouseout', function() {
d3_select(this)
.classed('focused', false);
});
row.append('button')
.attr('class', 'choose')
.on('click', function(d) {
d.choose.call(this);
});
row.each(function(d) {
d3_select(this).call(
uiPresetIcon()
.geometry(d.geometry)
.preset(d.preset)
.sizeClass('small')
);
});
var label = row.append('div')
.attr('class', 'label');
label.each(function(d) {
if (!d.geometry) {
d3_select(this)
.call(svgIcon((textDirection === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward'), 'inline'));
}
});
label.each(function(d) {
if ((d.geometry && !d.isSubitem) || d.geometries) {
// NOTE: split/join on en-dash, not a hypen (to avoid conflict with fr - nl names in Brussels etc)
d3_select(this)
.append('div')
.attr('class', 'label-inner')
.selectAll('.namepart')
.data(d.preset.name().split(' '))
.enter()
.append('div')
.attr('class', 'namepart')
.text(function(d) { return d; });
} else {
d3_select(this).append('span')
.text(function(d) {
if (d.isSubitem) {
if (d.preset.setTags({}, d.geometry).building) {
return t('presets.presets.building.name');
}
return t('modes.add_' + d.geometry + '.title');
}
return d.preset.name();
});
}
});
row.each(function(d) {
if (d.geometry) {
var presetFavorite = uiPresetFavorite(d.preset, d.geometry, context, 'accessory');
d3_select(this).call(presetFavorite.button);
}
});
}
function updateForFeatureHiddenState() {
var listItem = d3_selectAll('.search-add .popover .list-item');
// remove existing tooltips
listItem.selectAll('button.choose').call(tooltip().destroyAny);
listItem.each(function(item, index) {
if (!item.geometry) return;
var hiddenPresetFeaturesId = context.features().isHiddenPreset(item.preset, item.geometry);
var isHiddenPreset = !!hiddenPresetFeaturesId;
var button = d3_select(this).selectAll('button.choose');
d3_select(this).classed('disabled', isHiddenPreset);
button.classed('disabled', isHiddenPreset);
if (isHiddenPreset) {
var isAutoHidden = context.features().autoHidden(hiddenPresetFeaturesId);
var tooltipIdSuffix = isAutoHidden ? 'zoom' : 'manual';
var tooltipObj = { features: t('feature.' + hiddenPresetFeaturesId + '.description') };
button.call(tooltip('dark')
.html(true)
.title(t('inspector.hidden_preset.' + tooltipIdSuffix, tooltipObj))
.placement(index < 2 ? 'bottom' : 'top')
);
}
});
}
function chooseExpandable(item, itemSelection) {
var shouldExpand = !itemSelection.classed('expanded');
itemSelection.classed('expanded', shouldExpand);
var iconName = shouldExpand ?
'#iD-icon-down' : (textDirection === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
itemSelection.selectAll('.label svg.icon use')
.attr('href', iconName);
if (shouldExpand) {
var subitems = item.subitems();
var selector = '#' + itemSelection.node().id + ' + *';
item.subsection = d3_select(itemSelection.node().parentElement).insert('div', selector)
.attr('class', 'subsection');
var subitemsEnter = item.subsection.selectAll('.list-item')
.data(subitems)
.enter();
drawItems(subitemsEnter);
updateForFeatureHiddenState();
scrollPopoverToShow(item.subsection);
} else {
item.subsection.remove();
}
}
function CategoryItem(preset) {
var item = {};
item.subsection = d3_select(null);
item.preset = preset;
item.choose = function() {
var selection = d3_select(this);
if (selection.classed('disabled')) return;
chooseExpandable(item, d3_select(selection.node().closest('.list-item')));
};
item.subitems = function() {
return preset.members.matchAnyGeometry(shownGeometry).collection.map(function(preset) {
return itemForPreset(preset);
});
};
return item;
}
function MultiGeometryPresetItem(preset, geometries) {
var item = {};
item.subsection = d3_select(null);
item.preset = preset;
item.geometries = geometries;
item.choose = function() {
var selection = d3_select(this);
if (selection.classed('disabled')) return;
chooseExpandable(item, d3_select(selection.node().closest('.list-item')));
};
item.subitems = function() {
return geometries.map(function(geometry) {
return AddablePresetItem(preset, geometry, true);
});
};
return item;
}
function AddablePresetItem(preset, geometry, isSubitem) {
var item = {};
item.isSubitem = isSubitem;
item.preset = preset;
item.geometry = geometry;
item.choose = function() {
if (d3_select(this).classed('disabled')) return;
var markerClass = 'add-preset add-' + geometry +
' add-preset-' + preset.name().replace(/\s+/g, '_') + '-' + geometry;
var modeInfo = {
button: markerClass,
preset: preset,
geometry: geometry
};
var mode;
switch (geometry) {
case 'point':
case 'vertex':
mode = modeAddPoint(context, modeInfo);
break;
case 'line':
mode = modeAddLine(context, modeInfo);
break;
case 'area':
mode = modeAddArea(context, modeInfo);
}
search.node().blur();
context.presets().choose(preset);
context.enter(mode);
};
return item;
}
return utilRebind(searchAdd, dispatch, 'on');
}
+6 -1
View File
@@ -189,7 +189,8 @@ export function uiShortcuts(context) {
return _uniq(arr).map(function(s) {
return {
shortcut: s,
separator: d.separator
separator: d.separator,
suffix: d.suffix
};
});
})
@@ -212,6 +213,10 @@ export function uiShortcuts(context) {
selection
.append('span')
.text(d.separator || '\u00a0' + t('shortcuts.or') + '\u00a0');
} else if (i === nodes.length - 1 && d.suffix) {
selection
.append('span')
.text(d.suffix);
}
});
+1 -1
View File
@@ -46,7 +46,7 @@ export function uiUndoRedo(context) {
.data(commands)
.enter()
.append('button')
.attr('class', function(d) { return 'disabled ' + d.id + '-button'; })
.attr('class', function(d) { return 'disabled ' + d.id + '-button bar-button'; })
.on('click', function(d) { return d.action(); })
.call(tooltipBehavior);
+2 -2
View File
@@ -3,7 +3,7 @@ import { utilFunctor } from './index';
var _tooltipID = 0;
export function tooltip() {
export function tooltip(klass) {
var _id = _tooltipID++;
var tooltip = function(selection) {
selection.each(setup);
@@ -98,7 +98,7 @@ export function tooltip() {
var enter = tip.enter()
.append('div')
.attr('class', 'tooltip tooltip-' + _id);
.attr('class', 'tooltip tooltip-' + _id + ' ' + (klass ? klass : ''));
enter
.append('div')
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="60" height="60" viewBox="0 0 60 60">
<path d="M22,41 L25,30 L28,19 L32,19 L35,30 L38,41 z" fill="currentColor" id="category-path-stroke"/>
</svg>

Before

Width:  |  Height:  |  Size: 401 B

-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="60" height="60" viewBox="0 0 60 60">
<path d="M23.5,18 L22,19 L21.531,21 L18.25,21 C17.696,21 17.384,21.463 17.25,22 L17,23 C16.866,23.537 17.446,24 18,24 L42,24 C42.554,24 43.134,23.537 43,23 L42.75,22 C42.616,21.463 42.304,21 41.75,21 L38.969,21 L38.5,19 L37,18 L36,19 L36.469,21 L24.031,21 L24.5,19 L23.5,18 z M21.5,22 C21.776,22 22,22.224 22,22.5 C22,22.776 21.776,23 21.5,23 C21.224,23 21,22.776 21,22.5 C21,22.224 21.224,22 21.5,22 z M38.5,22 C38.776,22 39,22.224 39,22.5 C39,22.776 38.776,23 38.5,23 C38.224,23 38,22.776 38,22.5 C38,22.224 38.224,22 38.5,22 z M20.562,25 L20.094,27 L17.25,27 C16.696,27 16.384,27.463 16.25,28 L16,29 C15.866,29.537 16.446,30 17,30 L43,30 C43.554,30 44.134,29.537 44,29 L43.75,28 C43.616,27.463 43.304,27 42.75,27 L40.406,27 L39.938,25 L37.438,25 L37.906,27 L22.594,27 L23.062,25 L20.562,25 z M20.5,28 C20.776,28 21,28.224 21,28.5 C21,28.776 20.776,29 20.5,29 C20.224,29 20,28.776 20,28.5 C20,28.224 20.224,28 20.5,28 z M39.5,28 C39.776,28 40,28.224 40,28.5 C40,28.776 39.776,29 39.5,29 C39.224,29 39,28.776 39,28.5 C39,28.224 39.224,28 39.5,28 z M19.156,31 L18.688,33 L16.25,33 C15.696,33 15.384,33.463 15.25,34 L15,35 C14.866,35.537 15.446,36 16,36 L44,36 C44.554,36 45.134,35.537 45,35 L44.75,34 C44.616,33.463 44.304,33 43.75,33 L41.812,33 L41.344,31 L38.844,31 L39.312,33 L21.188,33 L21.656,31 L19.156,31 z M19.5,34 C19.776,34 20,34.224 20,34.5 C20,34.776 19.776,35 19.5,35 C19.224,35 19,34.776 19,34.5 C19,34.224 19.224,34 19.5,34 z M40.5,34 C40.776,34 41,34.224 41,34.5 C41,34.776 40.776,35 40.5,35 C40.224,35 40,34.776 40,34.5 C40,34.224 40.224,34 40.5,34 z M17.719,37 L17,40 L18.5,41 L19.5,40 L20.219,37 L17.719,37 z M40.281,37 L41,40 L42,41 L43.5,40 L42.781,37 L40.281,37 z" fill="#989898"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="60" height="60" viewBox="0 0 60 60">
<path d="M22.5,20 L19.625,26 L18,26 L17,27 L17,29 L18.406,29 L18,30 L18,35 L18,36 L18,36 C18,36 18.608,36.608 19,37 L20,37 L24,37 L26,38 L34,38 L36,37 L40,37 L41,37 L42,36 L42,36 L42,35 L42,30 L41.594,29 L43,29 L43,27 L42,26 L40.375,26 L37.5,20 z M23.5,23 L36.5,23 L38,27 L37,28 L23,28 L22,27 z M21,31 L24,31 L25,33 L25,34 L21,34 L20,33 L20,32 z M36,31 L39,31 L40,32 L40,33 L39,34 L35,34 L35,33 z M19,38 L19,40 L20,41 L23,41 L24,40 L24,38 z M36,38 L36,40 L37,41 L40,41 L41,40 L41,38 z" fill="#989898"/>
</svg>

Before

Width:  |  Height:  |  Size: 802 B

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="60" height="60" viewBox="0 0 60 60">
<svg y="7">
<path d="M20,10 L20,11 L22,11 L22,10 L20,10 z M24,10 L24,11 L26,11 L26,10 L24,10 z M34,10 L34,11 L36,11 L36,10 L34,10 z M38,10 L38,11 L40,11 L40,10 L38,10 z M20.312,15 C19.647,18.533 17.267,20.5 15,20.5 L14,20.5 L14,21.5 L15,21.5 C16.042,21.5 17.082,21.196 18,20.594 L18,21.5 L19,21.5 C21.879,21.5 24.615,19.022 25.312,15 L24.312,15 C23.647,18.533 21.267,20.5 19,20.5 L18.125,20.5 C19.686,19.42 20.885,17.509 21.312,15 L20.312,15 z M34.688,15 C35.385,19.022 38.121,21.5 41,21.5 L42,21.5 L42,20.594 C42.918,21.196 43.958,21.5 45,21.5 L46,21.5 L46,20.5 L45,20.5 C42.733,20.5 40.353,18.533 39.688,15 L38.688,15 C39.115,17.509 40.314,19.42 41.875,20.5 L41,20.5 C38.733,20.5 36.353,18.533 35.688,15 L34.688,15 z" fill="#989898"/>
<path d="M28,10 L28,12 L19,12 L19,14 L28,14 L28,36 L32,36 L32,14 L41,14 L41,12 L32,12 L32,10 L28,10 z" fill="#989898"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="60" height="60" viewBox="0 0 60 60">
<path d="M16.762,41 C16.762,41 16.225,39.154 16.417,38.25 C16.638,37.203 18.071,35.5 18.071,35.5 C18.071,35.5 19.505,33.797 19.726,32.75 C19.917,31.846 19.381,30 19.381,30 C19.381,30 18.844,28.154 19.036,27.25 C19.257,26.203 20.69,24.5 20.69,24.5 C20.69,24.5 22.124,22.797 22.345,21.75 C22.536,20.846 22,19 22,19 L38.5,19 C38.5,19 39.933,20.703 40.155,21.75 C40.346,22.654 39.809,24.5 39.809,24.5 C39.809,24.5 39.273,26.346 39.464,27.25 C39.686,28.297 41.119,30 41.119,30 C41.119,30 42.552,31.703 42.774,32.75 C42.965,33.654 42.428,35.5 42.428,35.5 C42.428,35.5 41.892,37.346 42.083,38.25 C42.305,39.297 43.738,41 43.738,41 z" fill="currentColor" id="category-water-stroke1"/>
<path d="M17.966,32.759 C17.751,33.559 17.145,34.092 16.612,33.949 C16.078,33.806 15.82,33.041 16.034,32.241 C16.248,31.441 16.855,30.908 17.388,31.051 C17.922,31.194 18.18,31.959 17.966,32.759 z M19.799,22.75 C20.351,21.793 20.217,20.682 19.5,20.268 C18.783,19.854 17.753,20.293 17.201,21.25 C16.649,22.207 16.783,23.318 17.5,23.732 C18.217,24.146 19.247,23.707 19.799,22.75 z M41.422,26.708 C41.208,25.908 41.467,25.143 42,25 C42.533,24.857 43.14,25.39 43.354,26.19 C43.569,26.99 43.31,27.755 42.776,27.898 C42.243,28.041 41.637,27.508 41.422,26.708 z M44.299,37.75 C43.747,36.793 43.881,35.682 44.598,35.268 C45.316,34.854 46.345,35.293 46.897,36.25 C47.449,37.207 47.316,38.318 46.598,38.732 C45.881,39.146 44.851,38.707 44.299,37.75 z" fill="currentColor" id="category-water-stroke2" opacity="0.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB