简体   繁体   中英

How to extend Leaflet Icon Class to add data-open attribute to marker HTML?

I'm trying to trigger some functionality based on the click of a marker on a GeoJSON layer in Leaflet. The eventual functionality I'm trying to implement is a flyout, or scroll out type modal populated from the individual feature's JSON attributes. Essentially, I'm trying to implement the functionality in this Tutsplus Tutorial with dynamic feature content based on the marker click.

I THINK I've figured out most of the pieces I need, but I'm struggling with how to add a data attribute, specifically data-open , to the individual marker. Building on an earlier question of mine I've realized it's not enough to just update a DOM element's CSS, but rather my app should be implementing changes based on data attributes to fully get the functionality I want.

From this question I know that this should be done by extending the L.Icon class that Leaflet provides, but the answer is a bit too terse for my current JS skills. I apologize for this effectively being a "ELI5" of a previously asked question, but I'm not sure where the options and slug come into function. I think they're implied by the question, rather than the answer I'm citing and being set on the marker itself.

Here's a simplified version of the the click handler on my markers, which grabs and zooms to location, gets feature info, and populates that info to a div. The zoom functionality works, as does extracting and placing the feature info, but I'm struggling with how to connect the functionality to trigger the modal and place the div with the feature info over the map.

function zoomToFeature(e) {
  var latLngs = [e.target.getLatLng()];
  var markerBounds = L.latLngBounds(latLngs);
  var street = e.target.feature.properties.str_addr;
  document.getElementById('street').textContent = street;
  mymap.fitBounds(markerBounds);
  //where the modal trigger should be
  document.getElementById('infoBox').classList.add('is-visible');
}

Here are the event listeners taken from the linked tutorial, which are currently not firing, but I have them working in a standalone implementation:

const openEls = document.querySelectorAll("[data-open]");
const closeEls = document.querySelectorAll("[data-close]");
const isVisible = "is-visible";
//this is the event I want to trigger on marker click
for (const el of openEls) {
  el.addEventListener("click", function() {
    const modalId = this.dataset.open;
    console.log(this);
    document.getElementById(modalId).classList.add(isVisible);
  });
}
for (const el of closeEls) {
  el.addEventListener("click", function() {
 this.parentElement.parentElement.parentElement.classList.remove(isVisible);
  });
}
document.addEventListener("click", e => {
  if (e.target == document.querySelector(".modal.is-visible")) {
    document.querySelector(".modal.is-visible").classList.remove(isVisible);
  }
});

So, where I'm trying to get is that when my markers are clicked, the trigger the modal to appear over the map. So, I think I'm missing connecting the marker click event with the event that triggers the modal. I think what's missing is adding the data attribute to the markers, or some way chain the events without the data attributes. As there's no direct way to add an attribute to the markers, I try to add slug option on my circle markers:

var circleMarkerOptions = {
    radius: 2,
    weight: 1,
    opacity: 1,
    fillOpacity: 0.8,
    slug: 'open',
}

and If I read the previously asked question's answer correctly, than extending the Icon Class this way should add a data-open attribute.

L.Icon.DataMarkup = L.Icon.extend({

    _setIconStyles: function(img, name) {
        L.Icon.prototype._setIconStyles.call(this, img, name);

        if (options.slug) {
            img.dataset.slug = options.slug;
        }
    }

});

A stripped down version of my code is here (thanks @ghybs). My full implementation pulls the markers from a PostGIS table. It's a bit hard to see in the Plunker, but this code adds my class to my modal, but doesn't trigger the functionality. It does trigger the visibility if the class is manually updated to modal.is-visible , but the current implementation which renders modal is-visbile doesn't, which I think is because the CSS is interpreted on page load(?) and not in response to the update via the dev tools, while the concatenated css class matches extactly(?). When I do trigger the modal via the dev tools, the close modal listeners don't seem to work, so I'm also missing that piece of the puzzle.

So, it's a work-around to setting the data attribute, but I realized I was shoe-horning a solution where it wasn't needed. Assuming someone ends up with the same mental block. Appropriate listeners on the modal close button and another function passed to the existing marker click listener produce the desired functionality.

const closeM = document.querySelector(".close-modal");
closeM.addEventListener("click", closeMe);
var modal = document.getElementById('infoBox');

and

function modalAction(){
    modal.style.display = 'block';
}
function closeMe(){
    modal.style.display = 'none';
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM