From 1f0c21ac6002e091548ba168f73811c2ad8cfab1 Mon Sep 17 00:00:00 2001 From: acanimal Date: Thu, 26 Mar 2015 09:35:39 +0100 Subject: [PATCH 1/3] Add "filter" option to Select interaction --- externs/olx.js | 11 ++++++++++- src/ol/interaction/selectinteraction.js | 26 ++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index bb863598be..5686485536 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -2584,7 +2584,8 @@ olx.interaction.PointerOptions.prototype.handleUpEvent; * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * removeCondition: (ol.events.ConditionType|undefined), * toggleCondition: (ol.events.ConditionType|undefined), - * multi: (boolean|undefined)}} + * multi: (boolean|undefined), + * filter: (ol.interaction.SelectFilterFunction|undefined)}} * @api */ olx.interaction.SelectOptions; @@ -2670,6 +2671,14 @@ olx.interaction.SelectOptions.prototype.toggleCondition; */ olx.interaction.SelectOptions.prototype.multi; +/** + * A function that takes an {@link ol.Feature} and an {@link ol.layer.Layer} and + * returns `true` if the feature may be selected or `false` otherwise. + * @type {ol.interaction.SelectFilterFunction|undefined} + * @api + */ +olx.interaction.SelectOptions.prototype.filter; + /** * Namespace. diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index c205f65f23..9e1c16a638 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -27,6 +27,15 @@ ol.SelectEventType = { }; +/** + * A function that takes an {@link ol.Feature} and an {@link ol.layer.Layer} + * and returns `true` if the feature may be selected or `false` otherwise. + * @typedef {function(ol.Feature, ol.layer.Layer): boolean} + * @api + */ +ol.interaction.SelectFilterFunction; + + /** * @classdesc @@ -115,6 +124,13 @@ ol.interaction.Select = function(opt_options) { */ this.multi_ = goog.isDef(options.multi) ? options.multi : false; + /** + * @private + * @type {ol.interaction.SelectFilterFunction} + */ + this.filter_ = goog.isDef(options.filter) ? options.filter : + goog.functions.TRUE; + var layerFilter; if (goog.isDef(options.layers)) { if (goog.isFunction(options.layers)) { @@ -198,7 +214,9 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) { * @param {ol.layer.Layer} layer Layer. */ function(feature, layer) { - selected.push(feature); + if (this.filter_(feature, layer)) { + selected.push(feature); + } return !this.multi_; }, this, this.layerFilter_); if (selected.length > 0 && features.getLength() == 1 && @@ -223,14 +241,16 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) { var index = goog.array.indexOf(features.getArray(), feature); if (index == -1) { if (add || toggle) { - selected.push(feature); + if (this.filter_(feature, layer)) { + selected.push(feature); + } } } else { if (remove || toggle) { deselected.push(feature); } } - }, undefined, this.layerFilter_); + }, this, this.layerFilter_); var i; for (i = deselected.length - 1; i >= 0; --i) { features.remove(deselected[i]); From 2f417bbb28cbe192ca069151ba75dc016028a6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 30 Mar 2015 13:07:50 +0200 Subject: [PATCH 2/3] Add empty lines for better code readability --- test/spec/ol/interaction/selectinteraction.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/spec/ol/interaction/selectinteraction.test.js b/test/spec/ol/interaction/selectinteraction.test.js index d0aaf4f85a..0cefc2c735 100644 --- a/test/spec/ol/interaction/selectinteraction.test.js +++ b/test/spec/ol/interaction/selectinteraction.test.js @@ -8,6 +8,7 @@ describe('ol.interaction.Select', function() { beforeEach(function(done) { target = document.createElement('div'); + var style = target.style; style.position = 'absolute'; style.left = '-1000px'; @@ -15,6 +16,7 @@ describe('ol.interaction.Select', function() { style.width = width + 'px'; style.height = height + 'px'; document.body.appendChild(target); + var geometry = new ol.geom.Polygon([[[0, 0], [0, 40], [40, 40], [40, 0]]]); var geometry2 = new ol.geom.Polygon([[[0, 0], [0, 40], [40, 40], [40, 0]]]); var feature = new ol.Feature({ @@ -23,10 +25,12 @@ describe('ol.interaction.Select', function() { var feature2 = new ol.Feature({ geometry: geometry2 }); + source = new ol.source.Vector({ features: [feature, feature2] }); var layer = new ol.layer.Vector({source: source}); + map = new ol.Map({ target: target, layers: [layer], @@ -36,6 +40,7 @@ describe('ol.interaction.Select', function() { resolution: 1 }) }); + map.on('postrender', function() { done(); }); From f90308b504a1dd741db40fed54231bed56383a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 30 Mar 2015 13:35:00 +0200 Subject: [PATCH 3/3] Tests for the Select interaction's filter option --- .../ol/interaction/selectinteraction.test.js | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/test/spec/ol/interaction/selectinteraction.test.js b/test/spec/ol/interaction/selectinteraction.test.js index 0cefc2c735..4d3278fe79 100644 --- a/test/spec/ol/interaction/selectinteraction.test.js +++ b/test/spec/ol/interaction/selectinteraction.test.js @@ -2,6 +2,7 @@ goog.provide('ol.test.interaction.Select'); describe('ol.interaction.Select', function() { var target, map, source; + var feature1, feature2; var width = 360; var height = 180; @@ -17,17 +18,21 @@ describe('ol.interaction.Select', function() { style.height = height + 'px'; document.body.appendChild(target); - var geometry = new ol.geom.Polygon([[[0, 0], [0, 40], [40, 40], [40, 0]]]); + var geometry1 = new ol.geom.Polygon([[[0, 0], [0, 40], [40, 40], [40, 0]]]); var geometry2 = new ol.geom.Polygon([[[0, 0], [0, 40], [40, 40], [40, 0]]]); - var feature = new ol.Feature({ - geometry: geometry + + feature1 = new ol.Feature({ + geometry: geometry1 }); - var feature2 = new ol.Feature({ + feature1.setId('fid1'); + + feature2 = new ol.Feature({ geometry: geometry2 }); + feature2.setId('fid2'); source = new ol.source.Vector({ - features: [feature, feature2] + features: [feature1, feature2] }); var layer = new ol.layer.Vector({source: source}); @@ -132,6 +137,45 @@ describe('ol.interaction.Select', function() { }); }); + describe.only('filter out features using the filter option', function() { + var select; + + describe('with multi set to true', function() { + + it('does not select features that are filtered out', function() { + var select = new ol.interaction.Select({ + multi: true, + filter: function(feature, layer) { + return feature.getId() !== 'fid2'; + } + }); + map.addInteraction(select); + + simulateEvent(ol.MapBrowserEvent.EventType.SINGLECLICK, 10, -20); + var features = select.getFeatures(); + expect(features.getLength()).to.equal(1); + expect(features.item(0).getId()).not.to.be('fid2'); + }); + }); + + describe('with multi set to false', function() { + + it('does not select features that are filtered out', function() { + var select = new ol.interaction.Select({ + multi: false, + filter: function(feature, layer) { + return feature.getId() !== 'fid2'; + } + }); + map.addInteraction(select); + simulateEvent(ol.MapBrowserEvent.EventType.SINGLECLICK, 10, -20); + var features = select.getFeatures(); + expect(features.getLength()).to.equal(0); + }); + }); + + }); + describe('#setActive()', function() { var interaction;