Reputation: 5986
I have an increasingly complex Google map which plots thousands of points and clusters them. I have an infowindow opening when the user clicks one of the map markers and it all works great. However, one improvement I'd like to make is to force all other infowindows to close when a new one is opened so that only 1 infowindow can be open at once.
I've tried adding some code (if (infowindow) infowindow.close();
) into the listener function to do this, but I think the issue is wider in that I'm currently creating an infowindow for each marker, and there is no access to other infowindows on the event which opens a new one. So, from reading around this it would seem to be a better idea to have just one infowindow which gets reused rather than many.
Trouble is, the code is at the edge of what I can really understand, and my experiments in doing this so far have just broken everything.
The code I currently have is as follows:
var _iconCenter = new google.maps.MarkerImage('/css/img/map-marker.png',
new google.maps.Size(38, 48),
new google.maps.Point(0,0),
new google.maps.Point(19, 44));
var shadow = new google.maps.MarkerImage('/css/img/map-marker-shadow.png',
new google.maps.Size(57, 49),
new google.maps.Point(0,0),
new google.maps.Point(7, 44));
var _icon = '/css/img/map-marker-purple.png';
var infowindow;
var markersArray = [];
var map;
var currentPosition = 0;
var currentmarker;
var firstload = true;
var maploaded = false;
var interval = 5000;
var geocoder;
var stylez = [];
function initialize(items,loop,zoom) {
geocoder = new google.maps.Geocoder();
if (items.length > 0) {
var latlng = new google.maps.LatLng(items[0].Lat, items[0].Lng);
var myOptions = {
zoom: zoom,
center: latlng,
//mapTypeControl: false,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), myOptions);
map.setOptions({styles: stylez});
for (var i = 0; i < items.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(items[i].Lat, items[i].Lng),
title: items[i].Title,
icon: _icon,
shadow: shadow,
infocontent: items[i].Description
});
marker.setMap(map);
attachListener(marker,'marker:'+i);
markersArray.push(marker);
}
//set style options for marker clusters (these are the default styles)
mcOptions = {
gridSize: 44
}
var markerCluster = new MarkerClusterer(map, markersArray, mcOptions);
google.maps.event.addListener(map, "tilesloaded", function () {
if(loop == true){
SetLoop();
}
});
function attachListener(marker,content){
google.maps.event.addListener(marker, "click", function () {
var infowindow = new google.maps.InfoWindow();
map.setCenter(new google.maps.LatLng(marker.getPosition().lat(), marker.getPosition().lng()));
infowindow.setContent(content);
infowindow.open(map,this);
});
}
}
}
function SetLoop() {
//This will fire everytime map loads or recenteres
maploaded = true;
if (firstload) {
firstload = false;
Recenter();
}
}
function Recenter() {
//If previous iteration is not loaded completely, wait to avoid errors
//It could happen for slow internet connection
if (maploaded) {
maploaded = false;
} else {
//keep adding 1 second to interval for slow connection till page loads
interval = interval + 1;
setTimeout("Recenter()", interval);
return;
}
if (infowindow != null && currentmarker != null) {
//currentmarker.icon = _icon;
currentmarker.icon = _iconCenter;
currentmarker.setMap(map);
infowindow.close(map, currentmarker);
}
markersArray[currentPosition].icon = _iconCenter;
markersArray[currentPosition].setMap(map);
map.setCenter(new google.maps.LatLng(markersArray[currentPosition].getPosition().lat(), markersArray[currentPosition].getPosition().lng()));
infowindow = new google.maps.InfoWindow({
content: markersArray[currentPosition].infocontent,
size: new google.maps.Size(50, 50)
});
infowindow.open(map, markersArray[currentPosition]);
currentmarker = markersArray[currentPosition];
if (currentPosition >= markersArray.length - 1) {
currentPosition = 0;
} else {
currentPosition++;
}
if (markersArray.length > 1) {
setTimeout("Recenter()", interval);
}
}
Is the best way to re-use the infowindow or is it okay to do this another way? Any help in pointing me in the right direction here would be much appreciated, thanks folks!
Upvotes: 3
Views: 2921
Reputation: 9407
Remove the 'var infowindow' declaration from function attachListener(). If you declare it inside the function it becomes local to the function and you create a new instance each time you execute the function. so:
function attachListener(marker,content){
google.maps.event.addListener(marker, "click", function () {
// marker.getPosition() already returns a google.maps.LatLng() object
map.setCenter(marker.getPosition());
infowindow.close();
infowindow.setContent(content);
infowindow.open(map,this);
});
}
and instead, declare it as a global variable:
var _icon = '/css/img/map-marker-purple.png';
var infowindow = new google.maps.InfoWindow();
//...etc
so that you have only one infowindow object in the whole application
Upvotes: 9