Search code examples
google-maps-api-3gmaps4railsmarkerclusterer

How do you add an infowindow to a cluster marker?


The documentation and stackoverflow tickets are very sparse in this area.

I want to open an infowindow when a user mouseover's a cluster marker. I want this infowindow to be generated using two things, a piece of data from the clusters's markers, and a rails partial.

How do I:

  1. add a mouseover listener to a cluster
  2. get the markers inside the cluster (select the right object) create an infowindow for this
  3. cluster based on a partial (using data from the above)

I am using google maps for rail's gem and the Marker Clusterer Plus libary.

I have the following in my builder:

handler = Gmaps.build("Google",
  { markers:
    { clusterer: {
        gridSize: 8,
        maxZoom: 12,
        zoomOnClick: true,
        styles: [ {
              textSize: 1,
              textColor: '#45A6DD',
              url: 'images/maps/cluster.marker.png',
              height: 51,
              width: 51 }
            ]
      }
    },
    builders: {
      Marker: KhMarker
    }
  });

And I have added the following script onto the page with the map. This listens for the 'clusterclick' event. I would like to use the MarkerClustererPlus mouseover event, but I can't figure out which js object I should pass into the addListener event.

    google.maps.event.addListener(handler.clusterer.getServiceObject(), 'clusterclick', function(cluster) {
      // console.log("Cluster clicked")

      var content = '';

      content = this;
      console.log (content)

      // Convert lat/long from cluster object to a usable MVCObject
      // var info = new google.maps.MVCObject;
      // info.set('position', cluster.center_);

      // var infowindow = new google.maps.InfoWindow();
      // infowindow.close();
      // infowindow.setContent();

      // infowindow.open(handler.map.getServiceObject(), info);
    });

In the console I am seeing the MarkerClusterer object, but what I am trying to get is the specific cluster I just moused over and the markers it contains. I need to grab the city name (or lat/long) of the first marker to then get the region it is from so I can pass this data to the infowindow.

I can get a basic infowindow to open on click. I want to have the infowindow open from a partial similar to the way that my markers do.

  marker.infowindow render_to_string(partial: "/destinations/map_tile.html", locals: { city: city })

How do I do these 3 things?


Solution

  • UPDATE:

    Using google maps api, and the marker cluster plus documentation I was able to piece most of this together.

    I was able to add these 3 things, but I now need 1 last piece (answered out of order):

    1. add a mouseover listener to a cluster

        google.maps.event.addListener(handler.clusterer.getServiceObject(), 'mouseover', function(cluster) {
            // Convert lat/long from cluster object to a usable MVCObject
            var info = new google.maps.MVCObject;
            info.set('position', cluster.center_);
      
            var city_lat = cluster.getMarkers().shift().position.d
      
            if (city_lat !== undefined) {
              var cluster_stuff = cities_with_lat[city_lat]
      
              var infowindow = new google.maps.InfoWindow({
                content: cluster_stuff
              });
              infowindow.open(handler.map.getServiceObject(), info);
            };
        });
      
    2. cluster infowindow based on a partial (using data from the above)

    I also created an object with latitudes for keys, and values with the partials.

    var cities_with_lat = {
      <% @cities_for_map.each do |city| %>
        <% if city.areas.present? %>
          <% render 'map_tile', city: nil, area_info: city.areas.first %>
          <%= city.latitude %>: "<%= escape_javascript(render 'map_tile', city: nil, area_info: city.areas.first)  %>",
        <% end %>
      <% end %>
    }
    
    1. get the markers inside the cluster (select the right object) create an infowindow for this

    I then found marker and matched it with the city via the latitude key. See the above 2 code snippets.

    1. Lastly I wanted the infowindow Look and behave like the regular markers, to do this I created a new function:

      clusterMarker: function(cluster, cities_with_lat) { var city_lat = cluster.getMarkers();

      cluster_marker = new google.maps.Marker({
       map: handler.map.getServiceObject(),
       position: new google.maps.LatLng(cluster.center_.d, cluster.center_.e),
       visible: false
      });
      
      var boxText = document.createElement("div");
      boxText.innerHTML = cities_with_lat[city_lat[0].position.d];
      
      var myOptions = {
         content: boxText
        ,disableAutoPan: true
        ,closeBoxURL: ""
        ,pane: "floatPane"
        ,enableEventPropagation: false
      };
      
      ib = new InfoBox(myOptions);
      ib.open(handler.map.getServiceObject(), cluster_marker);
      _closeClusterInfowindow(ib);
      

      } };

    I fed this function an object with compiled partials from a rails helper. This object was escaped and passed to javascript. This object had the latitude of the city as a key and the partial of its respective area as a value.

      var cities_with_lat = <%= cities_with_lat_obj %>;