Attaching different infowindows to group of polygons google maps

379 views Asked by At

Right now my code looks like this:

   // create a LatLng array out of given coordinates string
  for (var i = 0; i < coordinateString.length; i++) {
    var polygonCoords = new Array();
    var j = 0;
    var z = j + 1;
    while (z < coordinate.length) 
    {
      if ((j%2) === 0) 
      {
        var coord1 = parseFloat(coord[z]);
        var coord2 = parseFloat(coord[j]);
        var newLatLng = new google.maps.LatLng(coord1,coord2);
        polygonCoords.push(newLatLng);
        } else 
        {
            var coord1 = parseFloat(coord[j]);
            var coord2 = parseFloat(coord[z]);
            var newLatLng = new google.maps.LatLng(coord1,coord2);
            polygonCoords.push(newLatLng);
        }
    z++;
    j++;
    }

    /** Adds the polygon to a polygon array
    * and maps it onto the map
    */

         var newPoly = new google.maps.Polygon(
          {
            paths: polygonCoords,
            strokeColor: objArray[i].borderColor,
            strokeOpacity: 0.8,
            strokeWeight: 2,
            fillColor: objArray[i].fillColor,
            fillOpacity: 0.35
            })
          newPoly.setMap(map);
          newPoly.set("eventNum",objArray[i].eventID)
          newPoly.set("offTime", objArray[i].offTime)

           function attachInfoWindow(event) 
            {
              var infowindowPoly = new google.maps.InfoWindow();
              var eventNo = newPoly.get("eventNum");
              var outTime = newPoly.get("offTime");
              var resTime = objArray[i].restoreTime;
              var contentString = "Event Number: " + eventNo + "<br> Outage Time: " + outTime + "<br> Estimated Restoration Time: " + resTime;
              infowindowPoly.setContent(contentString);
              infowindowPoly.setPosition(event.latLng);
              infowindowPoly.open(map);
              google.maps.event.addListener(map, 'click', function() 
                {
                  infowindowPoly.close();
                });
            }
          google.maps.event.addListener(newPoly, 'click', attachInfoWindow); 
         }
       }

Which creates an array of polygons in different positions (its looping, so everytime a new polygon is created and set to the map) and when clicked an infowindow pops up and displays some content, except it is the same content. However I want to display different infowindows for each polygon. I've read all the other similar questions and answers and have modified my code.

Note that, I've stored objects holding the content I want into an array and am using indexes and other ways to grab properties of the object and then display it as my infowindow content.

2

There are 2 answers

1
geocodezip On BEST ANSWER

Create a function to return the click listener function. Pass the index and the polygon into that function so you get function closure on them to keep them associated:

function attachInfoWindow(newPoly, i) {
    return function (event) {
        var eventNo = newPoly.get("eventNum");
        var outTime = newPoly.get("offTime");
        var resTime = objArray[i].restoreTime;
        var contentString = "Event Number: " + eventNo + "<br> Outage Time: " + outTime + "<br> Estimated Restoration Time: " + resTime;
        infowindowPoly.setContent(contentString);
        infowindowPoly.setPosition(event.latLng);
        infowindowPoly.open(map);
        google.maps.event.addListener(map, 'click', function () {
            infowindowPoly.close();
        });
    };
}

Call the function like this:

for (var i = 0; i < numOfPolygons; i++) {
    var newPoly = new google.maps.Polygon({
        paths: polygons[i],
        strokeColor: objArray[i].borderCol,
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: objArray[i].fill,
        fillOpacity: 0.35
    });
    newPoly.setMap(map);
    newPoly.set("eventNum", objArray[i].eventID);
    newPoly.set("offTime", objArray[i].offTime);

    google.maps.event.addListener(newPoly, 'click', attachInfoWindow(newPoly, i));
}

proof of concept fiddle

code snippet:

function attachInfoWindow(newPoly, i) {
  return function(event) {
    var eventNo = newPoly.get("eventNum");
    var outTime = newPoly.get("offTime");
    var resTime = objArray[i].restoreTime;
    var contentString = "Event Number: " + eventNo + "<br> Outage Time: " + outTime + "<br> Estimated Restoration Time: " + resTime;
    infowindowPoly.setContent(contentString);
    infowindowPoly.setPosition(event.latLng);
    infowindowPoly.open(map);
    google.maps.event.addListener(map, 'click', function() {
      infowindowPoly.close();
    });
  };
}

function initialize() {
  map = new google.maps.Map(
    document.getElementById("map_canvas"), {
      center: new google.maps.LatLng(37.4419, -122.1419),
      zoom: 13,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
  var bounds = new google.maps.LatLngBounds();
  var polygons = [];

  for (var j = 0; j < coordinateStrings.length; j++) {
    var coordinates = coordinateStrings[j].split(" ");
    var polygonCoords = [];
    for (var i = 0; i < coordinates.length; i++) {
      var point = coordinates[i].split(",");
      var latlng = new google.maps.LatLng(parseFloat(point[1]), parseFloat(point[0]));
      bounds.extend(latlng);
      polygonCoords.push(latlng);
    }
    polygons.push(polygonCoords);
  }

  /** Adds the polygon to a polygon array
   * and maps it onto the map
   */
  var numOfPolygons = objArray.length;

  for (var i = 0; i < numOfPolygons; i++) {
    var newPoly = new google.maps.Polygon({
      paths: polygons[i],
      strokeColor: objArray[i].borderCol,
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: objArray[i].fill,
      fillOpacity: 0.35
    });
    newPoly.setMap(map);
    newPoly.set("eventNum", objArray[i].eventID);
    newPoly.set("offTime", objArray[i].offTime);


    google.maps.event.addListener(newPoly, 'click', attachInfoWindow(newPoly, i));
  }
  map.fitBounds(bounds);
}

google.maps.event.addDomListener(window, "load", initialize);
var geocoder;
var map;
var infowindowPoly = new google.maps.InfoWindow();
var objArray = [{
  borderCol: "#FF0000",
  fill: "#FF0000",
  eventID: 1,
  offTime: "12:10"
}, {
  borderCol: "#0000FF",
  fill: "#0000FF",
  eventID: 2,
  offTime: "12:00"
}, {
  borderCol: "#00FF00",
  fill: "#00FF00",
  eventID: 3,
  offTime: "12:20"
}];
var coordinateStrings = ["-82.4908447265625,42.99058552185121,0 -82.52174377441406,43.013182961445914,0 -82.42286682128906,43.02573350308799,0 -82.38578796386719,42.98958099829517,0 -82.452392578125,42.96596996868038,0 -82.45857238769531,42.99359899401497,0",
  "-82.33840942382812,42.96094517567432,0 -82.33016967773438,43.014689161895184,0 -82.23129272460938,43.04079076668198,0 -82.23197937011719,42.954412331213284,0",
  "-82.4139404296875,43.062868070571454,0 -82.38372802734375,43.014689161895184,0 -82.22442626953125,43.06387139555526,0 -82.276611328125,43.15209968803547,0 -82.37411499023438,43.141078106345844,0"
];
html,
body,
#map_canvas {
  height: 500px;
  width: 500px;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>

1
Michael Geary On

One problem here is that you have a variable i that is updated each time through the loop, and you're using that variable in an asynchronous callback. But that callback function is called long after the loop has completed, so i does not have the value you expect.

You can fix this by creating a function for the loop body and calling that function each time through the loop. This way, every function parameter and variable defined inside the function is local to that specific invocation of the function - so it has the value that matches the individual polygon you're working with.

It might look something like this:

      for (var i = 0; i<numOfPolygons; i++) {
          addPoly( objArray[i] );
      }

      function addPoly( source ) {
         var newPoly = new google.maps.Polygon(
          {
            paths: polygonCoords,
            strokeColor: source.borderCol,
            strokeOpacity: 0.8,
            strokeWeight: 2,
            fillColor: source.fill,
            fillOpacity: 0.35
            })
          newPoly.setMap(map);
          newPoly.set("eventNum",source.eventID)
          newPoly.set("offTime", source.offTime)
           function attachInfoWindow(event) 
            {
              var infowindowPoly = new google.maps.InfoWindow();
              var eventNo = newPoly.get("eventNum");
              var outTime = newPoly.get("offTime");
              var resTime = source.restoreTime;
              var contentString = "Event Number: " + eventNo + "<br> Outage Time: " + outTime + "<br> Estimated Restoration Time: " + resTime;
              infowindowPoly.setContent(contentString);
              infowindowPoly.setPosition(event.latLng);
              infowindowPoly.open(map);
              google.maps.event.addListener(map, 'click', function() 
                {
                  infowindowPoly.close();
                });
            }
          google.maps.event.addListener(newPoly, 'click', attachInfoWindow); 
         }
       }