Hide Table of Contents
View History API to track selected feature sample in sandbox
History API to track selected feature

Description

This sample demonstrates how to select features using a value retrieved from the url. In this case, parcels are selected using the parcel id, which is provided to the application using the parcelid url parameters. The API provides a helper method esri.urlToObject that simplifies the process of extracting url parameters.When users click on parcels in the map we update the url to contain the new parcelid using the history object. The history object is part of HTML5 and may not be supported by all browsers. Visit caniuse.com to determine if your browser supports this capability. In browsers that do support this capability users will be able to navigate through the selected parcels using the browser's back/forward buttons. To test the history object select a few parcels then use the browser's navigation buttons to move through the selection history. View the Manipulating the browser history documentation on the Mozilla Developer Network for more information.

Code

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Parcel Locator</title>

    <link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css">
    <style>
      html, body, #map {
        height: 100%;
        width: 100%;
        margin: 0;
        padding: 0;
      }
    </style>

    <script>var dojoConfig = { parseOnLoad: true };</script>
    <script src="https://js.arcgis.com/3.21/"></script>
    <script>
      var map;
      var parcels;
      require([
        "esri/map", "esri/layers/FeatureLayer", 
        "esri/layers/ArcGISTiledMapServiceLayer", "esri/tasks/query",
        "esri/symbols/SimpleFillSymbol", "esri/symbols/SimpleLineSymbol",
        "esri/graphic", "esri/dijit/Popup", "esri/dijit/PopupTemplate",
        "esri/urlUtils", "esri/graphicsUtils",
        "esri/Color", 
        "dojo/on", "dojo/query", "dojo/parser", "dojo/dom-construct",

        "dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dojo/domReady!"
      ], function(
        Map, FeatureLayer, 
        ArcGISTiledMapServiceLayer, Query,
        SimpleFillSymbol, SimpleLineSymbol,
        Graphic, Popup, PopupTemplate,
        urlUtils, graphicsUtils,
        Color, 
        on, query, parser, domConstruct
      ) {
        //apply a selection symbol that determines the symbology for selected features 
        var sfs = new SimpleFillSymbol(
          SimpleFillSymbol.STYLE_SOLID, 
          new SimpleLineSymbol(
            SimpleLineSymbol.STYLE_SOLID, 
            new Color([111, 0, 255]), 
            2
          ), 
          new Color([111, 0, 255, 0.15])
        );

        var popup = new Popup({
          fillSymbol: sfs
        }, domConstruct.create("div"));

        map = new Map("map", {
          infoWindow: popup,
          slider: false
        });
        var basemap = new ArcGISTiledMapServiceLayer("https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/AssessorsBasemap/MapServer/");
        map.addLayer(basemap);

        //apply a popup template to the parcels layer to format popup info 
        var popupTemplate = new PopupTemplate({
          title: "{PARCELID}",
          fieldInfos: [{
            fieldName: "SITEADDRESS",
            label: "Address:",
            visible: true
          }, {
            fieldName: "OWNERNME1",
            label: "Owner:",
            visible: true
          }]
        });

        //add the parcels layer to the map as a feature layer in selection mode we'll use this layer to query and display the selected parcels
        parcels = new FeatureLayer("https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/AssessorsBasemap/MapServer/1", {
          outFields: ["*"],
          infoTemplate: popupTemplate,
          mode: FeatureLayer.MODE_SELECTION
        });

        parcels.setSelectionSymbol(sfs);

        //when users click on the map select the parcel using the map point and update the url parameter
        map.on("click", function (e) {
          var query = new Query();
          query.geometry = e.mapPoint;
          var deferred = parcels.selectFeatures(query, FeatureLayer.SELECTION_NEW, function (selection) {
            //update the url param if a parcel was located
            if (selection.length > 0) {
              var parcelid = selection[0].attributes["PARCELID"];
              //Refresh the URL with the currently selected parcel
              if (typeof history.pushState !== "undefined") {
                window.history.pushState(null, null, "?parcelid=" + selection[0].attributes.PARCELID);
              }
            }
          });
          map.infoWindow.setFeatures([deferred]);
          map.infoWindow.show(e.mapPoint);
        });

        map.on("layers-add-result", function (result) {
          // Add a link into the InfoWindow Actions panel       
          var emailLink = domConstruct.create("a", {
            "class": "action",
            "innerHTML": "Email Map",
            "href": "javascript:void(0);"
          }, query(".actionList", map.infoWindow.domNode)[0]);

          // Register a function to be called when the user clicks on
          // the above link
          on(emailLink, "click", function (evt) {
            var feature = map.infoWindow.getSelectedFeature();
            var url = window.location;
            var emailLink = "mailto:?subject=Parcel Map of :" + 
              feature.attributes.PARCELID + "&body=Check out this map: %0D%0A " + 
              window.location;
            window.location.href = emailLink;
          });

          //When users navigate through the history using the browser back/forward buttons select appropriate parcel  
          //http://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
          window.onpopstate = function (event) {
            var parcelid = getParcelFromUrl(document.location.href);
            if (parcelid) {
              selectParcel(parcelid);
            } else {
              parcels.clearSelection();
              map.infoWindow.hide();
            }
          };

          //if a parcelid is specified in url param select that feature 
          var parcelid = getParcelFromUrl(document.location.href);
          selectParcel(parcelid);
        });

        map.addLayers([parcels]);

        //extract the parcel id from the url
        function getParcelFromUrl(url) {
          var urlObject = urlUtils.urlToObject(url);
          if (urlObject.query && urlObject.query.parcelid) {
            return urlObject.query.parcelid;
          } else {
            return null;
          }
        }

        //select parcel from the feature layer by creating a query to look for the input parcel id 
        function selectParcel(parcelid) {
          if (parcelid) {
            var query = new Query();
            query.where = "PARCELID = '" + parcelid + "'";
            var deferred = parcels.selectFeatures(query, FeatureLayer.SELECTION_NEW, function (selection) {
              var center = graphicsUtils.graphicsExtent(selection).getCenter();
              var extHandler = map.on("extent-change", function () {
                extHandler.remove();
                //zoom to the center then display the popup 
                map.infoWindow.setFeatures(selection);
                map.infoWindow.show(center);
              });
              map.centerAt(center);
            });
          }
        }
      });
    </script>
  </head>
  
  <body class="claro">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline',gutters:false" 
    style="width: 100%; height: 100%; margin: 0;">
      <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
    </div>
  </body>

</html>