WIP: Move layer-hit to layer-points with explict sublayers, update tests

This is more work to further isolate the layers that entities draw to.
It makes it easier to debug what is going on, and can eventually lead to
deferred drawing, if each draw function is in its own place and not dependant
on anything else.

I've started to replace the vertex-hover with an explicit layer for touch
targets.

Also had to change a lot of the svg tests, which are really brittle.
Things would happen like - the surface would be created, it would kick of a
deferred redraw, which would notice that the zoom was 0 and call
editOff, which would remove the osm layers that were just created and
that the tests were trying to draw to. These tests need proper zoom and
projection otherwise nothing works.
This commit is contained in:
Bryan Housel
2017-12-14 17:38:43 -05:00
parent bfaf17538e
commit b9e48d1682
17 changed files with 405 additions and 339 deletions
+12 -3
View File
@@ -45,6 +45,7 @@ g.point.selected .shadow {
stroke-opacity: 0.7;
}
g.vertex.active, g.vertex.active *,
g.point.active, g.point.active * {
pointer-events: none;
}
@@ -88,6 +89,12 @@ g.midpoint .shadow {
fill-opacity: 0;
}
/*debug*/
.vertex.target {
fill: #f00;
fill-opacity: 0.5;
}
/*g.vertex.vertex-hover {
display: none;
}
@@ -99,6 +106,7 @@ g.midpoint .shadow {
.mode-add-point g.vertex.vertex-hover,
.mode-drag-node g.vertex.vertex-hover {
display: block;
color: #f00;
}
.mode-draw-area .hover-disabled g.vertex.vertex-hover,
@@ -110,8 +118,9 @@ g.midpoint .shadow {
display: none;
}
*/
g.vertex.related:not(.selected) .shadow,
g.vertex.hover:not(.selected) .shadow,
/*g.vertex.hover:not(.selected) .shadow,*/
g.midpoint.related:not(.selected) .shadow,
g.midpoint.hover:not(.selected) .shadow {
fill-opacity: 0.5;
@@ -262,11 +271,11 @@ g.turn circle {
}
path.gpx {
stroke: #FF26D4;
stroke: #ff26d4;
stroke-width: 2;
fill: none;
}
text.gpx {
fill: #FF26D4;
fill: #ff26d4;
}
+3 -3
View File
@@ -44,12 +44,12 @@
display: none;
}
*/
.mode-draw-line .way.active,
.mode-draw-area .way.active,
/*.mode-draw-line .active,
.mode-draw-area .active,
.mode-drag-node .active {
pointer-events: none;
}
*/
/* Ensure drawing doesn't interact with area fills. */
.mode-add-point path.area.fill,
.mode-draw-line path.area.fill,
+16 -16
View File
@@ -178,23 +178,23 @@ export function rendererMap(context) {
})
.on('mousemove.map', function() {
mousemove = d3_event;
})
.on('mouseover.vertices', function() {
if (map.editable() && !transformed) {
var hover = d3_event.target.__data__;
surface.selectAll('.data-layer-osm')
.call(drawVertices.drawHover, context.graph(), hover, map.extent());
dispatch.call('drawn', this, { full: false });
}
})
.on('mouseout.vertices', function() {
if (map.editable() && !transformed) {
var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
surface.selectAll('.data-layer-osm')
.call(drawVertices.drawHover, context.graph(), hover, map.extent());
dispatch.call('drawn', this, { full: false });
}
});
// .on('mouseover.vertices', function() {
// if (map.editable() && !transformed) {
// var hover = d3_event.target.__data__;
// surface.selectAll('.data-layer-osm')
// .call(drawVertices.drawHover, context.graph(), hover, map.extent());
// dispatch.call('drawn', this, { full: false });
// }
// })
// .on('mouseout.vertices', function() {
// if (map.editable() && !transformed) {
// var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
// surface.selectAll('.data-layer-osm')
// .call(drawVertices.drawHover, context.graph(), hover, map.extent());
// dispatch.call('drawn', this, { full: false });
// }
// });
supersurface
.call(context.background());
-10
View File
@@ -676,20 +676,10 @@ export function svgLabels(projection, context) {
var layer = selection.selectAll('.layer-labels');
var groups = layer.selectAll('.layer-labels-group')
.data(['halo','label','debug']);
groups = groups.enter()
.append('g')
.attr('class', function(d) { return 'layer-labels-group layer-labels-' + d; })
.merge(groups);
var halo = layer.selectAll('.layer-labels-halo');
var label = layer.selectAll('.layer-labels-label');
var debug = layer.selectAll('.layer-labels-debug');
// points
drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
+1 -1
View File
@@ -16,7 +16,7 @@ import {
export function svgMidpoints(projection, context) {
return function drawMidpoints(selection, graph, entities, filter, extent) {
var layer = selection.selectAll('.layer-hit');
var layer = selection.selectAll('.layer-points .layer-points-midpoints');
var mode = context.mode();
if (mode && mode.id !== 'select') {
+13 -1
View File
@@ -4,10 +4,22 @@ export function svgOsm(projection, context, dispatch) {
function drawOsm(selection) {
selection.selectAll('.layer-osm')
.data(['areas', 'lines', 'hit', 'labels'])
.data(['areas', 'lines', 'points', 'labels'])
.enter()
.append('g')
.attr('class', function(d) { return 'layer-osm layer-' + d; });
selection.selectAll('.layer-points').selectAll('.layer-points-group')
.data(['points', 'midpoints', 'vertices', 'turns', 'targets'])
.enter()
.append('g')
.attr('class', function(d) { return 'layer-points-group layer-points-' + d; });
selection.selectAll('.layer-labels').selectAll('.layer-labels-group')
.data(['halo', 'label', 'debug'])
.enter()
.append('g')
.attr('class', function(d) { return 'layer-labels-group layer-labels-' + d; });
}
+2 -1
View File
@@ -36,7 +36,8 @@ export function svgPoints(projection, context) {
points.sort(sortY);
var layer = selection.selectAll('.layer-hit');
var layer = selection.selectAll('.layer-points .layer-points-points');
var groups = layer.selectAll('g.point')
.filter(filter)
+2 -1
View File
@@ -18,7 +18,8 @@ export function svgTurns(projection) {
(!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
}
var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
var layer = selection.selectAll('.layer-points .layer-points-turns');
var groups = layer.selectAll('g.turn')
.data(turns, key);
groups.exit()
+97 -78
View File
@@ -54,7 +54,8 @@ export function svgVertices(projection, context) {
function setClass(klass) {
return function(entity) {
this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
d3_select(this)
.attr('class', 'node vertex ' + klass + ' ' + entity.id);
};
}
@@ -171,9 +172,7 @@ export function svgVertices(projection, context) {
function drawVertices(selection, graph, entities, filter, extent) {
var wireframe = context.surface().classed('fill-wireframe');
var zoom = ktoz(projection.scale());
var siblings = {};
getSiblingAndChildVertices(context.selectedIDs(), graph, extent);
var siblings = getSiblingAndChildVertices(context.selectedIDs(), graph, extent, wireframe, zoom);
// always render selected and sibling vertices..
var vertices = _clone(siblings);
@@ -184,7 +183,7 @@ export function svgVertices(projection, context) {
var entity = entities[i];
var geometry = entity.geometry(graph);
if ((geometry === 'point') && renderAsVertex(entity)) {
if ((geometry === 'point') && renderAsVertex(entity, graph, wireframe, zoom)) {
vertices[entity.id] = entity;
} else if ((geometry === 'vertex') &&
@@ -193,85 +192,105 @@ export function svgVertices(projection, context) {
}
}
selection.selectAll('.layer-hit')
selection.selectAll('.layer-points .layer-points-vertices')
.call(draw, _values(vertices), 'vertex-persistent', graph, siblings, filterWithSiblings);
// drawHover(selection, graph, extent, true);
drawTargets(selection, graph, _values(vertices), filter, extent);
// Points can also render as vertices:
// 1. in wireframe mode or
// 2. at higher zooms if they have a direction
function renderAsVertex(entity) {
var geometry = entity.geometry(graph);
return geometry === 'vertex' || (geometry === 'point' && (
wireframe || (zoom > 18 && entity.directions(graph, projection).length)
));
}
function getSiblingAndChildVertices(ids, graph, extent) {
function addChildVertices(entity) {
var geometry = entity.geometry(graph);
if (!context.features().isHiddenFeature(entity, graph, geometry)) {
var i;
if (entity.type === 'way') {
for (i = 0; i < entity.nodes.length; i++) {
var child = context.hasEntity(entity.nodes[i]);
if (child) {
addChildVertices(child);
}
}
} else if (entity.type === 'relation') {
for (i = 0; i < entity.members.length; i++) {
var member = context.hasEntity(entity.members[i].id);
if (member) {
addChildVertices(member);
}
}
} else if (renderAsVertex(entity) && entity.intersects(extent, graph)) {
siblings[entity.id] = entity;
}
}
}
ids.forEach(function(id) {
var entity = context.hasEntity(id);
if (!entity) return;
if (entity.type === 'node') {
if (renderAsVertex(entity)) {
siblings[entity.id] = entity;
graph.parentWays(entity).forEach(function(entity) {
addChildVertices(entity);
});
}
} else { // way, relation
addChildVertices(entity);
}
});
}
}
// function drawHover(selection, graph, extent, follow) {
// var hovered = _hover ? siblingAndChildVertices([_hover.id], graph, extent) : {};
// var wireframe = context.surface().classed('fill-wireframe');
// var layer = selection.selectAll('.layer-hit');
//
// layer.selectAll('g.vertex.vertex-hover')
// .call(draw, _values(hovered), 'vertex-hover', graph, {}, false);
// }
//
//
// drawVertices.drawHover = function(selection, graph, target, extent) {
// if (target === _hover) return;
// _hover = target;
// drawHover(selection, graph, extent);
// };
function drawTargets(selection, graph, entities, filter, extent) {
// todo coming soon
return;
var layer = selection.selectAll('.layer-points .layer-points-targets');
var targets = layer.selectAll('g.vertex.target')
.data(entities, osmEntity.key);
// exit
targets.exit()
.remove();
// enter/update
targets.enter()
.append('circle')
.attr('r', radiuses.shadow[3]) // just use the biggest one for now
.attr('class', function(d) { return 'node vertex target ' + d.id; })
.merge(targets)
.attr('transform', svgPointTransform(projection));
}
// Points can also render as vertices:
// 1. in wireframe mode or
// 2. at higher zooms if they have a direction
function renderAsVertex(entity, graph, wireframe, zoom) {
var geometry = entity.geometry(graph);
return geometry === 'vertex' || (geometry === 'point' && (
wireframe || (zoom > 18 && entity.directions(graph, projection).length)
));
}
function getSiblingAndChildVertices(ids, graph, extent, wireframe, zoom) {
var results = {};
function addChildVertices(entity) {
var geometry = entity.geometry(graph);
if (!context.features().isHiddenFeature(entity, graph, geometry)) {
var i;
if (entity.type === 'way') {
for (i = 0; i < entity.nodes.length; i++) {
var child = context.hasEntity(entity.nodes[i]);
if (child) {
addChildVertices(child);
}
}
} else if (entity.type === 'relation') {
for (i = 0; i < entity.members.length; i++) {
var member = context.hasEntity(entity.members[i].id);
if (member) {
addChildVertices(member);
}
}
} else if (renderAsVertex(entity, graph, wireframe, zoom) && entity.intersects(extent, graph)) {
results[entity.id] = entity;
}
}
}
ids.forEach(function(id) {
var entity = context.hasEntity(id);
if (!entity) return;
if (entity.type === 'node') {
if (renderAsVertex(entity, graph, wireframe, zoom)) {
results[entity.id] = entity;
graph.parentWays(entity).forEach(function(entity) {
addChildVertices(entity);
});
}
} else { // way, relation
addChildVertices(entity);
}
});
return results;
}
drawVertices.drawHover = function(selection, graph, target, extent) {
if (target === _hover) return;
_hover = target;
var wireframe = context.surface().classed('fill-wireframe');
var zoom = ktoz(projection.scale());
var hovered = _hover ? getSiblingAndChildVertices([_hover.id], graph, extent, wireframe, zoom) : {};
var filter = function() { return true; };
drawTargets(selection, graph, _values(hovered), filter, extent);
};
return drawVertices;
}
+73 -69
View File
@@ -1,17 +1,21 @@
describe('iD.svgAreas', function () {
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]),
all = function() { return true; },
none = function() { return false; };
var TAU = 2 * Math.PI;
function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
var context, surface;
var all = function() { return true; };
var none = function() { return false; };
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(ztok(17))
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context();
context = iD.coreContext();
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
.call(context.map().centerZoom([0, 0], 17));
surface = context.surface();
iD.setAreaKeys({
@@ -22,13 +26,13 @@ describe('iD.svgAreas', function () {
});
it('adds way and area classes', function () {
var graph = iD.Graph([
iD.Node({id: 'a', loc: [0, 0]}),
iD.Node({id: 'b', loc: [1, 0]}),
iD.Node({id: 'c', loc: [1, 1]}),
iD.Node({id: 'd', loc: [0, 1]}),
iD.Way({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
]);
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0, 0]}),
iD.osmNode({id: 'b', loc: [1, 0]}),
iD.osmNode({id: 'c', loc: [1, 1]}),
iD.osmNode({id: 'd', loc: [0, 1]}),
iD.osmWay({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
]);
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], none);
@@ -37,13 +41,13 @@ describe('iD.svgAreas', function () {
});
it('adds tag classes', function () {
var graph = iD.Graph([
iD.Node({id: 'a', loc: [0, 0]}),
iD.Node({id: 'b', loc: [1, 0]}),
iD.Node({id: 'c', loc: [1, 1]}),
iD.Node({id: 'd', loc: [0, 1]}),
iD.Way({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
]);
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0, 0]}),
iD.osmNode({id: 'b', loc: [1, 0]}),
iD.osmNode({id: 'c', loc: [1, 1]}),
iD.osmNode({id: 'd', loc: [0, 1]}),
iD.osmWay({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
]);
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('w')], none);
@@ -52,14 +56,14 @@ describe('iD.svgAreas', function () {
});
it('handles deletion of a way and a member vertex (#1903)', function () {
var graph = iD.Graph([
iD.Node({id: 'a', loc: [0, 0]}),
iD.Node({id: 'b', loc: [1, 0]}),
iD.Node({id: 'c', loc: [1, 1]}),
iD.Node({id: 'd', loc: [1, 1]}),
iD.Way({id: 'w', tags: {area: 'yes'}, nodes: ['a', 'b', 'c', 'a']}),
iD.Way({id: 'x', tags: {area: 'yes'}, nodes: ['a', 'b', 'd', 'a']})
]);
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0, 0]}),
iD.osmNode({id: 'b', loc: [1, 0]}),
iD.osmNode({id: 'c', loc: [1, 1]}),
iD.osmNode({id: 'd', loc: [1, 1]}),
iD.osmWay({id: 'w', tags: {area: 'yes'}, nodes: ['a', 'b', 'c', 'a']}),
iD.osmWay({id: 'x', tags: {area: 'yes'}, nodes: ['a', 'b', 'd', 'a']})
]);
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('x')], all);
graph = graph.remove(graph.entity('x')).remove(graph.entity('d'));
@@ -69,18 +73,18 @@ describe('iD.svgAreas', function () {
});
describe('z-indexing', function() {
var graph = iD.Graph([
iD.Node({id: 'a', loc: [-0.0002, 0.0001]}),
iD.Node({id: 'b', loc: [ 0.0002, 0.0001]}),
iD.Node({id: 'c', loc: [ 0.0002, -0.0001]}),
iD.Node({id: 'd', loc: [-0.0002, -0.0001]}),
iD.Node({id: 'e', loc: [-0.0004, 0.0002]}),
iD.Node({id: 'f', loc: [ 0.0004, 0.0002]}),
iD.Node({id: 'g', loc: [ 0.0004, -0.0002]}),
iD.Node({id: 'h', loc: [-0.0004, -0.0002]}),
iD.Way({id: 's', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'd', 'a']}),
iD.Way({id: 'l', tags: {landuse: 'park'}, nodes: ['e', 'f', 'g', 'h', 'e']})
]);
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [-0.0002, 0.0001]}),
iD.osmNode({id: 'b', loc: [ 0.0002, 0.0001]}),
iD.osmNode({id: 'c', loc: [ 0.0002, -0.0001]}),
iD.osmNode({id: 'd', loc: [-0.0002, -0.0001]}),
iD.osmNode({id: 'e', loc: [-0.0004, 0.0002]}),
iD.osmNode({id: 'f', loc: [ 0.0004, 0.0002]}),
iD.osmNode({id: 'g', loc: [ 0.0004, -0.0002]}),
iD.osmNode({id: 'h', loc: [-0.0004, -0.0002]}),
iD.osmWay({id: 's', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'd', 'a']}),
iD.osmWay({id: 'l', tags: {landuse: 'park'}, nodes: ['e', 'f', 'g', 'h', 'e']})
]);
it('stacks smaller areas above larger ones in a single render', function () {
surface.call(iD.svgAreas(projection, context), graph, [graph.entity('s'), graph.entity('l')], none);
@@ -114,13 +118,13 @@ describe('iD.svgAreas', function () {
});
it('renders fills for multipolygon areas', function () {
var a = iD.Node({loc: [1, 1]}),
b = iD.Node({loc: [2, 2]}),
c = iD.Node({loc: [3, 3]}),
w = iD.Way({nodes: [a.id, b.id, c.id, a.id]}),
r = iD.Relation({tags: {type: 'multipolygon'}, members: [{id: w.id, type: 'way'}]}),
graph = iD.Graph([a, b, c, w, r]),
areas = [w, r];
var a = iD.osmNode({loc: [1, 1]});
var b = iD.osmNode({loc: [2, 2]});
var c = iD.osmNode({loc: [3, 3]});
var w = iD.osmWay({nodes: [a.id, b.id, c.id, a.id]});
var r = iD.osmRelation({tags: {type: 'multipolygon'}, members: [{id: w.id, type: 'way'}]});
var graph = iD.coreGraph([a, b, c, w, r]);
var areas = [w, r];
surface.call(iD.svgAreas(projection, context), graph, areas, none);
@@ -128,13 +132,13 @@ describe('iD.svgAreas', function () {
});
it('renders no strokes for multipolygon areas', function () {
var a = iD.Node({loc: [1, 1]}),
b = iD.Node({loc: [2, 2]}),
c = iD.Node({loc: [3, 3]}),
w = iD.Way({nodes: [a.id, b.id, c.id, a.id]}),
r = iD.Relation({tags: {type: 'multipolygon'}, members: [{id: w.id, type: 'way'}]}),
graph = iD.Graph([a, b, c, w, r]),
areas = [w, r];
var a = iD.osmNode({loc: [1, 1]});
var b = iD.osmNode({loc: [2, 2]});
var c = iD.osmNode({loc: [3, 3]});
var w = iD.osmWay({nodes: [a.id, b.id, c.id, a.id]});
var r = iD.osmRelation({tags: {type: 'multipolygon'}, members: [{id: w.id, type: 'way'}]});
var graph = iD.coreGraph([a, b, c, w, r]);
var areas = [w, r];
surface.call(iD.svgAreas(projection, context), graph, areas, none);
@@ -142,12 +146,12 @@ describe('iD.svgAreas', function () {
});
it('renders fill for a multipolygon with tags on the outer way', function() {
var a = iD.Node({loc: [1, 1]}),
b = iD.Node({loc: [2, 2]}),
c = iD.Node({loc: [3, 3]}),
w = iD.Way({tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]}),
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, w, r]);
var a = iD.osmNode({loc: [1, 1]});
var b = iD.osmNode({loc: [2, 2]});
var c = iD.osmNode({loc: [3, 3]});
var w = iD.osmWay({tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]});
var r = iD.osmRelation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}});
var graph = iD.coreGraph([a, b, c, w, r]);
surface.call(iD.svgAreas(projection, context), graph, [w, r], none);
@@ -157,12 +161,12 @@ describe('iD.svgAreas', function () {
});
it('renders no strokes for a multipolygon with tags on the outer way', function() {
var a = iD.Node({loc: [1, 1]}),
b = iD.Node({loc: [2, 2]}),
c = iD.Node({loc: [3, 3]}),
w = iD.Way({tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]}),
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, w, r]);
var a = iD.osmNode({loc: [1, 1]});
var b = iD.osmNode({loc: [2, 2]});
var c = iD.osmNode({loc: [3, 3]});
var w = iD.osmWay({tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]});
var r = iD.osmRelation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}});
var graph = iD.coreGraph([a, b, c, w, r]);
surface.call(iD.svgAreas(projection, context), graph, [w, r], none);
+9 -6
View File
@@ -1,12 +1,15 @@
describe('iD.svgLayers', function () {
var context, container,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]);
var TAU = 2 * Math.PI;
function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
var context, container;
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(ztok(17))
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context();
context = iD.coreContext();
container = d3.select(document.createElement('div'));
});
+47 -43
View File
@@ -1,26 +1,30 @@
describe('iD.svgLines', function () {
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]),
all = function() { return true; },
none = function() { return false; };
var TAU = 2 * Math.PI;
function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
var context, surface;
var all = function() { return true; };
var none = function() { return false; };
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(ztok(17))
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context();
context = iD.coreContext();
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
.call(context.map().centerZoom([0, 0], 17));
surface = context.surface();
});
it('adds way and line classes', function () {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [1, 1]}),
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]);
var a = iD.osmNode({loc: [0, 0]});
var b = iD.osmNode({loc: [1, 1]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var graph = iD.coreGraph([a, b, line]);
surface.call(iD.svgLines(projection, context), graph, [line], all);
@@ -29,10 +33,10 @@ describe('iD.svgLines', function () {
});
it('adds tag classes', function () {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [1, 1]}),
line = iD.Way({nodes: [a.id, b.id], tags: {highway: 'residential'}}),
graph = iD.Graph([a, b, line]);
var a = iD.osmNode({loc: [0, 0]});
var b = iD.osmNode({loc: [1, 1]});
var line = iD.osmWay({nodes: [a.id, b.id], tags: {highway: 'residential'}});
var graph = iD.coreGraph([a, b, line]);
surface.call(iD.svgLines(projection, context), graph, [line], all);
@@ -41,11 +45,11 @@ describe('iD.svgLines', function () {
});
it('adds stroke classes for the tags of the parent relation of multipolygon members', function() {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [1, 1]}),
line = iD.Way({nodes: [a.id, b.id]}),
relation = iD.Relation({members: [{id: line.id}], tags: {type: 'multipolygon', natural: 'wood'}}),
graph = iD.Graph([a, b, line, relation]);
var a = iD.osmNode({loc: [0, 0]});
var b = iD.osmNode({loc: [1, 1]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var relation = iD.osmRelation({members: [{id: line.id}], tags: {type: 'multipolygon', natural: 'wood'}});
var graph = iD.coreGraph([a, b, line, relation]);
surface.call(iD.svgLines(projection, context), graph, [line], all);
@@ -53,12 +57,12 @@ describe('iD.svgLines', function () {
});
it('renders stroke for outer way of multipolygon with tags on the outer way', function() {
var a = iD.Node({loc: [1, 1]}),
b = iD.Node({loc: [2, 2]}),
c = iD.Node({loc: [3, 3]}),
w = iD.Way({id: 'w-1', tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]}),
r = iD.Relation({members: [{id: w.id}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, w, r]);
var a = iD.osmNode({loc: [1, 1]});
var b = iD.osmNode({loc: [2, 2]});
var c = iD.osmNode({loc: [3, 3]});
var w = iD.osmWay({id: 'w-1', tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]});
var r = iD.osmRelation({members: [{id: w.id}], tags: {type: 'multipolygon'}});
var graph = iD.coreGraph([a, b, c, w, r]);
surface.call(iD.svgLines(projection, context), graph, [w], all);
@@ -67,13 +71,13 @@ describe('iD.svgLines', function () {
});
it('adds stroke classes for the tags of the outer way of multipolygon with tags on the outer way', function() {
var a = iD.Node({loc: [1, 1]}),
b = iD.Node({loc: [2, 2]}),
c = iD.Node({loc: [3, 3]}),
o = iD.Way({id: 'w-1', nodes: [a.id, b.id, c.id, a.id], tags: {natural: 'wood'}}),
i = iD.Way({id: 'w-2', nodes: [a.id, b.id, c.id, a.id]}),
r = iD.Relation({members: [{id: o.id, role: 'outer'}, {id: i.id, role: 'inner'}], tags: {type: 'multipolygon'}}),
graph = iD.Graph([a, b, c, o, i, r]);
var a = iD.osmNode({loc: [1, 1]});
var b = iD.osmNode({loc: [2, 2]});
var c = iD.osmNode({loc: [3, 3]});
var o = iD.osmWay({id: 'w-1', nodes: [a.id, b.id, c.id, a.id], tags: {natural: 'wood'}});
var i = iD.osmWay({id: 'w-2', nodes: [a.id, b.id, c.id, a.id]});
var r = iD.osmRelation({members: [{id: o.id, role: 'outer'}, {id: i.id, role: 'inner'}], tags: {type: 'multipolygon'}});
var graph = iD.coreGraph([a, b, c, o, i, r]);
surface.call(iD.svgLines(projection, context), graph, [i, o], all);
@@ -84,14 +88,14 @@ describe('iD.svgLines', function () {
});
describe('z-indexing', function() {
var graph = iD.Graph([
iD.Node({id: 'a', loc: [0, 0]}),
iD.Node({id: 'b', loc: [1, 1]}),
iD.Node({id: 'c', loc: [0, 0]}),
iD.Node({id: 'd', loc: [1, 1]}),
iD.Way({id: 'lo', tags: {highway: 'residential', tunnel: 'yes'}, nodes: ['a', 'b']}),
iD.Way({id: 'hi', tags: {highway: 'residential', bridge: 'yes'}, nodes: ['c', 'd']})
]);
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0, 0]}),
iD.osmNode({id: 'b', loc: [1, 1]}),
iD.osmNode({id: 'c', loc: [0, 0]}),
iD.osmNode({id: 'd', loc: [1, 1]}),
iD.osmWay({id: 'lo', tags: {highway: 'residential', tunnel: 'yes'}, nodes: ['a', 'b']}),
iD.osmWay({id: 'hi', tags: {highway: 'residential', bridge: 'yes'}, nodes: ['c', 'd']})
]);
it('stacks higher lines above lower ones in a single render', function () {
surface.call(iD.svgLines(projection, context), graph, [graph.entity('lo'), graph.entity('hi')], none);
+58 -58
View File
@@ -1,103 +1,103 @@
describe('iD.svgMidpoints', function () {
var context, surface,
selectedIDs = [],
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]),
filter = function() { return true; };
var TAU = 2 * Math.PI;
function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
var context, surface;
var _selectedIDs = [];
var filter = function() { return true; };
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(ztok(17))
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context();
context.mode = function() {
return {
id: 'select',
selectedIDs: function() { return selectedIDs; }
};
};
d3.select(document.createElement('div'))
context = iD.coreContext();
context.enter({
id: 'select',
enter: function() { },
exit: function() { },
selectedIDs: function() { return _selectedIDs; }
});
var map = d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
.call(context.map().centerZoom([0, 0], 17));
surface = context.surface();
});
it('creates midpoint on segment completely within the extent', function () {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [50, 0]}),
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]),
extent = iD.geoExtent([0, 0], [100, 100]);
var a = iD.osmNode({loc: [0, 0]});
var b = iD.osmNode({loc: [1, 0]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var graph = iD.coreGraph([a, b, line]);
var extent = iD.geoExtent([0, 0], [1, 1]);
selectedIDs = [line.id];
context.selectedIDs = function() { return selectedIDs; };
_selectedIDs = [line.id];
context.entity = function(id) { return graph.entity(id); };
context.hasEntity = context.entity;
context.hasEntity = function(id) { return graph.entities[id]; };
surface.call(iD.svgMidpoints(projection, context), graph, [line], filter, extent);
expect(surface.selectAll('.midpoint').datum().loc).to.eql([25, 0]);
expect(surface.selectAll('.midpoint').datum().loc).to.eql([0.5, 0]);
});
it('doesn\'t create midpoint on segment with pixel length less than 40', function () {
var a = iD.Node({loc: [0, 0]}),
b = iD.Node({loc: [39, 0]}),
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]),
extent = iD.geoExtent([0, 0], [100, 100]);
var a = iD.osmNode({loc: [0, 0]});
var b = iD.osmNode({loc: [0.0001, 0]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var graph = iD.coreGraph([a, b, line]);
var extent = iD.geoExtent([0, 0], [1, 1]);
selectedIDs = [line.id];
context.selectedIDs = function() { return selectedIDs; };
_selectedIDs = [line.id];
context.entity = function(id) { return graph.entity(id); };
context.hasEntity = context.entity;
context.hasEntity = function(id) { return graph.entities[id]; };
surface.call(iD.svgMidpoints(projection, context), graph, [line], filter, extent);
expect(surface.selectAll('.midpoint').nodes()).to.have.length(0);
});
it('doesn\'t create midpoint on segment completely outside of the extent', function () {
var a = iD.Node({loc: [-100, 0]}),
b = iD.Node({loc: [-50, 0]}),
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]),
extent = iD.geoExtent([0, 0], [100, 100]);
var a = iD.osmNode({loc: [-1, 0]});
var b = iD.osmNode({loc: [-0.5, 0]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var graph = iD.coreGraph([a, b, line]);
var extent = iD.geoExtent([0, 0], [1, 1]);
selectedIDs = [line.id];
context.selectedIDs = function() { return selectedIDs; };
_selectedIDs = [line.id];
context.entity = function(id) { return graph.entity(id); };
context.hasEntity = context.entity;
context.hasEntity = function(id) { return graph.entities[id]; };
surface.call(iD.svgMidpoints(projection, context), graph, [line], filter, extent);
expect(surface.selectAll('.midpoint').nodes()).to.have.length(0);
});
it('creates midpoint on extent edge for segment partially outside of the extent', function () {
var a = iD.Node({loc: [50, 0]}),
b = iD.Node({loc: [500, 0]}),
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]),
extent = iD.geoExtent([0, 0], [100, 100]);
var a = iD.osmNode({loc: [0.5, 0]});
var b = iD.osmNode({loc: [2, 0]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var graph = iD.coreGraph([a, b, line]);
var extent = iD.geoExtent([0, 0], [1, 1]);
selectedIDs = [line.id];
context.selectedIDs = function() { return selectedIDs; };
_selectedIDs = [line.id];
context.entity = function(id) { return graph.entity(id); };
context.hasEntity = context.entity;
context.hasEntity = function(id) { return graph.entities[id]; };
surface.call(iD.svgMidpoints(projection, context), graph, [line], filter, extent);
expect(surface.selectAll('.midpoint').datum().loc).to.eql([100, 0]);
expect(surface.selectAll('.midpoint').datum().loc).to.eql([1, 0]);
});
it('doesn\'t create midpoint on extent edge for segment with pixel length less than 20', function () {
var a = iD.Node({loc: [81, 0]}),
b = iD.Node({loc: [500, 0]}),
line = iD.Way({nodes: [a.id, b.id]}),
graph = iD.Graph([a, b, line]),
extent = iD.geoExtent([0, 0], [100, 100]);
var a = iD.osmNode({loc: [0.9999, 0]});
var b = iD.osmNode({loc: [2, 0]});
var line = iD.osmWay({nodes: [a.id, b.id]});
var graph = iD.coreGraph([a, b, line]);
var extent = iD.geoExtent([0, 0], [1, 1]);
selectedIDs = [line.id];
context.selectedIDs = function() { return selectedIDs; };
_selectedIDs = [line.id];
context.entity = function(id) { return graph.entity(id); };
context.hasEntity = context.entity;
context.hasEntity = function(id) { return graph.entities[id]; };
surface.call(iD.svgMidpoints(projection, context), graph, [line], filter, extent);
expect(surface.selectAll('.midpoint').nodes()).to.have.length(0);
+26 -6
View File
@@ -7,12 +7,32 @@ describe('iD.svgOsm', function () {
it('creates default osm layers', function () {
container.call(iD.svgOsm());
var nodes = container.selectAll('.layer-osm').nodes();
expect(nodes.length).to.eql(4);
expect(d3.select(nodes[0]).classed('layer-areas')).to.be.true;
expect(d3.select(nodes[1]).classed('layer-lines')).to.be.true;
expect(d3.select(nodes[2]).classed('layer-hit')).to.be.true;
expect(d3.select(nodes[3]).classed('layer-labels')).to.be.true;
var layers = container.selectAll('g.layer-osm').nodes();
expect(layers.length).to.eql(4);
expect(d3.select(layers[0]).classed('layer-areas')).to.be.true;
expect(d3.select(layers[1]).classed('layer-lines')).to.be.true;
expect(d3.select(layers[2]).classed('layer-points')).to.be.true;
expect(d3.select(layers[3]).classed('layer-labels')).to.be.true;
});
it('creates default osm point layers', function () {
container.call(iD.svgOsm());
var layers = container.selectAll('g.layer-points g.layer-points-group').nodes();
expect(layers.length).to.eql(5);
expect(d3.select(layers[0]).classed('layer-points-points')).to.be.true;
expect(d3.select(layers[1]).classed('layer-points-midpoints')).to.be.true;
expect(d3.select(layers[2]).classed('layer-points-vertices')).to.be.true;
expect(d3.select(layers[3]).classed('layer-points-turns')).to.be.true;
expect(d3.select(layers[4]).classed('layer-points-targets')).to.be.true;
});
it('creates default osm label layers', function () {
container.call(iD.svgOsm());
var layers = container.selectAll('g.layer-labels g.layer-labels-group').nodes();
expect(layers.length).to.eql(3);
expect(d3.select(layers[0]).classed('layer-labels-halo')).to.be.true;
expect(d3.select(layers[1]).classed('layer-labels-label')).to.be.true;
expect(d3.select(layers[2]).classed('layer-labels-debug')).to.be.true;
});
});
+12 -9
View File
@@ -1,22 +1,25 @@
describe('iD.svgPoints', function () {
var context, surface,
projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(180 / Math.PI)
.clipExtent([[0, 0], [Infinity, Infinity]]);
var TAU = 2 * Math.PI;
function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
var context, surface;
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
.translate([0, 0])
.scale(ztok(17))
.clipExtent([[0, 0], [Infinity, Infinity]]);
beforeEach(function () {
context = iD.Context();
context = iD.coreContext();
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
.call(context.map().centerZoom([0, 0], 17));
surface = context.surface();
});
it('adds tag classes', function () {
var point = iD.Node({tags: {amenity: 'cafe'}, loc: [0, 0]}),
graph = iD.Graph([point]);
var point = iD.osmNode({tags: {amenity: 'cafe'}, loc: [0, 0]});
var graph = iD.coreGraph([point]);
surface.call(iD.svgPoints(projection, context), graph, [point]);
+28 -28
View File
@@ -7,156 +7,156 @@ describe('iD.svgTagClasses', function () {
it('adds no classes to elements whose datum has no tags', function() {
selection
.datum(iD.Entity())
.datum(iD.osmEntity())
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal(null);
});
it('adds classes for primary tag key and key-value', function() {
selection
.datum(iD.Entity({tags: {highway: 'primary'}}))
.datum(iD.osmEntity({tags: {highway: 'primary'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-highway tag-highway-primary');
});
it('adds only one primary tag', function() {
selection
.datum(iD.Entity({tags: {highway: 'primary', railway: 'rail'}}))
.datum(iD.osmEntity({tags: {highway: 'primary', railway: 'rail'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-highway tag-highway-primary');
});
it('orders primary tags', function() {
selection
.datum(iD.Entity({tags: {railway: 'rail', highway: 'primary'}}))
.datum(iD.osmEntity({tags: {railway: 'rail', highway: 'primary'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-highway tag-highway-primary');
});
it('adds status tag when status in primary value (`railway=abandoned`)', function() {
selection
.datum(iD.Entity({tags: {railway: 'abandoned'}}))
.datum(iD.osmEntity({tags: {railway: 'abandoned'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-railway tag-status tag-status-abandoned');
});
it('adds status tag when status in key and value matches "yes" (railway=rail + abandoned=yes)', function() {
selection
.datum(iD.Entity({tags: {railway: 'rail', abandoned: 'yes'}}))
.datum(iD.osmEntity({tags: {railway: 'rail', abandoned: 'yes'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-railway tag-railway-rail tag-status tag-status-abandoned');
});
it('adds status tag when status in key and value matches primary (railway=rail + abandoned=railway)', function() {
selection
.datum(iD.Entity({tags: {railway: 'rail', abandoned: 'railway'}}))
.datum(iD.osmEntity({tags: {railway: 'rail', abandoned: 'railway'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-railway tag-railway-rail tag-status tag-status-abandoned');
});
it('adds primary and status tag when status in key and no primary (abandoned=railway)', function() {
selection
.datum(iD.Entity({tags: {abandoned: 'railway'}}))
.datum(iD.osmEntity({tags: {abandoned: 'railway'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-railway tag-status tag-status-abandoned');
});
it('does not add status tag for different primary tag (highway=path + abandoned=railway)', function() {
selection
.datum(iD.Entity({tags: {highway: 'path', abandoned: 'railway'}}))
.datum(iD.osmEntity({tags: {highway: 'path', abandoned: 'railway'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-highway tag-highway-path');
});
it('adds secondary tags', function() {
selection
.datum(iD.Entity({tags: {highway: 'primary', bridge: 'yes'}}))
.datum(iD.osmEntity({tags: {highway: 'primary', bridge: 'yes'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('tag-highway tag-highway-primary tag-bridge tag-bridge-yes');
});
it('adds no bridge=no tags', function() {
selection
.datum(iD.Entity({tags: {bridge: 'no'}}))
.datum(iD.osmEntity({tags: {bridge: 'no'}}))
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal(null);
});
it('adds tag-unpaved for highway=track with no surface tagging', function() {
selection
.datum(iD.Entity({tags: {highway: 'track'}}))
.datum(iD.osmEntity({tags: {highway: 'track'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.true;
});
it('does not add tag-unpaved for highway=track with explicit paved surface tagging', function() {
selection
.datum(iD.Entity({tags: {highway: 'track', surface: 'asphalt'}}))
.datum(iD.osmEntity({tags: {highway: 'track', surface: 'asphalt'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
selection
.datum(iD.Entity({tags: {highway: 'track', tracktype: 'grade1'}}))
.datum(iD.osmEntity({tags: {highway: 'track', tracktype: 'grade1'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
});
it('adds tag-unpaved for highway=track with explicit unpaved surface tagging', function() {
selection
.datum(iD.Entity({tags: {highway: 'track', surface: 'dirt'}}))
.datum(iD.osmEntity({tags: {highway: 'track', surface: 'dirt'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.true;
selection
.datum(iD.Entity({tags: {highway: 'track', tracktype: 'grade3'}}))
.datum(iD.osmEntity({tags: {highway: 'track', tracktype: 'grade3'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.true;
});
it('does not add tag-unpaved for other highway types with no surface tagging', function() {
selection
.datum(iD.Entity({tags: {highway: 'tertiary'}}))
.datum(iD.osmEntity({tags: {highway: 'tertiary'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
selection
.datum(iD.Entity({tags: {highway: 'foo'}}))
.datum(iD.osmEntity({tags: {highway: 'foo'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
});
it('does not add tag-unpaved for other highway types with explicit paved surface tagging', function() {
selection
.datum(iD.Entity({tags: {highway: 'tertiary', surface: 'asphalt'}}))
.datum(iD.osmEntity({tags: {highway: 'tertiary', surface: 'asphalt'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
selection
.datum(iD.Entity({tags: {highway: 'foo', tracktype: 'grade1'}}))
.datum(iD.osmEntity({tags: {highway: 'foo', tracktype: 'grade1'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
});
it('adds tag-unpaved for other highway types with explicit unpaved surface tagging', function() {
selection
.datum(iD.Entity({tags: {highway: 'tertiary', surface: 'dirt'}}))
.datum(iD.osmEntity({tags: {highway: 'tertiary', surface: 'dirt'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.true;
selection
.datum(iD.Entity({tags: {highway: 'foo', tracktype: 'grade3'}}))
.datum(iD.osmEntity({tags: {highway: 'foo', tracktype: 'grade3'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.true;
});
it('does not add tag-unpaved for non-highways', function() {
selection
.datum(iD.Entity({tags: {railway: 'abandoned', surface: 'gravel'}}))
.datum(iD.osmEntity({tags: {railway: 'abandoned', surface: 'gravel'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
selection
.datum(iD.Entity({tags: {amenity: 'parking', surface: 'dirt'}}))
.datum(iD.osmEntity({tags: {amenity: 'parking', surface: 'dirt'}}))
.call(iD.svgTagClasses());
expect(selection.classed('tag-unpaved')).to.be.false;
});
@@ -164,7 +164,7 @@ describe('iD.svgTagClasses', function () {
it('adds tags based on the result of the `tags` accessor', function() {
var primary = function () { return { highway: 'primary'}; };
selection
.datum(iD.Entity())
.datum(iD.osmEntity())
.call(iD.svgTagClasses().tags(primary));
expect(selection.attr('class')).to.equal('tag-highway tag-highway-primary');
});
@@ -172,7 +172,7 @@ describe('iD.svgTagClasses', function () {
it('removes classes for tags that are no longer present', function() {
selection
.attr('class', 'tag-highway tag-highway-primary')
.datum(iD.Entity())
.datum(iD.osmEntity())
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('');
});
@@ -180,7 +180,7 @@ describe('iD.svgTagClasses', function () {
it('preserves existing non-"tag-"-prefixed classes', function() {
selection
.attr('class', 'selected')
.datum(iD.Entity())
.datum(iD.osmEntity())
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal('selected');
});
@@ -188,7 +188,7 @@ describe('iD.svgTagClasses', function () {
it('works on SVG elements', function() {
selection = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'g'));
selection
.datum(iD.Entity())
.datum(iD.osmEntity())
.call(iD.svgTagClasses());
expect(selection.attr('class')).to.equal(null);
});
+6 -6
View File
@@ -11,19 +11,19 @@ describe('iD.svgVertices', function () {
beforeEach(function () {
context = iD.Context();
context = iD.coreContext();
d3.select(document.createElement('div'))
.attr('id', 'map')
.call(context.map());
.call(context.map().centerZoom([0, 0], 17));
surface = context.surface();
});
it('adds the .shared class to vertices that are members of two or more ways', function () {
var node = iD.Node({loc: [0, 0]});
var way1 = iD.Way({nodes: [node.id], tags: {highway: 'residential'}});
var way2 = iD.Way({nodes: [node.id], tags: {highway: 'residential'}});
var graph = iD.Graph([node, way1, way2]);
var node = iD.osmNode({loc: [0, 0]});
var way1 = iD.osmWay({nodes: [node.id], tags: {highway: 'residential'}});
var way2 = iD.osmWay({nodes: [node.id], tags: {highway: 'residential'}});
var graph = iD.coreGraph([node, way1, way2]);
surface.call(iD.svgVertices(projection, context), graph, [node]);
expect(surface.select('.vertex').classed('shared')).to.be.true;