mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-14 21:28:11 +02:00
Add CSS classes for relation memberships
An entity that is a member of a relation will have the classes `member`, `member-role-<member role>`, and `member-type-<relation type>`. The first use of these classes is to avoid filling multipolygon member areas.
This commit is contained in:
@@ -154,6 +154,10 @@ path.multipolygon {
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
|
||||
path.area.member-type-multipolygon {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
path.area.selected {
|
||||
stroke-width:4 !important;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<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>
|
||||
|
||||
+2
-1
@@ -52,7 +52,8 @@ iD.svg.Areas = function(projection) {
|
||||
paths
|
||||
.order()
|
||||
.attr('d', lineString)
|
||||
.call(iD.svg.TagClasses());
|
||||
.call(iD.svg.TagClasses())
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
paths.exit()
|
||||
.remove();
|
||||
|
||||
+20
-20
@@ -33,27 +33,27 @@ iD.svg.Lines = function(projection) {
|
||||
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) {
|
||||
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())
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
paths.exit()
|
||||
.remove();
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
if (!alength) {
|
||||
var arrow = surface.append('text').text(arrowtext);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
iD.svg.MemberClasses = function(graph) {
|
||||
var tagClassRe = /^member-?/;
|
||||
|
||||
return function memberClassesSelection(selection) {
|
||||
selection.each(function memberClassesEach(d, i) {
|
||||
var classes, value = this.className;
|
||||
|
||||
if (value.baseVal !== undefined) value = value.baseVal;
|
||||
|
||||
classes = value.trim().split(/\s+/).filter(function(name) {
|
||||
return name.length && !tagClassRe.test(name);
|
||||
}).join(' ');
|
||||
|
||||
var relations = graph.parentRelations(d);
|
||||
|
||||
if (relations.length) {
|
||||
classes += ' member';
|
||||
}
|
||||
|
||||
relations.forEach(function (relation) {
|
||||
classes += ' member-type-' + relation.tags.type;
|
||||
classes += ' member-role-' + _.find(relation.members, function (member) { return member.id == d.id; }).role;
|
||||
});
|
||||
|
||||
classes = classes.trim();
|
||||
|
||||
if (classes !== value) {
|
||||
d3.select(this).attr('class', classes);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -40,7 +40,8 @@ iD.svg.Multipolygons = function(projection) {
|
||||
paths
|
||||
.order()
|
||||
.attr('d', lineString)
|
||||
.call(iD.svg.TagClasses());
|
||||
.call(iD.svg.TagClasses())
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
paths.exit()
|
||||
.remove();
|
||||
|
||||
+2
-1
@@ -45,7 +45,8 @@ iD.svg.Points = function(projection) {
|
||||
.attr('transform', 'translate(-8, -8)');
|
||||
|
||||
groups.attr('transform', iD.svg.PointTransform(projection))
|
||||
.call(iD.svg.TagClasses());
|
||||
.call(iD.svg.TagClasses())
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
// Selecting the following implicitly
|
||||
// sets the data (point entity) on the element
|
||||
|
||||
@@ -31,6 +31,7 @@ iD.svg.Vertices = function(projection) {
|
||||
|
||||
groups.attr('transform', iD.svg.PointTransform(projection))
|
||||
.call(iD.svg.TagClasses())
|
||||
.call(iD.svg.MemberClasses(graph))
|
||||
.classed('shared', function(entity) { return graph.parentWays(entity).length > 1; });
|
||||
|
||||
// Selecting the following implicitly
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<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>
|
||||
@@ -159,6 +160,8 @@
|
||||
|
||||
<script src="spec/svg.js"></script>
|
||||
<script src="spec/svg/areas.js"></script>
|
||||
<script src="spec/svg/lines.js"></script>
|
||||
<script src="spec/svg/member_classes.js"></script>
|
||||
<script src="spec/svg/multipolygons.js"></script>
|
||||
<script src="spec/svg/points.js"></script>
|
||||
<script src="spec/svg/vertices.js"></script>
|
||||
|
||||
@@ -64,6 +64,8 @@
|
||||
|
||||
<script src="spec/svg.js"></script>
|
||||
<script src="spec/svg/areas.js"></script>
|
||||
<script src="spec/svg/lines.js"></script>
|
||||
<script src="spec/svg/member_classes.js"></script>
|
||||
<script src="spec/svg/multipolygons.js"></script>
|
||||
<script src="spec/svg/points.js"></script>
|
||||
<script src="spec/svg/vertices.js"></script>
|
||||
|
||||
@@ -28,6 +28,18 @@ describe("iD.svg.Areas", function () {
|
||||
expect(surface.select('.area')).to.be.classed('tag-building-yes');
|
||||
});
|
||||
|
||||
it("adds member classes", function () {
|
||||
var area = iD.Way({tags: {area: 'yes'}}),
|
||||
relation = iD.Relation({members: [{id: area.id, role: 'outer'}], tags: {type: 'multipolygon'}}),
|
||||
graph = iD.Graph([area, relation]);
|
||||
|
||||
surface.call(iD.svg.Areas(projection), graph, [area], filter);
|
||||
|
||||
expect(surface.select('.area')).to.be.classed('member');
|
||||
expect(surface.select('.area')).to.be.classed('member-role-outer');
|
||||
expect(surface.select('.area')).to.be.classed('member-type-multipolygon');
|
||||
});
|
||||
|
||||
it("preserves non-area paths", function () {
|
||||
var area = iD.Way({tags: {area: 'yes'}}),
|
||||
graph = iD.Graph([area]);
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
describe("iD.svg.MemberClasses", function () {
|
||||
var selection;
|
||||
|
||||
beforeEach(function () {
|
||||
selection = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'g'));
|
||||
});
|
||||
|
||||
it("adds no classes to elements that aren't a member of any relations", function() {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
|
||||
selection
|
||||
.datum(node)
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
expect(selection.attr('class')).to.equal(null);
|
||||
});
|
||||
|
||||
it("adds tags for member, role, and type", function() {
|
||||
var node = iD.Node(),
|
||||
relation = iD.Relation({members: [{id: node.id, role: 'r'}], tags: {type: 't'}}),
|
||||
graph = iD.Graph([node, relation]);
|
||||
|
||||
selection
|
||||
.datum(node)
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
expect(selection.attr('class')).to.equal('member member-type-t member-role-r');
|
||||
});
|
||||
|
||||
it('removes classes for tags that are no longer present', function() {
|
||||
var node = iD.Entity(),
|
||||
graph = iD.Graph([node]);
|
||||
|
||||
selection
|
||||
.attr('class', 'member member-type-t member-role-r')
|
||||
.datum(node)
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
expect(selection.attr('class')).to.equal('');
|
||||
});
|
||||
|
||||
it("preserves existing non-'member-'-prefixed classes", function() {
|
||||
var node = iD.Entity(),
|
||||
graph = iD.Graph([node]);
|
||||
|
||||
selection
|
||||
.attr('class', 'selected')
|
||||
.datum(node)
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
expect(selection.attr('class')).to.equal('selected');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user