Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Materialize CSS not showing multiple checkboxes with Leaflet web-mapping overlays

I am using Materialize 0.97.7 with Leaflet 1.0.1 (latest)

<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet-src.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.css">

When I try to create an overlay with multiple checkboxes to toggle items, no checkbox appears, only labels, which work as a toggle but I want either checkboxes or switches. If I switch CSS cdn to another framework eg Bootstrap, they appear.

Leaflet code for debudding in case someone is interested: http://leafletjs.com/reference-1.0.0.html#layergroup

// items to toggle
var myItems = new L.LayerGroup();
// bind popup to each item once checkbox is selected
L.marker([lat, lon]).bindPopup('Item').addTo(myItems);
// create overlays multi-checkbox selection
var overlays = {
    Items = myItems
};
// add overlays to the web-map
L.control.layers(null, overlays).addTo(map);

This is obviously not a Leaflet issue as it works fine with other CSS

Can anyone offer a fix?

Thanks

like image 393
Dazzle Avatar asked Oct 20 '16 12:10

Dazzle


1 Answers

It looks like the visual checkbox from Materialize CSS is an artifact created by Materialize CSS, within the <label> tag of your input, whereas the actual <input type="checkbox" /> is hidden away.

That is what happens with the Leaflet Layers Control: the <input> is hidden away, but since Leaflet does not associate a proper <label> to that <input> (or at least, not the way Materialize CSS expects it), Materialize CSS has no placeholder to create the visual replacement.

As for your comment, I am not sure you can "opt out" so easily from a stylesheet. In your specific case, you could try to override the Materialize CSS rules for Leaflet checkboxes, in order to avoid them being hidden away:

input[type="checkbox"].leaflet-control-layers-selector {
  position: inherit;
  left: inherit;
  opacity: inherit;
}

enter image description here

Demo: https://jsfiddle.net/3v7hd2vx/289/

However, the last part of your comment is indeed do-able, and can lead to a more interesting result: one of the beauties of Leaflet code structure is that you can quite easily extend its classes or even just override some methods.

See the Extending Leaflet: Class Theory tutorial for example.

In your case, that would simply require making sure there is a proper <label> associated to the Layers Control <input type="checkbox" />:

L.Control.Layers.include({
  _addItem: function(obj) {
    var label = document.createElement('label'),
        checked = this._map.hasLayer(obj.layer),
        input;

    if (obj.overlay) {
      input = document.createElement('input');
      input.type = 'checkbox';
      input.className = 'leaflet-control-layers-selector';
      input.defaultChecked = checked;
    } else {
      input = this._createRadioElement('leaflet-base-layers', checked);
    }

    input.layerId = L.stamp(obj.layer);

    // Create an explicit ID so that we can associate a <label> to the <input>.
    var id = input.id = 'leaflet-layers-control-layer-' + input.layerId;

    L.DomEvent.on(input, 'click', this._onInputClick, this);

    // Use a <label> instead of a <span>.
    var name = document.createElement('label');
    name.innerHTML = ' ' + obj.name;
    name.setAttribute('for', id); // Associate the <label> to the <input>.

    var holder = document.createElement('div');

    label.appendChild(holder);
    holder.appendChild(input);
    holder.appendChild(name);

    var container = obj.overlay ? this._overlaysList : this._baseLayersList;
    container.appendChild(label);

    this._checkDisabledLayers();
    return label;
  }
});

(most of the code is just duplicated from the original method, there are actually only 3 inserted or modified lines, as shown by the comments)

enter image description here

Demo: https://jsfiddle.net/3v7hd2vx/288/

With this, you let Materialize CSS do its job and create the checkbox replacement, so that the result is what you might have expected by including that library onto your page.

Demo with a Materialize CSS switch instead of the checkbox: https://jsfiddle.net/3v7hd2vx/290/

enter image description here

(similar method override concept as above, but slightly more complicated because you need to wrap the entire <label> and <input> with a <div> of class "switch" and add an extra "lever" placeholder).

like image 152
ghybs Avatar answered Nov 01 '22 22:11

ghybs