Have just one InfoWindow open in Google Maps API v3 - javascript

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?

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.

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);
});
}

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);
}

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);

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);
});

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.

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

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:
Create a global array to store all the infoWindows
var infoWindows = [];
Store each new infoWindow in the array, just after the infoWindow = new...
infoWindows.push(infoWindow);
Create the closeAllInfoWindows function
function closeAllInfoWindows() {
for (var i=0;i<infoWindows.length;i++) {
infoWindows[i].close();
}
}
In your code, call to closeAllInfoWindows() just before open the infoWindow.
Regards,

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.

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;
}
});

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);

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

Related

Map not adding click event handlers to markers

The code below will add markers to my map. But the add Listener event never gets added to each marker.
var mapDiv = document.getElementById("google-map");
var infowindow = new google.maps.InfoWindow({
content: 'test'
});
var map = new google.maps.Map(mapDiv);
map.setCenter(new GLatLng(53.635784, 6.943359));
map.setZoom(5);
for (var i = 0; i < data.length; i++) {
var dataMarker = data[i];
var marker = new GLatLng(dataMarker.Latitude, dataMarker.Longitude);
map.addOverlay(new google.maps.Marker(marker, {
title: dataMarker.Name,
html: dataMarker.HtmlAttributes[0]
}));
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(this.html);
infoWindow.open(map, this);
});
}
What am I doing wrong?
Oh and I am using Maps v2.
You did not add any listener to marker.
var marker = new GLatLng(dataMarker.Latitude, dataMarker.Longitude);
marker is not a google.maps.Marker , it's a google.maps.LatLng , which will not respond to mouse-events, because it's not an UI-element, it's just a javascript-object
You created event listeners which are most probably connected with last marker.
You have to link info window with marker in separate function. Last part of your code should be written as:
addEventListener(marker, infoWindow, map);
}
function addEventListener(marker, infoWindow, map) {
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(marker.html);
infoWindow.open(map, marker);
});
}
See also An array of infoWindow in Google maps api and link with explanation about closures.
It looks like you have a mix of v2 and v3 code in that snippet, and so the whole thing is unlikely to work.
For example, you're using new google.maps.Infowindow (v3) in the same place as GLatLng.
My suggestion would be to change the bootstrap on the page to v3, and delete any references to v2 objects (like GLatLng). Make sure you're loading the API like this:
<script src="//maps.googleapis.com/maps/api/js?…"></script>

InfoWindow - Google map API

I try to add infowindows for all my markers. But I add only one InfoWindow for last marker.
Can you help me?
for (i = 0; i < events.length; i++) {
var contentString = '<div id="content">'+i+'bla-bla-bla</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var newMarker = new google.maps.Marker({
position: new google.maps.LatLng(events[i][1], events[i][2]),
map: map,
title: events[i][0]
});
newMarker.categorysassasas = 2;
newMarker.category = events[i][3];
markers.push(newMarker);
google.maps.event.addListener(newMarker, 'click', function() {
infowindow.open(map,newMarker);
});
}
found a similar solution to your question in this stackoverflow: Trying to bind multiple InfoWindows to multiple Markers on a Google Map and failing
Essentially all you'll have to do is wrap your addlistener function within another function to create a closure for your marker variable - so that it is bound to the infowindow. In your case, I believe you'll have to add the listenMarker function outside of your init() and pass in the variable for marker and infowindow, like so..
function listenMarker (marker, info)
{
// so marker is associated with the closure created for the listenMarker function call
google.maps.event.addListener(marker, 'click', function() {
info.open(map, marker);
});
}
and then in your for loop where you call the addlistener event, replace that with:
listenMarker(newMarker, infowindow);
That should do the trick.

Automatically opening marker info pane on google map

I've created a custom map with most things I want on it (custom icon and custom info bubble), however I can't find a solution to automatically open the markers info window on load, I've done alot of searching but can't seem to find anything the code I have so far is as follows, any help would be much appreciated:
function initialize() {
var myLatlng = new google.maps.LatLng(54.325109,-2.742226);
var myOptions = {
zoom: 15,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var countries = [
{
title:'Remedy',
lat:54.3210,
lon:-2.7438,
content:"<h2>Remedy</h2><p>address, <br />location, <br />postcode</p> <p><b>T:</b> 07595 153 835 <br /><b>E:</b> <a href='mailto:email'>email</a></p>"
}
];
for (var i = 0; i < countries.length; i++) {
var c = countries[i];
c.marker = new google.maps.Marker({
position: new google.maps.LatLng(c.lat, c.lon),
map: map,
icon: '/wp-content/themes/remedy/display_images/google_map_icon.png',
title: c.title});
c.infowindow = new google.maps.InfoWindow({content: c.content});
google.maps.event.addListener(c.marker, 'click', makeCallback(c));
}
function makeCallback(country) {
return function () {
country.infowindow.open(map, country.marker);
};
}
infowindow.open(map, marker);
}
Maybe it's not working because you just created the instance of the Map and didn't wait for the complete load of the map to open the InfoWindow.
Try something like this:
google.maps.event.addListenerOnce(map, 'tilesloaded', function(event) {
infowindow.open(map, marker);
});
According to the reference:
http://code.google.com/intl/en/apis/maps/documentation/javascript/reference.html#Map
tilesloaded - This event is fired when the visible tiles have finished loading.
Hmm, inforwindow does not refer to anything in your code, which is why it is not working.
Since you have one country in the list as of now you can do a quick test and intialize the infowindow variable with an actual info window, or better yet also since you have 1 item in the list, just define c to be outside the loop so you can access it and then open the popup passing it the map and the marker, something like this (assuming c has been defined outside the loop)
c.infowindow.open(map, c.marker);
var infowindow = new google.maps.InfoWindow({
content: "Test Route",
position: new google.maps.LatLng(38.8709866, -77.208055),
});
infowindow.open(map);

Preserving Nodes with Google InfoWindow and content_changed?

I'm trying to use Google Maps's InfoWindow with DOM nodes and preserve the nodes between InfoWindow swaps without having to create an explicit content store outside of the DOM. Unfortunately, when an InfoWindow's content is changed the previous content seems to be destroyed, this is unfortunate as it makes it impossible to switch back to the previous node. To make matters worse, it appears that the InfoWindow's content_changed event has no reference to the previous content, as the MVC events have no event args. Furthermore, as mentioned here, referencing the content property within the function references only the current value, and not the previous value, thus it would seem the previous value is gone for all tense and purposes.
For example, say you wanted to do this, assume we already have a map, and LatLng in myLatLng, myLatLng2. Note the only reference to shortlived node was added to the dom.
document.body.appendChild(document.createElement('div')).id = 'shortlived';
document.getElementById('shortlived').innerHTML = 'I will pass soon...';
var infowindow = new google.maps.InfoWindow();
var marker1 = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Marker1"
});
var marker2 = new google.maps.Marker({
position: myLatlng2,
map: map,
title:"Marker2"
});
google.maps.event.addListener(marker1, 'click', function() {
infoWindow.setContent(document.getElementById('shortlived'));
infowindow.open(map, marker1);
});
google.maps.event.addListener(marker2, 'click', function() {
infoWindow.setContent('Some Text');
infowindow.open(map, marker2);
});
You'll notice that if you click on marker1 you see the shortlived node, then if you click on marker2 it goes away, but when you click marker1 again, you won't get shortlived, you may get 'Some Text' or you may get nothing, but in either case, shortlived is gone. In my case I would like to ideally do the following:
google.maps.event.addListener(infoWindow, 'content_changed' function(e){
//where e.content is the previous content
document.body.appendChild(e.content)
}
or
google.maps.event.addListener(infoWindow, 'content_changed' function(e){
//No such thing exists
document.body.appendChild(infoWindow.previousContent)
}
This doesn't seem like it's possible out of the box, any ideas? Again, I would like to avoid creating an independent store to keep a separate reference to the DOM nodes, other than the reference already in the DOM. I'm hoping there's something I'm missing.
Thanks in advance.
I'm not 100% sure it meets your use-case, but how about attaching the DOM reference to the marker itself? This should work well if you only have one DOM node per marker, and it means you can simplify your click handler code (not a big gain for two markers, but pretty handy for 20). This works for me:
document.body.appendChild(document.createElement('div')).id = 'longlived';
document.getElementById('longlived').innerHTML = 'I will stick around!';
var infowindow = new google.maps.InfoWindow();
var marker1 = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Marker1"
});
// attach the DOM node to the marker instance
// marker1.iwcontent = myNode also works, but this follows the API
marker1.set('iwcontent', document.getElementById('longlived'));
var marker2 = new google.maps.Marker({
position: myLatlng2,
map: map,
title:"Marker2"
});
// attach alternate content to this marker
marker2.set('iwcontent', "Some Text");
// create a click handler that will work for both markers
// a more robust option might check for the existence of iwcontent first
var openContentWindow = function() {
var marker = this;
// set the content to whatever's attached to the marker
infowindow.setContent(marker.get('iwcontent'));
infowindow.open(map, marker);
}
// attach your handler to your markers
google.maps.event.addListener(marker1, 'click', openContentWindow);
google.maps.event.addListener(marker2, 'click', openContentWindow);
Note that, while the DOM node persists between marker clicks, it's been removed from the actual page. I can't tell whether this is what you want or not, but if you'd like to have the DOM node available after the info window changes, it looks like you can access the marker via the anchor attribute on the info window:
google.maps.event.addListener(infowindow, 'content_changed', function(){
// I don't see this in the documented API, but it seems to reference
// the *previous* anchor, the one you're interested in
var marker = this.anchor;
// there are better tests for whether a var is a DOM node
if (marker && marker.get('iwcontent').nodeType) {
// do something with the DOM node here
}
});
If you were worried about using an undocumented API attribute, you could use the same technique as above to set a reference to the old anchor on the info window and then retrieve it when the content changes - but it seems unnecessary.
You can do it, something like this
createMessage();
var infowindow = new google.maps.InfoWindow();
var marker1 = new google.maps.Marker({
position: new google.maps.LatLng(18.464008, -66.117776),
map: map,
title:"Marker1"
});
var marker2 = new google.maps.Marker({
position: new google.maps.LatLng(18.470338, -66.123503),
map: map,
title:"Marker2"
});
google.maps.event.addListener(marker1, 'click', function() {
infowindow.setContent(document.getElementById('shortlived'));
infowindow.open(map, marker1);
createMessage();
});
google.maps.event.addListener(marker2, 'click', function() {
infowindow.setContent('Some Text');
infowindow.open(map, marker2);
});
function createMessage(){
document.body.appendChild(document.createElement('div')).id = 'shortlived';
document.getElementById('shortlived').innerHTML = 'I will pass soon...';
}

Google Maps API v3: Close infowindow when DOM element is clicked

I'm playing around with Google maps for the first time, so I looked at a nice tutorial over at CSS Tricks: http://css-tricks.com/google-maps-slider/ I like working with jQuery better than pure JS, and this tutorial makes a nice way to click on a place in a list to display the marker in the map.
I liked it that way, but I need to add infowindows to the marker. Which I did, but when I click on a place on the list and the map pans away, the infowindow stays open! I think it's because I need to attach the infowindow.close() to the event of clicking on a "#locations li".
Here's my code, which runs on document.ready:
$(function() {
var chicago = new google.maps.LatLng(41.924832, -87.697456),
pointToMoveTo,
first = true,
curMarker = new google.maps.Marker({}),
$el;
var myOptions = {
zoom: 10,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map($("#map_canvas")[0], myOptions);
$("#locations li").click(function() {
$el = $(this);
if (!$el.hasClass("hover")) {
$("#locations li").removeClass("hover");
$el.addClass("hover");
if (!first) {
// Clear current marker
curMarker.setMap();
// Set zoom back to Chicago level
// map.setZoom(10);
}
// Move (pan) map to new location
function move(){
pointToMoveTo = new google.maps.LatLng($el.attr("data-geo-lat"), $el.attr("data-geo-long"));
map.panTo(pointToMoveTo);
}
move();
// Add new marker
curMarker = new google.maps.Marker({
position: pointToMoveTo,
map: map
});
// Infowindow: contenido
var contentString = '<p>'+$el.find("h3").html()+'</p>';
contentString += 'hola' ;
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50),
content: contentString
});
// On click, zoom map
google.maps.event.addListener(curMarker, 'click', function() {
//map.setZoom(14);
infowindow.open(map,curMarker);
});
It looks like you're creating a new InfoWindow for each marker. 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 one InfoWindow object just after you initialize your map, and then handle the click event handler as follows:
google.maps.event.addListener(curMarker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map, curMarker);
});
Then the InfoWindow should automatically close when you click on a new marker without having to call the close() method.

Categories