Google Maps: Auto close open InfoWindows? - javascript

On my site, I'm using Google Maps API v3 to place house markers on the map.
The InfoWindows stay open unless you explicitly click the close icon. Meaning, you can have 2+ InfoWindows open at a time if you hover over the map marker.
Question: How do I make it so that only the current active InfoWindow is open and all other InfoWindows are closed? Meaning, no more than 1 InfoWindow will be open at a time?

There is a close() function for InfoWindows. Just keep track of the last opened window, and call the close function on it when a new window is created.

alternative solution for this with using many infowindows:
save prev opened infowindow in a variable and then close it when new window opened
var prev_infowindow =false;
...
base.attachInfo = function(marker, i){
var infowindow = new google.maps.InfoWindow({
content: 'yourmarkerinfocontent'
});
google.maps.event.addListener(marker, 'click', function(){
if( prev_infowindow ) {
prev_infowindow.close();
}
prev_infowindow = infowindow;
infowindow.open(base.map, marker);
});
}

//assuming you have a map called 'map'
var infowindow = new google.maps.InfoWindow();
var latlng1 = new google.maps.LatLng(0,0);
var marker1 = new google.maps.Marker({position:latlng1, map:map});
google.maps.event.addListener(marker1, 'click',
function(){
infowindow.close();//hide the infowindow
infowindow.setContent('Marker #1');//update the content for this marker
infowindow.open(map, marker1);//"move" the info window to the clicked marker and open it
}
);
var latlng2 = new google.maps.LatLng(10,10);
var marker2 = new google.maps.Marker({position:latlng2, map:map});
google.maps.event.addListener(marker2, 'click',
function(){
infowindow.close();//hide the infowindow
infowindow.setContent('Marker #2');//update the content for this marker
infowindow.open(map, marker2);//"move" the info window to the clicked marker and open it
}
);
This will "move" the info window around to each clicked marker, in effect closing itself, then reopening (and panning to fit the viewport) in its new location. It changes its contents before opening to give the desired effect. Works for n markers.

My solution.
var map;
var infowindow = new google.maps.InfoWindow();
...
function createMarker(...) {
var marker = new google.maps.Marker({
...,
descrip: infowindowHtmlContent
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setOptions({
content: this.descrip,
maxWidth:300
});
infowindow.open(map, marker);
});

Declare a variable for active window
var activeInfoWindow;
and bind this code in marker listener
marker.addListener('click', function () {
if (activeInfoWindow) { activeInfoWindow.close();}
infowindow.open(map, marker);
activeInfoWindow = infowindow;
});

From this link http://www.svennerberg.com/2009/09/google-maps-api-3-infowindows/:
Teo: The easiest way to do this is to
just have one instance of the
InfoWindow object that you reuse over
and over again. That way when you
click a new marker the infoWindow is
“moved” from where it’s currently at,
to point at the new marker.
Use its setContent method to load it
with the correct content.

There is a easier way besides using the close() function. if you create a variable with the InfoWindow property it closes automatically when you open another.
var info_window;
var map;
var chicago = new google.maps.LatLng(33.84659, -84.35686);
function initialize() {
var mapOptions = {
center: chicago,
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
info_window = new google.maps.InfoWindow({
content: 'loading'
)};
createLocationOnMap('Location Name 1', new google.maps.LatLng(33.84659, -84.35686), '<p><strong>Location Name 1</strong><br/>Address 1</p>');
createLocationOnMap('Location Name 2', new google.maps.LatLng(33.84625, -84.36212), '<p><strong>Location Name 1</strong><br/>Address 2</p>');
}
function createLocationOnMap(titulo, posicao, conteudo) {
var m = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
title: titulo,
position: posicao,
html: conteudo
});
google.maps.event.addListener(m, 'click', function () {
info_window.setContent(this.html);
info_window.open(map, this);
});
}

var map;
var infowindow;
...
function createMarker(...) {
var marker = new google.maps.Marker({...});
google.maps.event.addListener(marker, 'click', function() {
...
if (infowindow) {
infowindow.close();
};
infowindow = new google.maps.InfoWindow({
content: contentString,
maxWidth: 300
});
infowindow.open(map, marker);
}
...
function initialize() {
...
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
...
google.maps.event.addListener(map, 'click', function(event) {
if (infowindow) {
infowindow.close();
};
...
}
}

How about -
google.maps.event.addListener(yourMarker, 'mouseover', function () {
yourInfoWindow.open(yourMap, yourMarker);
});
google.maps.event.addListener(yourMarker, 'mouseout', function () {
yourInfoWindow.open(yourMap, yourMarker);
});
Then you can just hover over it and it will close itself.

I stored a variable at the top to keep track of which info window is currently open, see below.
var currentInfoWin = null;
google.maps.event.addListener(markers[counter], 'click', function() {
if (currentInfoWin !== null) {
currentInfoWin.close(map, this);
}
this.infoWin.open(map, this);
currentInfoWin = this.infoWin;
});

Here is what I used if you are using many markers in a for loop (Django here). You can set an index on each marker and set that index every time you open a window. Closing the previously saved index:
markers = Array();
infoWindows = Array();
var prev_infowindow =false;
{% for obj in objects %}
var contentString = 'your content'
var infowindow = new google.maps.InfoWindow({
content: contentString,
});
var marker = new google.maps.Marker({
position: {lat: {{ obj.lat }}, lng: {{ obj.lon }}},
map: map,
title: '{{ obj.name }}',
infoWindowIndex : {{ forloop.counter0 }}
});
google.maps.event.addListener(marker, 'click',
function(event)
{
if( prev_infowindow ) {
infoWindows[prev_infowindow].close();
}
prev_infowindow = this.infoWindowIndex;
infoWindows[this.infoWindowIndex].open(map, this);
}
);
infoWindows.push(infowindow);
markers.push(marker);
{% endfor %}

var contentString = "Location: " + results[1].formatted_address;
google.maps.event.addListener(marker,'click', (function(){
infowindow.close();
infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, marker);
}));

Related

GoogleMap infowindow push onclick on a button

im using Googlemap JS API, i have some markers fetched from my Database and an infowindow foreach marker, on each infowindow i have a button wish pushes to another page with a certain variable, i tried to use ngZone, im not really familiar with it but i tried x), here's my code:
// GET request to get data from database
for(var i=0;i<data.length;i++)
{
var ouvrier=data[i].firstname+' '+data[i].lastname; //Getting data from db
var Latlng = new google.maps.LatLng(data[i].lat,data[i].lon);
var marker = new google.maps.Marker({
position: Latlng,
map: this.map,
labelAnchor: new google.maps.Point(22, 0),
draggable:false,
icon: { url : 'assets/imgs/worker.png',scaledSize: new google.maps.Size(70, 70)
},
});
var infowindow = new google.maps.InfoWindow({
content: "Name: "+ouvrier+" <input type='button' id='clickableItem' value='consulter profile' >"
});
google.maps.event.addListener(infowindow, 'domready', () => {
var clickableItem = document.getElementById('clickableItem');
clickableItem.addEventListener('click', () => {
this.zone.run( () => { //Im using ngZone
console.log("wlidoz "+ data[i].idprof);
this.navCtrl.push(ProfilPage, {
profilId: data[i].idprof // PROBLEM HERE
});
});
});
});
marker.addListener('click', event => {
infowindow.open(this.map, marker);
});
}
Everything is working fine, the map is loading..etc
But when i click on that button, nothing happens, i tried to console.log that data[i].idprof inside the ngZone but its undefined, but before the listener the console.log is working
I fixed it, i just declared a variable berfore the google.maps.event.addLister :
let idz=data[i].idprof;
let that=this;
google.maps.event.addListener(infowindow, 'domready', () => {
var clickableItem = document.getElementById('clickableItem');
clickableItem.addEventListener('click', () => {
that.zone.run( () => {
that.navCtrl.push(ProfilPage, {
profilId: idz
});
});
});
});
If anyone has a better solution, i'll take it

linking a function to a clicking event

Im trying to code a functionality so when I click on a certain location button that markers info window pops up. Ive got the code to console log the certain title and location of the marker, but when i try to call the infowindow in the viewmodel it comes up undefined. I know that the Infowindow is in the init function for google map, i cant seem to figure out how to open it from the viewmodel
and here is my code for the view model:
function viewModel() {
this.marker = locationArray().location;
this.openWindow = function(location){
if(this.marker){
console.log(this.marker);
};
}
}
and my click event:
google.maps.event.addListener(marker,'click', (function(marker){
return function() {
viewModel()
infoWindow.setContent("<div>" + marker.title + "</div>");
infoWindow.open( map, marker);
}
})(marker));
here is my google map api, hopefully this will help :
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 41.764117, lng: -72.676470},
zoom: 13,
styles: style
});
// Iterates through the locationArray and gives the marker a proper
// location.
for(var i = 0; i < locationArray().length; i++){
var locations = locationArray()[i].location;
var title = locationArray()[i].title;
var marker = new google.maps.Marker({
position: locations,
map: map,
title: title,
animation: google.maps.Animation.DROP
});
locationArray()[i].marker = marker;
var message = "hello world!";
var infoWindow = new google.maps.InfoWindow({
content: title,
position: locations
});
google.maps.event.addListener(marker,'click', (function(marker){
return function() {
viewModel();
infoWindow.setContent("<div>" + marker.title + "</div>");
infoWindow.open( map, marker);
}
})(marker));
};
};
ko.applyBindings(new viewModel());
You definition of marker in the ViewModel is ambiguous. You should in general define the observables inside the ViewModel.
function ViewModel(data) {
var self = this;
self.locations = ko.observableArray(data.locations || []);
self.showMarker(function(loc) { // bind this to click (in html)
loc.marker.showInfo(); // I'm not sure if loc.marker.click() would work
});
}
var locations = []; // your list of locations
ko.applyBindings( new ViewModel({locations: locations}) );
And you can bind the click event of your marker in a simpler way, that'll also help to easily call the
marker.showInfo = function() {
infoWindow.setContent("<div>" + this.title + "</div>");
infoWindow.open( map, this);
};
google.maps.event.addListener(marker,'click', marker.showInfo);

Issue toggle on/off with infowindow

today i saw an answer about toggle on/off in the same button, and i decided to try to use.
What i want is to click in the marker and than a infowindow appear in my map, but it doesn't work.
JSFiddle simple marker with infowindow
JSFiddle toogle on/off but no infowindow
When i try to join(toogle with infowindow) like this:
google.maps.event.addDomListener(buttonCarrosUI, 'click', function() {
if(marker && marker.setMap){
if (marker.getMap() != null)
marker.setMap(null);
else marker.setMap(map_canvas);
}else{
var myLatLng;
var title = marker.title;
$.each( data.markers, function(i, marker) {
myLatLng = new google.maps.LatLng(marker.latitude, marker.longitude);
});
var infowindow = new google.maps.InfoWindow({
content: title,
});
marker = new google.maps.Marker({
position: myLatLng,
map: map_canvas,
icon: image,
title: title
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map_canvas,marker);
});
}
});
I Got this issue
TypeError: marker is undefined
var title = marker.title;
I'll be very gratefull if someone can help me, thanks.
You are creating the marker outside of the $.each. Unless you want more than one infowindow open at a time, it is better to make a global infowindow and reuse it. Also, you are overwriting the "marker" variable inside the $.each. Note that this wont work for more than one marker. You need to keep references to the markers in an array if you have more than one (the original example from which this code came toggled a single polyline). The code below works for me:
google.maps.event.addDomListener(buttonCarrosUI, 'click', function () {
var data = JSON;
var myLatLng;
if (marker && marker.setMap) {
if (marker.getMap() != null) marker.setMap(null);
else marker.setMap(map_canvas);
} else {
$.each(data.markers, function (i, markerInfo) {
myLatLng = new google.maps.LatLng(markerInfo.latitude, markerInfo.longitude);
marker = new google.maps.Marker({
position: myLatLng,
map: map_canvas,
title: markerInfo.title
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent(marker.getTitle());
infowindow.open(map_canvas, marker);
});
});
}
});
working fiddle

TypeError: e.getPosition is not a function

I'm trying to update my lat and lng after a marker is dragged. and update input's with id's lat and lng. but i'm getting some errors
Here is my code
function createMyLocationMarker(point) {
var marker = new google.maps.Marker({
map: EGMap0,
position: point,
draggable:true,
title:"Hello World!"
});
google.maps.event.addListener(marker, 'dragend', function(e) {
jQuery("#lat").val(e.getPosition().lat());
jQuery("#lng").val(e.getPosition().lng());
});
}
I get this error
TypeError: getPosition is not a function on
jQuery("#lat").val(e.getPosition().lat());
also tried this
google.maps.event.addListener(marker, 'dragend', function(event) {
document.getElementById("#lat").value = event.getPosition().lat();
document.getElementById("#lng").value = event.getPosition().lng();
});
but get this error
TypeError: event.getPosition is not a function
document.getElementById("#lat").value = event.getPosition().lat();
any idea what i'm missing here? Thanks
This should work
google.maps.event.addListener(marker, 'dragend', function(event) {
var lng= event.latLng.lng();
var lat= event.latLng.lat();
});
or use this.
google.maps.event.addListener(marker, 'dragend', function(e) {
document.getElementById("#lat").value = event.latLng.lng();
document.getElementById("#lng").value = event.latLng.lat();
});
Im using JS here

InfoWindow not showing up

Hello I'm trying to bind Google Maps with Knockout script.
Nearly everything works but I can't force infowindows to show up on event.
Without Knockout my code works but with it doesn't.
Below my js code:
var infowindow;
function point(name, lat, long) {
this.name = name;
this.lat = ko.observable(lat);
this.long = ko.observable(long);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, long),
title: name,
map: map,
draggable: true
});
//if you need the poition while dragging
google.maps.event.addListener(marker, 'drag', function () {
var pos = marker.getPosition();
this.lat(pos.lat());
this.long(pos.lng());
}.bind(this));
//if you just need to update it when the user is done dragging
google.maps.event.addListener(marker, 'dragend', function () {
var pos = marker.getPosition();
this.lat(pos.lat());
this.long(pos.lng());
}.bind(this));
google.maps.event.addListener(marker, 'mouseover', function () {
infowindow = new google.maps.InfoWindow({ content: "empty" });
console.log("mouseover");
infowindow.setContent(this.title);
infowindow.open(map, this);
}.bind(this));
}
var map = new google.maps.Map(document.getElementById('googleMap'), {
zoom: 5,
center: new google.maps.LatLng(55, 11),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var viewModel = {
points: ko.observableArray([
new point('Test1', 55, 11),
new point('Test2', 56, 12),
new point('Test3', 57, 13)])
};
function addPoint() {
viewModel.points.push(new point('a', 58, 14));
}
ko.applyBindings(viewModel);
Now my question:
Is it simple way to make it works. If yes can anyone suggest me where should I look for it?
Could be your use of this.
Add var self = this; as the first line within point function & use self to refer to properties within point.
In the mouseover event, does this refer to the marker, the map, or viewmodel? If the drag event are setting values correctly, then this is the point viewmodel, in which case within the mouseover event you called this.title. There is no title...
function point(name, lat, long) {
var self = this;
self.name = name;
self.lat = ko.observable(lat);
self.long = ko.observable(long);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, long),
title: name,
map: map,
draggable: true
});
//if you need the poition while dragging
google.maps.event.addListener(marker, 'drag', function () {
var pos = marker.getPosition();
self.lat(pos.lat());
self.long(pos.lng());
}.bind(this));
//if you just need to update it when the user is done dragging
google.maps.event.addListener(marker, 'dragend', function () {
var pos = marker.getPosition();
self.lat(pos.lat());
self.long(pos.lng());
}.bind(this));
google.maps.event.addListener(marker, 'mouseover', function () {
infowindow = new google.maps.InfoWindow({ content: "empty" });
console.log("mouseover");
infowindow.setContent(marker.title);
infowindow.open(map, this);
}.bind(this));
}
I have never used knockout myself but integrating it with maps does not look simple, here are some reading materials: http://www.codeproject.com/Articles/351298/KnockoutJS-and-Google-Maps-binding
http://www.codeproject.com/Articles/387626/BikeInCity-2-KnockoutJS-JQuery-Google-Maps
Google maps and knockoutjs
The maps code you have provided looks correct so I assume the issue lies with the knockout integration.

Categories