CreateJSのイベント周りの仕組み


CreateJSのライブラリ群（EaselJS、TweenJS、SoundJS、PreloadJS）で共通して使えるイベント周りの仕組みのまとめ。とはいえ、今回もドキュメントの訳みたいになってしまった。

記事に対応するライブラリのバージョン

| library   | version |
|:----------|:-------:|
| EaselJS    | 0.7.1   |
| TweenJS   | 0.5.1   |
| SoundJS   | 0.5.2   |
| PreloadJS | 0.4.1   |

## 概要

CreateJSのイベントの仕組みは`Event`クラスと`EventDispatcher`クラスにより提供されています。DOMのイベントモデルと似たような感じになっています。JavaScriptのライブラリではよくあるイベント周りの実装だと思います。

EaselJSなどの各ライブラリは`EventDispatcher`を継承するなりMixinするなりして、CreateJS共通のイベントモデルを使えるようにしています。直接関係するクラスは以下のような感じ（漏れてるかも）。`Extends`と`Uses`は実装を見れば違いがわかると思う。

EaselJS

- [DisplayObject Class](http://www.createjs.com/Docs/EaselJS/classes/DisplayObject.html): Extends EventDispatcher
- [MouseEvent Class](http://www.createjs.com/Docs/EaselJS/classes/MouseEvent.html): Uses EventDispatcher
- [Ticker Class](http://www.createjs.com/Docs/EaselJS/classes/Ticker.html): Uses EventDispatcher
- [SpriteSheet Class](http://www.createjs.com/Docs/EaselJS/classes/SpriteSheet.html): Extends EventDispatcher
- [SpriteSheetBuilder Class](http://www.createjs.com/Docs/EaselJS/classes/SpriteSheetBuilder.html): Extends EventDispatcher

TweenJS

- [Timeline Class](http://www.createjs.com/Docs/TweenJS/classes/Timeline.html): Extends EventDispatcher
- [Tween Class](http://www.createjs.com/Docs/TweenJS/classes/Tween.html): Extends EventDispatcher

SoundJS

- [Sound Class](http://www.createjs.com/Docs/SoundJS/classes/Sound.html): Uses EventDispatcher
- [SoundInstance Class](http://www.createjs.com/Docs/SoundJS/classes/SoundInstance.html): Extends EventDispatcher

PreloadJS

- [AbstractLoader Class](http://www.createjs.com/Docs/PreloadJS/classes/AbstractLoader.html): Extends EventDispatcher


だいたい基底クラスで使えるようになっているので、ほとんどのクラスでイベントモデルが使えるようになっています。


## EventDispatcher

イベントの発火とイベントリスナーを管理するクラス。
自作クラスで`EventDispatcher`の機能使いたければ以下のようにする。これは便利。

```Javascript
EventDispatcher.initialize(MyClass.prototype);
```

以下はよく使いそうなメソッド
### addEventListener ( type, listener, [useCapture] ) 
オブジェクトにリスナーを加える。第3引数はDOMイベントのキャプチャリングおよびバブリングと似たようなパラメータ。displayObjectみたいな階層構造をもつオブジェクトで使える。

```Javascript
displayObject.addEventListener('click', handleClick);
function handleClick(event) {
  // Click happened.
}
```


### removeEventListener ( type, listener, [useCapture] )
オブジェクトからリスナーを削除する。

```Javascript
displayObject.removeEventListener("click", handleClick);
```

### removeAllEventListeners( [type] )
引数に対応するイベントタイプのすべてのリスナーを削除する。引数を省略すると、全リスナーを削除する。

```Javascript
// 全リスナー削除
displayObject.removeAllEventListeners();

// clickイベントのすべてのリスナー削除
displayObject.removeAllEventListeners('click');
```

### dispatchEvent ( eventObj, [target] ) 

イベントを発火させる。第1引数はイベントタイプの文字列かイベントオブジェクトを渡せる。第2引数は、イベントオブジェクトの`target`プロパティを指定できるみたいですが、非推奨なのでそのうち消されるらしい。

```Javascript
// 文字列で指定
this.dispatchEvent('complete');

// イベントオブジェクトで指定
var event = new createjs.Event('progress');
this.dispatchEvent(event);
```

### hasEventListener ( type )
引数で指定したイベントタイプのリスナーがあるかどうかをBoolean返す。

### on ( type, listener, [scope], [once=false], [data], [useCapture=false] ) 
`addEventListener`のエイリアスかと思いきや、ちょっと違う。大きな違いは第2引数に渡す関数がそのままリスナーとして追加されるのではない所。内部的には無名関数でラップされたものがリスナーとして追加される。`removeEventListener`するときは`on`の返り値（リスナー）を使う必要がある。
第3引数はリスナーのコンテキストの指定みたいなもの。第4引数はjQueryの`once`と同じ。第4引数はリスナーの第2引数として渡すオブジェクト。

```Javascript
var listener = myBtn.on('click', handleClick, null, false, {count:3});
    function handleClick(evt, data) {
        data.count -= 1;
        console.log(this == myBtn); // true → scopeがnullなので
        if (data.count == 0) {
            alert('3回クリックされた');
            myBtn.off('click', listener);// evt.remove(); でもいける。
        }
    }
```

### off ( type, listener, [useCapture] )
こっちは完全に`removeEventListener`のエイリアス

## Eventクラス

イベントオブジェクトのクラス。
DOMのイベントモデルと同様なプロパティやメソッドが使える。基本的には階層構造を作れる表示オブジェクトで使われる。

### type `String`
イベントタイプ

### bubbles `Boolean`
イベントがバブリングするかどうか

### cancelable `Boolean`
イベントをキャンセル可能かどうか

### preventDefault ()
DOMイベントと同じ

### stopPropagation ()
DOMイベントと同じ

### stopImmediatePropagation ()
DOMイベントと同じ

### remove ()
イベントオブジェクトからリスナーを削除できる。これは結構便利だと思った。

```Javascript
myBtn.addEventListener('click', function(evt) {
  evt.remove(); // リスナーを削除
});
```