WMSGetFeatureInfo control: add support for mutiple WMS services, r=ahocevar (closes #2091)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@9874 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -31,6 +31,14 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
*/
|
||||
hover: false,
|
||||
|
||||
/**
|
||||
* APIProperty: drillDown
|
||||
* {Boolean} Drill down over all WMS layers in the map. When
|
||||
* using drillDown mode, hover is not possible, and an infoFormat that
|
||||
* returns parseable features is required. Default is false.
|
||||
*/
|
||||
drillDown: false,
|
||||
|
||||
/**
|
||||
* APIProperty: maxFeatures
|
||||
* {Integer} Maximum number of features to return from a WMS query. This
|
||||
@@ -139,7 +147,10 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
* response (String), a *features* property with an array of the
|
||||
* parsed features, an *xy* property with the position of the mouse
|
||||
* click or hover event that triggered the request, and a *request*
|
||||
* property with the request itself.
|
||||
* property with the request itself. If drillDown is set to true and
|
||||
* multiple requests were issued to collect feature info from all
|
||||
* layers, *text* and *request* will only contain the response body
|
||||
* and request object of the last request.
|
||||
*/
|
||||
EVENT_TYPES: ["beforegetfeatureinfo", "getfeatureinfo"],
|
||||
|
||||
@@ -166,8 +177,12 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
options.formatOptions
|
||||
);
|
||||
}
|
||||
|
||||
if(this.drillDown === true) {
|
||||
this.hover = false;
|
||||
}
|
||||
|
||||
if (this.hover) {
|
||||
if(this.hover) {
|
||||
this.handler = new OpenLayers.Handler.Hover(
|
||||
this, {
|
||||
'move': this.cancelHover,
|
||||
@@ -256,9 +271,8 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
*/
|
||||
findLayers: function() {
|
||||
|
||||
var layers = [];
|
||||
|
||||
var candidates = this.layers || this.map.layers;
|
||||
var layers = [];
|
||||
var layer, url;
|
||||
for(var i=0, len=candidates.length; i<len; ++i) {
|
||||
layer = candidates[i];
|
||||
@@ -267,15 +281,14 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
url = layer.url instanceof Array ? layer.url[0] : layer.url;
|
||||
// if the control was not configured with a url, set it
|
||||
// to the first layer url
|
||||
if(!this.url) {
|
||||
if(this.drillDown === false && !this.url) {
|
||||
this.url = url;
|
||||
}
|
||||
if(this.urlMatches(url)) {
|
||||
if(this.drillDown === true || this.urlMatches(url)) {
|
||||
layers.push(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return layers;
|
||||
},
|
||||
|
||||
@@ -304,6 +317,78 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
return matches;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: buildWMSOptions
|
||||
* Build an object with the relevant WMS options for the GetFeatureInfo request
|
||||
*
|
||||
* Parameters:
|
||||
* url - {String} The url to be used for sending the request
|
||||
* layers - {Array(<OpenLayers.Layer.WMS)} An array of layers
|
||||
* clickPosition - {<OpenLayers.Pixel>} The position on the map where the mouse
|
||||
* event occurred.
|
||||
* format - {String} The format from the corresponding GetMap request
|
||||
*/
|
||||
buildWMSOptions: function(url, layers, clickPosition, format) {
|
||||
var layerNames = [], styleNames = [];
|
||||
for (var i = 0, len = layers.length; i < len; i++) {
|
||||
layerNames = layerNames.concat(layers[i].params.LAYERS);
|
||||
styleNames = styleNames.concat(this.getStyleNames(layers[i]));
|
||||
}
|
||||
return {
|
||||
url: url,
|
||||
params: OpenLayers.Util.applyDefaults({
|
||||
service: "WMS",
|
||||
version: "1.1.0",
|
||||
request: "GetFeatureInfo",
|
||||
layers: layerNames,
|
||||
query_layers: layerNames,
|
||||
styles: styleNames,
|
||||
bbox: this.map.getExtent().toBBOX(),
|
||||
srs: this.map.getProjection(),
|
||||
feature_count: this.maxFeatures,
|
||||
x: clickPosition.x,
|
||||
y: clickPosition.y,
|
||||
height: this.map.getSize().h,
|
||||
width: this.map.getSize().w,
|
||||
format: format,
|
||||
info_format: this.infoFormat
|
||||
}, this.vendorParams),
|
||||
callback: function(request) {
|
||||
this.handleResponse(clickPosition, request);
|
||||
},
|
||||
scope: this
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getStyleNames
|
||||
* Gets the STYLES parameter for the layer. Make sure the STYLES parameter
|
||||
* matches the LAYERS parameter
|
||||
*
|
||||
* Parameters:
|
||||
* layer - {<OpenLayers.Layer.WMS>}
|
||||
*
|
||||
* Returns:
|
||||
* {Array(String)} The STYLES parameter
|
||||
*/
|
||||
getStyleNames: function(layer) {
|
||||
// in the event of a WMS layer bundling multiple layers but not
|
||||
// specifying styles,we need the same number of commas to specify
|
||||
// the default style for each of the layers. We can't just leave it
|
||||
// blank as we may be including other layers that do specify styles.
|
||||
var styleNames;
|
||||
if (layer.params.STYLES) {
|
||||
styleNames = layer.params.STYLES;
|
||||
} else {
|
||||
if (layer.params.LAYERS instanceof Array) {
|
||||
styleNames = new Array(layer.params.LAYERS.length);
|
||||
} else { // Assume it's a String
|
||||
styleNames = layer.params.LAYERS.replace(/[^,]/g, "");
|
||||
}
|
||||
}
|
||||
return styleNames;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: request
|
||||
* Sends a GetFeatureInfo request to the WMS
|
||||
@@ -317,65 +402,70 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
* - *hover* {Boolean} true if we do the request for the hover handler
|
||||
*/
|
||||
request: function(clickPosition, options) {
|
||||
options = options || {};
|
||||
var layerNames = [];
|
||||
var styleNames = [];
|
||||
|
||||
var layers = this.findLayers();
|
||||
if(layers.length > 0) {
|
||||
|
||||
for (var i = 0, len = layers.length; i < len; i++) {
|
||||
layerNames = layerNames.concat(layers[i].params.LAYERS);
|
||||
// in the event of a WMS layer bundling multiple layers but not
|
||||
// specifying styles,we need the same number of commas to specify
|
||||
// the default style for each of the layers. We can't just leave it
|
||||
// blank as we may be including other layers that do specify styles.
|
||||
if (layers[i].params.STYLES) {
|
||||
styleNames = styleNames.concat(layers[i].params.STYLES);
|
||||
} else {
|
||||
if (layers[i].params.LAYERS instanceof Array) {
|
||||
styleNames = styleNames.concat(new Array(layers[i].params.LAYERS.length));
|
||||
} else { // Assume it's a String
|
||||
styleNames = styleNames.concat(layers[i].params.LAYERS.replace(/[^,]/g, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var wmsOptions = {
|
||||
url: this.url,
|
||||
params: OpenLayers.Util.applyDefaults({
|
||||
service: "WMS",
|
||||
version: "1.1.0",
|
||||
request: "GetFeatureInfo",
|
||||
layers: layerNames,
|
||||
query_layers: layerNames,
|
||||
styles: styleNames,
|
||||
bbox: this.map.getExtent().toBBOX(),
|
||||
srs: this.map.getProjection(),
|
||||
feature_count: this.maxFeatures,
|
||||
x: clickPosition.x,
|
||||
y: clickPosition.y,
|
||||
height: this.map.getSize().h,
|
||||
width: this.map.getSize().w,
|
||||
format: layers[0].params.FORMAT,
|
||||
info_format: this.infoFormat
|
||||
}, this.vendorParams),
|
||||
callback: function(request) {
|
||||
this.handleResponse(clickPosition, request);
|
||||
},
|
||||
scope: this
|
||||
};
|
||||
|
||||
if(layers.length == 0) {
|
||||
// Reset the cursor.
|
||||
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
||||
return;
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
if(this.drillDown === false) {
|
||||
var wmsOptions = this.buildWMSOptions(this.url, layers,
|
||||
clickPosition, layers[0].params.FORMAT);
|
||||
var response = OpenLayers.Request.GET(wmsOptions);
|
||||
|
||||
if (options.hover === true) {
|
||||
this.hoverRequest = response.priv;
|
||||
}
|
||||
} else {
|
||||
// Reset the cursor.
|
||||
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
||||
this._requestCount = 0;
|
||||
this._numRequests = 0;
|
||||
this.features = [];
|
||||
// group according to service url to combine requests
|
||||
var services = {}, url;
|
||||
for(var i=0, len=layers.length; i<len; i++) {
|
||||
var layer = layers[i];
|
||||
var service, found = false;
|
||||
url = layer.url instanceof Array ? layer.url[0] : layer.url;
|
||||
if(url in services) {
|
||||
services[url].push(layer);
|
||||
} else {
|
||||
this._numRequests++;
|
||||
services[url] = [layer]
|
||||
}
|
||||
}
|
||||
var layers;
|
||||
for (var url in services) {
|
||||
layers = services[url];
|
||||
var wmsOptions = this.buildWMSOptions(url, layers,
|
||||
clickPosition, layers[0].params.FORMAT);
|
||||
OpenLayers.Request.GET(wmsOptions);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: triggerGetFeatureInfo
|
||||
* Trigger the getfeatureinfo event when all is done
|
||||
*
|
||||
* Parameters:
|
||||
* request - {XMLHttpRequest} The request object
|
||||
* xy - {<OpenLayers.Pixel>} The position on the map where the
|
||||
* mouse event occurred.
|
||||
* features - {Array(<OpenLayers.Feature.Vector>)}
|
||||
*/
|
||||
triggerGetFeatureInfo: function(request, xy, features) {
|
||||
this.events.triggerEvent("getfeatureinfo", {
|
||||
text: request.responseText,
|
||||
features: features,
|
||||
request: request,
|
||||
xy: xy
|
||||
});
|
||||
|
||||
// Reset the cursor.
|
||||
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: handleResponse
|
||||
@@ -393,16 +483,18 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
||||
doc = request.responseText;
|
||||
}
|
||||
var features = this.format.read(doc);
|
||||
|
||||
this.events.triggerEvent("getfeatureinfo", {
|
||||
text: request.responseText,
|
||||
features: features,
|
||||
request: request,
|
||||
xy: xy
|
||||
});
|
||||
|
||||
// Reset the cursor.
|
||||
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
||||
if (this.drillDown === false) {
|
||||
this.triggerGetFeatureInfo(request, xy, features);
|
||||
} else {
|
||||
this._requestCount++;
|
||||
this._features = (this._features || []).concat(features);
|
||||
if (this._requestCount === this._numRequests) {
|
||||
this.triggerGetFeatureInfo(request, xy, this._features.concat());
|
||||
delete this._features;
|
||||
delete this._requestCount;
|
||||
delete this._numRequests;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user