Limit Legend Dijit based on visible features in time extent

2620
1
10-04-2013 03:08 PM
AdamRoberts1
New Contributor
Hi, is it possible to limit the items in the legend based on the visible features in the current time extent?
I have one feature layer with 12 symbologies, but depending on the time extent that is set, I may only see 1 or 2. I need the legend to show only what is currently visible on the map. Using JSAPI3.6.
0 Kudos
1 Reply
FC_Basson
MVP Regular Contributor
Unfortunately there is no method in the legend widget to do this, but it is possible with some legend element manipulation.

I created a very simple example of how this can be done and here are the basic steps:
1) Get all the features currently in the map extent with a QueryTask request and make a list of unique values for the legend items you want to show in the end.  These values will be extracted from the field that the symbology is based on and might be displayed as a single symbol for grouped values.
2) Get the full legend for the Web Service layer (as JSON) with a standard GET request as described in the REST API.
3) Compare the values from (1) to the legend values from (2) and extract the label/symbol from the full legend.  Now you will have the legend symbols that correspond with the visible features in the map.
4) Manually rebuild the legend table with the label/symbol values from (3).

Here is my code (a mix of Javascript dojo and jQuery), which I tested and it worked surprisingly well, but it is VERY rough and should be adapted according to your specific needs and Web Service:

function clipLegend() {
   // STEP 1: BUILD QUERYTASK
   var queryURL = 'http://<myserver>/arcgis/rest/services/<myservice>/<layerID>';
   var queryTask = new esri.tasks.QueryTask(queryURL);
   var query = new esri.tasks.Query();   
   query.where = "1=1";
   query.outFields = ["TYPE"];      
   query.geometry = map.geographicExtent;
   query.returnGeometry = false;
   query.spatialRelationship = esri.tasks.Query.SPATIAL_REL_INTERSECTS;
   var valList = [];
   // run query task
   queryTask.execute(query, function(results){
      // iterate features in result (visible features) and create a list of unique values
      for (r in results.features){
         // get feature attributes
         var attr = results.features.attributes;
         // value
         var val = attr['TYPE'];
         // add to value list
         if (valList.indexOf(val) == -1) {
            valList.push(val);
         }         
      }
      // done creating value list
      
      // clear Legend table
      $('.esriLegendLayer').html('')
      
      // STEP 2: get legend via REST API
      $.get('http:/<myserver>/arcgis/rest/services<myservice>/legend?f=json', function(json){
         // STEP 3: compare value list to layer legend and select
        // label/symbol list
         var clipList = [];
         for (labels in json['layers']) {
            if (json['layers'][labels]['layerId'] == <layerID>){
               // legend for layer
               var leg = json['layers'][labels]['legend'];               
               // iterate labels
               for (label in leg){
                  if ('values' in leg[label]) {
                     // get values for that make up current label symbology
                     var labelVals = leg[label]['values'];
                     /// check in which label/symbol category the feature value falls
                     for (v in valList){
                        // use only label/symbol categories with a value list
                        if (labelVals.indexOf(valList) != -1) {
                           // add unique label value to clip list
                           if (!(leg[label]['label'] in clipList)) {
                              clipList[leg[label]['label']] = leg[label]['url'];
                           }                                                      
                        }
                     }
                  }
               }               
            }           
         }

         //  STEP 4: rebuild legend table
         for (c in clipList){
            var url = clipList;            
            var img = queryURL + '/images/' + url;
            $('.esriLegendLayer').append('<tr><td><img src="'+ img +'"></td><td align="left">' + c + '</td></tr>');
         }
      }, "json");      
   });
}


Hope it helps.  Let me know if you get lost in the explanation.