简体   繁体   中英

Listener event always triggers with last element's info

I'm trying to make a map-based application, but I'm having bit of difficulty. The original code I had been working with added a separate InfoWindow for each marker, but I'd like to get it using a single InfoWindow for which I can set the content on the fly.

However, I still seem to be a little fuzzy on how JavaScript behaves, because each time any marker is clicked the InfoWindow pops up over the last marker and the alert indicates the ID of the last entry in locations .

Short snippet, problem highlighted:

function plotLocations(my_locations) {
    locations = my_locations;
    for(var i=0; i<locations.length; i++) {
        var pos = new google.maps.LatLng(locations[i].loc_lat, locations[i].loc_lng);
        var icon = new google.maps.MarkerImage(
            "http://goo.gl/TQpwU",
            new google.maps.Size(20,32),
            new google.maps.Point(0,0),
            new google.maps.Point(0,32)
        );
        var marker = new google.maps.Marker({
            map: map,
            position: pos,
            animation: google.maps.Animation.DROP,
            icon: icon
        });
// ! -- trouble right here -- ! //
        google.maps.event.addListener(marker, 'click', function() {
            setPopInfo(pos, i);
        });
// ! -- ------------------ -- ! //
    }
}

function setPopInfo(pos, index) {
    pop_info.setPosition(pos);
    pop_info.open(map);
    window.alert(pos+"::"+index);
}

Most of the rest of my code:

var map;
var mapBounds;
var locations;
var pop_info;

$(document).ready(init);

function init() {
    var mapOptions = {
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
    pop_info = new google.maps.InfoWindow({
        content: "I'm not populated!",
        size: new google.maps.Size(100,25)
    });
    google.maps.event.addListener(map, 'bounds_changed', function() {
        queryLocations(map.getBounds());
    });

    prepareGeolocation();
    doGeolocation();
}

function queryLocations(bounds) {
    jQuery.ajax({
        url: 'http://mydomain.com/myapp/test2.php',
        data: bounds.toString(),
        dataType: 'json',
        success: addLocations
    });
}

function addLocations(new_locations) {
    document.getElementById('footer').innerHTML = new_locations;
    plotLocations(new_locations);
}

My reasoning for the single InfoWindow is that once a few hundred Markers and InfoWindows have been created the performance might take a nosedive. Is what I'm trying to do feasible/advisable?

The problem occurs because you're defining your event listener callback function inside the loop. Closures refer to their context dynamically rather than binding to a copy of the data at the time of definition, so you have effectively created locations.length number of functions that are all bound to the same values of marker , pos and i , which are whatever they happened to be when the loop terminated.

To work round this, you could create a function that calls addListener outside the body of the loop, like so:

function plotLocations (my_locations) {
    locations = my_locations;
    for(var i=0; i<locations.length; i++) {
        var pos = new google.maps.LatLng(locations[i].loc_lat, locations[i].loc_lng);
        var icon = new google.maps.MarkerImage(
            "http://goo.gl/TQpwU",
            new google.maps.Size(20,32),
            new google.maps.Point(0,0),
            new google.maps.Point(0,32)
        );
        var marker = new google.maps.Marker({
            map: map,
            position: pos,
            animation: google.maps.Animation.DROP,
            icon: icon
        });
        bindEvent(marker, pos, i);
    }
}

function bindEvent (marker, pos, i) {
    google.maps.event.addListener(marker, 'click', function() {
        setPopInfo(pos, i);
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM