mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-22 00:07:03 +02:00
Merge pull request #2498 from bhousel/copy-paste
Copy paste map features with Cmd-C, Cmd-V
This commit is contained in:
@@ -147,6 +147,7 @@
|
||||
<script src='js/id/actions/change_tags.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
<script src='js/id/actions/connect.js'></script>
|
||||
<script src='js/id/actions/copy_entity.js'></script>
|
||||
<script src='js/id/actions/delete_member.js'></script>
|
||||
<script src='js/id/actions/delete_multiple.js'></script>
|
||||
<script src='js/id/actions/delete_node.js'></script>
|
||||
@@ -170,6 +171,7 @@
|
||||
|
||||
<script src='js/id/behavior.js'></script>
|
||||
<script src='js/id/behavior/add_way.js'></script>
|
||||
<script src='js/id/behavior/copy.js'></script>
|
||||
<script src='js/id/behavior/drag.js'></script>
|
||||
<script src='js/id/behavior/draw.js'></script>
|
||||
<script src='js/id/behavior/draw_way.js'></script>
|
||||
@@ -177,6 +179,7 @@
|
||||
<script src='js/id/behavior/hash.js'></script>
|
||||
<script src='js/id/behavior/hover.js'></script>
|
||||
<script src='js/id/behavior/lasso.js'></script>
|
||||
<script src='js/id/behavior/paste.js'></script>
|
||||
<script src='js/id/behavior/select.js'></script>
|
||||
<script src='js/id/behavior/tail.js'></script>
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
iD.actions.CopyEntity = function(entity, deep) {
|
||||
var newEntities = [];
|
||||
|
||||
var action = function(graph) {
|
||||
newEntities = entity.copy(deep, graph);
|
||||
|
||||
for (var i = 0; i < newEntities.length; i++) {
|
||||
graph = graph.replace(newEntities[i]);
|
||||
}
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.newEntities = function() {
|
||||
return newEntities;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
iD.behavior.Copy = function(context) {
|
||||
var keybinding = d3.keybinding('copy');
|
||||
|
||||
function groupEntities(ids, graph) {
|
||||
var entities = ids.map(function (id) { return graph.entity(id); });
|
||||
return _.extend({relation: [], way: [], node: []},
|
||||
_.groupBy(entities, function(entity) { return entity.type; }));
|
||||
}
|
||||
|
||||
function getDescendants(id, graph, descendants) {
|
||||
var entity = graph.entity(id),
|
||||
i, children;
|
||||
|
||||
descendants = descendants || {};
|
||||
|
||||
if (entity.type === 'relation') {
|
||||
children = _.pluck(entity.members, 'id');
|
||||
} else if (entity.type === 'way') {
|
||||
children = entity.nodes;
|
||||
} else {
|
||||
children = [];
|
||||
}
|
||||
|
||||
for (i = 0; i < children.length; i++) {
|
||||
if (!descendants[children[i]]) {
|
||||
descendants[children[i]] = true;
|
||||
descendants = getDescendants(children[i], graph, descendants);
|
||||
}
|
||||
}
|
||||
|
||||
return descendants;
|
||||
}
|
||||
|
||||
function doCopy() {
|
||||
d3.event.preventDefault();
|
||||
|
||||
var graph = context.graph(),
|
||||
selected = groupEntities(context.selectedIDs(), graph),
|
||||
canCopy = [],
|
||||
skip = {},
|
||||
i, entity;
|
||||
|
||||
for (i = 0; i < selected.relation.length; i++) {
|
||||
entity = selected.relation[i];
|
||||
if (!skip[entity.id] && entity.isComplete()) {
|
||||
canCopy.push(entity.id);
|
||||
skip = getDescendants(entity.id, graph, skip);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < selected.way.length; i++) {
|
||||
entity = selected.way[i];
|
||||
if (!skip[entity.id]) {
|
||||
canCopy.push(entity.id);
|
||||
skip = getDescendants(entity.id, graph, skip);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < selected.node.length; i++) {
|
||||
entity = selected.node[i];
|
||||
if (!skip[entity.id]) {
|
||||
canCopy.push(entity.id);
|
||||
}
|
||||
}
|
||||
|
||||
context.copiedIDs(canCopy);
|
||||
}
|
||||
|
||||
function copy() {
|
||||
keybinding.on(iD.ui.cmd('⌘C'), doCopy);
|
||||
d3.select(document).call(keybinding);
|
||||
return copy;
|
||||
}
|
||||
|
||||
copy.off = function() {
|
||||
d3.select(document).call(keybinding.off);
|
||||
};
|
||||
|
||||
return copy;
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
iD.behavior.Paste = function(context) {
|
||||
var keybinding = d3.keybinding('paste');
|
||||
|
||||
function omitTag(v, k) {
|
||||
return (
|
||||
k === 'phone' ||
|
||||
k === 'fax' ||
|
||||
k === 'email' ||
|
||||
k === 'website' ||
|
||||
k === 'url' ||
|
||||
k === 'note' ||
|
||||
k === 'description' ||
|
||||
k.indexOf('name') !== -1 ||
|
||||
k.indexOf('wiki') === 0 ||
|
||||
k.indexOf('addr:') === 0 ||
|
||||
k.indexOf('contact:') === 0
|
||||
);
|
||||
}
|
||||
|
||||
function doPaste() {
|
||||
d3.event.preventDefault();
|
||||
|
||||
var mouse = context.mouse(),
|
||||
projection = context.projection,
|
||||
viewport = iD.geo.Extent(projection.clipExtent()).polygon();
|
||||
|
||||
if (!iD.geo.pointInPolygon(mouse, viewport)) return;
|
||||
|
||||
var graph = context.graph(),
|
||||
extent = iD.geo.Extent(),
|
||||
oldIDs = context.copiedIDs(),
|
||||
newIDs = [],
|
||||
i, j;
|
||||
|
||||
for (i = 0; i < oldIDs.length; i++) {
|
||||
var oldEntity = graph.entity(oldIDs[i]),
|
||||
action = iD.actions.CopyEntity(oldEntity, true),
|
||||
newEntities;
|
||||
|
||||
extent._extend(oldEntity.extent(graph));
|
||||
context.perform(action);
|
||||
|
||||
// First element in `newEntities` contains the copied Entity,
|
||||
// Subsequent array elements contain any descendants..
|
||||
newEntities = action.newEntities();
|
||||
newIDs.push(newEntities[0].id);
|
||||
|
||||
for (j = 0; j < newEntities.length; j++) {
|
||||
var newEntity = newEntities[j],
|
||||
tags = _.omit(newEntity.tags, omitTag);
|
||||
|
||||
context.perform(iD.actions.ChangeTags(newEntity.id, tags));
|
||||
}
|
||||
}
|
||||
|
||||
// Put pasted objects where mouse pointer is..
|
||||
var center = projection(extent.center()),
|
||||
delta = [ mouse[0] - center[0], mouse[1] - center[1] ];
|
||||
|
||||
context.perform(iD.actions.Move(newIDs, delta, projection));
|
||||
context.enter(iD.modes.Move(context, newIDs));
|
||||
}
|
||||
|
||||
function paste() {
|
||||
keybinding.on(iD.ui.cmd('⌘V'), doPaste);
|
||||
d3.select(document).call(keybinding);
|
||||
return paste;
|
||||
}
|
||||
|
||||
paste.off = function() {
|
||||
d3.select(document).call(keybinding.off);
|
||||
};
|
||||
|
||||
return paste;
|
||||
};
|
||||
+11
-1
@@ -44,7 +44,11 @@ iD.Entity.prototype = {
|
||||
var source = sources[i];
|
||||
for (var prop in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, prop)) {
|
||||
this[prop] = source[prop];
|
||||
if (source[prop] === undefined) {
|
||||
delete this[prop];
|
||||
} else {
|
||||
this[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +69,12 @@ iD.Entity.prototype = {
|
||||
return this;
|
||||
},
|
||||
|
||||
copy: function() {
|
||||
// Returns an array so that we can support deep copying ways and relations.
|
||||
// The first array element will contain this.copy, followed by any descendants.
|
||||
return [iD.Entity(this, {id: undefined, user: undefined, version: undefined})];
|
||||
},
|
||||
|
||||
osmId: function() {
|
||||
return iD.Entity.id.toOSM(this.id);
|
||||
},
|
||||
|
||||
@@ -20,6 +20,34 @@ _.extend(iD.Relation.prototype, {
|
||||
type: 'relation',
|
||||
members: [],
|
||||
|
||||
copy: function(deep, resolver, replacements) {
|
||||
var copy = iD.Entity.prototype.copy.call(this);
|
||||
if (!deep || !resolver || !this.isComplete(resolver)) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
var members = [],
|
||||
i, oldmember, oldid, newid, children;
|
||||
|
||||
replacements = replacements || {};
|
||||
replacements[this.id] = copy[0].id;
|
||||
|
||||
for (i = 0; i < this.members.length; i++) {
|
||||
oldmember = this.members[i];
|
||||
oldid = oldmember.id;
|
||||
newid = replacements[oldid];
|
||||
if (!newid) {
|
||||
children = resolver.entity(oldid).copy(true, resolver, replacements);
|
||||
newid = replacements[oldid] = children[0].id;
|
||||
copy = copy.concat(children);
|
||||
}
|
||||
members.push({id: newid, type: oldmember.type, role: oldmember.role});
|
||||
}
|
||||
|
||||
copy[0] = copy[0].update({members: members});
|
||||
return copy;
|
||||
},
|
||||
|
||||
extent: function(resolver, memo) {
|
||||
return resolver.transient(this, 'extent', function() {
|
||||
if (memo && memo[this.id]) return iD.geo.Extent();
|
||||
|
||||
@@ -12,6 +12,32 @@ _.extend(iD.Way.prototype, {
|
||||
type: 'way',
|
||||
nodes: [],
|
||||
|
||||
copy: function(deep, resolver) {
|
||||
var copy = iD.Entity.prototype.copy.call(this);
|
||||
|
||||
if (!deep || !resolver) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
var nodes = [],
|
||||
replacements = {},
|
||||
i, oldid, newid, child;
|
||||
|
||||
for (i = 0; i < this.nodes.length; i++) {
|
||||
oldid = this.nodes[i];
|
||||
newid = replacements[oldid];
|
||||
if (!newid) {
|
||||
child = resolver.entity(oldid).copy();
|
||||
newid = replacements[oldid] = child[0].id;
|
||||
copy = copy.concat(child);
|
||||
}
|
||||
nodes.push(newid);
|
||||
}
|
||||
|
||||
copy[0] = copy[0].update({nodes: nodes});
|
||||
return copy;
|
||||
},
|
||||
|
||||
extent: function(resolver) {
|
||||
return resolver.transient(this, 'extent', function() {
|
||||
var extent = iD.geo.Extent();
|
||||
|
||||
@@ -204,6 +204,14 @@ window.iD = function () {
|
||||
context.surface().call(behavior.off);
|
||||
};
|
||||
|
||||
/* Copy/Paste */
|
||||
var copiedIDs = [];
|
||||
context.copiedIDs = function(_) {
|
||||
if (!arguments.length) return copiedIDs;
|
||||
copiedIDs = _;
|
||||
return context;
|
||||
};
|
||||
|
||||
/* Projection */
|
||||
context.projection = iD.geo.RawMercator();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ iD.modes.Browse = function(context) {
|
||||
}, sidebar;
|
||||
|
||||
var behaviors = [
|
||||
iD.behavior.Paste(context),
|
||||
iD.behavior.Hover(context)
|
||||
.on('hover', context.ui().sidebar.hover),
|
||||
iD.behavior.Select(context),
|
||||
|
||||
@@ -7,6 +7,8 @@ iD.modes.Select = function(context, selectedIDs) {
|
||||
var keybinding = d3.keybinding('select'),
|
||||
timeout = null,
|
||||
behaviors = [
|
||||
iD.behavior.Copy(context),
|
||||
iD.behavior.Paste(context),
|
||||
iD.behavior.Hover(context),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.Lasso(context),
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
<script src='../js/id/actions/change_tags.js'></script>
|
||||
<script src='../js/id/actions/circularize.js'></script>
|
||||
<script src='../js/id/actions/connect.js'></script>
|
||||
<script src='../js/id/actions/copy_entity.js'></script>
|
||||
<script src='../js/id/actions/delete_member.js'></script>
|
||||
<script src='../js/id/actions/delete_multiple.js'></script>
|
||||
<script src='../js/id/actions/delete_node.js'></script>
|
||||
@@ -149,6 +150,7 @@
|
||||
|
||||
<script src='../js/id/behavior.js'></script>
|
||||
<script src='../js/id/behavior/add_way.js'></script>
|
||||
<script src='../js/id/behavior/copy.js'></script>
|
||||
<script src='../js/id/behavior/drag.js'></script>
|
||||
<script src='../js/id/behavior/draw.js'></script>
|
||||
<script src='../js/id/behavior/draw_way.js'></script>
|
||||
@@ -156,6 +158,7 @@
|
||||
<script src='../js/id/behavior/hash.js'></script>
|
||||
<script src='../js/id/behavior/hover.js'></script>
|
||||
<script src='../js/id/behavior/lasso.js'></script>
|
||||
<script src='../js/id/behavior/paste.js'></script>
|
||||
<script src='../js/id/behavior/select.js'></script>
|
||||
<script src='../js/id/behavior/tail.js'></script>
|
||||
|
||||
@@ -225,6 +228,7 @@
|
||||
<script src='spec/actions/orthogonalize.js'></script>
|
||||
<script src='spec/actions/straighten.js'></script>
|
||||
<script src='spec/actions/connect.js'></script>
|
||||
<script src="spec/actions/copy_entity.js"></script>
|
||||
<script src='spec/actions/delete_member.js'></script>
|
||||
<script src="spec/actions/delete_multiple.js"></script>
|
||||
<script src="spec/actions/delete_node.js"></script>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<script src="spec/actions/change_tags.js"></script>
|
||||
<script src='spec/actions/circularize.js'></script>
|
||||
<script src='spec/actions/connect.js'></script>
|
||||
<script src="spec/actions/copy_entity.js"></script>
|
||||
<script src='spec/actions/delete_member.js'></script>
|
||||
<script src="spec/actions/delete_multiple.js"></script>
|
||||
<script src="spec/actions/delete_node.js"></script>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
describe("iD.actions.CopyEntity", function () {
|
||||
it("copies a Node and adds it to the graph", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
base = iD.Graph([a]),
|
||||
head = iD.actions.CopyEntity(a)(base),
|
||||
diff = iD.Difference(base, head),
|
||||
created = diff.created();
|
||||
|
||||
expect(head.hasEntity('a')).to.be.ok;
|
||||
expect(created).to.have.length(1);
|
||||
expect(created[0]).to.be.an.instanceof(iD.Node);
|
||||
});
|
||||
|
||||
it("shallow copies a Way and adds it to the graph", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
w = iD.Way({id: 'w', nodes: ['a', 'b']}),
|
||||
base = iD.Graph([a, b, w]),
|
||||
head = iD.actions.CopyEntity(w)(base),
|
||||
diff = iD.Difference(base, head),
|
||||
created = diff.created();
|
||||
|
||||
expect(head.hasEntity('w')).to.be.ok;
|
||||
expect(created).to.have.length(1);
|
||||
expect(created[0]).to.be.an.instanceof(iD.Way);
|
||||
});
|
||||
|
||||
it("deep copies a Way and child Nodes and adds them to the graph", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
w = iD.Way({id: 'w', nodes: ['a', 'b']}),
|
||||
base = iD.Graph([a, b, w]),
|
||||
head = iD.actions.CopyEntity(w, true)(base),
|
||||
diff = iD.Difference(base, head),
|
||||
created = diff.created();
|
||||
|
||||
expect(head.hasEntity('w')).to.be.ok;
|
||||
expect(created).to.have.length(3);
|
||||
expect(created[0]).to.be.an.instanceof(iD.Way);
|
||||
expect(created[1]).to.be.an.instanceof(iD.Node);
|
||||
expect(created[2]).to.be.an.instanceof(iD.Node);
|
||||
});
|
||||
|
||||
it("shallow copies a Relation and adds it to the graph", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
w = iD.Way({id: 'w', nodes: ['a', 'b']}),
|
||||
r = iD.Relation({id: 'r', members: [{id: 'w'}]}),
|
||||
base = iD.Graph([a, b, w, r]),
|
||||
head = iD.actions.CopyEntity(r)(base),
|
||||
diff = iD.Difference(base, head),
|
||||
created = diff.created();
|
||||
|
||||
expect(head.hasEntity('r')).to.be.ok;
|
||||
expect(created).to.have.length(1);
|
||||
expect(created[0]).to.be.an.instanceof(iD.Relation);
|
||||
});
|
||||
|
||||
it("deep copies a Relation, member Ways, and child Nodes and adds them to the graph", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
w = iD.Way({id: 'w', nodes: ['a', 'b']}),
|
||||
r = iD.Relation({id: 'r', members: [{id: 'w'}]}),
|
||||
base = iD.Graph([a, b, w, r]),
|
||||
head = iD.actions.CopyEntity(r, true)(base),
|
||||
diff = iD.Difference(base, head),
|
||||
created = diff.created();
|
||||
|
||||
expect(head.hasEntity('r')).to.be.ok;
|
||||
expect(created).to.have.length(4);
|
||||
expect(created[0]).to.be.an.instanceof(iD.Relation);
|
||||
expect(created[1]).to.be.an.instanceof(iD.Way);
|
||||
expect(created[2]).to.be.an.instanceof(iD.Node);
|
||||
expect(created[3]).to.be.an.instanceof(iD.Node);
|
||||
});
|
||||
});
|
||||
@@ -36,6 +36,30 @@ describe('iD.Entity', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#copy", function () {
|
||||
it("returns a new Entity", function () {
|
||||
var a = iD.Entity(),
|
||||
result = a.copy();
|
||||
expect(result).to.have.length(1);
|
||||
expect(result[0]).to.be.an.instanceof(iD.Entity);
|
||||
expect(a).not.to.equal(result[0]);
|
||||
});
|
||||
|
||||
it("resets 'id', 'user', and 'version' properties", function () {
|
||||
var a = iD.Entity({id: 'n1234', version: 10, user: 'bot-mode'}),
|
||||
b = a.copy()[0];
|
||||
expect(b.isNew()).to.be.ok;
|
||||
expect(b.version).to.be.undefined;
|
||||
expect(b.user).to.be.undefined;
|
||||
});
|
||||
|
||||
it("copies tags", function () {
|
||||
var a = iD.Entity({id: 'n1234', version: 10, user: 'test', tags: {foo: 'foo'}}),
|
||||
b = a.copy()[0];
|
||||
expect(b.tags).to.deep.equal(a.tags);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#update", function () {
|
||||
it("returns a new Entity", function () {
|
||||
var a = iD.Entity(),
|
||||
|
||||
@@ -26,6 +26,101 @@ describe('iD.Relation', function () {
|
||||
expect(iD.Relation({tags: {foo: 'bar'}}).tags).to.eql({foo: 'bar'});
|
||||
});
|
||||
|
||||
describe("#copy", function () {
|
||||
it("returns a new Relation", function () {
|
||||
var r1 = iD.Relation({id: 'r1'}),
|
||||
result = r1.copy(),
|
||||
r2 = result[0];
|
||||
|
||||
expect(result).to.have.length(1);
|
||||
expect(r2).to.be.an.instanceof(iD.Relation);
|
||||
expect(r1).not.to.equal(r2);
|
||||
});
|
||||
|
||||
it("keeps same members when deep = false", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
c = iD.Node({id: 'c'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['a','b','c','a']}),
|
||||
r1 = iD.Relation({id: 'r1', members: [{id: 'w1', role: 'outer'}]}),
|
||||
graph = iD.Graph([a, b, c, w1, r1]),
|
||||
result = r1.copy(),
|
||||
r1_copy = result[0];
|
||||
|
||||
expect(result).to.have.length(1);
|
||||
expect(r1.members).to.deep.equal(r1_copy.members);
|
||||
});
|
||||
|
||||
it("makes new members when deep = true", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
c = iD.Node({id: 'c'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['a','b','c','a']}),
|
||||
r1 = iD.Relation({id: 'r1', members: [{id: 'w1', role: 'outer'}]}),
|
||||
graph = iD.Graph([a, b, c, w1, r1]),
|
||||
result = r1.copy(true, graph),
|
||||
r1_copy = result[0];
|
||||
|
||||
expect(result).to.have.length(5);
|
||||
expect(result[0]).to.be.an.instanceof(iD.Relation);
|
||||
expect(result[1]).to.be.an.instanceof(iD.Way);
|
||||
expect(result[2]).to.be.an.instanceof(iD.Node);
|
||||
expect(result[3]).to.be.an.instanceof(iD.Node);
|
||||
expect(result[4]).to.be.an.instanceof(iD.Node);
|
||||
|
||||
expect(r1_copy.members[0].id).not.to.equal(r1.members[0].id);
|
||||
expect(r1_copy.members[0].role).to.equal(r1.members[0].role);
|
||||
});
|
||||
|
||||
it("deep copies non-tree relation graphs without duplicating children", function () {
|
||||
var w = iD.Way({id: 'w'}),
|
||||
r1 = iD.Relation({id: 'r1', members: [{id: 'r2'}, {id: 'w'}]}),
|
||||
r2 = iD.Relation({id: 'r2', members: [{id: 'w'}]}),
|
||||
graph = iD.Graph([w, r1, r2]),
|
||||
result = r1.copy(true, graph),
|
||||
r1_copy = result[0],
|
||||
r2_copy = result[1],
|
||||
w_copy = result[2];
|
||||
|
||||
expect(result).to.have.length(3);
|
||||
expect(r1_copy).to.be.an.instanceof(iD.Relation);
|
||||
expect(r2_copy).to.be.an.instanceof(iD.Relation);
|
||||
expect(w_copy).to.be.an.instanceof(iD.Way);
|
||||
|
||||
expect(r1_copy.members[0].id).to.equal(r2_copy.id);
|
||||
expect(r1_copy.members[1].id).to.equal(r2_copy.members[0].id);
|
||||
});
|
||||
|
||||
// it("deep copies cyclical relation graphs without issue", function () {
|
||||
// var r1 = iD.Relation({id: 'r1', members: [{id: 'r2'}]}),
|
||||
// r2 = iD.Relation({id: 'r2', members: [{id: 'r1'}]}),
|
||||
// graph = iD.Graph([r1, r2]),
|
||||
// result = r1.copy(true, graph),
|
||||
// r1_copy = result[0],
|
||||
// r2_copy = result[1];
|
||||
|
||||
// expect(result).to.have.length(2);
|
||||
// expect(r1_copy).to.be.an.instanceof(iD.Relation);
|
||||
// expect(r2_copy).to.be.an.instanceof(iD.Relation);
|
||||
|
||||
// var msg = 'r1_copy = ' + JSON.stringify(r1_copy) +
|
||||
// 'r2_copy = ' + JSON.stringify(r2_copy);
|
||||
// expect(r1_copy.members[0].id).to.equal(r2_copy.id, msg);
|
||||
// expect(r2_copy.members[0].id).to.equal(r1_copy.id, msg);
|
||||
// });
|
||||
|
||||
// it("deep copies self-refrencing relations without issue", function () {
|
||||
// var r1 = iD.Relation({id: 'r1', members: [{id: 'r1'}]}),
|
||||
// graph = iD.Graph([r1]),
|
||||
// result = r1.copy(true, graph),
|
||||
// r1_copy = result[0];
|
||||
|
||||
// expect(result).to.have.length(1);
|
||||
// expect(r1_copy).to.be.an.instanceof(iD.Relation);
|
||||
// expect(r1_copy.members[0].id).to.equal(r1_copy.id);
|
||||
// });
|
||||
});
|
||||
|
||||
describe("#extent", function () {
|
||||
it("returns the minimal extent containing the extents of all members", function () {
|
||||
var a = iD.Node({loc: [0, 0]}),
|
||||
|
||||
@@ -26,6 +26,52 @@ describe('iD.Way', function() {
|
||||
expect(iD.Way({tags: {foo: 'bar'}}).tags).to.eql({foo: 'bar'});
|
||||
});
|
||||
|
||||
describe("#copy", function () {
|
||||
it("returns a new Way", function () {
|
||||
var w1 = iD.Way({id: 'w1'}),
|
||||
result = w1.copy(),
|
||||
w2 = result[0];
|
||||
|
||||
expect(result).to.have.length(1);
|
||||
expect(w2).to.be.an.instanceof(iD.Way);
|
||||
expect(w1).not.to.equal(w2);
|
||||
});
|
||||
|
||||
it("keeps same nodes when deep = false", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
c = iD.Node({id: 'c'}),
|
||||
w1 = iD.Entity({id: 'w1', nodes: ['a','b','c','a']}),
|
||||
graph = iD.Graph([a, b, c, w1]),
|
||||
result = w1.copy(),
|
||||
w2 = result[0];
|
||||
|
||||
expect(result).to.have.length(1);
|
||||
expect(w1.nodes).to.deep.equal(w2.nodes);
|
||||
});
|
||||
|
||||
it("makes new nodes when deep = true", function () {
|
||||
var a = iD.Node({id: 'a'}),
|
||||
b = iD.Node({id: 'b'}),
|
||||
c = iD.Node({id: 'c'}),
|
||||
w1 = iD.Entity({id: 'w1', nodes: ['a','b','c','a']}),
|
||||
graph = iD.Graph([a, b, c, w1]),
|
||||
result = w1.copy(true, graph),
|
||||
w2 = result[0];
|
||||
|
||||
expect(result).to.have.length(4);
|
||||
expect(result[0]).to.be.an.instanceof(iD.Way);
|
||||
expect(result[1]).to.be.an.instanceof(iD.Node);
|
||||
expect(result[2]).to.be.an.instanceof(iD.Node);
|
||||
expect(result[3]).to.be.an.instanceof(iD.Node);
|
||||
|
||||
expect(w2.nodes[0]).not.to.equal(w1.nodes[0]);
|
||||
expect(w2.nodes[1]).not.to.equal(w1.nodes[1]);
|
||||
expect(w2.nodes[2]).not.to.equal(w1.nodes[2]);
|
||||
expect(w2.nodes[3]).to.equal(w2.nodes[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#first", function () {
|
||||
it("returns the first node", function () {
|
||||
expect(iD.Way({nodes: ['a', 'b', 'c']}).first()).to.equal('a');
|
||||
|
||||
Reference in New Issue
Block a user