diff --git a/data/core.yaml b/data/core.yaml index 7336fceba..502c40fba 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -307,13 +307,25 @@ en: annotation: create: Added a turn restriction delete: Deleted a turn restriction - detach_node: - title: Detach + extract: + title: Extract key: E - description: Detach this node from these lines/areas. - annotation: Detached a node from parent lines/areas. - restriction: "This node can't be detached because it would damage a \"{relation}\" relation." - connected_to_hidden: This node can't be detached because it is connected to a hidden feature. + description: + vertex: + single: Extract this point from its parent lines/areas. + area: + single: Extract a point from this area. + annotation: + single: Extracted a point. + too_large: + area: + single: A point can't be extracted from this area because not enough of it is currently visible. + restriction: + vertex: + single: "This point can't be extracted because it would damage a \"{relation}\" relation." + connected_to_hidden: + vertex: + single: This point can't be extracted because it is connected to a hidden feature. restriction: controls: distance: Distance @@ -1733,7 +1745,7 @@ en: continue_line: "Continue a line at the selected node" merge: "Combine (merge) selected features" disconnect: "Disconnect features at the selected node" - detach_node: "Detach selected node from parent lines/areas" + extract: "Extract a point from a feature" split: "Split a line into two at the selected node" reverse: "Reverse a line" move: "Move selected features" diff --git a/data/shortcuts.json b/data/shortcuts.json index d043d7fd0..ce189797c 100644 --- a/data/shortcuts.json +++ b/data/shortcuts.json @@ -237,8 +237,8 @@ "text": "shortcuts.editing.operations.disconnect" }, { - "shortcuts": ["operations.detach_node.key"], - "text": "shortcuts.editing.operations.detach_node" + "shortcuts": ["operations.extract.key"], + "text": "shortcuts.editing.operations.extract" }, { "shortcuts": ["operations.split.key"], diff --git a/dist/locales/en.json b/dist/locales/en.json index 9476c2ec8..f5ddb84a9 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -397,13 +397,35 @@ "delete": "Deleted a turn restriction" } }, - "detach_node": { - "title": "Detach", + "extract": { + "title": "Extract", "key": "E", - "description": "Detach this node from these lines/areas.", - "annotation": "Detached a node from parent lines/areas.", - "restriction": "This node can't be detached because it would damage a \"{relation}\" relation.", - "connected_to_hidden": "This node can't be detached because it is connected to a hidden feature." + "description": { + "vertex": { + "single": "Extract this point from its parent lines/areas." + }, + "area": { + "single": "Extract a point from this area." + } + }, + "annotation": { + "single": "Extracted a point." + }, + "too_large": { + "area": { + "single": "A point can't be extracted from this area because not enough of it is currently visible." + } + }, + "restriction": { + "vertex": { + "single": "This point can't be extracted because it would damage a \"{relation}\" relation." + } + }, + "connected_to_hidden": { + "vertex": { + "single": "This point can't be extracted because it is connected to a hidden feature." + } + } } }, "restriction": { @@ -2098,7 +2120,7 @@ "continue_line": "Continue a line at the selected node", "merge": "Combine (merge) selected features", "disconnect": "Disconnect features at the selected node", - "detach_node": "Detach selected node from parent lines/areas", + "extract": "Extract a point from a feature", "split": "Split a line into two at the selected node", "reverse": "Reverse a line", "move": "Move selected features", diff --git a/modules/actions/detach_node.js b/modules/actions/detach_node.js deleted file mode 100644 index 39bcd59fa..000000000 --- a/modules/actions/detach_node.js +++ /dev/null @@ -1,48 +0,0 @@ -import { osmNode } from '../osm'; - - -export function actionDetachNode(nodeID) { - - var action = function(graph) { - var node = graph.entity(nodeID); - - // Create a new node to replace the one we will detach - var replacement = osmNode({ loc: node.loc }); - graph = graph.replace(replacement); - - // Process each way in turn, updating the graph as we go - graph = graph.parentWays(node) - .reduce(function(accGraph, parentWay) { - return accGraph.replace(parentWay.replaceNode(nodeID, replacement.id)); - }, graph); - - // Process any relations too - return graph.parentRelations(node) - .reduce(function(accGraph, parentRel) { - return accGraph.replace(parentRel.replaceMember(node, replacement)); - }, graph); - }; - - - action.disabled = function(graph) { - var node = graph.entity(nodeID); - var parentRels = graph.parentRelations(node); - - for (var i = 0; i < parentRels.length; i++) { - var relation = parentRels[i]; - if (!relation.isValidRestriction()) continue; - - for (var j = 0; j < relation.members.length; j++) { - var m = relation.members[j]; - if (m.id === nodeID && (m.role === 'via' || m.role === 'location_hint')) { - return 'restriction'; - } - } - } - - return false; - }; - - - return action; -} diff --git a/modules/actions/extract.js b/modules/actions/extract.js new file mode 100644 index 000000000..8b23ddf78 --- /dev/null +++ b/modules/actions/extract.js @@ -0,0 +1,117 @@ + +import { geoPath as d3_geoPath } from 'd3-geo'; +import { osmNode } from '../osm'; + +export function actionExtract(entityID, projection) { + + var extractedNodeID; + + var action = function(graph) { + var entity = graph.entity(entityID); + + if (entity.type === 'node') { + return extractFromNode(entity, graph); + } + + return extractFromArea(entity, graph); + }; + + function extractFromNode(node, graph) { + + extractedNodeID = node.id; + + // Create a new node to replace the one we will detach + var replacement = osmNode({ loc: node.loc }); + graph = graph.replace(replacement); + + // Process each way in turn, updating the graph as we go + graph = graph.parentWays(node) + .reduce(function(accGraph, parentWay) { + return accGraph.replace(parentWay.replaceNode(entityID, replacement.id)); + }, graph); + + // Process any relations too + return graph.parentRelations(node) + .reduce(function(accGraph, parentRel) { + return accGraph.replace(parentRel.replaceMember(node, replacement)); + }, graph); + } + + function extractFromArea(entity, graph) { + + var keysToCopyAndRetain = ['source', 'wheelchair']; + var keysToRetain = ['type']; + var buildingKeysToRetain = ['architect', 'building', 'height', 'layer']; + + var centroid = d3_geoPath(projection).centroid(entity.asGeoJSON(graph, true)); + + var isBuilding = entity.tags.building; + + var areaTags = Object.assign({}, entity.tags); // shallow copy + var pointTags = {}; + for (var key in areaTags) { + + if (keysToRetain.indexOf(key) !== -1) { + continue; + } + + if (isBuilding) { + // don't transfer building-related tags + if (buildingKeysToRetain.indexOf(key) !== -1 || + key.match(/^building:.{1,}/) || + key.match(/^roof:.{1,}/)) continue; + } + + // copy the tag from the area to the point + pointTags[key] = areaTags[key]; + + // leave addresses and some other tags so they're on both features + if (keysToCopyAndRetain.indexOf(key) !== -1 || key.match(/^addr:.{1,}/)) { + continue; + } + + // remove the tag from the area + delete areaTags[key]; + } + + if (!isBuilding) { + // ensure that the area keeps the area geometry + areaTags.area = 'yes'; + } + + var replacement = osmNode({ loc: centroid, tags: pointTags }); + graph = graph.replace(replacement); + + extractedNodeID = replacement.id; + + return graph.replace(entity.update({tags: areaTags})); + } + + action.getExtractedNodeID = function() { + return extractedNodeID; + }; + + action.disabled = function(graph) { + var entity = graph.entity(entityID); + + if (entity.type === 'node') { + var parentRels = graph.parentRelations(entity); + for (var i = 0; i < parentRels.length; i++) { + var relation = parentRels[i]; + if (!relation.isValidRestriction()) continue; + + for (var j = 0; j < relation.members.length; j++) { + var m = relation.members[j]; + if (m.id === entityID && (m.role === 'via' || m.role === 'location_hint')) { + return 'restriction'; + } + } + } + } + + return false; + }; + + + return action; +} diff --git a/modules/actions/index.js b/modules/actions/index.js index daf3e1a0e..b56fbbb09 100644 --- a/modules/actions/index.js +++ b/modules/actions/index.js @@ -15,6 +15,7 @@ export { actionDeleteRelation } from './delete_relation'; export { actionDeleteWay } from './delete_way'; export { actionDiscardTags } from './discard_tags'; export { actionDisconnect } from './disconnect'; +export { actionExtract } from './extract'; export { actionJoin } from './join'; export { actionMerge } from './merge'; export { actionMergeNodes } from './merge_nodes'; @@ -33,5 +34,4 @@ export { actionSplit } from './split'; export { actionStraighten } from './straighten'; export { actionUnrestrictTurn } from './unrestrict_turn'; export { actionReflect } from './reflect.js'; -export { actionDetachNode } from './detach_node'; export { actionUpgradeTags } from './upgrade_tags'; diff --git a/modules/operations/detach_node.js b/modules/operations/detach_node.js deleted file mode 100644 index 5b03e731d..000000000 --- a/modules/operations/detach_node.js +++ /dev/null @@ -1,83 +0,0 @@ -import { actionDetachNode, actionMoveNode } from '../actions'; -import { behaviorOperation } from '../behavior'; -import { modeMove } from '../modes'; -import { t } from '../util/locale'; - - -export function operationDetachNode(selectedIDs, context) { - var nodeID = selectedIDs.length && selectedIDs[0]; - var action = actionDetachNode(nodeID); - - var operation = function () { - context.perform(action); // do the detach - - var mouse = context.map().mouseCoordinates(); - if (mouse.some(isNaN)) { - enterMoveMode(); - - } else { - // move detached node to the mouse location (transitioned) - context.perform(actionMoveNode(nodeID, mouse)); - - // after transition completes, put at final mouse location and enter move mode. - window.setTimeout(function() { - mouse = context.map().mouseCoordinates(); - context.replace(actionMoveNode(nodeID, mouse)); - enterMoveMode(); - }, 150); - } - - function enterMoveMode() { - var baseGraph = context.graph(); - context.enter(modeMove(context, [nodeID], baseGraph)); - } - }; - - - operation.available = function () { - if (selectedIDs.length !== 1) return false; - - var graph = context.graph(); - var entity = graph.hasEntity(nodeID); - if (!entity) return false; - - return entity.type === 'node' && - entity.hasInterestingTags() && - graph.parentWays(entity).length > 0; - }; - - - operation.disabled = function () { - var reason; - if (selectedIDs.some(context.hasHiddenConnections)) { - reason = 'connected_to_hidden'; - } - return action.disabled(context.graph()) || reason; - }; - - - operation.tooltip = function () { - var disableReason = operation.disabled(); - if (disableReason) { - return t('operations.detach_node.' + disableReason, - { relation: context.presets().item('type/restriction').name() }); - } else { - return t('operations.detach_node.description'); - } - }; - - - operation.annotation = function () { - return t('operations.detach_node.annotation'); - }; - - - operation.id = 'detach-node'; - operation.keys = [t('operations.detach_node.key')]; - operation.title = t('operations.detach_node.title'); - operation.behavior = behaviorOperation(context).which(operation); - - - return operation; -} - diff --git a/modules/operations/extract.js b/modules/operations/extract.js new file mode 100644 index 000000000..b5d819674 --- /dev/null +++ b/modules/operations/extract.js @@ -0,0 +1,96 @@ +import { actionExtract, actionMoveNode } from '../actions'; +import { behaviorOperation } from '../behavior'; +import { modeMove } from '../modes'; +import { t } from '../util/locale'; + + +export function operationExtract(selectedIDs, context) { + var entityID = selectedIDs.length && selectedIDs[0]; + var action = actionExtract(entityID, context.projection); + + var geometry = entityID && context.geometry(entityID); + var extent = geometry === 'area' && context.entity(entityID).extent(context.graph()); + + var operation = function () { + context.perform(action); // do the extract + + var extractedNodeID = action.getExtractedNodeID(); + + var mouse = context.map().mouseCoordinates(); + if (mouse.some(isNaN)) { + enterMoveMode(); + + } else { + // move detached node to the mouse location (transitioned) + context.perform(actionMoveNode(extractedNodeID, mouse)); + + // after transition completes, put at final mouse location and enter move mode. + window.setTimeout(function() { + mouse = context.map().mouseCoordinates(); + context.replace(actionMoveNode(extractedNodeID, mouse)); + enterMoveMode(); + }, 150); + } + + function enterMoveMode() { + var baseGraph = context.graph(); + context.enter(modeMove(context, [extractedNodeID], baseGraph)); + } + }; + + + operation.available = function () { + if (selectedIDs.length !== 1) return false; + + var graph = context.graph(); + var entity = graph.hasEntity(entityID); + if (!entity) return false; + + if (!entity.hasInterestingTags()) return false; + + if (geometry === 'area') { + var preset = context.presets().match(entity, graph); + return preset.geometry.indexOf('point') !== -1; + } + + return entity.type === 'node' && graph.parentWays(entity).length > 0; + }; + + + operation.disabled = function () { + var reason; + if (geometry === 'vertex' && selectedIDs.some(context.hasHiddenConnections)) { + reason = 'connected_to_hidden'; + } + if (extent && extent.area() && extent.percentContainedIn(context.extent()) < 0.8) { + reason = 'too_large'; + } + + return action.disabled(context.graph()) || reason; + }; + + + operation.tooltip = function () { + var disableReason = operation.disabled(); + if (disableReason) { + return t('operations.extract.' + disableReason + '.' + geometry + '.single', + { relation: context.presets().item('type/restriction').name() }); + } else { + return t('operations.extract.description.' + geometry + '.single'); + } + }; + + + operation.annotation = function () { + return t('operations.extract.annotation.single'); + }; + + + operation.id = 'extract'; + operation.keys = [t('operations.extract.key')]; + operation.title = t('operations.extract.title'); + operation.behavior = behaviorOperation(context).which(operation); + + + return operation; +} diff --git a/modules/operations/index.js b/modules/operations/index.js index d5724aa28..77be52df1 100644 --- a/modules/operations/index.js +++ b/modules/operations/index.js @@ -3,6 +3,7 @@ export { operationContinue } from './continue'; export { operationDelete } from './delete'; export { operationDisconnect } from './disconnect'; export { operationDowngrade } from './downgrade'; +export { operationExtract } from './extract'; export { operationMerge } from './merge'; export { operationMove } from './move'; export { operationOrthogonalize } from './orthogonalize'; @@ -11,4 +12,3 @@ export { operationReverse } from './reverse'; export { operationRotate } from './rotate'; export { operationSplit } from './split'; export { operationStraighten } from './straighten'; -export { operationDetachNode } from './detach_node'; diff --git a/svg/iD-sprite/operations/operation-detach-node.svg b/svg/iD-sprite/operations/operation-extract.svg similarity index 100% rename from svg/iD-sprite/operations/operation-detach-node.svg rename to svg/iD-sprite/operations/operation-extract.svg diff --git a/test/index.html b/test/index.html index 4cb1e94fa..b83deba23 100644 --- a/test/index.html +++ b/test/index.html @@ -62,7 +62,7 @@ - + @@ -86,7 +86,7 @@ - + diff --git a/test/spec/actions/detach_node.js b/test/spec/actions/extract.js similarity index 91% rename from test/spec/actions/detach_node.js rename to test/spec/actions/extract.js index 1bac58e44..e11547501 100644 --- a/test/spec/actions/detach_node.js +++ b/test/spec/actions/extract.js @@ -1,4 +1,4 @@ -describe('iD.actionDetachNode', function () { +describe('iD.actionExtract', function () { var tags = { 'name': 'test' }; function createTargetNode(id, lonlat) { @@ -29,7 +29,7 @@ describe('iD.actionDetachNode', function () { it('does not change length of way', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // Confirm that the way still has 4 nodes var target = assertionGraph.entity('-'); @@ -38,7 +38,7 @@ describe('iD.actionDetachNode', function () { it('does not change order of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // Confirm that the way is ordered correctly var target = assertionGraph.entity('-'); @@ -53,7 +53,7 @@ describe('iD.actionDetachNode', function () { it('does not change location of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // Confirm that the nodes have not moved, including the replacement node var nodes = assertionGraph.entity('-').nodes; @@ -65,7 +65,7 @@ describe('iD.actionDetachNode', function () { it('does replace target node', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); var nodes = assertionGraph.entity('-').nodes; // Confirm that the target is no longer "a" @@ -76,7 +76,7 @@ describe('iD.actionDetachNode', function () { it('does detach target node', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // confirm that a still exists var targetNode = assertionGraph.entity('a'); @@ -99,7 +99,7 @@ describe('iD.actionDetachNode', function () { it('does not change length of way', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Confirm that the way still has 4 nodes var target = assertionGraph.entity('-'); @@ -108,7 +108,7 @@ describe('iD.actionDetachNode', function () { it('does not change order of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Confirm that the way is ordered correctly var target = assertionGraph.entity('-'); @@ -123,7 +123,7 @@ describe('iD.actionDetachNode', function () { it('does not change location of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Confirm that the nodes have not moved, including the replacement node var nodes = assertionGraph.entity('-').nodes; @@ -135,7 +135,7 @@ describe('iD.actionDetachNode', function () { it('does replace target node', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); var nodes = assertionGraph.entity('-').nodes; // Confirm that the target is no longer "a" @@ -146,7 +146,7 @@ describe('iD.actionDetachNode', function () { it('does detach target node', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // confirm that a still exists var targetNode = assertionGraph.entity('b'); @@ -188,7 +188,7 @@ describe('iD.actionDetachNode', function () { it('does not change length of way', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // Confirm that the way still has 5 nodes var target = assertionGraph.entity('-'); @@ -197,7 +197,7 @@ describe('iD.actionDetachNode', function () { it('does not change order of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // Confirm that the way is ordered correctly var target = assertionGraph.entity('-'); @@ -214,7 +214,7 @@ describe('iD.actionDetachNode', function () { it('does not change location of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // Confirm that the nodes have not moved, including the replacement node var nodes = assertionGraph.entity('-').nodes; @@ -227,7 +227,7 @@ describe('iD.actionDetachNode', function () { it('does replace target node', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); var nodes = assertionGraph.entity('-').nodes; // Confirm that the target is no longer "a" @@ -240,7 +240,7 @@ describe('iD.actionDetachNode', function () { it('does detach target node', function () { // Act - var assertionGraph = iD.actionDetachNode('a')(graph); + var assertionGraph = iD.actionExtract('a')(graph); // confirm that a still exists var targetNode = assertionGraph.entity('a'); @@ -263,7 +263,7 @@ describe('iD.actionDetachNode', function () { it('does not change length of way', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Confirm that the way still has 5 nodes var target = assertionGraph.entity('-'); @@ -272,7 +272,7 @@ describe('iD.actionDetachNode', function () { it('does not change order of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Confirm that the way is ordered correctly var target = assertionGraph.entity('-'); @@ -288,7 +288,7 @@ describe('iD.actionDetachNode', function () { it('does not change location of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Confirm that the nodes have not moved, including the replacement node var nodes = assertionGraph.entity('-').nodes; @@ -301,7 +301,7 @@ describe('iD.actionDetachNode', function () { it('does replace target node', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); var nodes = assertionGraph.entity('-').nodes; // Confirm that the target is no longer "a" @@ -312,7 +312,7 @@ describe('iD.actionDetachNode', function () { it('does detach target node', function () { // Act - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // confirm that a still exists var targetNode = assertionGraph.entity('b'); @@ -354,7 +354,7 @@ describe('iD.actionDetachNode', function () { it('does not change length of ways', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm that the way still has 4 nodes var target = assertionGraph.entity('-'); @@ -366,7 +366,7 @@ describe('iD.actionDetachNode', function () { it('does not change order of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm that the way is ordered correctly var target = assertionGraph.entity('-'); @@ -385,7 +385,7 @@ describe('iD.actionDetachNode', function () { it('does not change location of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm that the nodes have not moved, including the replacement node var nodes = assertionGraph.entity('-').nodes; @@ -402,14 +402,14 @@ describe('iD.actionDetachNode', function () { it('uses same replacement node at intersection', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm both ways have the same replacement node expect(assertionGraph.entity('-').nodes[2]).to.eql(assertionGraph.entity('=').nodes[0]); }); it('does replace target node', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); var nodes = assertionGraph.entity('-').nodes; // Confirm that the target is no longer "c" @@ -422,7 +422,7 @@ describe('iD.actionDetachNode', function () { it('does detach target node', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // confirm that a still exists var targetNode = assertionGraph.entity('c'); @@ -464,7 +464,7 @@ describe('iD.actionDetachNode', function () { it('does not change length of ways', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm that the way still has 5 nodes var target = assertionGraph.entity('-'); @@ -476,7 +476,7 @@ describe('iD.actionDetachNode', function () { it('does not change order of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm that the way is ordered correctly var target = assertionGraph.entity('-'); @@ -499,7 +499,7 @@ describe('iD.actionDetachNode', function () { it('does not change location of nodes', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm that the nodes have not moved, including the replacement node var nodes = assertionGraph.entity('-').nodes; @@ -518,14 +518,14 @@ describe('iD.actionDetachNode', function () { it('uses same replacement node at intersection', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // Confirm both ways have the same replacement node expect(assertionGraph.entity('-').nodes[2]).to.eql(assertionGraph.entity('=').nodes[0]); }); it('does replace target node', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); var nodes = assertionGraph.entity('-').nodes; // Confirm that the target is no longer "c" @@ -539,7 +539,7 @@ describe('iD.actionDetachNode', function () { it('does detach target node', function () { // Act - var assertionGraph = iD.actionDetachNode('c')(graph); + var assertionGraph = iD.actionExtract('c')(graph); // confirm that a still exists var targetNode = assertionGraph.entity('c'); @@ -580,7 +580,7 @@ describe('iD.actionDetachNode', function () { }); it('detached node not a member of relation', function () { - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); var targetNode = assertionGraph.entity('b'); // Confirm is not a member of the relation @@ -588,7 +588,7 @@ describe('iD.actionDetachNode', function () { }); it('new node is a member of relation', function () { - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Find the new node var targetWay = assertionGraph.entity('-'); @@ -603,7 +603,7 @@ describe('iD.actionDetachNode', function () { }); it('Relation membership has the same properties', function () { - var assertionGraph = iD.actionDetachNode('b')(graph); + var assertionGraph = iD.actionExtract('b')(graph); // Find the new node var targetWay = assertionGraph.entity('-'); diff --git a/test/spec/operations/detach_node.js b/test/spec/operations/extract.js similarity index 83% rename from test/spec/operations/detach_node.js rename to test/spec/operations/extract.js index e79bf8349..4dfefa54e 100644 --- a/test/spec/operations/detach_node.js +++ b/test/spec/operations/extract.js @@ -1,4 +1,4 @@ -describe('iD.operationDetachNode', function () { +describe('iD.operationExtract', function () { var fakeContext; var graph; @@ -6,6 +6,7 @@ describe('iD.operationDetachNode', function () { fakeContext = {}; fakeContext.graph = function () { return graph; }; fakeContext.hasHiddenConnections = function () { return false; }; + fakeContext.geometry = function () { return 'vertex'; }; var fakeTags = { 'name': 'fake' }; @@ -37,52 +38,52 @@ describe('iD.operationDetachNode', function () { }); it('is not available for no selected ids', function () { - var result = iD.operationDetachNode([], fakeContext).available(); + var result = iD.operationExtract([], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for two selected ids', function () { - var result = iD.operationDetachNode(['a', 'b'], fakeContext).available(); + var result = iD.operationExtract(['a', 'b'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for unknown selected id', function () { - var result = iD.operationDetachNode(['z'], fakeContext).available(); + var result = iD.operationExtract(['z'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for selected way', function () { - var result = iD.operationDetachNode(['x'], fakeContext).available(); + var result = iD.operationExtract(['x'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for selected node with tags, no parent way', function () { - var result = iD.operationDetachNode(['e'], fakeContext).available(); + var result = iD.operationExtract(['e'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for selected node with no tags, no parent way', function () { - var result = iD.operationDetachNode(['f'], fakeContext).available(); + var result = iD.operationExtract(['f'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for selected node with no tags, parent way', function () { - var result = iD.operationDetachNode(['c'], fakeContext).available(); + var result = iD.operationExtract(['c'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is not available for selected node with no tags, two parent ways', function () { - var result = iD.operationDetachNode(['d'], fakeContext).available(); + var result = iD.operationExtract(['d'], fakeContext).available(); expect(result).to.be.not.ok; }); it('is available for selected node with tags, parent way', function () { - var result = iD.operationDetachNode(['a'], fakeContext).available(); + var result = iD.operationExtract(['a'], fakeContext).available(); expect(result).to.be.ok; }); it('is available for selected node with tags, two parent ways', function () { - var result = iD.operationDetachNode(['b'], fakeContext).available(); + var result = iD.operationExtract(['b'], fakeContext).available(); expect(result).to.be.ok; }); }); @@ -96,7 +97,7 @@ describe('iD.operationDetachNode', function () { iD.osmNode(createFakeNode('c', false)), iD.osmWay({ id: 'x', nodes: ['a', 'b', 'c'] }) ]); - var result = iD.operationDetachNode(['b'], fakeContext).disabled(); + var result = iD.operationExtract(['b'], fakeContext).disabled(); expect(result).to.be.not.ok; }); @@ -108,7 +109,7 @@ describe('iD.operationDetachNode', function () { iD.osmWay({ id: 'x', nodes: ['a', 'b', 'c'] }), iD.osmRelation({ id: 'r', members: [{ id: 'b', role: 'label' }] }) ]); - var result = iD.operationDetachNode(['b'], fakeContext).disabled(); + var result = iD.operationExtract(['b'], fakeContext).disabled(); expect(result).to.be.not.ok; }); @@ -133,7 +134,7 @@ describe('iD.operationDetachNode', function () { ] }) ]); - var result = iD.operationDetachNode(['d'], fakeContext).disabled(); + var result = iD.operationExtract(['d'], fakeContext).disabled(); expect(result).to.eql('restriction'); }); @@ -159,7 +160,7 @@ describe('iD.operationDetachNode', function () { ] }) ]); - var result = iD.operationDetachNode(['d'], fakeContext).disabled(); + var result = iD.operationExtract(['d'], fakeContext).disabled(); expect(result).to.eql('restriction'); }); });