Google-Maps-for-Railsで情報ウィンドウを開くイベントを発生させる

# はじめに
[Google-Maps-for-Rails](https://github.com/apneadiving/Google-Maps-for-Rails)はRailsでGoogle Mapを表示させるためのgemです。本記事では、Google Mapのマーカーに紐付いた情報ウィンドウを開くイベントを発生させる方法を紹介します。

# 環境
- Rails 5.1.4
- Ruby 2.4.1
- gem’gmaps4rails’（https://github.com/apneadiving/Google-Maps-for-Rails）

# 1. 情報ウィンドウを作成する
```Ruby:map_controller.rb
class MapController < ApplicationController
  def index
    @places =Place.all
    @hash = Gmaps4rails.build_markers(@places) do |place, marker|
      marker.lat place.latitude
      marker.lng place.longitude
      marker.infowindow render_to_string( partial: "map/infowindow",
                                          locals: { place: place} )
      marker.json({ id: place.id, })
    end
  end
end
```
```ERB:_infowindow.html.erb
<div>
  <%= link_to "#{place.name}", place %>
</div>
```
上記のように、情報ウィンドウを作成します。イベント発生の際に、マーカーを指定できるようにするため、placeのidをマーカーに付加しておきます。

# 2. マーカーのserviceObjectに情報ウィンドウをセットする

マーカーのserviceObjectに、placeのidとinfowindowをセットします。

```JavaScript:
Gmaps.store = {}
Gmaps.store.markers = markers.map(function(m) {
  marker = handler.addMarker(m);
  marker.serviceObject.set('id', m.id);
  marker.serviceObject.set('infowindow', m.infowindow);
  return marker;
});
```


# 3. 情報ウィンドウのリスナーを追加する

情報ウィンドウのリスナーを追加します。イベント発生時には、指定したidのマーカーの情報ウィンドウを開くようにします。

```JavaScript:
google.maps.event.addListener(handler.getMap(), "open", function(id) {
  $.each(Gmaps.store.markers, function() {
    if (this.serviceObject.id == id) {
      infowindow = new google.maps.InfoWindow({
        content: this.serviceObject.infowindow
      });
      infowindow.open(this.serviceObject.map, this.serviceObject);
    }
  });
});
```

index.html.erbの全体は、以下のようになります。

```ERB:map/index.html.erb
<div class="map_container">
  <div id="map" class="map_canvas"></div>
</div>

<script type="text/javascript">
  handler = Gmaps.build('Google');
  handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
    markers = <%= raw @hash.to_json %>
    Gmaps.store = {}
    Gmaps.store.markers = markers.map(function(m) {
      marker = handler.addMarker(m);
      marker.serviceObject.set('id', m.id);
      marker.serviceObject.set('infowindow', m.infowindow);
      return marker;
    });
    handler.bounds.extendWith(Gmaps.store.markers);
    handler.fitMapToBounds();
    handler.getMap().setCenter(new google.maps.LatLng(35.720969, 139.735877));
    handler.getMap().setZoom(12);
    google.maps.event.addListener(handler.getMap(), "open", function(id) {
      $.each(Gmaps.store.markers, function() {
        if (this.serviceObject.id == id) {
          infowindow = new google.maps.InfoWindow({
            content: this.serviceObject.infowindow
          });
          infowindow.open(this.serviceObject.map, this.serviceObject);
        }
      });
    });
  });
</script>
```
# 4. イベントを発生させる
あとは、下記でイベントを発生させることで、指定した情報ウィンドウを開くことができます。

``` JavaScript:
google.maps.event.trigger(handler.getMap(), "open", id);
```

<img width="649" alt="スクリーンショット 2018-01-21 18.37.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/154756/a0b66711-3b37-de17-2cd3-8eb5e5c1f7c9.png">

#### 問題点
イベントを発生させると、マーカーをクリックしたときに、二重に情報ウィンドウを開いてしまう。
#### 解決法
以下のコードを追記することで、クリックイベントで開いた情報ウィンドウを閉じることが出来ます。

``` JavaScript:
if (handler.currentInfowindow()) {
  handler.currentInfowindow().close();
}
```

# まとめ
Google-Maps-for-Railsを使用して、Google Mapのマーカーに紐付いた情報ウィンドウを開くイベントを発生させる方法を紹介しました。この方法を利用して、マーカーのクリックイベント以外でも、好きなタイミングで指定したマーカーの情報ウィンドウを開くことができます。