popup anchor - geocode executing a selectFeatures vs. map click

3581
5
Jump to solution
06-09-2015 08:43 AM
TracySchloss
Frequent Contributor

I need to do a selectFeatures on a featureLayer based on a geocoded point.  I also want them to be able to get information when they click around on the map, so I have a infoTemplate set on the featureLayer.

If the user enters an address, the anchor to the popup appears where I expect, tied to the geocoded symbol.  If the user then clicks around on the map and then goes back to entering an address, the anchor to the popup ends up set to the last map click, rather than the geocoded location.

What am I doing wrong?

Here are my definitions:

     var popup = new Popup({
          markerSymbol: new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 22, 
          new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 255, 0]), 2), 
          new Color([255, 255, 0, 0.5])),
          fillSymbol: highlightFillSymbol}, domConstruct.create("div"));

     var infoTemplate = new InfoTemplate("Poverty Status");
      infoTemplate.setContent(setInfoContent);

      var featureLayer = new FeatureLayer(featureLayerUrl, { mode: FeatureLayer.MODE_ONDEMAND, outFields: ['*'],
           infoTemplate: infoTemplate,
           opacity: 0.6
        });

  

Here are the relevant functions:

  function setInfoContent(graphic){
    var per = formatPercentage(graphic.attributes.pov_perc);
    return "Percentage Poverty: " + per;
  }
  function showLocation(evt){
      map.graphics.clear();
      var startPoint = evt.result.feature.geometry;
      addr = evt.result.name;
          map.centerAndZoom(startPoint, 13);
          var graphic = new Graphic(startPoint, geoSymbol);
          map.graphics.add(graphic);
           popup.show(startPoint);
          var query = new Query();
          query.geometry = startPoint;
          query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
          featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(results){
            var per = formatPercentage(results[0].attributes.pov_perc);
            popup.setContent(addr + "</br> Percentage Poverty: " + per);
            dom.byId('povStatus').innerHTML = "Census tract is eligible, with a poverty percentage of " + per;
          });
  }

Here is a link:Poverty Tract Search 

Suggested input address: 301 W High St, Jefferson City, MO

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  The animate error I have seen before and has to do with trying to display the popup when the map is not done zooming. Try adding the 'dojo/_base/lang' require to your page and then update the showLocation function to this:

      //functions for geocoding
      function showLocation(evt) {
        popup.hide();
        popup.clearFeatures();
        featureLayer.clearSelection();
        var per;
        var startPoint = evt.result.feature.geometry;
        addr = evt.result.name;
        var graphic = new Graphic(startPoint, geoSymbol);
        map.graphics.add(graphic);

        map.centerAndZoom(startPoint, 13).then(lang.hitch(this, function(){
          var query = new Query();
          query.geometry = startPoint;
          featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function (results) {
            per = formatPercentage(results[0].attributes.pov_perc);
            popup.setContent(addr + "</br> Percentage Poverty: " + per);
            map.infoWindow.show(startPoint);
            dom.byId('povStatus').innerHTML = "Census tract is eligible, with a poverty percentage of " + per;
          });
        }));
      }

View solution in original post

0 Kudos
5 Replies
YousefQuran
Occasional Contributor

Hi,


Error
: index.html:223 Uncaught SyntaxError: missing ) after argument list

Anyways, this may help you.

Re: swapping map.on click events for measurement tool vs info

Ken BujaLevel 6

Take a look at dojo/on and its pausable method. This allows you to pause and resume the event listeners without needing to remove them and add them back in.

Regards,
Yusuf

0 Kudos
TracySchloss
Frequent Contributor

You just happen to look at it when I had moved on to adding some print functionality.  I took that part out again.  That wasn't it.

As far as looking at making one of my events pausable, I'm not sure what event I'm pausing or when.   I had a similar problem with identify and measuring as well and fixed it using pausable with  dojo/on.   In this case I'm not sure what I'm pausing.  I don't have a map click event defined.  

The problem I'm seeing is random.  It will be fine for two or three times, but then it will decide not to work again.  I'm occasionally getting on onAnimate error, which I tried to look up.  The other postings  for that didn't seems to relate too much to my problem.

Maybe in true production people will never randomly quickly enter a bunch of addresses and click around a lot.  But in test, that's always what people do.  Once it starts happening, it continues and will only geocode properly again if you enter a different address.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  The animate error I have seen before and has to do with trying to display the popup when the map is not done zooming. Try adding the 'dojo/_base/lang' require to your page and then update the showLocation function to this:

      //functions for geocoding
      function showLocation(evt) {
        popup.hide();
        popup.clearFeatures();
        featureLayer.clearSelection();
        var per;
        var startPoint = evt.result.feature.geometry;
        addr = evt.result.name;
        var graphic = new Graphic(startPoint, geoSymbol);
        map.graphics.add(graphic);

        map.centerAndZoom(startPoint, 13).then(lang.hitch(this, function(){
          var query = new Query();
          query.geometry = startPoint;
          featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function (results) {
            per = formatPercentage(results[0].attributes.pov_perc);
            popup.setContent(addr + "</br> Percentage Poverty: " + per);
            map.infoWindow.show(startPoint);
            dom.byId('povStatus').innerHTML = "Census tract is eligible, with a poverty percentage of " + per;
          });
        }));
      }
0 Kudos
TracySchloss
Frequent Contributor

That seems to have done the trick.  Since I defined the map as a bootstrapMap, one of the things it seems to try to do is pan to keep the info tag completely on the display.  That's nice, but it does mean there is more panning that's going on then a typical esri/map.

I did a bunch of random clicking and address entering and no matter how quickly I went, once I geocoded the tag was properly anchored to the flag. 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  Once I commented out your printing stuff and cleaned up the parentheses issue I was able to get your app running and I did not see the issue that is the main point of your question (unless I am just not understanding it).

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="Missouri Department of Economic Development - Interactive map used to search for tracts with higher poverty percentages based on an input address">
  <meta name="author" content="Missouri Office of Geospatial Information">

  <title>Poverty Tract Search</title>
  <link type="text/css" rel="stylesheet" href="https://community.esri.com//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="https://community.esri.com//js.arcgis.com/3.13/esri/css/esri.css">
  <link rel="stylesheet" type="text/css" href="https://community.esri.com//esri.github.io/bootstrap-map-js/dist/css/bootstrapmap.min.css">
  <link type="text/css" rel="stylesheet" href="css/app.css">
</head>

<body class="claro">
  <script type="text/javascript">
    var djConfig = {
      parseOnLoad: false,
      async: true,
      packages: [{
        name: 'dojo-bootstrap',
        location: '//rawgit.com/xsokev/Dojo-Bootstrap/master'
      }, {
        name: 'bootstrap-map-js',
        location: '//esri.github.io/bootstrap-map-js/src/'
      }]
    };
  </script>
  <script type="text/javascript" src="//js.arcgis.com/3.13compact"></script>
  <script type="text/javascript">
    var pathName = "https://ogitest.oa.mo.gov";
    var currentExtent, grid, addr;
    var providerList = [];
    var printServiceUrl = "/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";

    require(['dojo/parser', 'dojo/query', 'dojo/dom', 'dojo/dom-class', 'dojo/dom-style',
  'dojo/dom-attr', 'dojo/dom-construct', 'dojo/on', 'dijit/registry', 'dojo/_base/array',
  'dojo/string', 'esri/SpatialReference', 'esri/geometry/Extent', 'esri/layers/FeatureLayer',
  'esri/InfoTemplate', "esri/dijit/Popup", 'esri/graphic', 'esri/dijit/Geocoder',
  'esri/dijit/LocateButton', 'esri/tasks/query',
  "esri/symbols/PictureMarkerSymbol", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleFillSymbol",
  "esri/symbols/SimpleLineSymbol", "esri/renderers/SimpleRenderer", "dojo/_base/Color",
  "esri/tasks/PrintTask", "esri/tasks/PrintParameters",
  'bootstrap-map-js/js/bootstrapmap', 'dojo/domReady!'],
    function (parser, query, dom, domClass, domStyle, domAttr, domConstruct, on, registry, arrayUtils,
      Memory, SpatialReference, Extent, FeatureLayer, InfoTemplate, Popup, Graphic, Geocoder, LocateButton,
      Query, PictureMarkerSymbol, SimpleMarkerSymbol, SimpleFillSymbol,
      SimpleLineSymbol, SimpleRenderer, Color, PrintTask, PrintParameters, BootstrapMap) {

      parser.parse();
      var startExtent = new Extent(-10583000, 4287025, -9979000, 4980462, new SpatialReference({
        wkid: 102100
      }));

      var spatialReference = new SpatialReference({
        wkid: 102100
      });

      var featureLayerUrl = pathName + '/arcgis/rest/services/DED/WIA/MapServer/0';

      var infoTemplate = new InfoTemplate("Poverty Status");
      infoTemplate.setContent(setInfoContent);

      var geoSymbol = new PictureMarkerSymbol('images/flag_orange.png', 32, 32);
      var highlightFillSymbol = SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
        new Color([255, 255, 20]), 3), new Color([255, 255, 0, 0.25])); //yellow outline, shaded fill

      var popup = new Popup({
        markerSymbol: new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 22,
          new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 255, 0]), 2),
          new Color([255, 255, 0, 0.5])),
        fillSymbol: highlightFillSymbol
      }, domConstruct.create("div"));

      // initialize the map, add the feature layer and initialize map widgets
      var map = BootstrapMap.create('map', {
        basemap: "streets",
        extent: startExtent,
        sliderPosition: 'upper-left',
        scrollWheelZoom: true,
        infoWindow: popup
      });
      var featureLayer = new FeatureLayer(featureLayerUrl, {
        mode: FeatureLayer.MODE_ONDEMAND,
        outFields: ['*'],
        opacity: 0.5,
        infoWindow: infoTemplate
      });

      map.addLayer(featureLayer);

      //geocoder widget
      var geocoder = new Geocoder({
        map: map,
        autoComplete: true,
        autoNavigate: false,
        symbol: geoSymbol,
        minCharacters: 8,
        arcgisGeocoder: {
          placeholder: 'Please enter address here',
          searchCounty: 'USA',
          searchExtent: startExtent
        },
        'class': 'geocoder'
      }, 'geocoder');
      geocoder.startup();

      //locate widget
      var locateButton = new LocateButton({
        map: map
      }, 'locateButton');

      //functions for defining the information tag
      function setInfoContent(graphic) {
        var addr = "test address";
        var per = formatPercentage(graphic.attributes.pov_perc);
        return addr + "</br>Percentage Poverty: " + per;
      }

      function formatPercentage(checkNumber) {
        var test1 = checkNumber.toFixed(3);
        var test2 = test1 * 100;
        var formatPct = test2.toFixed(1) + "%";
        return formatPct;
      }

      //functions for geocoding
      function showLocation(evt) {
        popup.hide();
        popup.clearFeatures();
        featureLayer.clearSelection();
        var per;
        var startPoint = evt.result.feature.geometry;
        addr = evt.result.name;
        map.centerAndZoom(startPoint, 13);
        var graphic = new Graphic(startPoint, geoSymbol);
        map.graphics.add(graphic);
        var query = new Query();
        query.geometry = startPoint;
        featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function (results) {
          per = formatPercentage(results[0].attributes.pov_perc);
          popup.setContent(addr + "</br> Percentage Poverty: " + per);
          map.infoWindow.show(startPoint);
          dom.byId('povStatus').innerHTML = "Census tract is eligible, with a poverty percentage of " + per;
        });
      }

      /*function submitPrint() {
        var deferred;
        var printTitle = dojo.byId("txtTitle").value;
        printTitle = "Poverty Status Map"
        var customElementString;

        customElementString = [
          {
            "legalDescriptionText": checkName + '\r\n ' + printLegalString + '\r\n' + printDeed + '\r\n' + printCounty
          },
          {
            "subTitleText": print_subTitle
          }
        ];
      }

      var printParams = new PrintParameters();
      printParams.map = map;
      var status = dom.byId("printStatus");
      status.innerHTML = "Generating ...";
      var e = dijit.byId("templateSelect");
      var choice = e.value;
      if (choice == "Portrait") {
        template = templates[1];
      } else {
        template = templates[0];
      }
      if (!template) {
        template = templates[0];
      }
      printParams.template = template;
      template.layoutOptions.titleText = printTitle;
      template.layoutOptions.customTextElements = customElementString;

      var printTask = new PrintTask(printServiceUrl);
      deferred = printTask.execute(printParams);
      deferred.addCallback(function (response) {
        var d = new Date();
        // console.log(d);
        var dateTime = d.getTime();
        var outputUrl = response.url + '?time=' + dateTime;
        status.innerHTML = "";

        var select = dijit.byId("templateSelect");
        var selectOptions = select.getOptions();
        select.set("value", "Choose Print Format");
        printTry = 0;
        window.open(outputUrl, "_blank");
      });

      deferred.addErrback(function (error) {
        printTry = printTry + 1;
        console.log("Print Task Error = " + error);
        if (printTry == 1) {
          submitPrint();
        } else {
          status.innerHTML = "Error generating printout, try again";
        }
      });*/
    // })
    // event listeners
    geocoder.on("select", showLocation);

    geocoder.on("clear", function (evt) {
      map.graphics.clear();
      map.infoWindow.hide();
      dom.byId('povStatus').innerHTML = "Enter an Address to determine poverty status.";
    });

    on(popup, "hide", function (evt) {
      dom.byId('povStatus').innerHTML = "Enter an Address to determine poverty status.";
      addr = "";
    });

    featureLayer.on('click', function (evt) {
      var per = formatPercentage(evt.graphic.attributes.pov_perc);
      addr = "";
      popup.setContent(" Percentage Poverty: " + per);
      //   popup.show(evt.graphic.geometry.getExtent().getCenter());
      popup.show(evt.mapPoint);
      dom.byId('povStatus').innerHTML = "Census tract is eligible, with a poverty percentage of " + per;
    });

    });
  </script>
  <!-- top nav -->
  <div class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid myheader">
      <div class="navbar-header">
        Missouri Department of Economic Development
      </div>
    </div>

    <div id="subHeader" class="subheader">
      Poverty Search
    </div>
  </div>
  <!-- map row -->
  <div class="container-fluid container-map">
    <div class="row row-map">
      <!-- the map -->

      <div class="col-xs-12 col-sm-12 col-lg-12 col col-map">
        <div id="map">
          <div id="geocoder">
          </div>
          <div id="locateButton" class="locate-button">
          </div>
        </div>
      </div>
    </div>
    <div id="povStatus" class="row footer">
      Enter an Address to determine poverty status.
    </div>
  </div>
</body>

</html>
0 Kudos