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,
|
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
|
* APIProperty: maxFeatures
|
||||||
* {Integer} Maximum number of features to return from a WMS query. This
|
* {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
|
* response (String), a *features* property with an array of the
|
||||||
* parsed features, an *xy* property with the position of the mouse
|
* parsed features, an *xy* property with the position of the mouse
|
||||||
* click or hover event that triggered the request, and a *request*
|
* 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"],
|
EVENT_TYPES: ["beforegetfeatureinfo", "getfeatureinfo"],
|
||||||
|
|
||||||
@@ -167,7 +178,11 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hover) {
|
if(this.drillDown === true) {
|
||||||
|
this.hover = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.hover) {
|
||||||
this.handler = new OpenLayers.Handler.Hover(
|
this.handler = new OpenLayers.Handler.Hover(
|
||||||
this, {
|
this, {
|
||||||
'move': this.cancelHover,
|
'move': this.cancelHover,
|
||||||
@@ -256,9 +271,8 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
*/
|
*/
|
||||||
findLayers: function() {
|
findLayers: function() {
|
||||||
|
|
||||||
var layers = [];
|
|
||||||
|
|
||||||
var candidates = this.layers || this.map.layers;
|
var candidates = this.layers || this.map.layers;
|
||||||
|
var layers = [];
|
||||||
var layer, url;
|
var layer, url;
|
||||||
for(var i=0, len=candidates.length; i<len; ++i) {
|
for(var i=0, len=candidates.length; i<len; ++i) {
|
||||||
layer = candidates[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;
|
url = layer.url instanceof Array ? layer.url[0] : layer.url;
|
||||||
// if the control was not configured with a url, set it
|
// if the control was not configured with a url, set it
|
||||||
// to the first layer url
|
// to the first layer url
|
||||||
if(!this.url) {
|
if(this.drillDown === false && !this.url) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
if(this.urlMatches(url)) {
|
if(this.drillDown === true || this.urlMatches(url)) {
|
||||||
layers.push(layer);
|
layers.push(layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return layers;
|
return layers;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -304,6 +317,78 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
return matches;
|
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
|
* Method: request
|
||||||
* Sends a GetFeatureInfo request to the WMS
|
* Sends a GetFeatureInfo request to the WMS
|
||||||
@@ -317,66 +402,71 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
* - *hover* {Boolean} true if we do the request for the hover handler
|
* - *hover* {Boolean} true if we do the request for the hover handler
|
||||||
*/
|
*/
|
||||||
request: function(clickPosition, options) {
|
request: function(clickPosition, options) {
|
||||||
options = options || {};
|
|
||||||
var layerNames = [];
|
|
||||||
var styleNames = [];
|
|
||||||
|
|
||||||
var layers = this.findLayers();
|
var layers = this.findLayers();
|
||||||
if(layers.length > 0) {
|
if(layers.length == 0) {
|
||||||
|
// Reset the cursor.
|
||||||
for (var i = 0, len = layers.length; i < len; i++) {
|
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
||||||
layerNames = layerNames.concat(layers[i].params.LAYERS);
|
return;
|
||||||
// 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
|
|
||||||
};
|
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
if(this.drillDown === false) {
|
||||||
|
var wmsOptions = this.buildWMSOptions(this.url, layers,
|
||||||
|
clickPosition, layers[0].params.FORMAT);
|
||||||
var response = OpenLayers.Request.GET(wmsOptions);
|
var response = OpenLayers.Request.GET(wmsOptions);
|
||||||
|
|
||||||
if (options.hover === true) {
|
if (options.hover === true) {
|
||||||
this.hoverRequest = response.priv;
|
this.hoverRequest = response.priv;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Reset the cursor.
|
this._requestCount = 0;
|
||||||
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
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
|
* Method: handleResponse
|
||||||
* Handler for the GetFeatureInfo response.
|
* Handler for the GetFeatureInfo response.
|
||||||
@@ -393,16 +483,18 @@ OpenLayers.Control.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
doc = request.responseText;
|
doc = request.responseText;
|
||||||
}
|
}
|
||||||
var features = this.format.read(doc);
|
var features = this.format.read(doc);
|
||||||
|
if (this.drillDown === false) {
|
||||||
this.events.triggerEvent("getfeatureinfo", {
|
this.triggerGetFeatureInfo(request, xy, features);
|
||||||
text: request.responseText,
|
} else {
|
||||||
features: features,
|
this._requestCount++;
|
||||||
request: request,
|
this._features = (this._features || []).concat(features);
|
||||||
xy: xy
|
if (this._requestCount === this._numRequests) {
|
||||||
});
|
this.triggerGetFeatureInfo(request, xy, this._features.concat());
|
||||||
|
delete this._features;
|
||||||
// Reset the cursor.
|
delete this._requestCount;
|
||||||
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
|
delete this._numRequests;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -307,6 +307,51 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_drillDown(t) {
|
||||||
|
t.plan(4);
|
||||||
|
var map = new OpenLayers.Map("map", {
|
||||||
|
getExtent: function() {return(new OpenLayers.Bounds(-180,-90,180,90));}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var a = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", {
|
||||||
|
layers: "a"
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = new OpenLayers.Layer.WMS("dummy","http://localhost/wms", {
|
||||||
|
layers: "c"
|
||||||
|
});
|
||||||
|
|
||||||
|
var c = new OpenLayers.Layer.WMS("dummy","http://myhost/wms", {
|
||||||
|
layers: "x"
|
||||||
|
});
|
||||||
|
|
||||||
|
map.addLayers([a, b, c]);
|
||||||
|
|
||||||
|
var click = new OpenLayers.Control.WMSGetFeatureInfo({
|
||||||
|
drillDown: true
|
||||||
|
});
|
||||||
|
|
||||||
|
map.addControl(click);
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
var _request = OpenLayers.Request.GET;
|
||||||
|
OpenLayers.Request.GET = function(options) {
|
||||||
|
count++;
|
||||||
|
if (count == 1) {
|
||||||
|
t.eq(options.params["query_layers"].join(","), "a,c", "Layers should be grouped by service url");
|
||||||
|
t.eq(options.url, "http://localhost/wms", "Correct url used for first request");
|
||||||
|
} else if (count == 2) {
|
||||||
|
t.eq(options.url, "http://myhost/wms", "Correct url used for second request");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
click.activate();
|
||||||
|
click.getInfoForClick({xy: {x: 50, y: 50}});
|
||||||
|
OpenLayers.Request.GET = _request;
|
||||||
|
t.eq(count, 2, "We expect 2 requests to go off");
|
||||||
|
map.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Reference in New Issue
Block a user