diff --git a/css/map.css b/css/map.css
index 1f31beca4..0e3465cc5 100644
--- a/css/map.css
+++ b/css/map.css
@@ -44,10 +44,6 @@ path.casing {
stroke-width: 3;
}
-.elastic-true {
- pointer-events:none;
-}
-
path.casing.hover {
stroke:#FF0F0F !important;
opacity:0.8;
diff --git a/index.html b/index.html
index 9cf8c269f..33706d3dd 100644
--- a/index.html
+++ b/index.html
@@ -45,6 +45,7 @@
+
@@ -54,7 +55,6 @@
-
diff --git a/js/id/actions/start_way.js b/js/id/actions/add_way.js
similarity index 70%
rename from js/id/actions/start_way.js
rename to js/id/actions/add_way.js
index 6c82e389d..4b53a8ea3 100644
--- a/js/id/actions/start_way.js
+++ b/js/id/actions/add_way.js
@@ -1,4 +1,4 @@
-iD.actions.StartWay = function(way) {
+iD.actions.AddWay = function(way) {
return function(graph) {
return graph.replace(way, 'started a road');
};
diff --git a/js/id/actions/add_way_node.js b/js/id/actions/add_way_node.js
index 7c8772dba..f3c4521aa 100644
--- a/js/id/actions/add_way_node.js
+++ b/js/id/actions/add_way_node.js
@@ -1,8 +1,10 @@
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
-iD.actions.AddWayNode = function(way, node, index) {
+iD.actions.AddWayNode = function(wayId, nodeId, index) {
return function(graph) {
- var nodes = way.nodes.slice();
- nodes.splice(index || nodes.length, 0, node.id);
- return graph.replace(way.update({nodes: nodes})).replace(node, 'added to a road');
+ var way = graph.entity(wayId),
+ node = graph.entity(nodeId),
+ nodes = way.nodes.slice();
+ nodes.splice(index || nodes.length, 0, nodeId);
+ return graph.replace(way.update({nodes: nodes}), 'added to a road');
};
};
diff --git a/js/id/actions/change_entity_tags.js b/js/id/actions/change_entity_tags.js
index 97c67f0aa..25cf5911c 100644
--- a/js/id/actions/change_entity_tags.js
+++ b/js/id/actions/change_entity_tags.js
@@ -1,7 +1,6 @@
-iD.actions.ChangeEntityTags = function(entity, tags) {
+iD.actions.ChangeEntityTags = function(entityId, tags) {
return function(graph) {
- return graph.replace(entity.update({
- tags: tags
- }), 'changed tags');
+ var entity = graph.entity(entityId);
+ return graph.replace(entity.update({tags: tags}), 'changed tags');
};
};
diff --git a/js/id/actions/delete_node.js b/js/id/actions/delete_node.js
index c7813ce48..fb858d75f 100644
--- a/js/id/actions/delete_node.js
+++ b/js/id/actions/delete_node.js
@@ -1,14 +1,16 @@
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
-iD.actions.DeleteNode = function(node) {
+iD.actions.DeleteNode = function(nodeId) {
return function(graph) {
- graph.parentWays(node.id)
+ var node = graph.entity(nodeId);
+
+ graph.parentWays(nodeId)
.forEach(function(parent) {
- graph = iD.actions.RemoveWayNode(parent, node)(graph);
+ graph = iD.actions.RemoveWayNode(parent.id, nodeId)(graph);
});
- graph.parentRelations(node.id)
+ graph.parentRelations(nodeId)
.forEach(function(parent) {
- graph = iD.actions.RemoveRelationMember(parent, node)(graph);
+ graph = iD.actions.RemoveRelationMember(parent.id, nodeId)(graph);
});
return graph.remove(node, 'removed a node');
diff --git a/js/id/actions/delete_way.js b/js/id/actions/delete_way.js
index 641f61af2..86fe3a3bc 100644
--- a/js/id/actions/delete_way.js
+++ b/js/id/actions/delete_way.js
@@ -1,17 +1,19 @@
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
-iD.actions.DeleteWay = function(way) {
+iD.actions.DeleteWay = function(wayId) {
return function(graph) {
- graph.parentRelations(way.id)
+ var way = graph.entity(wayId);
+
+ graph.parentRelations(wayId)
.forEach(function(parent) {
- graph = iD.actions.RemoveRelationMember(parent, way)(graph);
+ graph = iD.actions.RemoveRelationMember(parent.id, wayId)(graph);
});
- way.nodes.forEach(function (id) {
- var node = graph.entity(id);
+ way.nodes.forEach(function (nodeId) {
+ var node = graph.entity(nodeId);
- graph = iD.actions.RemoveWayNode(way, node)(graph);
+ graph = iD.actions.RemoveWayNode(wayId, nodeId)(graph);
- if (!graph.parentWays(id).length && !graph.parentRelations(id).length) {
+ if (!graph.parentWays(nodeId).length && !graph.parentRelations(nodeId).length) {
if (!node.hasInterestingTags()) {
graph = graph.remove(node);
} else {
diff --git a/js/id/actions/move.js b/js/id/actions/move.js
index 6c15e8bdc..42c82db56 100644
--- a/js/id/actions/move.js
+++ b/js/id/actions/move.js
@@ -1,7 +1,8 @@
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
-iD.actions.Move = function(entity, loc) {
+iD.actions.Move = function(entityId, loc) {
return function(graph) {
+ var entity = graph.entity(entityId);
return graph.replace(entity.update({loc: loc}), 'moved an element');
};
};
diff --git a/js/id/actions/remove_relation_member.js b/js/id/actions/remove_relation_member.js
index b10224c26..f4061d177 100644
--- a/js/id/actions/remove_relation_member.js
+++ b/js/id/actions/remove_relation_member.js
@@ -1,6 +1,7 @@
-iD.actions.RemoveRelationMember = function(relation, member) {
+iD.actions.RemoveRelationMember = function(relationId, memberId) {
return function(graph) {
- var members = _.without(relation.members, member.id);
+ var relation = graph.entity(relationId),
+ members = _.without(relation.members, memberId);
return graph.replace(relation.update({members: members}), 'removed from a relation');
};
};
diff --git a/js/id/actions/remove_way_node.js b/js/id/actions/remove_way_node.js
index bf645b6b2..5988e0f0b 100644
--- a/js/id/actions/remove_way_node.js
+++ b/js/id/actions/remove_way_node.js
@@ -1,6 +1,7 @@
-iD.actions.RemoveWayNode = function(way, node) {
+iD.actions.RemoveWayNode = function(wayId, nodeId) {
return function(graph) {
- var nodes = _.without(way.nodes, node.id);
+ var way = graph.entity(wayId),
+ nodes = _.without(way.nodes, nodeId);
return graph.replace(way.update({nodes: nodes}), 'removed from a road');
};
};
diff --git a/js/id/actions/reverse_way.js b/js/id/actions/reverse_way.js
index 4d14eb8f1..b170bf883 100644
--- a/js/id/actions/reverse_way.js
+++ b/js/id/actions/reverse_way.js
@@ -1,8 +1,8 @@
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
-iD.actions.ReverseWay = function(way) {
+iD.actions.ReverseWay = function(wayId) {
return function(graph) {
- return graph.replace(way.update({
- nodes: way.nodes.slice()
- }), 'changed way direction');
+ var way = graph.entity(wayId),
+ nodes = way.nodes.slice();
+ return graph.replace(way.update({nodes: nodes}), 'changed way direction');
};
};
diff --git a/js/id/graph/history.js b/js/id/graph/history.js
index 11a6111ce..df444840b 100644
--- a/js/id/graph/history.js
+++ b/js/id/graph/history.js
@@ -19,16 +19,28 @@ iD.History = function() {
}
},
- perform: function (action) {
+ perform: function () {
stack = stack.slice(0, index + 1);
- stack.push(action(this.graph()));
+
+ var graph = this.graph();
+ for (var i = 0; i < arguments.length; i++) {
+ graph = arguments[i](graph);
+ }
+
+ stack.push(graph);
index++;
maybeChange();
},
- replace: function (action) {
+ replace: function () {
// assert(index == stack.length - 1)
- stack[index] = action(this.graph());
+
+ var graph = this.graph();
+ for (var i = 0; i < arguments.length; i++) {
+ graph = arguments[i](graph);
+ }
+
+ stack[index] = graph;
maybeChange();
},
diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js
index 15fe6fd84..7a76a98db 100644
--- a/js/id/modes/add_area.js
+++ b/js/id/modes/add_area.js
@@ -12,19 +12,21 @@ iD.modes.AddArea = function() {
mode.map.surface.on('click.addarea', function() {
var datum = d3.select(d3.event.target).datum() || {},
- node,
way = iD.Way({tags: { building: 'yes', area: 'yes' }});
// connect a way to an existing way
if (datum.type === 'node') {
- node = datum;
+ mode.history.perform(
+ iD.actions.AddWay(way),
+ iD.actions.AddWayNode(way.id, datum.id));
} else {
- node = iD.Node({loc: mode.map.mouseCoordinates()});
+ var node = iD.Node({loc: mode.map.mouseCoordinates()});
+ mode.history.perform(
+ iD.actions.AddWay(way),
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(way.id, node.id));
}
- mode.history.perform(iD.actions.StartWay(way));
- mode.history.perform(iD.actions.AddWayNode(way, node));
-
mode.controller.enter(iD.modes.DrawArea(way.id));
});
diff --git a/js/id/modes/add_road.js b/js/id/modes/add_road.js
index 8f7495b45..a194b3295 100644
--- a/js/id/modes/add_road.js
+++ b/js/id/modes/add_road.js
@@ -7,54 +7,53 @@ iD.modes.AddRoad = function() {
};
mode.enter = function() {
- mode.map.dblclickEnable(false);
+ var map = mode.map;
- mode.map.hint('Click on the map to start drawing an road, path, or route.');
+ map.dblclickEnable(false)
+ .hint('Click on the map to start drawing an road, path, or route.');
- mode.map.surface.on('click.addroad', function() {
+ map.surface.on('click.addroad', function() {
var datum = d3.select(d3.event.target).datum() || {},
- node,
direction = 'forward',
- start = true,
way = iD.Way({ tags: { highway: 'residential' } });
if (datum.type === 'node') {
// continue an existing way
- node = datum;
-
var id = datum.id;
var parents = mode.history.graph().parentWays(id);
- if (parents.length) {
- if (parents[0].nodes[0] === id) {
- way = parents[0];
- direction = 'backward';
- start = false;
- } else if (_.last(parents[0].nodes) === id) {
- way = parents[0];
- start = false;
- }
+ if (parents.length && parents[0].nodes[0] === id) {
+ way = parents[0];
+ direction = 'backward';
+ } else if (parents.length && _.last(parents[0].nodes) === id) {
+ way = parents[0];
+ } else {
+ mode.history.perform(
+ iD.actions.AddWay(way),
+ iD.actions.AddWayNode(way.id, datum.id));
}
} else if (datum.type === 'way') {
// begin a new way starting from an existing way
- node = iD.Node({loc: mode.map.mouseCoordinates()});
+ var node = iD.Node({loc: map.mouseCoordinates()}),
+ index = iD.util.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
- var index = iD.util.geo.chooseIndex(datum, d3.mouse(mode.map.surface.node()), mode.map);
- var connectedWay = mode.history.graph().entity(datum.id);
- mode.history.perform(iD.actions.AddWayNode(connectedWay, node, index));
+ mode.history.perform(
+ iD.actions.AddWay(way),
+ iD.actions.AddWayNode(datum.id, node, index),
+ iD.actions.AddWayNode(way.id, node.id));
} else {
// begin a new way
- node = iD.Node({loc: mode.map.mouseCoordinates()});
- }
+ var node = iD.Node({loc: map.mouseCoordinates()});
- if (start) {
- mode.history.perform(iD.actions.StartWay(way));
- mode.history.perform(iD.actions.AddWayNode(way, node));
+ mode.history.perform(
+ iD.actions.AddWay(way),
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(way.id, node.id));
}
mode.controller.enter(iD.modes.DrawRoad(way.id, direction));
});
- mode.map.keybinding().on('⎋.addroad', function() {
+ map.keybinding().on('⎋.addroad', function() {
mode.controller.exit();
});
};
diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js
index 51d65289c..034330359 100644
--- a/js/id/modes/browse.js
+++ b/js/id/modes/browse.js
@@ -17,17 +17,17 @@ iD.modes.Browse = function() {
d3.event.sourceEvent.stopPropagation();
if (!dragging) {
if (entity.accuracy) {
- var way = history.graph().entity(entity.way),
- index = entity.index;
- entity = iD.Node(entity);
- mode.history.perform(iD.actions.AddWayNode(way, entity, index));
+ var node = iD.Node(entity);
+ mode.history.perform(
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(entity.way, node.id, entity.index));
}
dragging = iD.util.trueObj([entity.id].concat(
_.pluck(mode.history.graph().parentWays(entity.id), 'id')));
mode.history.perform(iD.actions.Noop());
}
var to = mode.map.projection.invert([d3.event.x, d3.event.y]);
- mode.history.replace(iD.actions.Move(entity, to));
+ mode.history.replace(iD.actions.Move(entity.id, to));
})
.on('dragend', function () {
if (!dragging) return;
diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js
index 83cc80030..2b952a897 100644
--- a/js/id/modes/draw_area.js
+++ b/js/id/modes/draw_area.js
@@ -1,68 +1,68 @@
-iD.modes.DrawArea = function(way_id) {
+iD.modes.DrawArea = function(wayId) {
var mode = {
button: 'area'
};
mode.enter = function() {
+ var map = mode.map,
+ history = mode.history,
+ controller = mode.controller,
+ way = history.graph().entity(wayId),
+ headId = _.last(way.nodes),
+ tailId = _.first(way.nodes),
+ node = iD.Node({loc: map.mouseCoordinates()});
- mode.map.hint('Click on the map to add points to your area. Finish the ' +
+ map.dblclickEnable(false)
+ .fastEnable(false)
+ .hint('Click on the map to add points to your area. Finish the ' +
'area by clicking on your first point');
- mode.map.dblclickEnable(false).fastEnable(false);
- var way = mode.history.graph().entity(way_id),
- firstnode_id = _.first(way.nodes),
- node = iD.Node({loc: mode.map.mouseCoordinates()});
+ history.perform(
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(way.id, node.id));
- function finish(next) {
- way = mode.history.graph().entity(way.id);
- way.tags = _.omit(way.tags, 'elastic');
- mode.history.perform(iD.actions.ChangeEntityTags(way, way.tags));
- return mode.controller.enter(next);
- }
-
- mode.history.perform(iD.actions.AddWayNode(way, node));
-
- mode.map.surface.on('mousemove.drawarea', function() {
- mode.history.replace(iD.actions.AddWayNode(way, node.update({loc: mode.map.mouseCoordinates()})));
+ map.surface.on('mousemove.drawarea', function() {
+ history.replace(iD.actions.Move(node.id, map.mouseCoordinates()));
});
- mode.map.surface.on('click.drawarea', function() {
- d3.event.stopPropagation();
+ map.surface.on('click.drawarea', function() {
+ var datum = d3.select(d3.event.target).datum() || {};
- var datum = d3.select(d3.event.target).datum();
+ if (datum.id === tailId) {
+ history.replace(
+ iD.actions.DeleteNode(node.id),
+ iD.actions.AddWayNode(way.id, tailId));
- if (datum.type === 'node') {
- if (datum.id == firstnode_id) {
- mode.history.replace(iD.actions.DeleteNode(node));
- mode.history.replace(iD.actions.AddWayNode(way,
- mode.history.graph().entity(way.nodes[0])));
+ controller.enter(iD.modes.Select(way));
+
+ } else if (datum.type === 'node' && datum.id !== node.id) {
+ // connect the way to an existing node
+ history.replace(
+ iD.actions.DeleteNode(node.id),
+ iD.actions.AddWayNode(way.id, datum.id));
+
+ controller.enter(iD.modes.DrawArea(wayId));
- return finish(iD.modes.Select(way));
- } else {
- // connect a way to an existing way
- mode.history.replace(iD.actions.AddWayNode(way, datum));
- }
} else {
- node = node.update({loc: mode.map.mouseCoordinates()});
- mode.history.replace(iD.actions.AddWayNode(way, node));
+ controller.enter(iD.modes.DrawArea(wayId));
}
-
- mode.controller.enter(iD.modes.DrawArea(way_id));
});
- mode.map.keybinding().on('⎋.drawarea', function() {
- finish(iD.modes.Browse());
+ map.keybinding().on('⎋.drawarea', function() {
+ history.replace(
+ iD.actions.DeleteNode(node.id));
+
+ controller.enter(iD.modes.Browse());
});
- mode.map.keybinding().on('⌫.drawarea', function() {
+ map.keybinding().on('⌫.drawarea', function() {
d3.event.preventDefault();
- var lastNode = _.last(way.nodes);
- mode.history.replace(iD.actions.RemoveWayNode(way,
- mode.history.graph().entity(lastNode)));
- mode.history.replace(iD.actions.DeleteNode(
- mode.history.graph().entity(lastNode)));
- mode.history.replace(iD.actions.DeleteNode(node));
- mode.controller.enter(iD.modes.DrawArea(way_id));
+
+ history.replace(
+ iD.actions.DeleteNode(node.id),
+ iD.actions.DeleteNode(headId));
+
+ controller.enter(iD.modes.DrawArea(wayId));
});
};
diff --git a/js/id/modes/draw_road.js b/js/id/modes/draw_road.js
index e8a637e3f..46ac3e818 100644
--- a/js/id/modes/draw_road.js
+++ b/js/id/modes/draw_road.js
@@ -1,95 +1,81 @@
-iD.modes.DrawRoad = function(way_id, direction) {
+iD.modes.DrawRoad = function(wayId, direction) {
var mode = {
button: 'road'
};
mode.enter = function() {
- mode.map.dblclickEnable(false)
+ var map = mode.map,
+ history = mode.history,
+ controller = mode.controller,
+ way = history.graph().entity(wayId),
+ node = iD.Node({loc: map.mouseCoordinates()}),
+ index = (direction === 'forward') ? undefined : -1,
+ headId = (direction === 'forward') ? _.last(way.nodes) : _.first(way.nodes),
+ tailId = (direction === 'forward') ? _.first(way.nodes) : _.last(way.nodes);
+
+ map.dblclickEnable(false)
.dragEnable(false)
- .fastEnable(false);
+ .fastEnable(false)
+ .hint('Click to add more points to the road. ' +
+ 'Click on other roads to connect to them, and double-click to ' +
+ 'end the road.');
- mode.map.hint('Click to add more points to the road. ' +
- 'Click on other roads to connect to them, and double-click to ' +
- 'end the road.');
+ history.perform(
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(wayId, node.id, index));
- var index = (direction === 'forward') ? undefined : -1,
- node = iD.Node({loc: mode.map.mouseCoordinates() }),
- way = mode.history.graph().entity(way_id),
- firstNode = way.nodes[0],
- lastNode = _.last(way.nodes);
-
- function finish(next) {
- way.tags = _.omit(way.tags, 'elastic');
- mode.history.perform(iD.actions.ChangeEntityTags(way, way.tags));
- return mode.controller.enter(next);
- }
-
- mode.history.perform(iD.actions.AddWayNode(way, node, index));
-
- mode.map.surface.on('mousemove.drawroad', function() {
- mode.history.replace(iD.actions.AddWayNode(way,
- node.update({ loc: mode.map.mouseCoordinates() }), index));
+ map.surface.on('mousemove.drawroad', function() {
+ history.replace(iD.actions.Move(node.id, map.mouseCoordinates()));
});
- mode.map.surface.on('click.drawroad', function() {
- // d3.event.stopPropagation();
-
+ map.surface.on('click.drawroad', function() {
var datum = d3.select(d3.event.target).datum() || {};
+ if (datum.id === tailId) {
+ // connect the way in a loop
+ history.replace(
+ iD.actions.DeleteNode(node.id),
+ iD.actions.AddWayNode(wayId, tailId, index));
+
+ controller.enter(iD.modes.Select(way));
+
+ } else if (datum.type === 'node' && datum.id !== node.id) {
+ // connect the way to an existing node
+ history.replace(
+ iD.actions.DeleteNode(node.id),
+ iD.actions.AddWayNode(wayId, datum.id, index));
+
+ controller.enter(iD.modes.DrawRoad(wayId, direction));
- if (datum.type === 'node') {
- if (datum.id == firstNode || datum.id == lastNode) {
- // If mode is drawing a loop and mode is not the drawing
- // end of the stick, finish the circle
- if (direction === 'forward' && datum.id == firstNode) {
- mode.history.replace(iD.actions.AddWayNode(way,
- mode.history.graph().entity(firstNode), index));
- } else if (direction === 'backward' && datum.id == lastNode) {
- mode.history.replace(iD.actions.AddWayNode(way,
- mode.history.graph().entity(lastNode), index));
- }
- mode.history.replace(iD.actions.DeleteNode(node));
- return finish(iD.modes.Select(way));
- } else if (datum.id == node.id) {
- datum = datum.update({ tags: {} });
- mode.history.replace(iD.actions.ChangeEntityTags(datum, {}));
- mode.history.replace(iD.actions.DeleteNode(node));
- mode.history.replace(iD.actions.AddWayNode(way, datum, index));
- } else {
- // connect a way to an existing way
- mode.history.replace(iD.actions.DeleteNode(node));
- mode.history.replace(iD.actions.AddWayNode(way, datum, index));
- }
} else if (datum.type === 'way') {
- node = node.update({loc: mode.map.mouseCoordinates() });
- mode.history.replace(iD.actions.AddWayNode(way, node, index));
+ // connect the way to an existing way
+ var connectedIndex = iD.modes.chooseIndex(datum, d3.mouse(map.surface.node()), map);
+
+ history.replace(
+ iD.actions.AddWayNode(datum.id, node.id, connectedIndex));
+
+ controller.enter(iD.modes.DrawRoad(wayId, direction));
- var connectedWay = mode.history.graph().entity(datum.id);
- var connectedIndex = iD.modes.chooseIndex(datum,
- d3.mouse(mode.map.surface.node()),
- mode.map);
- mode.history.perform(iD.actions.AddWayNode(connectedWay,
- node,
- connectedIndex));
} else {
- mode.history.replace(iD.actions.AddWayNode(way, node, index));
+ controller.enter(iD.modes.DrawRoad(wayId, direction));
}
-
- mode.controller.enter(iD.modes.DrawRoad(way_id, direction));
});
- mode.map.keybinding().on('⎋.drawroad', function() {
- finish(iD.modes.Browse());
+ map.keybinding().on('⎋.drawroad', function() {
+ history.replace(
+ iD.actions.DeleteNode(node.id));
+
+ controller.enter(iD.modes.Browse());
});
- mode.map.keybinding().on('⌫.drawroad', function() {
+ map.keybinding().on('⌫.drawroad', function() {
d3.event.preventDefault();
- mode.history.replace(iD.actions.RemoveWayNode(way,
- mode.history.graph().entity(lastNode)));
- mode.history.replace(iD.actions.DeleteNode(
- mode.history.graph().entity(lastNode)));
- mode.history.replace(iD.actions.DeleteNode(node));
- mode.controller.enter(iD.modes.DrawRoad(way_id, direction));
+
+ history.replace(
+ iD.actions.DeleteNode(node.id),
+ iD.actions.DeleteNode(headId));
+
+ controller.enter(iD.modes.DrawRoad(wayId, direction));
});
};
diff --git a/js/id/modes/select.js b/js/id/modes/select.js
index d4ad71c74..07dc36723 100644
--- a/js/id/modes/select.js
+++ b/js/id/modes/select.js
@@ -1,8 +1,9 @@
iD.modes.Select = function (entity) {
var mode = {
- button: ''
- },
- inspector = iD.Inspector(),
+ button: 'browse'
+ };
+
+ var inspector = iD.Inspector(),
dragging, target;
var dragWay = d3.behavior.drag()
@@ -26,8 +27,7 @@ iD.modes.Select = function (entity) {
var end = mode.map.projection.invert([
start[0] + d3.event.dx,
start[1] + d3.event.dy]);
- node.loc = end;
- mode.history.replace(iD.actions.Move(node, end));
+ mode.history.replace(iD.actions.Move(node.id, end));
});
})
.on('dragend', function () {
@@ -39,10 +39,10 @@ iD.modes.Select = function (entity) {
function remove() {
switch (entity.type) {
case 'way':
- mode.history.perform(iD.actions.DeleteWay(entity));
+ mode.history.perform(iD.actions.DeleteWay(entity.id));
break;
case 'node':
- mode.history.perform(iD.actions.DeleteNode(entity));
+ mode.history.perform(iD.actions.DeleteNode(entity.id));
}
mode.controller.exit();
@@ -59,9 +59,9 @@ iD.modes.Select = function (entity) {
.call(inspector);
inspector.on('changeTags', function(d, tags) {
- mode.history.perform(iD.actions.ChangeEntityTags(mode.history.graph().entity(d.id), tags));
+ mode.history.perform(iD.actions.ChangeEntityTags(d.id, tags));
}).on('changeWayDirection', function(d) {
- mode.history.perform(iD.actions.ReverseWay(d));
+ mode.history.perform(iD.actions.ReverseWay(d.id));
}).on('remove', function() {
remove();
}).on('close', function() {
diff --git a/test/index.html b/test/index.html
index f5234875f..dbfd7cba6 100644
--- a/test/index.html
+++ b/test/index.html
@@ -45,6 +45,7 @@
+
@@ -54,7 +55,6 @@
-
diff --git a/test/spec/actions/add_way_node.js b/test/spec/actions/add_way_node.js
index e1df86158..aaed97ecc 100644
--- a/test/spec/actions/add_way_node.js
+++ b/test/spec/actions/add_way_node.js
@@ -2,14 +2,14 @@ describe("iD.actions.AddWayNode", function () {
it("adds a node to the end of a way", function () {
var way = iD.Way(),
node = iD.Node({id: "n1"}),
- graph = iD.actions.AddWayNode(way, node)(iD.Graph());
+ graph = iD.actions.AddWayNode(way.id, node.id)(iD.Graph([way, node]));
expect(graph.entity(way.id).nodes).to.eql(["n1"]);
});
it("adds a node to a way at the specified index", function () {
var way = iD.Way({nodes: ["n1", "n3"]}),
node = iD.Node({id: "n2"}),
- graph = iD.actions.AddWayNode(way, node, 1)(iD.Graph());
+ graph = iD.actions.AddWayNode(way.id, node.id, 1)(iD.Graph([way, node]));
expect(graph.entity(way.id).nodes).to.eql(["n1", "n2", "n3"]);
});
});
diff --git a/test/spec/actions/delete_node.js b/test/spec/actions/delete_node.js
index 82388b96c..a296a75b5 100644
--- a/test/spec/actions/delete_node.js
+++ b/test/spec/actions/delete_node.js
@@ -1,7 +1,7 @@
describe("iD.actions.DeleteNode", function () {
it("removes the node from the graph", function () {
var node = iD.Node(),
- action = iD.actions.DeleteNode(node),
+ action = iD.actions.DeleteNode(node.id),
graph = action(iD.Graph([node]));
expect(graph.entity(node.id)).to.be.undefined;
});
@@ -9,7 +9,7 @@ describe("iD.actions.DeleteNode", function () {
it("removes the node from parent ways", function () {
var node = iD.Node(),
way = iD.Way({nodes: [node.id]}),
- action = iD.actions.DeleteNode(node),
+ action = iD.actions.DeleteNode(node.id),
graph = action(iD.Graph([node, way]));
expect(graph.entity(way.id).nodes).not.to.contain(node.id);
});
@@ -17,7 +17,7 @@ describe("iD.actions.DeleteNode", function () {
it("removes the node from parent relations", function () {
var node = iD.Node(),
relation = iD.Relation({members: [node.id]}),
- action = iD.actions.DeleteNode(node),
+ action = iD.actions.DeleteNode(node.id),
graph = action(iD.Graph([node, relation]));
expect(graph.entity(relation.id).members).not.to.contain(node.id);
});
diff --git a/test/spec/actions/delete_way.js b/test/spec/actions/delete_way.js
index 0323b75ee..cb67e9081 100644
--- a/test/spec/actions/delete_way.js
+++ b/test/spec/actions/delete_way.js
@@ -1,7 +1,7 @@
describe("iD.actions.DeleteWay", function () {
it("removes the way from the graph", function () {
var way = iD.Way(),
- action = iD.actions.DeleteWay(way),
+ action = iD.actions.DeleteWay(way.id),
graph = action(iD.Graph([way]));
expect(graph.entity(way.id)).to.be.undefined;
});
@@ -9,7 +9,7 @@ describe("iD.actions.DeleteWay", function () {
it("removes a way from parent relations", function () {
var way = iD.Way(),
relation = iD.Relation({members: [way.id]}),
- action = iD.actions.DeleteWay(way),
+ action = iD.actions.DeleteWay(way.id),
graph = action(iD.Graph([way, relation]));
expect(graph.entity(relation.id).members).not.to.contain(way.id);
});
@@ -17,7 +17,7 @@ describe("iD.actions.DeleteWay", function () {
it("deletes member nodes not referenced by another parent", function () {
var node = iD.Node(),
way = iD.Way({nodes: [node.id]}),
- action = iD.actions.DeleteWay(way),
+ action = iD.actions.DeleteWay(way.id),
graph = action(iD.Graph([node, way]));
expect(graph.entity(node.id)).to.be.undefined;
});
@@ -26,7 +26,7 @@ describe("iD.actions.DeleteWay", function () {
var node = iD.Node(),
way1 = iD.Way({nodes: [node.id]}),
way2 = iD.Way({nodes: [node.id]}),
- action = iD.actions.DeleteWay(way1),
+ action = iD.actions.DeleteWay(way1.id),
graph = action(iD.Graph([node, way1, way2]));
expect(graph.entity(node.id)).not.to.be.undefined;
});
@@ -34,7 +34,7 @@ describe("iD.actions.DeleteWay", function () {
it("does not delete member nodes with interesting tags", function () {
var node = iD.Node({tags: {highway: 'traffic_signals'}}),
way = iD.Way({nodes: [node.id]}),
- action = iD.actions.DeleteWay(way),
+ action = iD.actions.DeleteWay(way.id),
graph = action(iD.Graph([node, way]));
expect(graph.entity(node.id)).not.to.be.undefined;
});
@@ -42,7 +42,7 @@ describe("iD.actions.DeleteWay", function () {
it("registers member nodes with interesting tags as POIs", function () {
var node = iD.Node({tags: {highway: 'traffic_signals'}}),
way = iD.Way({nodes: [node.id]}),
- action = iD.actions.DeleteWay(way),
+ action = iD.actions.DeleteWay(way.id),
graph = action(iD.Graph([node, way]));
expect(graph.entity(node.id)._poi).to.be.ok;
});
diff --git a/test/spec/actions/remove_way_node.js b/test/spec/actions/remove_way_node.js
index 56a302ec0..6e5751b76 100644
--- a/test/spec/actions/remove_way_node.js
+++ b/test/spec/actions/remove_way_node.js
@@ -2,7 +2,7 @@ describe("iD.actions.RemoveWayNode", function () {
it("removes a node from a way", function () {
var node = iD.Node({id: "n1"}),
way = iD.Way({id: "w1", nodes: ["n1"]}),
- graph = iD.actions.RemoveWayNode(way, node)(iD.Graph({n1: node, w1: way}));
+ graph = iD.actions.RemoveWayNode(way.id, node.id)(iD.Graph({n1: node, w1: way}));
expect(graph.entity(way.id).nodes).to.eql([]);
});
});
diff --git a/test/spec/graph/history.js b/test/spec/graph/history.js
index dda4f3168..49f4fe397 100644
--- a/test/spec/graph/history.js
+++ b/test/spec/graph/history.js
@@ -36,6 +36,48 @@ describe("History", function () {
history.perform(iD.actions.Noop);
expect(spy).not.to.have.been.called;
});
+
+ it("performs multiple actions", function () {
+ var action1 = sinon.stub().returns(graph),
+ action2 = sinon.stub().returns(graph);
+ history.perform(action1, action2);
+ expect(action1).to.have.been.called;
+ expect(action2).to.have.been.called;
+ });
+ });
+
+ describe("#replace", function () {
+ it("updates the graph", function () {
+ history.replace(action);
+ expect(history.graph()).to.equal(graph);
+ });
+
+ it("replaces the undo stack", function () {
+ history.perform(action);
+ history.replace(action);
+ history.undo();
+ expect(history.undoAnnotation()).to.be.undefined;
+ });
+
+ it("emits a change event", function () {
+ history.on('change', spy);
+ history.replace(action);
+ expect(spy).to.have.been.called;
+ });
+
+ it("does not emit a change event when performing a noop", function () {
+ history.on('change', spy);
+ history.replace(iD.actions.Noop);
+ expect(spy).not.to.have.been.called;
+ });
+
+ it("performs multiple actions", function () {
+ var action1 = sinon.stub().returns(graph),
+ action2 = sinon.stub().returns(graph);
+ history.replace(action1, action2);
+ expect(action1).to.have.been.called;
+ expect(action2).to.have.been.called;
+ });
});
describe("#undo", function () {