diff --git a/Makefile b/Makefile
index 3b0f2d1b7..9fd5afb0e 100644
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,9 @@ all: \
js/id/validate.js \
js/id/end.js \
locale/locale.js \
- locale/en.js
+ locale/en.js \
+ data/data.js \
+ data/deprecated.js
iD.js: Makefile
@rm -f $@
diff --git a/css/map.css b/css/map.css
index 63950671f..749aeb7b3 100644
--- a/css/map.css
+++ b/css/map.css
@@ -17,11 +17,11 @@ g.point .shadow {
-moz-transition: fill 100ms linear;
}
.behavior-hover g.point.hover:not(.selected) .shadow {
- fill: #E96666;
- fill-opacity: 0.3;
+ fill: #f6634f;
+ fill-opacity: 0.5;
}
g.point.selected .shadow {
- fill: #E96666;
+ fill: #f6634f;
fill-opacity: 0.7;
}
@@ -30,8 +30,10 @@ g.point.selected .shadow {
g.vertex .fill {
fill:white;
}
+
g.vertex .stroke {
- stroke:#333;
+ stroke:black;
+ stroke-opacity: .5;
stroke-width:2;
fill:white;
}
@@ -101,18 +103,18 @@ g.vertex.shared .fill {
g.vertex .shadow {
fill: none;
pointer-events: all;
- stroke-width: 10;
+ stroke-width: 20;
-webkit-transition: -webkit-transform 100ms linear;
transition: transform 100ms linear;
-moz-transition: fill 100ms linear;
}
.behavior-hover g.vertex.hover:not(.selected) .shadow {
- fill: #E96666;
+ fill: #f6634f;
fill-opacity: 0.3;
-}
+}
g.vertex.selected .shadow {
- fill: #E96666;
- fill-opacity: 0.7;
+ fill: #f6634f;
+ fill-opacity: 0.5;
}
/* midpoints */
@@ -121,16 +123,20 @@ g.vertex.selected .shadow {
.mode-draw-line g.midpoint,
.mode-add-area g.midpoint,
.mode-add-line g.midpoint,
-.mode-add-point g.midpoint {
+.mode-add-point g.midpoint,
+.behavior-drag-node g.midpoint {
display: none;
}
g.midpoint .fill {
- fill:#aaa;
+ fill:#ddd;
+ stroke:black;
+ stroke-opacity: .5;
+ opacity: .5;
}
.behavior-hover g.midpoint .fill.hover:not(.selected) {
- fill:#fff;
- stroke:#000;
+ fill:white;
+ opacity: .75;
}
g.midpoint .shadow {
@@ -142,7 +148,7 @@ g.midpoint .shadow {
-moz-transition: fill 100ms linear;
}
.behavior-hover g.midpoint .shadow.hover:not(.selected) {
- fill:#E96666;
+ fill:#f6634f;
fill-opacity: 0.3;
}
@@ -154,8 +160,8 @@ path.line {
}
path.stroke {
- stroke: #222;
- stroke-width: 2;
+ stroke: black;
+ stroke-width: 4;
}
path.shadow {
@@ -165,12 +171,12 @@ path.shadow {
}
.behavior-hover path.shadow.hover:not(.selected) {
- stroke: #E96666;
+ stroke: #f6634f;
stroke-opacity: 0.3;
}
path.shadow.selected {
- stroke: #E96666;
+ stroke: #f6634f;
stroke-opacity: 0.7;
}
@@ -199,31 +205,31 @@ path.area.stroke.selected {
path.area.stroke.tag-natural,
path.multipolygon.tag-natural {
- stroke: #ADD6A5;
+ stroke: #b6e199;
stroke-width:1;
}
path.area.fill.tag-natural,
path.multipolygon.tag-natural {
- fill: #ADD6A5;
+ fill: #b6e199;
}
path.area.stroke.tag-natural-water,
path.multipolygon.tag-natural-water {
- stroke: #6382FF;
+ stroke: #77d3de;
}
path.area.fill.tag-natural-water,
path.multipolygon.tag-natural-water {
- fill: #ADBEFF;
+ fill: #77d3de;
}
path.area.stroke.tag-building,
path.multipolygon.tag-building {
- stroke: #9E176A;
+ stroke: #e06e5f;
stroke-width: 1;
}
path.area.fill.tag-building,
path.multipolygon.tag-building {
- fill: #ff6ec7;
+ fill: #e06e5f;
}
path.area.stroke.tag-landuse,
@@ -236,7 +242,7 @@ path.multipolygon.tag-natural-wood,
path.multipolygon.tag-natural-tree,
path.multipolygon.tag-natural-grassland,
path.multipolygon.tag-leisure-park {
- stroke: #006B34;
+ stroke: #8cd05f;
stroke-width: 1;
}
path.area.fill.tag-landuse,
@@ -249,18 +255,18 @@ path.multipolygon.tag-natural-wood,
path.multipolygon.tag-natural-tree,
path.multipolygon.tag-natural-grassland,
path.multipolygon.tag-leisure-park {
- fill: #189E59;
+ fill: #8cd05f;
fill-opacity: 0.2;
}
path.area.stroke.tag-amenity-parking,
path.multipolygon.tag-amenity-parking {
- stroke: #beb267;
+ stroke: #aaa;
stroke-width: 1;
}
path.area.fill.tag-amenity-parking,
path.multipolygon.tag-amenity-parking {
- fill: #edecc0;
+ fill: #aaa;
}
path.multipolygon.tag-boundary {
@@ -294,56 +300,57 @@ svg[data-zoom="16"] path.stroke.tag-highway {
path.stroke.tag-highway-motorway,
path.stroke.tag-highway-motorway_link,
path.stroke.tag-construction-motorway {
- stroke:#809bc0;
+ stroke:#58a9ed;
}
+
path.casing.tag-highway-motorway,
path.casing.tag-highway-motorway_link,
path.casing.tag-construction-motorway {
- stroke:#506077;
+ stroke:#2c5476;
}
path.stroke.tag-highway-trunk,
path.stroke.tag-highway-trunk_link,
path.stroke.tag-construction-trunk {
- stroke:#97d397;
+ stroke:#8cd05f;
}
path.casing.tag-highway-trunk,
path.casing.tag-highway-trunk_link,
path.casing.tag-construction-trunk {
- stroke:#477147;
+ stroke:#46682f;
}
path.stroke.tag-highway-primary,
path.stroke.tag-highway-primary_link,
path.stroke.tag-construction-primary {
- stroke:#ec989a;
+ stroke:#e06d5f;
}
path.casing.tag-highway-primary,
path.casing.tag-highway-primary_link,
path.casing.tag-construction-primary {
- stroke:#8d4346;
+ stroke:#70372f;
}
path.stroke.tag-highway-secondary,
path.stroke.tag-highway-secondary_link,
path.stroke.tag-construction-secondary {
- stroke:#fecc8b;
+ stroke:#eab056;
}
path.casing.tag-highway-secondary,
path.casing.tag-highway-secondary_link,
path.casing.tag-construction-secondary {
- stroke:#a37b48;
+ stroke:#75582b;
}
path.stroke.tag-highway-tertiary,
path.stroke.tag-highway-tertiary_link,
path.stroke.tag-construction-tertiary {
- stroke:#ffffb3;
+ stroke:#ffff7e;
}
path.casing.tag-highway-tertiary,
path.casing.tag-highway-tertiary_link,
path.casing.tag-construction-tertiary {
- stroke:#bbb;
+ stroke:#7f7f3f;
}
path.stroke.tag-highway-unclassified,
@@ -380,7 +387,7 @@ path.stroke.tag-highway-pedestrian {
shapeRendering: auto;
}
path.casing.tag-highway-pedestrian {
- stroke:#84C382;
+ stroke:#8cd05f;
stroke-width:6 !important;
}
@@ -453,17 +460,17 @@ svg[data-zoom="16"] path.casing.tag-highway-bridleway {
}
path.stroke.tag-highway-footway {
- stroke: #996600;
+ stroke: #ae8681;
}
path.stroke.tag-highway-cycleway {
- stroke: #69f;
+ stroke: #58a9ed;
}
path.stroke.tag-highway-bridleway {
- stroke: green;
+ stroke: #e06d5f;
}
path.stroke.tag-highway-steps {
- stroke: #ff6257;
+ stroke: #81d25c;
stroke-width: 4;
stroke-linecap: butt;
stroke-dasharray: 3, 3;
@@ -475,7 +482,7 @@ path.casing.tag-highway-steps {
path.casing.tag-bridge-yes {
stroke-width: 14;
- stroke: #000;
+ stroke: #333;
}
path.stroke.tag-highway-construction,
@@ -519,12 +526,16 @@ path.casing.tag-railway-subway {
/* waterways */
+path.area.fill.tag-waterway {
+ fill: #77d3de;
+}
+
path.stroke.tag-waterway {
- stroke: #10539a;
+ stroke: #77d3de;
stroke-width: 2;
}
path.casing.tag-waterway {
- stroke: #6AA2FF;
+ stroke: #77d3de;
stroke-width: 4;
}
@@ -543,11 +554,11 @@ svg[data-zoom="16"] path.casing.tag-waterway-river {
}
path.stroke.tag-waterway-ditch {
- stroke: #10539a;
+ stroke: #6591ff;
stroke-width: 1;
}
path.casing.tag-waterway-ditch {
- stroke: #999692;
+ stroke: #6591ff;
stroke-width: 3;
}
@@ -576,17 +587,22 @@ path.casing.tag-boundary {
path.casing.tag-boundary-protected_area,
path.casing.tag-boundary-national_park {
- stroke: #4D9849;
+ stroke: #b0e298;
}
text {
font-size:10px;
pointer-events: none;
+ color: #222;
+ opacity: 1;
}
.oneway .textpath {
pointer-events: none;
+ font-size: 7px;
+ baseline-shift: 2px;
+ opacity: .7;
}
text.tag-oneway {
@@ -614,7 +630,7 @@ text.pathlabel,
text.pointlabel {
font-size: 12px;
font-weight: bold;
- fill: black;
+ fill: #333;
text-anchor: middle;
pointer-events: none;
}
@@ -640,7 +656,8 @@ text.pointlabel {
text.point {
- font-size: 9px;
+ font-size: 10px;
+ baseline-shift: 2px;
}
/* Cursors */
@@ -700,14 +717,16 @@ text.point {
.mode-draw-line .behavior-hover .way,
.mode-draw-area .behavior-hover .way,
.mode-add-line .behavior-hover .way,
-.mode-add-area .behavior-hover .way {
+.mode-add-area .behavior-hover .way,
+.behavior-drag-node.behavior-hover .way {
cursor:url(../img/cursor-draw-connect-line.png) 9 9, auto;
}
.mode-draw-line .behavior-hover .vertex,
.mode-draw-area .behavior-hover .vertex,
.mode-add-line .behavior-hover .vertex,
-.mode-add-area .behavior-hover .vertex {
+.mode-add-area .behavior-hover .vertex,
+.behavior-drag-node.behavior-hover .vertex {
cursor:url(../img/cursor-draw-connect-vertex.png) 9 9, auto;
}
@@ -718,12 +737,14 @@ text.point {
/* Modes */
.mode-draw-line .vertex.active,
-.mode-draw-area .vertex.active {
+.mode-draw-area .vertex.active,
+.behavior-drag-node .vertex.active {
display: none;
}
.mode-draw-line .way.active,
-.mode-draw-area .way.active {
+.mode-draw-area .way.active,
+.behavior-drag-node .active {
pointer-events: none;
}
diff --git a/icons/tree.png b/icons/tree.png
index 7575bd63b..d88c945d4 100644
Binary files a/icons/tree.png and b/icons/tree.png differ
diff --git a/icons/unknown.png b/icons/unknown.png
index 404602aa4..03fff0c0e 100644
Binary files a/icons/unknown.png and b/icons/unknown.png differ
diff --git a/img/source/sprite.svg b/img/source/sprite.svg
index 29e87e2b8..64f682c3d 100644
--- a/img/source/sprite.svg
+++ b/img/source/sprite.svg
@@ -39,12 +39,12 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="1"
- inkscape:cx="329.64693"
- inkscape:cy="58.693021"
+ inkscape:zoom="0.5"
+ inkscape:cx="279.87773"
+ inkscape:cy="136.54467"
inkscape:document-units="px"
inkscape:current-layer="layer1"
- showgrid="false"
+ showgrid="true"
inkscape:window-width="1280"
inkscape:window-height="700"
inkscape:window-x="48"
@@ -186,7 +186,7 @@
image/svg+xml
-
+
@@ -195,11 +195,200 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(-25,-62.362183)"
- style="display:inline">
+ style="display:none">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fix misalignment
+
+
+
+
+ RESET
+ style="display:inline;fill:#1a1a1a;fill-opacity:1"
+ transform="translate(505,-653.36218)">
+ style="display:inline;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;overflow:visible;enable-background:accumulate" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+ style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ style="opacity:0.50000000000000000;fill:#000000;fill-opacity:1;display:inline">
+ style="opacity:0.50000000000000000;fill:#000000;fill-opacity:1;display:inline">
@@ -778,9 +932,9 @@
inkscape:connector-curvature="0"
id="path58971"
d="m 35,44 c 0,1 0,4 0,4 0,0 0,0.5 -0.5,0.5 -0.5,0 -0.429283,-0.27516 -0.5,-0.5 -0.304688,-0.96875 -0.867187,-2.36459 -1,-3 -0.204595,-0.97885 -0.666667,-1 -1,-1 -1,0 -1,1 -1,1 l 1,4 0,3 C 32,52 31.5,51.5 30.5,50.5 29.945312,49.94531 29.257659,49.7508 28.8125,50.00781 28.377049,50.25922 28.150942,50.89541 28.5,51.5 28.853553,52.11237 32,56 32,56 c 1,1 2,1 4,1 2.666667,0 1,0 3,0 2,0 2.288488,-2.86546 3,-5 1,-3 1.5,-5 1.5,-5 0.113427,-0.42332 -0.04289,-0.846 -0.5,-1 -0.880461,-0.29662 -1.36006,0.35278 -1.5,1 -0.25,1.15625 -0.5,2 -0.5,2 -0.09375,0.31383 0.0013,0.5 -0.5,0.5 C 39.99086,49.5 40,49 40,49 c 0,0 0,-2.66667 0,-4 0,-1 -1,-1 -1,-1 0,0 -1,0 -1,1 0,1 0,1.66667 0,3 0,0 0.01305,0.5 -0.5,0.5 C 36.998673,48.5 37,48 37,48 c 0,0 0,-3 0,-4 0,-1 -1,-1 -1,-1 0,0 -1,0 -1,1 z"
- style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
+ style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
+ transform="translate(25,-3.0625001e-6)" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- fix misalignment
-
-
-
-
- RESET
diff --git a/index.html b/index.html
index 3be283a1f..ee00705ac 100644
--- a/index.html
+++ b/index.html
@@ -9,8 +9,8 @@
-
-
+
+
@@ -81,6 +81,7 @@
+
@@ -142,7 +143,7 @@
-
-
+
@@ -151,6 +152,7 @@
+
diff --git a/test/index_packaged.html b/test/index_packaged.html
index ef91e2823..d21d48ff2 100644
--- a/test/index_packaged.html
+++ b/test/index_packaged.html
@@ -35,6 +35,7 @@
+
diff --git a/test/spec/actions/connect.js b/test/spec/actions/connect.js
new file mode 100644
index 000000000..3838d83c2
--- /dev/null
+++ b/test/spec/actions/connect.js
@@ -0,0 +1,110 @@
+describe("iD.actions.Connect", function() {
+ describe("#enabled", function () {
+ it("returns true for two or more nodes", function () {
+ expect(iD.actions.Connect(['a', 'b']).enabled()).to.be.true;
+ });
+
+ it("returns false for less than two nodes", function () {
+ expect(iD.actions.Connect(['a']).enabled()).to.be.false;
+ });
+ });
+
+ it("removes all but the final node", function() {
+ var graph = iD.Graph({
+ 'a': iD.Node({id: 'a'}),
+ 'b': iD.Node({id: 'b'}),
+ 'c': iD.Node({id: 'c'})
+ });
+
+ graph = iD.actions.Connect(['a', 'b', 'c'])(graph);
+
+ expect(graph.entity('a')).to.be.undefined;
+ expect(graph.entity('b')).to.be.undefined;
+ expect(graph.entity('c')).not.to.be.undefined;
+ });
+
+ it("replaces non-surviving nodes in parent ways", function() {
+ // a --- b --- c
+ //
+ // e
+ // |
+ // d
+ //
+ // Connect [e, b].
+ //
+ // Expected result:
+ //
+ // a --- b --- c
+ // |
+ // d
+ //
+ var graph = iD.Graph({
+ 'a': iD.Node({id: 'a'}),
+ 'b': iD.Node({id: 'b'}),
+ 'c': iD.Node({id: 'c'}),
+ 'd': iD.Node({id: 'd'}),
+ 'e': iD.Node({id: 'e'}),
+ '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}),
+ '|': iD.Way({id: '|', nodes: ['d', 'e']})
+ });
+
+ graph = iD.actions.Connect(['e', 'b'])(graph);
+
+ expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
+ expect(graph.entity('|').nodes).to.eql(['d', 'b']);
+ });
+
+ it("handles circular ways", function() {
+ // c -- a d === e
+ // | /
+ // | /
+ // | /
+ // b
+ //
+ // Connect [a, d].
+ //
+ var graph = iD.Graph({
+ 'a': iD.Node({id: 'a'}),
+ 'b': iD.Node({id: 'b'}),
+ 'c': iD.Node({id: 'c'}),
+ 'd': iD.Node({id: 'd'}),
+ 'e': iD.Node({id: 'e'}),
+ '-': iD.Way({id: '-', nodes: ['a', 'b', 'c', 'a']}),
+ '=': iD.Way({id: '=', nodes: ['d', 'e']})
+ });
+
+ graph = iD.actions.Connect(['a', 'd'])(graph);
+
+ expect(graph.entity('-').nodes).to.eql(['d', 'b', 'c', 'd']);
+ });
+
+ it("merges tags to the surviving node", function() {
+ var graph = iD.Graph({
+ 'a': iD.Node({id: 'a', tags: {a: 'a'}}),
+ 'b': iD.Node({id: 'b', tags: {b: 'b'}}),
+ 'c': iD.Node({id: 'c', tags: {c: 'c'}})
+ });
+
+ graph = iD.actions.Connect(['a', 'b', 'c'])(graph);
+
+ expect(graph.entity('c').tags).to.eql({a: 'a', b: 'b', c: 'c'});
+ });
+
+ it("merges memberships to the surviving node", function() {
+ var graph = iD.Graph({
+ 'a': iD.Node({id: 'a'}),
+ 'b': iD.Node({id: 'b'}),
+ 'c': iD.Node({id: 'c'}),
+ 'd': iD.Node({id: 'c'}),
+ '-': iD.Way({id: '-', nodes: ['a', 'b']}),
+ '=': iD.Way({id: '=', nodes: ['c', 'd']}),
+ 'r1': iD.Relation({id: 'r1', members: [{id: 'b', role: 'r1', type: 'node'}]}),
+ 'r2': iD.Relation({id: 'r2', members: [{id: 'b', role: 'r1', type: 'node'}, {id: 'c', role: 'r2', type: 'node'}]})
+ });
+
+ graph = iD.actions.Connect(['b', 'c'])(graph);
+
+ expect(graph.entity('r1').members).to.eql([{id: 'c', role: 'r1', type: 'node'}]);
+ expect(graph.entity('r2').members).to.eql([{id: 'c', role: 'r2', type: 'node'}]);
+ });
+});
diff --git a/test/spec/actions/join.js b/test/spec/actions/join.js
index 1cddb94bf..261fe607d 100644
--- a/test/spec/actions/join.js
+++ b/test/spec/actions/join.js
@@ -160,13 +160,13 @@ describe("iD.actions.Join", function () {
'c': iD.Node({id: 'c'}),
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
'=': iD.Way({id: '=', nodes: ['b', 'c']}),
- 'r1': iD.Relation({id: 'r1', members: [{id: '=', role: 'r1'}]}),
- 'r2': iD.Relation({id: 'r2', members: [{id: '=', role: 'r1'}, {id: '-', role: 'r2'}]})
+ 'r1': iD.Relation({id: 'r1', members: [{id: '=', role: 'r1', type: 'way'}]}),
+ 'r2': iD.Relation({id: 'r2', members: [{id: '=', role: 'r1', type: 'way'}, {id: '-', role: 'r2', type: 'way'}]})
});
graph = iD.actions.Join('-', '=')(graph);
- expect(graph.entity('r1').members).to.eql([{id: '-', role: 'r1'}]);
- expect(graph.entity('r2').members).to.eql([{id: '-', role: 'r2'}]);
+ expect(graph.entity('r1').members).to.eql([{id: '-', role: 'r1', type: 'way'}]);
+ expect(graph.entity('r2').members).to.eql([{id: '-', role: 'r2', type: 'way'}]);
});
});
diff --git a/test/spec/svg/midpoints.js b/test/spec/svg/midpoints.js
index c34ac0350..e00f6f78b 100644
--- a/test/spec/svg/midpoints.js
+++ b/test/spec/svg/midpoints.js
@@ -14,6 +14,8 @@ describe("iD.svg.Midpoints", function () {
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]);
+ // If no vertices are drawn, no midpoints are drawn. This dependence needs to be removed
+ surface.call(iD.svg.Vertices(projection), graph, [a], filter);
surface.call(iD.svg.Midpoints(projection), graph, [line], filter);
expect(surface.select('.midpoint').datum().loc).to.eql([25, 0]);
@@ -42,6 +44,8 @@ describe("iD.svg.Midpoints", function () {
graph = iD.Graph([a, b, c, d, l1, l2, l3, l4]),
ab = function (d) { return d.id === [a.id, b.id].sort().join("-"); };
+ // If no vertices are drawn, no midpoints are drawn. This dependence needs to be removed
+ surface.call(iD.svg.Vertices(projection), graph, [a], filter);
surface.call(iD.svg.Midpoints(projection), graph, [l1, l2, l3, l4], filter);
expect(surface.selectAll('.midpoint').filter(ab).datum().ways).to.eql([