2
votes

I'm developing a web application using GeoExt, OpenLayers and having my own GeoServer to serve various maps. Still, I want to let the user add other WMS's if needed, to be able to play around with all desired layers.

Thus, my problem with the GetFeatureInfo request. Right now I have a toolbar button attached to geoext's map panel,

new GeoExt.Action({
            iconCls: "feature",
            map: map,
            toggleGroup: "tools",
            tooltip: "Feature",
            control: featureControl             
        })

its control attribute being

var featureControl = new OpenLayers.Control.WMSGetFeatureInfo({
            queryVisible: true,
            drillDown: true,
            infoFormat:"application/vnd.ogc.gml"
        });

I've also defined an event listener to do what I really want once I receive the responses, but that is not relevant here. My problem is the following:

Considering the user clicks on a point where there are 2+ visible layers and at least one of them is from a different source, OpenLayers will have to do one AJAX request per different source and, from OpenLayers own documentation,

Triggered when a GetFeatureInfo response is received. The event object has a text property with the body of the 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. 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.

so, yeah, it will obviously wont work like that right away. Having a look at the debugger I can clearly see that, giving two layers from different sources, it actually DOES the request, it's just that it doesn't wait for the first's response and jumps for the next one (obviously, being asynchronous). I've thought about doing the requests one-by-one, meaning doing the first one as stated above and once it's finished and the response saved, go for the next one. But I'm still getting used to the data structure GeoExt uses.

Is there any API (be it GeoExt or OpenLayers) option/method I'm missing? Any nice workarounds?

Thanks for reading :-)

PS: I'm sorry if I've not been clear enough, english is not my mother tongue. Let me know if something stated above was not clear enough :)

3

3 Answers

4
votes

i Hope this help to someone else, I realized that: you're rigth this control make the request in asynchronous mode, but this is ok, no problem with that, the real problem is when the control handle the request and trigger the event "getfeatureinfo" so, i modified 2 methods for this control and it works!, so to do this i declare the control first, and then in the savage mode i modified the methods here is de code:

    getInfo = new OpenLayers.Control.WMSGetFeatureInfo({ drillDown:true , queryVisible: true , maxFeatures:100 });
  //then i declare a variable that help me to handle more than 1 request.....
 getInfo.responses  = [];
 getInfo.handleResponse=function(xy, request) {        var doc = request.responseXML;
    if(!doc || !doc.documentElement) {   doc = request.responseText; }
    var features = this.format.read(doc);
    if (this.drillDown === false) {
        this.triggerGetFeatureInfo(request, xy, features);
    } else {
        this._requestCount++;
        this._features = (this._features || []).concat(features);
        if( this._numRequests > 1){
                          //if the num of RQ, (I mean more than 1 resource ), i put the Request in array, this is for maybe in a future i could be need other properties or methods from RQ, i dont know.
            this.responses.push(request);}
        else{
            this.responses = request;}
        if (this._requestCount === this._numRequests) {
            //here i change the code....
            //this.triggerGetFeatureInfo(request, xy, this._features.concat());
            this.triggerGetFeatureInfo(this.responses, xy, this._features.concat());
            delete this._features;
            delete this._requestCount;
            delete this._numRequests;
            // I Adding this when the all info is done 4 reboot
            this.responses=[];
        }
    }
}

 getInfo.triggerGetFeatureInfo= function( request , xy , features) {
//finally i added this code for get all request.responseText's
if( isArray( request ) ){
    text_rq = '';
    for(i in request ){
        text_rq += request[i].responseText;

        }
    }
else{
    text_rq = request.responseText;

    }

    this.events.triggerEvent("getfeatureinfo", {
       //text: request.responseText,
       text : text_rq,
        features: features,
        request: request,
        xy: xy
    });

    // Reset the cursor.
    OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");}

Thanks, you bring me a way for discover my problem and here is the way i solved, i hope this can help to somebody else.

1
votes

saheka's answer was almost perfect! Congratulations and thank you, I had the same problem, and with it I finally managed to solve it.

What I would change in your code:

  • isArray() does not work, change it like this: if(request instanceof Array) {...} at the first line of getInfo.triggerGetFeatureInfo()
  • to show the results in a popup this is the way:

My code:

getInfo.addPopup = function(map, text, xy) {
    if(map.popups.length > 0) {
        map.removePopup(map.popups[0]);
    }
    var popup = new OpenLayers.Popup.FramedCloud(
        "anything",
        map.getLonLatFromPixel(xy),
        null,
        text,
        null,
        true
    );
    map.addPopup(popup);
}

and in the getInfo.triggerGetFeatureInfo() function, after the last line, append:

this.addPopup(map, text_rq, xy);
0
votes

A GetFeatureInfo request is send as a JavaScript Ajax call to the external server. So, the requests are likely blocked for security reasons. You'll have to send the requests to the external servers by a proxy on your own domain.

Then, configure this proxy in openlayers by setting OpenLayers.ProxyHost to the proper path. For example:

OpenLayers.ProxyHost = "/proxy_script";

See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost for more background information.