昨今、限られた環境(iPhone限定とか)でない限り、JavaScriptのライブラリを使用して作成することが多いと思いますが、その際のお話です。なお、理解するにはMooToolsのクラスの仕様についてある程度知っている必要があります。
汎用ライブラリと目的特化型ライブラリ
有名どころのライブラリではjQueryとかPrototypeとかDojoとかMochiKit(まだあるのか?)とかYUIとかあるのですが、その肝は概ね「JavaScriptのシンプルすぎる実装を拡張する」「めんどくさいブラウザ実装の差異を吸収する」の二点に尽きると思います。他にも色々ありますが、あえて言い切ります。こういうのを「汎用ライブラリ」と呼んでおきます。
では、目的特化型ライブラリとはなにかというと、Google Mapみたいなやつですね。実現したい目的が明確に一つあるというパターンです。Google Mapの場合は「地図を表示する」です。この場合も汎用ライブラリが持っているのと同じような機能(イベント処理など)がついています。
イベントのデリゲート
さて、いまお仕事でMooToolsとGoogle Mapを連携して作っています。今回の案件ではすごく沢山のマップを作る上に、CMSの管理画面も作らなくちゃいけないため、マップの上にポリゴン(半透明のシートみたいなやつ)を描画したり、マップに書いたポリゴンの各頂点の座標情報をDBに保存したりもします。
さらに、2つのライブラリを併用する場合に面倒臭いのは、Google Mapのように特化型のライブラリは替えが効かないということ。それはそれで仕方ないので、せめてGoogle Mapに対する処理を一つのクラス(ex. MoogleMap)にまとめてしまい、外部から利用する場合はMooToolsのAPIですべてなんとかなるようにしたいものです。
というわけで、ラッパークラスをもごもご作ることになるのですが、Google Mapの性質上、独自のイベントがけっこう沢山あります。そのイベントすべてをMooToolsに代替させる必要はないと思いますが、よく使うものに関してはなるべくラッパークラスにデリゲート(委譲)させたくなります。
MooToolsではaddEventというイベントハンドラがあるので、うまいことカスタムイベントを定義して、わかりやすくしようという魂胆ですね。
Google Mapのラッパークラスにカスタムイベントを実装
さて、早速作ってみました。Resultをクリックすると結果が表示されます。
Google Mapがあって、地図をクリックするとマーカーが追加されます。クリック回数が指定した回数(デフォルトは10)で割り切れるときにカスタムイベントdivisibleが発生するというものです。実装の詳細はクラスを見ていただきたいのですが、MooToolsはEventオブジェクトを継承したクラスで下記のように任意のイベントを発生させることができます。
簡単ですね。自前でイベントを発生させるのは超めんどくさい(参考:JavaScript tutorial – DOM events)ので、こういうのが楽です。
また、マーカーをドラッグできるようにしておいて、ドラッグが終了すると、dragendイベントを発生し、リスナー関数にイベントと緯度・経度を渡すようにもしています。
これらのイベントをリッスンするときは、外部からこうします。
var map = new MoogleMap("container"); map.addEvent('divisible', function(e){ //何かする do_something(); });
これだけだとなんの役に立つのかわかりませんが、ボタンとかスライダーなどのコントロールを置いて、それと反応させるようにすれば、色々夢は広がるかもしれません。まあ、かなり大掛かりなものを作るのではない限り、あんまりやらなくてもいいかもしれませんが、Javascriptはイベントドリブンなので、デリゲートパターンとかよく知らなくても整理しやすくなるかも。
ちなみに、Optionsオブジェクトの継承は必須ではありませんが、下記のような構文が可能になるので、便利です。
var map = new MoogleMap("map", { onDivisible: function(e){ alert(e + '回クリックされました'); } });
MooToolsの疑似イベントについてもちょっと
MooToolsはMore 1.3から疑似イベント(Event.Pseudos)というのがサポートされました。
こんな感じで使えます。
$('button').addEvent('click:once', function(e){ //一回目しか出ません alert("あなたとはお別れです"); }); $('button').addEvent('click:throttle(1000)', { //1秒(1000ms)に一回しか実行されません。 alert('1秒経ちました'); }); $('button').addEvent('click:pause(1000)', { //最初にクリックされてから1秒間クリックされないと発生します alert('1秒経ちましたよ!クリックしてください'); });
言ってみればイベント処理を楽にしてくれるのが疑似イベントなのですが、この疑似イベント、自分で作ることもできます。詳しくはMooTools1.3のドキュメントを見てください。また、MooTools内でイベントのデリゲートをやるなら、Event.Delegationというのがあります。
まとめ
というわけで、MooToolsを使ったイベント処理を「使う側」ではなく、「作る側」から考え得てみました。jQueryじゃないんで、あんまり需要がないと思いますが…
ただ、node.jsとかのサーバサイドJSが本格化してきたら、MooToolsのクラス構造などを利用して結構楽にできるんじゃないかと思います。世界中のMooToolerの尊敬を集めているDavid Walsh先生はMooToolsでNode.jsを利用する方法(英文)を書いてますよ。