Javascript - toggle layers on/off

4475
10
Jump to solution
07-23-2015 01:51 PM
LauraMiles1
Occasional Contributor III

Hi everyone, I'm using the ESRI sample for turning my layers on and off: Toggle layer visibility | ArcGIS API for JavaScript

 

I've tried to modify things because I have some checkboxes that I'd like to be able to turn on and off as a group. As I've written the code, turning these on and off using the "Select All" link does seem to work fine, until it gets to this line (line 29 in the codeblock below):

 

var inputs = query(".enviro_list_item")

 

At this point it's passed the case test, but it seems that the variable "inputs" is empty.

 

I get an 'Uncaught TypeError: Cannot read property of 'length' of undefined' in my NetBeans Console, and the layers within the div (everything that just got checked) are not drawn. However if I check a checkbox with the same class, outside or inside the div (as long as I'm not using "Select All"), all the checked layers do get drawn. I tried to look up exactly what this query(".enviro_list_item") does but I can't find any information on query(). I'm guessing it polls the values of the checkboxes within the specified class and puts them in an array. But why would it not work because these are being turned on/off via the html link? It must be to do with the click or change event not being fired? I tried adding this jquery (line 13 below) but it didn't make a difference:

 

$(targetSelectMenu).find(':checkbox').trigger('change');

 

If I could get the above working, I think I would not need line 15 then?

 

 

Here is my code

 

HTML:

 

<div id="divMenuEnvironment" class='divMenu'>

                        <label id="lblBIEAP" class="lblSubMenuItem"><img id="imgBIEAP" src="Images\plus.png" width="13"/>BIEAP</label><a class="aSelectAll" id="aBIEAPSelectAll"> Select All</a></br>

                        <div id='divMenuBIEAP' class='divSubMenu'>

                            <div id='txtBIEAPHighTide' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPHighTide' value=26 />High Tide Line</div>

                            <div id='txtBIEAPLowTide' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPLowTide' value=38 />Low Tide Line</div>

                            <div id='txtBIEAPShoreSeg' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPShoreSeg' value=37 />Shoreline Segments</div>

                            <div id='txtBIEAPOverVeg' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPOverVeg' value=36 />Overhanging Vegetation</div>

                            <div id='txtBIEAPShoreEros' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPShoreEros' value=35 />Shoreline Erosion</div>

                            <div id='txtBIEAPOutfalls' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPOutfalls' value=34 />Outfalls</div>

                            <div id='txtBIEAPIntFeat' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPIntFeat' value=33 />Interesting Features</div>

                            <div id='txtBIEAPBirdNest' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPBirdNest' value=32 />Bird Nests</div>

                            <div id='txtBIEAPIntPlant' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPIntPlant' value=31 />Introduced Plants</div>

                            <div id='txtBIEAPIntVegFeat' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPIntVegFeat' value=30 />Intertidal Vegetation Features</div>

                            <div id='txtBIEAPIntVegAreas' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPIntVegAreas' value=29 />Intertidal Vegetation Areas</div>

                            <div id='txtBIEAPIntSubs' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBIEAPIntSubs' value=28 />Intertidal Substrates</div>

                        </div>

                        <label id="lblFREMP" class="lblSubMenuItem"><img id="imgFREMP" src="Images\plus.png" width="13"/>FREMP</label><a class="aSelectAll" id="aFREMPSelectAll"> Select All</a></br>

                        <div id='divMenuFREMP' class='divSubMenu'>

                            <div id='txtFREMPColCode' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkFREMPColCode' value=43 />Colour Codes</div>

                            <div id='txtFREMPAreaDes' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkFREMPAreaDes' value=42 />Area Designation</div>

                            <div id='txtFREMPHabComp' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkFREMPHabComp' value=41 />Habitat Compensation</div>

                            <div id='txtFREMPHabOrd' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkFREMPHabOrd' value=40 />Habitat Order</div>

                        </div>

                        <div id='txtBoreholes' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkBoreholes' value=0 />Boreholes</div>

                        <img id='imgContSitesLock' src='Images\lock.png' height='0' style='float:left;' title='You do not have access to this layer'/>

                        <div id='txtContSites' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkContSites' value=45 />Contaminated Sites</div>

                        <img id='imgEnvLibLock' src='Images\lock.png' height='0' style='float:left;' title='You do not have access to this layer'/>

                        <div id='txtEnviroLib' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkEnvLib' value= />Enviro Library</div>

                        <div id='txtHabComp' class='divMenuItem'><input type='checkbox' class='enviro_list_item' id='chkHabComp' value=17 />Habitat Compensation Sites</div>

                    </div>

 

Javascript:

 

//The following fires when a "Select All" link is clicked to turn all layers in a subgroup on/off

$(".aSelectAll").click(function(){

    //cut off the "a" and "SelectAll" from the clicked link's id

    //example id would be 'aBIEAPSelectAll'

    var targetSelectAll = ((event.srcElement.id).replace("SelectAll", '')).slice(1);

    //piece together the id of the menu targeted

    //example result would be "#divMenuBIEAP

    var targetSelectMenu = "#divMenu" + targetSelectAll;

    //find all the checkboxes in the divMenu and toggle them

    var checked = $(this).data('checked');

    $(targetSelectMenu).find(':checkbox').prop('checked', !checked);

    $(this).data('checked', !checked);

    $(targetSelectMenu).find(':checkbox').trigger('change');

    //run the function to update the visibility of layers

    updateLayerVisibility();

});

 

on(document.body, ".cadastral_list_item:change", updateLayerVisibility);

on(document.body, ".enviro_list_item:change", updateLayerVisibility);

 

        function updateLayerVisibility () {

 

            switch(event.srcElement.className) {

                case "cadastral_list_item":

                    var inputs = query(".cadastral_list_item");

                    var serviceLayer = layerCadastral;

                    break;

                case "enviro_list_item":

                    var inputs = query(".enviro_list_item");

                    var serviceLayer = layerEnvironment;

                    break;

            }

           var inputCount = inputs.length;

 

            visibleLayerIds = [1001];

            for (var i = 0; i < inputCount; i++) {

              if (inputs.checked) {

                visibleLayerIds.push(inputs.value);

              }

            }

            if (visibleCadastralLayerIds.length === 0) {

              visibleLayerIds.push(-1);

            }

            serviceLayer.setVisibleLayers(visibleLayerIds);

            // run the identify task setup every time the layer visibility is updated

            identifyTaskSetup();

            //refresh the legend

            legendDijit.refresh();

        }

 

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
thejuskambi
Occasional Contributor III

The reason you get error, if when click the "selectall", the event.srcElement.className is neither of the switch case value and hence the inputs will not be populated and you get error on line

var inputCount = inputs.length;

change it to

var inputCount=0, inputs && (inputCount = inputs.length);

but that may still not work of toggeling on/off, as individual checkbox change event will be responsible to updating it. you need to check the whole flow.

View solution in original post

10 Replies
LauraMiles1
Occasional Contributor III

Sorry, I've tried to format the syntax-highlighting twice, but it seems it's unformatting itself.

0 Kudos
thejuskambi
Occasional Contributor III

that query is part of jQuery. check the require arguments if you have defined another query there than that might be conflicting with jQuery.

and yes you are right query(".enviro_list_item") returns all the nodes where that class has been defined.

LauraMiles1
Occasional Contributor III

Hi Thejus, thanks for answering. I'm not using query anywhere else in my code, is that what you meant?

So if query(".enviro_list_item") is polling that class, do you know why it seems to be failing when using the "Select All" link to turn checkboxes on/off, but not when checking checkboxes directly? I'm confused because the code seems to know the checkboxes were changed, as it passes the switch statement successfully. If it gets to that point, from my understanding, all that has to happen next is to look at the enviro_list_item class, which doesn't require any further check or change event?

switch(event.srcElement.className) {
                case "cadastral_list_item":
                    var inputs = query(".cadastral_list_item");
                    var serviceLayer = layerCadastral;
                    break;
                case "enviro_list_item":
                    var inputs = query(".enviro_list_item");
                    var serviceLayer = layerEnvironment;
                    break;
            }
0 Kudos
thejuskambi
Occasional Contributor III

The reason you get error, if when click the "selectall", the event.srcElement.className is neither of the switch case value and hence the inputs will not be populated and you get error on line

var inputCount = inputs.length;

change it to

var inputCount=0, inputs && (inputCount = inputs.length);

but that may still not work of toggeling on/off, as individual checkbox change event will be responsible to updating it. you need to check the whole flow.

LauraMiles1
Occasional Contributor III

Thanks Thejus, you are correct - I thought I had checked that it was reaching the intended case in the switch statement but now that I check again, it is not.

I've tried adding into the jquery something to trigger the change event but it doesn't seem to be working. See line 12 below, do you see any reason this does not work? I've also tried changing lines 10 and 11 (see bottom codeblock) to:

$(targetSelectMenu).find(':checkbox').prop('checked', !checked).change();
$(this).data('checked', !checked).change();

But these don't work either. I can change things so that "inputs" gets populated in the jquery, but it would be more efficient if I could trigger the change event somehow.

My jquery:

$(".aSelectAll").click(function(){
    //cut off the "a" and "SelectAll" from the clicked link's id
    //example id would be 'aBIEAPSelectAll'
    var targetSelectAll = ((event.srcElement.id).replace("SelectAll", '')).slice(1);
    //piece together the id of the menu targeted
    //example result would be "#divMenuBIEAP
    var targetSelectMenu = "#divMenu" + targetSelectAll;
    //find all the checkboxes in the divMenu and toggle them
    var checked = $(this).data('checked');
    $(targetSelectMenu).find(':checkbox').prop('checked', !checked);
    $(this).data('checked', !checked);
    $(targetSelectMenu).find(':checkbox').trigger('change');
    //run the function to update the visibility of layers
    updateLayerVisibility();
});
0 Kudos
thejuskambi
Occasional Contributor III

The value of targetSelectMenu is wrong.

targetSelectAll will be equal to 'aBIEAP', but you are looking for 'BIEAP' so the resulting targetSelectMenu will be "#divMemuaBIEAP" which does not exist.

LauraMiles1
Occasional Contributor III

var targetSelectAll = ((event.srcElement.id).replace("SelectAll", '')).slice(1);

the .slice(1) part is cutting off the 'a' at the beginning, the result does end up as just BIEAP or FREMP

If I throw in an alert box showing targetSelectAll, the result shows correctly

See this jsfiddle, which doesn't work very well ("on(document.body, ".enviro_list_item:change", updateLayerVisibility);" doesn't seem to be working, though it does in my map).

0 Kudos
thejuskambi
Occasional Contributor III

Sorry for jumping the gun there. Could you comment out the line 14 updateLayerVisibility();  and let me know what happens.

0 Kudos
LauraMiles1
Occasional Contributor III

No worries, I appreciate your help very much. If I comment out line 14, the code never reaches the updateLayerVisibility function. That is if using either the .trigger('change') or .change(), as I specified above. So this leads me to believe neither of these methods are actually triggering the change event?

0 Kudos