diff --git a/modules/actions/rotate_way.js b/modules/actions/rotate.js similarity index 100% rename from modules/actions/rotate_way.js rename to modules/actions/rotate.js diff --git a/modules/util/index.js b/modules/util/index.js index 75e691fc2..e84dc86db 100644 --- a/modules/util/index.js +++ b/modules/util/index.js @@ -1,6 +1,7 @@ export { utilTagText } from './util'; export { utilEntitySelector } from './util'; export { utilEntityOrMemberSelector } from './util'; +export { utilGetAllNodes } from './util'; export { utilDisplayName } from './util'; export { utilDisplayType } from './util'; export { utilStringQs } from './util'; diff --git a/modules/util/util.js b/modules/util/util.js index 4e142178a..3302a3f56 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -32,6 +32,30 @@ export function utilEntityOrMemberSelector(ids, graph) { } +export function utilGetAllNodes(ids, graph) { + var seen = {}; + var nodes = []; + ids.forEach(getNodes); + return nodes; + + function getNodes(id) { + if (seen[id]) return; + seen[id] = true; + + var entity = graph.hasEntity(id); + if (!entity) return; + + if (entity.type === 'node') { + nodes.push(entity); + } else if (entity.type === 'way') { + entity.nodes.forEach(getNodes); + } else { + entity.members.map(function(member) { return member.id; }).forEach(getNodes); + } + } +} + + export function utilDisplayName(entity) { var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0], name = entity.tags[localizedNameKey] || entity.tags.name || '', diff --git a/test/spec/util/util.js b/test/spec/util/util.js index f235f4fb0..da64f309e 100644 --- a/test/spec/util/util.js +++ b/test/spec/util/util.js @@ -1,4 +1,58 @@ describe('iD.util', function() { + + describe('utilGetAllNodes', function() { + it('gets all descendant nodes of a way', function() { + var a = iD.Node({ id: 'a' }), + b = iD.Node({ id: 'b' }), + w = iD.Way({ id: 'w', nodes: ['a','b','a'] }), + graph = iD.Graph([a, b, w]), + result = iD.utilGetAllNodes(['w'], graph); + + expect(result).to.have.members([a, b]); + expect(result).to.have.lengthOf(2); + }); + + it('gets all descendant nodes of a relation', function() { + var a = iD.Node({ id: 'a' }), + b = iD.Node({ id: 'b' }), + c = iD.Node({ id: 'c' }), + w = iD.Way({ id: 'w', nodes: ['a','b','a'] }), + r = iD.Relation({ id: 'r', members: [{id: 'w'}, {id: 'c'}] }), + graph = iD.Graph([a, b, c, w, r]), + result = iD.utilGetAllNodes(['r'], graph); + + expect(result).to.have.members([a, b, c]); + expect(result).to.have.lengthOf(3); + }); + + it('gets all descendant nodes of multiple ids', function() { + var a = iD.Node({ id: 'a' }), + b = iD.Node({ id: 'b' }), + c = iD.Node({ id: 'c' }), + d = iD.Node({ id: 'd' }), + e = iD.Node({ id: 'e' }), + w1 = iD.Way({ id: 'w1', nodes: ['a','b','a'] }), + w2 = iD.Way({ id: 'w2', nodes: ['c','b','a','c'] }), + r = iD.Relation({ id: 'r', members: [{id: 'w1'}, {id: 'd'}] }), + graph = iD.Graph([a, b, c, d, e, w1, w2, r]), + result = iD.utilGetAllNodes(['r', 'w2', 'e'], graph); + + expect(result).to.have.members([a, b, c, d, e]); + expect(result).to.have.lengthOf(5); + }); + + it('handles recursive relations', function() { + var a = iD.Node({ id: 'a' }), + r1 = iD.Relation({ id: 'r1', members: [{id: 'r2'}] }), + r2 = iD.Relation({ id: 'r2', members: [{id: 'r1'}, {id: 'a'}] }), + graph = iD.Graph([a, r1, r2]), + result = iD.utilGetAllNodes(['r1'], graph); + + expect(result).to.have.members([a]); + expect(result).to.have.lengthOf(1); + }); + }); + it('utilTagText', function() { expect(iD.utilTagText({})).to.eql(''); expect(iD.utilTagText({tags:{foo:'bar'}})).to.eql('foo=bar');