-2

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.

jbruce95
  • 3
  • 3
  • this `google.maps.event.addListener(map, "click", function (polygon, polyContent) { closeInfos(); })` and this `google.maps.event.addListener(map, "click", function (marker, content) { closeInfos(); });` should be merged in a single bind – GrafiCode Aug 07 '19 at 15:49
  • @GrafiCode, like this? `google.maps.event.addListener(markers, polygons, 'click', (function (markers, polygons, markerContent, polyContent2) { return function () { closeInfos(); infowindow.setContent(markerContent, polyContent2); infowindow.open(map, markers, polygons); infos[0] = infowindow; }; })(markers, polygons, markerContent, polyContent2)); google.maps.event.addListener(map, "click", function (markers, polygons, markerContent, polyContent2) { closeInfos(); });` – jbruce95 Aug 07 '19 at 17:26

1 Answers1

0

Two issues remain.

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

screenshot of resulting map

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>
geocodezip
  • 158,664
  • 13
  • 220
  • 245