[Commits] r615 - apps/opengeo/geoexplorer/trunk/lib

commits at geoext.org commits at geoext.org
Wed May 6 21:44:23 CEST 2009


Author: dwins
Date: 2009-05-06 21:44:23 +0200 (Wed, 06 May 2009)
New Revision: 615

Removed:
   apps/opengeo/geoexplorer/trunk/lib/MassGetFeatureInfo.js
Modified:
   apps/opengeo/geoexplorer/trunk/lib/GeoExplorer.js
Log:
Reimplement per-layer getfeature requests without modifying the OpenLayers control


Modified: apps/opengeo/geoexplorer/trunk/lib/GeoExplorer.js
===================================================================
--- apps/opengeo/geoexplorer/trunk/lib/GeoExplorer.js	2009-05-06 19:33:28 UTC (rev 614)
+++ apps/opengeo/geoexplorer/trunk/lib/GeoExplorer.js	2009-05-06 19:44:23 UTC (rev 615)
@@ -70,6 +70,13 @@
     capGrid: null,
 
     /**
+     * Property: popupCache
+     * {Object} An object containing references to visible popups so that 
+     *     we can insert responses from multiple requests.
+     */
+    popupCache: {},
+
+    /**
      * Method: load
      * Called at the end of construction.  This initiates the sequence that
      *     prepares the application for use.
@@ -578,47 +585,62 @@
             }
         });
         this.map.addControl(historyControl);
+
+        var toolGroup = "toolGroup";
         
         // create a get feature info control
-        var infoControl = new MassGetFeatureInfo({
-            url: this.initialConfig.ows,
-            queryVisible: true,
-            singleRequest: false,
-            eventListeners: {
-                getfeatureinfo:  this.displayPopup,
-                scope: this
+        var info = {controls: []};
+        var infoButton = new Ext.Button({
+            tooltip: "Get Feature Info",
+            iconCls: "icon-getfeatureinfo",
+            toggleGroup: toolGroup,
+            enableToggle: true,
+            allowDepress: false,
+            toggleHandler: function(button, pressed) {
+                for (var i = 0, len = info.controls.length; i < len; i++){
+                    if(pressed) {
+                        info.controls[i].activate();
+                    } else {
+                        info.controls[i].deactivate();
+                    }
+                }
             }
-        });
+        })
 
         var updateInfo = function() {
             var queryableLayers = this.mapPanel.layers.queryBy(function(x){
-                return x.data.queryable;
+                return x.get("queryable");
             });
-            var layerObjects = [];
-            queryableLayers.each(function(x){layerObjects.push(x.data.layer);});
 
-            if (queryableLayers.length > 0) {
-                infoControl.url = queryableLayers[0];
+            var map = this.mapPanel.map;
+            var gx = this;
+
+            for (var i = 0, len = info.controls.length; i < len; i++){
+                map.removeControl(info.controls[i]);
             }
 
-            infoControl.layers = layerObjects;
+            info.controls = [];
+            queryableLayers.each(function(x){
+                var control = new OpenLayers.Control.WMSGetFeatureInfo({
+                    url: x.get("layer").url,
+                    queryVisible: true,
+                    layers: [x.get("layer")],
+                    eventListeners: {
+                        getfeatureinfo: function(evt) {
+                            gx.displayPopup(evt, x.get("title"));
+                        },
+                        scope: gx 
+                    }
+                });
+                map.addControl(control);
+                info.controls.push(control);
+            });
         };
 
         this.mapPanel.layers.on("update", updateInfo, this);
         this.mapPanel.layers.on("add", updateInfo, this);
         this.mapPanel.layers.on("remove", updateInfo, this);
 
-        this.on({
-            ready: function() {
-                var record = this.capabilities.getAt(0);
-                if(record) {
-                    infoControl.layerUrls = [record.get("layer").url];
-                }
-            },
-            scope: this
-        });
-        this.map.addControl(infoControl);
-        
         // create length measure control
         var measureLength = this.createMeasureTool(
             OpenLayers.Handler.Path, 'Length'
@@ -631,7 +653,6 @@
         );
         this.map.addControl(measureArea);
 
-        var toolGroup = "toolGroup";
         var tools = [
             new Ext.Button({
                 text: "GeoExplorer",
@@ -662,20 +683,7 @@
                 },
                 scope: this
             }),
-            new Ext.Button({
-                tooltip: "Get Feature Info",
-                iconCls: "icon-getfeatureinfo",
-                toggleGroup: toolGroup,
-                enableToggle: true,
-                allowDepress: false,
-                toggleHandler: function(button, pressed) {
-                    if(pressed) {
-                        infoControl.activate();
-                    } else {
-                        infoControl.deactivate();
-                    }
-                }
-            }),
+            infoButton,
             new MapToolSplitToggle({
                 tooltip: "Measure",
                 iconCls: "icon-measure",
@@ -847,49 +855,45 @@
         return measureControl;
     },
 
-    displayPopup: function(evt){
-        var items = [];
+    displayPopup: function(evt, title){
+        var popup;
+        var popupKey = evt.xy.x + "." + evt.xy.y;
 
-        for (var i in evt.responses) {
-            var html = evt.responses[i].text;
-            if (html == '' || html.match(/<body>\s*<\/body>/)) {
-                continue;
-            }
+        if (!(popupKey in this.popupCache)) {
+            var lonlat = this.map.getLonLatFromPixel(evt.xy);
+            popup = new GeoExt.Popup({
+                title: "Feature Info",
+                lonlat: lonlat,
+                width: 250,
+                height: 300,
+                autoScroll: true,
+                listeners: {
+                    close: (function(key) {
+                        return function(panel){
+                            delete this.popupCache[key];
+                        };
+                    })(popupKey),
+                    scope: this
+                }
+            });
+            popup.addToMapPanel(this.mapPanel);
+            popup.show();
+            this.popupCache[popupKey] = popup;
+        } else {
+            popup = this.popupCache[popupKey];
+        }
 
-            items.push({
-                title: i,
+        var html = evt.text;
+        if (!(html == '' || html.match(/<body>\s*<\/body>/))) {
+            popup.add({
+                title: title,
                 html: html,
                 autoScroll: true,
                 collapsible: true
             });
         }
 
-        if (items.length == 0) {
-            return;
-        }
-
-        if (items.length == 1) {
-            items[0].collapsible = false;
-        }
-        
-        
-        var lonlat = this.map.getLonLatFromPixel(evt.xy);
-        var win = new GeoExt.Popup({
-            title: "Feature Info",
-            lonlat: lonlat,
-            width: 250,
-            height: 300,
-            autoScroll: true,
-            items: [new Ext.Panel({
-                //width: 250,
-                //height: 300,
-                //enableTabScroll: true,
-                //activeTab: 0,
-                items: items
-            })]
-        });
-        win.addToMapPanel(this.mapPanel);
-        win.show();
+        popup.doLayout();
     },
 
 

Deleted: apps/opengeo/geoexplorer/trunk/lib/MassGetFeatureInfo.js
===================================================================
--- apps/opengeo/geoexplorer/trunk/lib/MassGetFeatureInfo.js	2009-05-06 19:33:28 UTC (rev 614)
+++ apps/opengeo/geoexplorer/trunk/lib/MassGetFeatureInfo.js	2009-05-06 19:44:23 UTC (rev 615)
@@ -1,478 +0,0 @@
-
-/* Copyright (c) 2006-2008 MetaCarta, Inc., 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/Hover.js
- * @requires OpenLayers/Request.js
- */
-
-/**
- * Class: OpenLayers.Control.WMSGetFeatureInfo
- * The WMSGetFeatureInfo control uses a WMS query to get information about a point on the map.  The
- * information may be in a display-friendly format such as HTML, or a machine-friendly format such 
- * as GML, depending on the server's capabilities and the client's configuration.  This control 
- * handles click or hover events, attempts to parse the results using an OpenLayers.Format, and 
- * fires a 'getfeatureinfo' event with the click position, the raw body of the response, and an 
- * array of features if it successfully read the response.
- *
- * Inherits from:
- *  - <OpenLayers.Control>
- */
-MassGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
-    
-   /**
-     * APIProperty: hover
-     * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
-     *     Default is false.
-     */
-    hover: false,
-
-    /**
-     * APIProperty: maxFeatures
-     * {Integer} Maximum number of features to return from a WMS query. This
-     *     sets the feature_count parameter on WMS GetFeatureInfo
-     *     requests.
-     */
-    maxFeatures: 10,
-    
-    /**
-     * Property: layers
-     * {Array(<OpenLayers.Layer.WMS>)} The layers to query for feature info.
-     *     If omitted, all map WMS layers with a url that matches this <url> or
-     *     <layerUrl> will be considered.
-     */
-    layers: null,
-
-    /**
-     * Property: queryVisible
-     * {Boolean} If true, filter out hidden layers when searching the map for
-     *     layers to query.  Default is false.
-     */
-    queryVisible: false,
-
-    /**
-     * Property: singleRequest
-     * {Boolean} if true, aggregate requests to the same service into a single 
-     *    request with multiple LAYERs specified. Otherwise, issue one http 
-     *    request per layer. Default is true.
-     */
-    singleRequest: true,
-
-    /**
-     * Property: url
-     * {String} The URL of the WMS service to use.  If not provided, the url
-     *     of the first eligible layer will be used.
-     */
-    url: null,
-    
-    /**
-     * Property: layerUrls
-     * {Array(String)} Optional list of urls for layers that should be queried.
-     *     This can be used when the layer url differs from the url used for
-     *     making GetFeatureInfo requests (in the case of a layer using cached
-     *     tiles).
-     */
-    layerUrls: null,
-
-    /**
-     * Property: infoFormat
-     * {String} The mimetype to request from the server
-     */
-    infoFormat: 'text/html',
-    
-    /**
-     * Property: vendorParams
-     * {Object} Additional parameters that will be added to the request, for
-     * WMS implementations that support them. This could e.g. look like
-     * (start code)
-     * {
-     *     radius: 5
-     * }
-     * (end)
-     */
-    vendorParams: {},
-    
-    /**
-     * Property: format
-     * {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
-     *     Default is <OpenLayers.Format.WMSGetFeatureInfo>.
-     */
-    format: null,
-    
-    /**
-     * Property: formatOptions
-     * {Object} Optional properties to set on the format (if one is not provided
-     *     in the <format> property.
-     */
-    formatOptions: null,
-
-    /**
-     * APIProperty: handlerOptions
-     * {Object} Additional options for the handlers used by this control, e.g.
-     * (start code)
-     * {
-     *     "click": {delay: 100},
-     *     "hover": {delay: 300}
-     * }
-     * (end)
-     */
-    handlerOptions: null,
-    
-    /**
-     * Property: handler
-     * {Object} Reference to the <OpenLayers.Handler> for this control
-     */
-    handler: null,
-    
-    /**
-     * Property: hoverRequest
-     * {<OpenLayers.Request>} contains the currently running hover request
-     *     (if any).
-     */
-    hoverRequest: null,
-    
-    /**
-     * Constant: EVENT_TYPES
-     *
-     * Supported event types (in addition to those from <OpenLayers.Control>):
-     * getfeatureinfo - 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.
-     */
-    EVENT_TYPES: ["getfeatureinfo"],
-
-    /**
-     * Constructor: <OpenLayers.Control.WMSGetFeatureInfo>
-     *
-     * Parameters:
-     * options - {Object} 
-     */
-    initialize: function(options) {
-        // concatenate events specific to vector with those from the base
-        this.EVENT_TYPES =
-            MassGetFeatureInfo.prototype.EVENT_TYPES.concat(
-            OpenLayers.Control.prototype.EVENT_TYPES
-        );
-
-        options = options || {};
-        options.handlerOptions = options.handlerOptions || {};
-
-        OpenLayers.Control.prototype.initialize.apply(this, [options]);
-        
-        if(!this.format) {
-            this.format = new OpenLayers.Format.WMSGetFeatureInfo(
-                options.formatOptions
-            );
-        }
-
-        if (this.hover) {
-            this.handler = new OpenLayers.Handler.Hover(
-                   this, {
-                       'move': this.cancelHover,
-                       'pause': this.getInfoForHover
-                   },
-                   OpenLayers.Util.extend(this.handlerOptions.hover || {}, {
-                       'delay': 250
-                   }));
-        } else {
-            this.handler = new OpenLayers.Handler.Click(this,
-                {click: this.getInfoForClick}, this.handlerOptions.click || {});
-        }
-    },
-
-    /**
-     * Method: activate
-     * Activates the control.
-     * 
-     * Returns:
-     * {Boolean} The control was effectively activated.
-     */
-    activate: function () {
-        if (!this.active) {
-            this.handler.activate();
-        }
-        return OpenLayers.Control.prototype.activate.apply(
-            this, arguments
-        );
-    },
-
-    /**
-     * Method: deactivate
-     * Deactivates the control.
-     * 
-     * Returns:
-     * {Boolean} The control was effectively deactivated.
-     */
-    deactivate: function () {
-        return OpenLayers.Control.prototype.deactivate.apply(
-            this, arguments
-        );
-    },
-    
-    /**
-     * Method: getInfoForClick 
-     * Called on click
-     *
-     * Parameters:
-     * evt - {<OpenLayers.Event>} 
-     */
-    getInfoForClick: function(evt) {
-        // Set the cursor to "wait" to tell the user we're working on their
-        // click.
-        OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
-        this.request(evt.xy, {});
-    },
-   
-    /**
-     * Method: getInfoForHover
-     * Pause callback for the hover handler
-     *
-     * Parameters:
-     * evt - {Object}
-     */
-    getInfoForHover: function(evt) {
-        this.request(evt.xy, {hover: true});
-    },
-
-    /**
-     * Method: cancelHover
-     * Cancel callback for the hover handler
-     */
-    cancelHover: function() {
-        if (this.hoverRequest) {
-            this.hoverRequest.abort();
-            this.hoverRequest = null;
-        }
-    },
-
-    /**
-     * Method: findLayers
-     * Internal method to get the layers, independent of whether we are
-     *     inspecting the map or using a client-provided array
-     */
-    findLayers: function() {
-
-        var layers = [];
-        
-        var candidates = this.layers || this.map.layers;
-        var layer, url;
-        for(var i=0, len=candidates.length; i<len; ++i) {
-            layer = candidates[i];
-            if(layer instanceof OpenLayers.Layer.WMS &&
-               (!this.queryVisible || layer.getVisibility())) {
-                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) {
-                    this.url = url;
-                }
-                if(this.urlMatches(url)) {
-                    layers.push(layer);
-                }
-            }
-        }
-
-        return layers;
-    },
-    
-    /**
-     * Method: urlMatches
-     * Test to see if the provided url matches either the control <url> or one
-     *     of the <layerUrls>.
-     *
-     * Parameters:
-     * url - {String} The url to test.
-     *
-     * Returns:
-     * {Boolean} The provided url matches the control <url> or one of the
-     *     <layerUrls>.
-     */
-    urlMatches: function(url) {
-        var matches = OpenLayers.Util.isEquivalentUrl(this.url, url);
-        if(!matches && this.layerUrls) {
-            for(var i=0, len=this.layerUrls.length; i<len; ++i) {
-                if(OpenLayers.Util.isEquivalentUrl(this.layerUrls[i], url)) {
-                    matches = true;
-                    break;
-                }
-            }
-        }
-        return matches;
-    },
-
-    /**
-     * Method: request
-     * Sends a GetFeatureInfo request to the WMS
-     * 
-     * Parameters:
-     * clickPosition - {<OpenLayers.Pixel>} The position on the map where the
-     *     mouse event occurred.
-     * options - {Object} additional options for this method.
-     * 
-     * Valid options:
-     * - *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 baseRequestParams = OpenLayers.Util.applyDefaults({
-                    service: "WMS",
-                    version: "1.1.0",
-                    request: "GetFeatureInfo",
-                    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,
-                    info_format: this.infoFormat 
-            }, this.vendorParams);
-
-            if (this.singleRequest) {
-                var layerRequestParams = OpenLayers.Util.applyDefaults({
-                    layers: layerNames,
-                    query_layers: layerNames,
-                    styles: styleNames
-                }, baseRequestParams);
-
-                var wmsOptions = {
-                    url: this.url,
-                    params: layerRequestParams,
-                    callback: function (request) {
-                        this.handleResponse(clickPosition, request);
-                    },
-                    scope: this
-                };
-
-                var response = OpenLayers.Request.GET(wmsOptions);
-    
-                if (options.hover === true) {
-                    this.hoverRequest = response.priv;
-                }
-            } else {
-                var requestFuncs = [];
-                var results = {};
-
-                for (var i = 0, len = layerNames.length; i < len; i++) {
-                    var layerRequestParams = OpenLayers.Util.applyDefaults({
-                        layers: layerNames[i],
-                        query_layers: layerNames[i],
-                        styles: styleNames[i]
-                    }, baseRequestParams);
-
-                    requestFuncs.push((function(url, params){
-                        return (function(done) {
-                            var wmsOptions = {
-                                url: this.url,
-                                params: params,
-                                callback: function(request) {
-                                    results[params.layers] = 
-                                        this.handlePartialResponse(clickPosition, request);
-                                    done();
-                                }, 
-                                scope: this};
-
-                            OpenLayers.Request.GET(wmsOptions);
-                        });})(this.url, layerRequestParams));
-                }
-
-                Viewer.prototype.dispatch.call(this, requestFuncs, function() {
-                    OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
-                    this.events.triggerEvent('getfeatureinfo', {
-                        responses: results,
-                        xy: clickPosition
-                    });
-                });
-            }
-        } else {
-            // Reset the cursor.
-            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
-        }
-    },
-
-    handlePartialResponse: function(xy, request) {
-        var doc = request.responseXML;
-        if(!doc || !doc.documentElement) {
-            doc = request.responseText;
-        }
-
-        var features = this.format.read(doc);
-
-        return {
-            text: request.responseText,
-            features: features,
-            request: request
-        }
-    },
-    
-    /**
-     * Method: handleResponse
-     * Handler for the GetFeatureInfo response.
-     * 
-     * Parameters:
-     * xy - {<OpenLayers.Pixel>} The position on the map where the
-     *     mouse event occurred.
-     * request - {XMLHttpRequest} The request object.
-     */
-    handleResponse: function(xy, request) {
-        var doc = request.responseXML;
-        if(!doc || !doc.documentElement) {
-            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");
-    },
-   
-    /** 
-     * Method: setMap
-     * Set the map property for the control. 
-     * 
-     * Parameters:
-     * map - {<OpenLayers.Map>} 
-     */
-    setMap: function(map) {
-        this.handler.setMap(map);
-        OpenLayers.Control.prototype.setMap.apply(this, arguments);
-    },
-
-    CLASS_NAME: "MassGetFeatureInfo"
-});



More information about the Commits mailing list