3
votes

I am having troubles with executing callback functions on markers (in my case they are circle and semiCircle markers). The marker context menu extends map's context menu with additional marker-specific operations. Map context menu callbacks are working properly. Marker additional menu options are shown, but I cannot execute the corresponding functions (for example getting Lat and Lon of a marker). The error in both variants that I tried (see below) is "Uncaught TypeError: Cannot read property 'getLatLng' of undefined".

Below is shown the code that I am using.

Markers are created from external JS file and stored in a layerGroup.

Variant 1 - Using event "contextmenu.show" as suggested in contextMenu documentation.

Creating layerGroups with Circle markers:

for(i in sites) {
var title = sites[i].ID,    
    loc = sites[i].loc,     
    object = sites[i].Type,
    marker = new L.circle(new L.latLng(loc), {radius: radsiteinit+50,color: 'gold', weight: 3, title: title, pane: "sitePane",
           contextmenu: true,contextmenuItems: [{text: 'Show Charts',index:0}, {separator: true, index: 1}]} ).
           bindPopup(object+': '+ title ).on('click', onClick);

    layerSites.addLayer(marker);
}

"contextmenu.show" event:

    mymap.on('contextmenu.show', function (event) {

    var latlngs = event.relatedTarget.getLatLng();

});

As mentioned above produced error is "Uncaught TypeError: Cannot read property 'getLatLng' of undefined". Also event is fired before user gets the chance to select and option from context menu. What I need is to fire the event after user selects some marker-specific options from context menu.

Variant 2 - With definition of callback function.

Creating layerGroups with Circle markers - the difference here from above is that I added callback function is context menu definition:

for(i in sites) {
var title = sites[i].ID,    
    loc = sites[i].loc,     
    object = sites[i].Type,
    marker = new L.circle(new L.latLng(loc), {radius: radsiteinit+50,color: 'gold', weight: 3, title: title, pane: "sitePane",
           contextmenu: true,contextmenuItems: [{text: 'Show Charts',callback:showCharts,index:0}, {separator: true, index: 1}]} ).
           bindPopup(object+': '+ title ).on('click', onClick);

    layerSites.addLayer(marker);
}

Callback function definition:

function showCharts(e) {

    var latlngs = e.relatedTarget.getLatLng();

};

The same error here.

I am very new to JavaScript, so I guess I do something wrong when I am trying to pass marker's reference to the function (var. 2) or event (var. 1).

Because I am stuck a lot, I would appreciate getting some advice.

Thank you in advance!

EDIT In the link you can find a JS Bin example of variant 2: JS Bin Example

1
Could you possibly provide a JSBin or JSFiddle with the minimum amount of code required to reproduce the error?Iavor

1 Answers

2
votes

A possible solution:

var circle = L.circle(new L.LatLng(-36.79, 174.7), {
  radius: 400,
  weight: 10,
  contextmenu: true,
  contextmenuItems: [{
    text: 'Circle 1',
    callback: function() {
      showCharts(circle);
    }
  }]
}).addTo(map);


function showCharts(circle) {
  console.log(circle.getLatLng().toString());
}

Key points:

  • Declare a variable and assign your circle marker to it (var circle = L.circle(...)).
  • Set the callback property to an anonymous function. Within that function, execute yourshowCharts method and pass it the circle variable as an argument (showCharts(circle)).

Here is a JSBin with a working example.

Update

For multiple circle markers, you can do something like this:

for (var i in sites) {
  var title = sites[i].Site,
    loc = sites[i].loc,
    marker = new L.circle(new L.latLng(loc), {
      radius: 100,
      contextmenu: true
    }).bindPopup('Site: ' + title);

  marker.options.contextmenuItems = [{
    text: 'Show Charts',
    callback: (function(marker) {
      return function() {
        showCharts(marker)
      }
    })(marker)
  }]

  layerSites.addLayer(marker);
}

The code makes use of closures to keep track of the correct marker variable within the loop.

Test it out in this JSBin.