イベントを活用する

Apache CordovaでGoogle Mapsを表示します。

[phonegap-googlemaps-plugin](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/)というプラグインを使用します。
インストール方法はこちらをご覧ください。
* [Androidのインストール方法](http://qiita.com/wf9a5m75/items/798b847dcd470f8afed9)
* [iOSのインストール方法](http://qiita.com/wf9a5m75/items/863287cc99e4622052ca)

今回はイベントの仕組みを活用し、 **地図ダイアログが閉じた時に地図上のマーカーを全て削除する** という機能を実装します。

#1. イベントとは
イベントとは、ある状態が変化した時にその事を通知する仕組みです。
イベントが発生したことを知るには、イベントリスナを追加します。
１つのイベントに対して、イベントリスナはいくつも追加することが可能です。

例えば、ボタンが押されたという事を検出するには、次のようなコードです。

```js
var button = document.getElementById("button");
button.addEventListener("click", function() {
  console.log("ボタンがクリックされた");
});


button.addEventListener("click", function() {
  alert("ボタンがクリックされた");
});
```

#2. phoengap-googlemaps-pluginでイベント処理
[phonegap-googlemaps-plugin](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/)では、[Map](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/Map)、[Marker](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/Marker)、[Polyline](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/Polyline)、[Polygon](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/Polygon)、[Circle](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/Circle)、[TileOverlay](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/TileOverlay)、[GroundOverlay](https://github.com/wf9a5m75/phonegap-googlemaps-plugin/wiki/GroundOverlay)クラスでは、イベントを使うことができます。

例えば次のようなコードで、これは地図の初期化が完了したことを検出します。

```js
var map = plugin.google.maps.getMap();
map.addEventListener(plugin.google.maps.event.MAP_READY, function(map) {
  console.log("Mapの準備が完了");
});
```

イベントは **何かが変化したことを知る** だけでなく、 **何かが変化したことを知らせる** ためにも使うことができます。

```js
map.addEventListener("MY_EVENT", function() {
  alert("MY_EVENT が発生した");
});

map.trigger("MY_EVENT");
```

イベントと一緒にデータを渡すこともできます。

```js
map.addEventListener("MY_EVENT", function(map, data) {
  alert("MY_EVENT (" +  data + ")が発生した");
});

map.trigger("MY_EVENT", "DATA1");
map.trigger("MY_EVENT", "DATA2");
```

#3. マーカーをまとめて削除する
イベントを使って、マーカーをまとめて削除する、という処理を実装してみます。

まず **イベントを使わない**でコードを書くと、このようになります。
このコードの問題点は、マーカーを削除するためには、all_markers変数にアクセスできる必要があります。
JavaScriptコードを複数のファイルに分割するような場合、１つの変数が他のファイルからもアクセスできるようなコードを書くと、
コードが読みにくくなり、また変数を不意に上書きしてしまう、という危険性もあります。

```js
//マーカーを保持するための配列
var all_markers = [];

//位置の定義
const GOOGLE = new plugin.google.maps.LatLng(37.422858, -122.085065);
const GOOGLE_TOKYO = new plugin.google.maps.LatLng(35.660556,139.729167);
const GOOGLE_SYDNEY = new plugin.google.maps.LatLng(-33.867487,151.20699);
const GOOGLE_NY = new plugin.google.maps.LatLng(40.740658,-74.002089);

//マーカーを追加する
var GOOGLES = [GOOGLE, GOOGLE_TOKYO, GOOGLE_SYDNEY, GOOGLE_NY];
GOOGLES.forEach(function(latLng) {

    map.addMarker({
        'position': latLng
    }, function(marker) {

        //配列にマーカーを追加
        all_markers.push(marker);
    });
});

//ボタンがクリックされたら、マーカーを削除する
var button = document.getElementById("button");
button.addEventListener("click", function() {

    //全てのマーカーをここで削除する
    all_markers.forEach(function(marker) {
        marker.remove();
    });
});
```

そこでイベントを使います。
イベントを使うことで **マーカーを削除しろ** という指示だけを発行し、その処理はそれぞれのイベントリスナに任せるのです。

```js
//位置の定義
const GOOGLE = new plugin.google.maps.LatLng(37.422858, -122.085065);
const GOOGLE_TOKYO = new plugin.google.maps.LatLng(35.660556,139.729167);
const GOOGLE_SYDNEY = new plugin.google.maps.LatLng(-33.867487,151.20699);
const GOOGLE_NY = new plugin.google.maps.LatLng(40.740658,-74.002089);

//マーカーを追加する
var GOOGLES = [GOOGLE, GOOGLE_TOKYO, GOOGLE_SYDNEY, GOOGLE_NY];
GOOGLES.forEach(function(latLng) {

    map.addMarker({
        'position': latLng
    }, function(marker) {

        // MARKER_REMOVEイベントが発行されたら、マーカーを削除する
        map.addEventListener("MARKER_REMOVE", function() {
            marker.remove();
        });
    });
});

//ボタンがクリックされたら、マーカーを削除する
var button = document.getElementById("button");
button.addEventListener("click", function() {

    // MARKER_REMOVEイベントを発行する
    map.trigger("MARKER_REMOVE");
});
```

#4.地図ダイアログが閉じたことを検出する
地図ダイアログが閉じられたことを検出するには、MAP_CLOSEイベントを検出します。

```js
map.addEventListener(plugin.google.maps.event.MAP_CLOSE, function() {
    
    alert("地図が閉じられた");
    
});
```
![img](https://raw.githubusercontent.com/wf9a5m75/phonegap-googlemaps-plugin/Images/snippet/map_close.gif)

#5. 組み合わせる
これらを総合すると、以下のコードで **地図ダイアログが閉じた時に地図上のマーカーを全て削除する** を実現できます。

```js
function onMapReady(map) {
  /**
   * ボタン1が押されたら、地図を表示して、マーカーを追加する
   */
  var button1 = document.getElementById("button1");
  button1.addEventListener("click", function() {
    
    map.showDialog();
  
    /**
     * マーカーの追加
     */
    const GOOGLE = new plugin.google.maps.LatLng(37.422858, -122.085065);
    const GOOGLE_TOKYO = new plugin.google.maps.LatLng(35.660556,139.729167);
    const GOOGLE_SYDNEY = new plugin.google.maps.LatLng(-33.867487,151.20699);
    const GOOGLE_NY = new plugin.google.maps.LatLng(40.740658,-74.002089);
    
    var GOOGLES = [GOOGLE, GOOGLE_TOKYO, GOOGLE_SYDNEY, GOOGLE_NY];
    GOOGLES.forEach(function(latLng) {
      
      map.addMarker({
        'position': latLng
      }, function(marker) {
        
        // MARKER_REMOVEイベントが発行されたら、マーカーを削除する
        map.addEventListenerOnce("MARKER_REMOVE", function() {
          marker.remove();
        });
        
      });
    });
    
    // マーカーが画面に収まるようにカメラの位置を合わせる
    map.moveCamera({
      'target': GOOGLES
    });
    
  });
  
  
  /**
   * 地図ダイアログが閉じられた時、MARKER_REMOVEイベントを発行する
   */
  map.addEventListener(plugin.google.maps.event.MAP_CLOSE, function() {
    map.trigger("MARKER_REMOVE");
  });
  
  
  /**
   * 確認のために、ボタン2を押したら地図ダイアログを表示する
   */
  var button2 = document.getElementById("button2");
  button2.addEventListener("click", function() {
    
    map.showDialog();
    
  }, false);
}
```
![img](https://raw.githubusercontent.com/wf9a5m75/phonegap-googlemaps-plugin/Images/snippet/marker_remove.gif)