mirror of
https://github.com/FoggedLens/iD.git
synced 2026-04-21 11:16:36 +02:00
Merge branch 'master' of github.com:systemed/iD
This commit is contained in:
@@ -41,7 +41,6 @@ all: \
|
||||
js/id/modes/*.js \
|
||||
js/id/operations.js \
|
||||
js/id/operations/*.js \
|
||||
js/id/controller.js \
|
||||
js/id/graph/*.js \
|
||||
js/id/renderer/*.js \
|
||||
js/id/svg.js \
|
||||
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>iD</title>
|
||||
<link rel='stylesheet' href='css/reset.css'>
|
||||
<link rel='stylesheet' href='css/map.css'>
|
||||
<link rel='stylesheet' href='css/app.css'>
|
||||
|
||||
<!-- mobile devices -->
|
||||
<meta name='viewport' content='initial-scale=1.0 maximum-scale=1.0'>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
|
||||
<script src='js/lib/lodash.js'></script>
|
||||
<script src='js/lib/d3.v3.js'></script>
|
||||
<script src='js/lib/sha.js'></script>
|
||||
<script src='js/lib/ohauth.js'></script>
|
||||
<script src='js/lib/jxon.js'></script>
|
||||
<script src='js/lib/d3.typeahead.js'></script>
|
||||
<script src='js/lib/d3.combobox.js'></script>
|
||||
<script src='js/lib/d3.geo.tile.js'></script>
|
||||
<script src='js/lib/d3.size.js'></script>
|
||||
<script src='js/lib/d3.trigger.js'></script>
|
||||
<script src='js/lib/d3.keybinding.js'></script>
|
||||
<script src='js/lib/d3.tail.js'></script>
|
||||
<script src='js/lib/d3-compat.js'></script>
|
||||
<script src='js/lib/bootstrap-tooltip.js'></script>
|
||||
<script src='js/lib/rtree.js'></script>
|
||||
|
||||
<script src='js/id/id.js'></script>
|
||||
<script src='js/id/util.js'></script>
|
||||
<script src='js/id/oauth.js'></script>
|
||||
<script src='js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src="js/id/geo.js"></script>
|
||||
<script src="js/id/geo/extent.js"></script>
|
||||
|
||||
<script src='js/id/renderer/background.js'></script>
|
||||
<script src='js/id/renderer/background_source.js'></script>
|
||||
<script src='js/id/renderer/map.js'></script>
|
||||
<script src='js/id/renderer/hash.js'></script>
|
||||
|
||||
<script src="js/id/svg.js"></script>
|
||||
<script src="js/id/svg/areas.js"></script>
|
||||
<script src="js/id/svg/lines.js"></script>
|
||||
<script src="js/id/svg/member_classes.js"></script>
|
||||
<script src="js/id/svg/midpoints.js"></script>
|
||||
<script src="js/id/svg/multipolygons.js"></script>
|
||||
<script src="js/id/svg/points.js"></script>
|
||||
<script src="js/id/svg/surface.js"></script>
|
||||
<script src="js/id/svg/tag_classes.js"></script>
|
||||
<script src="js/id/svg/vertices.js"></script>
|
||||
<script src="js/id/svg/labels.js"></script>
|
||||
|
||||
<script src="js/id/ui.js"></script>
|
||||
<script src='js/id/ui/radial_menu.js'></script>
|
||||
<script src='js/id/ui/inspector.js'></script>
|
||||
<script src='js/id/ui/modal.js'></script>
|
||||
<script src='js/id/ui/confirm.js'></script>
|
||||
<script src='js/id/ui/commit.js'></script>
|
||||
<script src='js/id/ui/success.js'></script>
|
||||
<script src='js/id/ui/loading.js'></script>
|
||||
<script src='js/id/ui/userpanel.js'></script>
|
||||
<script src='js/id/ui/layerswitcher.js'></script>
|
||||
<script src='js/id/ui/contributors.js'></script>
|
||||
<script src='js/id/ui/geocoder.js'></script>
|
||||
<script src='js/id/ui/geolocate.js'></script>
|
||||
<script src='js/id/ui/notice.js'></script>
|
||||
<script src='js/id/ui/flash.js'></script>
|
||||
<script src='js/id/ui/save.js'></script>
|
||||
<script src='js/id/ui/tag_reference.js'></script>
|
||||
<script src='js/id/ui/key_reference.js'></script>
|
||||
|
||||
<script src='js/id/actions.js'></script>
|
||||
<script src="js/id/actions/add_midpoint.js"></script>
|
||||
<script src='js/id/actions/add_entity.js'></script>
|
||||
<script src='js/id/actions/add_vertex.js'></script>
|
||||
<script src='js/id/actions/change_tags.js'></script>
|
||||
<script src='js/id/actions/delete_node.js'></script>
|
||||
<script src="js/id/actions/delete_way.js"></script>
|
||||
<script src='js/id/actions/disconnect.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
<script src='js/id/actions/noop.js'></script>
|
||||
<script src='js/id/actions/reverse.js'></script>
|
||||
<script src='js/id/actions/split.js'></script>
|
||||
|
||||
<script src='js/id/behavior.js'></script>
|
||||
<script src='js/id/behavior/add_way.js'></script>
|
||||
<script src='js/id/behavior/drag.js'></script>
|
||||
<script src='js/id/behavior/drag_midpoint.js'></script>
|
||||
<script src='js/id/behavior/drag_node.js'></script>
|
||||
<script src='js/id/behavior/draw.js'></script>
|
||||
<script src='js/id/behavior/draw_way.js'></script>
|
||||
<script src='js/id/behavior/hover.js'></script>
|
||||
<script src='js/id/behavior/select.js'></script>
|
||||
|
||||
<script src='js/id/modes.js'></script>
|
||||
<script src='js/id/modes/add_area.js'></script>
|
||||
<script src='js/id/modes/add_point.js'></script>
|
||||
<script src='js/id/modes/add_line.js'></script>
|
||||
<script src='js/id/modes/browse.js'></script>
|
||||
<script src='js/id/modes/draw_area.js'></script>
|
||||
<script src='js/id/modes/draw_line.js'></script>
|
||||
<script src='js/id/modes/move_way.js'></script>
|
||||
<script src='js/id/modes/select.js'></script>
|
||||
|
||||
<script src='js/id/operations.js'></script>
|
||||
<script src='js/id/operations/circularize.js'></script>
|
||||
<script src='js/id/operations/delete.js'></script>
|
||||
<script src='js/id/operations/move.js'></script>
|
||||
<script src='js/id/operations/reverse.js'></script>
|
||||
<script src='js/id/operations/split.js'></script>
|
||||
<script src='js/id/operations/unjoin.js'></script>
|
||||
|
||||
<script src='js/id/graph/entity.js'></script>
|
||||
<script src='js/id/graph/graph.js'></script>
|
||||
<script src='js/id/graph/history.js'></script>
|
||||
<script src='js/id/graph/node.js'></script>
|
||||
<script src='js/id/graph/relation.js'></script>
|
||||
<script src='js/id/graph/way.js'></script>
|
||||
|
||||
<script src='js/id/controller.js'></script>
|
||||
<script src='js/id/validate.js'></script>
|
||||
<script src='js/id/connection.js'></script>
|
||||
|
||||
<script src='locale/locale.js'></script>
|
||||
<script src='locale/en.js'></script>
|
||||
<style>
|
||||
body {
|
||||
margin:20px;
|
||||
}
|
||||
#foo, #bar {
|
||||
position:relative;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='foo'><input /></div>
|
||||
<div id='bar'><input /></div>
|
||||
<div id="iD"></div><script>
|
||||
var options = d3.range(0, 50).map(function(i) {
|
||||
return {
|
||||
value: i * 10,
|
||||
title: i * 10
|
||||
};
|
||||
});
|
||||
d3.select('#foo').call(d3.combobox()
|
||||
.data(function(selection, cb) {
|
||||
cb(options);
|
||||
}));
|
||||
d3.select('#bar').call(d3.combobox()
|
||||
.data(function(selection, cb) {
|
||||
cb(options);
|
||||
}));
|
||||
</script></body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-38039653-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</html>
|
||||
+44
-1
@@ -476,7 +476,7 @@ button[disabled] .icon.nearby { background-position: -340px -40px;}
|
||||
.icon-operation-circularize { background-position: -20px -140px;}
|
||||
.icon-operation-straighten { background-position: -40px -140px;}
|
||||
.icon-operation-split { background-position: -60px -140px;}
|
||||
.icon-operation-unjoin { background-position: -80px -140px;}
|
||||
.icon-operation-disconnect { background-position: -80px -140px;}
|
||||
.icon-operation-reverse { background-position: -100px -140px;}
|
||||
.icon-operation-move { background-position: -120px -140px;}
|
||||
.icon-operation-merge { background-position: -140px -140px;}
|
||||
@@ -1398,3 +1398,46 @@ a.success-action {
|
||||
.icon.icon-pre-text { margin-right: 0px;}
|
||||
.save .label, .apply .label, .cancel .label { display: block;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
div.combobox {
|
||||
width:155px;
|
||||
z-index: 9999;
|
||||
display: none;
|
||||
box-shadow: 0 5px 10px 0 rgba(0,0,0,.2);
|
||||
margin-top: -1px;
|
||||
background: white;
|
||||
max-height: 180px;
|
||||
overflow: auto;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.combobox a {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
border-top:1px solid #ccc;
|
||||
background-color: #fff;
|
||||
padding:1px 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.combobox a:hover,
|
||||
div.combobox a.selected {
|
||||
background: #e1e8ff;
|
||||
color: #154dff;
|
||||
}
|
||||
|
||||
div.combobox a:first-child {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
div.combobox-carat {
|
||||
cursor: pointer;
|
||||
padding:0 5px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
+1
-5
@@ -150,11 +150,6 @@ path.stroke {
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
path.stroke,
|
||||
path.casing {
|
||||
shape-rendering: optimizeSpeed;
|
||||
}
|
||||
|
||||
path.shadow {
|
||||
pointer-events: stroke;
|
||||
stroke-width: 10;
|
||||
@@ -725,6 +720,7 @@ text.point {
|
||||
}
|
||||
|
||||
/* Ensure drawing doesn't interact with area fills. */
|
||||
.mode-add-point .area,
|
||||
.mode-draw-line .area,
|
||||
.mode-draw-area .area,
|
||||
.mode-add-line .area,
|
||||
|
||||
+19
-11
@@ -76,15 +76,18 @@
|
||||
<script src='js/id/actions/add_entity.js'></script>
|
||||
<script src='js/id/actions/add_vertex.js'></script>
|
||||
<script src='js/id/actions/change_tags.js'></script>
|
||||
<script src='js/id/actions/delete_multiple.js'></script>
|
||||
<script src='js/id/actions/delete_node.js'></script>
|
||||
<script src="js/id/actions/delete_relation.js"></script>
|
||||
<script src="js/id/actions/delete_way.js"></script>
|
||||
<script src='js/id/actions/disconnect.js'></script>
|
||||
<script src='js/id/actions/join.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
<script src='js/id/actions/noop.js'></script>
|
||||
<script src='js/id/actions/reverse_way.js'></script>
|
||||
<script src='js/id/actions/split_way.js'></script>
|
||||
<script src='js/id/actions/unjoin_node.js'></script>
|
||||
<script src='js/id/actions/reverse.js'></script>
|
||||
<script src='js/id/actions/split.js'></script>
|
||||
|
||||
<script src='js/id/behavior.js'></script>
|
||||
<script src='js/id/behavior/add_way.js'></script>
|
||||
@@ -110,11 +113,13 @@
|
||||
<script src='js/id/operations.js'></script>
|
||||
<script src='js/id/operations/circularize.js'></script>
|
||||
<script src='js/id/operations/delete.js'></script>
|
||||
<script src='js/id/operations/disconnect.js'></script>
|
||||
<script src='js/id/operations/merge.js'></script>
|
||||
<script src='js/id/operations/move.js'></script>
|
||||
<script src='js/id/operations/reverse.js'></script>
|
||||
<script src='js/id/operations/split.js'></script>
|
||||
<script src='js/id/operations/unjoin.js'></script>
|
||||
|
||||
<script src='js/id/graph/difference.js'></script>
|
||||
<script src='js/id/graph/entity.js'></script>
|
||||
<script src='js/id/graph/graph.js'></script>
|
||||
<script src='js/id/graph/history.js'></script>
|
||||
@@ -122,9 +127,8 @@
|
||||
<script src='js/id/graph/relation.js'></script>
|
||||
<script src='js/id/graph/way.js'></script>
|
||||
|
||||
<script src='js/id/controller.js'></script>
|
||||
<script src='js/id/validate.js'></script>
|
||||
<script src='js/id/connection.js'></script>
|
||||
<script src='js/id/validate.js'></script>
|
||||
|
||||
<script src='locale/locale.js'></script>
|
||||
<script src='locale/en.js'></script>
|
||||
@@ -134,12 +138,15 @@
|
||||
locale.current = 'en';
|
||||
d3.json('keys.json', function(err, keys) {
|
||||
var id = iD();
|
||||
id.connection().keys(keys)
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
d3.select("#iD").call(id);
|
||||
});
|
||||
</script></body>
|
||||
|
||||
id.connection()
|
||||
.keys(keys)
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
|
||||
d3.select("#iD")
|
||||
.call(id.ui())
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-38039653-2']);
|
||||
@@ -150,4 +157,5 @@ _gaq.push(['_trackPageview']);
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+11
-3
@@ -16,8 +16,16 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="iD"></div><script>
|
||||
var id = iD();
|
||||
id.connection().url('http://api06.dev.openstreetmap.org');
|
||||
d3.select("#iD").call(id);
|
||||
locale.current = 'en';
|
||||
d3.json('keys.json', function(err, keys) {
|
||||
var id = iD();
|
||||
|
||||
id.connection()
|
||||
.keys(keys)
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
|
||||
d3.select("#iD")
|
||||
.call(id.ui())
|
||||
});
|
||||
</script></body>
|
||||
</html>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
iD.actions.Circularize = function(wayId, map) {
|
||||
iD.actions.Circularize = function(wayId, projection) {
|
||||
|
||||
var action = function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = graph.childNodes(way),
|
||||
tags = {}, key, role;
|
||||
nodes = _.uniq(graph.childNodes(way));
|
||||
|
||||
var points = nodes.map(function(n) {
|
||||
return map.projection(n.loc);
|
||||
return projection(n.loc);
|
||||
}),
|
||||
centroid = d3.geom.polygon(points).centroid(),
|
||||
radius = d3.median(points, function(p) {
|
||||
@@ -15,14 +14,12 @@ iD.actions.Circularize = function(wayId, map) {
|
||||
circular_nodes = [];
|
||||
|
||||
for (var i = 0; i < 12; i++) {
|
||||
circular_nodes.push(iD.Node({ loc: map.projection.invert([
|
||||
circular_nodes.push(iD.Node({ loc: projection.invert([
|
||||
centroid[0] + Math.cos((i / 12) * Math.PI * 2) * radius,
|
||||
centroid[1] + Math.sin((i / 12) * Math.PI * 2) * radius])
|
||||
}));
|
||||
}
|
||||
|
||||
circular_nodes.push(circular_nodes[0]);
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
if (graph.parentWays(nodes[i]).length > 1) {
|
||||
var closest, closest_dist = Infinity, dist;
|
||||
@@ -34,10 +31,6 @@ iD.actions.Circularize = function(wayId, map) {
|
||||
}
|
||||
}
|
||||
circular_nodes.splice(closest, 1, nodes[i]);
|
||||
if (closest === 0) circular_nodes.splice(circular_nodes.length - 1, 1, nodes[i]);
|
||||
else if (closest === circular_nodes.length - 1) circular_nodes.splice(0, 1, nodes[i]);
|
||||
} else {
|
||||
graph = graph.remove(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +38,18 @@ iD.actions.Circularize = function(wayId, map) {
|
||||
graph = graph.replace(circular_nodes[i]);
|
||||
}
|
||||
|
||||
return graph.replace(way.update({
|
||||
nodes: _.pluck(circular_nodes, 'id')
|
||||
}));
|
||||
var ids = _.pluck(circular_nodes, 'id'),
|
||||
difference = _.difference(_.uniq(way.nodes), ids);
|
||||
|
||||
ids.push(ids[0]);
|
||||
|
||||
graph = graph.replace(way.update({nodes: ids}));
|
||||
|
||||
for (i = 0; i < difference.length; i++) {
|
||||
graph = iD.actions.DeleteNode(difference[i])(graph);
|
||||
}
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
iD.actions.DeleteMultiple = function(ids) {
|
||||
return function(graph) {
|
||||
var actions = {
|
||||
way: iD.actions.DeleteWay,
|
||||
node: iD.actions.DeleteNode,
|
||||
relation: iD.actions.DeleteRelation
|
||||
};
|
||||
|
||||
ids.forEach(function (id) {
|
||||
graph = actions[graph.entity(id).type](id)(graph);
|
||||
});
|
||||
|
||||
return graph;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
|
||||
iD.actions.DeleteRelation = function(relationId) {
|
||||
return function(graph) {
|
||||
var relation = graph.entity(relationId);
|
||||
|
||||
graph.parentRelations(relation)
|
||||
.forEach(function(parent) {
|
||||
graph = graph.replace(parent.removeMember(relationId));
|
||||
});
|
||||
|
||||
return graph.remove(relation);
|
||||
};
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
// Unjoin the ways at the given node.
|
||||
// Disconect the ways at the given node.
|
||||
//
|
||||
// For testing convenience, accepts an ID to assign to the (first) new node.
|
||||
// Normally, this will be undefined and the way will automatically
|
||||
@@ -8,7 +8,7 @@
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
|
||||
//
|
||||
iD.actions.UnjoinNode = function(nodeId, newNodeId) {
|
||||
iD.actions.Disconnect = function(nodeId, newNodeId) {
|
||||
var action = function(graph) {
|
||||
if (!action.enabled(graph))
|
||||
return graph;
|
||||
@@ -0,0 +1,65 @@
|
||||
// Join ways at the end node they share.
|
||||
//
|
||||
// This is the inverse of `iD.actions.Split`.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
|
||||
//
|
||||
iD.actions.Join = function(idA, idB) {
|
||||
var action = function(graph) {
|
||||
var a = graph.entity(idA),
|
||||
b = graph.entity(idB),
|
||||
nodes, tags;
|
||||
|
||||
if (a.first() === b.first()) {
|
||||
// a <-- b ==> c
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
nodes = b.nodes.slice().reverse().concat(a.nodes.slice(1));
|
||||
|
||||
} else if (a.first() === b.last()) {
|
||||
// a <-- b <== c
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
nodes = b.nodes.concat(a.nodes.slice(1));
|
||||
|
||||
} else if (a.last() === b.first()) {
|
||||
// a --> b ==> c
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
nodes = a.nodes.concat(b.nodes.slice(1));
|
||||
|
||||
} else if (a.last() === b.last()) {
|
||||
// a --> b <== c
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
nodes = a.nodes.concat(b.nodes.slice().reverse().slice(1));
|
||||
}
|
||||
|
||||
graph.parentRelations(b)
|
||||
.forEach(function (parent) {
|
||||
var memberA = parent.memberById(idA),
|
||||
memberB = parent.memberById(idB);
|
||||
if (!memberA) {
|
||||
graph = graph.replace(parent.addMember({id: idA, role: memberB.role}));
|
||||
}
|
||||
});
|
||||
|
||||
graph = graph.replace(a.mergeTags(b.tags).update({nodes: nodes}));
|
||||
graph = iD.actions.DeleteWay(idB)(graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
var a = graph.entity(idA),
|
||||
b = graph.entity(idB);
|
||||
return a.first() === b.first() ||
|
||||
a.first() === b.last() ||
|
||||
a.last() === b.first() ||
|
||||
a.last() === b.last();
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -27,7 +27,7 @@
|
||||
http://wiki.openstreetmap.org/wiki/Route#Members
|
||||
http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
|
||||
*/
|
||||
iD.actions.ReverseWay = function(wayId) {
|
||||
iD.actions.Reverse = function(wayId) {
|
||||
var replacements = [
|
||||
[/:right$/, ':left'], [/:left$/, ':right'],
|
||||
[/:forward$/, ':backward'], [/:backward$/, ':forward']
|
||||
@@ -1,5 +1,7 @@
|
||||
// Split a way at the given node.
|
||||
//
|
||||
// This is the inverse of `iD.actions.Join`.
|
||||
//
|
||||
// For testing convenience, accepts an ID to assign to the new way.
|
||||
// Normally, this will be undefined and the way will automatically
|
||||
// be assigned a new ID.
|
||||
@@ -7,7 +9,7 @@
|
||||
// Reference:
|
||||
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
|
||||
//
|
||||
iD.actions.SplitWay = function(nodeId, newWayId) {
|
||||
iD.actions.Split = function(nodeId, newWayId) {
|
||||
function candidateWays(graph) {
|
||||
var node = graph.entity(nodeId),
|
||||
parents = graph.parentWays(node);
|
||||
@@ -1,8 +1,6 @@
|
||||
iD.behavior.AddWay = function(mode) {
|
||||
var map = mode.map,
|
||||
controller = mode.controller,
|
||||
event = d3.dispatch('start', 'startFromWay', 'startFromNode', 'startFromMidpoint'),
|
||||
draw = iD.behavior.Draw(map);
|
||||
iD.behavior.AddWay = function(context) {
|
||||
var event = d3.dispatch('start', 'startFromWay', 'startFromNode', 'startFromMidpoint'),
|
||||
draw = iD.behavior.Draw(context);
|
||||
|
||||
var addWay = function(surface) {
|
||||
draw.on('click', event.start)
|
||||
@@ -12,7 +10,8 @@ iD.behavior.AddWay = function(mode) {
|
||||
.on('cancel', addWay.cancel)
|
||||
.on('finish', addWay.cancel);
|
||||
|
||||
map.fastEnable(false)
|
||||
context.map()
|
||||
.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
@@ -20,19 +19,20 @@ iD.behavior.AddWay = function(mode) {
|
||||
};
|
||||
|
||||
addWay.off = function(surface) {
|
||||
map.fastEnable(true)
|
||||
context.map()
|
||||
.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
context.map().dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(draw.off);
|
||||
};
|
||||
|
||||
addWay.cancel = function() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
};
|
||||
|
||||
return d3.rebind(addWay, event, 'on');
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
iD.behavior.DragMidpoint = function(mode) {
|
||||
var history = mode.history,
|
||||
projection = mode.map.projection;
|
||||
|
||||
iD.behavior.DragMidpoint = function(context) {
|
||||
var behavior = iD.behavior.drag()
|
||||
.delegate(".midpoint")
|
||||
.origin(function(d) {
|
||||
return projection(d.loc);
|
||||
return context.projection(d.loc);
|
||||
})
|
||||
.on('start', function(d) {
|
||||
var node = iD.Node();
|
||||
|
||||
history.perform(iD.actions.AddMidpoint(d, node));
|
||||
context.perform(iD.actions.AddMidpoint(d, node));
|
||||
|
||||
var vertex = d3.selectAll('.vertex')
|
||||
.filter(function(data) { return data.id === node.id; });
|
||||
@@ -19,11 +16,11 @@ iD.behavior.DragMidpoint = function(mode) {
|
||||
})
|
||||
.on('move', function(d) {
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
history.replace(
|
||||
iD.actions.MoveNode(d.id, projection.invert(d3.event.point)));
|
||||
context.replace(
|
||||
iD.actions.MoveNode(d.id, context.projection.invert(d3.event.point)));
|
||||
})
|
||||
.on('end', function() {
|
||||
history.replace(
|
||||
context.replace(
|
||||
iD.actions.Noop(),
|
||||
t('operations.add.annotation.vertex'));
|
||||
});
|
||||
|
||||
+10
-12
@@ -1,8 +1,6 @@
|
||||
iD.behavior.DragNode = function(mode) {
|
||||
var history = mode.history,
|
||||
size = mode.map.size(),
|
||||
nudgeInterval,
|
||||
projection = mode.map.projection;
|
||||
iD.behavior.DragNode = function(context) {
|
||||
var size = context.map().size(),
|
||||
nudgeInterval;
|
||||
|
||||
function edge(point) {
|
||||
var pad = [30, 100, 30, 100];
|
||||
@@ -16,7 +14,7 @@ iD.behavior.DragNode = function(mode) {
|
||||
function startNudge(nudge) {
|
||||
if (nudgeInterval) window.clearInterval(nudgeInterval);
|
||||
nudgeInterval = window.setInterval(function() {
|
||||
mode.map.pan(nudge).redraw();
|
||||
context.map().pan(nudge).redraw();
|
||||
}, 50);
|
||||
}
|
||||
|
||||
@@ -26,16 +24,16 @@ iD.behavior.DragNode = function(mode) {
|
||||
}
|
||||
|
||||
function annotation(entity) {
|
||||
return t('operations.move.annotation.' + entity.geometry(mode.history.graph()));
|
||||
return t('operations.move.annotation.' + entity.geometry(context.graph()));
|
||||
}
|
||||
|
||||
return iD.behavior.drag()
|
||||
.delegate(".node")
|
||||
.origin(function(entity) {
|
||||
return projection(entity.loc);
|
||||
return context.projection(entity.loc);
|
||||
})
|
||||
.on('start', function() {
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.Noop());
|
||||
})
|
||||
.on('move', function(entity) {
|
||||
@@ -45,13 +43,13 @@ iD.behavior.DragNode = function(mode) {
|
||||
if (nudge) startNudge(nudge);
|
||||
else stopNudge();
|
||||
|
||||
history.replace(
|
||||
iD.actions.MoveNode(entity.id, projection.invert(d3.event.point)),
|
||||
context.replace(
|
||||
iD.actions.MoveNode(entity.id, context.projection.invert(d3.event.point)),
|
||||
annotation(entity));
|
||||
})
|
||||
.on('end', function(entity) {
|
||||
stopNudge();
|
||||
history.replace(
|
||||
context.replace(
|
||||
iD.actions.Noop(),
|
||||
annotation(entity));
|
||||
});
|
||||
|
||||
+12
-12
@@ -1,7 +1,8 @@
|
||||
iD.behavior.Draw = function(map) {
|
||||
iD.behavior.Draw = function(context) {
|
||||
var event = d3.dispatch('move', 'click', 'clickWay', 'clickNode', 'clickMidpoint', 'undo', 'cancel', 'finish'),
|
||||
keybinding = d3.keybinding('draw'),
|
||||
down, surface, hover;
|
||||
hover = iD.behavior.Hover(),
|
||||
down;
|
||||
|
||||
function datum() {
|
||||
if (d3.event.altKey) {
|
||||
@@ -28,7 +29,7 @@ iD.behavior.Draw = function(map) {
|
||||
function click() {
|
||||
var d = datum();
|
||||
if (d.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(d, d3.mouse(map.surface.node()), map);
|
||||
var choice = iD.geo.chooseIndex(d, d3.mouse(context.surface().node()), context);
|
||||
event.clickWay(d, choice.loc, choice.index);
|
||||
|
||||
} else if (d.type === 'node') {
|
||||
@@ -38,19 +39,19 @@ iD.behavior.Draw = function(map) {
|
||||
event.clickMidpoint(d);
|
||||
|
||||
} else {
|
||||
event.click(map.mouseCoordinates());
|
||||
event.click(context.map().mouseCoordinates());
|
||||
}
|
||||
}
|
||||
|
||||
function keydown() {
|
||||
if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
|
||||
surface.call(hover.off);
|
||||
context.uninstall(hover);
|
||||
}
|
||||
}
|
||||
|
||||
function keyup() {
|
||||
if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
|
||||
surface.call(hover);
|
||||
context.install(hover);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +71,7 @@ iD.behavior.Draw = function(map) {
|
||||
}
|
||||
|
||||
function draw(selection) {
|
||||
surface = selection;
|
||||
hover = iD.behavior.Hover();
|
||||
context.install(hover);
|
||||
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
@@ -83,8 +83,7 @@ iD.behavior.Draw = function(map) {
|
||||
.on('mousedown.draw', mousedown)
|
||||
.on('mouseup.draw', mouseup)
|
||||
.on('mousemove.draw', mousemove)
|
||||
.on('click.draw', click)
|
||||
.call(hover);
|
||||
.on('click.draw', click);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding)
|
||||
@@ -95,12 +94,13 @@ iD.behavior.Draw = function(map) {
|
||||
}
|
||||
|
||||
draw.off = function(selection) {
|
||||
context.uninstall(hover);
|
||||
|
||||
selection
|
||||
.on('mousedown.draw', null)
|
||||
.on('mouseup.draw', null)
|
||||
.on('mousemove.draw', null)
|
||||
.on('click.draw', null)
|
||||
.call(hover.off);
|
||||
.on('click.draw', null);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding.off)
|
||||
|
||||
+40
-36
@@ -1,35 +1,35 @@
|
||||
iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
way = history.graph().entity(wayId),
|
||||
iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) {
|
||||
var way = context.entity(wayId),
|
||||
finished = false,
|
||||
annotation = t((way.isDegenerate() ?
|
||||
'operations.start.annotation.' :
|
||||
'operations.continue.annotation.') + way.geometry(history.graph())),
|
||||
draw = iD.behavior.Draw(map);
|
||||
'operations.continue.annotation.') + context.geometry(wayId)),
|
||||
draw = iD.behavior.Draw(context);
|
||||
|
||||
var node = iD.Node({loc: map.mouseCoordinates()}),
|
||||
var node = iD.Node({loc: context.map().mouseCoordinates()}),
|
||||
nodeId = node.id;
|
||||
|
||||
history[way.isDegenerate() ? 'replace' : 'perform'](
|
||||
context[way.isDegenerate() ? 'replace' : 'perform'](
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddVertex(wayId, node.id, index));
|
||||
|
||||
function move(datum) {
|
||||
var loc = map.mouseCoordinates();
|
||||
var loc = context.map().mouseCoordinates();
|
||||
|
||||
if (datum.type === 'node' || datum.type === 'midpoint') {
|
||||
if (datum.type === 'node') {
|
||||
loc = datum.loc;
|
||||
} else if (datum.type === 'way') {
|
||||
loc = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map).loc;
|
||||
} else if (datum.type === 'midpoint' || datum.type === 'way') {
|
||||
var way = datum.type === 'way' ?
|
||||
datum :
|
||||
context.entity(datum.ways[0].id);
|
||||
loc = iD.geo.chooseIndex(way, d3.mouse(context.surface().node()), context).loc;
|
||||
}
|
||||
|
||||
history.replace(iD.actions.MoveNode(nodeId, loc));
|
||||
context.replace(iD.actions.MoveNode(nodeId, loc));
|
||||
}
|
||||
|
||||
function undone() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
var drawWay = function(surface) {
|
||||
@@ -38,11 +38,12 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
.on('clickWay', drawWay.addWay)
|
||||
.on('clickNode', drawWay.addNode)
|
||||
.on('clickMidpoint', drawWay.addMidpoint)
|
||||
.on('undo', history.undo)
|
||||
.on('undo', context.undo)
|
||||
.on('cancel', drawWay.cancel)
|
||||
.on('finish', drawWay.finish);
|
||||
|
||||
map.fastEnable(false)
|
||||
context.map()
|
||||
.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
@@ -51,26 +52,29 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
.filter(function (d) { return d.id === wayId || d.id === nodeId; })
|
||||
.classed('active', true);
|
||||
|
||||
history.on('undone.draw', undone);
|
||||
context.history()
|
||||
.on('undone.draw', undone);
|
||||
};
|
||||
|
||||
drawWay.off = function(surface) {
|
||||
if (!finished)
|
||||
history.pop();
|
||||
context.pop();
|
||||
|
||||
map.fastEnable(true)
|
||||
context.map()
|
||||
.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
context.map().dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(draw.off)
|
||||
.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
history.on('undone.draw', null);
|
||||
context.history()
|
||||
.on('undone.draw', null);
|
||||
};
|
||||
|
||||
function ReplaceTemporaryNode(newNode) {
|
||||
@@ -85,74 +89,74 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
drawWay.add = function(loc) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.replace(
|
||||
context.replace(
|
||||
iD.actions.AddEntity(newNode),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing way.
|
||||
drawWay.addWay = function(way, loc, wayIndex) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(newNode),
|
||||
iD.actions.AddVertex(way.id, newNode.id, wayIndex),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing node and continue drawing.
|
||||
drawWay.addNode = function(node) {
|
||||
history.perform(
|
||||
context.perform(
|
||||
ReplaceTemporaryNode(node),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Add a midpoint, connect the way to it, and continue drawing.
|
||||
drawWay.addMidpoint = function(midpoint) {
|
||||
var node = iD.Node();
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
ReplaceTemporaryNode(node),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Finish the draw operation, removing the temporary node. If the way has enough
|
||||
// nodes to be valid, it's selected. Otherwise, return to browse mode.
|
||||
drawWay.finish = function() {
|
||||
history.pop();
|
||||
context.pop();
|
||||
finished = true;
|
||||
|
||||
var way = history.graph().entity(wayId);
|
||||
var way = context.entity(wayId);
|
||||
if (way) {
|
||||
controller.enter(iD.modes.Select([way.id], true));
|
||||
context.enter(iD.modes.Select(context, [way.id], true));
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel the draw operation and return to browse, deleting everything drawn.
|
||||
drawWay.cancel = function() {
|
||||
history.perform(
|
||||
context.perform(
|
||||
d3.functor(baseGraph),
|
||||
t('operations.cancel_draw.annotation'));
|
||||
|
||||
finished = true;
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
};
|
||||
|
||||
return d3.rebind(drawWay, event, 'on');
|
||||
|
||||
+15
-14
@@ -1,4 +1,4 @@
|
||||
iD.behavior.Hash = function(controller, map) {
|
||||
iD.behavior.Hash = function(context) {
|
||||
var s0 = null, // cached location.hash
|
||||
lat = 90 - 1e-8; // allowable latitude range
|
||||
|
||||
@@ -27,13 +27,13 @@ iD.behavior.Hash = function(controller, map) {
|
||||
};
|
||||
|
||||
var move = _.throttle(function() {
|
||||
var s1 = formatter(map);
|
||||
var s1 = formatter(context.map());
|
||||
if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
|
||||
}, 100);
|
||||
|
||||
function hashchange() {
|
||||
if (location.hash === s0) return; // ignore spurious hashchange events
|
||||
if (parser(map, (s0 = location.hash).substring(1))) {
|
||||
if (parser(context.map(), (s0 = location.hash).substring(1))) {
|
||||
move(); // replace bogus hash
|
||||
}
|
||||
}
|
||||
@@ -42,24 +42,24 @@ iD.behavior.Hash = function(controller, map) {
|
||||
// do so before any features are loaded. thus wait for the feature to
|
||||
// be loaded and then select
|
||||
function willselect(id) {
|
||||
map.on('drawn.hash', function() {
|
||||
var entity = map.history().graph().entity(id);
|
||||
if (entity === undefined) return;
|
||||
else selectoff();
|
||||
controller.enter(iD.modes.Select([entity.id]));
|
||||
map.on('drawn.hash', null);
|
||||
context.map().on('drawn.hash', function() {
|
||||
if (!context.entity(id)) return;
|
||||
selectoff();
|
||||
context.enter(iD.modes.Select(context, [id]));
|
||||
});
|
||||
controller.on('enter.hash', function() {
|
||||
if (controller.mode.id !== 'browse') selectoff();
|
||||
|
||||
context.on('enter.hash', function() {
|
||||
if (context.mode().id !== 'browse') selectoff();
|
||||
});
|
||||
}
|
||||
|
||||
function selectoff() {
|
||||
map.on('drawn.hash', null);
|
||||
context.map().on('drawn.hash', null);
|
||||
}
|
||||
|
||||
function hash() {
|
||||
map.on('move.hash', move);
|
||||
context.map()
|
||||
.on('move.hash', move);
|
||||
|
||||
d3.select(window)
|
||||
.on('hashchange.hash', hashchange);
|
||||
@@ -75,7 +75,8 @@ iD.behavior.Hash = function(controller, map) {
|
||||
}
|
||||
|
||||
hash.off = function() {
|
||||
map.on('move.hash', null);
|
||||
context.map()
|
||||
.on('move.hash', null);
|
||||
|
||||
d3.select(window)
|
||||
.on('hashchange.hash', null);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
iD.behavior.Select = function(mode) {
|
||||
var controller = mode.controller;
|
||||
|
||||
iD.behavior.Select = function(context) {
|
||||
function click() {
|
||||
var datum = d3.select(d3.event.target).datum();
|
||||
if (datum instanceof iD.Entity) {
|
||||
controller.enter(iD.modes.Select([datum.id]));
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
if (d3.event.shiftKey) {
|
||||
context.enter(iD.modes.Select(context, context.selection().concat([datum.id])));
|
||||
} else {
|
||||
context.enter(iD.modes.Select(context, [datum.id]));
|
||||
}
|
||||
} else if (!d3.event.shiftKey) {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-10
@@ -1,14 +1,13 @@
|
||||
iD.Connection = function() {
|
||||
iD.Connection = function(context) {
|
||||
|
||||
var event = d3.dispatch('auth', 'load'),
|
||||
url = 'http://www.openstreetmap.org',
|
||||
connection = {},
|
||||
user = {},
|
||||
version,
|
||||
keys,
|
||||
inflight = {},
|
||||
loadedTiles = {},
|
||||
oauth = iD.OAuth().url(url);
|
||||
oauth = iD.OAuth(context).url(url);
|
||||
|
||||
function changesetUrl(changesetId) {
|
||||
return url + '/browse/changeset/' + changesetId;
|
||||
@@ -186,7 +185,7 @@ iD.Connection = function() {
|
||||
content: JXON.stringify(connection.changesetJXON({
|
||||
imagery_used: imagery_used.join(';'),
|
||||
comment: comment,
|
||||
created_by: 'iD ' + (version || '')
|
||||
created_by: 'iD ' + iD.version
|
||||
}))
|
||||
}, function (err, changeset_id) {
|
||||
if (err) return callback(err);
|
||||
@@ -322,12 +321,6 @@ iD.Connection = function() {
|
||||
return oauth.authenticate(done);
|
||||
};
|
||||
|
||||
connection.version = function(_) {
|
||||
if (!arguments.length) return version;
|
||||
version = _;
|
||||
return connection;
|
||||
};
|
||||
|
||||
connection.bboxFromAPI = bboxFromAPI;
|
||||
connection.changesetUrl = changesetUrl;
|
||||
connection.loadFromURL = loadFromURL;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// A controller holds a single action at a time and calls `.enter` and `.exit`
|
||||
// to bind and unbind actions.
|
||||
iD.Controller = function(map, history) {
|
||||
var event = d3.dispatch('enter', 'exit');
|
||||
var controller = { mode: null };
|
||||
|
||||
controller.enter = function(mode) {
|
||||
mode.controller = controller;
|
||||
mode.history = history;
|
||||
mode.map = map;
|
||||
|
||||
if (controller.mode) {
|
||||
controller.mode.exit();
|
||||
event.exit(controller.mode);
|
||||
}
|
||||
|
||||
mode.enter();
|
||||
controller.mode = mode;
|
||||
event.enter(mode);
|
||||
};
|
||||
|
||||
return d3.rebind(controller, event, 'on');
|
||||
};
|
||||
+3
-3
@@ -14,11 +14,11 @@ iD.geo.dist = function(a, b) {
|
||||
Math.pow(a[1] - b[1], 2));
|
||||
};
|
||||
|
||||
iD.geo.chooseIndex = function(way, point, map) {
|
||||
iD.geo.chooseIndex = function(way, point, context) {
|
||||
var dist = iD.geo.dist,
|
||||
graph = map.history().graph(),
|
||||
graph = context.graph(),
|
||||
nodes = graph.childNodes(way),
|
||||
projNodes = nodes.map(function(n) { return map.projection(n.loc); });
|
||||
projNodes = nodes.map(function(n) { return context.projection(n.loc); });
|
||||
|
||||
for (var i = 0, changes = []; i < projNodes.length - 1; i++) {
|
||||
changes[i] =
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
iD.Difference represents the difference between two graphs.
|
||||
It knows how to calculate the set of entities that were
|
||||
created, modified, or deleted, and also contains the logic
|
||||
for recursively extending a difference to the complete set
|
||||
of entities that will require a redraw, taking into account
|
||||
child and parent relationships.
|
||||
*/
|
||||
iD.Difference = function (base, head) {
|
||||
var changes = {}, length = 0;
|
||||
|
||||
_.each(head.entities, function(h, id) {
|
||||
var b = base.entities[id];
|
||||
if (h !== b) {
|
||||
changes[id] = {base: b, head: h};
|
||||
length++;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(base.entities, function(b, id) {
|
||||
var h = head.entities[id];
|
||||
if (!changes[id] && h !== b) {
|
||||
changes[id] = {base: b, head: h};
|
||||
length++;
|
||||
}
|
||||
});
|
||||
|
||||
var difference = {};
|
||||
|
||||
difference.length = function () {
|
||||
return length;
|
||||
};
|
||||
|
||||
difference.changes = function() {
|
||||
return changes;
|
||||
};
|
||||
|
||||
difference.extantIDs = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change, id) {
|
||||
if (change.head) result.push(id);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.modified = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change) {
|
||||
if (change.base && change.head) result.push(change.head);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.created = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change) {
|
||||
if (!change.base && change.head) result.push(change.head);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.deleted = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change) {
|
||||
if (change.base && !change.head) result.push(change.base);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.complete = function(extent) {
|
||||
var result = {}, id, change;
|
||||
|
||||
function addParents(parents) {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
|
||||
if (parent.id in result)
|
||||
continue;
|
||||
|
||||
result[parent.id] = parent;
|
||||
addParents(head.parentRelations(parent));
|
||||
}
|
||||
}
|
||||
|
||||
for (id in changes) {
|
||||
change = changes[id];
|
||||
|
||||
var h = change.head,
|
||||
b = change.base,
|
||||
entity = h || b;
|
||||
|
||||
if (extent && !entity.intersects(extent, h ? head : base))
|
||||
continue;
|
||||
|
||||
result[id] = h;
|
||||
|
||||
if (entity.type === 'way') {
|
||||
var nh = h ? h.nodes : [],
|
||||
nb = b ? b.nodes : [],
|
||||
diff;
|
||||
|
||||
diff = _.difference(nh, nb);
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
result[diff[i]] = head.entity(diff[i]);
|
||||
}
|
||||
|
||||
diff = _.difference(nb, nh);
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
result[diff[i]] = head.entity(diff[i]);
|
||||
}
|
||||
}
|
||||
|
||||
addParents(head.parentWays(entity));
|
||||
addParents(head.parentRelations(entity));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return difference;
|
||||
};
|
||||
+13
-8
@@ -43,7 +43,6 @@ iD.Entity.prototype = {
|
||||
|
||||
if (!this.id && this.type) {
|
||||
this.id = iD.Entity.id(this.type);
|
||||
this._updated = true;
|
||||
}
|
||||
|
||||
if (iD.debug) {
|
||||
@@ -63,15 +62,21 @@ iD.Entity.prototype = {
|
||||
},
|
||||
|
||||
update: function(attrs) {
|
||||
return iD.Entity(this, attrs, {_updated: true});
|
||||
return iD.Entity(this, attrs);
|
||||
},
|
||||
|
||||
created: function() {
|
||||
return this._updated && this.osmId().charAt(0) === '-';
|
||||
},
|
||||
|
||||
modified: function() {
|
||||
return this._updated && this.osmId().charAt(0) !== '-';
|
||||
mergeTags: function(tags) {
|
||||
var merged = _.clone(this.tags);
|
||||
for (var k in tags) {
|
||||
var t1 = merged[k],
|
||||
t2 = tags[k];
|
||||
if (t1 && t1 !== t2) {
|
||||
merged[k] = t1 + "; " + t2;
|
||||
} else {
|
||||
merged[k] = t2;
|
||||
}
|
||||
}
|
||||
return this.update({tags: merged});
|
||||
},
|
||||
|
||||
intersects: function(extent, resolver) {
|
||||
|
||||
@@ -232,65 +232,5 @@ iD.Graph.prototype = {
|
||||
}
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
difference: function (graph) {
|
||||
|
||||
function diff(a, b) {
|
||||
var result = [],
|
||||
keys = Object.keys(a.entities),
|
||||
entity, oldentity, id, i;
|
||||
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
id = keys[i];
|
||||
entity = a.entities[id];
|
||||
oldentity = b.entities[id];
|
||||
if (entity !== oldentity) {
|
||||
|
||||
// maybe adding affected children better belongs in renderer/map.js?
|
||||
if (entity && entity.type === 'way' &&
|
||||
oldentity && oldentity.type === 'way') {
|
||||
result = result
|
||||
.concat(_.difference(entity.nodes, oldentity.nodes))
|
||||
.concat(_.difference(oldentity.nodes, entity.nodes));
|
||||
|
||||
} else if (entity && entity.type === 'way') {
|
||||
result = result.concat(entity.nodes);
|
||||
|
||||
} else if (oldentity && oldentity.type === 'way') {
|
||||
result = result.concat(oldentity.nodes);
|
||||
}
|
||||
|
||||
result.push(id);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return _.unique(diff(this, graph).concat(diff(graph, this)).sort());
|
||||
},
|
||||
|
||||
modified: function() {
|
||||
var result = [], base = this.base().entities;
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && base[id]) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
created: function() {
|
||||
var result = [], base = this.base().entities;
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && !base[id]) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
deleted: function() {
|
||||
var result = [], base = this.base().entities;
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (!entity && base[id]) result.push(id);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
+23
-23
@@ -21,7 +21,9 @@ iD.History = function() {
|
||||
}
|
||||
|
||||
function change(previous) {
|
||||
dispatch.change(history.graph().difference(previous));
|
||||
var difference = iD.Difference(previous, history.graph());
|
||||
dispatch.change(difference);
|
||||
return difference;
|
||||
}
|
||||
|
||||
var history = {
|
||||
@@ -33,6 +35,8 @@ iD.History = function() {
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
stack[i].graph.rebase(entities);
|
||||
}
|
||||
|
||||
dispatch.change();
|
||||
},
|
||||
|
||||
perform: function () {
|
||||
@@ -42,7 +46,7 @@ iD.History = function() {
|
||||
stack.push(perform(arguments));
|
||||
index++;
|
||||
|
||||
change(previous);
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
replace: function () {
|
||||
@@ -51,7 +55,7 @@ iD.History = function() {
|
||||
// assert(index == stack.length - 1)
|
||||
stack[index] = perform(arguments);
|
||||
|
||||
change(previous);
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
pop: function () {
|
||||
@@ -60,7 +64,7 @@ iD.History = function() {
|
||||
if (index > 0) {
|
||||
index--;
|
||||
stack.pop();
|
||||
change(previous);
|
||||
return change(previous);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -80,7 +84,7 @@ iD.History = function() {
|
||||
}
|
||||
|
||||
dispatch.undone();
|
||||
change(previous);
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
redo: function () {
|
||||
@@ -92,7 +96,7 @@ iD.History = function() {
|
||||
}
|
||||
|
||||
dispatch.redone();
|
||||
change(previous);
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
undoAnnotation: function () {
|
||||
@@ -111,31 +115,27 @@ iD.History = function() {
|
||||
}
|
||||
},
|
||||
|
||||
changes: function () {
|
||||
var initial = stack[0].graph,
|
||||
current = stack[index].graph;
|
||||
difference: function () {
|
||||
var base = stack[0].graph,
|
||||
head = stack[index].graph;
|
||||
return iD.Difference(base, head);
|
||||
},
|
||||
|
||||
changes: function () {
|
||||
var difference = history.difference();
|
||||
return {
|
||||
modified: current.modified().map(function (id) {
|
||||
return current.entity(id);
|
||||
}),
|
||||
created: current.created().map(function (id) {
|
||||
return current.entity(id);
|
||||
}),
|
||||
deleted: current.deleted().map(function (id) {
|
||||
return initial.entity(id);
|
||||
})
|
||||
};
|
||||
modified: difference.modified(),
|
||||
created: difference.created(),
|
||||
deleted: difference.deleted()
|
||||
}
|
||||
},
|
||||
|
||||
hasChanges: function() {
|
||||
return !!this.numChanges();
|
||||
return this.difference().length() > 0;
|
||||
},
|
||||
|
||||
numChanges: function() {
|
||||
return d3.sum(d3.values(this.changes()).map(function(c) {
|
||||
return c.length;
|
||||
}));
|
||||
return this.difference().length();
|
||||
},
|
||||
|
||||
imagery_used: function(source) {
|
||||
|
||||
+89
-266
@@ -1,280 +1,103 @@
|
||||
window.iD = function(container) {
|
||||
// the reported, displayed version of iD.
|
||||
var version = '0.0.0-alpha1';
|
||||
|
||||
var connection = iD.Connection()
|
||||
.version(version),
|
||||
window.iD = function () {
|
||||
var context = {},
|
||||
history = iD.History(),
|
||||
map = iD.Map()
|
||||
.connection(connection)
|
||||
.history(history),
|
||||
controller = iD.Controller(map, history);
|
||||
storage = localStorage || {},
|
||||
dispatch = d3.dispatch('enter', 'exit'),
|
||||
mode,
|
||||
container,
|
||||
ui = iD.ui(context),
|
||||
map = iD.Map(context);
|
||||
|
||||
map.background.source(iD.BackgroundSource.Bing);
|
||||
|
||||
function editor(container) {
|
||||
if (!iD.supported()) {
|
||||
container.html('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.')
|
||||
.style('text-align:center;font-style:italic;');
|
||||
return;
|
||||
}
|
||||
|
||||
function hintprefix(x, y) {
|
||||
return '<span>' + y + '</span>' + '<div class="keyhint-wrap"><span class="keyhint"> ' + x + '</span></div>';
|
||||
}
|
||||
|
||||
var m = container.append('div')
|
||||
.attr('id', 'map')
|
||||
.call(map);
|
||||
|
||||
var bar = container.append('div')
|
||||
.attr('id', 'bar')
|
||||
.attr('class','pad1 fillD');
|
||||
|
||||
var limiter = bar.append('div')
|
||||
.attr('class', 'limiter');
|
||||
|
||||
var buttons_joined = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col4');
|
||||
|
||||
var buttons = buttons_joined.selectAll('button.add-button')
|
||||
.data([iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()])
|
||||
.enter().append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function (mode) { return mode.title + ' add-button col3'; })
|
||||
.call(bootstrap.tooltip().placement('bottom').html(true))
|
||||
.attr('data-original-title', function (mode) {
|
||||
return hintprefix(mode.key, mode.description);
|
||||
})
|
||||
.on('click.editor', function (mode) { controller.enter(mode); });
|
||||
|
||||
function disableTooHigh() {
|
||||
if (map.editable()) {
|
||||
notice.message(false);
|
||||
buttons.attr('disabled', null);
|
||||
} else {
|
||||
buttons.attr('disabled', 'disabled');
|
||||
notice.message(true);
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
var notice = iD.ui.notice(limiter)
|
||||
.message(false)
|
||||
.on('zoom', function() { map.zoom(16); });
|
||||
|
||||
map.on('move.editor', _.debounce(function() {
|
||||
disableTooHigh();
|
||||
contributors.call(iD.ui.contributors(map));
|
||||
}, 500));
|
||||
|
||||
buttons.append('span')
|
||||
.attr('class', function(d) {
|
||||
return d.id + ' icon icon-pre-text';
|
||||
});
|
||||
|
||||
buttons.append('span').attr('class', 'label').text(function (mode) { return mode.title; });
|
||||
|
||||
controller.on('enter.editor', function (entered) {
|
||||
buttons.classed('active', function (mode) { return entered.button === mode.button; });
|
||||
container.classed("mode-" + entered.id, true);
|
||||
});
|
||||
|
||||
controller.on('exit.editor', function (exited) {
|
||||
container.classed("mode-" + exited.id, false);
|
||||
});
|
||||
|
||||
var undo_buttons = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col1'),
|
||||
undo_tooltip = bootstrap.tooltip().placement('bottom').html(true);
|
||||
|
||||
undo_buttons.append('button')
|
||||
.attr({ id: 'undo', 'class': 'col6' })
|
||||
.property('disabled', true)
|
||||
.html("<span class='undo icon'></span><small></small>")
|
||||
.on('click.editor', history.undo)
|
||||
.call(undo_tooltip);
|
||||
|
||||
undo_buttons.append('button')
|
||||
.attr({ id: 'redo', 'class': 'col6' })
|
||||
.property('disabled', true)
|
||||
.html("<span class='redo icon'><small></small>")
|
||||
.on('click.editor', history.redo)
|
||||
.call(undo_tooltip);
|
||||
|
||||
var save_button = limiter.append('div').attr('class','button-wrap col1').append('button')
|
||||
.attr('class', 'save col12')
|
||||
.call(iD.ui.save().map(map).controller(controller));
|
||||
|
||||
var zoom = container.append('div')
|
||||
.attr('class', 'zoombuttons map-control')
|
||||
.selectAll('button')
|
||||
.data([['zoom-in', '+', map.zoomIn, 'Zoom In'], ['zoom-out', '-', map.zoomOut, 'Zoom Out']])
|
||||
.enter()
|
||||
.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function(d) { return d[0]; })
|
||||
.attr('title', function(d) { return d[3]; })
|
||||
.on('click.editor', function(d) { return d[2](); })
|
||||
.append('span')
|
||||
.attr('class', function(d) {
|
||||
return d[0] + ' icon';
|
||||
});
|
||||
|
||||
if (navigator.geolocation) {
|
||||
container.append('div')
|
||||
.call(iD.ui.geolocate(map));
|
||||
}
|
||||
|
||||
var gc = container.append('div').attr('class', 'geocode-control map-control')
|
||||
.call(iD.ui.geocoder().map(map));
|
||||
|
||||
container.append('div').attr('class', 'map-control layerswitcher-control')
|
||||
.call(iD.ui.layerswitcher(map));
|
||||
|
||||
container.append('div')
|
||||
.style('display', 'none')
|
||||
.attr('class', 'inspector-wrap fr col5');
|
||||
|
||||
var about = container.append('div')
|
||||
.attr('class','col12 about-block fillD pad1');
|
||||
|
||||
about.append('div')
|
||||
.attr('class', 'user-container')
|
||||
.append('div')
|
||||
.attr('class', 'hello');
|
||||
|
||||
var aboutList = about.append('ul')
|
||||
.attr('id','about')
|
||||
.attr('class','link-list');
|
||||
|
||||
var linkList = aboutList.append('ul')
|
||||
.attr('id','about')
|
||||
.attr('class','pad1 fillD about-block link-list');
|
||||
linkList.append('li').append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://github.com/systemed/iD').text(version);
|
||||
linkList.append('li').append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://github.com/systemed/iD/issues').text('report a bug');
|
||||
|
||||
var imagery = linkList.append('li').attr('id', 'attribution');
|
||||
imagery.append('span').text('imagery');
|
||||
imagery.append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://opengeodata.org/microsoft-imagery-details').text(' provided by bing');
|
||||
|
||||
linkList.append('li').attr('class', 'source-switch').append('a').attr('href', '#')
|
||||
.text('dev')
|
||||
.on('click.editor', function() {
|
||||
d3.event.preventDefault();
|
||||
if (d3.select(this).classed('live')) {
|
||||
map.flush().connection()
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
d3.select(this).text('dev').classed('live', false);
|
||||
} else {
|
||||
map.flush().connection()
|
||||
.url('http://www.openstreetmap.org');
|
||||
d3.select(this).text('live').classed('live', true);
|
||||
}
|
||||
});
|
||||
|
||||
var contributors = linkList.append('li')
|
||||
.attr('id', 'user-list');
|
||||
contributors.append('span')
|
||||
.attr('class', 'icon nearby icon-pre-text');
|
||||
contributors.append('span')
|
||||
.text('Viewing contributions by ');
|
||||
contributors.append('span')
|
||||
.attr('class', 'contributor-list');
|
||||
contributors.append('span')
|
||||
.attr('class', 'contributor-count');
|
||||
|
||||
history.on('change.editor', function() {
|
||||
window.onbeforeunload = history.hasChanges() ? function() {
|
||||
return 'You have unsaved changes.';
|
||||
} : null;
|
||||
|
||||
var undo = history.undoAnnotation(),
|
||||
redo = history.redoAnnotation();
|
||||
|
||||
function refreshTooltip(selection) {
|
||||
if (selection.property('disabled')) {
|
||||
selection.call(undo_tooltip.hide);
|
||||
} else if (selection.property('tooltipVisible')) {
|
||||
selection.call(undo_tooltip.show);
|
||||
}
|
||||
}
|
||||
|
||||
limiter.select('#undo')
|
||||
.property('disabled', !undo)
|
||||
.attr('data-original-title', hintprefix('⌘ + Z', undo))
|
||||
.call(refreshTooltip);
|
||||
|
||||
limiter.select('#redo')
|
||||
.property('disabled', !redo)
|
||||
.attr('data-original-title', hintprefix('⌘ + ⇧ + Z', redo))
|
||||
.call(refreshTooltip);
|
||||
});
|
||||
|
||||
d3.select(window).on('resize.editor', function() {
|
||||
map.size(m.size());
|
||||
});
|
||||
|
||||
var keybinding = d3.keybinding('main')
|
||||
.on('⌘+Z', function() { history.undo(); })
|
||||
.on('⌃+Z', function() { history.undo(); })
|
||||
.on('⌘+⇧+Z', function() { history.redo(); })
|
||||
.on('⌃+⇧+Z', function() { history.redo(); })
|
||||
.on('⌫', function() { d3.event.preventDefault(); });
|
||||
|
||||
[iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()].forEach(function(m) {
|
||||
keybinding.on(m.key, function() { if (map.editable()) controller.enter(m); });
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
var hash = iD.behavior.Hash(controller, map);
|
||||
|
||||
hash();
|
||||
|
||||
if (!hash.hadHash) {
|
||||
map.centerZoom([-77.02271, 38.90085], 20);
|
||||
}
|
||||
|
||||
d3.select('.user-container').call(iD.ui.userpanel(connection)
|
||||
.on('logout.editor', connection.logout)
|
||||
.on('login.editor', connection.authenticate));
|
||||
|
||||
controller.enter(iD.modes.Browse());
|
||||
|
||||
if (!localStorage.sawSplash) {
|
||||
iD.ui.splash();
|
||||
localStorage.sawSplash = true;
|
||||
}
|
||||
}
|
||||
|
||||
editor.connection = function(_) {
|
||||
if (!arguments.length) return connection;
|
||||
connection = _;
|
||||
return editor;
|
||||
context.storage = function(k, v) {
|
||||
if (arguments.length === 1) return storage[k];
|
||||
else storage[k] = v;
|
||||
};
|
||||
|
||||
editor.map = function() {
|
||||
return map;
|
||||
// the connection requires .storage() to be available on calling.
|
||||
var connection = iD.Connection(context);
|
||||
|
||||
connection.on('load.context', function (err, result) {
|
||||
history.merge(result);
|
||||
});
|
||||
|
||||
/* Straight accessors. Avoid using these if you can. */
|
||||
context.ui = function() { return ui; };
|
||||
context.connection = function() { return connection; };
|
||||
context.history = function() { return history; };
|
||||
context.map = function() { return map; };
|
||||
|
||||
/* History */
|
||||
context.graph = history.graph;
|
||||
context.perform = history.perform;
|
||||
context.replace = history.replace;
|
||||
context.pop = history.pop;
|
||||
context.undo = history.undo;
|
||||
context.redo = history.undo;
|
||||
context.changes = history.changes;
|
||||
|
||||
/* Graph */
|
||||
context.entity = function(id) {
|
||||
return history.graph().entity(id);
|
||||
};
|
||||
|
||||
editor.controller = function() {
|
||||
return controller;
|
||||
context.geometry = function(id) {
|
||||
return context.entity(id).geometry(history.graph());
|
||||
};
|
||||
|
||||
if (arguments.length) {
|
||||
d3.select(container).call(editor);
|
||||
}
|
||||
/* Modes */
|
||||
context.enter = function(newMode) {
|
||||
if (mode) {
|
||||
mode.exit();
|
||||
dispatch.exit(mode);
|
||||
}
|
||||
|
||||
return editor;
|
||||
mode = newMode;
|
||||
mode.enter();
|
||||
dispatch.enter(mode);
|
||||
};
|
||||
|
||||
context.mode = function() {
|
||||
return mode;
|
||||
};
|
||||
|
||||
context.selection = function() {
|
||||
if (mode.id === 'select') {
|
||||
return mode.selection();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/* Behaviors */
|
||||
context.install = function(behavior) {
|
||||
context.surface().call(behavior);
|
||||
};
|
||||
|
||||
context.uninstall = function(behavior) {
|
||||
context.surface().call(behavior.off);
|
||||
};
|
||||
|
||||
/* Map */
|
||||
context.background = function() { return map.background; };
|
||||
context.surface = function() { return map.surface; };
|
||||
context.projection = map.projection;
|
||||
context.tail = map.tail;
|
||||
context.redraw = map.redraw;
|
||||
|
||||
context.container = function(_) {
|
||||
if (!arguments.length) return container;
|
||||
container = _;
|
||||
return context;
|
||||
};
|
||||
|
||||
context.background()
|
||||
.source(iD.BackgroundSource.Bing);
|
||||
|
||||
return d3.rebind(context, dispatch, 'on');
|
||||
};
|
||||
|
||||
iD.version = '0.0.0-alpha1';
|
||||
|
||||
iD.supported = function() {
|
||||
if (navigator.appName !== 'Microsoft Internet Explorer') {
|
||||
return true;
|
||||
|
||||
+63
-69
@@ -1,4 +1,4 @@
|
||||
iD.modes.AddArea = function() {
|
||||
iD.modes.AddArea = function(context) {
|
||||
var mode = {
|
||||
id: 'add-area',
|
||||
button: 'area',
|
||||
@@ -7,81 +7,75 @@ iD.modes.AddArea = function() {
|
||||
key: t('modes.add_area.key')
|
||||
};
|
||||
|
||||
var behavior,
|
||||
defaultTags = {area: 'yes'};
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function start(loc) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
function startFromMidpoint(midpoint) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.AddWay(mode)
|
||||
var behavior = iD.behavior.AddWay(context)
|
||||
.on('start', start)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('startFromNode', startFromNode)
|
||||
.on('startFromMidpoint', startFromMidpoint);
|
||||
.on('startFromMidpoint', startFromMidpoint),
|
||||
defaultTags = {area: 'yes'};
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.add_area.tail'));
|
||||
function start(loc) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = context.graph(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromMidpoint(midpoint) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_area.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+70
-76
@@ -1,4 +1,4 @@
|
||||
iD.modes.AddLine = function() {
|
||||
iD.modes.AddLine = function(context) {
|
||||
var mode = {
|
||||
id: 'add-line',
|
||||
button: 'line',
|
||||
@@ -7,88 +7,82 @@ iD.modes.AddLine = function() {
|
||||
key: t('modes.add_line.key')
|
||||
};
|
||||
|
||||
var behavior,
|
||||
defaultTags = {highway: 'residential'};
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function start(loc) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
parent = graph.parentWays(node)[0],
|
||||
isLine = parent && parent.geometry(graph) === 'line';
|
||||
|
||||
if (isLine && parent.first() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'backward', graph));
|
||||
|
||||
} else if (isLine && parent.last() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'forward', graph));
|
||||
|
||||
} else {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
}
|
||||
|
||||
function startFromMidpoint(midpoint) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.AddWay(mode)
|
||||
var behavior = iD.behavior.AddWay(context)
|
||||
.on('start', start)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('startFromNode', startFromNode)
|
||||
.on('startFromMidpoint', startFromMidpoint);
|
||||
.on('startFromMidpoint', startFromMidpoint),
|
||||
defaultTags = {highway: 'residential'};
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.add_line.tail'));
|
||||
function start(loc) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = context.graph(),
|
||||
parent = graph.parentWays(node)[0],
|
||||
isLine = parent && parent.geometry(graph) === 'line';
|
||||
|
||||
if (isLine && parent.first() === node.id) {
|
||||
context.enter(iD.modes.DrawLine(context, parent.id, 'backward', graph));
|
||||
|
||||
} else if (isLine && parent.last() === node.id) {
|
||||
context.enter(iD.modes.DrawLine(context, parent.id, 'forward', graph));
|
||||
|
||||
} else {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
}
|
||||
|
||||
function startFromMidpoint(midpoint) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_line.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+34
-43
@@ -1,4 +1,4 @@
|
||||
iD.modes.AddPoint = function() {
|
||||
iD.modes.AddPoint = function(context) {
|
||||
var mode = {
|
||||
id: 'add-point',
|
||||
title: t('modes.add_point.title'),
|
||||
@@ -6,53 +6,44 @@ iD.modes.AddPoint = function() {
|
||||
key: t('modes.add_point.key')
|
||||
};
|
||||
|
||||
var behavior;
|
||||
var behavior = iD.behavior.Draw(context)
|
||||
.on('click', add)
|
||||
.on('clickWay', addWay)
|
||||
.on('clickNode', addNode)
|
||||
.on('clickMidpoint', addNode)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel);
|
||||
|
||||
function add(loc) {
|
||||
var node = iD.Node({loc: loc});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
t('operations.add.annotation.point'));
|
||||
|
||||
context.enter(iD.modes.Select(context, [node.id], true));
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
add(loc);
|
||||
}
|
||||
|
||||
function addNode(node) {
|
||||
add(node.loc);
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function add(loc) {
|
||||
var node = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
t('operations.add.annotation.point'));
|
||||
|
||||
controller.enter(iD.modes.Select([node.id], true));
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
add(loc);
|
||||
}
|
||||
|
||||
function addNode(node) {
|
||||
add(node.loc);
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
behavior = iD.behavior.Draw(map)
|
||||
.on('click', add)
|
||||
.on('clickWay', addWay)
|
||||
.on('clickNode', addNode)
|
||||
.on('clickMidpoint', addNode)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.add_point.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_point.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface;
|
||||
|
||||
map.tail(false);
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
context.tail(false);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+8
-14
@@ -1,4 +1,4 @@
|
||||
iD.modes.Browse = function() {
|
||||
iD.modes.Browse = function(context) {
|
||||
var mode = {
|
||||
button: 'browse',
|
||||
id: 'browse',
|
||||
@@ -7,27 +7,21 @@ iD.modes.Browse = function() {
|
||||
key: t('modes.browse.key')
|
||||
};
|
||||
|
||||
var behaviors;
|
||||
var behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.DragNode(context),
|
||||
iD.behavior.DragMidpoint(context)];
|
||||
|
||||
mode.enter = function() {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(mode),
|
||||
iD.behavior.DragNode(mode),
|
||||
iD.behavior.DragMidpoint(mode)];
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior(surface);
|
||||
context.install(behavior);
|
||||
});
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
iD.modes.DrawArea = function(context, wayId, baseGraph) {
|
||||
var mode = {
|
||||
button: 'area',
|
||||
id: 'draw-area'
|
||||
@@ -7,11 +7,11 @@ iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
var way = context.entity(wayId),
|
||||
headId = way.nodes[way.nodes.length - 2],
|
||||
tailId = way.first();
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, -1, mode, baseGraph);
|
||||
behavior = iD.behavior.DrawWay(context, wayId, -1, mode, baseGraph);
|
||||
|
||||
var addNode = behavior.addNode;
|
||||
|
||||
@@ -23,12 +23,12 @@ iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
}
|
||||
};
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.draw_area.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.draw_area.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
iD.modes.DrawLine = function(context, wayId, direction, baseGraph) {
|
||||
var mode = {
|
||||
button: 'line',
|
||||
id: 'draw-line'
|
||||
@@ -7,11 +7,11 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
var way = context.entity(wayId),
|
||||
index = (direction === 'forward') ? undefined : 0,
|
||||
headId = (direction === 'forward') ? way.last() : way.first();
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, index, mode, baseGraph);
|
||||
behavior = iD.behavior.DrawWay(context, wayId, index, mode, baseGraph);
|
||||
|
||||
var addNode = behavior.addNode;
|
||||
|
||||
@@ -23,12 +23,12 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
}
|
||||
};
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.draw_line.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.draw_line.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+21
-26
@@ -1,4 +1,4 @@
|
||||
iD.modes.MoveWay = function(wayId) {
|
||||
iD.modes.MoveWay = function(context, wayId) {
|
||||
var mode = {
|
||||
id: 'move-way'
|
||||
};
|
||||
@@ -6,55 +6,53 @@ iD.modes.MoveWay = function(wayId) {
|
||||
var keybinding = d3.keybinding('move-way');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
graph = history.graph(),
|
||||
selection = map.surface,
|
||||
controller = mode.controller,
|
||||
projection = map.projection,
|
||||
way = graph.entity(wayId),
|
||||
origin = d3.mouse(selection.node()),
|
||||
annotation = t('operations.move.annotation.' + way.geometry(graph));
|
||||
var origin = point(),
|
||||
annotation = t('operations.move.annotation.' + context.geometry(wayId));
|
||||
|
||||
// If intiated via keyboard
|
||||
if (!origin[0] && !origin[1]) origin = null;
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.Noop(),
|
||||
annotation);
|
||||
|
||||
function point() {
|
||||
return d3.mouse(context.surface().node());
|
||||
}
|
||||
|
||||
function move() {
|
||||
var p = d3.mouse(selection.node()),
|
||||
var p = point(),
|
||||
delta = origin ?
|
||||
[p[0] - origin[0], p[1] - origin[1]] :
|
||||
[0, 0];
|
||||
|
||||
origin = p;
|
||||
|
||||
history.replace(
|
||||
iD.actions.MoveWay(wayId, delta, projection),
|
||||
context.replace(
|
||||
iD.actions.MoveWay(wayId, delta, context.projection),
|
||||
annotation);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
d3.event.stopPropagation();
|
||||
controller.enter(iD.modes.Select([way.id], true));
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
history.pop();
|
||||
controller.enter(iD.modes.Select([way.id], true));
|
||||
context.pop();
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function undone() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
selection
|
||||
context.surface()
|
||||
.on('mousemove.move-way', move)
|
||||
.on('click.move-way', finish);
|
||||
|
||||
history.on('undone.move-way', undone);
|
||||
context.history()
|
||||
.on('undone.move-way', undone);
|
||||
|
||||
keybinding
|
||||
.on('⎋', cancel)
|
||||
@@ -65,15 +63,12 @@ iD.modes.MoveWay = function(wayId) {
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
selection = map.surface;
|
||||
|
||||
selection
|
||||
context.surface()
|
||||
.on('mousemove.move-way', null)
|
||||
.on('click.move-way', null);
|
||||
|
||||
history.on('undone.move-way', null);
|
||||
context.history()
|
||||
.on('undone.move-way', null);
|
||||
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
+49
-53
@@ -1,4 +1,4 @@
|
||||
iD.modes.Select = function(selection, initial) {
|
||||
iD.modes.Select = function(context, selection, initial) {
|
||||
var mode = {
|
||||
id: 'select',
|
||||
button: 'browse'
|
||||
@@ -6,12 +6,16 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
var inspector = iD.ui.inspector().initial(!!initial),
|
||||
keybinding = d3.keybinding('select'),
|
||||
behaviors,
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.DragNode(context),
|
||||
iD.behavior.DragMidpoint(context)],
|
||||
radialMenu;
|
||||
|
||||
function changeTags(d, tags) {
|
||||
if (!_.isEqual(singular().tags, tags)) {
|
||||
mode.history.perform(
|
||||
context.perform(
|
||||
iD.actions.ChangeTags(d.id, tags),
|
||||
t('operations.change_tags.annotation'));
|
||||
}
|
||||
@@ -19,7 +23,7 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
function singular() {
|
||||
if (selection.length === 1) {
|
||||
return mode.map.history().graph().entity(selection[0]);
|
||||
return context.entity(selection[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,24 +32,14 @@ iD.modes.Select = function(selection, initial) {
|
||||
};
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = map.history(),
|
||||
graph = history.graph(),
|
||||
surface = map.surface,
|
||||
entity = singular();
|
||||
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(mode),
|
||||
iD.behavior.DragNode(mode),
|
||||
iD.behavior.DragMidpoint(mode)];
|
||||
var entity = singular();
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior(surface);
|
||||
context.install(behavior);
|
||||
});
|
||||
|
||||
var operations = d3.values(iD.operations)
|
||||
.map(function (o) { return o(selection, mode); })
|
||||
.map(function (o) { return o(selection, context); })
|
||||
.filter(function (o) { return o.available(); });
|
||||
|
||||
operations.forEach(function(operation) {
|
||||
@@ -62,9 +56,10 @@ iD.modes.Select = function(selection, initial) {
|
||||
}), true));
|
||||
|
||||
if (entity) {
|
||||
inspector.graph(graph);
|
||||
inspector.graph(context.graph());
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
.style('display', 'block')
|
||||
.style('opacity', 1)
|
||||
.datum(entity)
|
||||
@@ -73,38 +68,39 @@ iD.modes.Select = function(selection, initial) {
|
||||
if (d3.event) {
|
||||
// Pan the map if the clicked feature intersects with the position
|
||||
// of the inspector
|
||||
var inspector_size = d3.select('.inspector-wrap').size(),
|
||||
map_size = mode.map.size(),
|
||||
var inspector_size = context.container().select('.inspector-wrap').size(),
|
||||
map_size = context.map().size(),
|
||||
offset = 50,
|
||||
shift_left = d3.event.x - map_size[0] + inspector_size[0] + offset,
|
||||
center = (map_size[0] / 2) + shift_left + offset;
|
||||
|
||||
if (shift_left > 0 && inspector_size[1] > d3.event.y) {
|
||||
mode.map.centerEase(mode.map.projection.invert([center, map_size[1]/2]));
|
||||
context.map().centerEase(context.projection.invert([center, map_size[1]/2]));
|
||||
}
|
||||
}
|
||||
|
||||
inspector
|
||||
.on('changeTags', changeTags)
|
||||
.on('close', function() { mode.controller.enter(iD.modes.Browse()); });
|
||||
|
||||
history.on('change.select', function() {
|
||||
// Exit mode if selected entity gets undone
|
||||
var oldEntity = entity,
|
||||
newEntity = history.graph().entity(selection[0]);
|
||||
|
||||
if (!newEntity) {
|
||||
mode.controller.enter(iD.modes.Browse());
|
||||
} else if (!_.isEqual(oldEntity.tags, newEntity.tags)) {
|
||||
inspector.tags(newEntity.tags);
|
||||
}
|
||||
|
||||
surface.call(radialMenu.close);
|
||||
});
|
||||
.on('close', function() { context.enter(iD.modes.Browse(context)); });
|
||||
}
|
||||
|
||||
map.on('move.select', function() {
|
||||
surface.call(radialMenu.close);
|
||||
context.history().on('change.select', function() {
|
||||
context.surface().call(radialMenu.close);
|
||||
|
||||
if (_.any(selection, function (id) { return !context.entity(id); })) {
|
||||
// Exit mode if selected entity gets undone
|
||||
context.enter(iD.modes.Browse(context));
|
||||
|
||||
} else if (entity) {
|
||||
var newEntity = context.entity(selection[0]);
|
||||
if (!_.isEqual(entity.tags, newEntity.tags)) {
|
||||
inspector.tags(newEntity.tags);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
context.map().on('move.select', function() {
|
||||
context.surface().call(radialMenu.close);
|
||||
});
|
||||
|
||||
function dblclick() {
|
||||
@@ -113,10 +109,10 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
if (datum instanceof iD.Way && !target.classed('fill')) {
|
||||
var choice = iD.geo.chooseIndex(datum,
|
||||
d3.mouse(mode.map.surface.node()), mode.map),
|
||||
d3.mouse(context.surface().node()), context),
|
||||
node = iD.Node({ loc: choice.loc });
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddVertex(datum.id, node.id, choice.index),
|
||||
t('operations.add.annotation.vertex'));
|
||||
@@ -129,7 +125,8 @@ iD.modes.Select = function(selection, initial) {
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
surface.on('dblclick.select', dblclick)
|
||||
context.surface()
|
||||
.on('dblclick.select', dblclick)
|
||||
.selectAll("*")
|
||||
.filter(function (d) { return d && selection.indexOf(d.id) >= 0; })
|
||||
.classed('selected', true);
|
||||
@@ -137,25 +134,23 @@ iD.modes.Select = function(selection, initial) {
|
||||
radialMenu = iD.ui.RadialMenu(operations);
|
||||
|
||||
if (d3.event && !initial) {
|
||||
var loc = map.mouseCoordinates();
|
||||
var loc = context.map().mouseCoordinates();
|
||||
|
||||
if (entity && entity.type === 'node') {
|
||||
loc = entity.loc;
|
||||
}
|
||||
|
||||
surface.call(radialMenu, map.projection(loc));
|
||||
context.surface().call(radialMenu, context.projection(loc));
|
||||
}
|
||||
};
|
||||
|
||||
mode.exit = function () {
|
||||
var surface = mode.map.surface,
|
||||
history = mode.history;
|
||||
|
||||
if (singular()) {
|
||||
changeTags(singular(), inspector.tags());
|
||||
}
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
.style('display', 'none')
|
||||
.html('');
|
||||
|
||||
@@ -164,7 +159,7 @@ iD.modes.Select = function(selection, initial) {
|
||||
d3.selectAll('div.typeahead').remove();
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
@@ -172,13 +167,14 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
keybinding.off();
|
||||
|
||||
history.on('change.select', null);
|
||||
context.history()
|
||||
.on('change.select', null);
|
||||
|
||||
surface.on('dblclick.select', null)
|
||||
context.surface()
|
||||
.call(radialMenu.close)
|
||||
.on('dblclick.select', null)
|
||||
.selectAll(".selected")
|
||||
.classed('selected', false);
|
||||
|
||||
surface.call(radialMenu.close);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+7
-10
@@ -1,4 +1,4 @@
|
||||
iD.OAuth = function() {
|
||||
iD.OAuth = function(context) {
|
||||
var baseurl = 'http://www.openstreetmap.org',
|
||||
o = {},
|
||||
keys,
|
||||
@@ -6,10 +6,6 @@ iD.OAuth = function() {
|
||||
|
||||
function keyclean(x) { return x.replace(/\W/g, ''); }
|
||||
|
||||
if (token('oauth_token')) {
|
||||
o.oauth_token = token('oauth_token');
|
||||
}
|
||||
|
||||
function timenonce(o) {
|
||||
o.oauth_timestamp = ohauth.timestamp();
|
||||
o.oauth_nonce = ohauth.nonce();
|
||||
@@ -17,11 +13,12 @@ iD.OAuth = function() {
|
||||
}
|
||||
|
||||
// token getter/setter, namespaced to the current `apibase` value.
|
||||
function token(k, x) {
|
||||
if (arguments.length == 2) {
|
||||
localStorage[keyclean(baseurl) + k] = x;
|
||||
}
|
||||
return localStorage[keyclean(baseurl) + k];
|
||||
function token() {
|
||||
return context.storage.apply(context, arguments);
|
||||
}
|
||||
|
||||
if (token('oauth_token')) {
|
||||
o.oauth_token = token('oauth_token');
|
||||
}
|
||||
|
||||
oauth.authenticated = function() {
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
iD.operations.Circularize = function(selection, mode) {
|
||||
iD.operations.Circularize = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history(),
|
||||
action = iD.actions.Circularize(entityId, mode.map);
|
||||
action = iD.actions.Circularize(entityId, context.projection);
|
||||
|
||||
var operation = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId),
|
||||
annotation = t('operations.circularize.annotation.' + entity.geometry(graph));
|
||||
|
||||
history.perform(action, annotation);
|
||||
var annotation = t('operations.circularize.annotation.' + context.geometry(entityId));
|
||||
context.perform(action, annotation);
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 && entity.type === 'way';
|
||||
return selection.length === 1 &&
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
var graph = history.graph();
|
||||
return action.enabled(graph);
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "circularize";
|
||||
|
||||
+11
-14
@@ -1,23 +1,20 @@
|
||||
iD.operations.Delete = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history();
|
||||
|
||||
iD.operations.Delete = function(selection, context) {
|
||||
var operation = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId),
|
||||
action = {way: iD.actions.DeleteWay, node: iD.actions.DeleteNode}[entity.type],
|
||||
annotation = t('operations.delete.annotation.' + entity.geometry(graph));
|
||||
var annotation;
|
||||
|
||||
history.perform(
|
||||
action(entityId),
|
||||
if (selection.length === 1) {
|
||||
annotation = t('operations.delete.annotation.' + context.geometry(selection[0]));
|
||||
} else {
|
||||
annotation = t('operations.delete.annotation.multiple', {n: selection.length});
|
||||
}
|
||||
|
||||
context.perform(
|
||||
iD.actions.DeleteMultiple(selection),
|
||||
annotation);
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
(entity.type === 'way' || entity.type === 'node');
|
||||
return true;
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
iD.operations.Disconnect = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
action = iD.actions.Disconnect(entityId);
|
||||
|
||||
var operation = function() {
|
||||
context.perform(action, t('operations.disconnect.annotation'));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.geometry(entityId) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "disconnect";
|
||||
operation.key = t('operations.disconnect.key');
|
||||
operation.title = t('operations.disconnect.title');
|
||||
operation.description = t('operations.disconnect.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
iD.operations.Merge = function(selection, context) {
|
||||
var action = iD.actions.Join(selection[0], selection[1]);
|
||||
|
||||
var operation = function() {
|
||||
var annotation = t('operations.merge.annotation', {n: selection.length}),
|
||||
difference = context.perform(action, annotation);
|
||||
context.enter(iD.modes.Select(context, difference.extantIDs()));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 2 &&
|
||||
_.all(selection, function (id) {
|
||||
return context.geometry(id) === 'line';
|
||||
});
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "merge";
|
||||
operation.key = t('operations.merge.key');
|
||||
operation.title = t('operations.merge.title');
|
||||
operation.description = t('operations.merge.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -1,15 +1,13 @@
|
||||
iD.operations.Move = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history();
|
||||
iD.operations.Move = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
mode.controller.enter(iD.modes.MoveWay(entityId));
|
||||
context.enter(iD.modes.MoveWay(context, entityId));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph();
|
||||
return selection.length === 1 &&
|
||||
graph.entity(entityId).type === 'way';
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
iD.operations.Reverse = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history();
|
||||
iD.operations.Reverse = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
history.perform(
|
||||
iD.actions.ReverseWay(entityId),
|
||||
context.perform(
|
||||
iD.actions.Reverse(entityId),
|
||||
t('operations.reverse.annotation'));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
entity.geometry(graph) === 'line';
|
||||
context.geometry(entityId) === 'line';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
iD.operations.Split = function(selection, mode) {
|
||||
iD.operations.Split = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history(),
|
||||
action = iD.actions.SplitWay(entityId);
|
||||
action = iD.actions.Split(entityId);
|
||||
|
||||
var operation = function() {
|
||||
history.perform(action, t('operations.split.annotation'));
|
||||
var annotation = t('operations.split.annotation'),
|
||||
difference = context.perform(action, annotation);
|
||||
context.enter(iD.modes.Select(context, difference.extantIDs()));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
entity.geometry(graph) === 'vertex';
|
||||
context.geometry(entityId) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
var graph = history.graph();
|
||||
return action.enabled(graph);
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "split";
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
iD.operations.Unjoin = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history(),
|
||||
action = iD.actions.UnjoinNode(entityId);
|
||||
|
||||
var operation = function() {
|
||||
history.perform(action, 'Unjoined lines.');
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
entity.geometry(graph) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
var graph = history.graph();
|
||||
return action.enabled(graph);
|
||||
};
|
||||
|
||||
operation.id = "unjoin";
|
||||
operation.key = t('operations.unjoin.key');
|
||||
operation.title = t('operations.unjoin.title');
|
||||
operation.description = t('operations.unjoin.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -83,7 +83,10 @@ iD.Background = function() {
|
||||
}
|
||||
});
|
||||
|
||||
requests = uniqueBy(requests, 3);
|
||||
requests = uniqueBy(requests, 3).filter(function(r) {
|
||||
// don't re-request tiles which have failed in the past
|
||||
return cache[r[3]] !== false;
|
||||
});
|
||||
|
||||
function load(d) {
|
||||
cache[d[3]] = true;
|
||||
@@ -125,7 +128,7 @@ iD.Background = function() {
|
||||
.attr('src', function(d) { return d[3]; })
|
||||
.on('error', error)
|
||||
.on('load', load);
|
||||
|
||||
|
||||
image.style(transformProp, imageTransform);
|
||||
|
||||
if (Object.keys(cache).length > 100) cache = {};
|
||||
|
||||
+13
-75
@@ -1,6 +1,5 @@
|
||||
iD.Map = function() {
|
||||
var connection, history,
|
||||
dimensions = [],
|
||||
iD.Map = function(context) {
|
||||
var dimensions = [],
|
||||
dispatch = d3.dispatch('move', 'drawn'),
|
||||
projection = d3.geo.mercator().scale(1024),
|
||||
roundedProjection = iD.svg.RoundProjection(projection),
|
||||
@@ -27,6 +26,9 @@ iD.Map = function() {
|
||||
surface, tilegroup;
|
||||
|
||||
function map(selection) {
|
||||
context.history()
|
||||
.on('change.map', redraw);
|
||||
|
||||
selection.call(zoom);
|
||||
|
||||
tilegroup = selection.append('div')
|
||||
@@ -55,49 +57,23 @@ iD.Map = function() {
|
||||
function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }
|
||||
|
||||
function drawVector(difference) {
|
||||
if (surface.style(transformProp) != 'none') return;
|
||||
var filter, all,
|
||||
extent = map.extent(),
|
||||
graph = history.graph();
|
||||
|
||||
function addParents(parents) {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
if (only[parent.id] === undefined) {
|
||||
only[parent.id] = parent;
|
||||
addParents(graph.parentRelations(parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
graph = context.graph();
|
||||
|
||||
if (!difference) {
|
||||
all = graph.intersects(extent);
|
||||
filter = d3.functor(true);
|
||||
} else {
|
||||
var only = {};
|
||||
|
||||
for (var j = 0; j < difference.length; j++) {
|
||||
var id = difference[j],
|
||||
entity = graph.entity(id);
|
||||
|
||||
// Even if the entity is false (deleted), it needs to be
|
||||
// removed from the surface
|
||||
only[id] = entity;
|
||||
|
||||
if (entity && entity.intersects(extent, graph)) {
|
||||
addParents(graph.parentWays(only[id]));
|
||||
addParents(graph.parentRelations(only[id]));
|
||||
}
|
||||
}
|
||||
|
||||
all = _.compact(_.values(only));
|
||||
var complete = difference.complete(extent);
|
||||
all = _.compact(_.values(complete));
|
||||
filter = function(d) {
|
||||
if (d.type === 'midpoint') {
|
||||
for (var i = 0; i < d.ways.length; i++) {
|
||||
if (d.ways[i].id in only) return true;
|
||||
if (d.ways[i].id in complete) return true;
|
||||
}
|
||||
} else {
|
||||
return d.id in only;
|
||||
return d.id in complete;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -121,11 +97,6 @@ iD.Map = function() {
|
||||
surface.selectAll('.layer *').remove();
|
||||
}
|
||||
|
||||
function connectionLoad(err, result) {
|
||||
history.merge(result);
|
||||
redraw(Object.keys(result));
|
||||
}
|
||||
|
||||
function zoomPan() {
|
||||
if (d3.event && d3.event.sourceEvent.type === 'dblclick') {
|
||||
if (!dblclickEnabled) {
|
||||
@@ -183,7 +154,7 @@ iD.Map = function() {
|
||||
tilegroup.call(background);
|
||||
|
||||
if (map.editable()) {
|
||||
connection.loadTiles(projection, dimensions);
|
||||
context.connection().loadTiles(projection, dimensions);
|
||||
drawVector(difference);
|
||||
} else {
|
||||
editOff();
|
||||
@@ -259,7 +230,6 @@ iD.Map = function() {
|
||||
t[0] - ll[0] + c[0],
|
||||
t[1] - ll[1] + c[1]]);
|
||||
zoom.translate(projection.translate());
|
||||
dispatch.move(map);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -348,15 +318,8 @@ iD.Map = function() {
|
||||
};
|
||||
|
||||
map.flush = function () {
|
||||
connection.flush();
|
||||
history.reset();
|
||||
return map;
|
||||
};
|
||||
|
||||
map.connection = function(_) {
|
||||
if (!arguments.length) return connection;
|
||||
connection = _;
|
||||
connection.on('load.tile', connectionLoad);
|
||||
context.connection().flush();
|
||||
context.history().reset();
|
||||
return map;
|
||||
};
|
||||
|
||||
@@ -369,24 +332,6 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.hint = function (_) {
|
||||
if (_ === false) {
|
||||
d3.select('div.inspector-wrap')
|
||||
.style('opacity', 0)
|
||||
.style('display', 'none');
|
||||
} else {
|
||||
d3.select('div.inspector-wrap')
|
||||
.html('')
|
||||
.style('display', 'block')
|
||||
.transition()
|
||||
.style('opacity', 1);
|
||||
d3.select('div.inspector-wrap')
|
||||
.append('div')
|
||||
.attr('class','inspector-inner')
|
||||
.text(_);
|
||||
}
|
||||
};
|
||||
|
||||
map.editable = function() {
|
||||
return map.zoom() >= 16;
|
||||
};
|
||||
@@ -397,13 +342,6 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.history = function (_) {
|
||||
if (!arguments.length) return history;
|
||||
history = _;
|
||||
history.on('change.map', redraw);
|
||||
return map;
|
||||
};
|
||||
|
||||
map.background = background;
|
||||
map.projection = projection;
|
||||
map.redraw = redraw;
|
||||
|
||||
@@ -3,7 +3,7 @@ iD.svg.Surface = function() {
|
||||
selection.append('defs');
|
||||
|
||||
var layers = selection.selectAll('.layer')
|
||||
.data(['shadow', 'fill', 'casing', 'stroke', 'text', 'hit', 'halo', 'label']);
|
||||
.data(['fill', 'shadow', 'casing', 'stroke', 'text', 'hit', 'halo', 'label']);
|
||||
|
||||
layers.enter().append('g')
|
||||
.attr('class', function(d) { return 'layer layer-' + d; });
|
||||
|
||||
+257
-1
@@ -1 +1,257 @@
|
||||
iD.ui = {};
|
||||
iD.ui = function (context) {
|
||||
return function(container) {
|
||||
context.container(container);
|
||||
|
||||
var connection = context.connection(),
|
||||
history = context.history(),
|
||||
map = context.map();
|
||||
|
||||
if (!iD.supported()) {
|
||||
container.html('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.')
|
||||
.style('text-align:center;font-style:italic;');
|
||||
return;
|
||||
}
|
||||
|
||||
function hintprefix(x, y) {
|
||||
return '<span>' + y + '</span>' + '<div class="keyhint-wrap"><span class="keyhint"> ' + x + '</span></div>';
|
||||
}
|
||||
|
||||
var m = container.append('div')
|
||||
.attr('id', 'map')
|
||||
.call(map);
|
||||
|
||||
var bar = container.append('div')
|
||||
.attr('id', 'bar')
|
||||
.attr('class','pad1 fillD');
|
||||
|
||||
var limiter = bar.append('div')
|
||||
.attr('class', 'limiter');
|
||||
|
||||
var buttons_joined = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col4');
|
||||
|
||||
var modes = [
|
||||
iD.modes.Browse(context),
|
||||
iD.modes.AddPoint(context),
|
||||
iD.modes.AddLine(context),
|
||||
iD.modes.AddArea(context)];
|
||||
|
||||
var buttons = buttons_joined.selectAll('button.add-button')
|
||||
.data(modes)
|
||||
.enter().append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function (mode) { return mode.title + ' add-button col3'; })
|
||||
.call(bootstrap.tooltip().placement('bottom').html(true))
|
||||
.attr('data-original-title', function (mode) {
|
||||
return hintprefix(mode.key, mode.description);
|
||||
})
|
||||
.on('click.editor', function (mode) { context.enter(mode); });
|
||||
|
||||
function disableTooHigh() {
|
||||
if (map.editable()) {
|
||||
notice.message(false);
|
||||
buttons.attr('disabled', null);
|
||||
} else {
|
||||
buttons.attr('disabled', 'disabled');
|
||||
notice.message(true);
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
}
|
||||
|
||||
var notice = iD.ui.notice(limiter)
|
||||
.message(false)
|
||||
.on('zoom', function() { map.zoom(16); });
|
||||
|
||||
map.on('move.editor', _.debounce(function() {
|
||||
disableTooHigh();
|
||||
contributors.call(iD.ui.contributors(context));
|
||||
}, 500));
|
||||
|
||||
buttons.append('span')
|
||||
.attr('class', function(d) {
|
||||
return d.id + ' icon icon-pre-text';
|
||||
});
|
||||
|
||||
buttons.append('span').attr('class', 'label').text(function (mode) { return mode.title; });
|
||||
|
||||
context.on('enter.editor', function (entered) {
|
||||
buttons.classed('active', function (mode) { return entered.button === mode.button; });
|
||||
container.classed("mode-" + entered.id, true);
|
||||
});
|
||||
|
||||
context.on('exit.editor', function (exited) {
|
||||
container.classed("mode-" + exited.id, false);
|
||||
});
|
||||
|
||||
var undo_buttons = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col1'),
|
||||
undo_tooltip = bootstrap.tooltip().placement('bottom').html(true);
|
||||
|
||||
undo_buttons.append('button')
|
||||
.attr({ id: 'undo', 'class': 'col6' })
|
||||
.property('disabled', true)
|
||||
.html("<span class='undo icon'></span><small></small>")
|
||||
.on('click.editor', history.undo)
|
||||
.call(undo_tooltip);
|
||||
|
||||
undo_buttons.append('button')
|
||||
.attr({ id: 'redo', 'class': 'col6' })
|
||||
.property('disabled', true)
|
||||
.html("<span class='redo icon'><small></small>")
|
||||
.on('click.editor', history.redo)
|
||||
.call(undo_tooltip);
|
||||
|
||||
limiter.append('div').attr('class','button-wrap col1').append('button')
|
||||
.attr('class', 'save col12')
|
||||
.call(iD.ui.save(context));
|
||||
|
||||
var zoom = container.append('div')
|
||||
.attr('class', 'zoombuttons map-control')
|
||||
.selectAll('button')
|
||||
.data([['zoom-in', '+', map.zoomIn, 'Zoom In'], ['zoom-out', '-', map.zoomOut, 'Zoom Out']])
|
||||
.enter()
|
||||
.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function(d) { return d[0]; })
|
||||
.attr('title', function(d) { return d[3]; })
|
||||
.on('click.editor', function(d) { return d[2](); })
|
||||
.append('span')
|
||||
.attr('class', function(d) {
|
||||
return d[0] + ' icon';
|
||||
});
|
||||
|
||||
if (navigator.geolocation) {
|
||||
container.append('div')
|
||||
.call(iD.ui.geolocate(map));
|
||||
}
|
||||
|
||||
container.append('div').attr('class', 'geocode-control map-control')
|
||||
.call(iD.ui.geocoder().map(map));
|
||||
|
||||
container.append('div').attr('class', 'map-control layerswitcher-control')
|
||||
.call(iD.ui.layerswitcher(context));
|
||||
|
||||
container.append('div')
|
||||
.style('display', 'none')
|
||||
.attr('class', 'inspector-wrap fr col5');
|
||||
|
||||
var about = container.append('div')
|
||||
.attr('class','col12 about-block fillD pad1');
|
||||
|
||||
about.append('div')
|
||||
.attr('class', 'user-container')
|
||||
.append('div')
|
||||
.attr('class', 'hello');
|
||||
|
||||
var aboutList = about.append('ul')
|
||||
.attr('id','about')
|
||||
.attr('class','link-list');
|
||||
|
||||
var linkList = aboutList.append('ul')
|
||||
.attr('id','about')
|
||||
.attr('class','pad1 fillD about-block link-list');
|
||||
linkList.append('li').append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://github.com/systemed/iD').text(iD.version);
|
||||
linkList.append('li').append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://github.com/systemed/iD/issues').text('report a bug');
|
||||
|
||||
var imagery = linkList.append('li').attr('id', 'attribution');
|
||||
imagery.append('span').text('imagery');
|
||||
imagery.append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://opengeodata.org/microsoft-imagery-details').text(' provided by bing');
|
||||
|
||||
linkList.append('li').attr('class', 'source-switch').append('a').attr('href', '#')
|
||||
.text('dev')
|
||||
.on('click.editor', function() {
|
||||
d3.event.preventDefault();
|
||||
if (d3.select(this).classed('live')) {
|
||||
map.flush();
|
||||
context.connection()
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
d3.select(this).text('dev').classed('live', false);
|
||||
} else {
|
||||
map.flush();
|
||||
context.connection()
|
||||
.url('http://www.openstreetmap.org');
|
||||
d3.select(this).text('live').classed('live', true);
|
||||
}
|
||||
});
|
||||
|
||||
var contributors = linkList.append('li')
|
||||
.attr('id', 'user-list');
|
||||
contributors.append('span')
|
||||
.attr('class', 'icon nearby icon-pre-text');
|
||||
contributors.append('span')
|
||||
.text('Viewing contributions by ');
|
||||
contributors.append('span')
|
||||
.attr('class', 'contributor-list');
|
||||
contributors.append('span')
|
||||
.attr('class', 'contributor-count');
|
||||
|
||||
history.on('change.editor', function() {
|
||||
window.onbeforeunload = history.hasChanges() ? function() {
|
||||
return 'You have unsaved changes.';
|
||||
} : null;
|
||||
|
||||
var undo = history.undoAnnotation(),
|
||||
redo = history.redoAnnotation();
|
||||
|
||||
function refreshTooltip(selection) {
|
||||
if (selection.property('disabled')) {
|
||||
selection.call(undo_tooltip.hide);
|
||||
} else if (selection.property('tooltipVisible')) {
|
||||
selection.call(undo_tooltip.show);
|
||||
}
|
||||
}
|
||||
|
||||
limiter.select('#undo')
|
||||
.property('disabled', !undo)
|
||||
.attr('data-original-title', hintprefix('⌘ + Z', undo))
|
||||
.call(refreshTooltip);
|
||||
|
||||
limiter.select('#redo')
|
||||
.property('disabled', !redo)
|
||||
.attr('data-original-title', hintprefix('⌘ + ⇧ + Z', redo))
|
||||
.call(refreshTooltip);
|
||||
});
|
||||
|
||||
d3.select(window).on('resize.editor', function() {
|
||||
map.size(m.size());
|
||||
});
|
||||
|
||||
var keybinding = d3.keybinding('main')
|
||||
.on('⌘+Z', function() { history.undo(); })
|
||||
.on('⌃+Z', function() { history.undo(); })
|
||||
.on('⌘+⇧+Z', function() { history.redo(); })
|
||||
.on('⌃+⇧+Z', function() { history.redo(); })
|
||||
.on('⌫', function() { d3.event.preventDefault(); });
|
||||
|
||||
modes.forEach(function(m) {
|
||||
keybinding.on(m.key, function() { if (map.editable()) context.enter(m); });
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
var hash = iD.behavior.Hash(context);
|
||||
|
||||
hash();
|
||||
|
||||
if (!hash.hadHash) {
|
||||
map.centerZoom([-77.02271, 38.90085], 20);
|
||||
}
|
||||
|
||||
d3.select('.user-container').call(iD.ui.userpanel(connection)
|
||||
.on('logout.editor', connection.logout)
|
||||
.on('login.editor', connection.authenticate));
|
||||
|
||||
context.enter(iD.modes.Browse(context));
|
||||
|
||||
if (!context.storage('sawSplash')) {
|
||||
iD.ui.splash();
|
||||
context.storage('sawSplash', true);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
iD.ui.commit = function(map) {
|
||||
iD.ui.commit = function(context) {
|
||||
var event = d3.dispatch('cancel', 'save', 'fix');
|
||||
|
||||
function zipSame(d) {
|
||||
@@ -38,7 +38,7 @@ iD.ui.commit = function(map) {
|
||||
comment_section.append('textarea')
|
||||
.attr('class', 'changeset-comment')
|
||||
.attr('placeholder', 'Brief Description of your contributions')
|
||||
.property('value', localStorage.comment || '')
|
||||
.property('value', context.storage('comment') || '')
|
||||
.node().select();
|
||||
|
||||
var commit_info =
|
||||
@@ -89,7 +89,7 @@ iD.ui.commit = function(map) {
|
||||
cancelbutton.append('span').attr('class','label').text('Cancel');
|
||||
|
||||
var warnings = body.selectAll('div.warning-section')
|
||||
.data(iD.validate(changes, map.history().graph()))
|
||||
.data(iD.validate(changes, context.graph()))
|
||||
.enter()
|
||||
.append('div').attr('class', 'modal-section warning-section fillL');
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
iD.ui.contributors = function(map) {
|
||||
iD.ui.contributors = function(context) {
|
||||
|
||||
function contributors(selection) {
|
||||
|
||||
var users = {},
|
||||
limit = 3,
|
||||
entities = map.history().graph().intersects(map.extent());
|
||||
entities = context.graph().intersects(context.map().extent());
|
||||
|
||||
for (var i in entities) {
|
||||
if (entities[i].user) users[entities[i].user] = true;
|
||||
@@ -21,7 +21,7 @@ iD.ui.contributors = function(map) {
|
||||
|
||||
l.enter().append('a')
|
||||
.attr('class', 'user-link')
|
||||
.attr('href', function(d) { return map.connection().userUrl(d); })
|
||||
.attr('href', function(d) { return context.connection().userUrl(d); })
|
||||
.attr('target', '_blank')
|
||||
.text(String);
|
||||
|
||||
@@ -37,7 +37,7 @@ iD.ui.contributors = function(map) {
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('href', function() {
|
||||
var ext = map.extent();
|
||||
var ext = context.map().extent();
|
||||
return 'http://www.openstreetmap.org/browse/changesets?bbox=' + [
|
||||
ext[0][0], ext[0][1],
|
||||
ext[1][0], ext[1][1]];
|
||||
|
||||
+10
-8
@@ -6,18 +6,20 @@ iD.ui.geocoder = function() {
|
||||
function keydown() {
|
||||
if (d3.event.keyCode !== 13) return;
|
||||
d3.event.preventDefault();
|
||||
d3.json('http://a.tiles.mapbox.com/v3/openstreetmap.map-hn253zqn/geocode/' +
|
||||
encodeURIComponent(this.value) + '.json', function(err, resp) {
|
||||
var searchVal = this.value;
|
||||
d3.json('http://nominatim.openstreetmap.org/search/' +
|
||||
encodeURIComponent(searchVal) + '?limit=10&format=json', function(err, resp) {
|
||||
if (err) return hide();
|
||||
hide();
|
||||
if (!resp.results.length) {
|
||||
if (!resp.length) {
|
||||
return iD.ui.flash()
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text('No location found for "' + resp.query[0] + '"');
|
||||
.text('No location found for "' + searchVal + '"');
|
||||
}
|
||||
var bounds = resp.results[0][0].bounds;
|
||||
map.extent(iD.geo.Extent([bounds[0], bounds[1]], [bounds[2], bounds[3]]));
|
||||
var bounds = resp[0].boundingbox;
|
||||
map.extent(iD.geo.Extent([parseFloat(bounds[3]), parseFloat(bounds[0])], [parseFloat(bounds[2]), parseFloat(bounds[1])]));
|
||||
if (map.zoom() > 19) map.zoom(19);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -43,7 +45,7 @@ iD.ui.geocoder = function() {
|
||||
|
||||
var button = selection.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('title', 'Find A Location')
|
||||
.attr('title', t('geocoder.find_location'))
|
||||
.html('<span class=\'geocode icon\'></span>')
|
||||
.on('click', toggle);
|
||||
|
||||
@@ -51,7 +53,7 @@ iD.ui.geocoder = function() {
|
||||
|
||||
gcForm.attr('class','content fillD map-overlay hide')
|
||||
.append('input')
|
||||
.attr({ type: 'text', placeholder: 'find a place' })
|
||||
.attr({ type: 'text', placeholder: t('geocoder.find_a_place') })
|
||||
.on('keydown', keydown);
|
||||
|
||||
selection.call(clickoutside);
|
||||
|
||||
@@ -35,7 +35,7 @@ iD.ui.inspector = function() {
|
||||
});
|
||||
|
||||
newTag.append('span').attr('class', 'icon icon-pre-text plus');
|
||||
newTag.append('span').attr('class','label').text('New tag')
|
||||
newTag.append('span').attr('class','label').text(t('inspector.new_tag'));
|
||||
|
||||
drawTags(entity.tags);
|
||||
|
||||
@@ -63,7 +63,7 @@ iD.ui.inspector = function() {
|
||||
.attr('class', 'apply action')
|
||||
.on('click', apply);
|
||||
|
||||
inspectorButton.append('span').attr('class','label').text('Okay');
|
||||
inspectorButton.append('span').attr('class','label').text(t('okay'));
|
||||
|
||||
var minorButtons = selection.append('div').attr('class','minor-buttons fl');
|
||||
|
||||
@@ -148,7 +148,7 @@ iD.ui.inspector = function() {
|
||||
iD.ui.flash()
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('no_documentation_combination'));
|
||||
.text(t('inspector.no_documentation_combination'));
|
||||
}
|
||||
});
|
||||
} else if (d.key) {
|
||||
@@ -166,7 +166,7 @@ iD.ui.inspector = function() {
|
||||
iD.ui.flash()
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('no_documentation_key'));
|
||||
.text(t('inspector.no_documentation_key'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,4 +1,4 @@
|
||||
iD.ui.layerswitcher = function(map) {
|
||||
iD.ui.layerswitcher = function(context) {
|
||||
var event = d3.dispatch('cancel', 'save'),
|
||||
sources = [{
|
||||
name: 'Bing',
|
||||
@@ -59,7 +59,7 @@ iD.ui.layerswitcher = function(map) {
|
||||
.append('div')
|
||||
.attr('class', 'opacity-options-wrapper');
|
||||
|
||||
opa.append('h4').text(t('layers'));
|
||||
opa.append('h4').text(t('layerswitcher.layers'));
|
||||
|
||||
opa.append('ul')
|
||||
.attr('class', 'opacity-options')
|
||||
@@ -68,7 +68,7 @@ iD.ui.layerswitcher = function(map) {
|
||||
.enter()
|
||||
.append('li')
|
||||
.attr('data-original-title', function(d) {
|
||||
return t('percent_opacity', { opacity: (d * 100) });
|
||||
return t('layerswitcher.percent_brightness', { opacity: (d * 100) });
|
||||
})
|
||||
.on('click.set-opacity', function(d) {
|
||||
d3.select('#tile-g')
|
||||
@@ -94,7 +94,7 @@ iD.ui.layerswitcher = function(map) {
|
||||
function selectLayer(d) {
|
||||
content.selectAll('a.layer')
|
||||
.classed('selected', function(d) {
|
||||
return d.source === map.background.source();
|
||||
return d.source === context.background().source();
|
||||
});
|
||||
d3.select('#attribution a')
|
||||
.attr('href', d.link)
|
||||
@@ -126,9 +126,9 @@ iD.ui.layerswitcher = function(map) {
|
||||
d.source = configured;
|
||||
d.name = 'Custom (configured)';
|
||||
}
|
||||
map.background.source(d.source);
|
||||
map.history().imagery_used(d.name);
|
||||
map.redraw();
|
||||
context.background().source(d.source);
|
||||
context.history().imagery_used(d.name);
|
||||
context.redraw();
|
||||
selectLayer(d);
|
||||
})
|
||||
.insert('span')
|
||||
@@ -145,8 +145,8 @@ iD.ui.layerswitcher = function(map) {
|
||||
['bottom', [0, 1]]];
|
||||
|
||||
function nudge(d) {
|
||||
map.background.nudge(d[1]);
|
||||
map.redraw();
|
||||
context.background().nudge(d[1]);
|
||||
context.redraw();
|
||||
}
|
||||
|
||||
adjustments.append('a')
|
||||
@@ -181,12 +181,12 @@ iD.ui.layerswitcher = function(map) {
|
||||
.text('reset')
|
||||
.attr('class', 'reset')
|
||||
.on('click', function() {
|
||||
map.background.offset([0, 0]);
|
||||
map.redraw();
|
||||
context.background().offset([0, 0]);
|
||||
context.redraw();
|
||||
});
|
||||
|
||||
selection.call(clickoutside);
|
||||
selectLayer(map.background.source());
|
||||
selectLayer(context.background().source());
|
||||
}
|
||||
|
||||
return d3.rebind(layerswitcher, event, 'on');
|
||||
|
||||
+8
-25
@@ -1,11 +1,8 @@
|
||||
iD.ui.save = function() {
|
||||
|
||||
var map, controller;
|
||||
|
||||
function save(selection) {
|
||||
|
||||
var history = map.history(),
|
||||
connection = map.connection(),
|
||||
iD.ui.save = function(context) {
|
||||
return function (selection) {
|
||||
var map = context.map(),
|
||||
history = context.history(),
|
||||
connection = context.connection(),
|
||||
tooltip = bootstrap.tooltip()
|
||||
.placement('bottom');
|
||||
|
||||
@@ -53,14 +50,14 @@ iD.ui.save = function() {
|
||||
modal.select('.content')
|
||||
.classed('commit-modal', true)
|
||||
.datum(changes)
|
||||
.call(iD.ui.commit(map)
|
||||
.call(iD.ui.commit(context)
|
||||
.on('cancel', function() {
|
||||
modal.remove();
|
||||
})
|
||||
.on('fix', function(d) {
|
||||
map.extent(d.entity.extent(map.history().graph()));
|
||||
map.extent(d.entity.extent(context.graph()));
|
||||
if (map.zoom() > 19) map.zoom(19);
|
||||
controller.enter(iD.modes.Select([d.entity.id]));
|
||||
context.enter(iD.modes.Select(context, [d.entity.id]));
|
||||
modal.remove();
|
||||
})
|
||||
.on('save', commit));
|
||||
@@ -88,19 +85,5 @@ iD.ui.save = function() {
|
||||
selection.call(tooltip.hide);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
save.map = function(_) {
|
||||
if (!arguments.length) return map;
|
||||
map = _;
|
||||
return save;
|
||||
};
|
||||
|
||||
save.controller = function(_) {
|
||||
if (!arguments.length) return controller;
|
||||
controller = _;
|
||||
return save;
|
||||
};
|
||||
|
||||
return save;
|
||||
};
|
||||
|
||||
+19
-21
@@ -15,31 +15,29 @@ iD.validate = function(changes, graph) {
|
||||
if (tags.building && tags.building === 'yes') return 'building=yes';
|
||||
}
|
||||
|
||||
if (changes.created.length) {
|
||||
for (var i = 0; i < changes.created.length; i++) {
|
||||
change = changes.created[i];
|
||||
for (var i = 0; i < changes.created.length; i++) {
|
||||
change = changes.created[i];
|
||||
|
||||
if (change.geometry(graph) === 'point' && _.isEmpty(change.tags)) {
|
||||
warnings.push({
|
||||
message: t('validations.untagged_point'),
|
||||
entity: change
|
||||
});
|
||||
}
|
||||
if (change.geometry(graph) === 'point' && _.isEmpty(change.tags)) {
|
||||
warnings.push({
|
||||
message: t('validations.untagged_point'),
|
||||
entity: change
|
||||
});
|
||||
}
|
||||
|
||||
if (change.geometry(graph) === 'line' && _.isEmpty(change.tags)) {
|
||||
warnings.push({ message: t('validations.untagged_line'), entity: change });
|
||||
}
|
||||
if (change.geometry(graph) === 'line' && _.isEmpty(change.tags)) {
|
||||
warnings.push({ message: t('validations.untagged_line'), entity: change });
|
||||
}
|
||||
|
||||
if (change.geometry(graph) === 'area' && _.isEmpty(change.tags)) {
|
||||
warnings.push({ message: t('validations.untagged_area'), entity: change });
|
||||
}
|
||||
if (change.geometry(graph) === 'area' && _.isEmpty(change.tags)) {
|
||||
warnings.push({ message: t('validations.untagged_area'), entity: change });
|
||||
}
|
||||
|
||||
if (change.geometry(graph) === 'line' && tagSuggestsArea(change)) {
|
||||
warnings.push({
|
||||
message: t('validations.tag_suggests_area', {tag: tagSuggestsArea(change)}),
|
||||
entity: change
|
||||
});
|
||||
}
|
||||
if (change.geometry(graph) === 'line' && tagSuggestsArea(change)) {
|
||||
warnings.push({
|
||||
message: t('validations.tag_suggests_area', {tag: tagSuggestsArea(change)}),
|
||||
entity: change
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
d3.combobox = function() {
|
||||
var event = d3.dispatch('accept'),
|
||||
autohighlight = false,
|
||||
autofilter = false,
|
||||
input,
|
||||
container,
|
||||
data;
|
||||
|
||||
var typeahead = function(selection) {
|
||||
var hidden, idx = autohighlight ? 0 : -1;
|
||||
|
||||
var rect = selection.select('input').node().getBoundingClientRect();
|
||||
|
||||
input = selection.select('input');
|
||||
|
||||
container = selection
|
||||
.insert('div', ':first-child')
|
||||
.attr('class', 'combobox')
|
||||
.style({
|
||||
position: 'absolute',
|
||||
display: 'none',
|
||||
left: '0px',
|
||||
width: rect.width + 'px',
|
||||
top: rect.height + 'px'
|
||||
});
|
||||
|
||||
carat = selection
|
||||
.insert('div', ':first-child')
|
||||
.attr('class', 'combobox-carat')
|
||||
.text('+')
|
||||
.style({
|
||||
position: 'absolute',
|
||||
left: (rect.width - 20) + 'px',
|
||||
top: '0px'
|
||||
})
|
||||
.on('click', function() {
|
||||
update();
|
||||
show();
|
||||
});
|
||||
|
||||
selection
|
||||
.on('keyup.typeahead', key);
|
||||
|
||||
hidden = false;
|
||||
|
||||
function hide() {
|
||||
idx = autohighlight ? 0 : -1;
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
function show() {
|
||||
container.style('display', 'block');
|
||||
}
|
||||
|
||||
function slowHide() {
|
||||
if (autohighlight && container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
event.accept();
|
||||
}
|
||||
window.setTimeout(hide, 150);
|
||||
}
|
||||
|
||||
selection
|
||||
.on('focus.typeahead', show)
|
||||
.on('blur.typeahead', slowHide);
|
||||
|
||||
function key() {
|
||||
var len = container.selectAll('a').data().length;
|
||||
if (d3.event.keyCode === 40) {
|
||||
idx = Math.min(idx + 1, len - 1);
|
||||
return highlight();
|
||||
} else if (d3.event.keyCode === 38) {
|
||||
idx = Math.max(idx - 1, 0);
|
||||
return highlight();
|
||||
} else if (d3.event.keyCode === 13) {
|
||||
if (container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
}
|
||||
event.accept();
|
||||
hide();
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
function highlight() {
|
||||
container
|
||||
.selectAll('a')
|
||||
.classed('selected', function(d, i) { return i == idx; });
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
function run(data) {
|
||||
container.style('display', function() {
|
||||
return data.length ? 'block' : 'none';
|
||||
});
|
||||
|
||||
var options = container
|
||||
.selectAll('a')
|
||||
.data(data, function(d) { return d.value; });
|
||||
|
||||
options.enter()
|
||||
.append('a')
|
||||
.text(function(d) { return d.value; })
|
||||
.attr('title', function(d) { return d.title; })
|
||||
.on('click', select);
|
||||
|
||||
options.exit().remove();
|
||||
|
||||
options
|
||||
.classed('selected', function(d, i) { return i == idx; });
|
||||
}
|
||||
|
||||
if (typeof data === 'function') data(selection, run);
|
||||
else run(data);
|
||||
}
|
||||
|
||||
function select(d) {
|
||||
input
|
||||
.property('value', d.value)
|
||||
.trigger('change');
|
||||
container.style('display', 'none');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typeahead.data = function(_) {
|
||||
if (!arguments.length) return data;
|
||||
data = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
typeahead.autofilter = function(_) {
|
||||
if (!arguments.length) return autofilter;
|
||||
autofilter = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
typeahead.autohighlight = function(_) {
|
||||
if (!arguments.length) return autohighlight;
|
||||
autohighlight = _;
|
||||
return typeahead;
|
||||
};
|
||||
|
||||
return d3.rebind(typeahead, event, 'on');
|
||||
};
|
||||
Vendored
+900
-704
File diff suppressed because it is too large
Load Diff
+27
-14
@@ -73,9 +73,22 @@ locale.en = {
|
||||
point: "Deleted a point.",
|
||||
vertex: "Deleted a node from a way.",
|
||||
line: "Deleted a line.",
|
||||
area: "Deleted an area."
|
||||
area: "Deleted an area.",
|
||||
multiple: "Deleted {n} objects."
|
||||
}
|
||||
},
|
||||
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.",
|
||||
@@ -98,12 +111,6 @@ locale.en = {
|
||||
description: "Split this into two ways at this point.",
|
||||
key: "X",
|
||||
annotation: "Split a way."
|
||||
},
|
||||
unjoin: {
|
||||
title: "Unjoin",
|
||||
description: "Disconnect these ways from each other.",
|
||||
key: "⇧-J",
|
||||
annotation: "Unjoined ways."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -129,8 +136,11 @@ locale.en = {
|
||||
|
||||
"layer_settings": "Layer Settings",
|
||||
|
||||
"no_documentation_combination": "This is no documentation available for this tag combination",
|
||||
"no_documentation_key": "This is no documentation available for this key",
|
||||
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: "New Tag"
|
||||
},
|
||||
|
||||
"view_on_osm": "View on OSM",
|
||||
|
||||
@@ -138,13 +148,16 @@ locale.en = {
|
||||
|
||||
"edit_tags": "Edit tags",
|
||||
|
||||
"find_location": "Find A Location",
|
||||
"find_placeholder": "find a place",
|
||||
geocoder: {
|
||||
"find_location": "Find A Location",
|
||||
"find_a_place": "find a place"
|
||||
},
|
||||
|
||||
"description": "Description",
|
||||
|
||||
"logout": "logout",
|
||||
|
||||
"layers": "Layers",
|
||||
"percent_opacity": "{opacity}% opacity"
|
||||
layerswitcher: {
|
||||
layers: "Layers",
|
||||
percent_brightness: "{opacity}% brightness"
|
||||
}
|
||||
};
|
||||
|
||||
+22
-13
@@ -73,14 +73,17 @@
|
||||
<script src='../js/id/actions/add_vertex.js'></script>
|
||||
<script src='../js/id/actions/change_tags.js'></script>
|
||||
<script src='../js/id/actions/circularize.js'></script>
|
||||
<script src="../js/id/actions/delete_multiple.js"></script>
|
||||
<script src="../js/id/actions/delete_node.js"></script>
|
||||
<script src="../js/id/actions/delete_relation.js"></script>
|
||||
<script src="../js/id/actions/delete_way.js"></script>
|
||||
<script src='../js/id/actions/disconnect.js'></script>
|
||||
<script src='../js/id/actions/join.js'></script>
|
||||
<script src='../js/id/actions/move_node.js'></script>
|
||||
<script src='../js/id/actions/move_way.js'></script>
|
||||
<script src='../js/id/actions/noop.js'></script>
|
||||
<script src='../js/id/actions/reverse_way.js'></script>
|
||||
<script src='../js/id/actions/split_way.js'></script>
|
||||
<script src='../js/id/actions/unjoin_node.js'></script>
|
||||
<script src='../js/id/actions/reverse.js'></script>
|
||||
<script src='../js/id/actions/split.js'></script>
|
||||
|
||||
<script src='../js/id/behavior.js'></script>
|
||||
<script src='../js/id/behavior/add_way.js'></script>
|
||||
@@ -106,11 +109,13 @@
|
||||
<script src='../js/id/operations.js'></script>
|
||||
<script src='../js/id/operations/circularize.js'></script>
|
||||
<script src='../js/id/operations/delete.js'></script>
|
||||
<script src='../js/id/operations/disconnect.js'></script>
|
||||
<script src='../js/id/operations/merge.js'></script>
|
||||
<script src='../js/id/operations/move.js'></script>
|
||||
<script src='../js/id/operations/reverse.js'></script>
|
||||
<script src='../js/id/operations/split.js'></script>
|
||||
<script src='../js/id/operations/unjoin.js'></script>
|
||||
|
||||
<script src='../js/id/graph/difference.js'></script>
|
||||
<script src='../js/id/graph/entity.js'></script>
|
||||
<script src='../js/id/graph/graph.js'></script>
|
||||
<script src='../js/id/graph/history.js'></script>
|
||||
@@ -119,7 +124,6 @@
|
||||
<script src='../js/id/graph/way.js'></script>
|
||||
|
||||
<script src='../js/id/connection.js'></script>
|
||||
<script src='../js/id/controller.js'></script>
|
||||
|
||||
<script src='../locale/locale.js'></script>
|
||||
<script src='../locale/en.js'></script>
|
||||
@@ -141,17 +145,17 @@
|
||||
<script src="spec/actions/add_midpoint.js"></script>
|
||||
<script src="spec/actions/add_entity.js"></script>
|
||||
<script src="spec/actions/change_tags.js"></script>
|
||||
<script src="spec/actions/delete_multiple.js"></script>
|
||||
<script src="spec/actions/delete_node.js"></script>
|
||||
<script src="spec/actions/delete_relation.js"></script>
|
||||
<script src="spec/actions/delete_way.js"></script>
|
||||
<script src='spec/actions/disconnect.js'></script>
|
||||
<script src="spec/actions/join.js"></script>
|
||||
<script src="spec/actions/move_node.js"></script>
|
||||
<script src="spec/actions/move_way.js"></script>
|
||||
<script src="spec/actions/noop.js"></script>
|
||||
<script src="spec/actions/reverse_way.js"></script>
|
||||
<script src="spec/actions/split_way.js"></script>
|
||||
<script src='spec/actions/unjoin_node.js'></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
<script src="spec/actions/reverse.js"></script>
|
||||
<script src="spec/actions/split.js"></script>
|
||||
|
||||
<script src="spec/geo/extent.js"></script>
|
||||
|
||||
@@ -161,8 +165,7 @@
|
||||
<script src="spec/graph/way.js"></script>
|
||||
<script src="spec/graph/relation.js"></script>
|
||||
<script src="spec/graph/history.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
<script src="spec/graph/difference.js"></script>
|
||||
|
||||
<script src="spec/renderer/background.js"></script>
|
||||
<script src="spec/renderer/map.js"></script>
|
||||
@@ -189,6 +192,12 @@
|
||||
<script src="spec/taginfo.js"></script>
|
||||
<script src="spec/util.js"></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
<script src="spec/behavior/select.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
</script>
|
||||
|
||||
@@ -35,17 +35,17 @@
|
||||
<script src="spec/actions/add_midpoint.js"></script>
|
||||
<script src="spec/actions/add_entity.js"></script>
|
||||
<script src="spec/actions/change_tags.js"></script>
|
||||
<script src="spec/actions/delete_multiple.js"></script>
|
||||
<script src="spec/actions/delete_node.js"></script>
|
||||
<script src="spec/actions/delete_relation.js"></script>
|
||||
<script src="spec/actions/delete_way.js"></script>
|
||||
<script src='spec/actions/disconnect.js'></script>
|
||||
<script src="spec/actions/join.js"></script>
|
||||
<script src="spec/actions/move_node.js"></script>
|
||||
<script src="spec/actions/move_way.js"></script>
|
||||
<script src="spec/actions/noop.js"></script>
|
||||
<script src="spec/actions/reverse_way.js"></script>
|
||||
<script src="spec/actions/split_way.js"></script>
|
||||
<script src='spec/actions/unjoin_node.js'></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
<script src="spec/actions/reverse.js"></script>
|
||||
<script src="spec/actions/split.js"></script>
|
||||
|
||||
<script src="spec/geo/extent.js"></script>
|
||||
|
||||
@@ -55,8 +55,7 @@
|
||||
<script src="spec/graph/way.js"></script>
|
||||
<script src="spec/graph/relation.js"></script>
|
||||
<script src="spec/graph/history.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
<script src="spec/graph/difference.js"></script>
|
||||
|
||||
<script src="spec/renderer/background.js"></script>
|
||||
<script src="spec/renderer/map.js"></script>
|
||||
@@ -83,6 +82,12 @@
|
||||
<script src="spec/taginfo.js"></script>
|
||||
<script src="spec/util.js"></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
<script src="spec/behavior/select.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
describe("iD.actions.DeleteMultiple", function () {
|
||||
it("deletes multiple entities of heterogeneous types", function () {
|
||||
var n = iD.Node(),
|
||||
w = iD.Way(),
|
||||
r = iD.Relation(),
|
||||
action = iD.actions.DeleteMultiple([n.id, w.id, r.id]),
|
||||
graph = action(iD.Graph([n, w, r]));
|
||||
expect(graph.entity(n.id)).to.be.undefined;
|
||||
expect(graph.entity(w.id)).to.be.undefined;
|
||||
expect(graph.entity(r.id)).to.be.undefined;
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
describe("iD.actions.DeleteRelation", function () {
|
||||
it("removes the relation from the graph", function () {
|
||||
var relation = iD.Relation(),
|
||||
action = iD.actions.DeleteRelation(relation.id),
|
||||
graph = action(iD.Graph([relation]));
|
||||
expect(graph.entity(relation.id)).to.be.undefined;
|
||||
});
|
||||
|
||||
it("removes the relation from parent relations", function () {
|
||||
var a = iD.Relation(),
|
||||
b = iD.Relation(),
|
||||
parent = iD.Relation({members: [{ id: a.id }, { id: b.id }]}),
|
||||
action = iD.actions.DeleteRelation(a.id),
|
||||
graph = action(iD.Graph([a, b, parent]));
|
||||
expect(graph.entity(parent.id).members).to.eql([{ id: b.id }]);
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,9 @@
|
||||
describe("iD.actions.UnjoinNode", function () {
|
||||
describe("iD.actions.Disconnect", function () {
|
||||
describe("#enabled", function () {
|
||||
it("returns false for a node shared by less than two ways", function () {
|
||||
var graph = iD.Graph({'a': iD.Node()});
|
||||
|
||||
expect(iD.actions.UnjoinNode('a').enabled(graph)).to.equal(false);
|
||||
expect(iD.actions.Disconnect('a').enabled(graph)).to.equal(false);
|
||||
});
|
||||
|
||||
it("returns true for a node shared by two or more ways", function () {
|
||||
@@ -19,7 +19,7 @@ describe("iD.actions.UnjoinNode", function () {
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.UnjoinNode('b').enabled(graph)).to.equal(true);
|
||||
expect(iD.actions.Disconnect('b').enabled(graph)).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ describe("iD.actions.UnjoinNode", function () {
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.UnjoinNode('b', 'e')(graph);
|
||||
graph = iD.actions.Disconnect('b', 'e')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(graph.entity('|').nodes).to.eql(['d', 'e']);
|
||||
@@ -64,7 +64,7 @@ describe("iD.actions.UnjoinNode", function () {
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.UnjoinNode('b', 'e')(graph);
|
||||
graph = iD.actions.Disconnect('b', 'e')(graph);
|
||||
|
||||
// Immutable loc => should be shared by identity.
|
||||
expect(graph.entity('b').loc).to.equal(loc);
|
||||
@@ -0,0 +1,172 @@
|
||||
describe("iD.actions.Join", function () {
|
||||
describe("#enabled", function () {
|
||||
it("returns true for ways that share an end/start node", function () {
|
||||
// a --> b ==> c
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns true for ways that share a start/end node", function () {
|
||||
// a <-- b <== c
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['b', 'a']}),
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns true for ways that share a start/start node", function () {
|
||||
// a <-- b ==> c
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['b', 'a']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns true for ways that share an end/end node", function () {
|
||||
// a --> b <== c
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns false for ways that don't share the necessary nodes", function () {
|
||||
// a -- b -- c
|
||||
// |
|
||||
// d
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'd': iD.Node({id: 'd'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'd']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
it("joins a --> b ==> c", function () {
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
});
|
||||
|
||||
it("joins a <-- b <== c", function () {
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['b', 'a']}),
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['c', 'b', 'a']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
});
|
||||
|
||||
it("joins a <-- b ==> c", function () {
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
// tags on === reversed
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['b', 'a']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['c', 'b', 'a']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
});
|
||||
|
||||
it("joins a --> b <== c", function () {
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
// tags on === reversed
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
});
|
||||
|
||||
it("merges tags", function () {
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b'], tags: {a: 'a', b: '-', c: 'c'}}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c'], tags: {a: 'a', b: '=', d: 'd'}})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').tags).to.eql({a: 'a', b: '-; =', c: 'c', d: 'd'});
|
||||
});
|
||||
|
||||
it("merges relations", function () {
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']}),
|
||||
'r1': iD.Relation({id: 'r1', members: [{id: '=', role: 'r1'}]}),
|
||||
'r2': iD.Relation({id: 'r2', members: [{id: '=', role: 'r1'}, {id: '-', role: 'r2'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
|
||||
expect(graph.entity('r1').members).to.eql([{id: '-', role: 'r1'}]);
|
||||
expect(graph.entity('r2').members).to.eql([{id: '-', role: 'r2'}]);
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,9 @@
|
||||
describe("iD.actions.ReverseWay", function () {
|
||||
describe("iD.actions.Reverse", function () {
|
||||
it("reverses the order of nodes in the way", function () {
|
||||
var node1 = iD.Node(),
|
||||
node2 = iD.Node(),
|
||||
way = iD.Way({nodes: [node1.id, node2.id]}),
|
||||
graph = iD.actions.ReverseWay(way.id)(iD.Graph([node1, node2, way]));
|
||||
graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, way]));
|
||||
expect(graph.entity(way.id).nodes).to.eql([node2.id, node1.id]);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'highway': 'residential'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'highway': 'residential'});
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'oneway': 'yes'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'oneway': 'yes'});
|
||||
});
|
||||
|
||||
@@ -27,10 +27,10 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'cycleway:right': 'lane'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'cycleway:left': 'lane'});
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'cycleway:right': 'lane'});
|
||||
});
|
||||
|
||||
@@ -38,10 +38,10 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'maxspeed:forward': '25'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'maxspeed:backward': '25'});
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'maxspeed:forward': '25'});
|
||||
});
|
||||
|
||||
@@ -49,10 +49,10 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'incline': 'up'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': 'down'});
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': 'up'});
|
||||
});
|
||||
|
||||
@@ -60,10 +60,10 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'incline': 'up'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': 'down'});
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': 'up'});
|
||||
});
|
||||
|
||||
@@ -71,16 +71,16 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'incline': '5%'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': '-5%'});
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': '5%'});
|
||||
|
||||
way = iD.Way({tags: {'incline': '.8°'}});
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'incline': '-.8°'});
|
||||
});
|
||||
|
||||
@@ -88,10 +88,10 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'sidewalk': 'right'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'sidewalk': 'left'});
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'sidewalk': 'right'});
|
||||
});
|
||||
|
||||
@@ -99,7 +99,7 @@ describe("iD.actions.ReverseWay", function () {
|
||||
var way = iD.Way({tags: {'maxspeed:forward': '25', 'maxspeed:backward': '30'}}),
|
||||
graph = iD.Graph([way]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(way.id).tags).to.eql({'maxspeed:backward': '25', 'maxspeed:forward': '30'});
|
||||
});
|
||||
|
||||
@@ -108,10 +108,10 @@ describe("iD.actions.ReverseWay", function () {
|
||||
relation = iD.Relation({members: [{type: 'way', id: way.id, role: 'forward'}]}),
|
||||
graph = iD.Graph([way, relation]);
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(relation.id).members[0].role).to.eql('backward');
|
||||
|
||||
graph = iD.actions.ReverseWay(way.id)(graph);
|
||||
graph = iD.actions.Reverse(way.id)(graph);
|
||||
expect(graph.entity(relation.id).members[0].role).to.eql('forward');
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("iD.actions.SplitWay", function () {
|
||||
describe("iD.actions.Split", function () {
|
||||
describe("#enabled", function () {
|
||||
it("returns true for a non-end node of a single way", function () {
|
||||
var graph = iD.Graph({
|
||||
@@ -8,7 +8,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']})
|
||||
});
|
||||
|
||||
expect(iD.actions.SplitWay('b').enabled(graph)).to.be.true;
|
||||
expect(iD.actions.Split('b').enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns false for the first node of a single way", function () {
|
||||
@@ -18,7 +18,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.SplitWay('a').enabled(graph)).to.be.false;
|
||||
expect(iD.actions.Split('a').enabled(graph)).to.be.false;
|
||||
});
|
||||
|
||||
it("returns false for the last node of a single way", function () {
|
||||
@@ -28,7 +28,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.SplitWay('b').enabled(graph)).to.be.false;
|
||||
expect(iD.actions.Split('b').enabled(graph)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,7 +48,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b']);
|
||||
expect(graph.entity('=').nodes).to.eql(['b', 'c']);
|
||||
@@ -63,7 +63,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c'], tags: tags})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
// Immutable tags => should be shared by identity.
|
||||
expect(graph.entity('-').tags).to.equal(tags);
|
||||
@@ -92,7 +92,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b']);
|
||||
expect(graph.entity('=').nodes).to.eql(['b', 'c']);
|
||||
@@ -118,7 +118,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'r': iD.Relation({id: 'r', members: [{id: '-', type: 'way'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['-', '=']);
|
||||
});
|
||||
@@ -144,7 +144,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'r': iD.Relation({id: 'r', members: [{id: '-', type: 'way'}, {id: '~', type: 'way'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['-', '=', '~']);
|
||||
});
|
||||
@@ -170,7 +170,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'r': iD.Relation({id: 'r', members: [{id: '~', type: 'way'}, {id: '-', type: 'way'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['~', '=', '-']);
|
||||
});
|
||||
@@ -184,7 +184,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
'r': iD.Relation({id: 'r', members: [{id: '~', type: 'way'}, {id: '-', type: 'way'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(_.pluck(graph.entity('r').members, 'id')).to.eql(['~', '-', '=']);
|
||||
});
|
||||
@@ -214,7 +214,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
{id: 'c', role: 'via'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(graph.entity('r').members).to.eql([
|
||||
{id: '=', role: 'from'},
|
||||
@@ -246,7 +246,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
{id: 'c', role: 'via'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(graph.entity('r').members).to.eql([
|
||||
{id: '~', role: 'from'},
|
||||
@@ -278,7 +278,7 @@ describe("iD.actions.SplitWay", function () {
|
||||
{id: 'c', role: 'via'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.SplitWay('b', '=')(graph);
|
||||
graph = iD.actions.Split('b', '=')(graph);
|
||||
|
||||
expect(graph.entity('r').members).to.eql([
|
||||
{id: '-', role: 'from'},
|
||||
+33
-37
@@ -1,19 +1,18 @@
|
||||
describe("iD.behavior.Hash", function () {
|
||||
var hash, map, controller;
|
||||
mocha.globals('__onhashchange.hash');
|
||||
|
||||
var hash, context;
|
||||
|
||||
beforeEach(function () {
|
||||
map = {
|
||||
on: function () { return map; },
|
||||
zoom: function () { return arguments.length ? map : 0; },
|
||||
center: function () { return arguments.length ? map : [0, 0]; },
|
||||
centerZoom: function () { return arguments.length ? map : [0, 0]; }
|
||||
};
|
||||
context = iD();
|
||||
|
||||
controller = {
|
||||
on: function () { return controller; }
|
||||
};
|
||||
// Neuter connection
|
||||
context.connection().loadTiles = function () {};
|
||||
|
||||
hash = iD.behavior.Hash(controller, map);
|
||||
hash = iD.behavior.Hash(context);
|
||||
|
||||
d3.select(document.createElement('div'))
|
||||
.call(context.map());
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
@@ -22,44 +21,41 @@ describe("iD.behavior.Hash", function () {
|
||||
|
||||
it("sets hadHash if location.hash is present", function () {
|
||||
location.hash = "map=20.00/38.87952/-77.02405";
|
||||
|
||||
hash();
|
||||
|
||||
expect(hash.hadHash).to.be.true;
|
||||
});
|
||||
|
||||
it("centerZooms map to requested level", function () {
|
||||
location.hash = "map=20.00/38.87952/-77.02405";
|
||||
sinon.spy(map, 'centerZoom');
|
||||
|
||||
hash();
|
||||
expect(map.centerZoom).to.have.been.calledWith([-77.02405,38.87952], 20.0);
|
||||
|
||||
expect(context.map().center()[0]).to.be.closeTo(-77.02405, 0.1);
|
||||
expect(context.map().center()[1]).to.be.closeTo(38.87952, 0.1);
|
||||
expect(context.map().zoom()).to.equal(20.0);
|
||||
});
|
||||
|
||||
describe("on window hashchange events", function () {
|
||||
beforeEach(function () {
|
||||
hash();
|
||||
it("centerZooms map at requested coordinates on hash change", function (done) {
|
||||
hash();
|
||||
|
||||
d3.select(window).one('hashchange', function () {
|
||||
expect(context.map().center()[0]).to.be.closeTo(-77.02405, 0.1);
|
||||
expect(context.map().center()[1]).to.be.closeTo(38.87952, 0.1);
|
||||
expect(context.map().zoom()).to.equal(20.0);
|
||||
done();
|
||||
});
|
||||
|
||||
function onhashchange(fn) {
|
||||
d3.select(window).one("hashchange", fn);
|
||||
}
|
||||
|
||||
it("centerZooms map at requested coordinates", function (done) {
|
||||
onhashchange(function () {
|
||||
expect(map.centerZoom).to.have.been.calledWith([-77.02405,38.87952], 20.0);
|
||||
done();
|
||||
});
|
||||
|
||||
sinon.spy(map, 'centerZoom');
|
||||
location.hash = "#map=20.00/38.87952/-77.02405";
|
||||
});
|
||||
location.hash = "#map=20.00/38.87952/-77.02405";
|
||||
});
|
||||
|
||||
describe("on map move events", function () {
|
||||
it("stores the current zoom and coordinates in location.hash", function () {
|
||||
sinon.stub(map, 'on')
|
||||
.withArgs("move.hash", sinon.match.instanceOf(Function))
|
||||
.yields();
|
||||
hash();
|
||||
expect(location.hash).to.equal("#map=0.00/0/0");
|
||||
});
|
||||
it("stores the current zoom and coordinates in location.hash on map move events", function () {
|
||||
hash();
|
||||
|
||||
context.map().center([38.9, -77.0]);
|
||||
context.map().zoom(2.0);
|
||||
|
||||
expect(location.hash).to.equal("#map=2.00/-77.0/38.9");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
describe("iD.behavior.Select", function() {
|
||||
var a, b, context, behavior, container;
|
||||
|
||||
beforeEach(function() {
|
||||
container = d3.select('body').append('div');
|
||||
|
||||
context = iD().container(container);
|
||||
|
||||
a = iD.Node({loc: [0, 0]});
|
||||
b = iD.Node({loc: [0, 0]});
|
||||
|
||||
context.perform(iD.actions.AddEntity(a), iD.actions.AddEntity(b));
|
||||
|
||||
container.call(context.map())
|
||||
.append('div')
|
||||
.attr('class', 'inspector-wrap');
|
||||
|
||||
context.surface().selectAll('circle')
|
||||
.data([a, b])
|
||||
.enter().append('circle')
|
||||
.attr('class', function(d) { return d.id; });
|
||||
|
||||
behavior = iD.behavior.Select(context);
|
||||
context.install(behavior);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
context.uninstall(behavior);
|
||||
container.remove();
|
||||
});
|
||||
|
||||
specify("click on entity selects the entity", function() {
|
||||
happen.click(context.surface().select('.' + a.id).node());
|
||||
expect(context.selection()).to.eql([a.id]);
|
||||
});
|
||||
|
||||
specify("click on empty space clears the selection", function() {
|
||||
context.enter(iD.modes.Select(context, [a.id]));
|
||||
happen.click(context.surface().node());
|
||||
expect(context.selection()).to.eql([]);
|
||||
});
|
||||
|
||||
specify("shift-click on entity adds the entity to the selection", function() {
|
||||
context.enter(iD.modes.Select(context, [a.id]));
|
||||
happen.click(context.surface().select('.' + b.id).node(), {shiftKey: true});
|
||||
expect(context.selection()).to.eql([a.id, b.id]);
|
||||
});
|
||||
|
||||
specify("shift-click on empty space leaves the selection unchanged", function() {
|
||||
context.enter(iD.modes.Select(context, [a.id]));
|
||||
happen.click(context.surface().node(), {shiftKey: true});
|
||||
expect(context.selection()).to.eql([a.id]);
|
||||
});
|
||||
});
|
||||
@@ -2,7 +2,8 @@ describe('iD.Connection', function () {
|
||||
var c;
|
||||
|
||||
beforeEach(function () {
|
||||
c = new iD.Connection();
|
||||
context = iD();
|
||||
c = new iD.Connection(context);
|
||||
});
|
||||
|
||||
it('is instantiated', function () {
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
describe("iD.Difference", function () {
|
||||
describe("#changes", function () {
|
||||
it("includes created entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph(),
|
||||
head = base.replace(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.changes()).to.eql({n: {base: undefined, head: node}});
|
||||
});
|
||||
|
||||
it("includes undone created entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph(),
|
||||
head = base.replace(node),
|
||||
diff = iD.Difference(head, base);
|
||||
expect(diff.changes()).to.eql({n: {base: node, head: undefined}});
|
||||
});
|
||||
|
||||
it("includes modified entities", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.update(),
|
||||
base = iD.Graph([n1]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.changes()).to.eql({n: {base: n1, head: n2}});
|
||||
});
|
||||
|
||||
it("includes undone modified entities", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.update(),
|
||||
base = iD.Graph([n1]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(head, base);
|
||||
expect(diff.changes()).to.eql({n: {base: n2, head: n1}});
|
||||
});
|
||||
|
||||
it("includes deleted entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph([node]),
|
||||
head = base.remove(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.changes()).to.eql({n: {base: node, head: undefined}});
|
||||
});
|
||||
|
||||
it("includes undone deleted entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph([node]),
|
||||
head = base.remove(node),
|
||||
diff = iD.Difference(head, base);
|
||||
expect(diff.changes()).to.eql({n: {base: undefined, head: node}});
|
||||
});
|
||||
|
||||
it("doesn't include created entities that were subsequently deleted", function () {
|
||||
var node = iD.Node(),
|
||||
base = iD.Graph(),
|
||||
head = base.replace(node).remove(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.changes()).to.eql({});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#extantIDs", function () {
|
||||
it("includes the ids of created entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph(),
|
||||
head = base.replace(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.extantIDs()).to.eql(['n']);
|
||||
});
|
||||
|
||||
it("includes the ids of modified entities", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
base = iD.Graph([n1]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.extantIDs()).to.eql(['n']);
|
||||
});
|
||||
|
||||
it("omits the ids of deleted entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph([node]),
|
||||
head = base.remove(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.extantIDs()).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#created", function () {
|
||||
it("returns an array of created entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph(),
|
||||
head = base.replace(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.created()).to.eql([node]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#modified", function () {
|
||||
it("returns an array of modified entities", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
base = iD.Graph([n1]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.modified()).to.eql([n2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#deleted", function () {
|
||||
it("returns an array of deleted entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph([node]),
|
||||
head = base.remove(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.deleted()).to.eql([node]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#complete", function () {
|
||||
it("includes created entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph(),
|
||||
head = base.replace(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.complete()['n']).to.equal(node);
|
||||
});
|
||||
|
||||
it("includes modified entities", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
base = iD.Graph([n1]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.complete()['n']).to.equal(n2);
|
||||
});
|
||||
|
||||
it("includes deleted entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
base = iD.Graph([node]),
|
||||
head = base.remove(node),
|
||||
diff = iD.Difference(base, head);
|
||||
expect(diff.complete()).to.eql({n: undefined});
|
||||
});
|
||||
|
||||
it("includes nodes added to a way", function () {
|
||||
var n1 = iD.Node({id: 'n1'}),
|
||||
n2 = iD.Node({id: 'n2'}),
|
||||
w1 = iD.Way({id: 'w', nodes: ['n1']}),
|
||||
w2 = w1.addNode('n2'),
|
||||
base = iD.Graph([n1, n2, w1]),
|
||||
head = base.replace(w2),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()['n2']).to.equal(n2);
|
||||
});
|
||||
|
||||
it("includes nodes removed from a way", function () {
|
||||
var n1 = iD.Node({id: 'n1'}),
|
||||
n2 = iD.Node({id: 'n2'}),
|
||||
w1 = iD.Way({id: 'w', nodes: ['n1', 'n2']}),
|
||||
w2 = w1.removeNode('n2'),
|
||||
base = iD.Graph([n1, n2, w1]),
|
||||
head = base.replace(w2),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()['n2']).to.equal(n2);
|
||||
});
|
||||
|
||||
it("includes parent ways of modified nodes", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
way = iD.Way({id: 'w', nodes: ['n']}),
|
||||
base = iD.Graph([n1, way]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()['w']).to.equal(way);
|
||||
});
|
||||
|
||||
it("includes parent relations of modified entities", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
rel = iD.Relation({id: 'r', members: [{id: 'n'}]}),
|
||||
base = iD.Graph([n1, rel]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()['r']).to.equal(rel);
|
||||
});
|
||||
|
||||
it("includes parent relations of modified entities, recursively", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
rel1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
|
||||
rel2 = iD.Relation({id: 'r2', members: [{id: 'r1'}]}),
|
||||
base = iD.Graph([n1, rel1, rel2]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()['r2']).to.equal(rel2);
|
||||
});
|
||||
|
||||
it("includes parent relations of parent ways of modified nodes", function () {
|
||||
var n1 = iD.Node({id: 'n'}),
|
||||
n2 = n1.move([1, 2]),
|
||||
way = iD.Way({id: 'w', nodes: ['n']}),
|
||||
rel = iD.Relation({id: 'r', members: [{id: 'w'}]}),
|
||||
base = iD.Graph([n1, way, rel]),
|
||||
head = base.replace(n2),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()['r']).to.equal(rel);
|
||||
});
|
||||
|
||||
it("copes with recursive relations", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
rel1 = iD.Relation({id: 'r1', members: [{id: 'n'}, {id: 'r2'}]}),
|
||||
rel2 = iD.Relation({id: 'r2', members: [{id: 'r1'}]}),
|
||||
base = iD.Graph([node, rel1, rel2]),
|
||||
head = base.replace(node.move([1, 2])),
|
||||
diff = iD.Difference(base, head);
|
||||
|
||||
expect(diff.complete()).to.be.ok;
|
||||
});
|
||||
|
||||
it("limits changes to those within a given extent");
|
||||
});
|
||||
});
|
||||
+27
-42
@@ -52,12 +52,6 @@ describe('iD.Entity', function () {
|
||||
expect(e.id).to.equal('w1');
|
||||
});
|
||||
|
||||
it("tags the entity as updated", function () {
|
||||
var tags = {foo: 'bar'},
|
||||
e = iD.Entity().update({tags: tags});
|
||||
expect(e._updated).to.to.be.true;
|
||||
});
|
||||
|
||||
it("doesn't modify the input", function () {
|
||||
var attrs = {tags: {foo: 'bar'}},
|
||||
e = iD.Entity().update(attrs);
|
||||
@@ -69,6 +63,33 @@ describe('iD.Entity', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#mergeTags", function () {
|
||||
it("returns a new Entity", function () {
|
||||
var a = iD.Entity(),
|
||||
b = a.mergeTags({});
|
||||
expect(b instanceof iD.Entity).to.be.true;
|
||||
expect(a).not.to.equal(b);
|
||||
});
|
||||
|
||||
it("merges tags", function () {
|
||||
var a = iD.Entity({tags: {a: 'a'}}),
|
||||
b = a.mergeTags({b: 'b'});
|
||||
expect(b.tags).to.eql({a: 'a', b: 'b'});
|
||||
});
|
||||
|
||||
it("combines non-conflicting tags", function () {
|
||||
var a = iD.Entity({tags: {a: 'a'}}),
|
||||
b = a.mergeTags({a: 'a'});
|
||||
expect(b.tags).to.eql({a: 'a'});
|
||||
});
|
||||
|
||||
it("combines conflicting tags with semicolons", function () {
|
||||
var a = iD.Entity({tags: {a: 'a'}}),
|
||||
b = a.mergeTags({a: 'b'});
|
||||
expect(b.tags).to.eql({a: 'a; b'});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#osmId", function () {
|
||||
it("returns an OSM ID as a string", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).osmId()).to.eql('1234');
|
||||
@@ -77,42 +98,6 @@ describe('iD.Entity', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#created", function () {
|
||||
it("returns falsy by default", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).created()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("returns falsy for an unmodified Entity", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).created()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("returns falsy for a modified Entity with positive ID", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).update({}).created()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("returns truthy for a modified Entity with negative ID", function () {
|
||||
expect(iD.Entity({id: 'w-1234'}).update({}).created()).to.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#modified", function () {
|
||||
it("returns falsy by default", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).modified()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("returns falsy for an unmodified Entity", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).modified()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("returns truthy for a modified Entity with positive ID", function () {
|
||||
expect(iD.Entity({id: 'w1234'}).update({}).modified()).to.be.ok;
|
||||
});
|
||||
|
||||
it("returns falsy for a modified Entity with negative ID", function () {
|
||||
expect(iD.Entity({id: 'w-1234'}).update({}).modified()).not.to.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#intersects", function () {
|
||||
it("returns true for a way with a node within the given extent", function () {
|
||||
var node = iD.Node({loc: [0, 0]}),
|
||||
|
||||
@@ -333,86 +333,4 @@ describe('iD.Graph', function() {
|
||||
expect(graph.childNodes(way)).to.eql([node]);
|
||||
});
|
||||
});
|
||||
|
||||
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, and reverse", function () {
|
||||
var node = iD.Node(),
|
||||
graph1 = iD.Graph(),
|
||||
graph2 = graph1.replace(node);
|
||||
expect(graph2.difference(graph1)).to.eql([node.id]);
|
||||
expect(graph1.difference(graph2)).to.eql([node.id]);
|
||||
});
|
||||
|
||||
it("includes entities changed from base, and reverse", function () {
|
||||
var node = iD.Node(),
|
||||
graph1 = iD.Graph(node),
|
||||
graph2 = graph1.replace(node.update());
|
||||
expect(graph2.difference(graph1)).to.eql([node.id]);
|
||||
expect(graph1.difference(graph2)).to.eql([node.id]);
|
||||
});
|
||||
|
||||
it("includes already changed entities that were updated, and reverse", function () {
|
||||
var node = iD.Node(),
|
||||
graph1 = iD.Graph().replace(node),
|
||||
graph2 = graph1.replace(node.update());
|
||||
expect(graph2.difference(graph1)).to.eql([node.id]);
|
||||
expect(graph1.difference(graph2)).to.eql([node.id]);
|
||||
});
|
||||
|
||||
it("includes affected child nodes", function () {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
n2 = iD.Node({id: 'n2'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['n']}),
|
||||
w1_ = iD.Way({id: 'w1', nodes: ['n', 'n2']}),
|
||||
graph1 = iD.Graph([n, n2, w1]),
|
||||
graph2 = graph1.replace(w1_);
|
||||
expect(graph2.difference(graph1)).to.eql(['n2', 'w1']);
|
||||
expect(graph1.difference(graph2)).to.eql(['n2', 'w1']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("#modified", function () {
|
||||
it("returns an Array of ids of modified entities", function () {
|
||||
var node = iD.Node({id: 'n1'}),
|
||||
node_ = iD.Node({id: 'n1'}),
|
||||
graph = iD.Graph([node]).replace(node_);
|
||||
expect(graph.modified()).to.eql([node.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#created", function () {
|
||||
it("returns an Array of ids of created entities", function () {
|
||||
var node1 = iD.Node({id: 'n-1'}),
|
||||
node2 = iD.Node({id: 'n2'}),
|
||||
graph = iD.Graph([node2]).replace(node1);
|
||||
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().replace(node).remove(node);
|
||||
expect(graph.deleted()).to.eql([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+45
-10
@@ -13,7 +13,25 @@ describe("iD.History", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#merge", function () {
|
||||
it("merges the entities into all graph versions", function () {
|
||||
var n = iD.Node({id: 'n'});
|
||||
history.merge({n: n});
|
||||
expect(history.graph().entity('n')).to.equal(n);
|
||||
});
|
||||
|
||||
it("emits a change event", function () {
|
||||
history.on('change', spy);
|
||||
history.merge({});
|
||||
expect(spy).to.have.been.called;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#perform", function () {
|
||||
it("returns a difference", function () {
|
||||
expect(history.perform(action).changes()).to.eql({});
|
||||
});
|
||||
|
||||
it("updates the graph", function () {
|
||||
var node = iD.Node();
|
||||
history.perform(function (graph) { return graph.replace(node); });
|
||||
@@ -27,8 +45,8 @@ describe("iD.History", function () {
|
||||
|
||||
it("emits a change event", function () {
|
||||
history.on('change', spy);
|
||||
history.perform(action);
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
var difference = history.perform(action);
|
||||
expect(spy).to.have.been.calledWith(difference);
|
||||
});
|
||||
|
||||
it("performs multiple actions", function () {
|
||||
@@ -42,6 +60,10 @@ describe("iD.History", function () {
|
||||
});
|
||||
|
||||
describe("#replace", function () {
|
||||
it("returns a difference", function () {
|
||||
expect(history.replace(action).changes()).to.eql({});
|
||||
});
|
||||
|
||||
it("updates the graph", function () {
|
||||
var node = iD.Node();
|
||||
history.replace(function (graph) { return graph.replace(node); });
|
||||
@@ -56,8 +78,8 @@ describe("iD.History", function () {
|
||||
|
||||
it("emits a change event", function () {
|
||||
history.on('change', spy);
|
||||
history.replace(action);
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
var difference = history.replace(action);
|
||||
expect(spy).to.have.been.calledWith(difference);
|
||||
});
|
||||
|
||||
it("performs multiple actions", function () {
|
||||
@@ -71,6 +93,11 @@ describe("iD.History", function () {
|
||||
});
|
||||
|
||||
describe("#pop", function () {
|
||||
it("returns a difference", function () {
|
||||
history.perform(action, "annotation");
|
||||
expect(history.pop().changes()).to.eql({});
|
||||
});
|
||||
|
||||
it("updates the graph", function () {
|
||||
history.perform(action, "annotation");
|
||||
history.pop();
|
||||
@@ -86,12 +113,16 @@ describe("iD.History", function () {
|
||||
it("emits a change event", function () {
|
||||
history.perform(action);
|
||||
history.on('change', spy);
|
||||
history.pop();
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
var difference = history.pop();
|
||||
expect(spy).to.have.been.calledWith(difference);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#undo", function () {
|
||||
it("returns a difference", function () {
|
||||
expect(history.undo().changes()).to.eql({});
|
||||
});
|
||||
|
||||
it("pops the undo stack", function () {
|
||||
history.perform(action, "annotation");
|
||||
history.undo();
|
||||
@@ -121,12 +152,16 @@ describe("iD.History", function () {
|
||||
it("emits a change event", function () {
|
||||
history.perform(action);
|
||||
history.on('change', spy);
|
||||
history.undo();
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
var difference = history.undo();
|
||||
expect(spy).to.have.been.calledWith(difference);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#redo", function () {
|
||||
it("returns a difference", function () {
|
||||
expect(history.redo().changes()).to.eql({});
|
||||
});
|
||||
|
||||
it("emits an redone event", function () {
|
||||
history.perform(action);
|
||||
history.undo();
|
||||
@@ -139,8 +174,8 @@ describe("iD.History", function () {
|
||||
history.perform(action);
|
||||
history.undo();
|
||||
history.on('change', spy);
|
||||
history.redo();
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
var difference = history.redo();
|
||||
expect(spy).to.have.been.calledWith(difference);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -4,15 +4,6 @@ describe('iD.Node', function () {
|
||||
expect(iD.Node().type).to.equal("node");
|
||||
});
|
||||
|
||||
it("returns a created Entity if no ID is specified", function () {
|
||||
expect(iD.Node().created()).to.be.ok;
|
||||
});
|
||||
|
||||
it("returns an unmodified Entity if ID is specified", function () {
|
||||
expect(iD.Node({id: 'n1234'}).created()).not.to.be.ok;
|
||||
expect(iD.Node({id: 'n1234'}).modified()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("defaults tags to an empty object", function () {
|
||||
expect(iD.Node().tags).to.eql({});
|
||||
});
|
||||
|
||||
@@ -10,15 +10,6 @@ describe('iD.Relation', function () {
|
||||
expect(iD.Relation().type).to.equal("relation");
|
||||
});
|
||||
|
||||
it("returns a created Entity if no ID is specified", function () {
|
||||
expect(iD.Relation().created()).to.be.ok;
|
||||
});
|
||||
|
||||
it("returns an unmodified Entity if ID is specified", function () {
|
||||
expect(iD.Relation({id: 'r1234'}).created()).not.to.be.ok;
|
||||
expect(iD.Relation({id: 'r1234'}).modified()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("defaults members to an empty array", function () {
|
||||
expect(iD.Relation().members).to.eql([]);
|
||||
});
|
||||
|
||||
@@ -10,15 +10,6 @@ describe('iD.Way', function() {
|
||||
expect(iD.Way().type).to.equal("way");
|
||||
});
|
||||
|
||||
it("returns a created Entity if no ID is specified", function () {
|
||||
expect(iD.Way().created()).to.be.ok;
|
||||
});
|
||||
|
||||
it("returns an unmodified Entity if ID is specified", function () {
|
||||
expect(iD.Way({id: 'w1234'}).created()).not.to.be.ok;
|
||||
expect(iD.Way({id: 'w1234'}).modified()).not.to.be.ok;
|
||||
});
|
||||
|
||||
it("defaults nodes to an empty array", function () {
|
||||
expect(iD.Way().nodes).to.eql([]);
|
||||
});
|
||||
|
||||
@@ -1,41 +1,36 @@
|
||||
describe("iD.modes.AddPoint", function () {
|
||||
var container, map, history, controller, mode;
|
||||
var context;
|
||||
|
||||
beforeEach(function () {
|
||||
container = d3.select('body').append('div');
|
||||
history = iD.History();
|
||||
map = iD.Map().history(history);
|
||||
controller = iD.Controller(map, history);
|
||||
var container = d3.select(document.createElement('div'));
|
||||
|
||||
container.call(map);
|
||||
container.append('div')
|
||||
context = iD()
|
||||
.container(container);
|
||||
|
||||
container.call(context.map())
|
||||
.append('div')
|
||||
.attr('class', 'inspector-wrap');
|
||||
|
||||
mode = iD.modes.AddPoint();
|
||||
controller.enter(mode);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.remove();
|
||||
context.enter(iD.modes.AddPoint(context));
|
||||
});
|
||||
|
||||
describe("clicking the map", function () {
|
||||
it("adds a node", function () {
|
||||
happen.click(map.surface.node(), {});
|
||||
expect(history.changes().created).to.have.length(1);
|
||||
happen.click(context.surface().node(), {});
|
||||
expect(context.changes().created).to.have.length(1);
|
||||
});
|
||||
|
||||
it("selects the node", function () {
|
||||
happen.click(map.surface.node(), {});
|
||||
expect(controller.mode.id).to.equal('select');
|
||||
expect(controller.mode.selection()).to.eql([history.changes().created[0].id]);
|
||||
happen.click(context.surface().node(), {});
|
||||
expect(context.mode().id).to.equal('select');
|
||||
expect(context.mode().selection()).to.eql([context.changes().created[0].id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing ⎋", function () {
|
||||
it("exits to browse mode", function () {
|
||||
happen.keydown(document, {keyCode: 27});
|
||||
expect(controller.mode.id).to.equal('browse');
|
||||
expect(context.mode().id).to.equal('browse');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@ describe('iD.OAuth', function() {
|
||||
var o;
|
||||
|
||||
beforeEach(function() {
|
||||
o = iD.OAuth();
|
||||
context = iD();
|
||||
o = iD.OAuth(context);
|
||||
});
|
||||
|
||||
describe('#logout', function() {
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
describe('iD.Map', function() {
|
||||
var container, map;
|
||||
var map;
|
||||
|
||||
beforeEach(function() {
|
||||
container = d3.select('body').append('div');
|
||||
map = iD.Map();
|
||||
container.call(map);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.remove();
|
||||
});
|
||||
|
||||
describe('#connection', function() {
|
||||
it('gets and sets connection', function() {
|
||||
var connection = iD.Connection();
|
||||
expect(map.connection(connection)).to.equal(map);
|
||||
expect(map.connection()).to.equal(connection);
|
||||
});
|
||||
map = iD().map();
|
||||
d3.select(document.createElement('div'))
|
||||
.call(map);
|
||||
});
|
||||
|
||||
describe('#zoom', function() {
|
||||
|
||||
@@ -2,10 +2,13 @@ describe("iD.ui.confirm", function () {
|
||||
it('can be instantiated', function () {
|
||||
var confirm = iD.ui.confirm();
|
||||
expect(confirm).to.be.ok;
|
||||
happen.keydown(document, {keyCode: 27}); // dismiss
|
||||
});
|
||||
|
||||
it('can be dismissed', function () {
|
||||
var confirm = iD.ui.confirm();
|
||||
happen.click(confirm.select('button').node());
|
||||
expect(confirm.node().parentNode).to.be.null;
|
||||
happen.keydown(document, {keyCode: 27}); // dismiss
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,5 +4,6 @@ describe("iD.ui.modal", function () {
|
||||
.select('.content')
|
||||
.text('foo');
|
||||
expect(modal).to.be.ok;
|
||||
happen.keydown(document, {keyCode: 27}); // dismiss
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user