0

I have an JS object where the 1st value of each key is the checkbox id, 2nd is the API where the data is and the 3rd is the color

var layers={childcares: ["#childcares",'http://127.0.0.1:8000/childcare_data/','orange'], childcare_buff: ["#childcaresbuff","http://127.0.0.1:8000/childcare_buff_data/","orange"],
            religious: ["#religious","http://127.0.0.1:8000/religious_data/","blue"], religious_buff: ["#religiousbuff","http://127.0.0.1:8000/religious_buff_data/","blue"],
            park: ["#parks","http://127.0.0.1:8000/park_data/","green"],park_buff: ["#parksbuff","http://127.0.0.1:8000/park_buff_data/","green"],
            school: ["#schools","http://127.0.0.1:8000/school_data/","red"],school_buff: ["#schoolsbuff","http://127.0.0.1:8000/school_buff_data/","red"]
            };

now I have these two functions

    function color(feature, color_chosen, opacity){
        return{
        color: color_chosen,
        fillOpacity: opacity}
       };

this color one above is fairly simple and just sets the color

the legend_click one is where I am getting problems

    function legend_click(id,layer_api,color_layer) {
        $(id).click(function () {
          var layer_add=new L.GeoJSON.AJAX(layer_api,{
            style: color(layer_add,color_layer,0.8),
            onEachFeature: function(feature,layer_add){
             layer_add.bindPopup('<b>Buffer Type</b> = ' +feature.properties.buff+ '<br>'
                            +'<b>Address</b> = '+feature.properties.address+ '<br>' +'<b>Buffer Distance</b> = '+feature.properties.buff_dist)
                    }
                   }
                );
            if ($(id).prop('checked')==true) {
                layer_add.addTo(map);
                //map.fitBounds(layer_add.getBounds())
            }
            else if ($(id).prop('checked')==false) {
                console.log('noury') 
                map.removeLayer(layer_add);
            }
        })
    };

looping through the layers like this

for (var key in layers){
        console.log(layers[key])
        legend_click(layers[key][0],layers[key][1],layers[key][2])
    };

so in the map when I click on the checkbox the layer correctly gets added to the display but when I uncheck the checkbox is it throws NO error and prints out noury to the console but it does not remove the layer...

  • Problem is that with each click new layer is defined. When initially check bock is checked layer is defined and added to the map. When check box is then unchecked, new layer is created, map.removeLayer(layer_add); is applied to the new layer and initial layer stays intact on the map. – TomazicM Mar 11 at 18:08
  • ahhh okay I see what you are saying. so should I initialize the layer in the if checked statement? – ziggy Mar 11 at 18:38
  • Yes, and then save it to some array identifiable by id so you can remove it upon uncheck. – TomazicM Mar 11 at 18:47
  • @TomazicM I am having the hardest time with this. I tried storing layers in an JS Object but its not working as I planned – ziggy Mar 11 at 19:24
0

As I suggested in my comment, this could be one way of doing it:

var idArray = [];
var layerArray = [];

function legend_click(id, layer_api, color_layer) {
    $(id).click(function () {
        var layer_add;
        var i = idArray.indexOf(id);
        if (i < 0) {
          layer_add = new L.GeoJSON.AJAX(layer_api,{
            style: color(layer_add, color_layer, 0.8),
            onEachFeature: function(feature, layer_add){
              layer_add.bindPopup('<b>Buffer Type</b> = ' + feature.properties.buff + '<br>'
                            +'<b>Address</b> = ' + feature.properties.address+ '<br>' + '<b>Buffer Distance</b> = ' +feature.properties.buff_dist)
              }
            }
          );
          layerArray.push(layer_add);
          idArray.push(id);
          }
        else {
          layer_add = layerArray[i];
        };
        if ($(id).prop('checked') == true) {
          layer_add.addTo(map);
          }
        else if ($(id).prop('checked') == false) {
          map.removeLayer(layer_add);
        }
    })
};
  • awesome this works! one thing is I don't understand why you did this i = idArray.length - 1; – ziggy Mar 13 at 12:39
  • With push method new element is added to the end of array. Since indexes start at 0, it's index is number of array elements minus one. – TomazicM Mar 13 at 13:16
  • I know what its doing it just seems unnecessary because i is created in the scope of when the function is called...? – ziggy Mar 13 at 13:29
  • Not when id is not found in idArray and i has conseqently negative value. – TomazicM Mar 13 at 15:06
  • 1
    It looks like I need more (or less :) cofee. Of course it's not needed since it's not used after being calculated. I removed it. Thanks! – TomazicM Mar 13 at 18:09
0

This might help, it's a little different then your but works well. I use it in a sidebar or panel. Basically create a label and checkbox, in my case for the hospital layer called hosp. Note I used a "name" id.

The HTML checkbox:

<label class="container">Hospitals
    <input type="checkbox"  id="hosp" name="hosp" value="hosp"  >
</label>

The JavaScript that adds and adds/removes the layer from the map as checked or not.

document.querySelector("input[name=hosp]").addEventListener('change', function() {
    if(this.checked) map.addLayer(hosp)
      else map.removeLayer(hosp)
    })

remember to set the value to checked it you add it to the map on load, in my example, it's off.

Example: http://www.gistechsolutions.com/leaflet/DEMO/baseball/sports/sports.html

  • where would I initialize the geojson ajax? before this? and I set my checkbox to be unchecked when the page loads – ziggy Mar 11 at 18:35
  • Like I said, I did it a little different than you. Here is an example and write up of what I normally do for points. gistechsolutions.com/leaflet/DEMO/Simple/indexMap1.html I define each as a separate layer, then the checkbox see's them as separate layers to turn on/off. BTW since all your data is coming from the same database, and has the same fields, you could make just one service, and use a filter to define each layer and a GetColor function to show each different colors. The extra JavaScript won't make that much difference in page display speed. – Bill Chappell Mar 11 at 18:55
  • I was originally adding them as separate layers and it worked fine -- but I was just repeating the same code over and over so that is why i wrote this function...I will have a look at your link. thanks for the suggestions – ziggy Mar 11 at 19:25
  • Here is a 3000+ lines of code app. apps.health.ny.gov/statistics/cancer/environmental_facilities/… so you should be fine with what you are doing. – Bill Chappell Mar 11 at 19:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.