0

I have a FeatureGroup that serves as a container for imageOverlays. Normally a popup opens when one of the image overlays is clicked. Now at some times I don't want this to happen, and I can't figure out how to set the Group or the objects within temporaily to noninteractive.

I tried this function

L.Layer.prototype.setInteractive = function (interactive) {
    if (this.getLayers) {
        this.getLayers().forEach(layer => {
            layer.setInteractive(interactive);
        });
        return;
    }
    if (!this._path) {
        return;
    }
    this.options.interactive = interactive;
    if (interactive) {
        L.DomUtil.addClass(this._path, 'leaflet-interactive');
    } else {
        L.DomUtil.removeClass(this._path, 'leaflet-interactive');
    }
};

found here: https://github.com/Leaflet/Leaflet/issues/5442

and then

overlayGroup.eachLayer(function(layer){                                                             
    layer.setInteractive(false);
});

but to no avail. I can still click them and the popups open. Logging the Group to console shows me this: console log

but there's too much going on for someone still new to JS to make much sense of it. At some level interactive seems to be set to true while on another to false, but where exactly and what to do with this information... well, that's where I need your help!

Or am I on the completely wrong path and there's a way simpler method to prevent popup of this group to open?

UPDATE: I tried the version from @seth-lutske but it's still not working. I added some simple console logs to see what's happening:

L.Layer.include({

    setInteractive: function (interactive) {
        console.log("set");
       if (this.getLayers) {
          this.getLayers().forEach(layer => {
            console.log("loop");
             layer.setInteractive(interactive);
          });
          return;
       }
 
       if (interactive) {
        console.log("isinteractive");
        L.DomUtil.addClass(this.getElement(), 'leaflet-interactive');

       } else {
        console.log("notinteractive");
          L.DomUtil.removeClass(this.getElement(), 'leaflet-interactive');
       }
 
   }
 
 })

Now when I do group.setInteractive(false); it never goes into the 'isinteractive' part of the if clause: enter image description here

so in order to figure out where the problem is, have some more code of how I construct the group and call the function:

   function addAllDetailMaps(detailMaps){
        detailMaps.forEach(function (item) {
            var detailMapBounds = JSON.parse(decodeURIComponent(item.detail_map_bounds));   //the bounds are stored as an encoded string - here we have to revert it
            createDetailMap(item.detail_map_name, detailMapBounds, item.detail_map_start_zoom, item.detail_map_end_zoom);
        });
    }

    //creates one detail map image overlay
    function createDetailMap(name, detailMapBounds, startZoom, endZoom){
        window['detailMap'+name] = L.imageOverlay(mapPath+'detail-maps/'+name+'/'+name+'.png?rand='+simpleRandom(), [detailMapBounds._northEast, detailMapBounds._southWest], {
           interactive: true                       
        }).bindPopup(detailMapPopup(name, detailMapBounds, startZoom, endZoom)).addTo(map).addTo(detailMapsGroup); 
    }

In the popup is a button to edit the shape of the image. For this I replace it with distortableImageOverlay and want to prohibit clicks on any other image while this is going on.

function editDetailMapShape(){
    bounds = $("#detail_map_bounds").val();                                                                     //get the stringyfiedBounds from the hidden popup form input field - because handing it over in the onclick function does not work
    name = $("#detail_map_name").val();                                                                         //same here for the detail map name
    map.closePopup();                                                                                           //close the popup because we want to interact with the image below
    map.removeLayer(window['detailMap'+name]);
    detailMapsGroup.setInteractive(false);
    tmpImg =  L.distortableImageOverlay(mapPath+'detail-maps/'+name+'/'+name+'.png?rand='+simpleRandom(), {
        corners: getCornersFromBounds(JSON.parse(decodeURIComponent(bounds))),
        editable: true,
        mode: 'drag',
        actions: [L.DragAction, L.ScaleAction, L.RestoreAction, L.LockAction],
    }).addTo(map);
}

1 Answer 1

2

You were pretty dang close. When we want to extend or alter prototypes in leaflet, we use the .extend and .include functions on the prototype class itself. So you'd want to do this:

L.Layer.include({

   setInteractive: function (interactive) {

      if (this.getLayers) {
         this.getLayers().forEach(layer => {
            layer.setInteractive(interactive);
         });
         return;
      }

      if (interactive) {
         L.DomUtil.addClass(this.getElement(), 'leaflet-interactive');
      } else {
         L.DomUtil.removeClass(this.getElement(), 'leaflet-interactive');
      }

  }

})

Note this only works for elements that have a getElement() method. It may need to be adjusted for path type objects, but this should work for your image overlays and markers.

Working codesandbox

4
  • Thank you! I'm still failing to make it work, but it's getting real late here and I'll try again tomorrow when I'm well rested. Not quite sure yet I'm doing differently than in your working example, but if I don't get it to work after a good nights sleep, I'll update my question with the code parts where I create the group and the overlays. Maybe there's the problem...
    – Merion
    Commented Aug 31, 2020 at 23:40
  • Still not working, not sure why though. I added more code to the question - may how I create the group is the problem? You seem to do it slightly different, with creating a layers array first, I build it in a loop.
    – Merion
    Commented Sep 1, 2020 at 23:06
  • The code is a bit messy...It looks like you're adding the layer twice. Once to the map, and once to detailMapsGroup. Why? There's a lot of room for unexpected behavior there. I would try to neaten things up by adding each detailMap to the detailMapsGroup, then adding the group all at once. The setInteractive method that I showed you worked, I think at this point its all in the implementation. If you make a reproducable example of your complete setup (or the relevant parts) with a codesandbox, we can better help debug your issue. Commented Sep 1, 2020 at 23:38
  • I'm not doubting your code, it's clear the problem lies with my implementation. And sorry for the messy code, I'm still a (self-taught) beginner who wrote his first "Hello World" three month ago. I know I need to work on my code style. The double adding of the detailMap to the group and the map was obviously a mistake, but unfortunately not the one that's causing the setIntertactive to fail. I'll keep trying to find that error tonight and if not, I'll put the essential code in a codesandbox. Also: Thank you!
    – Merion
    Commented Sep 2, 2020 at 12:54

Your Answer

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

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