diff --git a/css/20_map.css b/css/20_map.css index 21f215e51..abcc08cf5 100644 --- a/css/20_map.css +++ b/css/20_map.css @@ -32,7 +32,7 @@ g.point .stroke { g.point .shadow { fill: none; stroke: #f6634f; - stroke-width: 8; + stroke-width: 16; stroke-opacity: 0; } @@ -74,6 +74,7 @@ g.midpoint .fill { g.vertex .shadow, g.midpoint .shadow { + stroke-width: 16; fill: #f6634f; fill-opacity: 0; } @@ -141,7 +142,7 @@ path.stroke { path.shadow { stroke: #f6634f; - stroke-width: 10; + stroke-width: 16; stroke-opacity: 0; } diff --git a/css/30_highways.css b/css/30_highways.css index 937dea366..76505ebf0 100644 --- a/css/30_highways.css +++ b/css/30_highways.css @@ -1,39 +1,44 @@ /* highways */ +.preset-icon .icon.tag-highway.other-line { + color: #fff; + fill: #777; +} +path.casing.tag-highway { + stroke: #444; +} +path.stroke.tag-highway { + stroke: #ccc; +} + /* highway areas */ + path.stroke.area.tag-highway { - stroke:#fff; + stroke: #fff; stroke-dasharray: none; stroke-width: 2; } /* wide highways */ -.preset-icon .icon.tag-highway.other-line { - color: #fff; - fill: #777; -} - path.shadow.tag-highway { - stroke-width:16; + stroke-width: 20; } path.casing.tag-highway { - stroke:#444; - stroke-width:10; + stroke-width: 10; } path.stroke.tag-highway { - stroke:#ccc; - stroke-width:8; + stroke-width: 8; } .low-zoom path.shadow.tag-highway { - stroke-width:12; + stroke-width: 16; } .low-zoom path.casing.tag-highway { - stroke-width:6; + stroke-width: 7; } .low-zoom path.stroke.tag-highway { - stroke-width:4; + stroke-width: 5; } .preset-icon .icon.highway-motorway, @@ -224,33 +229,54 @@ path.casing.tag-unclassified { /* narrow highways */ -path.stroke.tag-highway-living_street, -path.stroke.tag-highway-service, -path.stroke.tag-highway-track, -path.stroke.tag-highway-path, -path.stroke.tag-highway-footway, -path.stroke.tag-highway-cycleway, -path.stroke.tag-highway-bridleway, -path.stroke.tag-highway-corridor, -path.stroke.tag-highway-pedestrian, -path.stroke.tag-highway-steps, -path.stroke.tag-highway-road, -path.stroke.tag-living_street, -path.stroke.tag-service, -path.stroke.tag-track, -path.stroke.tag-path, -path.stroke.tag-footway, -path.stroke.tag-cycleway, -path.stroke.tag-bridleway, -path.stroke.tag-corridor, -path.stroke.tag-pedestrian, -path.stroke.tag-steps, -path.stroke.tag-road { - stroke-width:4; + +path.shadow.tag-highway-living_street, +path.shadow.tag-highway-service, +path.shadow.tag-highway-track, +path.shadow.tag-highway-road, +path.shadow.tag-living_street, +path.shadow.tag-service, +path.shadow.tag-track, +path.shadow.tag-road { + stroke-width: 16; } path.casing.tag-highway-living_street, path.casing.tag-highway-service, path.casing.tag-highway-track, +path.casing.tag-highway-road, +path.casing.tag-living_street, +path.casing.tag-service, +path.casing.tag-track, +path.casing.tag-road { + stroke-width: 7; +} +path.stroke.tag-highway-living_street, +path.stroke.tag-highway-service, +path.stroke.tag-highway-track, +path.stroke.tag-highway-road, +path.stroke.tag-living_street, +path.stroke.tag-service, +path.stroke.tag-track, +path.stroke.tag-road { + stroke-width: 5; +} + +path.shadow.tag-highway-path, +path.shadow.tag-highway-footway, +path.shadow.tag-highway-cycleway, +path.shadow.tag-highway-bridleway, +path.shadow.tag-highway-corridor, +path.shadow.tag-highway-pedestrian, +path.shadow.tag-highway-steps, +path.shadow.tag-path, +path.shadow.tag-footway, +path.shadow.tag-cycleway, +path.shadow.tag-bridleway, +path.shadow.tag-corridor, +path.shadow.tag-pedestrian, +path.shadow.tag-steps { + stroke-width: 16; +} path.casing.tag-highway-path, path.casing.tag-highway-footway, path.casing.tag-highway-cycleway, @@ -258,48 +284,79 @@ path.casing.tag-highway-bridleway, path.casing.tag-highway-corridor, path.casing.tag-highway-pedestrian, path.casing.tag-highway-steps, -path.casing.tag-highway-road, -path.casing.tag-living_street, -path.casing.tag-service, -path.casing.tag-track, path.casing.tag-path, path.casing.tag-footway, path.casing.tag-cycleway, path.casing.tag-bridleway, path.casing.tag-corridor, path.casing.tag-pedestrian, -path.casing.tag-steps, -path.casing.tag-road { - stroke-width:6; +path.casing.tag-steps { + stroke-width: 5; +} +path.stroke.tag-highway-path, +path.stroke.tag-highway-footway, +path.stroke.tag-highway-cycleway, +path.stroke.tag-highway-bridleway, +path.stroke.tag-highway-corridor, +path.stroke.tag-highway-pedestrian, +path.stroke.tag-highway-steps, +path.stroke.tag-path, +path.stroke.tag-footway, +path.stroke.tag-cycleway, +path.stroke.tag-bridleway, +path.stroke.tag-corridor, +path.stroke.tag-pedestrian, +path.stroke.tag-steps { + stroke-width: 3; } -.low-zoom path.stroke.tag-highway-living_street, -.low-zoom path.stroke.tag-highway-service, -.low-zoom path.stroke.tag-highway-track, -.low-zoom path.stroke.tag-highway-path, -.low-zoom path.stroke.tag-highway-footway, -.low-zoom path.stroke.tag-highway-cycleway, -.low-zoom path.stroke.tag-highway-bridleway, -.low-zoom path.stroke.tag-highway-corridor, -.low-zoom path.stroke.tag-highway-pedestrian, -.low-zoom path.stroke.tag-highway-steps, -.low-zoom path.stroke.tag-highway-road, -.low-zoom path.stroke.tag-living_street, -.low-zoom path.stroke.tag-service, -.low-zoom path.stroke.tag-track, -.low-zoom path.stroke.tag-path, -.low-zoom path.stroke.tag-footway, -.low-zoom path.stroke.tag-cycleway, -.low-zoom path.stroke.tag-bridleway, -.low-zoom path.stroke.tag-corridor, -.low-zoom path.stroke.tag-pedestrian, -.low-zoom path.stroke.tag-steps, -.low-zoom path.stroke.tag-road { - stroke-width:2; +.low-zoom path.shadow.tag-highway-living_street, +.low-zoom path.shadow.tag-highway-service, +.low-zoom path.shadow.tag-highway-track, +.low-zoom path.shadow.tag-highway-road, +.low-zoom path.shadow.tag-living_street, +.low-zoom path.shadow.tag-service, +.low-zoom path.shadow.tag-track, +.low-zoom path.shadow.tag-road { + stroke-width: 12; } .low-zoom path.casing.tag-highway-living_street, .low-zoom path.casing.tag-highway-service, .low-zoom path.casing.tag-highway-track, +.low-zoom path.casing.tag-highway-road, +.low-zoom path.casing.tag-living_street, +.low-zoom path.casing.tag-service, +.low-zoom path.casing.tag-track, +.low-zoom path.casing.tag-road { + stroke-width: 5; +} +.low-zoom path.stroke.tag-highway-living_street, +.low-zoom path.stroke.tag-highway-service, +.low-zoom path.stroke.tag-highway-track, +.low-zoom path.stroke.tag-highway-road, +.low-zoom path.stroke.tag-living_street, +.low-zoom path.stroke.tag-service, +.low-zoom path.stroke.tag-track, +.low-zoom path.stroke.tag-road { + stroke-width: 3; +} + +.low-zoom path.shadow.tag-highway-path, +.low-zoom path.shadow.tag-highway-footway, +.low-zoom path.shadow.tag-highway-cycleway, +.low-zoom path.shadow.tag-highway-bridleway, +.low-zoom path.shadow.tag-highway-corridor, +.low-zoom path.shadow.tag-highway-pedestrian, +.low-zoom path.shadow.tag-highway-steps, +.low-zoom path.shadow.tag-path, +.low-zoom path.shadow.tag-footway, +.low-zoom path.shadow.tag-cycleway, +.low-zoom path.shadow.tag-bridleway, +.low-zoom path.shadow.tag-corridor, +.low-zoom path.shadow.tag-pedestrian, +.low-zoom path.shadow.tag-steps { + stroke-width: 12; +} .low-zoom path.casing.tag-highway-path, .low-zoom path.casing.tag-highway-footway, .low-zoom path.casing.tag-highway-cycleway, @@ -307,20 +364,32 @@ path.casing.tag-road { .low-zoom path.casing.tag-highway-corridor, .low-zoom path.casing.tag-highway-pedestrian, .low-zoom path.casing.tag-highway-steps, -.low-zoom path.casing.tag-highway-road, -.low-zoom path.casing.tag-living_street, -.low-zoom path.casing.tag-service, -.low-zoom path.casing.tag-track, .low-zoom path.casing.tag-path, .low-zoom path.casing.tag-footway, .low-zoom path.casing.tag-cycleway, .low-zoom path.casing.tag-bridleway, .low-zoom path.casing.tag-corridor, .low-zoom path.casing.tag-pedestrian, -.low-zoom path.casing.tag-steps, -.low-zoom path.casing.tag-road { - stroke-width:4; +.low-zoom path.casing.tag-steps { + stroke-width: 3; } +.low-zoom path.stroke.tag-highway-path, +.low-zoom path.stroke.tag-highway-footway, +.low-zoom path.stroke.tag-highway-cycleway, +.low-zoom path.stroke.tag-highway-bridleway, +.low-zoom path.stroke.tag-highway-corridor, +.low-zoom path.stroke.tag-highway-pedestrian, +.low-zoom path.stroke.tag-highway-steps, +.low-zoom path.stroke.tag-path, +.low-zoom path.stroke.tag-footway, +.low-zoom path.stroke.tag-cycleway, +.low-zoom path.stroke.tag-bridleway, +.low-zoom path.stroke.tag-corridor, +.low-zoom path.stroke.tag-pedestrian, +.low-zoom path.stroke.tag-steps { + stroke-width: 1; +} + .preset-icon .icon.highway-living-street { color: #bbb; @@ -347,6 +416,12 @@ path.stroke.tag-pedestrian { stroke:#fff; stroke-dasharray: 2, 8; } +.low-zoom path.stroke.tag-highway-corridor, +.low-zoom path.stroke.tag-highway-pedestrian, +.low-zoom path.stroke.tag-corridor, +.low-zoom path.stroke.tag-pedestrian { + stroke-dasharray: 1, 4; +} path.casing.tag-highway-corridor, path.casing.tag-highway-pedestrian, path.casing.tag-corridor, @@ -406,6 +481,13 @@ path.stroke.tag-highway-bridleway { stroke-linecap: butt; stroke-dasharray: 6, 6; } +.low-zoom path.stroke.tag-highway-path, +.low-zoom path.stroke.tag-highway-footway, +.low-zoom path.stroke.tag-highway-cycleway, +.low-zoom path.stroke.tag-highway-bridleway { + stroke-linecap: butt; + stroke-dasharray: 3, 3; +} path.casing.tag-highway-path, path.casing.tag-highway-path.tag-unpaved { @@ -450,6 +532,9 @@ path.stroke.tag-highway-footway.tag-crossing { stroke: #444; stroke-dasharray: 6, 4; } +.low-zoom path.stroke.tag-highway-footway.tag-crossing { + stroke-dasharray: 3, 2; +} .preset-icon .icon.tag-route-bicycle, .preset-icon .icon.highway-cycleway { @@ -478,6 +563,9 @@ path.stroke.tag-highway-steps { stroke-linecap: butt; stroke-dasharray: 3, 3; } +.low-zoom path.stroke.tag-highway-steps { + stroke-dasharray: 2, 2; +} path.casing.tag-highway-steps, path.casing.tag-highway-steps.tag-unpaved { stroke: #fff; diff --git a/css/35_aeroways.css b/css/35_aeroways.css index 13f94f992..7598949d3 100644 --- a/css/35_aeroways.css +++ b/css/35_aeroways.css @@ -7,23 +7,32 @@ path.stroke.area.tag-aeroway { stroke-width: 2; } -/* lines */ -path.stroke.tag-aeroway-taxiway, -path.stroke.tag-taxiway { - stroke-width: 4; +/* narrow aeroways (taxiway) */ + +path.shadow.tag-aeroway-taxiway, +path.shadow.tag-taxiway { + stroke-width: 16; } path.casing.tag-aeroway-taxiway, path.casing.tag-taxiway { - stroke-width: 6; + stroke-width: 7; +} +path.stroke.tag-aeroway-taxiway, +path.stroke.tag-taxiway { + stroke-width: 5; } -.low-zoom path.stroke.tag-aeroway-taxiway, -.low-zoom path.stroke.tag-taxiway { - stroke-width: 2; +.low-zoom path.shadow.tag-aeroway-taxiway, +.low-zoom path.shadow.tag-taxiway { + stroke-width: 12; } .low-zoom path.casing.tag-aeroway-taxiway, .low-zoom path.casing.tag-taxiway { - stroke-width: 4; + stroke-width: 5; +} +.low-zoom path.stroke.tag-aeroway-taxiway, +.low-zoom path.stroke.tag-taxiway { + stroke-width: 3; } .preset-icon .icon.tag-aeroway-taxiway, @@ -40,6 +49,9 @@ path.casing.tag-taxiway { stroke: #666; } + +/* wide aeroways (runway) */ + .preset-icon .icon.tag-aeroway-runway, .preset-icon .icon.tag-runway { color: #444; @@ -48,17 +60,29 @@ path.casing.tag-taxiway { path.shadow.tag-aeroway-runway { stroke-width: 20; } +path.casing.tag-aeroway-runway { + stroke-width: 10; + stroke: #000; + stroke-linecap: square; +} path.stroke.tag-aeroway-runway { stroke: #fff; stroke-width: 2; stroke-linecap: butt; stroke-dasharray: 24, 48; } -path.casing.tag-aeroway-runway { - stroke-width: 10; - stroke: #000; - stroke-linecap: square; + +.low-zoom path.shadow.tag-aeroway-runway { + stroke-width: 16; } +.low-zoom path.casing.tag-aeroway-runway { + stroke-width: 7; +} +.low-zoom path.stroke.tag-aeroway-runway { + stroke-width: 2; + stroke-dasharray: 12, 24; +} + path.fill.tag-aeroway-runway { stroke: rgba(0, 0, 0, 0.6); fill: rgba(0, 0, 0, 0.6); diff --git a/css/40_railways.css b/css/40_railways.css index aaf62bf82..4649ae2ea 100644 --- a/css/40_railways.css +++ b/css/40_railways.css @@ -8,48 +8,77 @@ color: #555; fill: #eee; } + +/* narrow widths */ + +path.shadow.tag-railway { + stroke-width: 16; +} +path.casing.tag-railway { + stroke-width: 7; +} path.stroke.tag-railway { - stroke: #eee; stroke-width: 2; stroke-linecap: butt; stroke-dasharray: 12,12; } + +.low-zoom path.shadow.tag-railway { + stroke-width: 12; +} +.low-zoom path.casing.tag-railway { + stroke-width: 5; +} +.low-zoom path.stroke.tag-railway { + stroke-width: 2; + stroke-dasharray: 6,6; +} + + +/* styles */ + path.casing.tag-railway { stroke: #555; - stroke-width: 4; } +path.stroke.tag-railway { + stroke: #eee; +} + .preset-icon .icon.tag-railway-disused, .preset-icon .icon.tag-railway-abandoned { color: #999; fill: #eee; } -path.stroke.tag-railway-abandoned { - stroke: #eee; -} path.casing.tag-railway-abandoned { stroke: #999; } +path.stroke.tag-railway-abandoned { + stroke: #eee; +} + .preset-icon .icon.tag-railway-subway { color: #222; fill: #bbb; } -path.stroke.tag-railway-subway { - stroke: #bbb; -} path.casing.tag-railway-subway { stroke: #222; } +path.stroke.tag-railway-subway { + stroke: #bbb; +} + +path.casing.tag-railway-platform { + stroke: none; +} path.stroke.tag-railway-platform { stroke: #999; stroke-width: 4; stroke-dasharray: none; } -path.casing.tag-railway-platform { - stroke: none; -} + .area.stroke.tag-railway { stroke: white; diff --git a/css/45_waterways.css b/css/45_waterways.css index ca51b1a7b..44996a97e 100644 --- a/css/45_waterways.css +++ b/css/45_waterways.css @@ -15,35 +15,72 @@ path.fill.tag-waterway { stroke: rgba(119, 211, 222, 0.3); fill: rgba(119, 211, 222, 0.3); } - +path.casing.tag-waterway { + stroke: #3d6c71; +} path.stroke.tag-waterway { stroke: #77d3de; - stroke-width: 2; +} + + +/* narrow waterways (default) */ + +path.shadow.tag-waterway { + stroke-width: 16; } path.casing.tag-waterway { - stroke: #77d3de; - stroke-width: 4; + stroke-width: 7; +} +path.stroke.tag-waterway { + stroke-width: 5; } -path.stroke.tag-waterway-river { - stroke-width: 4; +.low-zoom path.shadow.tag-waterway { + stroke-width: 12; } -path.casing.tag-waterway-river { - stroke-width: 6; +.low-zoom path.casing.tag-waterway { + stroke-width: 5; } - -.preset-icon .icon.tag-waterway-ditch { - color: #6591ff; -} -path.stroke.tag-waterway-ditch { - stroke: #6591ff; - stroke-width: 1; -} -path.casing.tag-waterway-ditch { - stroke: #6591ff; +.low-zoom path.stroke.tag-waterway { stroke-width: 3; } + +/* wide waterways (river) */ + +path.shadow.tag-waterway-river { + stroke-width: 20; +} +path.casing.tag-waterway-river { + stroke-width: 10; +} +path.stroke.tag-waterway-river { + stroke-width: 8; +} + +.low-zoom path.shadow.tag-waterway-river { + stroke-width: 16; +} +.low-zoom path.casing.tag-waterway-river { + stroke-width: 7; +} +.low-zoom path.stroke.tag-waterway-river { + stroke-width: 5; +} + + +/* ditch */ + +.preset-icon .icon.tag-waterway-ditch { + color: #8eabf3; +} +path.stroke.tag-waterway-ditch { + stroke: #8eabf3; +} + + +/* waterway areas */ + path.area.stroke.tag-waterway-dock, path.area.stroke.tag-waterway-boatyard, path.area.stroke.tag-waterway-fuel { diff --git a/css/50_misc.css b/css/50_misc.css index fb1a9332c..faae427ad 100644 --- a/css/50_misc.css +++ b/css/50_misc.css @@ -48,7 +48,6 @@ path.stroke.tag-barrier { /* bridges */ path.casing.tag-bridge { - stroke-width: 16; stroke-opacity: 0.6; stroke: #000; stroke-linecap: butt; @@ -58,6 +57,29 @@ path.casing.tag-bridge { path.shadow.tag-bridge { stroke-width: 22; } +path.casing.tag-bridge { + stroke-width: 16; +} +.low-zoom path.shadow.tag-bridge { + stroke-width: 14; +} +.low-zoom path.casing.tag-bridge { + stroke-width: 10; +} + +path.shadow.line.tag-railway.tag-bridge, +path.shadow.tag-highway-living_street.tag-bridge, +path.shadow.tag-highway-path.tag-bridge, +path.shadow.tag-highway-corridor.tag-bridge, +path.shadow.line.tag-highway-pedestrian.tag-bridge, +path.shadow.tag-highway-service.tag-bridge, +path.shadow.tag-highway-track.tag-bridge, +path.shadow.tag-highway-steps.tag-bridge, +path.shadow.tag-highway-footway.tag-bridge, +path.shadow.tag-highway-cycleway.tag-bridge, +path.shadow.tag-highway-bridleway.tag-bridge { + stroke-width: 17; +} path.casing.line.tag-railway.tag-bridge, path.casing.tag-highway-living_street.tag-bridge, path.casing.tag-highway-path.tag-bridge, @@ -71,39 +93,6 @@ path.casing.tag-highway-cycleway.tag-bridge, path.casing.tag-highway-bridleway.tag-bridge { stroke-width: 10; } -path.shadow.line.tag-railway.tag-bridge, -path.shadow.tag-highway-living_street.tag-bridge, -path.shadow.tag-highway-path.tag-bridge, -path.shadow.tag-highway-corridor.tag-bridge, -path.shadow.line.tag-highway-pedestrian.tag-bridge, -path.shadow.tag-highway-service.tag-bridge, -path.shadow.tag-highway-track.tag-bridge, -path.shadow.tag-highway-steps.tag-bridge, -path.shadow.tag-highway-footway.tag-bridge, -path.shadow.tag-highway-cycleway.tag-bridge, -path.shadow.tag-highway-bridleway.tag-bridge { - stroke-width: 17; -} -.low-zoom path.casing.tag-bridge { - stroke-width: 10; -} -.low-zoom path.shadow.tag-bridge { - stroke-width: 14; -} - -.low-zoom path.casing.line.tag-railway.tag-bridge, -.low-zoom path.casing.tag-highway-living_street.tag-bridge, -.low-zoom path.casing.tag-highway-path.tag-bridge, -.low-zoom path.casing.tag-highway-corridor.tag-bridge, -.low-zoom path.casing.line.tag-highway-pedestrian.tag-bridge, -.low-zoom path.casing.tag-highway-service.tag-bridge, -.low-zoom path.casing.tag-highway-track.tag-bridge, -.low-zoom path.casing.tag-highway-steps.tag-bridge, -.low-zoom path.casing.tag-highway-footway.tag-bridge, -.low-zoom path.casing.tag-highway-cycleway.tag-bridge, -.low-zoom path.casing.tag-highway-bridleway.tag-bridge { - stroke-width: 6; -} .low-zoom path.shadow.line.tag-railway.tag-bridge, .low-zoom path.shadow.tag-highway-living_street.tag-bridge, @@ -116,7 +105,20 @@ path.shadow.tag-highway-bridleway.tag-bridge { .low-zoom path.shadow.tag-highway-footway.tag-bridge, .low-zoom path.shadow.tag-highway-cycleway.tag-bridge, .low-zoom path.shadow.tag-highway-bridleway.tag-bridge { - stroke-width: 13; + stroke-width: 14; +} +.low-zoom path.casing.line.tag-railway.tag-bridge, +.low-zoom path.casing.tag-highway-living_street.tag-bridge, +.low-zoom path.casing.tag-highway-path.tag-bridge, +.low-zoom path.casing.tag-highway-corridor.tag-bridge, +.low-zoom path.casing.line.tag-highway-pedestrian.tag-bridge, +.low-zoom path.casing.tag-highway-service.tag-bridge, +.low-zoom path.casing.tag-highway-track.tag-bridge, +.low-zoom path.casing.tag-highway-steps.tag-bridge, +.low-zoom path.casing.tag-highway-footway.tag-bridge, +.low-zoom path.casing.tag-highway-cycleway.tag-bridge, +.low-zoom path.casing.tag-highway-bridleway.tag-bridge { + stroke-width: 6; } @@ -132,6 +134,10 @@ path.casing.tag-tunnel { /* embankments / cuttings */ +path.shadow.tag-embankment, +path.shadow.tag-cutting { + stroke-width: 28; +} path.casing.tag-embankment, path.casing.tag-cutting { stroke-opacity: 0.5; @@ -141,20 +147,14 @@ path.casing.tag-cutting { stroke-linecap: butt; } -path.shadow.tag-embankment, -path.shadow.tag-cutting { - stroke-width: 28; -} - -.low-zoom path.casing.tag-embankment, -.low-zoom path.casing.tag-cutting { - stroke-width: 10; -} - .low-zoom path.shadow.tag-embankment, .low-zoom path.shadow.tag-cutting { stroke-width: 14; } +.low-zoom path.casing.tag-embankment, +.low-zoom path.casing.tag-cutting { + stroke-width: 10; +} /* Surface - unpaved */ diff --git a/css/70_fills.css b/css/70_fills.css index 6d564417a..9402eec5d 100644 --- a/css/70_fills.css +++ b/css/70_fills.css @@ -10,15 +10,15 @@ .low-zoom.fill-wireframe path.shadow, .fill-wireframe path.shadow { - stroke-width: 8 !important; + stroke-width: 12; } .fill-wireframe path.shadow.related:not(.selected), .fill-wireframe path.shadow.hover:not(.selected) { - stroke-opacity: 0.4 !important; + stroke-opacity: 0.4; } .fill-wireframe path.shadow.selected { - stroke-opacity: 0.6 !important; + stroke-opacity: 0.6; } .fill-wireframe .point, diff --git a/css/80_app.css b/css/80_app.css index cfd30e4a6..dab8de5ae 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -1610,6 +1610,15 @@ div.combobox { clear: both; } +.tag-row.readonly, +.tag-row.readonly input.key, +.tag-row.readonly input.value, +.tag-row.readonly button.remove { + color: #777777; + background-color: #eee; + cursor: not-allowed; +} + .tag-row input { height: 31px; border: 0; @@ -1682,7 +1691,7 @@ div.combobox { /* Adding form fields to tag editor */ -.inspector-inner .add-tag { +.raw-tag-editor .add-tag { width: 40%; height: 30px; border-top: 0; @@ -1690,11 +1699,11 @@ div.combobox { border-radius: 0 0 4px 4px; } -.inspector-inner .add-tag:hover { +.raw-tag-editor .add-tag:hover { background: rgba(0,0,0,.8); } -.inspector-inner .add-tag .label { +.raw-tag-editor .add-tag .label { display: none; } diff --git a/data/presets.yaml b/data/presets.yaml index 295c52ba3..861a9fd4d 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -316,6 +316,9 @@ en: anticlockwise: Counterclockwise # direction=clockwise clockwise: Clockwise + club: + # club=* + label: Type collection_times: # collection_times=* label: Collection Times @@ -1435,6 +1438,21 @@ en: amenity: # amenity=* name: Amenity + amenity/animal_boarding: + # amenity=animal_boarding + name: Animal Boarding Facility + # 'terms: boarding,cat,dog,horse,kitten,pet boarding,pet care,pet hotel,puppy,reptile' + terms: '' + amenity/animal_breeding: + # amenity=animal_breeding + name: Animal Breeding Facility + # 'terms: breeding,bull,cat,cow,dog,horse,husbandry,kitten,livestock,pet breeding,puppy,reptile' + terms: '' + amenity/animal_shelter: + # amenity=animal_shelter + name: Animal Shelter + # 'terms: adoption,aspca,cat,dog,horse,kitten,pet care,pet rescue,puppy,raptor,reptile,rescue,spca' + terms: '' amenity/arts_centre: # amenity=arts_centre name: Arts Center @@ -1589,6 +1607,10 @@ en: name: Drinking Water # 'terms: fountain,potable' terms: '' + amenity/driving_school: + # amenity=driving_school + name: Driving School + terms: '' amenity/embassy: # amenity=embassy name: Embassy @@ -1929,6 +1951,10 @@ en: # amenity=water_point name: RV Drinking Water terms: '' + amenity/watering_place: + # amenity=watering_place + name: Animal Watering Place + terms: '' area: # area=yes name: Area @@ -2166,6 +2192,11 @@ en: name: Camp Pitch # 'terms: tent,rv' terms: '' + club: + # club=* + name: Club + # 'terms: social' + terms: '' craft: # craft=* name: Craft @@ -3017,6 +3048,11 @@ en: # 'leisure=pitch, sport=cricket' name: Cricket Field terms: '' + leisure/pitch/equestrian: + # 'leisure=pitch, sport=equestrian' + name: Riding Arena + # 'terms: dressage,equestrian,horse,horseback,riding' + terms: '' leisure/pitch/rugby_league: # 'leisure=pitch, sport=rugby_league' name: Rugby League Field @@ -3483,15 +3519,20 @@ en: name: Neighborhood # 'terms: neighbourhood' terms: '' + place/quarter: + # place=quarter + name: Sub-Borough / Quarter + # 'terms: boro,borough,quarter' + terms: '' place/square: # place=square name: Square terms: '' place/suburb: # place=suburb - name: Borough - # 'terms: Boro,Quarter' - terms: '' + name: Borough / Suburb + # 'terms: boro,borough,quarter' + terms: '' place/town: # place=town name: Town @@ -3880,6 +3921,11 @@ en: name: Garden Center # 'terms: landscape,mulch,shrub,tree' terms: '' + shop/gas: + # shop=gas + name: Bottled Gas Shop + # 'terms: cng,lpg,natural gas,propane,refill,tank' + terms: '' shop/gift: # shop=gift name: Gift Shop @@ -4022,10 +4068,14 @@ en: # shop=pawnbroker name: Pawn Shop terms: '' + shop/perfumery: + # shop=perfumery + name: Perfume Store + terms: '' shop/pet: # shop=pet name: Pet Store - # 'terms: cat,dog,fish' + # 'terms: animal,cat,dog,fish,kitten,puppy,reptile' terms: '' shop/photo: # shop=photo diff --git a/data/presets/fields.json b/data/presets/fields.json index c51733d1b..1d329dea0 100644 --- a/data/presets/fields.json +++ b/data/presets/fields.json @@ -401,6 +401,11 @@ } } }, + "club": { + "key": "club", + "type": "typeCombo", + "label": "Type" + }, "collection_times": { "key": "collection_times", "type": "text", diff --git a/data/presets/fields/club.json b/data/presets/fields/club.json new file mode 100644 index 000000000..9483b0113 --- /dev/null +++ b/data/presets/fields/club.json @@ -0,0 +1,5 @@ +{ + "key": "club", + "type": "typeCombo", + "label": "Type" +} diff --git a/data/presets/presets.json b/data/presets/presets.json index 1ca16bfc0..db95c5e5d 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -564,6 +564,98 @@ "name": "Swimming Pool", "searchable": false }, + "amenity/animal_boarding": { + "icon": "veterinary", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "boarding", + "cat", + "dog", + "horse", + "kitten", + "pet boarding", + "pet care", + "pet hotel", + "puppy", + "reptile" + ], + "tags": { + "amenity": "animal_boarding" + }, + "name": "Animal Boarding Facility" + }, + "amenity/animal_breeding": { + "icon": "veterinary", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "breeding", + "bull", + "cat", + "cow", + "dog", + "horse", + "husbandry", + "kitten", + "livestock", + "pet breeding", + "puppy", + "reptile" + ], + "tags": { + "amenity": "animal_breeding" + }, + "name": "Animal Breeding Facility" + }, + "amenity/animal_shelter": { + "icon": "veterinary", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "adoption", + "aspca", + "cat", + "dog", + "horse", + "kitten", + "pet care", + "pet rescue", + "puppy", + "raptor", + "reptile", + "rescue", + "spca" + ], + "tags": { + "amenity": "animal_shelter" + }, + "name": "Animal Shelter" + }, "amenity/arts_centre": { "icon": "theatre", "fields": [ @@ -1201,6 +1293,23 @@ ], "name": "Drinking Water" }, + "amenity/driving_school": { + "icon": "car", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "amenity": "driving_school" + }, + "name": "Driving School" + }, "amenity/embassy": { "icon": "embassy", "fields": [ @@ -2776,6 +2885,18 @@ }, "name": "RV Drinking Water" }, + "amenity/watering_place": { + "icon": "drinking-water", + "geometry": [ + "area", + "vertex", + "point" + ], + "tags": { + "amenity": "watering_place" + }, + "name": "Animal Watering Place" + }, "area": { "name": "Area", "tags": { @@ -3660,6 +3781,27 @@ }, "name": "Camp Pitch" }, + "club": { + "icon": "heart", + "fields": [ + "club", + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "club": "*" + }, + "terms": [ + "social" + ], + "name": "Club" + }, "craft": { "icon": "poi-tool", "fields": [ @@ -4658,7 +4800,9 @@ "icon": "poi-fire-hydrant", "fields": [ "fire_hydrant/type", - "fire_hydrant/position" + "fire_hydrant/position", + "ref", + "operator" ], "geometry": [ "point", @@ -7251,6 +7395,30 @@ "terms": [], "name": "Cricket Field" }, + "leisure/pitch/equestrian": { + "icon": "horse-riding", + "fields": [ + "surface", + "lit", + "building" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "leisure": "pitch", + "sport": "equestrian" + }, + "terms": [ + "dressage", + "equestrian", + "horse", + "horseback", + "riding" + ], + "name": "Riding Arena" + }, "leisure/pitch/rugby_league": { "icon": "america-football", "fields": [ @@ -9026,6 +9194,25 @@ ], "name": "Neighborhood" }, + "place/quarter": { + "icon": "triangle-stroked", + "fields": [ + "population" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "place": "quarter" + }, + "terms": [ + "boro", + "borough", + "quarter" + ], + "name": "Sub-Borough / Quarter" + }, "place/square": { "icon": "poi-foot", "geometry": [ @@ -9050,10 +9237,11 @@ "place": "suburb" }, "terms": [ - "Boro", - "Quarter" + "boro", + "borough", + "quarter" ], - "name": "Borough" + "name": "Borough / Suburb" }, "place/town": { "icon": "town", @@ -10646,6 +10834,31 @@ }, "name": "Garden Center" }, + "shop/gas": { + "icon": "shop", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "cng", + "lpg", + "natural gas", + "propane", + "refill", + "tank" + ], + "tags": { + "shop": "gas" + }, + "name": "Bottled Gas Shop" + }, "shop/gift": { "icon": "gift", "fields": [ @@ -11246,6 +11459,23 @@ }, "name": "Pawn Shop" }, + "shop/perfumery": { + "icon": "shop", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "shop": "perfumery" + }, + "name": "Perfume Store" + }, "shop/pet": { "icon": "dog-park", "fields": [ @@ -11259,9 +11489,13 @@ "area" ], "terms": [ + "animal", "cat", "dog", - "fish" + "fish", + "kitten", + "puppy", + "reptile" ], "tags": { "shop": "pet" diff --git a/data/presets/presets/amenity/animal_boarding.json b/data/presets/presets/amenity/animal_boarding.json new file mode 100644 index 000000000..f0832a8eb --- /dev/null +++ b/data/presets/presets/amenity/animal_boarding.json @@ -0,0 +1,29 @@ +{ + "icon": "veterinary", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "boarding", + "cat", + "dog", + "horse", + "kitten", + "pet boarding", + "pet care", + "pet hotel", + "puppy", + "reptile" + ], + "tags": { + "amenity": "animal_boarding" + }, + "name": "Animal Boarding Facility" +} diff --git a/data/presets/presets/amenity/animal_breeding.json b/data/presets/presets/amenity/animal_breeding.json new file mode 100644 index 000000000..ddcdec17b --- /dev/null +++ b/data/presets/presets/amenity/animal_breeding.json @@ -0,0 +1,31 @@ +{ + "icon": "veterinary", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "breeding", + "bull", + "cat", + "cow", + "dog", + "horse", + "husbandry", + "kitten", + "livestock", + "pet breeding", + "puppy", + "reptile" + ], + "tags": { + "amenity": "animal_breeding" + }, + "name": "Animal Breeding Facility" +} diff --git a/data/presets/presets/amenity/animal_shelter.json b/data/presets/presets/amenity/animal_shelter.json new file mode 100644 index 000000000..0212e60f8 --- /dev/null +++ b/data/presets/presets/amenity/animal_shelter.json @@ -0,0 +1,32 @@ +{ + "icon": "veterinary", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "adoption", + "aspca", + "cat", + "dog", + "horse", + "kitten", + "pet care", + "pet rescue", + "puppy", + "raptor", + "reptile", + "rescue", + "spca" + ], + "tags": { + "amenity": "animal_shelter" + }, + "name": "Animal Shelter" +} diff --git a/data/presets/presets/amenity/driving_school.json b/data/presets/presets/amenity/driving_school.json new file mode 100644 index 000000000..7b709e73d --- /dev/null +++ b/data/presets/presets/amenity/driving_school.json @@ -0,0 +1,17 @@ +{ + "icon": "car", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "amenity": "driving_school" + }, + "name": "Driving School" +} diff --git a/data/presets/presets/amenity/watering_place.json b/data/presets/presets/amenity/watering_place.json new file mode 100644 index 000000000..12972f0ae --- /dev/null +++ b/data/presets/presets/amenity/watering_place.json @@ -0,0 +1,12 @@ +{ + "icon": "drinking-water", + "geometry": [ + "area", + "vertex", + "point" + ], + "tags": { + "amenity": "watering_place" + }, + "name": "Animal Watering Place" +} diff --git a/data/presets/presets/club.json b/data/presets/presets/club.json new file mode 100644 index 000000000..45d86d73e --- /dev/null +++ b/data/presets/presets/club.json @@ -0,0 +1,21 @@ +{ + "icon": "heart", + "fields": [ + "club", + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "club": "*" + }, + "terms": [ + "social" + ], + "name": "Club" +} diff --git a/data/presets/presets/emergency/fire_hydrant.json b/data/presets/presets/emergency/fire_hydrant.json index 408b0774d..688977234 100644 --- a/data/presets/presets/emergency/fire_hydrant.json +++ b/data/presets/presets/emergency/fire_hydrant.json @@ -2,7 +2,9 @@ "icon": "poi-fire-hydrant", "fields": [ "fire_hydrant/type", - "fire_hydrant/position" + "fire_hydrant/position", + "ref", + "operator" ], "geometry": [ "point", diff --git a/data/presets/presets/leisure/pitch/equestrian.json b/data/presets/presets/leisure/pitch/equestrian.json new file mode 100644 index 000000000..fc01be3a1 --- /dev/null +++ b/data/presets/presets/leisure/pitch/equestrian.json @@ -0,0 +1,24 @@ +{ + "icon": "horse-riding", + "fields": [ + "surface", + "lit", + "building" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "leisure": "pitch", + "sport": "equestrian" + }, + "terms": [ + "dressage", + "equestrian", + "horse", + "horseback", + "riding" + ], + "name": "Riding Arena" +} diff --git a/data/presets/presets/place/quarter.json b/data/presets/presets/place/quarter.json new file mode 100644 index 000000000..73757831d --- /dev/null +++ b/data/presets/presets/place/quarter.json @@ -0,0 +1,19 @@ +{ + "icon": "triangle-stroked", + "fields": [ + "population" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "place": "quarter" + }, + "terms": [ + "boro", + "borough", + "quarter" + ], + "name": "Sub-Borough / Quarter" +} diff --git a/data/presets/presets/place/suburb.json b/data/presets/presets/place/suburb.json index b1384e801..5006f654c 100644 --- a/data/presets/presets/place/suburb.json +++ b/data/presets/presets/place/suburb.json @@ -11,8 +11,9 @@ "place": "suburb" }, "terms": [ - "Boro", - "Quarter" + "boro", + "borough", + "quarter" ], - "name": "Borough" + "name": "Borough / Suburb" } diff --git a/data/presets/presets/shop/gas.json b/data/presets/presets/shop/gas.json new file mode 100644 index 000000000..f7d8eb032 --- /dev/null +++ b/data/presets/presets/shop/gas.json @@ -0,0 +1,25 @@ +{ + "icon": "shop", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "terms": [ + "cng", + "lpg", + "natural gas", + "propane", + "refill", + "tank" + ], + "tags": { + "shop": "gas" + }, + "name": "Bottled Gas Shop" +} diff --git a/data/presets/presets/shop/perfumery.json b/data/presets/presets/shop/perfumery.json new file mode 100644 index 000000000..e35a19dec --- /dev/null +++ b/data/presets/presets/shop/perfumery.json @@ -0,0 +1,17 @@ +{ + "icon": "shop", + "fields": [ + "operator", + "address", + "building_area", + "opening_hours" + ], + "geometry": [ + "point", + "area" + ], + "tags": { + "shop": "perfumery" + }, + "name": "Perfume Store" +} diff --git a/data/presets/presets/shop/pet.json b/data/presets/presets/shop/pet.json index ee048d82e..4091f5d2a 100644 --- a/data/presets/presets/shop/pet.json +++ b/data/presets/presets/shop/pet.json @@ -11,9 +11,13 @@ "area" ], "terms": [ + "animal", "cat", "dog", - "fish" + "fish", + "kitten", + "puppy", + "reptile" ], "tags": { "shop": "pet" diff --git a/data/taginfo.json b/data/taginfo.json index e798291ea..60fa5a30d 100644 --- a/data/taginfo.json +++ b/data/taginfo.json @@ -143,6 +143,18 @@ "key": "amenity", "value": "swimming_pool" }, + { + "key": "amenity", + "value": "animal_boarding" + }, + { + "key": "amenity", + "value": "animal_breeding" + }, + { + "key": "amenity", + "value": "animal_shelter" + }, { "key": "amenity", "value": "arts_centre" @@ -271,6 +283,10 @@ "key": "amenity", "value": "drinking_water" }, + { + "key": "amenity", + "value": "driving_school" + }, { "key": "amenity", "value": "embassy" @@ -547,6 +563,10 @@ "key": "amenity", "value": "water_point" }, + { + "key": "amenity", + "value": "watering_place" + }, { "key": "area", "value": "yes" @@ -776,6 +796,9 @@ "key": "camp_site", "value": "camp_pitch" }, + { + "key": "club" + }, { "key": "craft" }, @@ -1543,6 +1566,10 @@ "key": "sport", "value": "cricket" }, + { + "key": "sport", + "value": "equestrian" + }, { "key": "sport", "value": "rugby_league" @@ -1959,6 +1986,10 @@ "key": "place", "value": "neighbourhood" }, + { + "key": "place", + "value": "quarter" + }, { "key": "place", "value": "square" @@ -2306,6 +2337,10 @@ "key": "shop", "value": "garden_centre" }, + { + "key": "shop", + "value": "gas" + }, { "key": "shop", "value": "gift" @@ -2434,6 +2469,10 @@ "key": "shop", "value": "pawnbroker" }, + { + "key": "shop", + "value": "perfumery" + }, { "key": "shop", "value": "pet" diff --git a/dist/locales/en.json b/dist/locales/en.json index 4b8d724fa..e8cc898a0 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1003,6 +1003,9 @@ "anticlockwise": "Counterclockwise" } }, + "club": { + "label": "Type" + }, "collection_times": { "label": "Collection Times" }, @@ -2000,6 +2003,18 @@ "name": "Swimming Pool", "terms": "" }, + "amenity/animal_boarding": { + "name": "Animal Boarding Facility", + "terms": "boarding,cat,dog,horse,kitten,pet boarding,pet care,pet hotel,puppy,reptile" + }, + "amenity/animal_breeding": { + "name": "Animal Breeding Facility", + "terms": "breeding,bull,cat,cow,dog,horse,husbandry,kitten,livestock,pet breeding,puppy,reptile" + }, + "amenity/animal_shelter": { + "name": "Animal Shelter", + "terms": "adoption,aspca,cat,dog,horse,kitten,pet care,pet rescue,puppy,raptor,reptile,rescue,spca" + }, "amenity/arts_centre": { "name": "Arts Center", "terms": "" @@ -2128,6 +2143,10 @@ "name": "Drinking Water", "terms": "fountain,potable" }, + "amenity/driving_school": { + "name": "Driving School", + "terms": "" + }, "amenity/embassy": { "name": "Embassy", "terms": "" @@ -2404,6 +2423,10 @@ "name": "RV Drinking Water", "terms": "" }, + "amenity/watering_place": { + "name": "Animal Watering Place", + "terms": "" + }, "area": { "name": "Area", "terms": "" @@ -2636,6 +2659,10 @@ "name": "Camp Pitch", "terms": "tent,rv" }, + "club": { + "name": "Club", + "terms": "social" + }, "craft": { "name": "Craft", "terms": "" @@ -3408,6 +3435,10 @@ "name": "Cricket Field", "terms": "" }, + "leisure/pitch/equestrian": { + "name": "Riding Arena", + "terms": "dressage,equestrian,horse,horseback,riding" + }, "leisure/pitch/rugby_league": { "name": "Rugby League Field", "terms": "" @@ -3832,13 +3863,17 @@ "name": "Neighborhood", "terms": "neighbourhood" }, + "place/quarter": { + "name": "Sub-Borough / Quarter", + "terms": "boro,borough,quarter" + }, "place/square": { "name": "Square", "terms": "" }, "place/suburb": { - "name": "Borough", - "terms": "Boro,Quarter" + "name": "Borough / Suburb", + "terms": "boro,borough,quarter" }, "place/town": { "name": "Town", @@ -4188,6 +4223,10 @@ "name": "Garden Center", "terms": "landscape,mulch,shrub,tree" }, + "shop/gas": { + "name": "Bottled Gas Shop", + "terms": "cng,lpg,natural gas,propane,refill,tank" + }, "shop/gift": { "name": "Gift Shop", "terms": "souvenir" @@ -4316,9 +4355,13 @@ "name": "Pawn Shop", "terms": "" }, + "shop/perfumery": { + "name": "Perfume Store", + "terms": "" + }, "shop/pet": { "name": "Pet Store", - "terms": "cat,dog,fish" + "terms": "animal,cat,dog,fish,kitten,puppy,reptile" }, "shop/photo": { "name": "Photography Store", diff --git a/modules/behavior/breathe.js b/modules/behavior/breathe.js index 5591bd560..80870914f 100644 --- a/modules/behavior/breathe.js +++ b/modules/behavior/breathe.js @@ -94,8 +94,8 @@ export function behaviorBreathe() { p.tag = tag; p.from.opacity = opacity * 0.6; p.to.opacity = opacity * 1.25; - p.from.width = width * 0.9; - p.to.width = width * (tag === 'circle' ? 1.5 : 1.25); + p.from.width = width * 0.7; + p.to.width = width * (tag === 'circle' ? 1.5 : 1); params[d.id] = p; }); } diff --git a/modules/modes/save.js b/modules/modes/save.js index 74743d846..27a70ebca 100644 --- a/modules/modes/save.js +++ b/modules/modes/save.js @@ -2,6 +2,17 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { t } from '../util/locale'; +import { JXON } from '../util/jxon'; + +import { + actionDiscardTags, + actionMergeRemoteChanges, + actionNoop, + actionRevert +} from '../actions'; + +import { coreGraph } from '../core'; +import { modeBrowse } from './index'; import { uiConflicts, @@ -9,23 +20,13 @@ import { uiCommit, uiLoading, uiSuccess -} from '../ui/index'; - -import { - actionDiscardTags, - actionMergeRemoteChanges, - actionNoop, - actionRevert -} from '../actions/index'; +} from '../ui'; import { utilDisplayName, utilDisplayType -} from '../util/index'; +} from '../util'; -import { modeBrowse } from './index'; -import { coreGraph } from '../core/index'; -import { JXON } from '../util/jxon'; export function modeSave(context) { @@ -33,7 +34,7 @@ export function modeSave(context) { id: 'save' }; - var ui = uiCommit(context) + var commit = uiCommit(context) .on('cancel', cancel) .on('save', save); @@ -43,23 +44,7 @@ export function modeSave(context) { } - function save(e, tryAgain) { - function withChildNodes(ids, graph) { - return _.uniq(_.reduce(ids, function(result, id) { - var e = graph.entity(id); - if (e.type === 'way') { - try { - var cn = graph.childNodes(e); - result.push.apply(result, _.map(_.filter(cn, 'version'), 'id')); - } catch (err) { - /* eslint-disable no-console */ - if (typeof console !== 'undefined') console.error(err); - /* eslint-enable no-console */ - } - } - return result; - }, _.clone(ids))); - } + function save(changeset, tryAgain) { var loading = uiLoading(context).message(t('save.uploading')).blocking(true), history = context.history(), @@ -72,13 +57,34 @@ export function modeSave(context) { conflicts = [], errors = []; - if (!tryAgain) history.perform(actionNoop()); // checkpoint + if (!tryAgain) { + history.perform(actionNoop()); // checkpoint + } + context.container().call(loading); if (toCheck.length) { context.connection().loadMultiple(toLoad, loaded); } else { - finalize(); + upload(); + } + + + function withChildNodes(ids, graph) { + return _.uniq(_.reduce(ids, function(result, id) { + var entity = graph.entity(id); + if (entity.type === 'way') { + try { + var cn = graph.childNodes(entity); + result.push.apply(result, _.map(_.filter(cn, 'version'), 'id')); + } catch (err) { + /* eslint-disable no-console */ + if (typeof console !== 'undefined') console.error(err); + /* eslint-enable no-console */ + } + } + return result; + }, _.clone(ids))); } @@ -182,11 +188,11 @@ export function modeSave(context) { }); }); - finalize(); + upload(); } - function finalize() { + function upload() { if (conflicts.length) { conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); }); showConflicts(); @@ -195,29 +201,7 @@ export function modeSave(context) { } else { var changes = history.changes(actionDiscardTags(history.difference())); if (changes.modified.length || changes.created.length || changes.deleted.length) { - context.connection().putChangeset( - changes, - context.version, - e.comment, - history.imageryUsed(), - function(err, changeset_id) { - if (err) { - errors.push({ - msg: err.responseText, - details: [ t('save.status_code', { code: err.status }) ] - }); - showErrors(); - } else { - history.clearSaved(); - success(e, changeset_id); - // Add delay to allow for postgres replication #1646 #2678 - window.setTimeout(function() { - d3.select('.inspector-wrap *').remove(); - loading.close(); - context.flush(); - }, 2500); - } - }); + context.connection().putChangeset(changeset, changes, uploadCallback); } else { // changes were insignificant or reverted by user d3.select('.inspector-wrap *').remove(); loading.close(); @@ -228,6 +212,26 @@ export function modeSave(context) { } + function uploadCallback(err, changeset) { + if (err) { + errors.push({ + msg: err.responseText, + details: [ t('save.status_code', { code: err.status }) ] + }); + showErrors(); + } else { + history.clearSaved(); + success(changeset); + // Add delay to allow for postgres replication #1646 #2678 + window.setTimeout(function() { + d3.select('.inspector-wrap *').remove(); + loading.close(); + context.flush(); + }, 2500); + } + } + + function showConflicts() { var selection = context.container() .select('#sidebar') @@ -239,7 +243,7 @@ export function modeSave(context) { selection.call(uiConflicts(context) .list(conflicts) .on('download', function() { - var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)), + var data = JXON.stringify(changeset.update({ id: 'CHANGEME' }).osmChangeJXON(origChanges)), win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank'); win.focus(); }) @@ -262,7 +266,7 @@ export function modeSave(context) { } selection.remove(); - save(e, true); + save(changeset, true); }) ); } @@ -335,13 +339,11 @@ export function modeSave(context) { } - function success(e, changeset_id) { + function success(changeset) { + commit.reset(); context.enter(modeBrowse(context) .sidebar(uiSuccess(context) - .changeset({ - id: changeset_id, - comment: e.comment - }) + .changeset(changeset) .on('cancel', function() { context.ui().sidebar.hide(); }) @@ -352,7 +354,7 @@ export function modeSave(context) { mode.enter = function() { function done() { - context.ui().sidebar.show(ui); + context.ui().sidebar.show(commit); } context.container().selectAll('#content') diff --git a/modules/osm/changeset.js b/modules/osm/changeset.js index b2ed36f11..26e940e24 100644 --- a/modules/osm/changeset.js +++ b/modules/osm/changeset.js @@ -46,6 +46,90 @@ _.extend(osmChangeset.prototype, { }, + // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange) + // XML. Returns a string. + osmChangeJXON: function(changes) { + var changeset_id = this.id; + + function nest(x, order) { + var groups = {}; + for (var i = 0; i < x.length; i++) { + var tagName = Object.keys(x[i])[0]; + if (!groups[tagName]) groups[tagName] = []; + groups[tagName].push(x[i][tagName]); + } + var ordered = {}; + order.forEach(function(o) { + if (groups[o]) ordered[o] = groups[o]; + }); + return ordered; + } + + + // sort relations in a changeset by dependencies + function sort(changes) { + + // find a referenced relation in the current changeset + function resolve(item) { + return _.find(relations, function(relation) { + return item.keyAttributes.type === 'relation' + && item.keyAttributes.ref === relation['@id']; + }); + } + + // a new item is an item that has not been already processed + function isNew(item) { + return !sorted[ item['@id'] ] && !_.find(processing, function(proc) { + return proc['@id'] === item['@id']; + }); + } + + var processing = [], + sorted = {}, + relations = changes.relation; + + if (!relations) return changes; + + for (var i = 0; i < relations.length; i++) { + var relation = relations[i]; + + // skip relation if already sorted + if (!sorted[relation['@id']]) { + processing.push(relation); + } + + while (processing.length > 0) { + var next = processing[0], + deps = _.filter(_.compact(next.member.map(resolve)), isNew); + if (deps.length === 0) { + sorted[next['@id']] = next; + processing.shift(); + } else { + processing = deps.concat(processing); + } + } + } + + changes.relation = _.values(sorted); + return changes; + } + + function rep(entity) { + return entity.asJXON(changeset_id); + } + + return { + osmChange: { + '@version': 0.6, + '@generator': 'iD', + 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])), + 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']), + 'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), { '@if-unused': true }) + } + }; + }, + + asGeoJSON: function() { return {}; } diff --git a/modules/osm/tags.js b/modules/osm/tags.js index b28d45a11..37fc8434a 100644 --- a/modules/osm/tags.js +++ b/modules/osm/tags.js @@ -35,6 +35,9 @@ export var osmOneWayTags = { 'yes': true }, 'waterway': { + 'canal': true, + 'ditch': true, + 'drain': true, 'river': true, 'stream': true } diff --git a/modules/services/osm.js b/modules/services/osm.js index 16077cdf3..de1d977e6 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -3,17 +3,15 @@ import _ from 'lodash'; import osmAuth from 'osm-auth'; import { JXON } from '../util/jxon'; import { d3geoTile } from '../lib/d3.geo.tile'; -import { geoExtent } from '../geo/index'; +import { geoExtent } from '../geo'; import { - osmChangeset, osmEntity, osmNode, osmRelation, osmWay -} from '../osm/index'; +} from '../osm'; -import { utilDetect } from '../util/detect'; -import { utilRebind } from '../util/rebind'; +import { utilRebind } from '../util'; var dispatch = d3.dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded'), @@ -288,132 +286,47 @@ export default { }, - // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange) - // XML. Returns a string. - osmChangeJXON: function(changeset_id, changes) { - function nest(x, order) { - var groups = {}; - for (var i = 0; i < x.length; i++) { - var tagName = Object.keys(x[i])[0]; - if (!groups[tagName]) groups[tagName] = []; - groups[tagName].push(x[i][tagName]); - } - var ordered = {}; - order.forEach(function(o) { - if (groups[o]) ordered[o] = groups[o]; - }); - return ordered; - } - // sort relations in a changeset by dependencies - function sort(changes) { - // find a referenced relation in the current changeset - function resolve(item){ - return _.find(relations, function(relation) { - return item.keyAttributes.type === 'relation' - && item.keyAttributes.ref === relation['@id']; - }); - } - // a new item is an item that has not been already processed - function isNew(item) { - return !sorted[ item['@id'] ] && !_.find(processing, function(proc){ - return proc['@id'] === item['@id']; - }); - } - var processing = [], - sorted = {}, - relations = changes.relation; - - if (!relations) return changes; - - for (var i = 0; i < relations.length; i++) { - - var relation = relations[i]; - - // skip relation if already sorted - if ( !sorted[relation['@id']] ) { - processing.push( relation ); - } - - while ( processing.length > 0 ){ - var next = processing[0], - deps = _.filter( _.compact(next.member.map(resolve)), isNew); - - if ( deps.length === 0 ){ - sorted[ next['@id'] ] = next; - processing.shift(); - } else { - processing = deps.concat( processing ); - } - } - - } - - changes.relation = _.values(sorted); - return changes; - } - - function rep(entity) { - return entity.asJXON(changeset_id); - } - - return { - osmChange: { - '@version': 0.6, - '@generator': 'iD', - 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])), - 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']), - 'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true}) - } - }; - }, - - - changesetTags: function(version, comment, imageryUsed) { - var detected = utilDetect(), - tags = { - created_by: ('iD ' + version).substr(0, 255), - imagery_used: imageryUsed.join(';').substr(0, 255), - host: detected.host.substr(0, 255), - locale: detected.locale.substr(0, 255) - }; - - if (comment) { - tags.comment = comment.substr(0, 255); - } - - return tags; - }, - - - putChangeset: function(changes, version, comment, imageryUsed, callback) { - var that = this, - changeset = new osmChangeset({ tags: this.changesetTags(version, comment, imageryUsed) }); + putChangeset: function(changeset, changes, callback) { + // Create the changeset.. oauth.xhr({ - method: 'PUT', - path: '/api/0.6/changeset/create', + method: 'PUT', + path: '/api/0.6/changeset/create', + options: { header: { 'Content-Type': 'text/xml' } }, + content: JXON.stringify(changeset.asJXON()) + }, createdChangeset); + + + function createdChangeset(err, changeset_id) { + if (err) return callback(err); + changeset = changeset.update({ id: changeset_id }); + + // Upload the changeset.. + oauth.xhr({ + method: 'POST', + path: '/api/0.6/changeset/' + changeset_id + '/upload', options: { header: { 'Content-Type': 'text/xml' } }, - content: JXON.stringify(changeset.asJXON()) - }, function(err, changeset_id) { - if (err) return callback(err); - oauth.xhr({ - method: 'POST', - path: '/api/0.6/changeset/' + changeset_id + '/upload', - options: { header: { 'Content-Type': 'text/xml' } }, - content: JXON.stringify(that.osmChangeJXON(changeset_id, changes)) - }, function(err) { - if (err) return callback(err); - // POST was successful, safe to call the callback. - // Still attempt to close changeset, but ignore response because #2667 - // Add delay to allow for postgres replication #1646 #2678 - window.setTimeout(function() { callback(null, changeset_id); }, 2500); - oauth.xhr({ - method: 'PUT', - path: '/api/0.6/changeset/' + changeset_id + '/close', - options: { header: { 'Content-Type': 'text/xml' } } - }, function() { return true; }); - }); - }); + content: JXON.stringify(changeset.osmChangeJXON(changes)) + }, uploadedChangeset); + } + + + function uploadedChangeset(err) { + if (err) return callback(err); + + // Upload was successful, safe to call the callback. + // Add delay to allow for postgres replication #1646 #2678 + window.setTimeout(function() { + callback(null, changeset); + }, 2500); + + // Still attempt to close changeset, but ignore response because #2667 + oauth.xhr({ + method: 'PUT', + path: '/api/0.6/changeset/' + changeset.id + '/close', + options: { header: { 'Content-Type': 'text/xml' } } + }, function() { return true; }); + } }, diff --git a/modules/ui/commit.js b/modules/ui/commit.js index 210ff8eea..c6e41f835 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -2,16 +2,23 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { t } from '../util/locale'; import { d3combobox } from '../lib/d3.combobox.js'; -import { modeSelect } from '../modes/index'; -import { svgIcon } from '../svg/index'; +import { osmChangeset } from '../osm'; +import { modeSelect } from '../modes'; +import { svgIcon } from '../svg'; import { tooltip } from '../util/tooltip'; +import { uiRawTagEditor } from './raw_tag_editor'; +import { utilDetect } from '../util/detect'; import { utilDisplayName, utilDisplayType, - utilEntityOrMemberSelector -} from '../util/index'; -import { utilRebind } from '../util/rebind'; -import { utilTriggerEvent } from '../util/trigger_event'; + utilEntityOrMemberSelector, + utilRebind, + utilTriggerEvent +} from '../util'; + + +var changeset; +var readOnlyTags = ['created_by', 'imagery_used', 'host', 'locale']; export function uiCommit(context) { @@ -19,8 +26,22 @@ export function uiCommit(context) { function commit(selection) { + 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) + }; + + changeset = new osmChangeset({ tags: tags }); + } + + var changes = context.history().changes(), - summary = context.history().difference().summary(); + summary = context.history().difference().summary(), + rawTagEditor = uiRawTagEditor(context).on('change', changeTags); selection .append('div') @@ -43,11 +64,12 @@ export function uiCommit(context) { var commentField = commentSection .append('textarea') + .attr('class', 'commit-form-comment') .attr('placeholder', t('commit.description_placeholder')) .attr('maxlength', 255) .property('value', context.storage('comment') || '') - .on('input.save', checkComment) - .on('change.save', checkComment) + .on('input.save', change(true)) + .on('change.save', change()) .on('blur.save', function() { context.storage('comment', this.value); }); @@ -169,12 +191,14 @@ export function uiCommit(context) { // Buttons var buttonSection = saveSection .append('div') - .attr('class','buttons fillL cf'); + .attr('class', 'buttons fillL cf'); var cancelButton = buttonSection .append('button') .attr('class', 'secondary-action col5 button cancel-button') - .on('click.cancel', function() { dispatch.call('cancel'); }); + .on('click.cancel', function() { + dispatch.call('cancel'); + }); cancelButton .append('span') @@ -189,9 +213,7 @@ export function uiCommit(context) { return (n && n.value.length) ? null : true; }) .on('click.save', function() { - dispatch.call('save', this, { - comment: commentField.node().value - }); + dispatch.call('save', this, changeset); }); saveButton @@ -200,6 +222,12 @@ export function uiCommit(context) { .text(t('commit.save')); + // Raw Tag Editor + var tagSection = body + .append('div') + .attr('class', 'modal-section tag-section raw-tag-editor'); + + // Changes var changeSection = body .append('div') @@ -251,7 +279,7 @@ export function uiCommit(context) { .style('opacity', 1); - // Call checkComment off the bat, in case a changeset + // Call change() off the bat, in case a changeset // comment is recovered from localStorage utilTriggerEvent(commentField, 'input'); @@ -290,14 +318,16 @@ export function uiCommit(context) { } - function checkComment() { + function checkComment(comment) { + // Save button disabled if there is no comment.. d3.selectAll('.save-section .save-button') - .attr('disabled', (this.value.length ? null : true)); + .attr('disabled', (comment.length ? null : true)); + // Warn if comment mentions Google.. var googleWarning = clippyArea .html('') .selectAll('a') - .data(this.value.match(/google/i) ? [true] : []); + .data(comment.match(/google/i) ? [true] : []); googleWarning.exit() .remove(); @@ -311,7 +341,71 @@ export function uiCommit(context) { .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); + } else { + delete tags[k]; + } + }); + + if (!_.isEqual(changeset.tags, tags)) { + changeset = changeset.update({ tags: tags }); + } + + return changeset; + } + } + + commit.reset = function() { + changeset = null; + }; + + return utilRebind(commit, dispatch, 'on'); } diff --git a/modules/ui/raw_tag_editor.js b/modules/ui/raw_tag_editor.js index 168ec4f66..e67674f4c 100644 --- a/modules/ui/raw_tag_editor.js +++ b/modules/ui/raw_tag_editor.js @@ -15,6 +15,9 @@ import { export function uiRawTagEditor(context) { var taginfo = services.taginfo, dispatch = d3.dispatch('change'), + expanded = context.storage('raw_tag_editor.expanded') === 'true', + readOnlyTags = [], + updatePreference = true, showBlank = false, state, preset, @@ -27,12 +30,15 @@ export function uiRawTagEditor(context) { selection.call(uiDisclosure() .title(t('inspector.all_tags') + ' (' + count + ')') - .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback()) + .expanded(expanded) .on('toggled', toggled) - .content(content)); + .content(content) + ); function toggled(expanded) { - context.storage('raw_tag_editor.expanded', expanded); + if (updatePreference) { + context.storage('raw_tag_editor.expanded', expanded); + } if (expanded) { selection.node().parentNode.scrollTop += 200; } @@ -77,7 +83,8 @@ export function uiRawTagEditor(context) { var enter = items.enter() .append('li') - .attr('class', 'tag-row cf'); + .attr('class', 'tag-row cf') + .classed('readonly', isReadOnly); enter .append('div') @@ -125,11 +132,11 @@ export function uiRawTagEditor(context) { key = row.select('input.key'), // propagate bound data to child value = row.select('input.value'); // propagate bound data to child - if (taginfo) { + if (id && taginfo) { bindTypeahead(key, value); } - var isRelation = (context.entity(id).type === 'relation'), + var isRelation = (id && context.entity(id).type === 'relation'), reference; if (isRelation && tag.key === 'type') { @@ -149,16 +156,26 @@ export function uiRawTagEditor(context) { items.selectAll('input.key') .attr('title', function(d) { return d.key; }) - .call(utilGetSetValue, function(d) { return d.key; }); + .call(utilGetSetValue, function(d) { return d.key; }) + .property('disabled', isReadOnly); + // .classed('deemphasize', isReadOnly); items.selectAll('input.value') .attr('title', function(d) { return d.value; }) - .call(utilGetSetValue, function(d) { return d.value; }); + .call(utilGetSetValue, function(d) { return d.value; }) + .property('disabled', isReadOnly); + // .classed('deemphasize', isReadOnly); items.selectAll('button.remove') .on('click', removeTag); + + function isReadOnly(d) { + return readOnlyTags.indexOf(d.key) !== -1; + } + + function pushMore() { if (d3.event.keyCode === 9 && !d3.event.shiftKey && list.selectAll('li:last-child input.value').node() === this) { @@ -168,6 +185,32 @@ export function uiRawTagEditor(context) { function bindTypeahead(key, value) { + if (isReadOnly({ key: key })) return; + var geometry = context.geometry(id); + + key.call(d3combobox() + .fetcher(function(value, callback) { + taginfo.keys({ + debounce: true, + geometry: geometry, + query: value + }, function(err, data) { + if (!err) callback(sort(value, data)); + }); + })); + + value.call(d3combobox() + .fetcher(function(value, callback) { + taginfo.values({ + debounce: true, + key: utilGetSetValue(key), + geometry: geometry, + query: value + }, function(err, data) { + if (!err) callback(sort(value, data)); + }); + })); + function sort(value, data) { var sameletter = [], @@ -181,29 +224,6 @@ export function uiRawTagEditor(context) { } return sameletter.concat(other); } - - key.call(d3combobox() - .fetcher(function(value, callback) { - taginfo.keys({ - debounce: true, - geometry: context.geometry(id), - query: value - }, function(err, data) { - if (!err) callback(sort(value, data)); - }); - })); - - value.call(d3combobox() - .fetcher(function(value, callback) { - taginfo.values({ - debounce: true, - key: utilGetSetValue(key), - geometry: context.geometry(id), - query: value - }, function(err, data) { - if (!err) callback(sort(value, data)); - }); - })); } @@ -223,6 +243,12 @@ export function uiRawTagEditor(context) { kNew = this.value.trim(), tag = {}; + + if (isReadOnly({ key: kNew })) { + this.value = kOld; + return; + } + if (kNew && kNew !== kOld) { var match = kNew.match(/^(.*?)(?:_(\d+))?$/), base = match[1], @@ -240,6 +266,7 @@ export function uiRawTagEditor(context) { function valueChange(d) { + if (isReadOnly(d)) return; var tag = {}; tag[d.key] = this.value; dispatch.call('change', this, tag); @@ -247,6 +274,7 @@ export function uiRawTagEditor(context) { function removeTag(d) { + if (isReadOnly(d)) return; var tag = {}; tag[d.key] = undefined; dispatch.call('change', this, tag); @@ -277,6 +305,13 @@ export function uiRawTagEditor(context) { rawTagEditor.preset = function(_) { if (!arguments.length) return preset; preset = _; + if (preset.isFallback()) { + expanded = true; + updatePreference = false; + } else { + expanded = context.storage('raw_tag_editor.expanded') === 'true'; + updatePreference = true; + } return rawTagEditor; }; @@ -295,5 +330,20 @@ export function uiRawTagEditor(context) { }; + rawTagEditor.expanded = function(_) { + if (!arguments.length) return expanded; + expanded = _; + updatePreference = false; + return rawTagEditor; + }; + + + rawTagEditor.readOnlyTags = function(_) { + if (!arguments.length) return readOnlyTags; + readOnlyTags = _; + return rawTagEditor; + }; + + return utilRebind(rawTagEditor, dispatch, 'on'); } diff --git a/modules/ui/success.js b/modules/ui/success.js index f182119aa..989363e3c 100644 --- a/modules/ui/success.js +++ b/modules/ui/success.js @@ -11,9 +11,6 @@ export function uiSuccess(context) { function success(selection) { - var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) + - ' ' + context.connection().changesetURL(changeset.id); - var header = selection .append('div') .attr('class', 'header fillL'); @@ -55,6 +52,10 @@ export function uiSuccess(context) { .attr('href', changesetURL) .text(t('success.view_on_osm')); + + var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) + + ' ' + context.connection().changesetURL(changeset.id); + var sharing = { facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL), twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message), diff --git a/package.json b/package.json index b5e67e575..f4d302fe0 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dist": "npm-run-all -p dist:**", "dist:css": "shx cat css/*.css > dist/iD.css", "dist:mapillary": "shx mkdir -p dist/mapillary-js && shx cp -R node_modules/mapillary-js/dist/* dist/mapillary-js/", - "dist:min": "uglifyjs dist/iD.js -c 'warnings=false' -m -o dist/iD.min.js", + "dist:min": "uglifyjs dist/iD.js -c warnings=false -m -o dist/iD.min.js", "dist:svg:maki": "svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/maki-sprite.svg node_modules/@mapbox/maki/icons/*.svg", "dist:svg:id": "node svg/spriteify.js --svg svg/iD-sprite.src.svg --json svg/iD-sprite.json > dist/img/iD-sprite.svg", "imagery": "node data/update_imagery", @@ -59,7 +59,7 @@ "npm-run-all": "~4.0.0", "phantomjs-prebuilt": "~2.1.11", "request": "~2.81.0", - "rollup": "0.41.5", + "rollup": "0.41.6", "rollup-plugin-commonjs": "8.0.2", "rollup-plugin-json": "2.0.2", "rollup-plugin-node-resolve": "2.0.0", diff --git a/test/spec/osm/changeset.js b/test/spec/osm/changeset.js index 566704218..16df504c0 100644 --- a/test/spec/osm/changeset.js +++ b/test/spec/osm/changeset.js @@ -12,6 +12,7 @@ describe('iD.osmChangeset', function () { expect(iD.osmChangeset({tags: {foo: 'bar'}}).tags).to.eql({foo: 'bar'}); }); + describe('#asJXON', function () { it('converts a node to jxon', function() { var node = iD.osmChangeset({tags: {'comment': 'hello'}}); @@ -26,4 +27,100 @@ describe('iD.osmChangeset', function () { }); }); }); + + + describe('#osmChangeJXON', function() { + it('converts change data to JXON', function() { + var changeset = iD.osmChangeset(), + jxon = changeset.osmChangeJXON({ created: [], modified: [], deleted: [] }); + + expect(jxon).to.eql({ + osmChange: { + '@version': 0.6, + '@generator': 'iD', + 'create': {}, + 'modify': {}, + 'delete': { '@if-unused': true } + } + }); + }); + + it('includes creations ordered by nodes, ways, relations', function() { + var n = iD.osmNode({ loc: [0, 0] }), + w = iD.osmWay(), + r = iD.osmRelation(), + c = iD.osmChangeset({ id: '1234' }), + changes = { created: [r, w, n], modified: [], deleted: [] }, + jxon = c.osmChangeJXON(changes); + + expect(d3.entries(jxon.osmChange.create)).to.eql([ + { key: 'node', value: [n.asJXON('1234').node] }, + { key: 'way', value: [w.asJXON('1234').way] }, + { key: 'relation', value: [r.asJXON('1234').relation] } + ]); + }); + + it('includes creations ordered by dependencies', function() { + var n = iD.osmNode({ loc: [0, 0] }), + w = iD.osmWay({nodes: [n.id]}), + r1 = iD.osmRelation({ members: [{ id: w.id, type: 'way' }] }), + r2 = iD.osmRelation({ members: [{ id: r1.id, type: 'relation' }] }), + c = iD.osmChangeset({ id: '1234' }), + changes = { created: [r2, r1, w, n], modified: [], deleted: [] }, + jxon = c.osmChangeJXON(changes); + + expect(d3.entries(jxon.osmChange.create)).to.eql([ + { key: 'node', value: [n.asJXON('1234').node] }, + { key: 'way', value: [w.asJXON('1234').way] }, + { key: 'relation', value: [r1.asJXON('1234').relation, r2.asJXON('1234').relation] }, + ]); + }); + + it('includes creations ignoring circular dependencies', function() { + var r1 = iD.osmRelation(), + r2 = iD.osmRelation(), + c = iD.osmChangeset({ id: '1234' }), + changes, jxon; + r1.addMember({ id: r2.id, type: 'relation' }); + r2.addMember({ id: r1.id, type: 'relation' }); + changes = { created: [r1,r2], modified: [], deleted: [] }; + jxon = c.osmChangeJXON(changes); + + expect(d3.entries(jxon.osmChange.create)).to.eql([ + { key: 'relation', value: [r1.asJXON('1234').relation, r2.asJXON('1234').relation] }, + ]); + }); + + it('includes modifications', function() { + var n = iD.osmNode({ loc: [0, 0] }), + w = iD.osmWay(), + r = iD.osmRelation(), + c = iD.osmChangeset({ id: '1234' }), + changes = { created: [], modified: [r, w, n], deleted: [] }, + jxon = c.osmChangeJXON(changes); + + expect(jxon.osmChange.modify).to.eql({ + node: [n.asJXON('1234').node], + way: [w.asJXON('1234').way], + relation: [r.asJXON('1234').relation] + }); + }); + + it('includes deletions ordered by relations, ways, nodes', function() { + var n = iD.osmNode({ loc: [0, 0] }), + w = iD.osmWay(), + r = iD.osmRelation(), + c = iD.osmChangeset({ id: '1234' }), + changes = { created: [], modified: [], deleted: [n, w, r] }, + jxon = c.osmChangeJXON(changes); + + expect(d3.entries(jxon.osmChange.delete)).to.eql([ + { key: 'relation', value: [r.asJXON('1234').relation] }, + { key: 'way', value: [w.asJXON('1234').way] }, + { key: 'node', value: [n.asJXON('1234').node] }, + { key: '@if-unused', value: true } + ]); + }); + }); + }); diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index bded77c43..4644b310b 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -333,95 +333,6 @@ describe('iD.serviceOsm', function () { }); - describe('#osmChangeJXON', function() { - it('converts change data to JXON', function() { - var jxon = connection.osmChangeJXON('1234', {created: [], modified: [], deleted: []}); - - expect(jxon).to.eql({ - osmChange: { - '@version': 0.6, - '@generator': 'iD', - 'create': {}, - 'modify': {}, - 'delete': {'@if-unused': true} - } - }); - }); - - it('includes creations ordered by nodes, ways, relations', function() { - var n = iD.Node({loc: [0, 0]}), - w = iD.Way(), - r = iD.Relation(), - changes = {created: [r, w, n], modified: [], deleted: []}, - jxon = connection.osmChangeJXON('1234', changes); - - expect(d3.entries(jxon.osmChange.create)).to.eql([ - {key: 'node', value: [n.asJXON('1234').node]}, - {key: 'way', value: [w.asJXON('1234').way]}, - {key: 'relation', value: [r.asJXON('1234').relation]} - ]); - }); - - it('includes creations ordered by dependencies', function() { - var n = iD.Node({loc: [0, 0]}), - w = iD.Way({nodes: [n.id]}), - r1 = iD.Relation({members: [{id: w.id, type: 'way'}]}), - r2 = iD.Relation({members: [{id: r1.id, type: 'relation'}]}), - changes = {created: [r2, r1, w, n], modified: [], deleted: []}, - jxon = connection.osmChangeJXON('1234', changes); - - expect(d3.entries(jxon.osmChange.create)).to.eql([ - {key: 'node', value: [n.asJXON('1234').node]}, - {key: 'way', value: [w.asJXON('1234').way]}, - {key: 'relation', value: [r1.asJXON('1234').relation, r2.asJXON('1234').relation]}, - ]); - }); - - it('includes creations ignoring circular dependencies', function() { - var r1 = iD.Relation(), - r2 = iD.Relation(), - changes, jxon; - r1.addMember({id: r2.id, type: 'relation'}); - r2.addMember({id: r1.id, type: 'relation'}); - changes = {created: [r1,r2], modified: [], deleted: []}; - jxon = connection.osmChangeJXON('1234', changes); - - expect(d3.entries(jxon.osmChange.create)).to.eql([ - {key: 'relation', value: [r1.asJXON('1234').relation, r2.asJXON('1234').relation]}, - ]); - }); - - it('includes modifications', function() { - var n = iD.Node({loc: [0, 0]}), - w = iD.Way(), - r = iD.Relation(), - changes = {created: [], modified: [r, w, n], deleted: []}, - jxon = connection.osmChangeJXON('1234', changes); - - expect(jxon.osmChange.modify).to.eql({ - node: [n.asJXON('1234').node], - way: [w.asJXON('1234').way], - relation: [r.asJXON('1234').relation] - }); - }); - - it('includes deletions ordered by relations, ways, nodes', function() { - var n = iD.Node({loc: [0, 0]}), - w = iD.Way(), - r = iD.Relation(), - changes = {created: [], modified: [], deleted: [n, w, r]}, - jxon = connection.osmChangeJXON('1234', changes); - - expect(d3.entries(jxon.osmChange.delete)).to.eql([ - {key: 'relation', value: [r.asJXON('1234').relation]}, - {key: 'way', value: [w.asJXON('1234').way]}, - {key: 'node', value: [n.asJXON('1234').node]}, - {key: '@if-unused', value: true} - ]); - }); - }); - - describe('#userChangesets', function() { var server, userDetailsFn; @@ -527,13 +438,6 @@ describe('iD.serviceOsm', function () { }); - describe('#changesetTags', function() { - it('omits comment when empty', function() { - expect(connection.changesetTags('2.0.0', '', [])).not.to.have.property('comment'); - }); - }); - - describe('API capabilities', function() { var server, capabilitiesXML = '' +