Google Maps API Polygon Infowindow Appears on Last Clicked Marker - javascript

I have a set of markers and polygons displayed on my map, each marker and polygon is stored in a separate array. Currently, I have infowindows tied to my markers and I wanted to add infowindows to my polygons in case the user clicks on them. The marker infowindows work perfectly.
The problem is that when you click on the polygon the infowindow won't pop up unless you've clicked on a marker first. Then, the polygon infowindow will appear on the last clicked marker.
I've worked through every line of relevant code. I think the problem exists in that the infowindow is tied specifically to the marker icons, but I don't know how to detach it. I'm relatively new to JS and this is my first major on-going project.
var map;
var mapCenter = { lat: 28.201890, lng: -81.027334 };
var mPoint = "/images/placemark_circle_highlight.png";
var locations = [];
var locationsPoly = [];
var markers = [];
var infos = [];
var polygons = [];
var polyInfos = [];
var infowindow;
var testInfoWindow1 =
'<div id="content">' +
'<h1 class="header">Test Marker #1</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 1.</p>" +
"</div>" +
"</div>";
var testInfoWindow2 =
'<div id="content">' +
'<h1 class="header">Test Marker #2</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 2.</p>" +
"</div>" +
"</div>";
var testInfoWindow3 =
'<div id="content">' +
'<h1 class="header">Test Marker #3</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 3.</p>" +
"</div>" +
"</div>";
var testInfoWindow4 =
'<div id="content">' +
'<h1 class="header">Test Marker #4</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 4.</p>" +
"</div>" +
"</div>";
var testInfoWindow5 =
'<div id="content">' +
'<h1 class="header">Test Marker #5</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 5.</p>" +
"</div>" +
"</div>";
var pOneDesc =
'<div id="content">' +
'<h1 class="header">#1 Polygon Window</h1>' +
'<div class="desc">' +
"<p>Lorem.</p>" +
"</div>" +
"</div>";
var pTwoDesc =
'<div id="content">' +
'<h1 class="header">#2 Polygon Window</h1>' +
'<div class="desc">' +
"<p>elementum pulvinar etiam.</p>" +
"</div>" +
"</div>";
var pThreeDesc =
'<div id="content">' +
'<h1 class="header">#3 Polygon Window</h1>' +
'<div class="desc">' +
"<p>orci eu lobortis elementum nibh tellus molestie.</p>" +
"</div>" +
"</div>";
function initMap() {
var myOptions = {
zoom: 15,
center: mapCenter,
mapTypeControl: true,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.TERRAIN,
};
map = new google.maps.Map(document.getElementById("map"),
myOptions);
locations = [
["Test Marker #1", 28.210862, -81.038192, testInfoWindow1, mPoint, 'category1'],
["Test Marker #2", 28.206477, -81.016176, testInfoWindow2, mPoint, 'category1'],
["Test Marker #3", 28.216659, -81.029092, testInfoWindow3, mPoint, 'category1'],
["Test Marker #4", 28.195328, -81.044638, testInfoWindow4, mPoint, 'category1'],
["Test Marker #5", 28.196439, -81.006932, testInfoWindow5, mPoint, 'category1']
];
var polygonOne = [
[28.187985, -81.045365],
[28.183579, -81.045365],
[28.183579, -81.041156],
[28.187922, -81.041341]
];
var pointsPolyOne = [];
for (var i = 0; i < polygonOne.length; i++) {
pointsPolyOne.push({
lat: polygonOne[i][0],
lng: polygonOne[i][1]
});
}
var polygonTwo = [
[28.185258, -81.033373],
[28.183601, -81.030751],
[28.187809, -81.026072]
];
var pointsPolyTwo = [];
for (var i = 0; i < polygonTwo.length; i++) {
pointsPolyTwo.push({
lat: polygonTwo[i][0],
lng: polygonTwo[i][1]
});
}
var polygonThree = [
[28.189691, -81.032381],
[28.188111, -81.032337],
[28.188291, -81.031608],
[28.189719, -81.031276]
];
var pointsPolyThree = [];
for (var i = 0; i < polygonThree.length; i++) {
pointsPolyThree.push({
lat: polygonThree[i][0],
lng: polygonThree[i][1]
});
}
locationsPoly = [
[pointsPolyThree, pOneDesc, "#f44336", 0.8, 2, "#ffffff", 0.35, 'FY19'],
[pointsPolyTwo, pTwoDesc, "#4caf50", 0.8, 2, "#bdeabf", 0.35, 'FY19'],
[pointsPolyOne, pThreeDesc, "#849199", 0.8, 2, "#ffffff", 0.35, 'FY19']
];
infowindow = new google.maps.InfoWindow();
setMarkers(map, locations);
setPolygons(map, locationsPoly);
}
function setMarkers(map, locations) {
var marker, i
for (i = 0; i < locations.length; i++) {
var title = locations[i][0];
var lat = locations[i][1];
var long = locations[i][2];
var desc = locations[i][3];
var pin = locations[i][4];
var category = locations[i][5];
latlngset = new google.maps.LatLng(lat, long);
marker = new google.maps.Marker({
map: map,
title: title,
position: latlngset,
icon: pin,
category: category
});
marker.mycategory = category;
marker.myname = name;
markers.push(marker);
var content = desc;
google.maps.event.addListener(marker, 'click', (function (marker, content) {
return function () {
/* close the previous info-window */
closeInfos();
infowindow.setContent(content);
infowindow.setPosition(event.latlng);
infowindow.open(map, marker);
/* keep the handle, in order to close it on next click event */
infos[0] = infowindow;
};
})(marker, content));
google.maps.event.addListener(map, "click", function (marker, content) {
closeInfos();
});
}
}
function setPolygons(map, locationsPoly) {
var polygon, i
for (i = 0; i < locationsPoly.length; i++) {
var paths = locationsPoly[i][0];
var polyDesc = locationsPoly[i][1];
var strokeColor = locationsPoly[i][2];
var strokeOpacity = locationsPoly[i][3];
var strokeWeight = locationsPoly[i][4];
var fillColor = locationsPoly[i][5];
var fillOpacity = locationsPoly[i][6];
var categoryPoly = locationsPoly[i][7];
polygon = new google.maps.Polygon({
map: map,
paths: paths,
strokeColor: strokeColor,
strokeOpacity: strokeOpacity,
strokeWeight: strokeWeight,
fillColor: fillColor,
fillOpacity: fillOpacity,
category: categoryPoly
});
polygon.mycategory = categoryPoly;
polygon.myname = name;
polygons.push(polygon);
var polyContent = polyDesc;
google.maps.event.addListener(polygon, 'click', (function (polygon, polyContent) {
return function () {
/* close the previous info-window */
closeInfos();
infowindow.setContent(polyContent);
infowindow.setPosition(getHighestWindowPosition(paths));
infowindow.open(map, polygon);
/* keep the handle, in order to close it on next click event */
infos[0] = infowindow;
};
})(polygon, polyContent));
google.maps.event.addListener(map, "click", function (marker, content) {
closeInfos();
});
}
}
function getHighestWindowPosition(paths) {
var lat = -5000, lng = 0, i = 0, n = paths.length;
for (; i !== n; ++i) {
if (paths[i].lat > lat) {
lat = paths[i].lat;
lng = paths[i].lng;
}
}
return { lat: lat, lng: lng };
}
function closeInfos() {
if (infos.length > 0) {
/* detach the info-window from the marker ... undocumented in the API docs */
infos[0].set("marker", "polygon", null);
/* and close it */
infos[0].close();
/* blank the array */
infos.length = 0;
}
}
<!DOCTYPE html>
<html>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<head>
<title>Test Map for Markers-Polygons</title>
<script type="application/javascript" src="js/checkbox.js?rndstr=<%= getRandomStr() %>"></script>
<style>
#map {
height: 100vh;
}
html,
body {
height: 100vh;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=##APIKEYHERE##&callback=initMap"
async defer></script>
</body>
</html>
UPDATE: Minimum reproducible example.
The infowindow now appears on a polygon, but only the first one in the array.

Two issues remain.
Per my comment, and the related question: Open InfoWindow for each polygon google maps V3, the InfoWindow.open method's second parameter (if it exists) must be an "anchor" (with a position property), which a google.maps.Polygon object is not.
infowindow.open(map, polygon);
should be:
infowindow.open(map);
You are using the paths variable inside the "click" event listener function, but you don't have function closure on it (you only have function closure on polygon and polygonContent).
google.maps.event.addListener(polygon, 'click', (function (polygon, polyContent) {
return function () {
/* close the previous info-window */
closeInfos();
infowindow.setContent(polyContent);
infowindow.setPosition(getHighestWindowPosition(paths));
infowindow.open(map, polygon);
/* keep the handle, in order to close it on next click event */
infos[0] = infowindow;
};
})(polygon, polyContent));
should be:
google.maps.event.addListener(polygon, 'click', (function (polygon, polyContent, paths) {
return function (evt) {
/* close the previous info-window */
closeInfos();
infowindow.setContent(polyContent);
infowindow.setPosition(getHighestWindowPosition(paths));
infowindow.open(map);
/* keep the handle, in order to close it on next click event */
infos[0] = infowindow;
};
})(polygon, polyContent, paths));
proof of concept fiddle
code snippet:
var map;
var mapCenter = {
lat: 28.201890,
lng: -81.027334
};
var mPoint = "/images/placemark_circle_highlight.png";
var locations = [];
var locationsPoly = [];
var markers = [];
var infos = [];
var polygons = [];
var polyInfos = [];
var infowindow;
var testInfoWindow1 =
'<div id="content">' +
'<h1 class="header">Test Marker #1</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 1.</p>" +
"</div>" +
"</div>";
var testInfoWindow2 =
'<div id="content">' +
'<h1 class="header">Test Marker #2</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 2.</p>" +
"</div>" +
"</div>";
var testInfoWindow3 =
'<div id="content">' +
'<h1 class="header">Test Marker #3</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 3.</p>" +
"</div>" +
"</div>";
var testInfoWindow4 =
'<div id="content">' +
'<h1 class="header">Test Marker #4</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 4.</p>" +
"</div>" +
"</div>";
var testInfoWindow5 =
'<div id="content">' +
'<h1 class="header">Test Marker #5</h1>' +
'<div class="desc">' +
"<p>This is a marker at position number 5.</p>" +
"</div>" +
"</div>";
var pOneDesc =
'<div id="content">' +
'<h1 class="header">#1 Polygon Window</h1>' +
'<div class="desc">' +
"<p>Lorem.</p>" +
"</div>" +
"</div>";
var pTwoDesc =
'<div id="content">' +
'<h1 class="header">#2 Polygon Window</h1>' +
'<div class="desc">' +
"<p>elementum pulvinar etiam.</p>" +
"</div>" +
"</div>";
var pThreeDesc =
'<div id="content">' +
'<h1 class="header">#3 Polygon Window</h1>' +
'<div class="desc">' +
"<p>orci eu lobortis elementum nibh tellus molestie.</p>" +
"</div>" +
"</div>";
function initMap() {
var myOptions = {
zoom: 13,
center: mapCenter,
mapTypeControl: true,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.TERRAIN,
};
map = new google.maps.Map(document.getElementById("map"),
myOptions);
locations = [
["Test Marker #1", 28.210862, -81.038192, testInfoWindow1, mPoint, 'category1'],
["Test Marker #2", 28.206477, -81.016176, testInfoWindow2, mPoint, 'category1'],
["Test Marker #3", 28.216659, -81.029092, testInfoWindow3, mPoint, 'category1'],
["Test Marker #4", 28.195328, -81.044638, testInfoWindow4, mPoint, 'category1'],
["Test Marker #5", 28.196439, -81.006932, testInfoWindow5, mPoint, 'category1']
];
var polygonOne = [
[28.187985, -81.045365],
[28.183579, -81.045365],
[28.183579, -81.041156],
[28.187922, -81.041341]
];
var pointsPolyOne = [];
for (var i = 0; i < polygonOne.length; i++) {
pointsPolyOne.push({
lat: polygonOne[i][0],
lng: polygonOne[i][1]
});
}
var polygonTwo = [
[28.185258, -81.033373],
[28.183601, -81.030751],
[28.187809, -81.026072]
];
var pointsPolyTwo = [];
for (var i = 0; i < polygonTwo.length; i++) {
pointsPolyTwo.push({
lat: polygonTwo[i][0],
lng: polygonTwo[i][1]
});
}
var polygonThree = [
[28.189691, -81.032381],
[28.188111, -81.032337],
[28.188291, -81.031608],
[28.189719, -81.031276]
];
var pointsPolyThree = [];
for (var i = 0; i < polygonThree.length; i++) {
pointsPolyThree.push({
lat: polygonThree[i][0],
lng: polygonThree[i][1]
});
}
locationsPoly = [
[pointsPolyThree, pOneDesc, "#f44336", 0.8, 2, "#ffffff", 0.35, 'FY19'],
[pointsPolyTwo, pTwoDesc, "#4caf50", 0.8, 2, "#bdeabf", 0.35, 'FY19'],
[pointsPolyOne, pThreeDesc, "#849199", 0.8, 2, "#ffffff", 0.35, 'FY19']
];
infowindow = new google.maps.InfoWindow();
setMarkers(map, locations);
setPolygons(map, locationsPoly);
}
function setMarkers(map, locations) {
var marker, i
for (i = 0; i < locations.length; i++) {
var title = locations[i][0];
var lat = locations[i][1];
var long = locations[i][2];
var desc = locations[i][3];
var pin = locations[i][4];
var category = locations[i][5];
latlngset = new google.maps.LatLng(lat, long);
marker = new google.maps.Marker({
map: map,
title: title,
position: latlngset,
// icon: pin,
category: category
});
marker.mycategory = category;
marker.myname = name;
markers.push(marker);
var content = desc;
google.maps.event.addListener(marker, 'click', (function(marker, content) {
return function() {
/* close the previous info-window */
closeInfos();
infowindow.setContent(content);
infowindow.setPosition(event.latlng);
infowindow.open(map, marker);
/* keep the handle, in order to close it on next click event */
infos[0] = infowindow;
};
})(marker, content));
google.maps.event.addListener(map, "click", function(marker, content) {
closeInfos();
});
}
}
function setPolygons(map, locationsPoly) {
var polygon, i
for (i = 0; i < locationsPoly.length; i++) {
var paths = locationsPoly[i][0];
var polyDesc = locationsPoly[i][1];
var strokeColor = locationsPoly[i][2];
var strokeOpacity = locationsPoly[i][3];
var strokeWeight = locationsPoly[i][4];
var fillColor = locationsPoly[i][5];
var fillOpacity = locationsPoly[i][6];
var categoryPoly = locationsPoly[i][7];
polygon = new google.maps.Polygon({
map: map,
paths: paths,
strokeColor: strokeColor,
strokeOpacity: strokeOpacity,
strokeWeight: strokeWeight,
fillColor: fillColor,
fillOpacity: fillOpacity,
category: categoryPoly
});
polygon.mycategory = categoryPoly;
polygon.myname = name;
polygons.push(polygon);
var polyContent = polyDesc;
google.maps.event.addListener(polygon, 'click', (function(polygon, polyContent, paths) {
return function(evt) {
/* close the previous info-window */
closeInfos();
infowindow.setContent(polyContent);
infowindow.setPosition(getHighestWindowPosition(paths));
infowindow.open(map);
/* keep the handle, in order to close it on next click event */
infos[0] = infowindow;
};
})(polygon, polyContent, paths));
google.maps.event.addListener(map, "click", function(marker, content) {
closeInfos();
});
}
}
function getHighestWindowPosition(paths) {
console.log(paths);
var lat = -5000,
lng = 0,
i = 0,
n = paths.length;
for (; i !== n; ++i) {
if (paths[i].lat > lat) {
lat = paths[i].lat;
lng = paths[i].lng;
}
}
console.log("lat=" + lat + " lng=" + lng);
return {
lat: lat,
lng: lng
};
}
function closeInfos() {
if (infos.length > 0) {
/* detach the info-window from the marker ... undocumented in the API docs */
infos[0].set("marker", "polygon", null);
/* and close it */
infos[0].close();
/* blank the array */
infos.length = 0;
}
}
html,
body,
#map {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>

Related

Google Maps API v3 infoWindow.close() not closing others on click

I have been working on this for a while now. I have looked at multiple stack overflow posts on the topic and several tutorials, but I have not been able to get infoWindow.close() to work.
I have even tried using jQuery to click $('#googleMap > div > div > div:nth-child(1) > div:nth-child(4) > div:nth-child(4) > div:nth-child(1) > div:nth-child(3)').click(); which actually seems to work in the browser console, but not when running the click listener.
Any suggestions or directions are much appreciated.
d3.csv('/data/locs.csv', function(locs){
var obj = [];
for(i=0;i<locs.length;i++) {
var country = locs[i].country;
var location = locs[i].location;
var lat = locs[i].lat;
var long = locs[i].long;
var description = locs[i].description;
obj.push({
con: country,
location: location,
lat: lat,
lng: long,
description: description
});
}
console.log(obj);
initMap(obj)
});
function initMap(obj, error) {
if (error){console.log("Error: "+error)}
var openInfoWindow = null;
var mapProp = {
center: {lat: 39.8283, lng: -98.5795},
zoom: 2
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var pointLoc = [];
var labels = [];
var descrip = [];
var locale = [];
for(i=0;i<obj.length;i++) {
pointLoc.push({lat: obj[i].lat, lng: obj[i].lng});
labels.push(obj[i].con);
descrip.push(obj[i].description);
locale.push(obj[i].location);
}
map.data.loadGeoJson();
for (var i = 0; i < pointLoc.length; i++) {
var coords = pointLoc[i];
var latLng = new google.maps.LatLng(coords.lat,coords.lng);
var marker = new google.maps.Marker({
position: latLng,
map: map
});
var contentStr = '<div id="popcontent">'+
'<div id="siteNotice">'+
'</div>'+
'<h1 id="firstHeading" class="firstHeading">'+descrip[i]+'</h1>'+
'<p>'+locale[i]+', '+labels[i]+'</p>' +
'</div>';
var infoWindow = new google.maps.InfoWindow({
maxWidth: 300
});
google.maps.event.addListener(marker,'click', (function(marker,contentStr,infowindow){
infowindow.close();
return function() {
infowindow.setContent(contentStr);
infowindow.open(map, marker);
};
})(marker,contentStr,infoWindow));
}
}
Stephen's answer identifies the problem with the infowindow. I want to help you learn to write simpler code.
There is a lot of complication in this code that you don't need; in fact you can get rid of most of the code!
The code first converts the locs array to a very similar obj array that has a couple of fields renamed.
Then it converts this obj array to four individual arrays pointLoc, labels, descrip, and locale.
None of this conversion is needed.
Also, when naming an array, I recommend using a plural name for the array and the singular form of that name for an element of the array. You did this in some places, just not consistently.
There is a map.data.loadGeoJson(); call that doesn't do anything because no URL is provided.
You also don't need the function-that-returns-a-function in the click listener, if you provide a closure in a simpler way as in the code below.
Here's an example of how you could do the whole thing in a much simpler manner:
d3.csv( '/data/locs.csv', function( places ) {
var infoWindow;
var map = new google.maps.Map( document.getElementById('googleMap'), {
center: { lat: 39.8283, lng: -98.5795 },
zoom: 2
});
places.forEach( function( place ) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng( place.lat, place.long ),
map: map
});
google.maps.event.addListener( marker, 'click', function() {
if( infoWindow ) infoWindow.close();
var content =
'<div id="popcontent">' +
'<div id="siteNotice">' +
'</div>' +
'<h1 id="firstHeading" class="firstHeading">' + place.description + '</h1>' +
'<p>' + place.location + ', ' + place.country + '</p>' +
'</div>';
infoWindow = new google.maps.InfoWindow({
maxWidth: 300,
content: content
});
infoWindow.open( map, marker );
});
});
});
Your variable infoWindow goes out of scope when returning a function, and you not modifying the outer infoWindow, but the one passed into the function. Try this.
d3.csv('/data/locs.csv', function(locs){
var obj = [];
for(i=0;i<locs.length;i++) {
var country = locs[i].country;
var location = locs[i].location;
var lat = locs[i].lat;
var long = locs[i].long;
var description = locs[i].description;
obj.push({
con: country,
location: location,
lat: lat,
lng: long,
description: description
});
}
console.log(obj);
initMap(obj)
});
function initMap(obj, error) {
if (error){console.log("Error: "+error)}
var openInfoWindow = null;
var mapProp = {
center: {lat: 39.8283, lng: -98.5795},
zoom: 2
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var pointLoc = [];
var labels = [];
var descrip = [];
var locale = [];
for(i=0;i<obj.length;i++) {
pointLoc.push({lat: obj[i].lat, lng: obj[i].lng});
labels.push(obj[i].con);
descrip.push(obj[i].description);
locale.push(obj[i].location);
}
map.data.loadGeoJson();
for (var i = 0; i < pointLoc.length; i++) {
var coords = pointLoc[i];
var latLng = new google.maps.LatLng(coords.lat,coords.lng);
var marker = new google.maps.Marker({
position: latLng,
map: map
});
var contentStr = '<div id="popcontent">'+
'<div id="siteNotice">'+
'</div>'+
'<h1 id="firstHeading" class="firstHeading">'+descrip[i]+'</h1>'+
'<p>'+locale[i]+', '+labels[i]+'</p>' +
'</div>';
var infoWindow = new google.maps.InfoWindow({
maxWidth: 300
});
google.maps.event.addListener(marker,'click', (function(marker,contentStr,infowindow){
infowindow.close();
return((function(infowindow) {
infowindow.setContent(contentStr);
infowindow.open(map, marker);
})(infowindow));
})(marker,contentStr,infoWindow));
}
}
I was able to handle it easily with jQuery trigger event.
jQuery('.gm-ui-hover-effect').trigger('click');
Just put above code inside addListener function of marker and don't forget to include jQuery in your script.

Add listener event for multiple markers in Google Maps API

I am using Google Maps API in Rails. Getting my all locations from ajax call and displaying it in for loop. I followed this link When I copy paste this
code in my file it seems to work perfectly. But when I am trying to do the same thing for my code. It keeps showing the last marker info.
jQuery(function($) {
var myCenter = new google.maps.LatLng(51.508742,-0.120850);
var mapCanvas = document.getElementById("map");
var mapOptions = {center: myCenter, zoom: 5};
var map = new google.maps.Map(mapCanvas, mapOptions);
$.ajax({
url: "/list_proposals",
type: "GET",
dataType: "json",
success:function(data) {
placeMarker(map, data);
}
});
function placeMarker(map, data){
for (var i = 0; i < data.length; i++) {
var location_data = data[i];
var lat = location_data["lat"];
var long = location_data["long"];
var planting_proposal = location_data["planting_proposal"];
var proposal_id = planting_proposal["id"];
var title = planting_proposal["title"];
var photo_url = planting_proposal["main_photo"]["attachment_thumb_url"];
latlngset = new google.maps.LatLng(lat, long);
var image = {
url: window.location.origin + "/" + photo_url,
size: new google.maps.Size(50, 50),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(0, 32)
};
var marker = new google.maps.Marker({
map: map, title: title , position: latlngset, icon: image
});
map.setCenter(marker.getPosition());
var show_proposal_link = '' + title + '';
var contentString = '<div class="card text-center" style="width: 20rem;">' +
'<div class="card-block">' +
'<h4 class="card-title">'+ show_proposal_link + '</h4>' +
'<p class="card-text">' + '<img src="'+ window.location.origin + "/" + photo_url + '" width="100%;"/>' + '</p>' +
'</div>' +
'</div>';
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker,'click', (function(marker,content,infowindow){
return function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
};
})(marker,content,infowindow));
}
}
});
I am new in Google Maps API. Please me help me out with it what am I doing wrong?
You should correctly implement an IIFE in your code. Please replace the google.maps.event.addListener(marker,... part of the code with the following IIFE:
(function(marker,content,infowindow) {
google.maps.event.addListener(marker,'click', function() {
infowindow.setContent(content);
infowindow.open(map, marker);
});
})(marker,contentString,infowindow);
Proof of concept
var map;
var locations = [
{
planting_proposal: {
id: 1,
title: "Proposal 1"
},
lat: 41.386043,
long: 2.14561
},
{
planting_proposal: {
id: 2,
title: "Proposal 2"
},
lat: 41.417371,
long: 2.172115
},
{
planting_proposal: {
id: 3,
title: "Proposal 3"
},
lat: 41.399475,
long: 2.184048
}
]
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 41.385064, lng: 2.173403},
zoom: 12
});
placeMarker(map, locations);
}
function placeMarker(map, data){
for (var i = 0; i < data.length; i++) {
var location_data = data[i];
var lat = location_data["lat"];
var long = location_data["long"];
var planting_proposal = location_data["planting_proposal"];
var proposal_id = planting_proposal["id"];
var title = planting_proposal["title"];
latlngset = new google.maps.LatLng(lat, long);
var marker = new google.maps.Marker({
map: map,
title: title ,
position: latlngset
});
var show_proposal_link = '' + title + '';
var contentString = '<div class="card text-center" style="width: 20rem;">' +
'<div class="card-block">' +
'<h4 class="card-title">'+ show_proposal_link + '</h4>' +
'</div>' +
'</div>';
var infowindow = new google.maps.InfoWindow();
(function(marker,content,infowindow) {
google.maps.event.addListener(marker,'click', function() {
infowindow.setContent(content);
infowindow.open(map, marker);
});
})(marker,contentString,infowindow);
}
}
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap"
async defer></script>
I hope this helps!

Google Maps API. calling multiple info windows from an array

I have searched all over this site to find an answer with no luck. I have an array of lat, and lng markers and I'd like to open an info window based on the array index. I got it to work by replacing markers with variables instead of an array list, but I want to keep my code DRY. Here is my code:
function initMap() {
var locations = [
["blairCountyPA", 40.453132, -78.384223],
["scrantonPA", 41.408969, -75.662412],
["warringtonTownshipPA", 40.250319, -75.166212],
["lancasterCountyPA", 40.046657, -76.178374],
["berkeleyCountyWV", 39.488560, -78.065193],
["bowieMD", 39.006777, -76.779136],
["anneArundelCountyMD", 38.953011, -76.548823],
["shenandoahVA", 38.483457, -78.849748],
["calvertCountyMD", 38.494950, -76.502574],
["salsiburyMD", 38.360674, -75.599369],
["berlinMD", 38.322615, -75.217689],
["ocMD", 38.336503, -75.084906],
["lynchburgVA", 37.413754, -79.142246]
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: new google.maps.LatLng(39.488560, -78.065193)
});
for(var i = 0; i < locations.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
icon: 'images/pin-cloud.png',
animation: google.maps.Animation.DROP,
map: map
});
}
var blairCountyContentString =
'<div id="content">'+
'<div id="siteNotice">'+
'</div>'+
'<h1 id="firstHeading" class="firstHeading">Blair County, PA</h1>'+
'<div id="bodyContent">'+
"<p>insert info here</p>" +
'<p><b>Resources</b>: <a href="https://efc.umd.edu/assets/sw_case_studies/blair_county_final.pdf" <span>Case Study Blair County, PA</span> </a></p>'+
'</div>'+
'</div>';
var blairCountyInfowindow = new google.maps.InfoWindow({
content: blairCountyContentString,
position: locations[0]
});
marker.addListener('click', function() {
blairCountyInfowindow.open(map, marker);
});
My issue seems to be with the "position: locations[0]" object literal. Sometimes I get an error stating that this needs to be a number value of lng, lat...Tried it though with no luck. The window currently opens but only for the last index of the array. Any ideas?
See updated Code. Now customize the infowindow content
Fiddle link
function initMap() {
var marker = [];
var locations = [
["blairCountyPA", 40.453132, -78.384223],
["scrantonPA", 41.408969, -75.662412],
["warringtonTownshipPA", 40.250319, -75.166212],
["lancasterCountyPA", 40.046657, -76.178374],
["berkeleyCountyWV", 39.488560, -78.065193],
["bowieMD", 39.006777, -76.779136],
["anneArundelCountyMD", 38.953011, -76.548823],
["shenandoahVA", 38.483457, -78.849748],
["calvertCountyMD", 38.494950, -76.502574],
["salsiburyMD", 38.360674, -75.599369],
["berlinMD", 38.322615, -75.217689],
["ocMD", 38.336503, -75.084906],
["lynchburgVA", 37.413754, -79.142246]
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: new google.maps.LatLng(39.488560, -78.065193)
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
var ContentString =
'<div id="content">' +
'<div id="siteNotice">' +
'</div>' +
'<h1 id="firstHeading" class="firstHeading">' + locations[i][0] + '</h1>' +
'<div id="bodyContent">' +
"<p>insert info here</p>" +
'<p><b>Resources</b>: <a href="https://efc.umd.edu/assets/sw_case_studies/blair_county_final.pdf" <span>Case Study ' + locations[i][0] + '</span> </a></p>' +
'</div>' +
'</div>';
return function() {
infowindow.setContent(ContentString);
infowindow.open(map, marker);
}
})(marker, i));
}
}

multiple markers with infowindows

I want to add multiple markers and infowindows that activated with a click.
I am having trouble to present the relevant infowindow of the marker, after a click the same infowindow open for all markers.
The information comes from a for loop
this is the code
function GetMarkerSuccess(results) {
results = $.parseJSON(results.d);
markers = [];
infowindows = [];
for (var i = 0; i < results.length; i++) {
var myLatLng = { lat: results[i].Latitude, lng: results[i].Longitude };
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
icon:'images/car.png'
});
var infowindow = new google.maps.InfoWindow({
content: "<div style='text-align:right'><h3>" + results[i].Date.substring(0, 10) + "</h3><p> התחלה: " + results[i].Starttime + " סיום: " + results[i].Endtime + "</p><p> &#8362 מחיר:" + results[i].Price + "</p></div>"
});
markers.push(marker);
infowindows.push(infowindow);
listenMarker(marker);
function listenMarker(marker) {
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
}
}
function GetMarkerSuccess(results) {
results = $.parseJSON(results.d);
markers = [];
infowindows = [];
for (var i = 0; i < results.length; i++) {
var myLatLng = { lat: results[i].Latitude, lng: results[i].Longitude };
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
icon:'images/car.png'
});
var infowindow = new google.maps.InfoWindow({
content: "<div style='text-align:right'><h3>" + results[i].Date.substring(0, 10) + "</h3><p> התחלה: " + results[i].Starttime + " סיום: " + results[i].Endtime + "</p><p> &#8362 מחיר:" + results[i].Price + "</p></div>"
});
markers.push(marker);
infowindows.push(infowindow);
listenMarker(marker);
function listenMarker(marker) {
google.maps.event.addListener(marker,'click', (function(marker,content,infowindow){
return function() {
infowindow.setContent(content);
infowindow.open(map,marker);
};
})(marker,content,infowindow));
}
}
}

Google Maps API - only one infowindow open at once

Here is the map I am working on. I'm trying to have only one infowindow open at a time, and the open infowindow will close when the map or another marker is clicked.
I know this has been asked and answered several times already, but I've attempted to go through those examples and can't figure out how to apply them to my specific code, which pulls photos from Flickr and puts them in infowindows tied to markers. I'm pretty sure the solution involves creating a single infowindow and changing its content.
updated fiddle displaying issue
code snippet (from fiddle):
var lat = 0;
var long = 0;
$(document).ready(function() {
$.getJSON("https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=14fca78b18f8e8f4d22216494ea29abf&user_id=136688117%40N05&has_geo=1&extras=geo&format=json&jsoncallback=?", displayImages3);
function displayImages3(data) {
$.each(data.photos.photo, function(i, item) {
lat = item.latitude;
lng = item.longitude;
var photoURL = 'https://farm' + item.farm + '.staticflickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_m.jpg';
var linkURL = 'https://www.flickr.com/photos/' + item.owner + '/' + item.id + '';
htmlString = '<img src="' + photoURL + '">';
var contentString = '<div id="content">' + htmlString + '</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var myLatlngMarker = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({
position: myLatlngMarker,
map: myMap
});
marker.setIcon('https://www.sherrihill.com/static/skin/images/pinkdot_pink-dot.png');
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(myMap, marker);
});
});
}
});
var myLatlngCenter = new google.maps.LatLng(46.140743, -116.682910);
var mapOptions = {
center: myLatlngCenter,
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var myMap = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
html {
height: 100%
}
body {
height: 100%;
margin: 0;
padding: 0
}
#map_canvas {
height: 100%
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<title>Cascadia Panamericana</title>
<div id="map_canvas"></div>
Make a single infowindow in the global scope. Re-use it to display the content for each marker. In this example I add the HTML content for the infowindow as a property of the marker, then access it in the marker click event listener with this.htmlContent.
var contentString = '<div id="content">' + htmlString + '</div>';
var myLatlngMarker = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({
position: myLatlngMarker,
map: myMap,
icon: 'https://www.sherrihill.com/static/skin/images/pinkdot_pink-dot.png',
htmlContent: contentString
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(this.htmlContent);
infowindow.open(myMap, this);
});
working code snippet:
var lat = 0;
var long = 0;
var infowindow = new google.maps.InfoWindow({});
$(document).ready(function() {
$.getJSON("https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=14fca78b18f8e8f4d22216494ea29abf&user_id=136688117%40N05&has_geo=1&extras=geo&format=json&jsoncallback=?", displayImages3);
function displayImages3(data) {
$.each(data.photos.photo, function(i, item) {
lat = item.latitude;
lng = item.longitude;
var photoURL = 'https://farm' + item.farm + '.staticflickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_m.jpg';
var linkURL = 'https://www.flickr.com/photos/' + item.owner + '/' + item.id + '';
htmlString = '<img src="' + photoURL + '">';
var contentString = '<div id="content">' + htmlString + '</div>';
var myLatlngMarker = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({
position: myLatlngMarker,
map: myMap,
icon: 'https://www.sherrihill.com/static/skin/images/pinkdot_pink-dot.png',
htmlContent: contentString
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(this.htmlContent);
infowindow.open(myMap, this);
});
});
}
});
var myLatlngCenter = new google.maps.LatLng(46.140743, -116.682910);
var mapOptions = {
center: myLatlngCenter,
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var myMap = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
html {
height: 100%
}
body {
height: 100%;
margin: 0;
padding: 0
}
#map_canvas {
height: 100%
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<title>Cascadia Panamericana</title>
<div id="map_canvas"></div>

Categories

Resources