Leaflet – Clicking Markers from Cluster Layer Opens Same URL Issue

iconleafleturl

I have marker cluster layer in Leaflet. I want to open specific URL when individual marker is clicked, but every time I click on any marker the URL of the last marker is opened.

I've tried many things like:

window.open(this.win_url);
window.open(this.options.win_url);

etc. but nothing works. Can anybody help me?

This is what I got so far:

<!DOCTYPE html>
<html>
  <head>
    <title>Leaflet - Marker Click Event</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="http://leafletjs.com/dist/leaflet.css" />
    <!--[if lte IE 8]><link rel="stylesheet" href="../dist/leaflet.ie.css" /><![endif]-->
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>

    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/MarkerCluster.css" />
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/MarkerCluster.Default.css" />

    <script src="https://unpkg.com/[email protected]/dist/leaflet.markercluster.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>

    <style>
      #map {
        width: 800px;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script type="text/javascript">
      var addressPoints = [
        [-37.8210922667, 175.2209316333, "1", "https://url_address_01.com"],
        [-37.8210819833, 175.2213903167, "2", "https://url_address_02.com"],
        [-37.8210881833, 175.2215004833, "3", "https://url_address_03.com"],
        [-37.8211946833, 175.2213655333, "4", "https://url_address_04.com"],
        [-37.8209458667, 175.2214051333, "5", "https://url_address_05.com"],
        [-37.8208292333, 175.2214374833, "6", "https://url_address_06.com"],
      ];

      var map = L.map("map").setView([-37.82, 175.23], 13);
      L.tileLayer("https://{s}.tile.osm.org/{z}/{x}/{y}.png", {
        attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      }).addTo(map);
      var markers = L.markerClusterGroup();
      for (var i = 0; i < addressPoints.length; i++) {
        var a = addressPoints[i];
        var title = a[2];
        var win_url = a[3];
        var marker = L.marker(
          new L.LatLng(a[0], a[1]),
          {
            title: title,
          },
          { win_url: a[3] }
        );

        marker.on("click", function (evt) {
          window.open(win_url);
        });
        markers.addLayer(marker);
      }
      map.addLayer(markers);
    </script>
  </body>
</html>

Best Answer

Your solution always opens last url from addressPoints beacuse value win_url is just pointer to array a which is again just pointer to array addressPoints, and this pointer changes when you iterate and it finally points to the last element of addressPoints array.

To use actual win_url option value of clicked marker inside click processing function you have to use evt.target.options.win_url value.

Relevant part of the code could then look something like this:

var markers = L.markerClusterGroup();
for (var i = 0; i < addressPoints.length; i++) {
  var a = addressPoints[i];
  var title = a[2];
  var win_url = a[3];
  var marker = L.marker(new L.LatLng(a[0], a[1]), {
    title: title,
    win_url: a[3]
  });
  marker.on('click', function(evt){ 
    window.open(evt.target.options.win_url);
  });
  markers.addLayer(marker);
}