90

I need to have only one InfoWindow open on my Google Map. I need to close all other InfoWindows before I open a new one.

Can someone show me how to do this?

Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
leo
  • 3,045
  • 5
  • 24
  • 23

12 Answers12

159

You need to create just one InfoWindow object, keep a reference to it, and reuse if for all the markers. Quoting from the Google Maps API Docs:

If you only want one info window to display at a time (as is the behavior on Google Maps), you need only create one info window, which you can reassign to different locations or markers upon map events (such as user clicks).

Therefore, you may simply want to create the InfoWindow object just after you initialize your map, and then handle the click event handlers of your markers as follows. Let's say you have a marker called someMarker:

google.maps.event.addListener(someMarker, 'click', function() {
   infowindow.setContent('Hello World');
   infowindow.open(map, this);
});

Then the InfoWindow should automatically close when you click on a new marker without having to call the close() method.

MatTheCat
  • 18,071
  • 6
  • 54
  • 69
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • I do this too but is it normal that the infoWindow takes like +1 second to open on the next marker? sometimes it doesn't open at all. I use the exact same code – MJB May 05 '12 at 18:05
  • Daniel, great idea!! before that i was trying to synchronize manually, but it show strange javascript errors (like "c is null" in main.js, or something like (123 out of range 43)). – Victor Apr 25 '13 at 19:08
31

Create your infowindow out of the scope so that you can share it.

Here is a simple example:

var markers = [AnArrayOfMarkers];
var infowindow = new google.maps.InfoWindow();

for (var i = 0, marker; marker = markers[i]; i++) {
  google.maps.event.addListener(marker, 'click', function(e) {
    infowindow.setContent('Marker position: ' + this.getPosition());
    infowindow.open(map, this);
  });
}
skarE
  • 5,880
  • 2
  • 23
  • 23
  • Thank you. Using "this" solved most of my problems. I still don't understand how to use custom content inside of setContent. E.g. in my marker loop, I create a contentHtml variable using the "i" variable and linking it to a database object. How can I pass that contentHtml variable in to the listener? – Ryan Oct 25 '11 at 10:27
  • In my case the window only opens when I use "this" in infowindow.open(map, this); Instead of "marker". Thx for sharing your solution. – ownking Mar 09 '12 at 13:21
  • I do this too but is it normal that the infoWindow takes like +1 second to open on the next marker? sometimes it doesn't open at all. I use the exact same code – MJB May 05 '12 at 18:06
14

I had the same problem but the best answer didn't solve it completely, what I had to do in my for statement was using the this relating to my current marker. Maybe this helps someone.

for(var i = 0; i < markers.length; i++){
    name = markers[i].getAttribute("name");
    address = markers[i].getAttribute("address");        
    point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));                                     
    contentString = '<div style="font-family: Lucida Grande, Arial, sans-serif;>'+'<div><b>'+ name +'</b></div>'+'<div>'+ address +'</div>';                    
    marker = new google.maps.Marker({                       
        map: map,
        position: point,
        title: name+" "+address,
        buborek: contentString 
    });                                     
    google.maps.event.addListener(marker, 'click', function(){
        infowindow.setContent(this.buborek); 
        infowindow.open(map,this); 
    });                                                         
    marker.setMap(map);                 
}
Bakudan
  • 19,134
  • 9
  • 53
  • 73
Ferenc Takacs
  • 597
  • 7
  • 8
6

a tad late, but I managed to have only one infowindow open by maken infowindow a global variable.

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

then inside the listner

infowindow.close();
infowindow = new google.maps.InfoWindow({   
    content: '<h1>'+arrondissement+'</h1>'+ gemeentesFiltered                           
});

infowindow.open(map, this);
user2827958
  • 357
  • 1
  • 4
  • 20
4

Declare a globar var selectedInfoWindow; and use it to hold the opened info window:

var infoWindow = new google.maps.InfoWindow({
    content: content
});

// Open the infowindow on marker click
google.maps.event.addListener(marker, "click", function() {
    //Check if there some info window selected and if is opened then close it
    if (selectedInfoWindow != null && selectedInfoWindow.getMap() != null) {
        selectedInfoWindow.close();
        //If the clicked window is the selected window, deselect it and return
        if (selectedInfoWindow == infoWindow) {
            selectedInfoWindow = null;
            return;
        }
    }
    //If arrive here, that mean you should open the new info window 
    //because is different from the selected
    selectedInfoWindow = infoWindow;
    selectedInfoWindow.open(map, marker);
});
IgniteCoders
  • 4,834
  • 3
  • 44
  • 62
0

You need to keep track of your previous InfoWindow object and call the close method on it when you handle the click event on a new marker.

N.B It is not necessary to call close on the shared info window object, calling open with a different marker will automatically close the original. See Daniel's answer for details.

Community
  • 1
  • 1
RedBlueThing
  • 42,006
  • 17
  • 96
  • 122
  • I know this is an old answer, and the v3 API was obscure at the time... But actually there's no need to call the `close()` method, if a single `InfoWindow` object is used. It will close automatically if the `open()` method is called again on the same object. – Daniel Vassallo Sep 15 '10 at 23:02
  • @daniel-vassallo Thanks for the note :) I have upvoted your answer accordingly, it is the most useful I think. – RedBlueThing Sep 16 '10 at 01:19
0

Basically you want one function that keeps reference to one new InfoBox() => delegate the onclick event. While creating your markers (in a loop) use bindInfoBox(xhr, map, marker);

// @param(project): xhr : data for infoBox template
// @param(map): object : google.maps.map
// @param(marker): object : google.maps.marker
bindInfoBox: (function () {
    var options = $.extend({}, cfg.infoBoxOptions, { pixelOffset: new google.maps.Size(-450, -30) }),
        infoBox = new window.InfoBox(options);

    return function (project, map, marker) {
        var tpl = renderTemplate(project, cfg.infoBoxTpl); // similar to Mustache, Handlebars

        google.maps.event.addListener(marker, 'click', function () {
            infoBox.setContent(tpl);
            infoBox.open(map, marker);
        });
    };
}())

var infoBox is assigned asynchronously and kept in memory. Every time you call bindInfoBox() the return function will be called instead. Also handy to pass the infoBoxOptions only once!

In my example I've had to add an extra param to the map as my initialization is delayed by tab events.

InfoBoxOptions

Tim Vermaelen
  • 6,869
  • 1
  • 25
  • 39
0

Here is a solution that doesn't need to create only one infoWindow to reuse it. You can continue creating many infoWindows, the only thing you need is to build a closeAllInfoWindows function, and call it before open a new infowindow. So, keeping your code, you just need to:

  1. Create a global array to store all the infoWindows

    var infoWindows = [];
    
  2. Store each new infoWindow in the array, just after the infoWindow = new...

    infoWindows.push(infoWindow);
    
  3. Create the closeAllInfoWindows function

    function closeAllInfoWindows() {
        for (var i=0;i<infoWindows.length;i++) {
            infoWindows[i].close();
        }
    }
    
  4. In your code, call to closeAllInfoWindows() just before open the infoWindow.

Regards,

Jortx
  • 707
  • 1
  • 7
  • 22
  • It works but is not a very good solution because you just keep adding info windows to the array, so there's the possibility to have an array with many occurrences of the same info window. – Wall-E Dec 30 '20 at 10:41
0

One smart easy way to do this with jQuery is the following :

            google.maps.event.addListener(marker, 'click', function (e) {
                jQuery(".gm-ui-hover-effect").click();
                marker.info.open(map, this);
            });

It will click on all the closing buttons amongst your tooltips.

Hugo Trial
  • 366
  • 5
  • 12
0

My approach allows you to toggle the infoWindow as well.

Global space

var infoWindow = new google.maps.InfoWindow();
infoWindow.setContent(contentString);

var lastInfoWindow;

Local space

marker.addListener("click", (e) => {
  if (lastInfoWindow === e.domEvent.srcElement) {
    infoWindow.close();
    lastInfoWindow = null;
  } else {
    infoWindow.open({
      anchor: marker,
      map,
      shouldFocus: false,
    });
    lastInfoWindow = e.domEvent.srcElement;
  }
});
Jens Törnell
  • 23,180
  • 45
  • 124
  • 206
-1

Solved it this way:

function window(content){
    google.maps.event.addListener(marker,'click', (function(){
        infowindow.close();
        infowindow = new google.maps.InfoWindow({
            content: content
        });
        infowindow.open(map, this);
    }))
}
window(contentHtml);
-6

Google Maps allows you to only have one info window open. So if you open a new window, then the other one closes automatically.

Kimmo Puputti
  • 260
  • 2
  • 7