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 ?

nmtoken
13.6k5 gold badges39 silver badges91 bronze badges
asked Apr 2, 2020 at 13:06

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/

answered Apr 2, 2020 at 20:19
5
  • waouh !Thank you very much TomazicM, I'll try your code and get back to you !! thanks!! 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 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. 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. 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!! Commented Apr 6, 2020 at 23:24

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.