简体   繁体   中英

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

  }
}

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

  }
}

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 );
        });
    });
});

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