|
/* 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/Handler/Click.js |
|
* @requires OpenLayers/Handler/Box.js |
|
* @requires OpenLayers/Handler/Hover.js |
|
* @requires OpenLayers/Filter/Spatial.js |
|
*/ |
|
|
|
/** |
|
* Class: OpenLayers.Control.GetFeature |
|
* Gets vector features for locations underneath the mouse cursor. Can be |
|
* configured to act on click, hover or dragged boxes. Uses an |
|
* <OpenLayers.Protocol> that supports spatial filters to retrieve |
|
* features from a server and fires events that notify applications of the |
|
* selected features. |
|
* |
|
* Inherits from: |
|
* - <OpenLayers.Control> |
|
*/ |
|
OpenLayers.Control.GetFeature = OpenLayers.Class(OpenLayers.Control, { |
|
|
|
/** |
|
* APIProperty: protocol |
|
* {<OpenLayers.Protocol>} Required. The protocol used for fetching |
|
* features. |
|
*/ |
|
protocol: null, |
|
|
|
/** |
|
* APIProperty: multipleKey |
|
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets |
|
* the <multiple> property to true. Default is null. |
|
*/ |
|
multipleKey: null, |
|
|
|
/** |
|
* APIProperty: toggleKey |
|
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets |
|
* the <toggle> property to true. Default is null. |
|
*/ |
|
toggleKey: null, |
|
|
|
/** |
|
* Property: modifiers |
|
* {Object} The event modifiers to use, according to the current event |
|
* being handled by this control's handlers |
|
*/ |
|
modifiers: null, |
|
|
|
/** |
|
* APIProperty: multiple |
|
* {Boolean} Allow selection of multiple geometries. Default is false. |
|
*/ |
|
multiple: false, |
|
|
|
/** |
|
* APIProperty: click |
|
* {Boolean} Use a click handler for selecting/unselecting features. If |
|
* both <click> and <box> are set to true, the click handler takes |
|
* precedence over the box handler if a box with zero extent was |
|
* selected. Default is true. |
|
*/ |
|
click: true, |
|
|
|
/** |
|
* APIProperty: single |
|
* {Boolean} Tells whether select by click should select a single |
|
* feature. If set to false, all matching features are selected. |
|
* If set to true, only the best matching feature is selected. |
|
* This option has an effect only of the <click> option is set |
|
* to true. Default is true. |
|
*/ |
|
single: true, |
|
|
|
/** |
|
* APIProperty: clickout |
|
* {Boolean} Unselect features when clicking outside any feature. |
|
* Applies only if <click> is true. Default is true. |
|
*/ |
|
clickout: true, |
|
|
|
/** |
|
* APIProperty: toggle |
|
* {Boolean} Unselect a selected feature on click. Applies only if |
|
* <click> is true. Default is false. |
|
*/ |
|
toggle: false, |
|
|
|
/** |
|
* APIProperty: clickTolerance |
|
* {Integer} Tolerance for the filter query in pixels. This has the |
|
* same effect as the tolerance parameter on WMS GetFeatureInfo |
|
* requests. Will be ignored for box selections. Applies only if |
|
* <click> or <hover> is true. Default is 5. Note that this not |
|
* only affects requests on click, but also on hover. |
|
*/ |
|
clickTolerance: 5, |
|
|
|
/** |
|
* APIProperty: hover |
|
* {Boolean} Send feature requests on mouse moves. Default is false. |
|
*/ |
|
hover: false, |
|
|
|
/** |
|
* APIProperty: box |
|
* {Boolean} Allow feature selection by drawing a box. If set to |
|
* true set <click> to false to disable the click handler and |
|
* rely on the box handler only, even for "zero extent" boxes. |
|
* See the description of the <click> option for additional |
|
* information. Default is false. |
|
*/ |
|
box: false, |
|
|
|
/** |
|
* APIProperty: maxFeatures |
|
* {Integer} Maximum number of features to return from a query in single mode |
|
* if supported by the <protocol>. This set of features is then used to |
|
* determine the best match client-side. Default is 10. |
|
*/ |
|
maxFeatures: 10, |
|
|
|
/** |
|
* Property: features |
|
* {Object} Hash of {<OpenLayers.Feature.Vector>}, keyed by fid, holding |
|
* the currently selected features |
|
*/ |
|
features: null, |
|
|
|
/** |
|
* Proeprty: hoverFeature |
|
* {<OpenLayers.Feature.Vector>} The feature currently selected by the |
|
* hover handler |
|
*/ |
|
hoverFeature: null, |
|
|
|
/** |
|
* APIProperty: handlerOptions |
|
* {Object} Additional options for the handlers used by this control. This |
|
* is a hash with the keys "click", "box" and "hover". |
|
*/ |
|
handlerOptions: null, |
|
|
|
/** |
|
* Property: handlers |
|
* {Object} Object with references to multiple <OpenLayers.Handler> |
|
* instances. |
|
*/ |
|
handlers: null, |
|
|
|
/** |
|
* Property: hoverResponse |
|
* {<OpenLayers.Protocol.Response>} The response object associated with |
|
* the currently running hover request (if any). |
|
*/ |
|
hoverResponse: null, |
|
|
|
/** |
|
* Property: filterType |
|
* {<String>} The type of filter to use when sending off a request. |
|
* Possible values: |
|
* OpenLayers.Filter.Spatial.<BBOX|INTERSECTS|WITHIN|CONTAINS> |
|
* Defaults to: OpenLayers.Filter.Spatial.BBOX |
|
*/ |
|
filterType: OpenLayers.Filter.Spatial.BBOX, |
|
|
|
/** |
|
* Constant: EVENT_TYPES |
|
* |
|
* Supported event types: |
|
* beforefeatureselected - Triggered when <click> is true before a |
|
* feature is selected. The event object has a feature property with |
|
* the feature about to select |
|
* featureselected - Triggered when <click> is true and a feature is |
|
* selected. The event object has a feature property with the |
|
* selected feature |
|
* beforefeaturesselected - Triggered when <click> is true before a |
|
* set of features is selected. The event object is an array of |
|
* feature properties with the features about to be selected. |
|
* Return false after receiving this event to discontinue processing |
|
* of all featureselected events and the featuresselected event. |
|
* featuresselected - Triggered when <click> is true and a set of |
|
* features is selected. The event object is an array of feature |
|
* properties of the selected features |
|
* featureunselected - Triggered when <click> is true and a feature is |
|
* unselected. The event object has a feature property with the |
|
* unselected feature |
|
* clickout - Triggered when when <click> is true and no feature was |
|
* selected. |
|
* hoverfeature - Triggered when <hover> is true and the mouse has |
|
* stopped over a feature |
|
* outfeature - Triggered when <hover> is true and the mouse moves |
|
* moved away from a hover-selected feature |
|
*/ |
|
EVENT_TYPES: ["featureselected", "featuresselected", "featureunselected", |
|
"clickout", "beforefeatureselected", "beforefeaturesselected", |
|
"hoverfeature", "outfeature"], |
|
|
|
/** |
|
* Constructor: OpenLayers.Control.GetFeature |
|
* Create a new control for fetching remote features. |
|
* |
|
* Parameters: |
|
* options - {Object} A configuration object which at least has to contain |
|
* a <protocol> property |
|
*/ |
|
initialize: function(options) { |
|
// concatenate events specific to vector with those from the base |
|
this.EVENT_TYPES = |
|
OpenLayers.Control.GetFeature.prototype.EVENT_TYPES.concat( |
|
OpenLayers.Control.prototype.EVENT_TYPES |
|
); |
|
|
|
options.handlerOptions = options.handlerOptions || {}; |
|
|
|
OpenLayers.Control.prototype.initialize.apply(this, [options]); |
|
|
|
this.features = {}; |
|
|
|
this.handlers = {}; |
|
|
|
if(this.click) { |
|
this.handlers.click = new OpenLayers.Handler.Click(this, |
|
{click: this.selectClick}, this.handlerOptions.click || {}); |
|
} |
|
|
|
if(this.box) { |
|
this.handlers.box = new OpenLayers.Handler.Box( |
|
this, {done: this.selectBox}, |
|
OpenLayers.Util.extend(this.handlerOptions.box, { |
|
boxDivClassName: "olHandlerBoxSelectFeature" |
|
}) |
|
); |
|
} |
|
|
|
if(this.hover) { |
|
this.handlers.hover = new OpenLayers.Handler.Hover( |
|
this, {'move': this.cancelHover, 'pause': this.selectHover}, |
|
OpenLayers.Util.extend(this.handlerOptions.hover, { |
|
'delay': 250 |
|
}) |
|
); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: activate |
|
* Activates the control. |
|
* |
|
* Returns: |
|
* {Boolean} The control was effectively activated. |
|
*/ |
|
activate: function () { |
|
if (!this.active) { |
|
for(var i in this.handlers) { |
|
this.handlers[i].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) { |
|
for(var i in this.handlers) { |
|
this.handlers[i].deactivate(); |
|
} |
|
} |
|
return OpenLayers.Control.prototype.deactivate.apply( |
|
this, arguments |
|
); |
|
}, |
|
|
|
/** |
|
* Method: selectClick |
|
* Called on click |
|
* |
|
* Parameters: |
|
* evt - {<OpenLayers.Event>} |
|
*/ |
|
selectClick: function(evt) { |
|
var bounds = this.pixelToBounds(evt.xy); |
|
|
|
this.setModifiers(evt); |
|
this.request(bounds, {single: this.single}); |
|
}, |
|
|
|
/** |
|
* Method: selectBox |
|
* Callback from the handlers.box set up when <box> selection is on |
|
* |
|
* Parameters: |
|
* position - {<OpenLayers.Bounds>} |
|
*/ |
|
selectBox: function(position) { |
|
var bounds; |
|
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) |
|
); |
|
bounds = new OpenLayers.Bounds( |
|
minXY.lon, minXY.lat, maxXY.lon, maxXY.lat |
|
); |
|
|
|
} else { |
|
if(this.click) { |
|
// box without extent - let the click handler take care of it |
|
return; |
|
} |
|
bounds = this.pixelToBounds(position); |
|
} |
|
this.setModifiers(this.handlers.box.dragHandler.evt); |
|
this.request(bounds); |
|
}, |
|
|
|
/** |
|
* Method selectHover |
|
* Callback from the handlers.hover set up when <hover> selection is on |
|
* |
|
* Parameters: |
|
* evt {Object} - event object with an xy property |
|
*/ |
|
selectHover: function(evt) { |
|
var bounds = this.pixelToBounds(evt.xy); |
|
this.request(bounds, {single: true, hover: true}); |
|
}, |
|
|
|
/** |
|
* Method: cancelHover |
|
* Callback from the handlers.hover set up when <hover> selection is on |
|
*/ |
|
cancelHover: function() { |
|
if (this.hoverResponse) { |
|
this.protocol.abort(this.hoverResponse); |
|
this.hoverResponse = null; |
|
|
|
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait"); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: request |
|
* Sends a GetFeature request to the WFS |
|
* |
|
* Parameters: |
|
* bounds - {<OpenLayers.Bounds>} bounds for the request's BBOX filter |
|
* options - {Object} additional options for this method. |
|
* |
|
* Supported options include: |
|
* single - {Boolean} A single feature should be returned. |
|
* Note that this will be ignored if the protocol does not |
|
* return the geometries of the features. |
|
* hover - {Boolean} Do the request for the hover handler. |
|
*/ |
|
request: function(bounds, options) { |
|
options = options || {}; |
|
var filter = new OpenLayers.Filter.Spatial({ |
|
type: this.filterType, |
|