mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 17:23:02 +00:00
resolved conflict
This commit is contained in:
16
css/app.css
16
css/app.css
@@ -1064,7 +1064,17 @@ div.typeahead a:first-child {
|
||||
}
|
||||
|
||||
.Browse .tooltip .tooltip-arrow {
|
||||
left: 30px;
|
||||
}
|
||||
|
||||
left: 30px;
|
||||
}
|
||||
|
||||
.tail {
|
||||
pointer-events:none;
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
max-width: 250px;
|
||||
margin-top: -15px;
|
||||
padding: 5px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
13
css/map.css
13
css/map.css
@@ -65,9 +65,12 @@ g.vertex circle.stroke {
|
||||
fill:#333;
|
||||
}
|
||||
|
||||
g.vertex.shared circle {
|
||||
g.vertex.shared circle.fill {
|
||||
fill:#aff;
|
||||
}
|
||||
g.vertex.shared circle.stroke {
|
||||
fill:#044;
|
||||
}
|
||||
|
||||
g.vertex.hover circle.fill {
|
||||
-webkit-transform:scale(1.5, 1.5);
|
||||
@@ -81,9 +84,12 @@ g.vertex.hover circle.stroke {
|
||||
transform:scale(1.4, 1.4);
|
||||
}
|
||||
|
||||
g.vertex circle.selected {
|
||||
g.vertex circle.selected.fill {
|
||||
fill: #ffff00;
|
||||
}
|
||||
g.vertex circle.selected.stroke {
|
||||
fill: #38380A;
|
||||
}
|
||||
|
||||
circle.midpoint {
|
||||
fill:#aaa;
|
||||
@@ -252,9 +258,6 @@ path.casing.tag-highway-secondary_link {
|
||||
stroke:#444;
|
||||
}
|
||||
|
||||
path.stroke.tag-bridge-yes {
|
||||
stroke:#eee;
|
||||
}
|
||||
path.casing.tag-bridge-yes {
|
||||
stroke-width: 14;
|
||||
stroke: #000;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<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/queue.js'></script>
|
||||
<script src='js/lib/bootstrap-tooltip.js'></script>
|
||||
@@ -31,7 +32,6 @@
|
||||
<script src='js/id/oauth.js'></script>
|
||||
<script src='js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src='js/id/renderer/style.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>
|
||||
|
||||
@@ -16,6 +16,7 @@ iD.Connection = function() {
|
||||
function bboxFromAPI(box, tile, callback) {
|
||||
function done(err, parsed) {
|
||||
loadedTiles[tile.toString()] = true;
|
||||
delete inflight[tile.toString()];
|
||||
callback(err, parsed);
|
||||
}
|
||||
inflight[tile.toString()] = loadFromURL(bboxUrl(box), done);
|
||||
@@ -26,8 +27,6 @@ iD.Connection = function() {
|
||||
return callback(null, parse(dom));
|
||||
}
|
||||
return d3.xml(url).get().on('load', done);
|
||||
inflight.push(d3.xml(url).get()
|
||||
.on('load', done));
|
||||
}
|
||||
|
||||
function getNodes(obj) {
|
||||
@@ -201,7 +200,7 @@ iD.Connection = function() {
|
||||
}
|
||||
|
||||
function loadTiles(projection) {
|
||||
var scaleExtent = [16, 16],
|
||||
var scaleExtent = [15, 15],
|
||||
s = projection.scale(),
|
||||
tiles = d3.geo.tile()
|
||||
.scaleExtent(scaleExtent)
|
||||
|
||||
@@ -13,6 +13,7 @@ iD.Graph = function(entities) {
|
||||
this.transients = {};
|
||||
this._parentWays = {};
|
||||
this._parentRels = {};
|
||||
this._fetches = {};
|
||||
|
||||
if (iD.debug) {
|
||||
Object.freeze(this);
|
||||
@@ -119,20 +120,29 @@ iD.Graph.prototype = {
|
||||
|
||||
// Resolve the id references in a way, replacing them with actual objects.
|
||||
fetch: function(id) {
|
||||
if (this._fetches[id]) return this._fetches[id];
|
||||
var entity = this.entities[id], nodes = [];
|
||||
if (!entity || !entity.nodes || !entity.nodes.length) return entity;
|
||||
for (var i = 0, l = entity.nodes.length; i < l; i++) {
|
||||
nodes[i] = this.fetch(entity.nodes[i]);
|
||||
}
|
||||
return iD.Entity(entity, {nodes: nodes});
|
||||
return (this._fetches[id] = iD.Entity(entity, {nodes: nodes}));
|
||||
},
|
||||
|
||||
difference: function (graph) {
|
||||
var result = [], entity, id;
|
||||
var result = [], entity, oldentity, id;
|
||||
|
||||
for (id in this.entities) {
|
||||
entity = this.entities[id];
|
||||
if (entity !== graph.entities[id]) {
|
||||
oldentity = graph.entities[id];
|
||||
if (entity !== oldentity) {
|
||||
if (entity && entity.type === 'way') {
|
||||
result = oldentity ?
|
||||
result
|
||||
.concat(_.difference(entity.nodes, oldentity.nodes))
|
||||
.concat(_.difference(oldentity.nodes, entity.nodes))
|
||||
: result.concat(entity.nodes);
|
||||
}
|
||||
result.push(id);
|
||||
}
|
||||
}
|
||||
@@ -141,6 +151,7 @@ iD.Graph.prototype = {
|
||||
entity = graph.entities[id];
|
||||
if (entity && !this.entities.hasOwnProperty(id)) {
|
||||
result.push(id);
|
||||
if (entity.type === 'way') result = result.concat(entity.nodes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ iD.Way = iD.Entity.extend({
|
||||
return resolver.transient(this, 'extent', function() {
|
||||
var extent = [[-Infinity, Infinity], [Infinity, -Infinity]];
|
||||
for (var i = 0, l = this.nodes.length; i < l; i++) {
|
||||
var node = resolver.entity(this.nodes[i]);
|
||||
var node = this.nodes[i];
|
||||
if (node.loc === undefined) node = resolver.entity(node);
|
||||
if (node.loc[0] > extent[0][0]) extent[0][0] = node.loc[0];
|
||||
if (node.loc[0] < extent[1][0]) extent[1][0] = node.loc[0];
|
||||
if (node.loc[1] < extent[0][1]) extent[0][1] = node.loc[1];
|
||||
|
||||
@@ -183,9 +183,9 @@ window.iD = function(container) {
|
||||
.call(redo ? refreshTooltip : undo_tooltip.hide);
|
||||
});
|
||||
|
||||
window.onresize = function() {
|
||||
d3.select(window).on('resize.map-size', function() {
|
||||
map.size(m.size());
|
||||
};
|
||||
});
|
||||
|
||||
map.keybinding()
|
||||
.on('a', function(evt, mods) {
|
||||
|
||||
@@ -12,7 +12,7 @@ iD.modes.AddArea = function() {
|
||||
controller = mode.controller;
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.hint('Click on the map to start drawing an area, like a park, lake, or building.');
|
||||
.tail('Click on the map to start drawing an area, like a park, lake, or building.');
|
||||
|
||||
map.surface.on('click.addarea', function() {
|
||||
var datum = d3.select(d3.event.target).datum() || {},
|
||||
@@ -23,8 +23,7 @@ iD.modes.AddArea = function() {
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, datum.id),
|
||||
iD.actions.AddWayNode(way.id, datum.id),
|
||||
'started an area');
|
||||
iD.actions.AddWayNode(way.id, datum.id));
|
||||
|
||||
} else {
|
||||
// start from a new node
|
||||
@@ -33,8 +32,7 @@ iD.modes.AddArea = function() {
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
'started an area');
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
}
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id));
|
||||
@@ -49,7 +47,7 @@ iD.modes.AddArea = function() {
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
mode.map.hint(false);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addarea', null);
|
||||
mode.map.keybinding().on('⎋.addarea', null);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ iD.modes.AddLine = function() {
|
||||
controller = mode.controller;
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.hint('Click on the map to start drawing an road, path, or route.');
|
||||
.tail('Click on the map to start drawing an road, path, or route.');
|
||||
|
||||
map.surface.on('click.addline', function() {
|
||||
var datum = d3.select(d3.event.target).datum() || {},
|
||||
@@ -33,8 +33,7 @@ iD.modes.AddLine = function() {
|
||||
} else {
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, datum.id),
|
||||
'started a line');
|
||||
iD.actions.AddWayNode(way.id, datum.id));
|
||||
}
|
||||
|
||||
} else if (datum.type === 'way') {
|
||||
@@ -46,8 +45,7 @@ iD.modes.AddLine = function() {
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(datum.id, node.id, choice.index),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
'started a line');
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
} else {
|
||||
// begin a new way
|
||||
@@ -56,8 +54,7 @@ iD.modes.AddLine = function() {
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
'started a line');
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
}
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, direction));
|
||||
@@ -70,7 +67,7 @@ iD.modes.AddLine = function() {
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
mode.map.hint(false);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addline', null);
|
||||
mode.map.keybinding().on('⎋.addline', null);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ iD.modes.AddPoint = function() {
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
map.hint('Click on the map to add a point.');
|
||||
map.tail('Click on the map to add a point.');
|
||||
|
||||
map.surface.on('click.addpoint', function() {
|
||||
var node = iD.Node({loc: map.mouseCoordinates(), _poi: true});
|
||||
@@ -28,7 +28,7 @@ iD.modes.AddPoint = function() {
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.hint(false);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addpoint', null);
|
||||
mode.map.keybinding().on('⎋.addpoint', null);
|
||||
};
|
||||
|
||||
@@ -18,8 +18,7 @@ iD.modes.DrawArea = function(wayId) {
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.fastEnable(false);
|
||||
map.hint('Click on the map to add points to your area. Finish the ' +
|
||||
'area by clicking on your first point');
|
||||
map.tail('Click to add points to your area. Click the first point to finish the area.');
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
@@ -42,22 +41,28 @@ iD.modes.DrawArea = function(wayId) {
|
||||
var datum = d3.select(d3.event.target).datum() || {};
|
||||
|
||||
if (datum.id === tailId || datum.id === headId) {
|
||||
history.replace(iD.actions.DeleteNode(node.id));
|
||||
controller.enter(iD.modes.Select(way));
|
||||
if (way.nodes.length > 3) {
|
||||
history.undo();
|
||||
controller.enter(iD.modes.Select(way));
|
||||
} else {
|
||||
// Areas with less than 3 nodes gets deleted
|
||||
history.replace(iD.actions.DeleteWay(way.id));
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
} else if (datum.type === 'node' && datum.id !== node.id) {
|
||||
// connect the way to an existing node
|
||||
history.replace(
|
||||
iD.actions.DeleteNode(node.id),
|
||||
iD.actions.AddWayNode(way.id, datum.id, -1),
|
||||
'added to an area');
|
||||
way.nodes.length > 2 ? 'added to an area' : '');
|
||||
|
||||
controller.enter(iD.modes.DrawArea(wayId));
|
||||
|
||||
} else {
|
||||
history.replace(
|
||||
iD.actions.Noop(),
|
||||
'added to an area');
|
||||
way.nodes.length > 2 ? 'added to an area' : '');
|
||||
|
||||
controller.enter(iD.modes.DrawArea(wayId));
|
||||
}
|
||||
@@ -110,7 +115,7 @@ iD.modes.DrawArea = function(wayId) {
|
||||
surface.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
mode.map.hint(false);
|
||||
mode.map.tail(false);
|
||||
mode.map.fastEnable(true);
|
||||
|
||||
surface
|
||||
|
||||
@@ -19,7 +19,7 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.fastEnable(false)
|
||||
.hint('Click to add more points to the line. ' +
|
||||
.tail('Click to add more points to the line. ' +
|
||||
'Click on other lines to connect to them, and double-click to ' +
|
||||
'end the line.');
|
||||
|
||||
@@ -42,16 +42,22 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
|
||||
if (datum.id === tailId) {
|
||||
// connect the way in a loop
|
||||
history.replace(
|
||||
iD.actions.DeleteNode(node.id),
|
||||
iD.actions.AddWayNode(wayId, tailId, index),
|
||||
'added to a line');
|
||||
if (way.nodes.length > 2) {
|
||||
history.replace(
|
||||
iD.actions.DeleteNode(node.id),
|
||||
iD.actions.AddWayNode(wayId, tailId, index),
|
||||
'added to a line');
|
||||
|
||||
controller.enter(iD.modes.Select(way));
|
||||
controller.enter(iD.modes.Select(way));
|
||||
|
||||
} else {
|
||||
history.replace(iD.actions.DeleteWay(way.id));
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
} else if (datum.id === headId) {
|
||||
// finish the way
|
||||
history.replace(iD.actions.DeleteNode(node.id));
|
||||
history.undo();
|
||||
|
||||
controller.enter(iD.modes.Select(way));
|
||||
|
||||
@@ -146,7 +152,7 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
surface.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
mode.map.hint(false);
|
||||
mode.map.tail(false);
|
||||
mode.map.fastEnable(true);
|
||||
mode.map.minzoom(0);
|
||||
|
||||
|
||||
@@ -87,11 +87,12 @@ iD.modes.Select = function (entity) {
|
||||
|
||||
// Exit mode if selected entity gets undone
|
||||
mode.history.on('change.entity-undone', function() {
|
||||
var old = entity;
|
||||
entity = mode.history.graph().entity(entity.id);
|
||||
if (!entity) {
|
||||
mode.controller.enter(iD.modes.Browse());
|
||||
} else {
|
||||
d3.select('.inspector-wrap').datum(entity).call(inspector);
|
||||
} else if(!_.isEqual(entity.tags, old.tags)) {
|
||||
inspector.tags(entity.tags);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -138,7 +139,7 @@ iD.modes.Select = function (entity) {
|
||||
mode.exit = function () {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
changeTags(entity, inspector.tags());
|
||||
entity && changeTags(entity, inspector.tags());
|
||||
d3.select('.inspector-wrap')
|
||||
.style('display', 'none')
|
||||
.html('');
|
||||
|
||||
@@ -55,14 +55,36 @@ iD.Background = function() {
|
||||
ups = {};
|
||||
|
||||
tiles.forEach(function(d) {
|
||||
d.push(source(d));
|
||||
// this tile has not been loaded yet
|
||||
if (!cache[d] &&
|
||||
cache[atZoom(d, -1)] &&
|
||||
|
||||
// if this tile has already failed, do
|
||||
// not request it
|
||||
if (cache[d] !== false) d.push(source(d));
|
||||
|
||||
// if this tile has failed, try to request its tile above
|
||||
if (cache[d] === false &&
|
||||
cache[atZoom(d, -1)] !== false &&
|
||||
!ups[atZoom(d, -1)]) {
|
||||
|
||||
ups[atZoom(d, -1)] = true;
|
||||
tiles.push(atZoom(d, -1));
|
||||
} else if (!cache[d]) {
|
||||
|
||||
// if this tile has not finished, req the one above
|
||||
} else if (cache[d] === undefined &&
|
||||
|
||||
// but the tile above is in the cache
|
||||
cache[atZoom(d, -1)] &&
|
||||
|
||||
// and another tile has not already requested the
|
||||
// tile above
|
||||
!ups[atZoom(d, -1)]) {
|
||||
|
||||
ups[atZoom(d, -1)] = true;
|
||||
tiles.push(atZoom(d, -1));
|
||||
|
||||
// if this tile has not yet completed, try keeping the
|
||||
// tiles below it
|
||||
} else if (cache[d] === undefined ||
|
||||
cache[d] === false) {
|
||||
upZoom(d, 1).forEach(function(u) {
|
||||
if (cache[u] && !ups[u]) {
|
||||
ups[u] = true;
|
||||
@@ -79,11 +101,12 @@ iD.Background = function() {
|
||||
image.exit().remove();
|
||||
|
||||
function load(d) {
|
||||
cache[d] = true;
|
||||
cache[d.slice(0, 3)] = true;
|
||||
d3.select(this).on('load', null);
|
||||
}
|
||||
|
||||
function error() {
|
||||
function error(d) {
|
||||
cache[d.slice(0, 3)] = false;
|
||||
d3.select(this).remove();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ iD.Map = function() {
|
||||
lines = iD.svg.Lines(),
|
||||
areas = iD.svg.Areas(),
|
||||
midpoints = iD.svg.Midpoints(),
|
||||
tail = d3.tail(),
|
||||
surface, tilegroup;
|
||||
|
||||
function map(selection) {
|
||||
@@ -29,14 +30,14 @@ iD.Map = function() {
|
||||
|
||||
var supersurface = selection.append('div')
|
||||
.style('position', 'absolute')
|
||||
.on('mousedown.drag', function() {
|
||||
translateStart = projection.translate();
|
||||
})
|
||||
.call(zoom);
|
||||
|
||||
surface = supersurface.append('svg')
|
||||
.on('mouseup.reset-transform', resetTransform)
|
||||
.on('touchend.reset-transform', resetTransform)
|
||||
.on('mousedown.drag', function() {
|
||||
translateStart = projection.translate();
|
||||
})
|
||||
.on('mousedown.zoom', function() {
|
||||
if (d3.event.button == 2) {
|
||||
d3.event.stopPropagation();
|
||||
@@ -44,9 +45,13 @@ iD.Map = function() {
|
||||
})
|
||||
.call(iD.svg.Surface());
|
||||
|
||||
|
||||
map.size(selection.size());
|
||||
map.surface = surface;
|
||||
|
||||
supersurface
|
||||
.call(tail);
|
||||
|
||||
d3.select(document).call(keybinding);
|
||||
}
|
||||
|
||||
@@ -62,16 +67,22 @@ iD.Map = function() {
|
||||
all = graph.intersects(extent);
|
||||
filter = d3.functor(true);
|
||||
} else {
|
||||
var only = {};
|
||||
var only = {},
|
||||
filterOnly = {};
|
||||
for (var j = 0; j < difference.length; j++) {
|
||||
var id = difference[j];
|
||||
only[id] = graph.fetch(id);
|
||||
if (only[id] && only[id].type === 'node') {
|
||||
var parents = graph.parentWays(only[id]);
|
||||
for (var k = 0; k < parents.length; k++) {
|
||||
// Don't re-fetch parents
|
||||
if (only[parents[k].id] === undefined) {
|
||||
only[parents[k].id] = graph.fetch(parents[k].id);
|
||||
var id = difference[j],
|
||||
entity = graph.fetch(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)) {
|
||||
if (only[id].type === 'node') {
|
||||
var parents = graph.parentWays(only[id]);
|
||||
for (var k = 0; k < parents.length; k++) {
|
||||
// Don't re-fetch parents
|
||||
if (only[parents[k].id] === undefined) {
|
||||
only[parents[k].id] = graph.fetch(parents[k].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +91,7 @@ iD.Map = function() {
|
||||
filter = function(d) { return d.midpoint ? d.way in only : d.id in only; };
|
||||
}
|
||||
|
||||
if (all.length > 10000) {
|
||||
if (all.length > 100000) {
|
||||
editOff();
|
||||
return;
|
||||
}
|
||||
@@ -113,14 +124,14 @@ iD.Map = function() {
|
||||
if (Math.log(d3.event.scale / Math.LN2 - 8) < minzoom + 1) {
|
||||
iD.flash()
|
||||
.select('.content')
|
||||
.text('Cannot zoom out further in current mode.')
|
||||
.text('Cannot zoom out further in current mode.');
|
||||
return map.zoom(16);
|
||||
}
|
||||
var fast = (d3.event.scale === projection.scale() && fastEnabled);
|
||||
projection
|
||||
.translate(d3.event.translate)
|
||||
.scale(d3.event.scale);
|
||||
if (fast) {
|
||||
if (fast && translateStart) {
|
||||
var a = d3.event.translate,
|
||||
b = translateStart,
|
||||
translate = 'translate(' + ~~(a[0] - b[0]) + 'px,' +
|
||||
@@ -278,6 +289,11 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.tail = function (_) {
|
||||
tail.text(_);
|
||||
return map;
|
||||
};
|
||||
|
||||
map.hint = function (_) {
|
||||
if (_ === false) {
|
||||
d3.select('div.inspector-wrap')
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
iD.Style = {};
|
||||
|
||||
// all styling that is done outside of CSS in iD.
|
||||
//
|
||||
// Since SVG does not support z-index, we sort roads manually with d3's `sort`
|
||||
// and the `waystack` fn.
|
||||
//
|
||||
// This also chooses kosher CSS classes for ways, and images for points
|
||||
|
||||
iD.Style.highway_stack = {
|
||||
motorway: 0,
|
||||
motorway_link: 1,
|
||||
trunk: 2,
|
||||
trunk_link: 3,
|
||||
primary: 4,
|
||||
primary_link: 5,
|
||||
secondary: 6,
|
||||
tertiary: 7,
|
||||
unclassified: 8,
|
||||
residential: 9,
|
||||
service: 10,
|
||||
footway: 11
|
||||
};
|
||||
|
||||
iD.Style.waystack = function(a, b) {
|
||||
if (!a || !b) return 0;
|
||||
if (a.tags.layer !== undefined && b.tags.layer !== undefined) {
|
||||
return a.tags.layer - b.tags.layer;
|
||||
}
|
||||
if (a.tags.bridge) return 1;
|
||||
if (b.tags.bridge) return -1;
|
||||
var as = 0, bs = 0;
|
||||
if (a.tags.highway && b.tags.highway) {
|
||||
as -= iD.Style.highway_stack[a.tags.highway];
|
||||
bs -= iD.Style.highway_stack[b.tags.highway];
|
||||
}
|
||||
return as - bs;
|
||||
};
|
||||
@@ -33,6 +33,25 @@ iD.taginfo = function() {
|
||||
return _.omit(parameters, 'geometry');
|
||||
}
|
||||
|
||||
function popularKeys(parameters) {
|
||||
var pop_field = 'count_all_fraction';
|
||||
if (parameters.filter) pop_field = 'count_' + parameters.filter + '_fraction';
|
||||
return function(d) { return parseFloat(d[pop_field]) > 0.01; };
|
||||
}
|
||||
|
||||
function popularValues(parameters) {
|
||||
return function(d) { return parseFloat(d['fraction']) > 0.01; };
|
||||
}
|
||||
|
||||
function valKey(d) { return { value: d.key }; }
|
||||
|
||||
function valKeyDescription(d) {
|
||||
return {
|
||||
value: d.value,
|
||||
title: d.description
|
||||
};
|
||||
}
|
||||
|
||||
taginfo.keys = function(parameters, callback) {
|
||||
parameters = clean(setSort(setFilter(parameters)));
|
||||
d3.json(endpoint + 'keys/all?' +
|
||||
@@ -41,7 +60,10 @@ iD.taginfo = function() {
|
||||
sortname: 'count_all',
|
||||
sortorder: 'desc',
|
||||
page: 1
|
||||
}, parameters)), callback);
|
||||
}, parameters)), function(err, d) {
|
||||
if (err) return callback(err);
|
||||
callback(null, d.data.filter(popularKeys(parameters)).map(valKey));
|
||||
});
|
||||
};
|
||||
|
||||
taginfo.values = function(parameters, callback) {
|
||||
@@ -52,7 +74,10 @@ iD.taginfo = function() {
|
||||
sortname: 'count_all',
|
||||
sortorder: 'desc',
|
||||
page: 1
|
||||
}, parameters)), callback);
|
||||
}, parameters)), function(err, d) {
|
||||
if (err) return callback(err);
|
||||
callback(null, d.data.filter(popularValues()).map(valKeyDescription));
|
||||
});
|
||||
};
|
||||
|
||||
taginfo.docs = function(parameters, callback) {
|
||||
|
||||
@@ -2,13 +2,13 @@ iD.svg = {
|
||||
RoundProjection: function (projection) {
|
||||
return function (d) {
|
||||
return iD.util.geo.roundCoords(projection(d));
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
PointTransform: function (projection) {
|
||||
projection = iD.svg.RoundProjection(projection);
|
||||
return function (entity) {
|
||||
return 'translate(' + projection(entity.loc) + ')';
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
iD.svg.Areas = function() {
|
||||
return function(surface, graph, entities, filter, projection) {
|
||||
|
||||
var area_stack = {
|
||||
building: 0,
|
||||
manmade: 1,
|
||||
natural: 1,
|
||||
boundary: 2
|
||||
};
|
||||
|
||||
function findKey(a) {
|
||||
var vals = Object.keys(a.tags).filter(function(k) {
|
||||
return area_stack[k] !== undefined;
|
||||
});
|
||||
if (vals.length > 0) return area_stack[vals[0]];
|
||||
else return -1;
|
||||
}
|
||||
|
||||
function areastack(a, b) {
|
||||
if (!a || !b || !a.tags || !b.tags) return 0;
|
||||
if (a.tags.layer !== undefined && b.tags.layer !== undefined) {
|
||||
return a.tags.layer - b.tags.layer;
|
||||
}
|
||||
var as = 0, bs = 0;
|
||||
as -= findKey(a);
|
||||
bs -= findKey(b);
|
||||
return as - bs;
|
||||
}
|
||||
|
||||
return function drawAreas(surface, graph, entities, filter, projection) {
|
||||
var areas = [];
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
@@ -9,6 +36,8 @@ iD.svg.Areas = function() {
|
||||
}
|
||||
}
|
||||
|
||||
areas.sort(areastack);
|
||||
|
||||
var lineStrings = {};
|
||||
|
||||
function lineString(entity) {
|
||||
|
||||
@@ -1,16 +1,68 @@
|
||||
iD.svg.Lines = function() {
|
||||
|
||||
var arrowtext = '►\u3000\u3000',
|
||||
alength;
|
||||
var arrowtext = '►\u3000\u3000',
|
||||
alength;
|
||||
|
||||
var highway_stack = {
|
||||
motorway: 0,
|
||||
motorway_link: 1,
|
||||
trunk: 2,
|
||||
trunk_link: 3,
|
||||
primary: 4,
|
||||
primary_link: 5,
|
||||
secondary: 6,
|
||||
tertiary: 7,
|
||||
unclassified: 8,
|
||||
residential: 9,
|
||||
service: 10,
|
||||
footway: 11
|
||||
};
|
||||
|
||||
function waystack(a, b) {
|
||||
if (!a || !b || !a.tags || !b.tags) return 0;
|
||||
if (a.tags.layer !== undefined && b.tags.layer !== undefined) {
|
||||
return a.tags.layer - b.tags.layer;
|
||||
}
|
||||
if (a.tags.bridge) return 1;
|
||||
if (b.tags.bridge) return -1;
|
||||
var as = 0, bs = 0;
|
||||
if (a.tags.highway && b.tags.highway) {
|
||||
as -= highway_stack[a.tags.highway];
|
||||
bs -= highway_stack[b.tags.highway];
|
||||
}
|
||||
return as - bs;
|
||||
}
|
||||
|
||||
function drawPaths(group, lines, filter, classes, lineString) {
|
||||
var paths = group.selectAll('path')
|
||||
.filter(filter)
|
||||
.data(lines, iD.Entity.key);
|
||||
|
||||
paths.enter()
|
||||
.append('path')
|
||||
.attr('class', classes);
|
||||
|
||||
paths
|
||||
.order()
|
||||
.attr('d', lineString)
|
||||
.call(iD.svg.TagClasses());
|
||||
|
||||
paths.exit()
|
||||
.remove();
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
return function drawLines(surface, graph, entities, filter, projection) {
|
||||
|
||||
return function(surface, graph, entities, filter, projection) {
|
||||
if (!alength) {
|
||||
var arrow = surface.append('text').text(arrowtext);
|
||||
alength = arrow.node().getComputedTextLength();
|
||||
arrow.remove();
|
||||
}
|
||||
|
||||
var lines = [];
|
||||
var lines = [],
|
||||
lineStrings = {};
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
var entity = entities[i];
|
||||
@@ -19,7 +71,7 @@ iD.svg.Lines = function() {
|
||||
}
|
||||
}
|
||||
|
||||
var lineStrings = {};
|
||||
lines.sort(waystack);
|
||||
|
||||
function lineString(entity) {
|
||||
if (lineStrings[entity.id] !== undefined) {
|
||||
@@ -31,32 +83,12 @@ iD.svg.Lines = function() {
|
||||
'M' + nodes.map(iD.svg.RoundProjection(projection)).join('L'));
|
||||
}
|
||||
|
||||
function drawPaths(group, lines, filter, classes) {
|
||||
var paths = group.selectAll('path')
|
||||
.filter(filter)
|
||||
.data(lines, iD.Entity.key);
|
||||
|
||||
paths.enter()
|
||||
.append('path')
|
||||
.attr('class', classes);
|
||||
|
||||
paths
|
||||
.order()
|
||||
.attr('d', lineString)
|
||||
.call(iD.svg.TagClasses());
|
||||
|
||||
paths.exit()
|
||||
.remove();
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
var casing = surface.select('.layer-casing'),
|
||||
stroke = surface.select('.layer-stroke'),
|
||||
defs = surface.select('defs'),
|
||||
text = surface.select('.layer-text'),
|
||||
casings = drawPaths(casing, lines, filter, 'way line casing'),
|
||||
strokes = drawPaths(stroke, lines, filter, 'way line stroke');
|
||||
casings = drawPaths(casing, lines, filter, 'way line casing', lineString),
|
||||
strokes = drawPaths(stroke, lines, filter, 'way line stroke', lineString);
|
||||
|
||||
// Determine the lengths of oneway paths
|
||||
var lengths = {},
|
||||
@@ -97,5 +129,5 @@ iD.svg.Lines = function() {
|
||||
// adding longer text than necessary, since overflow is hidden
|
||||
return (new Array(Math.floor(lengths[d.id] * 1.1))).join(arrowtext);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
iD.svg.Midpoints = function() {
|
||||
return function(surface, graph, entities, filter, projection) {
|
||||
return function drawMidpoints(surface, graph, entities, filter, projection) {
|
||||
var midpoints = [];
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
|
||||
@@ -10,7 +10,7 @@ iD.svg.Points = function() {
|
||||
return 'icons/unknown.png';
|
||||
}
|
||||
|
||||
return function(surface, graph, entities, filter, projection) {
|
||||
return function drawPoints(surface, graph, entities, filter, projection) {
|
||||
var points = [];
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
@@ -20,6 +20,10 @@ iD.svg.Points = function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (points.length > 100) {
|
||||
return surface.select('.layer-hit').selectAll('g.point').remove();
|
||||
}
|
||||
|
||||
var groups = surface.select('.layer-hit').selectAll('g.point')
|
||||
.filter(filter)
|
||||
.data(points, iD.Entity.key);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
iD.svg.Surface = function() {
|
||||
return function(selection) {
|
||||
return function drawSurface(selection) {
|
||||
selection.append('defs')
|
||||
.append('clipPath')
|
||||
.attr('id', 'clip')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
iD.svg.Vertices = function() {
|
||||
return function(surface, graph, entities, filter, projection) {
|
||||
return function drawVertices(surface, graph, entities, filter, projection) {
|
||||
var vertices = [];
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
@@ -9,6 +9,10 @@ iD.svg.Vertices = function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (vertices.length > 2000) {
|
||||
return surface.select('.layer-hit').selectAll('g.vertex').remove();
|
||||
}
|
||||
|
||||
var groups = surface.select('.layer-hit').selectAll('g.vertex')
|
||||
.filter(filter)
|
||||
.data(vertices, iD.Entity.key);
|
||||
|
||||
@@ -83,6 +83,7 @@ iD.ui.inspector = function() {
|
||||
}
|
||||
|
||||
function drawButtons(selection) {
|
||||
<<<<<<< HEAD
|
||||
var inspectorButton1 = selection.append('div')
|
||||
.attr('class', 'button-wrap')
|
||||
.append('button')
|
||||
@@ -111,7 +112,8 @@ iD.ui.inspector = function() {
|
||||
tags = [{key: '', value: ''}];
|
||||
}
|
||||
|
||||
var li = tagList.selectAll('li')
|
||||
var li = tagList.html('')
|
||||
.selectAll('li')
|
||||
.data(tags, function(d) { return d.key; });
|
||||
|
||||
li.exit().remove();
|
||||
@@ -166,7 +168,6 @@ iD.ui.inspector = function() {
|
||||
if (en.on_node) types.push('point');
|
||||
if (en.on_way) types.push('line');
|
||||
en.types = types;
|
||||
console.log(en);
|
||||
iD.ui.modal()
|
||||
.select('.content')
|
||||
.datum(en)
|
||||
@@ -225,15 +226,26 @@ iD.ui.inspector = function() {
|
||||
key = row.selectAll('.key'),
|
||||
value = row.selectAll('.value');
|
||||
|
||||
function sort(value, data) {
|
||||
var sameletter = [],
|
||||
other = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i].value.substring(0, value.length) === value) {
|
||||
sameletter.push(data[i]);
|
||||
} else {
|
||||
other.push(data[i]);
|
||||
}
|
||||
}
|
||||
return sameletter.concat(other);
|
||||
}
|
||||
|
||||
key.call(d3.typeahead()
|
||||
.data(_.debounce(function(_, callback) {
|
||||
taginfo.keys({
|
||||
geometry: geometry,
|
||||
query: key.property('value')
|
||||
}, function(err, data) {
|
||||
callback(data.data.map(function (d) {
|
||||
return {value: d.key};
|
||||
}));
|
||||
if (!err) callback(sort(key.property('value'), data));
|
||||
});
|
||||
}, 500)));
|
||||
|
||||
@@ -244,9 +256,7 @@ iD.ui.inspector = function() {
|
||||
geometry: geometry,
|
||||
query: value.property('value')
|
||||
}, function(err, data) {
|
||||
callback(data.data.map(function (d) {
|
||||
return {value: d.value, title: d.description};
|
||||
}));
|
||||
if (!err) callback(sort(value.property('value'), data));
|
||||
});
|
||||
}, 500)));
|
||||
}
|
||||
@@ -272,15 +282,19 @@ iD.ui.inspector = function() {
|
||||
event.close(entity);
|
||||
}
|
||||
|
||||
inspector.tags = function () {
|
||||
var tags = {};
|
||||
tagList.selectAll('li').each(function() {
|
||||
var row = d3.select(this),
|
||||
key = row.selectAll('.key').property('value'),
|
||||
value = row.selectAll('.value').property('value');
|
||||
if (key !== '') tags[key] = value;
|
||||
});
|
||||
return tags;
|
||||
inspector.tags = function (tags) {
|
||||
if (!arguments.length) {
|
||||
var tags = {};
|
||||
tagList.selectAll('li').each(function() {
|
||||
var row = d3.select(this),
|
||||
key = row.selectAll('.key').property('value'),
|
||||
value = row.selectAll('.value').property('value');
|
||||
if (key !== '') tags[key] = value;
|
||||
});
|
||||
return tags;
|
||||
} else {
|
||||
drawTags(tags);
|
||||
}
|
||||
};
|
||||
|
||||
return d3.rebind(inspector, event, 'on');
|
||||
|
||||
70
js/lib/d3.tail.js
Normal file
70
js/lib/d3.tail.js
Normal file
@@ -0,0 +1,70 @@
|
||||
d3.tail = function() {
|
||||
var text = false,
|
||||
container,
|
||||
xmargin = 20,
|
||||
tooltip_size = [0, 0],
|
||||
selection_size = [0, 0],
|
||||
transformProp = iD.util.prefixCSSProperty('Transform');
|
||||
|
||||
var tail = function(selection) {
|
||||
|
||||
d3.select(window).on('resize.tail-size', function() {
|
||||
selection_size = selection.size();
|
||||
});
|
||||
|
||||
function setup() {
|
||||
|
||||
container = d3.select(document.body)
|
||||
.append('div').attr('class', 'tail');
|
||||
|
||||
selection
|
||||
.on('mousemove.tail', mousemove)
|
||||
.on('mouseover.tail', mouseover)
|
||||
.on('mouseout.tail', mouseout);
|
||||
|
||||
container
|
||||
.on('mousemove.tail', mousemove);
|
||||
|
||||
selection_size = selection.size();
|
||||
|
||||
}
|
||||
|
||||
function mousemove() {
|
||||
if (text === false) return;
|
||||
var xoffset = ((d3.event.x + tooltip_size[0] + xmargin) > selection_size[0]) ?
|
||||
-tooltip_size[0] - xmargin : xoffset = xmargin;
|
||||
container.style(transformProp, 'translate(' +
|
||||
(~~d3.event.x + xoffset) + 'px,' +
|
||||
~~d3.event.y + 'px)');
|
||||
}
|
||||
|
||||
function mouseout() {
|
||||
if (d3.event.relatedTarget !== container.node() &&
|
||||
text !== false) container.style('display', 'none');
|
||||
}
|
||||
|
||||
function mouseover() {
|
||||
if (d3.event.relatedTarget !== container.node() &&
|
||||
text !== false) container.style('display', 'block');
|
||||
}
|
||||
|
||||
if (!container) setup();
|
||||
|
||||
};
|
||||
|
||||
tail.text = function(_) {
|
||||
if (_ === false) {
|
||||
text = _;
|
||||
container.style('display', 'none');
|
||||
return tail;
|
||||
} else if (container.style('display') == 'none') {
|
||||
container.style('display', 'block');
|
||||
}
|
||||
text = _;
|
||||
container.text(text);
|
||||
tooltip_size = container.size();
|
||||
return tail;
|
||||
};
|
||||
|
||||
return tail;
|
||||
};
|
||||
@@ -2,7 +2,7 @@ d3.typeahead = function() {
|
||||
var data;
|
||||
|
||||
var typeahead = function(selection) {
|
||||
var container, hidden, idx = 0;
|
||||
var container, hidden, idx = -1;
|
||||
|
||||
function setup() {
|
||||
var rect = selection.node().getBoundingClientRect();
|
||||
@@ -20,7 +20,7 @@ d3.typeahead = function() {
|
||||
|
||||
function hide() {
|
||||
container.remove();
|
||||
idx = 0;
|
||||
idx = -1;
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
@@ -33,14 +33,17 @@ d3.typeahead = function() {
|
||||
.on('blur.typeahead', slowHide);
|
||||
|
||||
function key() {
|
||||
var len = container.selectAll('a').data().length;
|
||||
if (d3.event.keyCode === 40) {
|
||||
idx++;
|
||||
idx = Math.min(idx + 1, len - 1);
|
||||
return highlight();
|
||||
} else if (d3.event.keyCode === 38) {
|
||||
idx--;
|
||||
idx = Math.max(idx - 1, 0);
|
||||
return highlight();
|
||||
} else if (d3.event.keyCode === 13) {
|
||||
select(container.select('a.selected').datum());
|
||||
if (container.select('a.selected').node()) {
|
||||
select(container.select('a.selected').datum());
|
||||
}
|
||||
hide();
|
||||
} else {
|
||||
update();
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
<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/renderer/style.js'></script>
|
||||
|
||||
<script src="../js/id/svg.js"></script>
|
||||
<script src="../js/id/svg/areas.js"></script>
|
||||
@@ -55,6 +54,9 @@
|
||||
<script src='../js/id/ui/userpanel.js'></script>
|
||||
<script src='../js/id/ui/geocoder.js'></script>
|
||||
<script src='../js/id/ui/notice.js'></script>
|
||||
<script src='../js/id/ui/modal.js'></script>
|
||||
<script src='../js/id/ui/flash.js'></script>
|
||||
<script src='../js/id/ui/confirm.js'></script>
|
||||
|
||||
<script src='../js/id/actions.js'></script>
|
||||
<script src='../js/id/actions/add_node.js'></script>
|
||||
@@ -152,6 +154,10 @@
|
||||
|
||||
<script src="spec/ui/inspector.js"></script>
|
||||
<script src="spec/ui/geocoder.js"></script>
|
||||
<script src="spec/ui/modal.js"></script>
|
||||
<script src="spec/ui/flash.js"></script>
|
||||
<script src="spec/ui/confirm.js"></script>
|
||||
|
||||
<script src="spec/connection.js"></script>
|
||||
<script src="spec/oauth.js"></script>
|
||||
<script src="spec/taginfo.js"></script>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
describe("iD.taginfo", function() {
|
||||
var server;
|
||||
var server, taginfo;
|
||||
|
||||
beforeEach(function() {
|
||||
server = sinon.fakeServer.create();
|
||||
taginfo = iD.taginfo();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -15,46 +16,81 @@ describe("iD.taginfo", function() {
|
||||
|
||||
describe("#keys", function() {
|
||||
it("calls the given callback with the results of the keys query", function() {
|
||||
var taginfo = iD.taginfo(),
|
||||
callback = sinon.spy();
|
||||
|
||||
var callback = sinon.spy();
|
||||
taginfo.keys({query: "amen"}, callback);
|
||||
|
||||
server.respondWith("GET", new RegExp("http://taginfo.openstreetmap.org/api/4/keys/all"),
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"data":[{"count_all":5190337,"key":"amenity"}]}']);
|
||||
'{"data":[{"count_all":5190337,"key":"amenity","count_all_fraction":1.0}]}']);
|
||||
server.respond();
|
||||
|
||||
expect(query(server.requests[0].url)).to.eql(
|
||||
{query: "amen", page: "1", rp: "6", sortname: "count_all", sortorder: "desc"});
|
||||
expect(callback).to.have.been.calledWith(null,
|
||||
{"data":[{"count_all":5190337,"key":"amenity"}]});
|
||||
expect(callback).to.have.been.calledWith(null, [{"value":"amenity"}]);
|
||||
});
|
||||
|
||||
it("filters only popular nodes", function() {
|
||||
var callback = sinon.spy();
|
||||
taginfo.keys({query: "amen"}, callback);
|
||||
|
||||
server.respondWith("GET", new RegExp("http://taginfo.openstreetmap.org/api/4/keys/all"),
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"data":[{"count_all":5190337,"key":"amenity","count_all_fraction":1.0, "count_nodes_fraction":1.0},\
|
||||
{"count_all":1,"key":"amenityother","count_all_fraction":0.0, "count_nodes_fraction":0.0}]}']);
|
||||
server.respond();
|
||||
|
||||
expect(callback).to.have.been.calledWith(null, [{"value":"amenity"}]);
|
||||
});
|
||||
|
||||
it("filters only popular nodes with an entity type filter", function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
taginfo.keys({query: "amen", filter: "nodes"}, callback);
|
||||
|
||||
server.respondWith("GET", new RegExp("http://taginfo.openstreetmap.org/api/4/keys/all"),
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"data":[{"count_all":5190337,"key":"amenity","count_all_fraction":1.0, "count_nodes_fraction":1.0},\
|
||||
{"count_all":1,"key":"amenityother","count_all_fraction":0.0, "count_nodes_fraction":1.0}]}']);
|
||||
server.respond();
|
||||
|
||||
expect(callback).to.have.been.calledWith(null, [{"value":"amenity"},{"value":"amenityother"}]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#values", function() {
|
||||
it("calls the given callback with the results of the values query", function() {
|
||||
var taginfo = iD.taginfo(),
|
||||
callback = sinon.spy();
|
||||
var callback = sinon.spy();
|
||||
|
||||
taginfo.values({key: "amenity", query: "par"}, callback);
|
||||
|
||||
server.respondWith("GET", new RegExp("http://taginfo.openstreetmap.org/api/4/key/values"),
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"data":[{"value":"parking","description":"A place for parking cars"}]}']);
|
||||
'{"data":[{"value":"parking","description":"A place for parking cars", "fraction":0.1}]}']);
|
||||
server.respond();
|
||||
|
||||
expect(query(server.requests[0].url)).to.eql(
|
||||
{key: "amenity", query: "par", page: "1", rp: "20", sortname: 'count_all', sortorder: 'desc'});
|
||||
expect(callback).to.have.been.calledWith(null,
|
||||
{"data":[{"value":"parking","description":"A place for parking cars"}]});
|
||||
expect(callback).to.have.been.calledWith(null, [{"value":"parking","title":"A place for parking cars"}]);
|
||||
});
|
||||
|
||||
it("filters popular values", function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
taginfo.values({key: "amenity", query: "par"}, callback);
|
||||
|
||||
server.respondWith("GET", new RegExp("http://taginfo.openstreetmap.org/api/4/key/values"),
|
||||
[200, { "Content-Type": "application/json" },
|
||||
'{"data":[{"value":"parking","description":"A place for parking cars", "fraction":1.0},\
|
||||
{"value":"party","description":"A place for partying", "fraction":0.0}]}']);
|
||||
server.respond();
|
||||
|
||||
expect(callback).to.have.been.calledWith(null, [{"value":"parking","title":"A place for parking cars"}]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#docs", function() {
|
||||
it("calls the given callback with the results of the docs query", function() {
|
||||
var taginfo = iD.taginfo(),
|
||||
callback = sinon.spy();
|
||||
var callback = sinon.spy();
|
||||
|
||||
taginfo.docs({key: "amenity", value: "parking"}, callback);
|
||||
|
||||
|
||||
11
test/spec/ui/confirm.js
Normal file
11
test/spec/ui/confirm.js
Normal file
@@ -0,0 +1,11 @@
|
||||
describe("iD.ui.confirm", function () {
|
||||
it('can be instantiated', function () {
|
||||
var confirm = iD.ui.confirm();
|
||||
expect(confirm).to.be.ok;
|
||||
});
|
||||
it('can be dismissed', function () {
|
||||
var confirm = iD.ui.confirm();
|
||||
happen.click(confirm.select('button').node());
|
||||
expect(confirm.node().parentNode).to.be.null;
|
||||
});
|
||||
});
|
||||
13
test/spec/ui/flash.js
Normal file
13
test/spec/ui/flash.js
Normal file
@@ -0,0 +1,13 @@
|
||||
describe("iD.ui.flash", function () {
|
||||
it('can be instantiated', function () {
|
||||
var flash = iD.ui.flash();
|
||||
expect(flash).to.be.ok;
|
||||
});
|
||||
it('leaves after 1000 ms', function (done) {
|
||||
var flash = iD.ui.flash();
|
||||
window.setTimeout(function() {
|
||||
expect(flash.node().parentNode).to.be.null;
|
||||
done();
|
||||
}, 1200);
|
||||
});
|
||||
});
|
||||
8
test/spec/ui/modal.js
Normal file
8
test/spec/ui/modal.js
Normal file
@@ -0,0 +1,8 @@
|
||||
describe("iD.ui.modal", function () {
|
||||
it('can be instantiated', function () {
|
||||
var modal = iD.ui.modal()
|
||||
.select('.content')
|
||||
.text('foo');
|
||||
expect(modal).to.be.ok;
|
||||
});
|
||||
});
|
||||
@@ -61,5 +61,36 @@ describe('Util', function() {
|
||||
expect(iD.util.geo.dist(a, b)).to.eql(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#pointInPolygon', function() {
|
||||
it('says a point in a polygon is on a polygon', function() {
|
||||
var poly = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]];
|
||||
var point = [0.5, 0.5];
|
||||
expect(iD.util.geo.pointInPolygon(point, poly)).to.be.true;
|
||||
});
|
||||
it('says a point outside of a polygon is outside', function() {
|
||||
var poly = [
|
||||
[0, 0],
|
||||
[0, 1],
|
||||
[1, 1],
|
||||
[1, 0],
|
||||
[0, 0]];
|
||||
var point = [0.5, 1.5];
|
||||
expect(iD.util.geo.pointInPolygon(point, poly)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('#polygonContainsPolygon', function() {
|
||||
it('says a polygon in a polygon is in', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]];
|
||||
expect(iD.util.geo.polygonContainsPolygon(outer, inner)).to.be.true;
|
||||
});
|
||||
it('says a polygon outside of a polygon is out', function() {
|
||||
var outer = [[0, 0], [0, 3], [3, 3], [3, 0], [0, 0]];
|
||||
var inner = [[1, 1], [1, 9], [2, 2], [2, 1], [1, 1]];
|
||||
expect(iD.util.geo.polygonContainsPolygon(outer, inner)).to.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user