LayerList widget enhanced to be collapsable

8071
15
10-26-2015 09:19 AM
RobertScheitlin__GISP
MVP Emeritus

All,

   This is a Proof of Concept sample that I was working on. I have taken the LayerList widget and enhanced it to allow for collapsing the widget layers and sublayers. It is simple css and dom manipulation. I have tested this with a deeply nested map service layer and it works well. I am not sure esri will be spending time on the 3.x version to add enhancements like this so I did.

Here is the Live Preview Site

And Attached is the sample 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>Layer List Dijit</title>
  <link rel="stylesheet" href="http://js.arcgis.com/3.14/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.14/esri/css/esri.css">

  <style>
    html,
    body,
    .container,
    #map {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
      margin: 0;
      font-family: "Open Sans";
    }

    #map {
      padding: 0;
    }

    #layerListPane {
      width: 25%;
    }

    .esriLayer {
      background-color: #fff;
    }

    .esriLayerList .esriList {
      border-top: none;
    }

    .esriLayerList .esriTitle {
      background-color: #fff;
      border-bottom: none;
    }

    .esriLayerList .esriList ul {
      background-color: #fff;
    }
/*css rules for the expand div*/
    .esriLayerExpand {
      width: 16px;
      height: 16px;
      float: left;
      margin: 12px 0;
    }
    .esriLayerExpand.expand {
      background-image: url(images/v_right.png);
      background-repeat: no-repeat;
      background-position: center;
      cursor: pointer;
    }
    .esriLayerExpand.collapse{
      background-image: url(images/v.png);
      background-repeat: no-repeat;
      background-position: center;
      cursor: pointer;
    }
/*narrow the margin of the checkbox for aesthetics*/
    .esriLayerList .esriCheckbox {
      margin: 12px 5px 12px 5px;
    }
  </style>
  <script>
    var dojoConfig = {
      parseOnLoad: true
    };
  </script>
  <script src="http://js.arcgis.com/3.14/"></script>
  <script>
    require([
    "esri/map",
    "esri/layers/ArcGISDynamicMapServiceLayer",
    "esri/dijit/LayerList",
    "dojo/query",
    "dojo/dom-construct",
    "dojo/dom-class",
    "dojo/dom-style",
    "dojo/on",
    "dojo/_base/array",
    "dijit/layout/BorderContainer",
    "dijit/layout/ContentPane",
    "dojo/domReady!"
], function (
      Map,
      ArcGISDynamicMapServiceLayer,
      LayerList,
      query,
      domConstruct,
      domClass,
      domStyle,
      on,
      array
    ) {
      var map = new Map("map", {
        basemap: "topo",
        center: [-123, 47],
        zoom: 8,
        sliderStyle: "small"
      });

      var atlasLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer", {
        "id": "atlasLayer",
        "showAttribution": false
      });

      var recreationLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Recreation/MapServer", {
        "id": "recreationLayer",
        "showAttribution": false
      });

      var waterNetLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/MapServer", {
        "id": "waterNetworkLayer",
        "showAttribution": false
      })

      map.addLayers([atlasLayer, recreationLayer, waterNetLayer]);

      var llWidget = new LayerList({
         map: map,
         layers: [{
           layer: atlasLayer,
            id: "Atlas layers",
            subLayers: true
         },
         {
           layer: recreationLayer,
            id: "Recreation layers",
            subLayers: true
         },
         {
           layer: waterNetLayer,
            id: "Water Network layers",
            subLayers: true
         }]
      },"layerList");
      llWidget.startup();
/*When the LayerList is loaded enhance it to add collapse capabilities*/
      llWidget.on('load', function(){
        enhanceLayerList();
      });

/*Work with all the layers*/
      function enhanceLayer(layerNode){
        layerExpand = domConstruct.create('div');
        domClass.add(layerExpand, 'esriLayerExpand collapse');
        domConstruct.place(layerExpand, layerNode, 'first');
        on(layerExpand, 'click', function(evt){
          var LayerNodes = query('.esriLayer');
          var SubList = query('.esriSubList', evt.target.parentNode);
          if(domClass.contains(evt.target, 'collapse')){
            domClass.replace(evt.target, 'expand', 'collapse');
            domStyle.set(SubList[0], 'display', 'none');
          }else{
            domClass.replace(evt.target, 'collapse', 'expand');
            domStyle.set(SubList[0], 'display', '');
          }
        });
        var subListNodes = query('.esriSubListLayer', layerNode);
        if(subListNodes.length > 0){
          array.map(subListNodes, function(subListNode){
            enhanceSubList(subListNode);
          });
        }
      }

/*Now work with all the sublayers*/
      function enhanceSubList(subLayerNode){
        var subLayerExpand;
        var subListNodes = query('.esriSubListLayer', subLayerNode);
        if(subListNodes.length > 0){
          subLayerExpand = domConstruct.create('div');
          domClass.add(subLayerExpand, 'esriLayerExpand collapse');
          domConstruct.place(subLayerExpand, subLayerNode, 'first');
          on(subLayerExpand, 'click', function(evt){
            var cState = '';
            var subListLayerNodes = query('.esriSubListLayer', evt.target.parentNode);
            if(domClass.contains(evt.target, 'collapse')){
              domClass.replace(evt.target, 'expand', 'collapse');
              cState = 'collapse';
            }else{
              domClass.replace(evt.target, 'collapse', 'expand');
              cState = 'expand';
            }
            array.map(subListLayerNodes, function(subListLayerNode){
              if(cState === 'collapse'){
                domStyle.set(subListLayerNode, 'display', 'none');
              }else{
                domStyle.set(subListLayerNode, 'display', 'block');
              }
            });
          });
        }else{
          subLayerExpand = domConstruct.create('div');
          domClass.add(subLayerExpand, 'esriLayerExpand');
          domConstruct.place(subLayerExpand, subLayerNode, 'first');
        }
      }

/*Begin with the individual layers*/
      function enhanceLayerList() {
        var layerExpand, subLayerExpand;
        var LayerNodes = query('.esriLayer');
        array.map(LayerNodes, function(layerNode){
          enhanceLayer(layerNode);
        });
      }

    });
  </script>
</head>

<body class="claro">
  <div class="container" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline',gutters:false">
    <div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
      <div id="layerList"></div>
    </div>
    <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
  </div>
</body>

</html>
0 Kudos
15 Replies
RickeyFight
MVP Regular Contributor

Thanks Robert!

0 Kudos
KenBuja
MVP Esteemed Contributor

The 3.15 version of the LayerList widget has some additional functionality, including collapsible layers. It also includes the legend items. One thing I did notice is that this legend list is only updated when the view is zoomed in or out (but not when it is panned), not when the checkbox is clicked.

0 Kudos
Quynh_NhuMai
New Contributor III

Hi, so the layerlist is collapsible out of the box? I didn't see that in the API...Can you point me in the right direction?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

it is a property called showsublayers:

https://developers.arcgis.com/javascript/3/jsapi/layerlist-amd.html#showsublayers 

or the widgets ui has arrows for expanding and collapsing.

0 Kudos
DanielOchoa
Occasional Contributor

Rob,

Have you created a enhanced layer list widget for the WAB from this?

Thanks!

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Daniel,

  No I have not as this was more of a proof of concept. I have considered creating a eLayerList widget but my widget development list is pretty big already.

0 Kudos
DanielOchoa
Occasional Contributor

Rob,

Thanks for the reply.  Another poster mentioned an "Enhanced Layer List Widget" here in this post:

ImportFile.zip

Any idea what they are referring to?

~ D

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Daniel,

  No there is not an enhanced Layer list widget out there that I am aware of.

0 Kudos
HiranDias
New Contributor

Hi Robert ! Another amazing solution but how can i set this up in my Webappbuilder ? Should i unzip this as new widget or update the current LayerList ? I could not find a LayerListWidget.html to replace on the source code. Thank you.

0 Kudos