From b1daf85cfde0156b7ced0d6055a92b37340ee64c Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 29 Mar 2013 12:17:39 -0700 Subject: [PATCH] Tooltips for disabled operations (fixes #573) --- data/core.yaml | 16 +++++++++++++--- data/locales.js | 27 +++++++++++++++++++-------- js/id/actions/circularize.js | 5 +++-- js/id/actions/connect.js | 8 +------- js/id/actions/disconnect.js | 15 +++++++-------- js/id/actions/join.js | 13 +++++++------ js/id/actions/merge.js | 9 +++++---- js/id/actions/move.js | 11 +++++++---- js/id/actions/orthogonalize.js | 5 +++-- js/id/actions/split.js | 8 ++++++-- js/id/modes/select.js | 2 +- js/id/operations/circularize.js | 15 +++++++++++---- js/id/operations/delete.js | 9 ++++++--- js/id/operations/disconnect.js | 12 +++++++++--- js/id/operations/merge.js | 19 ++++++++++++++----- js/id/operations/move.js | 12 +++++++++--- js/id/operations/orthogonalize.js | 11 +++++++++-- js/id/operations/reverse.js | 9 ++++++--- js/id/operations/rotate.js | 9 ++++++--- js/id/operations/split.js | 12 +++++++++--- js/id/ui/radial_menu.js | 7 +++++-- test/spec/actions/connect.js | 10 ---------- test/spec/actions/disconnect.js | 14 +++++++------- test/spec/actions/join.js | 30 +++++++++++++++++++----------- test/spec/actions/merge.js | 4 ++-- test/spec/actions/move.js | 14 +++++++------- test/spec/actions/split.js | 14 +++++++------- 27 files changed, 198 insertions(+), 122 deletions(-) diff --git a/data/core.yaml b/data/core.yaml index 82f36ef16..621edc78d 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -39,11 +39,14 @@ en: annotation: Changed tags. circularize: title: Circularize - description: Make this round. + description: + line: Make this line circular. + area: Make this area circular. key: O annotation: line: Made a line circular. area: Made an area circular. + not_closed: This can't be made circular because it's not a loop. orthogonalize: title: Orthogonalize description: Square these corners. @@ -51,6 +54,7 @@ en: annotation: line: Squared the corners of a line. area: Squared the corners of an area. + not_closed: This can't be made square because it's not a loop. delete: title: Delete description: Remove this from the map. @@ -69,14 +73,17 @@ en: area: Connected a way to an area. disconnect: title: Disconnect - description: Disconnect these ways from each other. + description: Disconnect these lines/areas from each other. key: D - annotation: Disconnected ways. + annotation: Disconnected lines/areas. + not_connected: There aren't enough lines/areas here to disconnect. merge: title: Merge description: Merge these lines. key: C annotation: "Merged {n} lines." + not_eligible: These features can't be merged. + not_adjacent: These lines can't be merged because they aren't connected. move: title: Move description: Move this to a different location. @@ -87,6 +94,7 @@ en: line: Moved a line. area: Moved an area. multiple: Moved multiple objects. + incomplete_relation: This feature can't be moved because it hasn't been fully downloaded. rotate: title: Rotate description: Rotate this object around its centre point. @@ -104,6 +112,8 @@ en: description: Split this into two ways at this point. key: X annotation: Split a way. + not_eligible: Lines can't be split at their beginning or end. + multiple_ways: There are too many lines here to split. nothing_to_undo: Nothing to undo. nothing_to_redo: Nothing to redo. just_edited: "You just edited OpenStreetMap!" diff --git a/data/locales.js b/data/locales.js index 1f3617c6c..e12e0fc09 100644 --- a/data/locales.js +++ b/data/locales.js @@ -53,12 +53,16 @@ locale.en = { }, "circularize": { "title": "Circularize", - "description": "Make this round.", + "description": { + "line": "Make this line circular.", + "area": "Make this area circular." + }, "key": "O", "annotation": { "line": "Made a line circular.", "area": "Made an area circular." - } + }, + "not_closed": "This can't be made circular because it's not a loop." }, "orthogonalize": { "title": "Orthogonalize", @@ -67,7 +71,8 @@ locale.en = { "annotation": { "line": "Squared the corners of a line.", "area": "Squared the corners of an area." - } + }, + "not_closed": "This can't be made square because it's not a loop." }, "delete": { "title": "Delete", @@ -91,15 +96,18 @@ locale.en = { }, "disconnect": { "title": "Disconnect", - "description": "Disconnect these ways from each other.", + "description": "Disconnect these lines/areas from each other.", "key": "D", - "annotation": "Disconnected ways." + "annotation": "Disconnected lines/areas.", + "not_connected": "There aren't enough lines/areas here to disconnect." }, "merge": { "title": "Merge", "description": "Merge these lines.", "key": "C", - "annotation": "Merged {n} lines." + "annotation": "Merged {n} lines.", + "not_eligible": "These features can't be merged.", + "not_adjacent": "These lines can't be merged because they aren't connected." }, "move": { "title": "Move", @@ -111,7 +119,8 @@ locale.en = { "line": "Moved a line.", "area": "Moved an area.", "multiple": "Moved multiple objects." - } + }, + "incomplete_relation": "This feature can't be moved because it hasn't been fully downloaded." }, "rotate": { "title": "Rotate", @@ -132,7 +141,9 @@ locale.en = { "title": "Split", "description": "Split this into two ways at this point.", "key": "X", - "annotation": "Split a way." + "annotation": "Split a way.", + "not_eligible": "Lines can't be split at their beginning or end.", + "multiple_ways": "There are too many lines here to split." } }, "nothing_to_undo": "Nothing to undo.", diff --git a/js/id/actions/circularize.js b/js/id/actions/circularize.js index dc936d48f..86a6bc489 100644 --- a/js/id/actions/circularize.js +++ b/js/id/actions/circularize.js @@ -58,8 +58,9 @@ iD.actions.Circularize = function(wayId, projection, count) { return graph; }; - action.enabled = function(graph) { - return graph.entity(wayId).isClosed(); + action.disabled = function(graph) { + if (!graph.entity(wayId).isClosed()) + return 'not_closed'; }; return action; diff --git a/js/id/actions/connect.js b/js/id/actions/connect.js index 82764e15f..933201e4f 100644 --- a/js/id/actions/connect.js +++ b/js/id/actions/connect.js @@ -13,7 +13,7 @@ // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java // iD.actions.Connect = function(nodeIds) { - var action = function(graph) { + return function(graph) { var survivor = graph.entity(_.last(nodeIds)); for (var i = 0; i < nodeIds.length - 1; i++) { @@ -37,10 +37,4 @@ iD.actions.Connect = function(nodeIds) { return graph; }; - - action.enabled = function() { - return nodeIds.length > 1; - }; - - return action; }; diff --git a/js/id/actions/disconnect.js b/js/id/actions/disconnect.js index a666a0d3e..b8f48ea2d 100644 --- a/js/id/actions/disconnect.js +++ b/js/id/actions/disconnect.js @@ -12,9 +12,6 @@ // iD.actions.Disconnect = function(nodeId, newNodeId) { var action = function(graph) { - if (!action.enabled(graph)) - return graph; - var node = graph.entity(nodeId); graph.parentWays(node).forEach(function(parent, i) { @@ -40,12 +37,14 @@ iD.actions.Disconnect = function(nodeId, newNodeId) { return graph; }; - action.enabled = function(graph) { + action.disabled = function(graph) { var parentWays = graph.parentWays(graph.entity(nodeId)); - return parentWays.length >= 2 || - (parentWays.length == 1 && parentWays[0].nodes.filter(function(d) { - return d === nodeId; - }).length >= 2); + if (parentWays.length >= 2) + return; + if (parentWays.length === 0) + return 'not_connected'; + if (parentWays[0].nodes.filter(function(d) { return d === nodeId; }).length < 2) + return 'not_connected'; }; return action; diff --git a/js/id/actions/join.js b/js/id/actions/join.js index d3b353dc5..1719a08b9 100644 --- a/js/id/actions/join.js +++ b/js/id/actions/join.js @@ -57,19 +57,20 @@ iD.actions.Join = function(ids) { return graph; }; - action.enabled = function(graph) { + action.disabled = function(graph) { var geometries = groupEntitiesByGeometry(graph); if (ids.length !== 2 || ids.length !== geometries.line.length) - return false; + return 'not_eligible'; var a = graph.entity(idA), b = graph.entity(idB); - return a.first() === b.first() || - a.first() === b.last() || - a.last() === b.first() || - a.last() === b.last(); + if (a.first() !== b.first() && + a.first() !== b.last() && + a.last() !== b.first() && + a.last() !== b.last()) + return 'not_adjacent'; }; return action; diff --git a/js/id/actions/merge.js b/js/id/actions/merge.js index abe6b2705..8d0880c15 100644 --- a/js/id/actions/merge.js +++ b/js/id/actions/merge.js @@ -25,11 +25,12 @@ iD.actions.Merge = function(ids) { return graph; }; - action.enabled = function(graph) { + action.disabled = function(graph) { var geometries = groupEntitiesByGeometry(graph); - return geometries.point.length > 0 && - (geometries.area.length + geometries.line.length) === 1 && - geometries.relation.length === 0; + if (geometries.point.length === 0 || + (geometries.area.length + geometries.line.length) !== 1 || + geometries.relation.length !== 0) + return 'not_eligible'; }; return action; diff --git a/js/id/actions/move.js b/js/id/actions/move.js index db6078c3a..6642368a1 100644 --- a/js/id/actions/move.js +++ b/js/id/actions/move.js @@ -29,11 +29,14 @@ iD.actions.Move = function(ids, delta, projection) { return graph; }; - action.enabled = function(graph) { - return _.every(ids, function(id) { + action.disabled = function(graph) { + function incompleteRelation(id) { var entity = graph.entity(id); - return entity.type !== 'relation' || entity.isComplete(graph); - }); + return entity.type === 'relation' && !entity.isComplete(graph); + } + + if (_.any(ids, incompleteRelation)) + return 'incomplete_relation'; }; return action; diff --git a/js/id/actions/orthogonalize.js b/js/id/actions/orthogonalize.js index 9b12714f0..54f3814d5 100644 --- a/js/id/actions/orthogonalize.js +++ b/js/id/actions/orthogonalize.js @@ -127,8 +127,9 @@ iD.actions.Orthogonalize = function(wayId, projection) { } }; - action.enabled = function(graph) { - return graph.entity(wayId).isClosed(); + action.disabled = function(graph) { + if (!graph.entity(wayId).isClosed()) + return 'not_closed'; }; return action; diff --git a/js/id/actions/split.js b/js/id/actions/split.js index cf5d56f84..e9ebc2a6e 100644 --- a/js/id/actions/split.js +++ b/js/id/actions/split.js @@ -94,8 +94,12 @@ iD.actions.Split = function(nodeId, newWayId) { return graph; }; - action.enabled = function(graph) { - return candidateWays(graph).length === 1; + action.disabled = function(graph) { + var candidates = candidateWays(graph); + if (candidates.length === 0) + return 'not_eligible'; + if (candidates.length > 1) + return 'multiple_ways'; }; return action; diff --git a/js/id/modes/select.js b/js/id/modes/select.js index 0838f1d1c..04ee6db7d 100644 --- a/js/id/modes/select.js +++ b/js/id/modes/select.js @@ -65,7 +65,7 @@ iD.modes.Select = function(context, selection, initial) { operations.forEach(function(operation) { operation.keys.forEach(function(key) { keybinding.on(key, function() { - if (operation.enabled()) { + if (!operation.disabled()) { operation(); } }); diff --git a/js/id/operations/circularize.js b/js/id/operations/circularize.js index b0b923420..00f0610f3 100644 --- a/js/id/operations/circularize.js +++ b/js/id/operations/circularize.js @@ -1,9 +1,10 @@ iD.operations.Circularize = function(selection, context) { var entityId = selection[0], + geometry = context.geometry(entityId), action = iD.actions.Circularize(entityId, context.projection); var operation = function() { - var annotation = t('operations.circularize.annotation.' + context.geometry(entityId)); + var annotation = t('operations.circularize.annotation.' + geometry); context.perform(action, annotation); }; @@ -12,14 +13,20 @@ iD.operations.Circularize = function(selection, context) { context.entity(entityId).type === 'way'; }; - operation.enabled = function() { - return action.enabled(context.graph()); + operation.disabled = function() { + return action.disabled(context.graph()); + }; + + operation.tooltip = function() { + var disable = operation.disabled(); + return disable ? + t('operations.circularize.' + disable) : + t('operations.circularize.description.' + geometry); }; operation.id = "circularize"; operation.keys = [t('operations.circularize.key')]; operation.title = t('operations.circularize.title'); - operation.description = t('operations.circularize.description'); return operation; }; diff --git a/js/id/operations/delete.js b/js/id/operations/delete.js index d74c7980b..8d6d9d3d7 100644 --- a/js/id/operations/delete.js +++ b/js/id/operations/delete.js @@ -19,14 +19,17 @@ iD.operations.Delete = function(selection, context) { return true; }; - operation.enabled = function() { - return true; + operation.disabled = function() { + return false; + }; + + operation.tooltip = function() { + return t('operations.delete.description'); }; operation.id = "delete"; operation.keys = [iD.ui.cmd('⌫'), iD.ui.cmd('⌦')]; operation.title = t('operations.delete.title'); - operation.description = t('operations.delete.description'); return operation; }; diff --git a/js/id/operations/disconnect.js b/js/id/operations/disconnect.js index e64653626..ecebac45c 100644 --- a/js/id/operations/disconnect.js +++ b/js/id/operations/disconnect.js @@ -11,14 +11,20 @@ iD.operations.Disconnect = function(selection, context) { context.geometry(entityId) === 'vertex'; }; - operation.enabled = function() { - return action.enabled(context.graph()); + operation.disabled = function() { + return action.disabled(context.graph()); + }; + + operation.tooltip = function() { + var disable = operation.disabled(); + return disable ? + t('operations.disconnect.' + disable) : + t('operations.disconnect.description'); }; operation.id = "disconnect"; operation.keys = [t('operations.disconnect.key')]; operation.title = t('operations.disconnect.title'); - operation.description = t('operations.disconnect.description'); return operation; }; diff --git a/js/id/operations/merge.js b/js/id/operations/merge.js index 5120e7d53..8cea1dcad 100644 --- a/js/id/operations/merge.js +++ b/js/id/operations/merge.js @@ -6,7 +6,7 @@ iD.operations.Merge = function(selection, context) { var annotation = t('operations.merge.annotation', {n: selection.length}), action; - if (join.enabled(context.graph())) { + if (!join.disabled(context.graph())) { action = join; } else { action = merge; @@ -20,15 +20,24 @@ iD.operations.Merge = function(selection, context) { return selection.length >= 2; }; - operation.enabled = function() { - return join.enabled(context.graph()) || - merge.enabled(context.graph()); + operation.disabled = function() { + return join.disabled(context.graph()) && + merge.disabled(context.graph()); + }; + + operation.tooltip = function() { + var j = join.disabled(context.graph()), + m = merge.disabled(context.graph()); + + if (j && m) + return t('operations.merge.' + j); + + return t('operations.merge.description'); }; operation.id = "merge"; operation.keys = [t('operations.merge.key')]; operation.title = t('operations.merge.title'); - operation.description = t('operations.merge.description'); return operation; }; diff --git a/js/id/operations/move.js b/js/id/operations/move.js index 7d3f7143e..d2c892ccc 100644 --- a/js/id/operations/move.js +++ b/js/id/operations/move.js @@ -8,15 +8,21 @@ iD.operations.Move = function(selection, context) { context.entity(selection[0]).type !== 'node'; }; - operation.enabled = function() { + operation.disabled = function() { return iD.actions.Move(selection) - .enabled(context.graph()); + .disabled(context.graph()); + }; + + operation.tooltip = function() { + var disable = operation.disabled(); + return disable ? + t('operations.move.' + disable) : + t('operations.move.description'); }; operation.id = "move"; operation.keys = [t('operations.move.key')]; operation.title = t('operations.move.title'); - operation.description = t('operations.move.description'); return operation; }; diff --git a/js/id/operations/orthogonalize.js b/js/id/operations/orthogonalize.js index 2e5844398..825347693 100644 --- a/js/id/operations/orthogonalize.js +++ b/js/id/operations/orthogonalize.js @@ -13,8 +13,15 @@ iD.operations.Orthogonalize = function(selection, context) { _.uniq(context.entity(entityId).nodes).length > 2; }; - operation.enabled = function() { - return action.enabled(context.graph()); + operation.disabled = function() { + return action.disabled(context.graph()); + }; + + operation.tooltip = function() { + var disable = operation.disabled(); + return disable ? + t('operations.orthogonalize.' + disable) : + t('operations.orthogonalize.description'); }; operation.id = "orthogonalize"; diff --git a/js/id/operations/reverse.js b/js/id/operations/reverse.js index cc341b1f9..3eca2d599 100644 --- a/js/id/operations/reverse.js +++ b/js/id/operations/reverse.js @@ -12,14 +12,17 @@ iD.operations.Reverse = function(selection, context) { context.geometry(entityId) === 'line'; }; - operation.enabled = function() { - return true; + operation.disabled = function() { + return false; + }; + + operation.tooltip = function() { + return t('operations.reverse.description'); }; operation.id = "reverse"; operation.keys = [t('operations.reverse.key')]; operation.title = t('operations.reverse.title'); - operation.description = t('operations.reverse.description'); return operation; }; diff --git a/js/id/operations/rotate.js b/js/id/operations/rotate.js index 8946a8707..c4e53783e 100644 --- a/js/id/operations/rotate.js +++ b/js/id/operations/rotate.js @@ -11,14 +11,17 @@ iD.operations.Rotate = function(selection, context) { context.entity(entityId).geometry() === 'area'; }; - operation.enabled = function() { - return true; + operation.disabled = function() { + return false; + }; + + operation.tooltip = function() { + return t('operations.rotate.description'); }; operation.id = "rotate"; operation.keys = [t('operations.rotate.key')]; operation.title = t('operations.rotate.title'); - operation.description = t('operations.rotate.description'); return operation; }; diff --git a/js/id/operations/split.js b/js/id/operations/split.js index 08a10d8d3..d61ad5450 100644 --- a/js/id/operations/split.js +++ b/js/id/operations/split.js @@ -13,14 +13,20 @@ iD.operations.Split = function(selection, context) { context.geometry(entityId) === 'vertex'; }; - operation.enabled = function() { - return action.enabled(context.graph()); + operation.disabled = function() { + return action.disabled(context.graph()); + }; + + operation.tooltip = function() { + var disable = operation.disabled(); + return disable ? + t('operations.split.' + disable) : + t('operations.split.description'); }; operation.id = "split"; operation.keys = [t('operations.split.key')]; operation.title = t('operations.split.title'); - operation.description = t('operations.split.description'); return operation; }; diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js index 0316dd009..2ac44d868 100644 --- a/js/id/ui/radial_menu.js +++ b/js/id/ui/radial_menu.js @@ -11,6 +11,8 @@ iD.ui.RadialMenu = function(operations) { function click(operation) { d3.event.stopPropagation(); + if (operation.disabled()) + return; operation(); radialMenu.close(); } @@ -49,7 +51,8 @@ iD.ui.RadialMenu = function(operations) { button.append('circle') .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; }) .attr('r', 15) - .classed('disabled', function(d) { return !d.enabled(); }) + .classed('disabled', function(d) { return d.disabled(); }) + .style('pointer-events', 'all') .on('click', click) .on('mouseover', mouseover) .on('mouseout', mouseout); @@ -72,7 +75,7 @@ iD.ui.RadialMenu = function(operations) { .style('left', (r + 25) * Math.sin(angle) + dx + center[0] + 'px') .style('top', (r + 25) * Math.cos(angle) + dy + center[1]+ 'px') .style('display', 'block') - .html(iD.ui.tooltipHtml(d.description, d.keys[0])); + .html(iD.ui.tooltipHtml(d.tooltip(), d.keys[0])); } function mouseout() { diff --git a/test/spec/actions/connect.js b/test/spec/actions/connect.js index 683bae623..00feae517 100644 --- a/test/spec/actions/connect.js +++ b/test/spec/actions/connect.js @@ -1,14 +1,4 @@ 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'}), diff --git a/test/spec/actions/disconnect.js b/test/spec/actions/disconnect.js index 0495e8e74..7048983a4 100644 --- a/test/spec/actions/disconnect.js +++ b/test/spec/actions/disconnect.js @@ -1,12 +1,12 @@ describe("iD.actions.Disconnect", function () { - describe("#enabled", function () { - it("returns false for a node shared by less than two ways", function () { + describe("#disabled", function () { + it("returns 'not_connected' for a node shared by less than two ways", function () { var graph = iD.Graph({'a': iD.Node()}); - expect(iD.actions.Disconnect('a').enabled(graph)).to.equal(false); + expect(iD.actions.Disconnect('a').disabled(graph)).to.equal('not_connected'); }); - it("returns true for a node appearing twice in the same way", function () { + it("returns falsy for a node appearing twice in the same way", function () { // a ---- b // | | // d ---- c @@ -17,10 +17,10 @@ describe("iD.actions.Disconnect", function () { 'd': iD.Node({id: 'd'}), 'w': iD.Way({id: 'w', nodes: ['a', 'b', 'c', 'd', 'a']}) }); - expect(iD.actions.Disconnect('a').enabled(graph)).to.equal(true); + expect(iD.actions.Disconnect('a').disabled(graph)).not.to.be.ok; }); - it("returns true for a node shared by two or more ways", function () { + it("returns falsy for a node shared by two or more ways", function () { // a ---- b ---- c // | // d @@ -33,7 +33,7 @@ describe("iD.actions.Disconnect", function () { '|': iD.Way({id: '|', nodes: ['d', 'b']}) }); - expect(iD.actions.Disconnect('b').enabled(graph)).to.equal(true); + expect(iD.actions.Disconnect('b').disabled(graph)).not.to.be.ok; }); }); diff --git a/test/spec/actions/join.js b/test/spec/actions/join.js index 59589ded3..1dffbdcd6 100644 --- a/test/spec/actions/join.js +++ b/test/spec/actions/join.js @@ -1,6 +1,6 @@ describe("iD.actions.Join", function () { - describe("#enabled", function () { - it("returns true for ways that share an end/start node", function () { + describe("#disabled", function () { + it("returns falsy for ways that share an end/start node", function () { // a --> b ==> c var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), @@ -10,10 +10,10 @@ describe("iD.actions.Join", function () { '=': iD.Way({id: '=', nodes: ['b', 'c']}) }); - expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true; + expect(iD.actions.Join(['-', '=']).disabled(graph)).not.to.be.ok; }); - it("returns true for ways that share a start/end node", function () { + it("returns falsy for ways that share a start/end node", function () { // a <-- b <== c var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), @@ -23,10 +23,10 @@ describe("iD.actions.Join", function () { '=': iD.Way({id: '=', nodes: ['c', 'b']}) }); - expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true; + expect(iD.actions.Join(['-', '=']).disabled(graph)).not.to.be.ok; }); - it("returns true for ways that share a start/start node", function () { + it("returns falsy for ways that share a start/start node", function () { // a <-- b ==> c var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), @@ -36,10 +36,10 @@ describe("iD.actions.Join", function () { '=': iD.Way({id: '=', nodes: ['b', 'c']}) }); - expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true; + expect(iD.actions.Join(['-', '=']).disabled(graph)).not.to.be.ok; }); - it("returns true for ways that share an end/end node", function () { + it("returns falsy for ways that share an end/end node", function () { // a --> b <== c var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), @@ -49,10 +49,18 @@ describe("iD.actions.Join", function () { '=': iD.Way({id: '=', nodes: ['c', 'b']}) }); - expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true; + expect(iD.actions.Join(['-', '=']).disabled(graph)).not.to.be.ok; }); - it("returns false for ways that don't share the necessary nodes", function () { + it("returns 'not_eligible' for non-line geometries", function () { + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}) + }); + + expect(iD.actions.Join(['a']).disabled(graph)).to.equal('not_eligible'); + }); + + it("returns 'not_adjacent' for ways that don't share the necessary nodes", function () { // a -- b -- c // | // d @@ -65,7 +73,7 @@ describe("iD.actions.Join", function () { '=': iD.Way({id: '=', nodes: ['b', 'd']}) }); - expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.false; + expect(iD.actions.Join(['-', '=']).disabled(graph)).to.equal('not_adjacent'); }); }); diff --git a/test/spec/actions/merge.js b/test/spec/actions/merge.js index c9d25600a..0ebc8256a 100644 --- a/test/spec/actions/merge.js +++ b/test/spec/actions/merge.js @@ -8,7 +8,7 @@ describe("iD.actions.Merge", function () { }), action = iD.actions.Merge(['a', 'b', 'w']); - expect(action.enabled(graph)).to.be.true; + expect(action.disabled(graph)).not.to.be.ok; graph = action(graph); @@ -27,7 +27,7 @@ describe("iD.actions.Merge", function () { }), action = iD.actions.Merge(['a', 'b', 'w']); - expect(action.enabled(graph)).to.be.true; + expect(action.disabled(graph)).not.to.be.ok; graph = action(graph); diff --git a/test/spec/actions/move.js b/test/spec/actions/move.js index 1e64c58e0..665b906a9 100644 --- a/test/spec/actions/move.js +++ b/test/spec/actions/move.js @@ -1,25 +1,25 @@ describe("iD.actions.Move", function() { - describe("#enabled", function() { - it("returns true by default", function() { + describe("#disabled", function() { + it("returns falsy 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; + expect(action.disabled(graph)).not.to.be.ok; }); - it("returns false for an incomplete relation", function() { + it("returns 'incomplete_relation' 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; + expect(action.disabled(graph)).to.equal('incomplete_relation'); }); - it("returns true for a complete relation", function() { + it("returns falsy 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; + expect(action.disabled(graph)).not.to.be.ok; }); }); diff --git a/test/spec/actions/split.js b/test/spec/actions/split.js index 2e829fc93..11e2b4a6e 100644 --- a/test/spec/actions/split.js +++ b/test/spec/actions/split.js @@ -1,6 +1,6 @@ describe("iD.actions.Split", function () { - describe("#enabled", function () { - it("returns true for a non-end node of a single way", function () { + describe("#disabled", function () { + it("returns falsy for a non-end node of a single way", function () { var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), 'b': iD.Node({id: 'b'}), @@ -8,27 +8,27 @@ describe("iD.actions.Split", function () { '-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}) }); - expect(iD.actions.Split('b').enabled(graph)).to.be.true; + expect(iD.actions.Split('b').disabled(graph)).not.to.be.ok; }); - it("returns false for the first node of a single way", function () { + it("returns 'not_eligible' for the first node of a single way", function () { var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), 'b': iD.Node({id: 'b'}), '-': iD.Way({id: '-', nodes: ['a', 'b']}) }); - expect(iD.actions.Split('a').enabled(graph)).to.be.false; + expect(iD.actions.Split('a').disabled(graph)).to.equal('not_eligible'); }); - it("returns false for the last node of a single way", function () { + it("returns 'not_eligible' for the last node of a single way", function () { var graph = iD.Graph({ 'a': iD.Node({id: 'a'}), 'b': iD.Node({id: 'b'}), '-': iD.Way({id: '-', nodes: ['a', 'b']}) }); - expect(iD.actions.Split('b').enabled(graph)).to.be.false; + expect(iD.actions.Split('b').disabled(graph)).to.equal('not_eligible'); }); });