Geocode and then do identify task - popup

949
7
04-14-2012 11:34 AM
ChristopherPollard
Occasional Contributor
I have a project with a simple 'onclick' execute identify task taken/modified from this sample:
http://help.arcgis.com/en/webapi/javascript/arcgis/demos/find/find_popup.html

What I want to do now is have that same function happen after a user enters in an address using the locator sample:
http://help.arcgis.com/en/webapi/javascript/arcgis/demos/locator/locator_address.html.

Do I need to create a separate identify function that works with the geometry of the results from the locator task?

or can a get that execute identify task to fire after the geocode results get added to the map as an event?

dojo.connect(map,'onClick',executeIdentifyTask);
// something like this ? ? ?
dojo.connect(map,"geocode results have been added to the map", executeIdentifyTask);
// or would i need to look for the geocode graphic (geo)?
dojo.connect(graphic,'onGraphicAdd',executeIdentifyTask);

Any help/direction would be appreciated.
My application can be found here:
http://www.dvrpc.org/webmaps/ci2/
Thanks.....

Full source code is here:
http://www.dvrpc.org/webmaps/ci2/js/script.js

Here's my locator code:
 //Locator
 function locate() {
        map.graphics.clear();
        var address = {"SingleLine":dojo.byId("address").value};
        locator.outSpatialReference= map.spatialReference;
        locator.addressToLocations(address,["Loc_name"]);
      }

      function showResults(candidates) {
        var candidate;
      var symbol = new esri.symbol.SimpleMarkerSymbol();
        var infoTemplate = new esri.InfoTemplate("Location", "Address: ${address}");
      //  var infoTemplate = new esri.InfoTemplate("Location", "Address: ${address}<br />Score: ${score}<br />Source locator: ${locatorName}");
     symbol.setStyle(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE);
        symbol.setSize (8);
        symbol.setColor(new dojo.Color([153,0,51,0.75]));

        var geom;
        
        dojo.every(candidates,function(candidate){
          console.log(candidate.score);
          if (candidate.score > 80) {
            console.log(candidate.location);
      var attributes = { address: candidate.address};   
          //  var attributes = { address: candidate.address, score:candidate.score, locatorName:candidate.attributes.Loc_name };   
            geom = candidate.location;
            var graphic = new esri.Graphic(geom, symbol, attributes, infoTemplate);
            //add a graphic to the map at the geocoded location
            map.graphics.add(graphic);
            //add a text symbol to the map listing the location of the matched address.
            var displayText = candidate.address;
            var font = new esri.symbol.Font("16pt",esri.symbol.Font.STYLE_NORMAL, esri.symbol.Font.VARIANT_NORMAL,esri.symbol.Font.WEIGHT_BOLD,"Helvetica");
           
            var textSymbol = new esri.symbol.TextSymbol(displayText,font,new dojo.Color("#666633"));
            textSymbol.setOffset(0,8);
       //     map.graphics.add(new esri.Graphic(geom, textSymbol));
            return false; //break out of loop after one candidate with score greater  than 80 is found.
          }
        });
        if(geom !== undefined){
          map.centerAndZoom(geom,14); 
        }
      }   
0 Kudos
7 Replies
derekswingley1
Frequent Contributor
When you have a result from your locator, take the geometry (an esri.geometry.Point) and set it to identifyParams.geometry. Then call identifyTask.execute(identifyParams). Basically, you take the geometry from the locator task instead of a map click and use it in your identify operation. No need to listen to any events�?? update your identifyParams and execute your identify.
0 Kudos
ChristopherPollard
Occasional Contributor
Derek,
Thanks for the reply. I have spent some time trying to get it to work properly and I'm getting it to run the identify but it seems to not be passing or using the location results?
I added my code to the end of the showResults function...Is that the right location?
if(geom !== undefined){
    map.centerAndZoom(geom,14);  
      
var sr = new esri.SpatialReference(102100); 
var geom = new esri.geometry.Point;
identifyParams.spatialReference = sr; 
 identifyParams.geometry = geom;  
 identifyTask.execute(identifyParams);
 executeIdentifyTask(geom);


Do I need to modify my executeIdentifyTask to listen for both an evtMap.point (from the onClick) as well as a the esri.geometry.Point (from the locator results) ?

function executeIdentifyTask(evt) {  
      if (visible.length === 1 && visible[0] == -1){
                    map.infoWindow.clearFeatures();
                  map.infoWindow.show(evt.mapPoint);
                } else {
                    identifyParams.geometry = evt.mapPoint;
                    identifyParams.mapExtent = map.extent;


I'm not an expert coder but have been slowly learing on my own over the past few months from some of your samples as well as a few other users on this forum.....Thanks for all your help and insight.
0 Kudos
TracySchloss
Frequent Contributor
I am trying to do about the same thing.  I want the user to either be able to click OR to enter an address and re-use my identifyTask.  This is mostly working.  If I use a map click, it returns just the polygons I would expect.

When I pass the executeidentifytask function the geocoded point, it seems to be using too high of a tolerance on the identify parameters.  It returns the polygons from the identify like I'd expect, but also several adjacent polygons to it. 

It seems like maybe because I'm zoomed out when I enter an address, that is still the map extent and tolerance that identify is using.  I am zooming into the geocoded point and I would expect the identifyparameters to use this closer map extent, but maybe that's not what is happening.  I think I might need to add something with a mapPoint/screenPoint conversion.

function mapReady(map){
          //identify task is the same layer as districtLayer added above
        identifyTask = new esri.tasks.IdentifyTask("http://ogitest.oa.mo.gov/ArcGIS/rest/services/legisDistrict/MapServer");
        identifyParams = new esri.tasks.IdentifyParameters();
        identifyParams.tolerance = 3; //
        identifyParams.returnGeometry = true;
        identifyParams.layerIds = [0,1,2];
        identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
        identifyParams.spatialReference = spatialReference;
       
        identifyParams.width = map.width;
        identifyParams.height = map.height;
       
        dojo.connect(map, "onClick", executeIdentifyTask);
       
        //resize the map when the browser resizes
        dojo.connect(dijit.byId('map'), 'resize', map, map.resize);
        dojo.connect(map.infoWindow, "onHide", function() {map.graphics.clear();});
    }
  
      
   function executeIdentifyTask(evt) {
   
      identifyParams.mapExtent = map.extent;
      identifyParams.geometry = evt.mapPoint;
    
if (identifyLocator) { // geometry is coming from address function
           identifyParams.geometry = evt;       
       }

      var deferred = identifyTask.execute(identifyParams);        
   //identify runs from geocoded point and not just click       

        deferred.addCallback(function(response) {     
          // response is an array of identify result objects    
          // Let's return an array of features.
          return dojo.map(response, function(result) {
            var feature = result.feature;
            feature.attributes.layerName = result.layerName;
            feature.setInfoTemplate(plainTemplate);

            identifyLocator = false;
            return feature;
           
          });
        });

        // InfoWindow expects an array of features from each deferred
        // object that you pass. If the response from the task execution 
        // above is not an array of features, then you need to add a callback
        // like the one above to post-process the response and return an
        // array of features.
        map.infoWindow.setFeatures([ deferred ]);
        map.infoWindow.show(evt.mapPoint);

   
      }

function locate() {
            map.graphics.clear();
            var address = {"SingleLine":dojo.byId("txtAddress").value};
           
            locator.outSpatialReference= map.spatialReference;
            var options = {
              address:address,
              outFields:["Loc_name"]
            };
            locator.addressToLocations(options);
      }

function showResults(candidates) {
            var candidate;
            var symbol = new esri.symbol.SimpleMarkerSymbol();
            var addressTemplate = new esri.InfoTemplate("Location", "Address: ${address}<br />");    
            symbol.setStyle(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE);
            symbol.setColor(new dojo.Color([255,0,0,0.75]));     
          
                dojo.every(candidates,function(candidate){
                  console.log(candidate.score);
                  if (candidate.score > 80) {
                    console.log(candidate.location);
                    var attributes = { address: candidate.address, score:candidate.score, pt:candidate.location };   
                    geometryPt = candidate.location;
                    var graphic = new esri.Graphic(geometryPt, symbol, attributes, addressTemplate);
                    //add a graphic to the map at the geocoded location
                    map.graphics.add(graphic);
                    //add a text symbol to the map listing the location of the matched address.
                    var displayText = candidate.address;   
                    map.infoWindow.show(geometryPt);
                 // map.infoWindow.resize(200,100);
                  map.infoWindow.setTitle("Address");
                  map.infoWindow.setContent(displayText);
                  //
                  identifyLocator = true;
                 executeIdentifyTask(geometryPt);
                 console.log("submitting address to executeIdentifyTask");
                  //
                  
                    return false; //break out of loop after one candidate with score greater  than 80 is found.
                   }        
                });
            if(geometryPt !== undefined){
                var containsCountyPosition = (dojo.byId("txtAddress").value.toLowerCase().indexOf(" county"));          
                      if (containsCountyPosition > 0) {
                      map.centerAndZoom(geometryPt,10);
                    } else {
                         map.centerAndZoom(geometryPt,12);
                    }
            }      
      }
0 Kudos
TracySchloss
Frequent Contributor
Just a quick update on this to push this up in the thread list again.  I don't know if it is more proper to say this is tied to the map extent or the LODs, but the current scale is definitely a factor.  I have tried to modify my code to zoom in first and then do the identify, but that hasn't completely taken care of the problem.  Maybe a listener on the extent change that only fires the identify after it zooms in?  Maybe also setting the LOD to something close long enough to do the identify and then zoom back out again?

Since I am using this to identify the new legislative boundaries, it will have a lot of eyes on it.  Right now, if you are zoomed out and enter an address in an urban area (where the districts are smaller) it returns more than one district.  That might be acceptable if the point was right on the boundary line, but it is not that close.

http://ogi.oa.mo.gov/LEGIS/LegislativeDistrict/district.html

Sample address to try:  111 e 11th, kansas city, mo
0 Kudos
TracySchloss
Frequent Contributor
Reading the API reference for extent, I saw a method expand that said it would expand the map extent by the factor given.  Since I didn't see a corresponding method for "contract" I took a chance and put in a number less than 1.  In the documentation for IdentifyParameters it states:
The values for mapExtent, height, width, and dpi are used to determine the current map scale. Once the scale is known, the map service can exclude layers based on their scale dependency settings. The map service is not performing a spatial intersection based on the provided extent. These properties are also used to calculate the search distance on the map based on the tolerance in screen pixels.


I hoped that meant that changing my map extent would also influence this tolerance.
In the top of my IdentifyTask function, the line formerly
     
identifyParams.mapExtent = map.extent;

became    

identifyParams.mapExtent = map.extent.expand(0.1); 


I don't know if this will satisfy all situations, but all my test addresses, which were originally returning multiple features with the identify now just return one!  I think it's fixed!
0 Kudos
BrianO_keefe
Occasional Contributor III
Have you figured out a solution for this?
0 Kudos
TracySchloss
Frequent Contributor
There were multiple people participating in this thread.  The sample code I posted has been working for me.  Since I wasn't the person who originally asked the question, I can't mark any particular response as the correct answer.
0 Kudos