Question

Alright, this has been a problem for me for 3 days, javascript closures are just not my strong suit.

I have a google map which I've applied an overlay with a series of clickable polygons. I want a specific function to run depending on the polygon clicked, which I have working. The problem is I can't figure out how to work the listener so that a function that displays an infowindow with that polygon's zip code in it. Here's the code:

for (x = 0; x < 50 && coordsObject.length > x; x++) { //Only draw 50 polygons at a time
    ...
    //create zipcoords array

    clickablePolygons.push(new google.maps.Polygon({
        paths: zipCoords
        , strokeColor: "#000"
        , strokeOpacity: 1
        , strokeWeight: 1
        , fillColor: convertRatingToHex(rating)
        , fillOpacity: 0.45
    }));


    infoWindow.push(
        new google.maps.InfoWindow({
           content: '<div id="gcontent">' + zip.toString() + '</div>'
        })
    );

    //problem child
    var theFunction = function(arguments, infowindow, map) {
        var marker = new google.maps.Marker({
            position: arguments[0].latLng
        });

        infowindow.open(map, marker);

    };

    google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function() {
         theFunction(arguments, infoWindow[x], map); //:(
    });


    clickablePolygons[clickablePolygons.length - 1].setMap(map);

}

What am I doing wrong with the closure?

Was it helpful?

Solution

in your addListener call you have function() and not function(arguments). I would also create a variable pointing to the infoWindow outside the call to addlistener. The assumption is that the click event will pass in the arguments that you are expecting. It may need to be function(e,arguments).

var win = infoWindow[x];

google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function(arguments) {
     theFunction(arguments, win, map);
});

OTHER TIPS

Looks like variable scoping problem, give it a try

(function(x){
    google.maps.event.addListener(clickablePolygons[clickablePolygons.length - 1], 'click', function(arg) {
        theFunction(arg, infoWindow[x], map);
    });
})(x);

You do not need multiple instances of an InfoWindow. Just use the methods to set the content and position when needed.

I do not understand why you are adding a marker, is that a requirement? If you just want an InfoWindow to show when the polygon is clicked you can use the MouseEvent object passed from the click event to get the current position of the click.

Here is an example: http://jsfiddle.net/bryan_weaver/akLBM/

code in the link:

var map;
var infoWindow;
var clickablePolygons = [];

function createPolygon(path, stateName) {
    var poly = new google.maps.Polygon({
        paths: path,
        strokeColor: "#000",
        strokeOpacity: 1,
        strokeWeight: 1,
        fillColor: "#330000",
        fillOpacity: 0.45
    });

    //add the polygon to the array, to use later if needed.
    clickablePolygons.push(poly);

    //attach a click event, the first argument of the listener is the event
    //you can get the position of the mouse cursor where the map 
    //was clicked through this.
    google.maps.event.addListener(poly, "click", function (event) {

        //call the setContent method and set the content for the info window
        infoWindow.setContent("This state is: " + stateName);
        //set the anchor of the info window, in this case 
        //I am using the mouse position at
        //the time of the click
        infoWindow.setPosition(event.latLng);
        //open the info window, passing the map in which to attach it to.
        infoWindow.open(map);
    });

    //add the polygon to the map
    poly.setMap(map);
}

function initialize() {
    var myLatLng = 
         new google.maps.LatLng(39.983994270935625, -111.02783203125);
    var mapOptions = {
        zoom: 5,
        center: myLatLng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    //polygon coords for Utah
    var utah = [
    new google.maps.LatLng(41.983994270935625, -111.02783203125),
    new google.maps.LatLng(42.00032514831621, -114.01611328125),
    new google.maps.LatLng(36.96744946416931, -114.01611328125),
    new google.maps.LatLng(37.00255267215955, -109.0283203125),
    new google.maps.LatLng(40.97989806962013, -109.0283203125),
    new google.maps.LatLng(41.0130657870063, -111.02783203125)];

    //polygon coords for Colorado
    var colorado = [
    new google.maps.LatLng(40.96330795307351, -109.05029296875),
    new google.maps.LatLng(36.96744946416931, -109.0283203125),
    new google.maps.LatLng(37.02009820136811, -101.9970703125),
    new google.maps.LatLng(40.97989806962013, -102.06298828125)];

    map = new google.maps.Map($('#map')[0], mapOptions);
    //create a single info window for use in the application
    infoWindow = new google.maps.InfoWindow();

    //add the polygon and infowindow content to the map.
    createPolygon(utah, "Utah");
    createPolygon(colorado, "Colorado");
}

google.maps.event.addDomListener(window, 'load', initialize);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top