Merge branch 'master' of github.com:systemed/iD

This commit is contained in:
Saman Bemel-Benrud
2013-02-12 17:31:39 -05:00
33 changed files with 274 additions and 70 deletions
+2 -2
View File
@@ -19,11 +19,11 @@ iD.actions.Connect = function(nodeIds) {
for (var i = 0; i < nodeIds.length - 1; i++) {
var node = graph.entity(nodeIds[i]), index;
graph.parentWays(node).forEach(function (parent) {
graph.parentWays(node).forEach(function(parent) {
graph = graph.replace(parent.replaceNode(node.id, survivor.id));
});
graph.parentRelations(node).forEach(function (parent) {
graph.parentRelations(node).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(node, survivor));
});
+1 -1
View File
@@ -6,7 +6,7 @@ iD.actions.DeleteMultiple = function(ids) {
relation: iD.actions.DeleteRelation
};
ids.forEach(function (id) {
ids.forEach(function(id) {
var entity = graph.entity(id);
if (entity) { // It may have been deleted aready.
graph = actions[entity.type](id)(graph);
+1 -1
View File
@@ -8,7 +8,7 @@ iD.actions.DeleteWay = function(wayId) {
graph = graph.replace(parent.removeMember(wayId));
});
way.nodes.forEach(function (nodeId) {
way.nodes.forEach(function(nodeId) {
var node = graph.entity(nodeId);
// Circular ways include nodes more than once, so they
+1 -1
View File
@@ -47,7 +47,7 @@ iD.actions.Join = function(ids) {
nodes = a.nodes.concat(b.nodes.slice().slice(1));
}
graph.parentRelations(b).forEach(function (parent) {
graph.parentRelations(b).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(b, a));
});
+2 -2
View File
@@ -9,10 +9,10 @@ iD.actions.Merge = function(ids) {
area = geometries.area[0],
points = geometries.point;
points.forEach(function (point) {
points.forEach(function(point) {
area = area.mergeTags(point.tags);
graph.parentRelations(point).forEach(function (parent) {
graph.parentRelations(point).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(point, area));
});
+2 -2
View File
@@ -1,9 +1,9 @@
iD.actions.MoveWay = function(wayId, delta, projection) {
return function(graph) {
return graph.update(function (graph) {
return graph.update(function(graph) {
var way = graph.entity(wayId);
_.uniq(way.nodes).forEach(function (id) {
_.uniq(way.nodes).forEach(function(id) {
var node = graph.entity(id),
start = projection(node.loc),
end = projection.invert([start[0] + delta[0], start[1] + delta[1]]);
+2 -2
View File
@@ -62,8 +62,8 @@ iD.actions.Reverse = function(wayId) {
tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
}
graph.parentRelations(way).forEach(function (relation) {
relation.members.forEach(function (member, index) {
graph.parentRelations(way).forEach(function(relation) {
relation.members.forEach(function(member, index) {
if (member.id === way.id && (role = {forward: 'backward', backward: 'forward'}[member.role])) {
relation = relation.updateMember({role: role}, index);
graph = graph.replace(relation);
+1 -1
View File
@@ -14,7 +14,7 @@ iD.actions.Split = function(nodeId, newWayId) {
var node = graph.entity(nodeId),
parents = graph.parentWays(node);
return parents.filter(function (parent) {
return parents.filter(function(parent) {
return parent.isClosed() ||
(parent.first() !== nodeId &&
parent.last() !== nodeId);
+1 -1
View File
@@ -61,7 +61,7 @@ iD.behavior.DragNode = function(context) {
context.surface()
.classed('behavior-drag-node', true)
.selectAll('.node, .way')
.filter(function (d) { return activeIDs.indexOf(d.id) >= 0; })
.filter(function(d) { return activeIDs.indexOf(d.id) >= 0; })
.classed('active', true);
}
+1 -1
View File
@@ -30,7 +30,7 @@ iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) {
if (datum.id === end.id || datum.id === segment.id) {
context.surface().selectAll('.way, .node')
.filter(function (d) {
.filter(function(d) {
return d.id === end.id || d.id === segment.id;
})
.classed('active', true);
+2 -2
View File
@@ -15,14 +15,14 @@ iD.behavior.Hover = function() {
var datum = d3.event.target.__data__;
if (datum) {
selection.selectAll('*')
.filter(function (d) { return d === datum; })
.filter(function(d) { return d === datum; })
.classed('hover', true);
}
}
selection.on('mouseover.hover', mouseover);
selection.on('mouseout.hover', function () {
selection.on('mouseout.hover', function() {
selection.selectAll('.hover')
.classed('hover', false);
});
+3 -3
View File
@@ -200,19 +200,19 @@ iD.Connection = function(context) {
comment: comment,
created_by: 'iD ' + iD.version
}))
}, function (err, changeset_id) {
}, function(err, changeset_id) {
if (err) return callback(err);
oauth.xhr({
method: 'POST',
path: '/api/0.6/changeset/' + changeset_id + '/upload',
options: { header: { 'Content-Type': 'text/xml' } },
content: JXON.stringify(connection.osmChangeJXON(user.id, changeset_id, changes))
}, function (err) {
}, function(err) {
if (err) return callback(err);
oauth.xhr({
method: 'PUT',
path: '/api/0.6/changeset/' + changeset_id + '/close'
}, function (err) {
}, function(err) {
callback(err, changeset_id);
});
});
+6 -4
View File
@@ -6,7 +6,7 @@
of entities that will require a redraw, taking into account
child and parent relationships.
*/
iD.Difference = function (base, head) {
iD.Difference = function(base, head) {
var changes = {}, length = 0;
_.each(head.entities, function(h, id) {
@@ -27,7 +27,7 @@ iD.Difference = function (base, head) {
var difference = {};
difference.length = function () {
difference.length = function() {
return length;
};
@@ -89,7 +89,9 @@ iD.Difference = function (base, head) {
b = change.base,
entity = h || b;
if (extent && !entity.intersects(extent, h ? head : base))
if (extent &&
(!h || !h.intersects(extent, head)) &&
(!b || !b.intersects(extent, base)))
continue;
result[id] = h;
@@ -105,7 +107,7 @@ iD.Difference = function (base, head) {
}
diff = _.difference(nb, nh);
for (var i = 0; i < diff.length; i++) {
for (i = 0; i < diff.length; i++) {
result[diff[i]] = head.entity(diff[i]);
}
}
+2 -2
View File
@@ -192,14 +192,14 @@ iD.Graph.prototype = {
if (this.entities[entity.id] === entity)
return this;
return this.update(function () {
return this.update(function() {
this._updateCalculated(this.entities[entity.id], entity);
this.entities[entity.id] = entity;
});
},
remove: function(entity) {
return this.update(function () {
return this.update(function() {
this._updateCalculated(entity, undefined);
this.entities[entity.id] = undefined;
});
+7 -7
View File
@@ -14,7 +14,7 @@ _.extend(iD.Relation.prototype, {
extent: function(resolver) {
return resolver.transient(this, 'extent', function() {
return this.members.reduce(function (extent, member) {
return this.members.reduce(function(extent, member) {
member = resolver.entity(member.id);
if (member) {
return extent.extend(member.extent(resolver));
@@ -156,8 +156,8 @@ _.extend(iD.Relation.prototype, {
//
multipolygon: function(resolver) {
var members = this.members
.filter(function (m) { return m.type === 'way' && resolver.entity(m.id); })
.map(function (m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.childNodes(resolver.entity(m.id)) }; });
.filter(function(m) { return m.type === 'way' && resolver.entity(m.id); })
.map(function(m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.childNodes(resolver.entity(m.id)) }; });
function join(ways) {
var joined = [], current, first, last, i, how, what;
@@ -202,7 +202,7 @@ _.extend(iD.Relation.prototype, {
}
}
return joined.map(function (nodes) { return _.pluck(nodes, 'loc'); });
return joined.map(function(nodes) { return _.pluck(nodes, 'loc'); });
}
function findOuter(inner) {
@@ -221,9 +221,9 @@ _.extend(iD.Relation.prototype, {
}
}
var outers = join(members.filter(function (m) { return m.role === 'outer'; })),
inners = join(members.filter(function (m) { return m.role === 'inner'; })),
result = outers.map(function (o) { return [o]; });
var outers = join(members.filter(function(m) { return m.role === 'outer'; })),
inners = join(members.filter(function(m) { return m.role === 'inner'; })),
result = outers.map(function(o) { return [o]; });
for (var i = 0; i < inners.length; i++) {
var o = findOuter(inners[i]);
+1 -1
View File
@@ -14,7 +14,7 @@ _.extend(iD.Way.prototype, {
extent: function(resolver) {
return resolver.transient(this, 'extent', function() {
return this.nodes.reduce(function (extent, id) {
return this.nodes.reduce(function(extent, id) {
return extent.extend(resolver.entity(id).extent(resolver));
}, iD.geo.Extent());
});
+2 -2
View File
@@ -64,13 +64,13 @@ iD.geo.pointInPolygon = function(point, polygon) {
};
iD.geo.polygonContainsPolygon = function(outer, inner) {
return _.every(inner, function (point) {
return _.every(inner, function(point) {
return iD.geo.pointInPolygon(point, outer);
});
};
iD.geo.polygonIntersectsPolygon = function(outer, inner) {
return _.some(inner, function (point) {
return _.some(inner, function(point) {
return iD.geo.pointInPolygon(point, outer);
});
};
+3 -3
View File
@@ -14,7 +14,7 @@ iD.geo.Extent = function geoExtent(min, max) {
iD.geo.Extent.prototype = [[], []];
_.extend(iD.geo.Extent.prototype, {
extend: function (obj) {
extend: function(obj) {
if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
return iD.geo.Extent([Math.min(obj[0][0], this[0][0]),
Math.min(obj[0][1], this[0][1])],
@@ -22,12 +22,12 @@ _.extend(iD.geo.Extent.prototype, {
Math.max(obj[1][1], this[1][1])]);
},
center: function () {
center: function() {
return [(this[0][0] + this[1][0]) / 2,
(this[0][1] + this[1][1]) / 2];
},
intersects: function (obj) {
intersects: function(obj) {
if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
return obj[0][0] <= this[1][0] &&
obj[0][1] <= this[1][1] &&
+2 -2
View File
@@ -319,14 +319,14 @@ iD.Map = function(context) {
}
};
map.flush = function () {
map.flush = function() {
context.connection().flush();
context.history().reset();
return map;
};
var usedTails = {};
map.tail = function (_) {
map.tail = function(_) {
if (!_ || usedTails[_] === undefined) {
tail.text(_);
usedTails[_] = true;
+3 -3
View File
@@ -32,10 +32,10 @@ iD.svg = {
};
},
MultipolygonMemberTags: function (graph) {
return function (entity) {
MultipolygonMemberTags: function(graph) {
return function(entity) {
var tags = entity.tags;
graph.parentRelations(entity).forEach(function (relation) {
graph.parentRelations(entity).forEach(function(relation) {
if (relation.isMultipolygon()) {
tags = _.extend({}, relation.tags, tags);
}
+3 -3
View File
@@ -28,11 +28,11 @@ iD.svg.Areas = function(projection) {
paths.enter()
.append('path')
.attr('class', function (d) { return d.type + ' area ' + klass; });
.attr('class', function(d) { return d.type + ' area ' + klass; });
paths
.order()
.attr('d', function (entity) { return path(entity.asGeoJSON(graph)); })
.attr('d', function(entity) { return path(entity.asGeoJSON(graph)); })
.call(tagClasses)
.call(iD.svg.MemberClasses(graph));
@@ -44,7 +44,7 @@ iD.svg.Areas = function(projection) {
areas = _.pluck(areas, 'entity');
var strokes = areas.filter(function (area) {
var strokes = areas.filter(function(area) {
return area.type === 'way';
});
+1 -1
View File
@@ -95,7 +95,7 @@ iD.svg.Lines = function(projection) {
// Determine the lengths of oneway paths
var lengths = {},
oneways = strokes.filter(function (d) { return d.isOneWay(); }).each(function(d) {
oneways = strokes.filter(function(d) { return d.isOneWay(); }).each(function(d) {
lengths[d.id] = Math.floor(this.getTotalLength() / alength);
}).data();
+1 -1
View File
@@ -17,7 +17,7 @@ iD.svg.MemberClasses = function(graph) {
classes += ' member';
}
relations.forEach(function (relation) {
relations.forEach(function(relation) {
classes += ' member-type-' + relation.tags.type;
classes += ' member-role-' + relation.memberById(d.id).role;
});
+1 -1
View File
@@ -35,7 +35,7 @@ iD.svg.Midpoints = function(projection) {
var groups = surface.select('.layer-hit').selectAll('g.midpoint')
.filter(filter)
.data(_.values(midpoints), function (d) { return d.id; });
.data(_.values(midpoints), function(d) { return d.id; });
var group = groups.enter()
.insert('g', ':first-child')
+1 -1
View File
@@ -23,7 +23,7 @@ iD.ui.geocoder = function(context) {
.text(t('geocoder.no_results', {name: searchVal}));
} else if (resp.length > 1) {
var spans = resultsList.selectAll('span')
.data(resp, function (d) { return d.place_id; });
.data(resp, function(d) { return d.place_id; });
spans.enter()
.append('span')
+1 -1
View File
@@ -64,5 +64,5 @@ iD.ui.Modes = function(context) {
d3.select(document)
.call(keybinding);
}
};
};
+4 -4
View File
@@ -42,10 +42,10 @@ iD.ui.RadialMenu = function(operations) {
});
button.append('circle')
.attr('class', function (d) { return 'radial-menu-item radial-menu-item-' + d.id; })
.attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
.attr('r', 15)
.attr('title', function (d) { return d.title; })
.classed('disabled', function (d) { return !d.enabled(); })
.attr('title', function(d) { return d.title; })
.classed('disabled', function(d) { return !d.enabled(); })
.on('click', click)
.on('mouseover', mouseover)
.on('mouseout', mouseout);
@@ -58,7 +58,7 @@ iD.ui.RadialMenu = function(operations) {
.attr('y', -10);
image.append('xhtml:span')
.attr('class', function (d) { return 'icon icon-operation icon-operation-' + d.id; });
.attr('class', function(d) { return 'icon icon-operation icon-operation-' + d.id; });
var tooltip = menu.append('foreignObject')
.style('display', 'none')
+3 -3
View File
@@ -10,7 +10,7 @@ iD.ui.Save = function(context) {
if (!history.hasChanges()) return;
connection.authenticate(function (err) {
connection.authenticate(function(err) {
var modal = iD.ui.modal(context.container());
var changes = history.changes();
changes.connection = connection;
@@ -18,7 +18,7 @@ iD.ui.Save = function(context) {
.classed('commit-modal', true)
.datum(changes)
.call(iD.ui.commit(context)
.on('cancel', function () {
.on('cancel', function() {
modal.remove();
})
.on('fix', clickFix)
@@ -73,7 +73,7 @@ iD.ui.Save = function(context) {
modal.remove();
}
return function (selection) {
return function(selection) {
var button = selection.append('button')
.attr('class', 'save col12 disabled')
.attr('tabindex', -1)
+1 -1
View File
@@ -43,5 +43,5 @@ iD.ui.UndoRedo = function(context) {
.attr('data-original-title', iD.ui.tooltipHtml(redo || t('nothing_to_redo'), iD.ui.cmd('⌘⇧Z')))
.call(refreshTooltip);
});
}
};
};
+201
View File
@@ -0,0 +1,201 @@
locale.da = {
modes: {
add_area: {
title: "Område",
description: "Tilføj parker, bygninger, søer, eller andre områder til kortet.",
tail: "Klik på kortet for at indtegne et område fx en park, sø eller bygning.",
key: "A"
},
add_line: {
title: "Linje",
description: "Linjer kan være veje, gader eller stier selv kanaler kan være linjer.",
tail: "Klik på koret for at indtegne en vej, sti eller rute.",
key: "L"
},
add_point: {
title: "Punkt",
description: "Restauranter, mindesmærker og postkasser er punkter.",
tail: "Klik på kortet for at tilføje et punkt.",
key: "P"
},
browse: {
title: "Browse",
description: "Træk rundt og zoom på kortet.",
key: "B"
},
draw_area: {
tail: "Klik her for at tilføje punkter til dit område. Click the first point to finish the area."
},
draw_line: {
tail: "Click to add more points to the line. Click on other lines to connect to them, and double-click to end the line."
}
},
operations: {
add: {
annotation: {
point: "Added a point.",
vertex: "Added a node to a way."
}
},
start: {
annotation: {
line: "Started a line.",
area: "Started an area."
}
},
'continue': {
annotation: {
line: "Continued a line.",
area: "Continued an area."
}
},
cancel_draw: {
annotation: "Cancelled drawing."
},
change_tags: {
annotation: "Changed tags."
},
circularize: {
title: "Circularize",
description: "Make this round.",
key: "O",
annotation: {
line: "Made a line circular.",
area: "Made an area circular."
}
},
orthogonalize: {
title: "Orthogonalize",
description: "Square these corners.",
key: "Q",
annotation: {
line: "Squared the corners of a line.",
area: "Squared the corners of an area."
}
},
'delete': {
title: "Delete",
description: "Remove this from the map.",
key: "⌫",
annotation: {
point: "Deleted a point.",
vertex: "Deleted a node from a way.",
line: "Deleted a line.",
area: "Deleted an area.",
relation: "Deleted a relation.",
multiple: "Deleted {n} objects."
}
},
connect: {
annotation: {
point: "Connected a way to a point.",
vertex: "Connected a way to another.",
line: "Connected a way to a line.",
area: "Connected a way to an area."
}
},
disconnect: {
title: "Disconnect",
description: "Disconnect these ways from each other.",
key: "D",
annotation: "Disconnected ways."
},
merge: {
title: "Merge",
description: "Merge these lines.",
key: "C",
annotation: "Merged {n} lines."
},
move: {
title: "Move",
description: "Move this to a different location.",
key: "M",
annotation: {
point: "Moved a point.",
vertex: "Moved a node in a way.",
line: "Moved a line.",
area: "Moved an area."
}
},
reverse: {
title: "Reverse",
description: "Make this line go in the opposite direction.",
key: "V",
annotation: "Reversed a line."
},
split: {
title: "Split",
description: "Split this into two ways at this point.",
key: "X",
annotation: "Split a way."
}
},
validations: {
untagged_point: "Untagged point which is not part of a line or area",
untagged_line: "Untagged line",
untagged_area: "Untagged area",
tag_suggests_area: "The tag {tag} suggests line should be area, but it is not an area",
deprecated_tags: "Deprecated tags: {tags}"
},
save: "Save",
unsaved_changes: "You have unsaved changes",
save_help: "Save changes to OpenStreetMap, making them visible to other users",
no_changes: "You don't have any changes to save.",
save_error: "An error occurred while trying to save",
uploading_changes: "Uploading changes to OpenStreetMap.",
just_edited: "You Just Edited OpenStreetMap!",
okay: "Okay",
"zoom-in": "Zoom ind",
"zoom-out": "Zoom ud",
nothing_to_undo: "Nothing to undo.",
nothing_to_redo: "Nothing to redo.",
browser_notice: "This editor is supported in Firefox, Chrome, Safari, Opera, and Internet Explorer 9 and above. Please upgrade your browser or use Potlatch 2 to edit the map.",
inspector: {
no_documentation_combination: "This is no documentation available for this tag combination",
no_documentation_key: "This is no documentation available for this key",
new_tag: "Nyt Tag"
},
view_on_osm: "Vis på OSM",
zoom_in_edit: "zoom ind for at rette kortet",
edit_tags: "Ret tags",
geocoder: {
title: "Find et sted",
placeholder: "find et sted",
no_results: "Kunne ikke finde '{name}'"
},
description: "Description",
logout: "log ud",
report_a_bug: "report a bug",
layerswitcher: {
title: "Background",
description: "Background Settings",
percent_brightness: "{opacity}% brightness",
fix_misalignment: "Fix misalignment",
reset: "nulstill"
},
contributors: {
list: "Vis bidrag fra {users}",
truncated_list: "Vis bidrag fra {users} og {count} andre"
},
source_switch: {
live: "live",
dev: "dev"
}
};
+1
View File
@@ -23,6 +23,7 @@
<!-- include spec files here... -->
<script src="spec/lib/d3.keybinding.js"></script>
<script src="spec/lib/locale.js"></script>
<script src="spec/translation.js"></script>
<script src="spec/actions/add_midpoint.js"></script>
<script src="spec/actions/add_entity.js"></script>
+8 -8
View File
@@ -1,12 +1,12 @@
describe("iD.actions.DeleteWay", function () {
it("removes the way from the graph", function () {
describe("iD.actions.DeleteWay", function() {
it("removes the way from the graph", function() {
var way = iD.Way(),
action = iD.actions.DeleteWay(way.id),
graph = iD.Graph([way]).update(action);
expect(graph.entity(way.id)).to.be.undefined;
});
it("removes a way from parent relations", function () {
it("removes a way from parent relations", function() {
var way = iD.Way(),
relation = iD.Relation({members: [{ id: way.id }]}),
action = iD.actions.DeleteWay(way.id),
@@ -14,7 +14,7 @@ describe("iD.actions.DeleteWay", function () {
expect(_.pluck(graph.entity(relation.id).members, 'id')).not.to.contain(way.id);
});
it("deletes member nodes not referenced by another parent", function () {
it("deletes member nodes not referenced by another parent", function() {
var node = iD.Node(),
way = iD.Way({nodes: [node.id]}),
action = iD.actions.DeleteWay(way.id),
@@ -22,7 +22,7 @@ describe("iD.actions.DeleteWay", function () {
expect(graph.entity(node.id)).to.be.undefined;
});
it("does not delete member nodes referenced by another parent", function () {
it("does not delete member nodes referenced by another parent", function() {
var node = iD.Node(),
way1 = iD.Way({nodes: [node.id]}),
way2 = iD.Way({nodes: [node.id]}),
@@ -31,7 +31,7 @@ describe("iD.actions.DeleteWay", function () {
expect(graph.entity(node.id)).not.to.be.undefined;
});
it("deletes multiple member nodes", function () {
it("deletes multiple member nodes", function() {
var a = iD.Node(),
b = iD.Node(),
way = iD.Way({nodes: [a.id, b.id]}),
@@ -41,7 +41,7 @@ describe("iD.actions.DeleteWay", function () {
expect(graph.entity(b.id)).to.be.undefined;
});
it("deletes a circular way's start/end node", function () {
it("deletes a circular way's start/end node", function() {
var a = iD.Node(),
b = iD.Node(),
c = iD.Node(),
@@ -53,7 +53,7 @@ describe("iD.actions.DeleteWay", function () {
expect(graph.entity(c.id)).to.be.undefined;
});
it("does not delete member nodes with interesting tags", function () {
it("does not delete member nodes with interesting tags", function() {
var node = iD.Node({tags: {highway: 'traffic_signals'}}),
way = iD.Way({nodes: [node.id]}),
action = iD.actions.DeleteWay(way.id),
+3 -3
View File
@@ -1,5 +1,5 @@
describe("iD.actions.MoveWay", function () {
it("moves all nodes in a way by the given amount", function () {
describe("iD.actions.MoveWay", function() {
it("moves all nodes in a way by the given amount", function() {
var node1 = iD.Node({loc: [0, 0]}),
node2 = iD.Node({loc: [5, 10]}),
way = iD.Way({nodes: [node1.id, node2.id]}),
@@ -14,7 +14,7 @@ describe("iD.actions.MoveWay", function () {
expect(loc2[1]).to.be.closeTo( 7.866, 0.001);
});
it("moves repeated nodes only once", function () {
it("moves repeated nodes only once", function() {
var node = iD.Node({loc: [0, 0]}),
way = iD.Way({nodes: [node.id, node.id]}),
delta = [2, 3],