|
/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
|
* full list of contributors). Published under the Clear BSD license. |
|
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the |
|
* full text of the license. */ |
|
|
|
|
|
/** |
|
* @requires OpenLayers/Control.js |
|
* @requires OpenLayers/Feature/Vector.js |
|
* @requires OpenLayers/Handler/Feature.js |
|
* @requires OpenLayers/Layer/Vector/RootContainer.js |
|
*/ |
|
|
|
/** |
|
* Class: OpenLayers.Control.SelectFeature |
|
* The SelectFeature control selects vector features from a given layer on |
|
* click or hover. |
|
* |
|
* Inherits from: |
|
* - <OpenLayers.Control> |
|
*/ |
|
OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, { |
|
|
|
/** |
|
* Constant: EVENT_TYPES |
|
* |
|
* Supported event types: |
|
* - *beforefeaturehighlighted* Triggered before a feature is highlighted |
|
* - *featurehighlighted* Triggered when a feature is highlighted |
|
* - *featureunhighlighted* Triggered when a feature is unhighlighted |
|
*/ |
|
EVENT_TYPES: ["beforefeaturehighlighted", "featurehighlighted", "featureunhighlighted"], |
|
|
|
/** |
|
* Property: multipleKey |
|
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets |
|
* the <multiple> property to true. Default is null. |
|
*/ |
|
multipleKey: null, |
|
|
|
/** |
|
* Property: toggleKey |
|
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets |
|
* the <toggle> property to true. Default is null. |
|
*/ |
|
toggleKey: null, |
|
|
|
/** |
|
* APIProperty: multiple |
|
* {Boolean} Allow selection of multiple geometries. Default is false. |
|
*/ |
|
multiple: false, |
|
|
|
/** |
|
* APIProperty: clickout |
|
* {Boolean} Unselect features when clicking outside any feature. |
|
* Default is true. |
|
*/ |
|
clickout: true, |
|
|
|
/** |
|
* APIProperty: toggle |
|
* {Boolean} Unselect a selected feature on click. Default is false. Only |
|
* has meaning if hover is false. |
|
*/ |
|
toggle: false, |
|
|
|
/** |
|
* APIProperty: hover |
|
* {Boolean} Select on mouse over and deselect on mouse out. If true, this |
|
* ignores clicks and only listens to mouse moves. |
|
*/ |
|
hover: false, |
|
|
|
/** |
|
* APIProperty: highlightOnly |
|
* {Boolean} If true do not actually select features (i.e. place them in the |
|
* layer's selected features array), just highlight them. This property has |
|
* no effect if hover is false. Defaults to false. |
|
*/ |
|
highlightOnly: false, |
|
|
|
/** |
|
* APIProperty: box |
|
* {Boolean} Allow feature selection by drawing a box. |
|
*/ |
|
box: false, |
|
|
|
/** |
|
* Property: onBeforeSelect |
|
* {Function} Optional function to be called before a feature is selected. |
|
* The function should expect to be called with a feature. |
|
*/ |
|
onBeforeSelect: function() {}, |
|
|
|
/** |
|
* APIProperty: onSelect |
|
* {Function} Optional function to be called when a feature is selected. |
|
* The function should expect to be called with a feature. |
|
*/ |
|
onSelect: function() {}, |
|
|
|
/** |
|
* APIProperty: onUnselect |
|
* {Function} Optional function to be called when a feature is unselected. |
|
* The function should expect to be called with a feature. |
|
*/ |
|
onUnselect: function() {}, |
|
|
|
/** |
|
* Property: scope |
|
* {Object} The scope to use with the onBeforeSelect, onSelect, onUnselect |
|
* callbacks. If null the scope will be this control. |
|
*/ |
|
scope: null, |
|
|
|
/** |
|
* APIProperty: geometryTypes |
|
* {Array(String)} To restrict selecting to a limited set of geometry types, |
|
* send a list of strings corresponding to the geometry class names. |
|
*/ |
|
geometryTypes: null, |
|
|
|
/** |
|
* Property: layer |
|
* {<OpenLayers.Layer.Vector>} The vector layer with a common renderer |
|
* root for all layers this control is configured with (if an array of |
|
* layers was passed to the constructor), or the vector layer the control |
|
* was configured with (if a single layer was passed to the constructor). |
|
*/ |
|
layer: null, |
|
|
|
/** |
|
* Property: layers |
|
* {Array(<OpenLayers.Layer.Vector>} The layers this control will work on, |
|
* or null if the control was configured with a single layer |
|
*/ |
|
layers: null, |
|
|
|
/** |
|
* APIProperty: callbacks |
|
* {Object} The functions that are sent to the handlers.feature for callback |
|
*/ |
|
callbacks: null, |
|
|
|
/** |
|
* APIProperty: selectStyle |
|
* {Object} Hash of styles |
|
*/ |
|
selectStyle: null, |
|
|
|
/** |
|
* Property: renderIntent |
|
* {String} key used to retrieve the select style from the layer's |
|
* style map. |
|
*/ |
|
renderIntent: "select", |
|
|
|
/** |
|
* Property: handlers |
|
* {Object} Object with references to multiple <OpenLayers.Handler> |
|
* instances. |
|
*/ |
|
handlers: null, |
|
|
|
/** |
|
* Constructor: OpenLayers.Control.SelectFeature |
|
* Create a new control for selecting features. |
|
* |
|
* Parameters: |
|
* layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers. The |
|
* layer(s) this control will select features from. |
|
* options - {Object} |
|
*/ |
|
initialize: function(layers, options) { |
|
// concatenate events specific to this control with those from the base |
|
this.EVENT_TYPES = |
|
OpenLayers.Control.SelectFeature.prototype.EVENT_TYPES.concat( |
|
OpenLayers.Control.prototype.EVENT_TYPES |
|
); |
|
OpenLayers.Control.prototype.initialize.apply(this, [options]); |
|
|
|
if(this.scope === null) { |
|
this.scope = this; |
|
} |
|
this.initLayer(layers); |
|
var callbacks = { |
|
click: this.clickFeature, |
|
clickout: this.clickoutFeature |
|
}; |
|
if (this.hover) { |
|
callbacks.over = this.overFeature; |
|
callbacks.out = this.outFeature; |
|
} |
|
|
|
this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks); |
|
this.handlers = { |
|
feature: new OpenLayers.Handler.Feature( |
|
this, this.layer, this.callbacks, |
|
{geometryTypes: this.geometryTypes} |
|
) |
|
}; |
|
|
|
if (this.box) { |
|
this.handlers.box = new OpenLayers.Handler.Box( |
|
this, {done: this.selectBox}, |
|
{boxDivClassName: "olHandlerBoxSelectFeature"} |
|
); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: initLayer |
|
* Assign the layer property. If layers is an array, we need to use |
|
* a RootContainer. |
|
* |
|
* Parameters: |
|
* layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers. |
|
*/ |
|
initLayer: function(layers) { |
|
if(layers instanceof Array) { |
|
this.layers = layers; |
|
this.layer = new OpenLayers.Layer.Vector.RootContainer( |
|
this.id + "_container", { |
|
layers: layers |
|
} |
|
); |
|
} else { |
|
this.layer = layers; |
|
} |
|
}, |
|
|
|
/** |
|
* Method: destroy |
|
*/ |
|
destroy: function() { |
|
if(this.active && this.layers) { |
|
this.map.removeLayer(this.layer); |
|
} |
|
OpenLayers.Control.prototype.destroy.apply(this, arguments); |
|
if(this.layers) { |
|
this.layer.destroy(); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: activate |
|
* Activates the control. |
|
* |
|
* Returns: |
|
* {Boolean} The control was effectively activated. |
|
*/ |
|
activate: function () { |
|
if (!this.active) { |
|
if(this.layers) { |
|
this.map.addLayer(this.layer); |
|
} |
|
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(); |
|
} |
|
if(this.layers) { |
|
this.map.removeLayer(this.layer); |
|
} |
|
} |
|
return OpenLayers.Control.prototype.deactivate.apply( |
|
this, arguments |
|
); |
|
}, |
|
|
|
/** |
|
* Method: unselectAll |
|
* Unselect all selected features. To unselect all except for a single |
|
* feature, set the options.except property to the feature. |
|
* |
|
* Parameters: |
|
* options - {Object} Optional configuration object. |
|
*/ |
|
unselectAll: function(options) { |
|
// we'll want an option to supress notification here |
|
var layers = this.layers || [this.layer]; |
|
var layer, feature; |
|
for(var l=0; l<layers.length; ++l) { |
|
layer = layers[l]; |
|
for(var i=layer.selectedFeatures.length-1; i>=0; --i) { |
|
feature = layer.selectedFeatures[i]; |
|
if(!options || options.except != feature) { |
|
this.unselect(feature); |
|
} |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* Method: clickFeature |
|
* Called on click in a feature |
|
* Only responds if this.hover is false. |
|
* |
|
* Parameters: |
|
* feature - {<OpenLayers.Feature.Vector>} |
|
*/ |
|
clickFeature: function(feature) { |
|
if(!this.hover) { |
|
var selected = (OpenLayers.Util.indexOf( |
|
feature.layer.selectedFeatures, feature) > -1); |
|
if(selected) { |
|
if(this.toggleSelect()) { |
|
this.unselect(feature); |
|
} else if(!this.multipleSelect()) { |
|
this.unselectAll({except: feature}); |
|
} |
|
} else { |
|
if(!this.multipleSelect()) { |
|
this.unselectAll({except: feature}); |
|
} |
|
this.select(feature); |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* Method: multipleSelect |
|
* Allow for multiple selected features based on <multiple> property and |
|
* <multipleKey> event modifier. |
|
* |
|
* Returns: |
|
* {Boolean} Allow for multiple selected features. |
|
*/ |
|
multipleSelect: function() { |
|
return this.multiple || (this.handlers.feature.evt && |
|
this.handlers.feature.evt[this.multipleKey]); |
|
}, |
|
|
|
/** |
|
* Method: toggleSelect |
|
* Event should toggle the selected state of a feature based on <toggle> |
|
* property and <toggleKey> event modifier. |
|
* |
|
* Returns: |
|
* {Boolean} Toggle the selected state of a feature. |
|
*/ |
|
toggleSelect: function() { |
|
return this.toggle || (this.handlers.feature.evt && |
|
this.handlers.feature.evt[this.toggleKey]); |
|
}, |
|
|
|
/** |
|
* Method: clickoutFeature |
|
* Called on click outside a previously clicked (selected) feature. |
|
* Only responds if this.hover is false. |
|
* |
|
* Parameters: |
|
* feature - {<OpenLayers.Vector.Feature>} |
|
*/ |
|
clickoutFeature: function(feature) { |
|
if(!this.hover && this.clickout) { |
|
this.unselectAll(); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: overFeature |
|
* Called on over a feature. |
|
* Only responds if this.hover i |