Convert "Detach" operation into "Extract" operation that also works on areas (close #6203)

This commit is contained in:
Quincy Morgan
2019-04-22 14:46:01 -07:00
parent e8c5c05b29
commit e04d860f62
13 changed files with 319 additions and 202 deletions
+19 -7
View File
@@ -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"
+2 -2
View File
@@ -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"],
+29 -7
View File
@@ -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",
-48
View File
@@ -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;
}
+117
View File
@@ -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;
}
+1 -1
View File
@@ -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';
-83
View File
@@ -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;
}
+96
View File
@@ -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;
}
+1 -1
View File
@@ -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';

Before

Width:  |  Height:  |  Size: 654 B

After

Width:  |  Height:  |  Size: 654 B

+2 -2
View File
@@ -62,7 +62,7 @@
<script src='spec/actions/straighten.js'></script>
<script src='spec/actions/unrestrict_turn.js'></script>
<script src='spec/actions/reflect.js'></script>
<script src='spec/actions/detach_node.js'></script>
<script src='spec/actions/extract.js'></script>
<script src='spec/actions/upgrade_tags.js'></script>
<script src='spec/behavior/hash.js'></script>
@@ -86,7 +86,7 @@
<script src='spec/modes/add_point.js'></script>
<script src='spec/modes/add_note.js'></script>
<script src='spec/operations/detach_node.js'></script>
<script src='spec/operations/extract.js'></script>
<script src='spec/operations/straighten.js'></script>
<script src='spec/osm/changeset.js'></script>
@@ -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('-');
@@ -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');
});
});