diff --git a/examples/select-feature.html b/examples/select-feature.html
index c1a9b9a18d..02f23c285d 100644
--- a/examples/select-feature.html
+++ b/examples/select-feature.html
@@ -41,7 +41,8 @@
clickout: false, toggle: false,
multiple: false, hover: false,
toggleKey: "ctrlKey", // ctrl key removes from selection
- multipleKey: "shiftKey" // shift key adds to selection
+ multipleKey: "shiftKey", // shift key adds to selection
+ box: true
}
)
};
@@ -69,8 +70,8 @@
drawControls.select.clickout = clickout;
var hover = document.getElementById("hover").checked;
drawControls.select.hover = hover;
- if(hover && drawControls.select.active) {
- // turn on/off to clear feature property of handler
+ drawControls.select.box = document.getElementById("box").checked;
+ if(drawControls.select.active) {
drawControls.select.deactivate();
drawControls.select.activate();
}
@@ -110,6 +111,11 @@
onclick="toggleControl(this);" />
+ -
+
+
+
-
diff --git a/lib/OpenLayers/Control/SelectFeature.js b/lib/OpenLayers/Control/SelectFeature.js
index cbb715eebd..b638cd26ec 100644
--- a/lib/OpenLayers/Control/SelectFeature.js
+++ b/lib/OpenLayers/Control/SelectFeature.js
@@ -59,6 +59,12 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
*/
hover: false,
+ /**
+ * APIProperty: box
+ * {Boolean} Allow feature selection by drawing a box.
+ */
+ box: false,
+
/**
* APIProperty: onSelect
* {Function} Optional function to be called when a feature is selected.
@@ -88,7 +94,7 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
/**
* APIProperty: callbacks
- * {Object} The functions that are sent to the handler for callback
+ * {Object} The functions that are sent to the handlers.feature for callback
*/
callbacks: null,
@@ -106,10 +112,11 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
renderIntent: "select",
/**
- * Property: handler
- * {}
+ * Property: handlers
+ * {Object} Object with references to multiple
+ * instances.
*/
- handler: null,
+ handlers: null,
/**
* Constructor:
@@ -127,10 +134,56 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
over: this.overFeature,
out: this.outFeature
}, this.callbacks);
- var handlerOptions = { geometryTypes: this.geometryTypes};
- this.handler = new OpenLayers.Handler.Feature(this, layer,
- this.callbacks,
- handlerOptions);
+ this.handlers = {
+ feature: new OpenLayers.Handler.Feature(
+ this, layer, this.callbacks, {geometryTypes: this.geometryTypes}
+ )
+ };
+
+ if (this.box) {
+ this.handlers.box = new OpenLayers.Handler.Box(
+ this, {done: this.selectBox},
+ {boxDivClassName: "olHandlerBoxSelectFeature"}
+ );
+ }
+ },
+
+ /**
+ * Method: activate
+ * Activates the control.
+ *
+ * Returns:
+ * {Boolean} The control was effectively activated.
+ */
+ activate: function () {
+ if (!this.active) {
+ this.handlers.feature.activate();
+ if(this.box && this.handlers.box) {
+ this.handlers.box.activate();
+ }
+ }
+ return OpenLayers.Control.prototype.activate.apply(
+ this, arguments
+ );
+ },
+
+ /**
+ * Method: deactivate
+ * Deactivates the control.
+ *
+ * Returns:
+ * {Boolean} The control was effectively deactivated.
+ */
+ deactivate: function () {
+ if (this.active) {
+ this.handlers.feature.deactivate();
+ if(this.handlers.box) {
+ this.handlers.box.deactivate();
+ }
+ }
+ return OpenLayers.Control.prototype.deactivate.apply(
+ this, arguments
+ );
},
/**
@@ -188,7 +241,7 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
* {Boolean} Allow for multiple selected features.
*/
multipleSelect: function() {
- return this.multiple || this.handler.evt[this.multipleKey];
+ return this.multiple || this.handlers.feature.evt[this.multipleKey];
},
/**
@@ -200,7 +253,7 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
* {Boolean} Toggle the selected state of a feature.
*/
toggleSelect: function() {
- return this.toggle || this.handler.evt[this.toggleKey];
+ return this.toggle || this.handlers.feature.evt[this.toggleKey];
},
/**
@@ -279,6 +332,49 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
this.layer.events.triggerEvent("featureunselected", {feature: feature});
this.onUnselect(feature);
},
+
+ /**
+ * Method: selectBox
+ * Callback from the handlers.box set up when selection is true
+ * on.
+ *
+ * Parameters:
+ * position - { || }
+ */
+ selectBox: function(position) {
+ if (position instanceof OpenLayers.Bounds) {
+ var minXY = this.map.getLonLatFromPixel(
+ new OpenLayers.Pixel(position.left, position.bottom)
+ );
+ var maxXY = this.map.getLonLatFromPixel(
+ new OpenLayers.Pixel(position.right, position.top)
+ );
+ var bounds = new OpenLayers.Bounds(
+ minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
+ );
+
+ // if multiple is false, first deselect currently selected features
+ if (!this.multipleSelect()) {
+ this.unselectAll();
+ }
+
+ // because we're using a box, we consider we want multiple selection
+ var prevMultiple = this.multiple;
+ this.multiple = true;
+ for(var i=0, len = this.layer.features.length; i -1) {
+ if (bounds.toGeometry().intersects(feature.geometry)) {
+ if (OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) == -1) {
+ this.select(feature);
+ }
+ }
+ }
+ }
+ this.multiple = prevMultiple;
+ }
+ },
/**
* Method: setMap
@@ -288,7 +384,10 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
* map - {}
*/
setMap: function(map) {
- this.handler.setMap(map);
+ this.handlers.feature.setMap(map);
+ if (this.box) {
+ this.handlers.box.setMap(map);
+ }
OpenLayers.Control.prototype.setMap.apply(this, arguments);
},
diff --git a/tests/Control/SelectFeature.html b/tests/Control/SelectFeature.html
index f6cf6e2cd0..d7e6b12781 100644
--- a/tests/Control/SelectFeature.html
+++ b/tests/Control/SelectFeature.html
@@ -13,19 +13,23 @@
"new OpenLayers.Control.SelectFeature returns an instance");
t.eq(control.layer, "bar",
"constructor sets layer correctly");
-// t.eq(control.featureHandler.geometryTypes, "foo",
+// t.eq(control.handlers.feature.geometryTypes, "foo",
// "constructor sets options correctly on feature handler");
}
function test_Control_SelectFeature_destroy(t) {
- t.plan(1);
+ t.plan(2);
var map = new OpenLayers.Map("map");
var layer = new OpenLayers.Layer.Vector();
map.addLayer(layer);
- var control = new OpenLayers.Control.SelectFeature(layer);
- control.handler.destroy = function() {
+ var control = new OpenLayers.Control.SelectFeature(layer, {box: true});
+ control.handlers.feature.deactivate = function() {
t.ok(true,
- "control.destroy calls destroy on feature handler");
+ "control.deactivate calls deactivate on feature handler");
+ }
+ control.handlers.box.deactivate = function() {
+ t.ok(true,
+ "control.deactivate calls deactivate on box handler");
}
// should nullify the layer property here
control.destroy();
@@ -61,7 +65,7 @@
};
// mock up active control
var control = new OpenLayers.Control.SelectFeature(layer);
- control.handler = {
+ control.handlers.feature = {
evt: {}
};
// mock up features
@@ -108,35 +112,85 @@
control.clickFeature(feature);
+ }
+
+ function test_box(t) {
+ t.plan(5);
+ var map = new OpenLayers.Map("map");
+ var layer = new OpenLayers.Layer.Vector();
+ map.addLayer(layer);
+ var control = new OpenLayers.Control.SelectFeature(layer, {'multiple': true, box: true });
+ var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0));
+ var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,1));
+ var feature3 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-2,-2));
+ var feature4 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([
+ new OpenLayers.Geometry.Point(0, 0), new OpenLayers.Geometry.Point(1, 1)
+ ]));
+ layer.addFeatures([feature, feature2, feature3, feature4]);
+ control.setMap(map);
+ map.getLonLatFromPixel = function(arg) {
+ return new OpenLayers.LonLat(arg.x, arg.y);
+ }
+ control.selectBox(new OpenLayers.Bounds(-1, -1, 2, 2));
+ t.eq(layer.selectedFeatures.length, 3, "box around all features selects 3 features");
+
+ control.selectBox(new OpenLayers.Bounds(-3, -3, -1, -1));
+ t.eq(layer.selectedFeatures.length, 4, "box around other features doesn't turn off already selected features.");
+
+ control.multipleSelect = function() {
+ return false;
+ };
+ control.selectBox(new OpenLayers.Bounds(-3, -3, -1, -1));
+ t.eq(layer.selectedFeatures.length, 1, "box around other features correctly turns off already selected features.");
+
+ control.geometryTypes = null;
+ control.selectBox(new OpenLayers.Bounds(-100, -100, 100, 100));
+ t.eq(layer.selectedFeatures.length, layer.features.length, "all features selected with no geometryTypes filter");
+
+ control.geometryTypes = ["OpenLayers.Geometry.Point"];
+ control.selectBox(new OpenLayers.Bounds(-100, -100, 100, 100));
+ t.eq(layer.selectedFeatures.length, 3, "3 features selected with geometryTypes filter");
+
+ ["OpenLayers.Geometry.Point"]
+
+
}
function test_Control_SelectFeature_activate(t) {
+ t.plan(4);
+ var map = new OpenLayers.Map("map");
+ var layer = new OpenLayers.Layer.Vector();
+ map.addLayer(layer);
+ var control = new OpenLayers.Control.SelectFeature(layer, {box: true});
+ map.addControl(control);
+ t.ok(!control.handlers.feature.active,
+ "feature handler is not active prior to activating control");
+ t.ok(!control.handlers.box.active,
+ "box handler is not active prior to activating control");
+ control.activate();
+ t.ok(control.handlers.feature.active,
+ "feature handler is active after activating control");
+ t.ok(control.handlers.box.active,
+ "box handler is active after activating control");
+ }
+
+ function test_Control_SelectFeature_deactivate(t) {
t.plan(2);
var map = new OpenLayers.Map("map");
var layer = new OpenLayers.Layer.Vector();
map.addLayer(layer);
- var control = new OpenLayers.Control.SelectFeature(layer);
+ var control = new OpenLayers.Control.SelectFeature(layer, {box: true});
map.addControl(control);
- t.ok(!control.handler.active,
- "feature handler is not active prior to activating control");
- control.activate();
- t.ok(control.handler.active,
- "feature handler is active after activating control");
- }
- function test_Control_SelectFeature_deactivate(t) {
- t.plan(1);
- var map = new OpenLayers.Map("map");
- var layer = new OpenLayers.Layer.Vector();
- map.addLayer(layer);
- var control = new OpenLayers.Control.SelectFeature(layer);
- map.addControl(control);
-
control.activate();
- control.handler.deactivate = function() {
+ control.handlers.feature.deactivate = function() {
t.ok(true,
"control.deactivate calls deactivate on feature handler");
}
+ control.handlers.box.deactivate = function() {
+ t.ok(true,
+ "control.deactivate calls deactivate on box handler");
+ }
control.deactivate();
}
diff --git a/theme/default/style.css b/theme/default/style.css
index 909aeeaeb0..5e5283188a 100644
--- a/theme/default/style.css
+++ b/theme/default/style.css
@@ -230,6 +230,14 @@ div.olControlMousePosition {
opacity: 0.50;
font-size: 1px;
filter: alpha(opacity=50);
+}
+.olHandlerBoxSelectFeature {
+ border: 2px solid blue;
+ position: absolute;
+ background-color: white;
+ opacity: 0.50;
+ font-size: 1px;
+ filter: alpha(opacity=50);
}
/*