1

As you can see, I'm iterating into a json object containing the markers info, like this:

( I'm also using the infobox plugin, but it's not relevant for the question)

function drawAirports() {
    var markers = [];

    if ( markers != undefined) {
        for (var i = 0; i < markers.length; i++ ) {
            markers[i].setMap(null);
        }
        markers.length = 0;
    }

    var json = [
        {"id":8585885,"airport":"airport name", "lat" : "1.3", "long" : "1.33"},
        {"id":8585886,"airport":"airport name 1", "lat" : "-1.3", "long" : "1.33"},
        {"id":8585886,"airport":"airport name 2", "lat" : "42.5000", "long" : "1.5000"},
        {"id":8585886,"airport":"airport name 3", "lat" : "24.0000", "long" : "54.0000"},
        {"id":8585886,"airport":"airport name 4", "lat" : "17.0500", "long" : "-61.8000"},
        {"id":8585886,"airport":"airport name 5", "lat" : "18.2500", "long" : "-63.1667"},
        {"id":8585886,"airport":"airport name 6", "lat" : "24.0000", "long" : "54.0000"},
        {"id":8585886,"airport":"airport name 7", "lat" : "41.0000", "long" : "20.0000"},
        {"id":8585886,"airport":"airport name 8", "lat" : "40.0000", "long" : "45.0000"},
        {"id":8585886,"airport":"airport name 9", "lat" : "12.2500", "long" : "-68.7500"},
        {"id":8585886,"airport":"airport name 10", "lat" : "-12.5000", "long" : "18.5000"},
        {"id":8585886,"airport":"airport name 11", "lat" : "35.0000", "long" : "105.0000"},
        {"id":8585886,"airport":"airport name 12", "lat" : "-90.0000", "long" : "0.0000"},
        {"id":8585886,"airport":"airport name 13", "lat" : "34.0000", "long" : "-64.0000"},
        {"id":8585886,"airport":"airport name 14", "lat" : "-14.3333", "long" : "-170.0000"},
        {"id":8585886,"airport":"airport name 15", "lat" : "47.3333", "long" : "13.3333"},
        {"id":8585886,"airport":"airport name 16", "lat" : "-27.0000", "long" : "133.0000"},
        {"id":8585886,"airport":"airport name 17", "lat" : "12.5000", "long" : "-69.9667"}
    ];

    var airports = eval(json);

    for (var i = 0; i < airports.length; i++) {

        var airport = airports[i];

        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(airport.lat, airport.long),
            map: map,
            title: airport.airport,
            icon: 'img/gmaps/marker.png',
            visible: true
        });

        infobox = new InfoBox({
             content: '<h3>'+airport.airport+'</h3><a class="info" href="">Información</a><a class="bags" href="">Equipajes</a>',
             disableAutoPan: false,
             maxWidth: 150,
             pixelOffset: new google.maps.Size(-212, -150),
             zIndex: null,
             boxStyle: {
                width: "280px"
            },
            closeBoxMargin: "0",
            closeBoxURL: "img/gmaps/close.png",
            infoBoxClearance: new google.maps.Size(1, 1)
        });

        google.maps.event.addListener(marker, 'click', function() {
            infobox.open(map, this);
            map.panTo(loc);
        });

        markers.push(marker);                       
    }
}

My problem is that each marker open the last ( number 17 ) infowindow,

What am I doing wrong?

Toni Michel Caubet
  • 19,333
  • 56
  • 202
  • 378

1 Answers1

3

So your problem is not with Google Maps API utilization, or the library, but with the way you use closures. You have global variable infobox, which is fine since you want only one infobox and close any infobox present on map before opening new one, but the way you have it infobox always points to the last one created, which is number 17, the last location. Just use Javascript closure and and create the infobox inside the listener code, leveraging the fact airport always contains the correct data because of the closure. This should work:

function drawAirports() {
  var markers = [];
  var infobox = new InfoBox({
      content: '',
      disableAutoPan: false,
      maxWidth: 150,
      pixelOffset: new google.maps.Size(-212, -150),
      zIndex: null,
      boxStyle: {
          width: "280px"
      },
      closeBoxMargin: "0",
      closeBoxURL: "img/gmaps/close.png",
      infoBoxClearance: new google.maps.Size(1, 1)
  });

  if (markers != undefined) {
      for (var i = 0; i < markers.length; i++) {
          markers[i].setMap(null);
      }
      markers.length = 0;
  }

  var json = [
      {"id": 8585885, "airport": "airport name", "lat": "1.3", "long": "1.33"},
      {"id": 8585886, "airport": "airport name 1", "lat": "-1.3", "long": "1.33"},
      {"id": 8585886, "airport": "airport name 2", "lat": "42.5000", "long": "1.5000"},
      {"id": 8585886, "airport": "airport name 3", "lat": "24.0000", "long": "54.0000"},
      {"id": 8585886, "airport": "airport name 4", "lat": "17.0500", "long": "-61.8000"},
      {"id": 8585886, "airport": "airport name 5", "lat": "18.2500", "long": "-63.1667"},
      {"id": 8585886, "airport": "airport name 6", "lat": "24.0000", "long": "54.0000"},
      {"id": 8585886, "airport": "airport name 7", "lat": "41.0000", "long": "20.0000"},
      {"id": 8585886, "airport": "airport name 8", "lat": "40.0000", "long": "45.0000"},
      {"id": 8585886, "airport": "airport name 9", "lat": "12.2500", "long": "-68.7500"},
      {"id": 8585886, "airport": "airport name 10", "lat": "-12.5000", "long": "18.5000"},
      {"id": 8585886, "airport": "airport name 11", "lat": "35.0000", "long": "105.0000"},
      {"id": 8585886, "airport": "airport name 12", "lat": "-90.0000", "long": "0.0000"},
      {"id": 8585886, "airport": "airport name 13", "lat": "34.0000", "long": "-64.0000"},
      {"id": 8585886, "airport": "airport name 14", "lat": "-14.3333", "long": "-170.0000"},
      {"id": 8585886, "airport": "airport name 15", "lat": "47.3333", "long": "13.3333"},
      {"id": 8585886, "airport": "airport name 16", "lat": "-27.0000", "long": "133.0000"},
      {"id": 8585886, "airport": "airport name 17", "lat": "12.5000", "long": "-69.9667"}
  ];

  var airports = eval(json);

  for (var i = 0; i < airports.length; i++) {
      (function (airport) {

          var marker = new google.maps.Marker({
              position: new google.maps.LatLng(airport.lat, airport.long),
              map: map,
              title: airport.airport,
              icon: 'img/gmaps/marker.png',
              visible: true
          });

          google.maps.event.addListener(marker, 'click', function () {
              infobox.setContent('<h3>' + airport.airport + '</h3><a class="info" href="">Información</a><a class="bags" href="">Equipajes</a>');
              infobox.open(map, this);
          });

          markers.push(marker);
      })(airports[i]);
  }
}
Matej P.
  • 5,303
  • 1
  • 28
  • 44
  • If you want to know more about closures: http://www.w3schools.com/js/js_function_closures.asp – Matej P. May 09 '16 at 10:42
  • Still this is probably not the way you should do it... You better create only one instance of the InfoBox and use the `setContent` method to update the contents. – MrUpsidown May 09 '16 at 11:06
  • @MrUpsidown I have updated my answer according to you suggestion, but I must say there are plenty other improvements which can be done. Same with most of code examples here on SO. I have also included infobox in the scope of the function so the global scope is not polluted. But I still think It's really petty to pick up on some detail and down-vote, considering that my answer was demonstrating wrong use of scope not the most feasible way to achieve what the user wanted. – Matej P. May 09 '16 at 11:57
  • And now it's a better answer. And I removed my downvote. And I think it's a pretty good way to push people to update/improve their answers ;-) – MrUpsidown May 09 '16 at 12:37
  • 1
    Btw. with only one InfoBox, I don't think you need the `if(infobox) infobox.close();` line if it works the same way than the standard infowindow. – MrUpsidown May 09 '16 at 15:27
  • @MrUpsidown The close() method only removes listeners and sets map to null. So yes, it seems it's not needed. I have tested locally and it works without it. I have updated the answer, thanks. – Matej P. May 09 '16 at 19:29