2

I am trying to build a Leaflet map. I already built custom checkboxes, the map itself, and an empty div which display data from a GeoJSON file when clicking on markers.

  • I would like to know how to uncheck filter/remove markers from the map when clicking on a second filter. All examples I see with checkbox are for multiple selections. I know I can add or remove Layers, but I'm using layerGroup and can't manage to do it.

  • I'm also trying to insert a "reset" or "show all" checkbox that would show or hide all markers.

I'm on this a whole day now.

Here is my js code...

$(document).ready(function(){
          const layers = {
            active: [],
            glucocerebrosidaseLayer: new L.LayerGroup(),
            gbaLayer: new L.LayerGroup(),
            gl1Layer: new L.LayerGroup(),
            SphingomyelinaseacideLayer: new L.LayerGroup(),
          };

              var cartoDb =  L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
            subdomains: 'abcd',
            maxZoom: 19});


            var glucocerebrosidaseIcon = L.AwesomeMarkers.icon({
                prefix: 'fa', //font awesome rather than bootstrap
                markerColor: 'red', // see colors above
                iconColor:'white',
                icon: 'ambulance' //http://fortawesome.github.io/Font-Awesome/icons/
            });
            var gbaIcon = L.AwesomeMarkers.icon({
                prefix: 'fa', //font awesome rather than bootstrap
                iconColor:'white',
                markerColor: 'green', // see colors above
                icon: 'ambulance' //http://fortawesome.github.io/Font-Awesome/icons/
            });
            var gl1Icon = L.AwesomeMarkers.icon({
                prefix: 'fa', //font awesome rather than bootstrap
                iconColor:'white',
                markerColor: 'blue', // see colors above
                icon: 'ambulance' //http://fortawesome.github.io/Font-Awesome/icons/
            });

            var sphingomyelinaseIcon = L.AwesomeMarkers.icon({
                prefix: 'fa', //font awesome rather than bootstrap
                iconColor:'white',
                markerColor: 'darkred', // see colors above
                icon: 'ambulance' //http://fortawesome.github.io/Font-Awesome/icons/
            });
        var map = L.map('map')
            .addLayer(cartoDb)
            .setView([46.85, 2.3518], 6); // LIGNE 14



        function onEachFeature(feature, layer) {

                    var html = '';
                    if (feature.properties.Description) {
                        html += '<p>' + feature.properties.Description + '</p>';
                    }
                    if (feature.properties.Envoi) {
                        html += '<p>' + feature.properties.Envoi + '</p>';
                    }
                    if (feature.properties.Mode) {
                        html += '<p>' + feature.properties.Mode + '</p>';
                    }
                    if (feature.properties.Laboratoire) {
                        html += '<p>' + feature.properties.Laboratoire + '</p>';
                    }
                    if (feature.properties.Chu) {
                        html += '<p>' + feature.properties.Chu + '</p>';
                    }
                    if (feature.properties.Adresse) {
                        html += '<p>' + feature.properties.Adresse + '</p>';
                    }
                    if (feature.properties.Cp) {
                        html += '<p>' + feature.properties.Cp + '</p>';
                    }
                    if (feature.properties.Professeur) {
                        html += '<p>' + feature.properties.Professeur + '</p>';
                    }
                    if (feature.properties.Tel) {
                        html += '<p>' + feature.properties.Tel + '</p>';
                    }
                    if (feature.properties.Fax) {
                        html += '<p>' + feature.properties.Fax + '</p>';
                    }
                    if (feature.properties.Mail) {
                        html += '<p>' + feature.properties.Mail + '</p>';
                    }
                    if (feature.properties.Renseignement) {
                        html += '<p>' + feature.properties.Renseignement + '</p>';
                    }

                    layer.on('click', function () {
                        $('#layer_infos .fill').html(html);
                    })

                    $('input[type="checkbox"]').on('click',function(){
                        $('#layer_infos .fill').html('<p>Cliquez sur une icône pour voir le détail</p>');

                    })

                    if ( L.Browser.mobile ) {   
                        layer.on('click', function () {
                        $('#infos').addClass("slide");
                        })

                        $('.hamburger').click(function(){
                            $(this).toggleClass("is-active");
                            $('#filters').toggleClass("slide");
                        })
                        $('.close').click(function(){
                            $('#infos').removeClass("slide");
                        })
                    }

                }


        var promise = $.getJSON("maladie.json");
                promise.then(function(data){
                 var allmaladies = L.geoJson(data);
        // based on the category assign a marker to the layer
          layers.glucocerebrosidaseLayer = L.geoJson(data, {
            filter: function(feature, layer) {
              return (feature.properties.Maladie === "glucocerebrosidase");
            },
            onEachFeature: onEachFeature,
            pointToLayer: function(feature, latlng) {
                return L.marker(latlng, {
                    icon: glucocerebrosidaseIcon
                })
            }
          })

          layers.gbaLayer = L.geoJson(data, {
            filter: function(feature, layer) {
              return (feature.properties.Maladie === "gba");
            },
            onEachFeature: onEachFeature,
            pointToLayer: function(feature, latlng) {
                return L.marker(latlng, {
                    icon: gbaIcon
                })
            }
          })

          layers.gl1Layer = L.geoJson(data, {
            filter: function(feature, layer) {
              return (feature.properties.Maladie === "gl1");
            },
            onEachFeature: onEachFeature,
            pointToLayer: function(feature, latlng) {
                return L.marker(latlng, {
                    icon: gl1Icon
                })
            }
          })

          layers.SphingomyelinaseacideLayer = L.geoJson(data, {
            filter: function(feature, layer) {
              return (feature.properties.Maladie === "Sphingomyelinase-acide");
            },
            onEachFeature: onEachFeature,
            pointToLayer: function(feature, latlng) {
                return L.marker(latlng, {
                    icon: sphingomyelinaseIcon
                })
            }
          })
            map.fitBounds(allmaladies.getBounds(), {
                    padding: [50, 50]
                });


        $('input[type="checkbox"]').on('change', function(e) {
            const layerName = e.target.name;

                // if a layer is already active, remove it from the map and the active array
            if (layers.active.includes(layerName)) {
              layers.active = layers.active.filter(layer => layer !== layerName);

              map.removeLayer(layers[layerName]);

            } else {
                    // add the layer to the map and to the active array
              layers.active.push(layerName);
              layers[layerName].addTo(map);

            }


          });
       });
     });

To check/uncheck checkbox I tried many snippets like

 $('input[type="checkbox"]').on('change', function() {
    $('input[type="checkbox"]').not(this).prop('checked', false);
 });

It works, I can select only one Checkbox at a time, but the markers of course stay on the map. I don't know how to link both..

To add a "show all" checkbox, I tried in many way

        $('#allmaladies').on('click',function(){
                 if (this.checked) {
                    layers[glucocerebrosidase].addTo(map);
                    layers[gl1].addTo(map);  
                   layers[ gba].addTo(map);
                    layers[sphingomyelinaseacide].addTo(map);
                }else{
                    map.removeLayer[glucocerebrosidase];
                    map.removeLayer[gl1];
                    map.removeLayer[gba];
                    map.removeLayer[sphingomyelinaseacide];
                     }
                })

this gives me nothing but error message : "Uncaught TypeError: Cannot read property 'addTo' of undefined"....

EDIT Here is my HTML code:

<div>
    <input type="checkbox" class="gaucher" id="1" name="gaucher[]" onchange="processCheck(this)">
    <label for="1">Glucocérébrosidase</label>
</div>
<div>
    <input type="checkbox" class="gaucher" id="2" name="gaucher[]" onchange="processCheck(this)">
  <label for="2">Gêne GBA</label>
</div>                          
<div>
    <input type="checkbox" class="gaucher" id="3" name="gaucher[]" onchange="processCheck(this)">
    <label for="3">Lyso GL1</label>
</div>
<div>
    <input type="checkbox" class="gaucher" id="4" name="gaucher[]" onchange="processCheck(this)">
    <label for="4">Chito</label>
</div>                      
<div>
    <input type="checkbox" class="gaucher" id="5" name="gaucher[]" onchange="processCheck(this)"
    <label for="5">CCL 18</label>
</div> 

I didn't understand if your code had to replace the input click function. I put it after to try, changed the html but the markers disappear from the map, with no error message. I guess it's a syntax error somewhere ?

1 Answer 1

1

This is answer to your first question, where only one group layer can be selected at a time. It's one of many approaches possible.

Solution is based on giving each input checkbox element id value that serves as an index to corresponding layers array which contains layer objects.

When checkbox is checked, first previously selected layer (if existing) is removed and corresponding checkbox unchecked, then new layer is added and it's id stored in selId global variable. When checkbox is unchecked, corresping layer is removed and selId set to null.

<input type="checkbox" id="1" onchange="processCheck(this)"> Layer 1<br>
<input type="checkbox" id="2" onchange="processCheck(this)"> Layer 2<br>
<input type="checkbox" id="3" onchange="processCheck(this)"> Layer 3<br>
<input type="checkbox" id="4" onchange="processCheck(this)"> Layer 4
.
.
.
var layerArray = [layers.glucocerebrosidaseLayer, layers.gbaLayer, layers.gl1Layer, layers.SphingomyelinaseacideLayer];

selId = null;

function processCheck(checkbox) {
  var checkId = checkbox.id;

  if (checkbox.checked) {
    if (selId != null) {
      map.removeLayer(layerArray[selId - 1]);
      document.getElementById(selId).checked = false;
    }
    layerArray[checkId - 1].addTo(map);
    selId = checkId;
    }
  else {
    map.removeLayer(layerArray[checkId - 1]);
    selId = null;
  }
}

EDIT: I edited example to correspond to your layer naming and input fields ids. Here you can see working JSFiddle: https://jsfiddle.net/TomazicM/p5nL6xjc/

5
  • waouh !Thank you very much TomazicM, I'll try your code and get back to you !! thanks!!
    – blogob
    Commented Apr 3, 2020 at 11:25
  • Finaly I tried in many ways, replacing the code, putting your code inside my click function, outside, at the begining or at the end, but it doesn't work for me. I also replaced the input IDs but I throws me errors like "index.html:74 Uncaught ReferenceError: processCheck is not defined" so I put all my js code directly in the hml code at the end of the file, but the checkboces don't work anymore..Thank you anyway, your code is very readable and I understand it, so I'll continue to try and come back to post the working code, of course If I find what's wrong !! Thanks
    – blogob
    Commented Apr 5, 2020 at 9:19
  • If you edit your question and include also the HTML part of your code where you define input checkbox fields, I might help you further.
    – TomazicM
    Commented Apr 5, 2020 at 9:37
  • I modified the code a bit to correspond to your code a bit more and added JSFiddle example.
    – TomazicM
    Commented Apr 5, 2020 at 17:43
  • Thank you so much for your help Tomazic ! I'll try your code this week and let you know if I succeeded. Anyway, thank you very much for spending time on this!!
    – blogob
    Commented Apr 6, 2020 at 23:24

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