diff --git a/js/id/presets.js b/js/id/presets.js
index 832b95f7c..c1d5090f9 100644
--- a/js/id/presets.js
+++ b/js/id/presets.js
@@ -11,6 +11,37 @@ iD.presets = function() {
other,
other_area;
+ // Index of presets by (geometry, tag key).
+ var index = {
+ point: {},
+ vertex: {},
+ line: {},
+ area: {},
+ relation: {}
+ };
+
+ all.match = function(entity, resolver) {
+ var geometry = entity.geometry(resolver),
+ geometryMatches = index[geometry],
+ best = -1,
+ match = geometry === 'area' ? other_area : other;
+
+ for (var k in entity.tags) {
+ var keyMatches = geometryMatches[k];
+ if (!keyMatches) continue;
+
+ for (var i = 0; i < keyMatches.length; i++) {
+ var score = keyMatches[i].matchScore(entity);
+ if (score > best) {
+ best = score;
+ match = keyMatches[i];
+ }
+ }
+ }
+
+ return match;
+ };
+
all.load = function(d) {
if (d.fields) {
@@ -45,6 +76,18 @@ iD.presets = function() {
other = all.item('other');
other_area = all.item('other_area');
+ for (var i = 0; i < all.collection.length; i++) {
+ var preset = all.collection[i],
+ geometry = preset.geometry;
+
+ for (var j = 0; j < geometry.length; j++) {
+ var g = index[geometry[j]];
+ for (var k in preset.tags) {
+ (g[k] = g[k] || []).push(preset);
+ }
+ }
+ }
+
return all;
};
diff --git a/js/id/presets/collection.js b/js/id/presets/collection.js
index 8087fd861..9459d8efb 100644
--- a/js/id/presets/collection.js
+++ b/js/id/presets/collection.js
@@ -10,32 +10,12 @@ iD.presets.Collection = function(collection) {
});
},
- match: function(entity, resolver) {
- return presets.matchGeometry(entity.geometry(resolver)).matchTags(entity);
- },
-
matchGeometry: function(geometry) {
return iD.presets.Collection(collection.filter(function(d) {
return d.matchGeometry(geometry);
}));
},
- matchTags: function(entity) {
-
- var best = -1,
- match;
-
- for (var i = 0; i < collection.length; i++) {
- var score = collection[i].matchScore(entity);
- if (score > best) {
- best = score;
- match = collection[i];
- }
- }
-
- return match;
- },
-
search: function(value) {
if (!value) return this;
diff --git a/test/index.html b/test/index.html
index f7142be05..bb376d036 100644
--- a/test/index.html
+++ b/test/index.html
@@ -246,6 +246,7 @@
+
diff --git a/test/index_packaged.html b/test/index_packaged.html
index af2741700..f4a1a9145 100644
--- a/test/index_packaged.html
+++ b/test/index_packaged.html
@@ -87,6 +87,7 @@
+
diff --git a/test/spec/presets.js b/test/spec/presets.js
new file mode 100644
index 000000000..f6ffcf706
--- /dev/null
+++ b/test/spec/presets.js
@@ -0,0 +1,38 @@
+describe("iD.presets", function() {
+ var p = {
+ other: {
+ tags: {},
+ geometry: ['point', 'vertex', 'line', 'area']
+ },
+ residential: {
+ tags: {
+ highway: 'residential'
+ },
+ geometry: ['line']
+ },
+ park: {
+ tags: {
+ leisure: 'park'
+ },
+ geometry: ['point', 'area']
+ }
+ };
+
+ var c = iD.presets().load({presets: p}),
+ w = iD.Way({tags: { highway: 'residential'}}),
+ g = iD.Graph().replace(w);
+
+ describe("#match", function() {
+ it("returns a collection containing presets matching a geometry and tags", function() {
+ var way = iD.Way({tags: { highway: 'residential'}}),
+ graph = iD.Graph([way]);
+ expect(c.match(way, graph).id).to.eql('residential');
+ });
+
+ it("returns an other preset when no tags match", function() {
+ var way = iD.Way({tags: {foo: 'bar'}}),
+ graph = iD.Graph([way]);
+ expect(c.match(way, graph).id).to.eql('other');
+ });
+ });
+});
diff --git a/test/spec/presets/collection.js b/test/spec/presets/collection.js
index 8bfb8d416..2c86d499a 100644
--- a/test/spec/presets/collection.js
+++ b/test/spec/presets/collection.js
@@ -36,12 +36,6 @@ describe("iD.presets.Collection", function() {
});
});
- describe("#matchTags", function() {
- it("returns a new collection only containing presets matching an entity's tags", function() {
- expect(c.matchTags(w, g)).to.eql(p.residential);
- });
- });
-
describe("#search", function() {
it("filters presets by name", function() {
expect(c.search("resid").collection.indexOf(p.residential) >= 0).to.eql(true);