Sven Sven - 5 months ago 246
Javascript Question

Google Maps API Multiple Markers with Infowindows - click events conflicting

I'm trying to have a map with multiple markers each with an infowindow.
Nothing fancy so far.

All infowindows should open onload.
No problem.

And every infowindow should close if I click


  1. on its own marker

  2. on the X in its infowindow.



The latter is also no problem.

But if I click on the markers it behaves not as it should.

The page is loaded. The infowindows are open. Now I click Marker 1 and it closes the infowindow of Marker 2. If I click again Marker 1 an second infowindow opens on Marker 1. The "initial" infowindow on Marker 1 can only be closed with the X in the infowindow.

If I close all infowindows via the X then I can can open and close each infowindow via their markers.
BUT: Opened infowindows will be closed from a click on the other marker, which is not what I want.
Only a click on their own marker should open and close the infowindow.

Here is my code:



<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Circles</title>
<style>
html, body {
height: 100%;
margin: 0px;
padding: 0px
}
#map-canvas {
height: 500px;
width:800px;
margin: 0px;
padding: 0px
}
</style>
<script>
function initialize() {
var infos = [];
var locations = [
['Marker 1', 54.08655, 13.39234, 2],
['Marker 2', 53.56783, 13.27793, 1]
];

var map = new google.maps.Map(document.getElementById('map-canvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
}

});

var bounds = new google.maps.LatLngBounds();

for (i = 0; i < locations.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map,
content: locations[i][0]
});

bounds.extend(marker.position);

var openedInfoWindow = null;

var infowindow = new google.maps.InfoWindow();

google.maps.event.addListener(marker, 'click', (function() {
console.log('Klick! Marker='+this.content);
if(openedInfoWindow != null){
openedInfoWindow.close();
openedInfoWindow = null;
}else{
infowindow.setContent(this.content);
infowindow.open(map, this);
openedInfoWindow = infowindow;
google.maps.event.addListener(infowindow, 'closeclick', function() {
openedInfoWindow = null;
});
}

}));




google.maps.event.trigger(marker, 'click');
}

map.fitBounds(bounds);

var listener = google.maps.event.addListener(map, "idle", function () {
map.setZoom(8);
google.maps.event.removeListener(listener);
});
}
function loadScript() {
var script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&' + 'callback=initialize';
document.body.appendChild(script);
}

window.onload = loadScript;
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>





And here is a link to the jsfiddle

It seems that the click events are conflicting, but in the moment I don't know how to change this.
Any ideas?
Thanks.

This post didn't address my problem (please correct me if I'm wrong). The infowindows in it behave as follows: if you open a new infowindow via click on its marker the already opened infowindow of another marker is closed. That's not what I want. Only a click on its own marker should close a infowindow not a click on another marker.

Answer

The post to which you link does contain the solution: "function closure". You just need to extend it to include the infowindow for each marker since you have a unique infowindow for each marker instead of a global infowindow shared among all the markers.

for (i = 0; i < locations.length; i++) {
    var marker = new google.maps.Marker({
        position: new google.maps.LatLng(locations[i][1], locations[i][2]),
        map: map,
        content: locations[i][0]
    });
    var infowindow = new google.maps.InfoWindow();
    google.maps.event.addListener(marker, 'click', (function (marker, i, infowindow) {
        return function () {
            console.log('Klick! Marker=' + this.content);
            infowindow.setContent(this.content);
            infowindow.open(map, this);
        };
    })(marker, i, infowindow));
    bounds.extend(marker.position);

    google.maps.event.trigger(marker, 'click');
}

working fiddle

code snippet:

function initialize() {
  var infos = [];
  var locations = [
    ['Marker 1', 54.08655, 13.39234, 2],
    ['Marker 2', 53.56783, 13.27793, 1]
  ];

  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    zoomControl: true,
    zoomControlOptions: {
      style: google.maps.ZoomControlStyle.SMALL
    }

  });

  var bounds = new google.maps.LatLngBounds();

  for (i = 0; i < locations.length; i++) {
    var marker = new google.maps.Marker({
      position: new google.maps.LatLng(locations[i][1], locations[i][2]),
      map: map,
      content: locations[i][0]
    });
    var infowindow = new google.maps.InfoWindow();
    google.maps.event.addListener(marker, 'click', (function(marker, i, infowindow) {
      return function() {
        console.log('Klick! Marker=' + this.content);
        infowindow.setContent(this.content);
        infowindow.open(map, this);
      };
    })(marker, i, infowindow));
    bounds.extend(marker.position);

    google.maps.event.trigger(marker, 'click');
  }

  map.fitBounds(bounds);

  var listener = google.maps.event.addListenerOnce(map, "idle", function() {
    map.setZoom(8);
  });
}

function loadScript() {
  var script = document.createElement('script');
  script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&' + 'callback=initialize';
  document.body.appendChild(script);
}

window.onload = loadScript;
html,
body {
  height: 100%;
  margin: 0px;
  padding: 0px
}
#map-canvas {
  height: 500px;
  width: 800px;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map-canvas"></div>