[GIS] Beginner needs suggestions on map clicks and geojson

geojsongeoserveropenlayers-2postgis

I'm a beginner with programming, and javascript. I went to the FOSS4G-NA conference and was very inspired to learn more. I'm trying to learn PostGIS, and have come across a very useful tutorial for using PostGIS with Openlayers and geoserver: http://workshops.opengeo.org/postgis-spatialdbtips/

I've followed through all of the examples, but one of many things I don't understand:
The examples show how to retrieve data from the postgis database and display on the map, or show how to calculate something within a distance of the map click. What about retrieving the clicked taxlot, then using the id of that taxlot to perform other spatial queries?

For example, I'm trying to build up an example based on the concepts for the tutorial. I want the user to click a watershed (a polygon layer), and have the map return the outline of the clicked watershed, as well as highlight/send to the map any withdrawal point data contained within that watershed, and produce some summary output (such as the total number and withdrawal amounts) and place that into the iframe on the page.

My strategy would be:

  • Have one function retrieve the clicked watershed, output the selected watershed vector to the map, and return the ID of that watershed and store it as a variable.

  • That variable would then be passed to a second function where the spatial query using st_contains is performed to select all of the points within the taxlot, and then output those selected building vectors to the map.

  • A third function would perform a similar query to the second function, except output the result of a summary calculation to the iframe.

Right now I'm stuck on whether this strategy is right, as I'm a bit lost on the code to both retrieve clicked attribute data and store it as a variable, as well as display it using geojson. Clicking in my map page gets me the error that my clicked_shed variable is null, in my getWatershed function. Right now I've only created a function to retrieve the ID of the clicked watershed, and a function to display those withdrawal points within that clicked watershed.
I'm so inspired by all of this I think my first task after I understand this better will be to write some easy tutorials following on to this existing tutorial for others in my position. There can never be enough examples and tutorials in my opinion.

Can anyone provide a lowly beginner with any thoughts?

    var x = -8684372;
    var y = 4765431;
    var zoom = 10;
    var map, json_layer;

function init(){

    initMap();
    var wwms = new OpenLayers.Layer.WMS( "Opequon Sub-watersheds","/geoserver/wms?",
               {
                transparent:'true',
                layers: 'medford:subshed2',
                'format':'image/png'},
               {'reproject': true});
    var swms = new OpenLayers.Layer.WMS( "Opequon Streams",
                    "/geoserver/wms?",
               {
                transparent:'true',
                layers: 'medford:OpequonStreams',
                'format':'image/png'},
               {'reproject': true});
    map.addLayer(wwms);
    map.addLayer(swms);

    map.events.register("click", map, getWatershed);
    map.events.register("click", map, getFeatures );

    }

    function initMap() {

        // Initialize our map using Mercator as the internal units.
        // That means our bounds, center, resolution, all have to be in Mercator.
        var options = {
            projection: new OpenLayers.Projection("EPSG:900913"),
            displayProjection: new OpenLayers.Projection("EPSG:4326"),
            units: "m",
            numZoomLevels:20,
            maxResolution: 156543.0339,
            maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508,
            20037508.34),
            controls:[new OpenLayers.Control.MouseDefaults(),
                      new OpenLayers.Control.LayerSwitcher(),
                      new OpenLayers.Control.PanZoomBar()]
        };

        map = new OpenLayers.Map( 'map' , options );

        var gmap = new OpenLayers.Layer.Google(
            "Google Physical", // the default
            {type: G_PHYSICAL_MAP, 'sphericalMercator': true}
        );
        var gsat = new OpenLayers.Layer.Google(
            "Google Satellite",
            {type: G_SATELLITE_MAP, 'sphericalMercator': true}
        );
        map.addLayers([gmap, gsat]); 
        map.setCenter(new OpenLayers.LonLat(x, y), zoom);
    }

    function getWatershed(e) {
        var geojson = new OpenLayers.Format.GeoJSON();
        // Get the mercator coordinates from the viewport
        var xy = map.getLonLatFromViewPortPx(e.xy);
        // Find the watershed ID.
        var sql  = "select st_asgeojson(the_geom), id ";
            sql += "from medford.subshed2 ";
            sql += "where st_contains(the_geom,st_transform(st_setsrid(";
            sql += "st_makepoint(" + xy.lon + "," + xy.lat + ")";
            sql += ",900913),26918))";
        var config = { 
              "method":"GET",
              "url":"04-sql-to-json.jsp",
              "async":false,
              "params":{"sql":sql}
              };
        var xmlhttp = OpenLayers.Request.issue(config);
        var clicked_shed = geojson.read(xmlhttp.responseText, "FeatureCollection");
            var id = clicked_shed.attributes.id;
            getFeatures(id);
        }

    function getFeatures(id) {
        var json_url = "04-sql-to-json.jsp?sql=";
        var sql = "select st_asgeojson(st_transform(withdraw.the_geom,900913)),
            shed.id
            from medford.subshed2 shed, medford.withdrawals6_opequonUTM withdraw
            where st_contains(shed.the_geom,withdraw.the_geom)
            AND shed.id = '" + id + "'";
        json_url += escape(sql);
        if (json_layer) {
        json_layer.destroy();
            }
        jsonlayer = new OpenLayers.Layer.Vector("GeoJSON", {
                strategies: [new OpenLayers.Strategy.Fixed()],
                protocol: new OpenLayers.Protocol.HTTP({
                url: json_url,
                format: new OpenLayers.Format.GeoJSON()
                })
            });
        map.addLayer(json_layer);

    }

Best Answer

You should parse response inside success function:

OpenLayers.Request.GET({
  async: false,
  url: "./04-sql-to-json.jsp",
  params: {sql: sql},
  success: function(e){
    features = geojson.read(e.responseText, "FeatureCollection");
  }
});
id = features[0].attributes.id;