LayerList and setting Legend graphics

4903
5
11-23-2015 01:32 PM
DavidColey
Frequent Contributor

Hi All -

In working with the LayerList widget the past month or so we kept trying to figure out a way to get the symbology from the feature layer and Legend into the innerHTML of the option of the LayerList widget so that we can display the feature layers' graphic under each list node. So we went back to the map's on 'layers-add-result' event setting up the function to return each layer and each layers defined id as the title:

mapMain.on("layers-add-result", function(results) {
     layerInfo = array.map(results.layers, function (layer, index) { //dojo array
            return {layer:layer.layer, title:layer.layer.id};
     });
       legend = new Legend({
            map : mapMain,
            layerInfos: layerInfo,
            arrangement : Legend.ALIGN_LEFT
       },  "legendDiv");
       legend.startup();
       for (i = 0; i < layerInfo.length; i++){ // cant use i=0, when a label layer is present,don't know why yet.
                     console.log(legend.layerInfos);
                     layerInfo.content = domConstruct.create("div", {
                     innerHTML: legend.domNode.childNodes[(layerInfo.length -1) -i].childNodes[1].innerHTML
            });
     }
    layerList = new LayerList({
         map: mapMain,   
         layers : layerInfo
         }, "layerListDiv");
       layerList.startup();
     });
mapMain.on("zoom-end", function(results) {
     legend.refresh();
     for (i = 0; i < layerInfo.length; i++){
                layerInfo.content = domConstruct.create("div", {
                innerHTML: legend.domNode.childNodes[(layerInfo.length -1) -i].childNodes[1].innerHTML
        });
       layerList.refresh();
 }
 });
document.getElementById("legendDiv").style.display = "none";

Basically we (Michael Stranovsky​) and myself discovered by setting a console log on the legend layerInfos, we could see that legend has a content property and that by stepping into the content property we could get at the innerHTML dom element that contains the graphic and at what index level.  So the for loop says that for each layer, go into the content, construct a div and then set the innerHTML of each layer at child node index:

[(layerInfo.length - 1) -i]

Because the legend layer ordering is the reverse of the map layer ordering we add the additional (-i).  At any rate, the innterHTML completes by stepping down one more childNodes element [1] to get at the graphic (childNodes element at [0] is the layer title text).  Add  the layerList Widgets, pass in the layerInfo value from the loop into the layerInfos option, and start the layerList.  To keep from displaying the legend div, simply set it's display to none. 

If there are layers with zoom dependency, no childNodes element will be created in the legend because they don't exist yet.  So add a on 'zoom-end' event with a legend refresh, loop through the layers childNodes elements again and refresh the layer list and when the node is created it will be added.

Known issue(s):  With a label layer present in the map, the loop counter must be started at 1.  Don't know why yet.  I also haven't tested this configuration using tiled or dynamic layers.  I welcome any comments or insights . . .

Thanks

David

0 Kudos
5 Replies
DavidColey
Frequent Contributor

Update:

With the 3.15 update, the above code is no longer needed, thank you ESRI.  Now simply:

    mapMain.on("layers-add-result", function(results) { 
      var layerInfo = array.map(results.layers, function (layer) {
      return {layer:layer.layer, title:layer.layer.id};
  });
    var layerList = new LayerList({
        map: mapMain,
        showLegend: true, 
        layers : layerInfo
        }, "layerListDiv");
  layerList.startup();
  });

set the showLegend constructor option to true and you have your legend...

David

0 Kudos
by Anonymous User
Not applicable

Perfect. Thanks for that info David.   Great work team ESRI.

Also, I think (??) this is new.. .but I noticed in the Sample now that LayerList turns on as soon as you 'open' a Group.  This is awesome. Smart thinking. Because this solves the question I've always had of if they'd make groups automatically turn on, if you turn a child sublayer on. Now, it's fixed, because opening a group turns in on.  Makes sense.  So happy with this widget now.  The last thing I'm wondering is if ESRI will add transparency sliders like AGSTOC.

I believe ESRI should consider adding a 'partial' icon for the Checkbox of a group if only some of the layers are turned on.   (i.e. https://css-tricks.com/indeterminate-checkboxes/​ & Axure Forums  ) That square dot that indicates only some of the group layers are on, like how desktop applications indicate this. This actually even applies to ArcGIS Desktop's TOC as well.  This user interface metaphor is widely understood and nearly universal in software.

0 Kudos
KenBuja
MVP Esteemed Contributor

The 3.15 version does have a transparency slider built in. You can add it with the showOpacitySlider property. Originally, it could be added by utilizing one of the optional custom nodes, but this is an easier implementation.

by Anonymous User
Not applicable

Thanks Ken. Sweet.

0 Kudos
DavidColey
Frequent Contributor

Yeah Ken I saw your earlier sample with slider node, got us thinking about child nodes in the legend and adding as the innerHtml content at 3.14, hence what we were able to come up with. But yes 3.15 much easier for sure

Thanks for that-

David

0 Kudos