mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-23 08:39:56 +02:00
Merge branch 'master' of github.com:systemed/iD
This commit is contained in:
+3
-3
@@ -52,17 +52,17 @@ iD.format.XML = {
|
||||
'@version': 0.3,
|
||||
'@generator': 'iD',
|
||||
// TODO: copy elements first
|
||||
create: nest(changes.create.map(function(c) {
|
||||
create: nest(changes.created.map(function(c) {
|
||||
var x = iD.Entity(c);
|
||||
x.changeset = changeset_id;
|
||||
return x;
|
||||
}).map(iD.format.XML.rep)),
|
||||
modify: changes.modify.map(function(c) {
|
||||
modify: changes.modified.map(function(c) {
|
||||
var x = iD.Entity(c);
|
||||
x.changeset = changeset_id;
|
||||
return x;
|
||||
}).map(iD.format.XML.rep),
|
||||
'delete': changes['delete'].map(function(c) {
|
||||
'delete': changes.deleted.map(function(c) {
|
||||
var x = iD.Entity(c);
|
||||
x.changeset = changeset_id;
|
||||
return x;
|
||||
|
||||
+49
-17
@@ -24,14 +24,14 @@ iD.Graph.prototype = {
|
||||
parentWays: function(id) {
|
||||
// This is slow and a bad hack.
|
||||
return _.filter(this.entities, function(e) {
|
||||
return e.type === 'way' && e.nodes.indexOf(id) !== -1;
|
||||
return e && e.type === 'way' && e.nodes.indexOf(id) !== -1;
|
||||
});
|
||||
},
|
||||
|
||||
parentRelations: function(id) {
|
||||
// This is slow and a bad hack.
|
||||
return _.filter(this.entities, function(e) {
|
||||
return e.type === 'relation' && e.members.indexOf(id) !== -1;
|
||||
return e && e.type === 'relation' && e.members.indexOf(id) !== -1;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -49,7 +49,13 @@ iD.Graph.prototype = {
|
||||
|
||||
remove: function(entity) {
|
||||
var entities = _.clone(this.entities);
|
||||
delete entities[entity.id];
|
||||
|
||||
if (entity.created()) {
|
||||
delete entities[entity.id];
|
||||
} else {
|
||||
entities[entity.id] = undefined;
|
||||
}
|
||||
|
||||
return iD.Graph(entities);
|
||||
},
|
||||
|
||||
@@ -58,7 +64,7 @@ iD.Graph.prototype = {
|
||||
var items = [];
|
||||
for (var i in this.entities) {
|
||||
var entity = this.entities[i];
|
||||
if (entity.intersects(extent, this)) {
|
||||
if (entity && entity.intersects(extent, this)) {
|
||||
items.push(this.fetch(entity.id));
|
||||
}
|
||||
}
|
||||
@@ -68,26 +74,52 @@ iD.Graph.prototype = {
|
||||
// Resolve the id references in a way, replacing them with actual objects.
|
||||
fetch: function(id) {
|
||||
var entity = this.entities[id], nodes = [];
|
||||
if (!entity.nodes || !entity.nodes.length) return entity;
|
||||
if (!entity || !entity.nodes || !entity.nodes.length) return entity;
|
||||
for (var i = 0, l = entity.nodes.length; i < l; i++) {
|
||||
nodes[i] = this.fetch(entity.nodes[i]);
|
||||
}
|
||||
return iD.Entity(entity, {nodes: nodes});
|
||||
},
|
||||
|
||||
modifications: function() {
|
||||
return _.filter(this.entities, function(entity) {
|
||||
return entity.modified();
|
||||
}).map(function(e) {
|
||||
return this.fetch(e.id);
|
||||
}.bind(this));
|
||||
difference: function (graph) {
|
||||
var result = [];
|
||||
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity !== graph.entities[id]) {
|
||||
result.push(id);
|
||||
}
|
||||
});
|
||||
|
||||
_.each(graph.entities, function(entity, id) {
|
||||
if (entity && !this.entities.hasOwnProperty(id)) {
|
||||
result.push(id);
|
||||
}
|
||||
}, this);
|
||||
|
||||
return result.sort();
|
||||
},
|
||||
|
||||
creations: function() {
|
||||
return _.filter(this.entities, function(entity) {
|
||||
return entity.created();
|
||||
}).map(function(e) {
|
||||
return this.fetch(e.id);
|
||||
}.bind(this));
|
||||
modified: function() {
|
||||
var result = [];
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && entity.modified()) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
created: function() {
|
||||
var result = [];
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && entity.created()) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
deleted: function() {
|
||||
var result = [];
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (!entity) result.push(id);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
+30
-29
@@ -19,10 +19,8 @@ iD.History = function() {
|
||||
return {graph: graph, annotation: annotation};
|
||||
}
|
||||
|
||||
function maybeChange() {
|
||||
if (stack[index].annotation) {
|
||||
dispatch.change();
|
||||
}
|
||||
function change(previous) {
|
||||
dispatch.change(history.graph().difference(previous));
|
||||
}
|
||||
|
||||
var history = {
|
||||
@@ -37,32 +35,44 @@ iD.History = function() {
|
||||
},
|
||||
|
||||
perform: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
stack = stack.slice(0, index + 1);
|
||||
stack.push(perform(arguments));
|
||||
index++;
|
||||
dispatch.change();
|
||||
|
||||
change(previous);
|
||||
},
|
||||
|
||||
replace: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
// assert(index == stack.length - 1)
|
||||
stack[index] = perform(arguments);
|
||||
dispatch.change();
|
||||
|
||||
change(previous);
|
||||
},
|
||||
|
||||
undo: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
while (index > 0) {
|
||||
index--;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
dispatch.change();
|
||||
|
||||
change(previous);
|
||||
},
|
||||
|
||||
redo: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
while (index < stack.length - 1) {
|
||||
index++;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
dispatch.change();
|
||||
|
||||
change(previous);
|
||||
},
|
||||
|
||||
undoAnnotation: function () {
|
||||
@@ -81,29 +91,20 @@ iD.History = function() {
|
||||
}
|
||||
},
|
||||
|
||||
// generate reports of changes for changesets to use
|
||||
modify: function () {
|
||||
return stack[index].graph.modifications();
|
||||
},
|
||||
|
||||
create: function () {
|
||||
return stack[index].graph.creations();
|
||||
},
|
||||
|
||||
'delete': function () {
|
||||
return _.difference(
|
||||
_.pluck(stack[0].graph.entities, 'id'),
|
||||
_.pluck(stack[index].graph.entities, 'id')
|
||||
).map(function (id) {
|
||||
return stack[0].graph.fetch(id);
|
||||
});
|
||||
},
|
||||
|
||||
changes: function () {
|
||||
var initial = stack[0].graph,
|
||||
current = stack[index].graph;
|
||||
|
||||
return {
|
||||
modify: this.modify(),
|
||||
create: this.create(),
|
||||
'delete': this['delete']()
|
||||
modified: current.modified().map(function (id) {
|
||||
return current.fetch(id);
|
||||
}),
|
||||
created: current.created().map(function (id) {
|
||||
return current.fetch(id);
|
||||
}),
|
||||
deleted: current.deleted().map(function (id) {
|
||||
return initial.fetch(id);
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
+22
-13
@@ -69,21 +69,30 @@ iD.Map = function() {
|
||||
return 'M' + _.pluck(d.nodes, 'loc').map(projection).map(iD.util.geo.roundCoords).join('L');
|
||||
}
|
||||
|
||||
function drawVector(only) {
|
||||
function drawVector(difference) {
|
||||
if (surface.style(transformProp) != 'none') return;
|
||||
var all = [], ways = [], areas = [], points = [], waynodes = [],
|
||||
var filter, all, ways = [], areas = [], points = [], waynodes = [],
|
||||
extent = map.extent(),
|
||||
graph = history.graph();
|
||||
|
||||
if (!only) {
|
||||
if (!difference) {
|
||||
all = graph.intersects(extent);
|
||||
filter = d3.functor(true);
|
||||
} else {
|
||||
for (var id in only) all.push(graph.fetch(id));
|
||||
var only = {};
|
||||
difference.forEach(function (id) {
|
||||
var entity = graph.fetch(id);
|
||||
if (entity) {
|
||||
only[id] = entity;
|
||||
graph.parentWays(id).forEach(function (entity) {
|
||||
only[entity.id] = graph.fetch(entity.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
all = _.values(only);
|
||||
filter = function(d) { return d.accuracy ? only[d.way.id] : only[d.id]; };
|
||||
}
|
||||
|
||||
var filter = only ?
|
||||
function(d) { return only[d.id]; } : function() { return true; };
|
||||
|
||||
if (all.length > 200000) return hideVector();
|
||||
|
||||
for (var i = 0; i < all.length; i++) {
|
||||
@@ -151,7 +160,7 @@ iD.Map = function() {
|
||||
function drawAccuracyHandles(waynodes, filter) {
|
||||
var handles = g.hit.selectAll('circle.accuracy-handle')
|
||||
.filter(filter)
|
||||
.data(waynodes, key);
|
||||
.data(waynodes, function (d) { return [d.way.id, d.index].join(","); });
|
||||
handles.exit().remove();
|
||||
handles.enter().append('circle')
|
||||
.attr({ r: 2, 'class': 'accuracy-handle' });
|
||||
@@ -241,14 +250,14 @@ iD.Map = function() {
|
||||
|
||||
function connectionLoad(err, result) {
|
||||
history.merge(result);
|
||||
drawVector(iD.util.trueObj(Object.keys(result.entities)));
|
||||
drawVector(Object.keys(result.entities));
|
||||
}
|
||||
|
||||
function hoverIn() {
|
||||
var datum = d3.select(d3.event.target).datum();
|
||||
if (datum instanceof iD.Entity) {
|
||||
hover = datum.id;
|
||||
drawVector(iD.util.trueObj([hover]));
|
||||
drawVector([hover]);
|
||||
d3.select('.messages').text(datum.tags.name || '#' + datum.id);
|
||||
}
|
||||
}
|
||||
@@ -257,7 +266,7 @@ iD.Map = function() {
|
||||
if (hover) {
|
||||
var oldHover = hover;
|
||||
hover = null;
|
||||
drawVector(iD.util.trueObj([oldHover]));
|
||||
drawVector([oldHover]);
|
||||
d3.select('.messages').text('');
|
||||
}
|
||||
}
|
||||
@@ -299,12 +308,12 @@ iD.Map = function() {
|
||||
redraw();
|
||||
}
|
||||
|
||||
function redraw() {
|
||||
function redraw(difference) {
|
||||
dispatch.move(map);
|
||||
tilegroup.call(background);
|
||||
if (map.zoom() > 16) {
|
||||
connection.loadTiles(projection);
|
||||
drawVector();
|
||||
drawVector(difference);
|
||||
} else {
|
||||
hideVector();
|
||||
}
|
||||
|
||||
+85
-40
@@ -21,35 +21,46 @@ describe('iD.Graph', function() {
|
||||
});
|
||||
}
|
||||
|
||||
describe('operations', function() {
|
||||
it('#remove', function() {
|
||||
var entities = { 'n-1': {
|
||||
type: 'node',
|
||||
loc: [-80, 30],
|
||||
id: 'n-1'
|
||||
}
|
||||
};
|
||||
var graph = iD.Graph(entities, 'first graph');
|
||||
var g2 = graph.remove(entities['n-1'], 'Removed node');
|
||||
expect(graph.entity('n-1')).to.equal(entities['n-1']);
|
||||
expect(g2.entity('n-1')).to.equal(undefined);
|
||||
describe("#remove", function () {
|
||||
it("returns a new graph", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.remove(node)).not.to.equal(graph);
|
||||
});
|
||||
it('#replace', function() {
|
||||
var entities = { 'n-1': {
|
||||
type: 'node',
|
||||
loc: [-80, 30],
|
||||
id: 'n-1'
|
||||
}
|
||||
};
|
||||
var replacement = {
|
||||
type: 'node',
|
||||
loc: [-80, 40],
|
||||
id: 'n-1'
|
||||
};
|
||||
var graph = iD.Graph(entities, 'first graph');
|
||||
var g2 = graph.replace(replacement, 'Removed node');
|
||||
expect(graph.entity('n-1').loc[1]).to.equal(30);
|
||||
expect(g2.entity('n-1').loc[1]).to.equal(40);
|
||||
|
||||
it("doesn't modify the receiver", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
graph.remove(node);
|
||||
expect(graph.entity(node.id)).to.equal(node);
|
||||
});
|
||||
|
||||
it("removes the entity from the result", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.remove(node).entity(node.id)).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#replace", function () {
|
||||
it("returns a new graph", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.replace(node)).not.to.equal(graph);
|
||||
});
|
||||
|
||||
it("doesn't modify the receiver", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
graph.replace(node);
|
||||
expect(graph.entity(node.id)).to.equal(node);
|
||||
});
|
||||
|
||||
it("replaces the entity in the result", function () {
|
||||
var node1 = iD.Node(),
|
||||
node2 = node1.update({}),
|
||||
graph = iD.Graph([node1]);
|
||||
expect(graph.replace(node2).entity(node2.id)).to.equal(node2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -82,21 +93,55 @@ describe('iD.Graph', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#modifications", function () {
|
||||
it("filters entities by modified", function () {
|
||||
var a = {id: 'a', modified: function () { return true; }},
|
||||
b = {id: 'b', modified: function () { return false; }},
|
||||
graph = iD.Graph({ 'a': a, 'b': b });
|
||||
expect(graph.modifications()).to.eql([graph.fetch('a')]);
|
||||
describe("#difference", function () {
|
||||
it("returns an Array of ids of changed entities", function () {
|
||||
var initial = iD.Node({id: "n1"}),
|
||||
updated = initial.update({}),
|
||||
created = iD.Node(),
|
||||
deleted = iD.Node({id: 'n2'}),
|
||||
graph1 = iD.Graph([initial, deleted]),
|
||||
graph2 = graph1.replace(updated).replace(created).remove(deleted);
|
||||
expect(graph2.difference(graph1)).to.eql([created.id, updated.id, deleted.id]);
|
||||
});
|
||||
|
||||
it("includes created entities that were subsequently deleted", function () {
|
||||
var node = iD.Node(),
|
||||
graph1 = iD.Graph([node]),
|
||||
graph2 = graph1.remove(node);
|
||||
expect(graph2.difference(graph1)).to.eql([node.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#creations", function () {
|
||||
it("filters entities by created", function () {
|
||||
var a = {id: 'a', created: function () { return true; }},
|
||||
b = {id: 'b', created: function () { return false; }},
|
||||
graph = iD.Graph({ 'a': a, 'b': b });
|
||||
expect(graph.creations()).to.eql([graph.fetch('a')]);
|
||||
describe("#modified", function () {
|
||||
it("returns an Array of ids of modified entities", function () {
|
||||
var node1 = iD.Node({id: 'n1', _updated: true}),
|
||||
node2 = iD.Node({id: 'n2'}),
|
||||
graph = iD.Graph([node1, node2]);
|
||||
expect(graph.modified()).to.eql([node1.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#created", function () {
|
||||
it("returns an Array of ids of created entities", function () {
|
||||
var node1 = iD.Node({id: 'n-1', _updated: true}),
|
||||
node2 = iD.Node({id: 'n2'}),
|
||||
graph = iD.Graph([node1, node2]);
|
||||
expect(graph.created()).to.eql([node1.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#deleted", function () {
|
||||
it("returns an Array of ids of deleted entities", function () {
|
||||
var node1 = iD.Node({id: "n1"}),
|
||||
node2 = iD.Node(),
|
||||
graph = iD.Graph([node1, node2]).remove(node1);
|
||||
expect(graph.deleted()).to.eql([node1.id]);
|
||||
});
|
||||
|
||||
it("doesn't include created entities that were subsequently deleted", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]).remove(node);
|
||||
expect(graph.deleted()).to.eql([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ describe("iD.History", function () {
|
||||
it("emits a change event", function () {
|
||||
history.on('change', spy);
|
||||
history.perform(action);
|
||||
expect(spy).to.have.been.called;
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
});
|
||||
|
||||
it("performs multiple actions", function () {
|
||||
@@ -57,7 +57,7 @@ describe("iD.History", function () {
|
||||
it("emits a change event", function () {
|
||||
history.on('change', spy);
|
||||
history.replace(action);
|
||||
expect(spy).to.have.been.called;
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
});
|
||||
|
||||
it("performs multiple actions", function () {
|
||||
@@ -87,7 +87,7 @@ describe("iD.History", function () {
|
||||
history.perform(action);
|
||||
history.on('change', spy);
|
||||
history.undo();
|
||||
expect(spy).to.have.been.called;
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,7 +97,32 @@ describe("iD.History", function () {
|
||||
history.undo();
|
||||
history.on('change', spy);
|
||||
history.redo();
|
||||
expect(spy).to.have.been.called;
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#changes", function () {
|
||||
it("includes created entities", function () {
|
||||
var node = iD.Node();
|
||||
history.perform(function (graph) { return graph.replace(node); });
|
||||
expect(history.changes().created).to.eql([node]);
|
||||
});
|
||||
|
||||
it("includes modified entities", function () {
|
||||
var node1 = iD.Node({id: "n1"}),
|
||||
node2 = node1.update({}),
|
||||
graph = iD.Graph([node1]);
|
||||
history.merge(graph);
|
||||
history.perform(function (graph) { return graph.replace(node2); });
|
||||
expect(history.changes().modified).to.eql([node2]);
|
||||
});
|
||||
|
||||
it("includes deleted entities", function () {
|
||||
var node = iD.Node({id: "n1"}),
|
||||
graph = iD.Graph([node]);
|
||||
history.merge(graph);
|
||||
history.perform(function (graph) { return graph.remove(node); });
|
||||
expect(history.changes().deleted).to.eql([node]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user