diff --git a/css/map.css b/css/map.css
index 2a4c700e5..2336220d7 100644
--- a/css/map.css
+++ b/css/map.css
@@ -23,6 +23,10 @@ path {
fill: none;
}
+use {
+ pointer-events: none;
+}
+
/* points */
g.point circle {
diff --git a/index.html b/index.html
index 2ecdca4e2..95579b505 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,7 @@
+
diff --git a/index_dev.html b/index_dev.html
index 0ec4e89db..00c70260c 100644
--- a/index_dev.html
+++ b/index_dev.html
@@ -7,6 +7,7 @@
+
diff --git a/js/id/presets/collection.js b/js/id/presets/collection.js
index 4e4a76684..da7f9e5c9 100644
--- a/js/id/presets/collection.js
+++ b/js/id/presets/collection.js
@@ -10,12 +10,14 @@ iD.presets.Collection = function(collection) {
});
},
- matchType: function(entity, resolver) {
- var newcollection = collection.filter(function(d) {
- return d.matchType(entity, resolver);
- });
+ match: function(entity, resolver) {
+ return presets.matchType(entity, resolver).matchTags(entity);
+ },
- return iD.presets.Collection(newcollection);
+ matchType: function(entity, resolver) {
+ return iD.presets.Collection(collection.filter(function(d) {
+ return d.matchType(entity, resolver);
+ }));
},
matchTags: function(entity) {
diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js
index 05113b4c9..89aaf4e2b 100644
--- a/js/id/renderer/map.js
+++ b/js/id/renderer/map.js
@@ -14,7 +14,7 @@ iD.Map = function(context) {
background = iD.Background()
.projection(projection),
transformProp = iD.util.prefixCSSProperty('Transform'),
- points = iD.svg.Points(roundedProjection),
+ points = iD.svg.Points(roundedProjection, context),
vertices = iD.svg.Vertices(roundedProjection),
lines = iD.svg.Lines(projection),
areas = iD.svg.Areas(roundedProjection),
diff --git a/js/id/svg/points.js b/js/id/svg/points.js
index 2944b0afd..1e50cf407 100644
--- a/js/id/svg/points.js
+++ b/js/id/svg/points.js
@@ -1,16 +1,11 @@
-iD.svg.Points = function(projection) {
- function imageHref(d) {
- // TODO: optimize
- for (var k in d.tags) {
- var key = k + '=' + d.tags[k];
- if (iD.svg.Points.imageTable[key]) {
- return 'icons/' + iD.svg.Points.imageTable[key] + '.png';
- }
- }
- return 'icons/unknown.png';
- }
-
+iD.svg.Points = function(projection, context) {
return function drawPoints(surface, graph, entities, filter) {
+ function imageHref(entity) {
+ var preset = context.presets()
+ .match(entity, context.graph());
+ return '#maki-' + preset.icon + '-12';
+ }
+
var points = [];
for (var i = 0; i < entities.length; i++) {
@@ -33,16 +28,16 @@ iD.svg.Points = function(projection) {
.attr('class', 'node point');
group.append('circle')
- .attr('r', 13)
+ .attr('r', 12)
.attr('class', 'shadow');
group.append('circle')
.attr('class', 'stroke')
- .attr('r', 9);
+ .attr('r', 8);
- group.append('image')
- .attr({ width: 16, height: 16 })
- .attr('transform', 'translate(-8, -8)');
+ group.append('use')
+ .attr('transform', 'translate(-6, -6)')
+ .attr('clip-path', 'url(#clip-square-12)');
groups.attr('transform', iD.svg.PointTransform(projection))
.call(iD.svg.TagClasses())
@@ -50,7 +45,7 @@ iD.svg.Points = function(projection) {
// Selecting the following implicitly
// sets the data (point entity) on the element
- groups.select('image')
+ groups.select('use')
.attr('xlink:href', imageHref);
groups.select('.shadow');
groups.select('.stroke');
@@ -59,570 +54,3 @@ iD.svg.Points = function(projection) {
.remove();
};
};
-
-// an index of tag -> point image combinations, taken from
-// http://svn.openstreetmap.org/applications/rendering/mapnik/inc/layer-amenity-symbols.xml.inc
-iD.svg.Points.imageIndex = [
- {
- tags: { aeroway: 'helipad' },
- icon: 'helipad'
- },
- {
- tags: { aeroway: 'airport' },
- icon: 'airport'
- },
- {
- tags: { aeroway: 'aerodrome' },
- icon: 'aerodrome'
- },
- {
- tags: { railway: 'level_crossing' },
- icon: 'level_crossing'
- },
- {
- tags: { man_made: 'lighthouse' },
- icon: 'lighthouse'
- },
- {
- tags: { natural: 'peak' },
- icon: 'peak'
- },
- {
- tags: { natural: 'volcano' },
- icon: 'volcano'
- },
- {
- tags: { natural: 'cave_entrance' },
- icon: 'poi_cave'
- },
- {
- tags: { natural: 'spring' },
- icon: 'spring'
- },
- {
- tags: { natural: 'tree' },
- icon: 'tree'
- },
- {
- tags: {
- power: 'generator',
- 'generator:source': 'wind'
- },
- icon: 'power_wind'
- },
- {
- tags: {
- power: 'generator',
- power_source: 'wind'
- },
- icon: 'power_wind'
- },
- {
- tags: {
- man_made: 'power_wind'
- },
- icon: 'power_wind'
- },
- {
- tags: {
- man_made: 'windmill'
- },
- icon: 'windmill'
- },
- {
- tags: {
- man_made: 'mast'
- },
- icon: 'communications'
- },
- {
- tags: {
- highway: 'mini_roundabout'
- },
- icon: 'mini_roundabout'
- },
- {
- tags: {
- highway: 'gate'
- },
- icon: 'gate2'
- },
- {
- tags: {
- barrier: 'gate'
- },
- icon: 'gate2'
- },
- {
- tags: {
- barrier: 'lift_gate'
- },
- icon: 'liftgate'
- },
- {
- tags: {
- barrier: 'bollard'
- },
- icon: 'bollard'
- },
- {
- tags: {
- barrier: 'block'
- },
- icon: 'bollard'
- },
- {
- "icon": "alpinehut",
- "tags": {
- "tourism": "alpine_hut"
- }
- },
- {
- "icon": "shelter2",
- "tags": {
- "amenity": "shelter"
- }
- },
- {
- "icon": "atm2",
- "tags": {
- "amenity": "atm"
- }
- },
- {
- "icon": "bank2",
- "tags": {
- "amenity": "bank"
- }
- },
- {
- "icon": "bar",
- "tags": {
- "amenity": "bar"
- }
- },
- {
- "icon": "rental_bicycle",
- "tags": {
- "amenity": "bicycle_rental"
- }
- },
- {
- "icon": "bus_stop_small",
- "tags": {
- "amenity": "bus_stop"
- }
- },
- {
- "icon": "bus_stop",
- "tags": {
- "amenity": "bus_stop"
- }
- },
- {
- "icon": "bus_station",
- "tags": {
- "amenity": "bus_station"
- }
- },
- {
- "icon": "traffic_light",
- "tags": {
- "highway": "traffic_signals"
- }
- },
- {
- "icon": "cafe",
- "tags": {
- "amenity": "cafe"
- }
- },
- {
- "icon": "camping",
- "tags": {
- "tourism": "camp_site"
- }
- },
- {
- "icon": "transport_ford",
- "tags": {
- "highway": "ford"
- }
- },
- {
- "icon": "caravan_park",
- "tags": {
- "tourism": "caravan_site"
- }
- },
- {
- "icon": "car_share",
- "tags": {
- "amenity": "car_sharing"
- }
- },
- {
- "icon": "chalet",
- "tags": {
- "tourism": "chalet"
- }
- },
- {
- "icon": "cinema",
- "tags": {
- "amenity": "cinema"
- }
- },
- {
- "icon": "firestation",
- "tags": {
- "amenity": "fire_station"
- }
- },
- {
- "icon": "fuel",
- "tags": {
- "amenity": "fuel"
- }
- },
- {
- "icon": "guest_house",
- "tags": {
- "tourism": "guest_house"
- }
- },
- {
- "icon": "bandb",
- "tags": {
- "tourism": "bed_and_breakfast"
- }
- },
- {
- "icon": "hospital",
- "tags": {
- "amenity": "hospital"
- }
- },
- {
- "icon": "hostel",
- "tags": {
- "tourism": "hostel"
- }
- },
- {
- "icon": "hotel2",
- "tags": {
- "tourism": "hotel"
- }
- },
- {
- "icon": "motel",
- "tags": {
- "tourism": "motel"
- }
- },
- {
- "icon": "information",
- "tags": {
- "tourism": "information"
- }
- },
- {
- "icon": "embassy",
- "tags": {
- "amenity": "embassy"
- }
- },
- {
- "icon": "library",
- "tags": {
- "amenity": "library"
- }
- },
- {
- "icon": "amenity_court",
- "tags": {
- "amenity": "courthouse"
- }
- },
- {
- "icon": "lock_gate",
- "tags": {
- "waterway": "lock"
- }
- },
- {
- "icon": "communications",
- "tags": {
- "man_made": "mast"
- }
- },
- {
- "icon": "museum",
- "tags": {
- "tourism": "museum"
- }
- },
- {
- "icon": "parking",
- "tags": {
- "amenity": "parking"
- }
- },
- {
- "icon": "parking_private",
- "tags": {
- "amenity": "parking"
- }
- },
- {
- "icon": "pharmacy",
- "tags": {
- "amenity": "pharmacy"
- }
- },
- {
- "icon": "christian3",
- "tags": {
- "amenity": "place_of_worship"
- }
- },
- {
- "icon": "islamic3",
- "tags": {
- "amenity": "place_of_worship"
- }
- },
- {
- "icon": "sikh3",
- "tags": {
- "amenity": "place_of_worship"
- }
- },
- {
- "icon": "jewish3",
- "tags": {
- "amenity": "place_of_worship"
- }
- },
- {
- "icon": "place_of_worship3",
- "tags": {
- "amenity": "place_of_worship"
- }
- },
- {
- "icon": "police",
- "tags": {
- "amenity": "police"
- }
- },
- {
- "icon": "post_box",
- "tags": {
- "amenity": "post_box"
- }
- },
- {
- "icon": "post_office",
- "tags": {
- "amenity": "post_office"
- }
- },
- {
- "icon": "pub",
- "tags": {
- "amenity": "pub"
- }
- },
- {
- "icon": "biergarten",
- "tags": {
- "amenity": "biergarten"
- }
- },
- {
- "icon": "recycling",
- "tags": {
- "amenity": "recycling"
- }
- },
- {
- "icon": "restaurant",
- "tags": {
- "amenity": "restaurant"
- }
- },
- {
- "icon": "fast_food",
- "tags": {
- "amenity": "fast_food"
- }
- },
- {
- "icon": "telephone",
- "tags": {
- "amenity": "telephone"
- }
- },
- {
- "icon": "sosphone",
- "tags": {
- "amenity": "emergency_phone"
- }
- },
- {
- "icon": "theatre",
- "tags": {
- "amenity": "theatre"
- }
- },
- {
- "icon": "toilets",
- "tags": {
- "amenity": "toilets"
- }
- },
- {
- "icon": "food_drinkingtap",
- "tags": {
- "amenity": "drinking_water"
- }
- },
- {
- "icon": "amenity_prison",
- "tags": {
- "amenity": "prison"
- }
- },
- {
- "icon": "view_point",
- "tags": {
- "tourism": "viewpoint"
- }
- },
- {
- "icon": "tower_water",
- "tags": {
- "man_made": "water_tower"
- }
- },
- {
- "icon": "tourist_memorial",
- "tags": {
- "historic": "memorial"
- }
- },
- {
- "icon": "tourist_archaeological2",
- "tags": {
- "historic": "archaeological_site"
- }
- },
- {
- "icon": "shop_supermarket",
- "tags": {
- "shop": "supermarket"
- }
- },
- {
- "icon": "shop_bakery",
- "tags": {
- "shop": "bakery"
- }
- },
- {
- "icon": "shop_butcher",
- "tags": {
- "shop": "butcher"
- }
- },
- {
- "icon": "shop_clothes",
- "tags": {
- "shop": "clothes"
- }
- },
- {
- "icon": "shop_convenience",
- "tags": {
- "shop": "convenience"
- }
- },
- {
- "icon": "department_store",
- "tags": {
- "shop": "department_store"
- }
- },
- {
- "icon": "shop_diy",
- "tags": {
- "shop": "doityourself"
- }
- },
- {
- "icon": "florist",
- "tags": {
- "shop": "florist"
- }
- },
- {
- "icon": "shop_hairdresser",
- "tags": {
- "shop": "hairdresser"
- }
- },
- {
- "icon": "shopping_car",
- "tags": {
- "shop": "car"
- }
- },
- {
- "icon": "shopping_car_repair",
- "tags": {
- "shop": "car_repair"
- }
- },
- {
- "icon": "shopping_bicycle",
- "tags": {
- "shop": "bicycle"
- }
- },
- {
- "icon": "playground",
- "tags": {
- "leisure": "playground"
- }
- },
- {
- "icon": "picnic",
- "tags": {
- "amenity": "picnic_site"
- }
- },
- {
- "icon": "transport_slipway",
- "tags": {
- "leisure": "slipway"
- }
- }
-];
-
-// generate a fast lookup table for point styling
-iD.svg.Points.imageTable = (function(points) {
- var table = {};
- for (var i = 0; i < points.length; i++) {
- var point = points[i];
- // single-tag matches, the easy case
- if (Object.keys(point.tags).length === 1) {
- for (var k in point.tags) {
- var key = k + '=' + point.tags[k];
- table[key] = point.icon;
- }
- }
- }
- return table;
-})(iD.svg.Points.imageIndex);
diff --git a/js/id/svg/surface.js b/js/id/svg/surface.js
index e6e2ae025..9f671eb11 100644
--- a/js/id/svg/surface.js
+++ b/js/id/svg/surface.js
@@ -1,6 +1,7 @@
iD.svg.Surface = function() {
return function drawSurface(selection) {
var defs = selection.append('defs');
+
defs.append('marker')
.attr({
id: 'oneway-marker',
@@ -51,6 +52,38 @@ iD.svg.Surface = function() {
})
.attr('xlink:href', function(d) { return 'img/pattern/' + d[1] + '.png'; });
+ defs.append('clipPath')
+ .attr('id', 'clip-square-12')
+ .append('rect')
+ .attr({
+ x: 0,
+ y: 0,
+ width: 12,
+ height: 12
+ });
+
+ defs.append('image')
+ .attr({
+ id: 'maki-sprite',
+ width: 306,
+ height: 294,
+ 'xlink:href': 'img/maki.png'
+ });
+
+ _.forEach(_.find(document.styleSheets, function(stylesheet) {
+ return stylesheet.href.indexOf("maki.css") > 0;
+ }).cssRules, function(rule) {
+ var klass = rule.selectorText,
+ match = klass.match(/^\.(maki-[a-z0-9-]+-12)$/);
+ if (match) {
+ var id = match[1];
+ match = rule.style.backgroundPosition.match(/(-?\d+)px (-?\d+)px/);
+ defs.append('use')
+ .attr('id', id)
+ .attr('transform', "translate(" + match[1] + "," + match[2] + ")")
+ .attr('xlink:href', '#maki-sprite');
+ }
+ });
var layers = selection.selectAll('.layer')
.data(['fill', 'shadow', 'casing', 'stroke', 'text', 'hit', 'halo', 'label']);
diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js
index 7a00f970e..4b9c4be7c 100644
--- a/js/id/ui/inspector.js
+++ b/js/id/ui/inspector.js
@@ -30,11 +30,7 @@ iD.ui.Inspector = function(context) {
inspectorbody.call(presetGrid, true);
});
- if (initial) {
- inspectorbody.call(presetGrid);
- } else {
- inspectorbody.call(tagEditor);
- }
+ inspectorbody.call(initial ? presetGrid : tagEditor);
selection.call(iD.ui.Toggle(true));
}
diff --git a/js/id/ui/tag_editor.js b/js/id/ui/tag_editor.js
index 8c9d1d3b7..6750685a5 100644
--- a/js/id/ui/tag_editor.js
+++ b/js/id/ui/tag_editor.js
@@ -26,7 +26,7 @@ iD.ui.TagEditor = function(context) {
// find a preset that best fits
} else if (!preset) {
- preset = presets.matchType(entity, context.graph()).matchTags(entity);
+ preset = presets.match(entity, context.graph());
}
selection.html('');