Search code examples
javascriptgoogle-maps-api-3infowindow

Google Maps Javascript two InfoWindow for the same marker


I would like to add an infoWindow that is always visible (like the title label but always visible) and another which is shown when the user clicks on the marker (aka the normal behavior). Currently my for loop for adding the markers look like this:

for (i = 0; i < markers.length; i++) {
        var data = markers[i];
        var icon = "";
        icon = "/images/map-icon.png";
        var position = new google.maps.LatLng(data.lat, data.lng);
        bounds.extend(position);
        marker = new google.maps.Marker({
            position: position,
            map: map,
            title: data.title,
            icon: new google.maps.MarkerImage(icon)
        });

        (function (marker, data) {
            google.maps.event.addListener(marker, "click", function (e) {
                infoWindow.setContent(data.description);

                infoWindow.open(map, marker);
            });
        })(marker, data);

        map.fitBounds(bounds);
        map.setCenter(bounds.getCenter());
        map.fitBounds(bounds);
    }

Solution

  • One option: Create a fixed InfoWindow for each marker, opened when created, then one dynamic InfoWindow with the "normal" InfoWindow behavior which opens on top of the fixed InfoWindow.

    for (i = 0; i < markers.length; i++) {
      var data = markers[i];
      var position = new google.maps.LatLng(data.lat, data.lng);
      bounds.extend(position);
      marker = new google.maps.Marker({
        position: position,
        map: map,
        title: data.title,
      });
      // fixed always open InfoWindow
      marker.iw = new google.maps.InfoWindow();
      marker.iw.setContent(data.title);
      marker.iw.open(map, marker);
    
      // dynamic InfoWindow, opened on click
      (function(marker, data) {
        google.maps.event.addListener(marker, "click", function(e) {
          infoWindow.setContent(data.description);
          infoWindow.open(map, marker);
        });
      })(marker, data);
    
      map.fitBounds(bounds);
    }
    

    proof of concept fiddle

    screenshot of resulting map

    code snippet:

    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 10,
        center: {
          lat: -33.9,
          lng: 151.2
        }
      });
    
      setMarkers(map);
    }
    
    var markers = [{
        description: 'Bondi Beach',
        lat: -33.89042,
        lng: 151.274856,
        title: "Bondi"
      },
      {
        description: 'Coogee Beach',
        lat: -33.923036,
        lng: 151.259052,
        title: "Coogee"
      },
      {
        description: 'Cronulla Beach',
        lat: -34.028249,
        lng: 151.157507,
        title: "Cronulla"
      },
      {
        description: 'Manly Beach',
        lat: -33.80010128657071,
        lng: 151.28747820854187,
        title: "Manly"
      },
      {
        description: 'Maroubra Beach',
        lat: -33.950198,
        lng: 151.259302,
        title: "Maroubra"
      }
    ];
    
    function setMarkers(map) {
      var infoWindow = new google.maps.InfoWindow();
      var bounds = new google.maps.LatLngBounds();
      for (i = 0; i < markers.length; i++) {
        var data = markers[i];
        var position = new google.maps.LatLng(data.lat, data.lng);
        bounds.extend(position);
        marker = new google.maps.Marker({
          position: position,
          map: map,
          title: data.title,
        });
        marker.iw = new google.maps.InfoWindow();
        google.maps.event.addListener(marker.iw, 'domready', function() {
          // warning relies on undocumented API behavior
          $("button.gm-ui-hover-effect").hide();
        });
        marker.iw.setContent(data.title);
        marker.iw.open(map, marker);
    
    
        (function(marker, data) {
          google.maps.event.addListener(marker, "click", function(e) {
            infoWindow.setContent(data.description);
    
            infoWindow.open(map, marker);
          });
        })(marker, data);
    
        map.fitBounds(bounds);
      }
    }
    html,
    body,
    #map {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <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>