diff --git a/js/id/actions/move.js b/js/id/actions/move.js index 09a69f09c..db6078c3a 100644 --- a/js/id/actions/move.js +++ b/js/id/actions/move.js @@ -14,7 +14,7 @@ iD.actions.Move = function(ids, delta, projection) { }); } - return function(graph) { + var action = function(graph) { var nodes = []; addNodes(ids, nodes, graph); @@ -28,4 +28,13 @@ iD.actions.Move = function(ids, delta, projection) { return graph; }; + + action.enabled = function(graph) { + return _.every(ids, function(id) { + var entity = graph.entity(id); + return entity.type !== 'relation' || entity.isComplete(graph); + }); + }; + + return action; }; diff --git a/js/id/core/relation.js b/js/id/core/relation.js index 778568917..13f7dc294 100644 --- a/js/id/core/relation.js +++ b/js/id/core/relation.js @@ -140,6 +140,15 @@ _.extend(iD.Relation.prototype, { return this.tags.type === 'multipolygon'; }, + isComplete: function(resolver) { + for (var i = 0; i < this.members.length; i++) { + if (!resolver.entity(this.members[i].id)) { + return false; + } + } + return true; + }, + isRestriction: function() { return !!(this.tags.type && this.tags.type.match(/^restriction:?/)); }, diff --git a/js/id/operations/move.js b/js/id/operations/move.js index 23e9bdcc6..7d3f7143e 100644 --- a/js/id/operations/move.js +++ b/js/id/operations/move.js @@ -1,5 +1,4 @@ iD.operations.Move = function(selection, context) { - var operation = function() { context.enter(iD.modes.Move(context, selection)); }; @@ -10,7 +9,8 @@ iD.operations.Move = function(selection, context) { }; operation.enabled = function() { - return true; + return iD.actions.Move(selection) + .enabled(context.graph()); }; operation.id = "move"; diff --git a/test/spec/actions/move.js b/test/spec/actions/move.js index 2017409c7..1e64c58e0 100644 --- a/test/spec/actions/move.js +++ b/test/spec/actions/move.js @@ -1,4 +1,28 @@ describe("iD.actions.Move", function() { + describe("#enabled", function() { + it("returns true by default", function() { + var node = iD.Node({loc: [0, 0]}), + action = iD.actions.Move([node.id], [0, 0], d3.geo.mercator()), + graph = iD.Graph([node]); + expect(action.enabled(graph)).to.be.true; + }); + + it("returns false for an incomplete relation", function() { + var relation = iD.Relation({members: [{id: 1}]}), + action = iD.actions.Move([relation.id], [0, 0], d3.geo.mercator()), + graph = iD.Graph([relation]); + expect(action.enabled(graph)).to.be.false; + }); + + it("returns true for a complete relation", function() { + var node = iD.Node({loc: [0, 0]}), + relation = iD.Relation({members: [{id: node.id}]}), + action = iD.actions.Move([relation.id], [0, 0], d3.geo.mercator()), + graph = iD.Graph([node, relation]); + expect(action.enabled(graph)).to.be.true; + }); + }); + it("moves all nodes in a way by the given amount", function() { var node1 = iD.Node({loc: [0, 0]}), node2 = iD.Node({loc: [5, 10]}),