Select to view content in your preferred language

QueryTask and Zoom to Result

6967
11
02-18-2013 05:47 AM
MJWaldstein
New Contributor
Hi,

I am looking to see if anyone knows how I can have both a queryTask function and have the map zoom to the result automatically after the search button is clicked. I am stuck on how to create the zoom function, as my search works.

Below is the code i have for the search ability:

var watershed_areas = new esri.layers.ArcGISDynamicMapServiceLayer("http://54.245..................");
map.addLayers(watershed_areas);



findTask = new esri.tasks.FindTask("http://54.245...............");

   
    findParams = new esri.tasks.FindParameters();
    findParams.returnGeometry = true;
    findParams.layerIds = [0];
    findParams.searchFields = ["NWWTRSHDCD", "WTRSHDD"];


   

function execute(searchText) {
   
    findParams.searchText = searchText;
    findTask.execute(findParams, showResults);
   }
   function showResults(results) {   
    var polygonSymbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1), new dojo.Color([255, 0, 0, 1]));
    map.graphics.clear();
    var dataForGrid = [];
   
    dojo.forEach(results, function(result) {
     var graphic = result.feature;
     dataForGrid.push([result.layerName, result.foundFieldName, result.value]);
     switch (graphic.geometry.type) {
      case "point":
       graphic.setSymbol(markerSymbol);
       break;
      case "polyline":
       graphic.setSymbol(lineSymbol);
       break;
      case "polygon":
       graphic.setSymbol(polygonSymbol);
       break;
     }
     map.graphics.add(graphic);
    });
    var data = {
     items : dataForGrid
    };
    var store = new dojo.data.ItemFileReadStore({
     data : data
    });
    grid.setStore(store);
   }

If anyone could lend any assistance, i would greatly appreciate it.

Thanks,

Margaret
0 Kudos
11 Replies
JonathanKressin
Regular Contributor
The way I handle this for multiple results is to create a new Extent, and then keep increasing the extent size to include each of the returned results. 

Once you have all your results, you can just use map.setExtent() to zoom to that specific extent.

If you only have a single result that is easier, as you then just grab the extent from your feature, expand that extent and again use map.setExtent().


Jonathan
0 Kudos
MJWaldstein
New Contributor
Hi Jonathan,

Thanks for the reply. I changed it to a drop down list, which works when you choose to pick from the first of the two drop-down lists. But it will not zoom to the feature when i choose form the second drop down list..... and ever other time I refresh the drop down won't work at all, which may be just a bug. I refresh it again, and it works.

function init() {
   
    map = new esri.Map("map");
    var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://54.245.226.122:6080/arcgis/rest/services/Stream_Application/Cutblocks/MapServer");
   
    map.addLayer(layer);
   
    blockQueryTask = new esri.tasks.QueryTask("http://54.245.226.122:6080/arcgis/rest/services/Stream_Application/Cutblocks/MapServer/1");
   
    blockQuery = new esri.tasks.Query();
    blockQuery.returnGeometry = false;
    blockQuery.outFields = ["CUT_BLK_ID"];
   
    blockQuery.where = "CUT_BLK_ID <> ''";
   
    blockQueryTask.execute(blockQuery, updateblockDD)

    var layer4 = new esri.layers.ArcGISDynamicMapServiceLayer("http://54.245.226.122:6080/arcgis/rest/services/Stream_Application/Lakes/MapServer");
   
    map.addLayer(layer4);
   
    lakeQueryTask = new esri.tasks.QueryTask("http://54.245.226.122:6080/arcgis/rest/services/Stream_Application/Lakes/MapServer/0");
   
    lakeQuery = new esri.tasks.Query();
    lakeQuery.returnGeometry = false;
    lakeQuery.outFields = ["GNSNM1"];
    lakeQuery.where = "GNSNM1 <> ''";   
    lakeQueryTask.execute(lakeQuery, updatelakeDD)
   }

   function updateblockDD(results) {
    var blockNames = new Array();
    var selectObj = document.getElementById("blockSelectDD");

    selectObj.options.length = 0;
    var optObj = new Option("Choose a block");
    selectObj.options[selectObj.options.length] = optObj;

    for (var i = 0, len = results.features.length; i < len; i++) {
     var featureAttributes = results.features.attributes;
     for (attribute in featureAttributes) {

      var index = blockNames.indexOf(featureAttributes.CUT_BLK_ID);
      if (index == -1) {
       blockNames.push(featureAttributes.CUT_BLK_ID)
      }
     }
    }

    blockNames.sort();
    //Sorting
    for (var j = 0; j < blockNames.length; j++) {
     var optObj = new Option(blockNames, blockNames);
     selectObj.options[selectObj.options.length] = optObj;
    }
   }

   function zoomToblock(block) {
    var selectionObject = document.getElementById("blockSelectDD");
    var strblock = selectionObject.options[selectionObject.selectedIndex].value;

    if (selectionObject.selectedIndex != 0) {
    
     blockQueryTask = new esri.tasks.QueryTask("http://54.245.226.122:6080/arcgis/rest/services/Stream_Application/Cutblocks/MapServer/1");
    
     blockQuery = new esri.tasks.Query();
     blockQuery.returnGeometry = true;
     blockQuery.where = "CUT_BLK_ID = '" + strblock + "'";
     blockQueryTask.execute(blockQuery, ZoomToGeometry)
    } else {
     zoomToFullExtent();
    
    }
   }

   function zoomToFullExtent()//to reset map extent
   {
    var layer1 = map.getLayer(map.layerIds[0]);
    map.setExtent(layer1.initialExtent);
   }

   function clearGraphics() {
    map.graphics.clear();
   }

   function ZoomToGeometry(geom) {
    if (geom.features.length > 0) {
     var graphic = geom.features[0];
     var selSymbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0, 0, 255]), 4.5));
     graphic.setSymbol(selSymbol);
     map.graphics.add(graphic);
     blockGraphic = graphic;
     var timeEvent = setTimeout(map.setExtent(geom.features[0].geometry.getExtent().expand(1)), 1);
    
    }
   }

   function updatelakeDD(results1) {
    var lakeNames = new Array();
    var selectObj1 = document.getElementById("lakeSelectDD");

    selectObj1.options.length = 0;
    var optObj1 = new Option("Choose a lake");
    selectObj1.options[selectObj1.options.length] = optObj1;

    for (var i = 0, len = results1.features.length; i < len; i++) {
     var featureAttributes = results1.features.attributes;
     for (attribute in featureAttributes) {

      var index = lakeNames.indexOf(featureAttributes.GNSNM1);
      if (index == -1) {
       lakeNames.push(featureAttributes.GNSNM1)
      }
     }
    }

    lakeNames.sort();
   
    for (var j = 0; j < lakeNames.length; j++) {
     var optObj1 = new Option(lakeNames, lakeNames);
     selectObj1.options[selectObj1.options.length] = optObj1;
    }
   }

   //Zoom to returned geometry - called at 'OnChange' event of the dropdown list
   function zoomTolake(lake) {
    var selectionObject = document.getElementById("lakeSelectDD");
    var strlake = selectionObject.options[selectionObject.selectedIndex].value;

    if (selectionObject.selectedIndex != 0) {
    
     lakeQueryTask = new esri.tasks.QueryTask("http://54.245.226.122:6080/arcgis/rest/services/Stream_Application/Lakes/MapServer/0");
    
     lakeQuery = new esri.tasks.Query();
     lakeQuery.returnGeometry = true;
     lakeQuery.where = "GNSNM1 = '" + strlake + "'";
     lakeQueryTask.execute(lakeQuery, ZoomToGeometry)
    } else {
     zoomToFullExtent();
    
    }
   }

   function zoomToFullExtent()//to reset map extent
   {
    var layer1 = map.getLayer(map.layerIds[0]);
    map.setExtent(layer1.initialExtent);
   }

   function clearGraphics() {
    map.graphics.clear();
   }

   function ZoomToGeometry(featureSet) {
    if (featureSet.features.length > 0) {
     var graphic = featureSet.features[0];
     var selSymbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0, 0, 255]), 4.5));
     graphic.setSymbol(selSymbol);
     map.graphics.add(graphic);
     lakeGraphic = graphic;
     var timeEvent = setTimeout(map.setExtent(featureSet.features[0].geometry.getExtent().expand(1)), 1);
    
    }
   }
0 Kudos
RahulMetangale1
Frequent Contributor
Margaret,

I understand that you want to zoom to the entire result set of query task. You are using query task which returns a feature set. I would use following esri namespace method to get the extent of all graphics and use that to set the extent of map:

var myFeatureExtent = esri.graphicsExtent(myFeatureSet.features);
map.setExtent(myFeatureExtent);


I hope this helps.

-Rahul
0 Kudos
DianaBenedict
Frequent Contributor
Margret

Rahul is correct in pointing you to using the esri.graphicsExtent method that is built in to the Javascript API.  Here is how I zoom to all the graphics that have been added to the map after executing a find task. So that you do not have to change much of your code you can simply add the following to the end of your "showResults method ..essentially AFTER you have added the new graphics to the map.

//zoom to graphics on the 
  var graphicsExtent = esri.graphicsExtent(map.graphics.graphics)
  if (graphicsExtent !== null) {
    map.setExtent(graphicsExtent);
//map.setExtent(graphicsExtent.expand(1.5)); //use this if you want to expand the extent
  } 
0 Kudos
WillHughes1
Frequent Contributor
Why does this only zoom to selected features when the result is > 1? If you enter a city such as Miami which returns multiple points it works, but Raleigh doesn't zoom to the selection because the result set is 1.

i use the sandbox to test the javascript - https://developers.arcgis.com/en/javascript//sandbox/sandbox.html?sample=

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7" />
    <title>QueryTask with value, results as an InfoWindow</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/1.6/js/dojo/dijit/themes/tundra/tundra.css">
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.6"></script>
    <script type="text/javascript" language="Javascript">
      dojo.require("esri.map");
      dojo.require("esri.tasks.query");

      var map, queryTask, query;
      var symbol, infoTemplate;
     
   

      function init() {
        //create map
        map = new esri.Map("mapDiv");
       
       

        //create and add new layer
        var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/Map...");
        map.addLayer(layer);

        //build query task
        queryTask = new esri.tasks.QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/Map...");

        //build query filter
        query = new esri.tasks.Query();
        query.returnGeometry = true;
        query.outFields = ["CITY_NAME", "STATE_NAME", "POP1990"];


        //create the infoTemplate to be used in an InfoWindow.
        //All ${attributeName} will be substituted with the attribute value for current feature.
        infoTemplate = new esri.InfoTemplate("${CITY_NAME}", "Name : ${CITY_NAME}<br/> State : ${STATE_NAME}<br />Population : ${POP1990}");

    //create symbol for selected features
        symbol = new esri.symbol.SimpleMarkerSymbol();
        symbol.setStyle(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE);
        symbol.setSize(10);
        symbol.setColor(new dojo.Color([255,255,0,0.5]));
   
 
      }

      function executeQueryTask(population) {
        //set query based on what user typed in for population;
        query.where = "CITY_NAME = " + "'" + population +"'";

        //execute query and call showResults on completion
        queryTask.execute(query,showResults);
     
      }


      function showResults(featureSet) {
        //remove all graphics on the maps graphics layer
        map.graphics.clear();
       
      


        //QueryTask returns a featureSet.  Loop through features in the featureSet and add them to the map.

        //Performance enhancer - assign featureSet array to a single variable.
        var resultFeatures = featureSet.features;

        for (var i=0, il=resultFeatures.length; i<il; i++) {
          //Get the current feature from the featureSet.
          //Feature is a graphic
          var graphic = resultFeatures;
          graphic.setSymbol(symbol);

          //Set the infoTemplate.
          graphic.setInfoTemplate(infoTemplate);

          //Add graphic to the map graphics layer.
          map.graphics.add(graphic);
         

  var myFeatureExtent = esri.graphicsExtent(resultFeatures);
map.setExtent(myFeatureExtent.expand(2.5));
         
        }
       
      }
  

      dojo.addOnLoad(init);
     
    </script>
  </head>
  <body class="tundra">
  <br/>
      US city population greater than : <input type="text" id="population" value="Raleigh" />
    <input type="button" value="Get Details" onclick="executeQueryTask(dojo.byId('population').value);" />


    <div id="mapDiv" style="width:600px; height:600px; border:1px solid #000;"></div>
    Click on a city once it's highlighted to get an InfoWindow.

  </body>
</html>
0 Kudos
KenBuja
MVP Esteemed Contributor
From the graphicsExtent help:   If the extent height and width are 0, null is returned.

That's the case when only one point is returned. You can test for that and set the extent for that point, like in this thread.

When posting code, get into the habit of put it into a code block, using the # button above. It makes it easier to read.
0 Kudos
ZachLiu1
Deactivated User
I would just use this to take care of the case when only one point is returned during a query task.

if(resultFeatures.length == 1) {
                map.centerAt(resultFeatures[0].geometry);
            }
0 Kudos
WillHughes1
Frequent Contributor
Thanks Zach and Ken. Zach, I like the option of just centering on the selected feature, but how would you set the zoom level? It would be fine to use a constant value for zoom level.

Will
0 Kudos
KenBuja
MVP Esteemed Contributor
You can use the centerAndZoom method, which allows you to use a zoom factor.
0 Kudos