JavaScriptのイベントリスナーの話

id:kz_shikabaneによるJavaScript勉強会が実施されました。

DOMの話は以前id:seiryoが行ったので、今回はイベントリスナーについて。
prototype.jsJQueryを使っていてあまり意識したことがなかったので参考になりました。
以下まとめ。

イベントリスナーとは

普通GUIアプリケーションを作るときにはイベントドリブン(イベント駆動型)プログラミングを行います。これはJavaScriptで書くときにも当てはまります。
HTMLファイルが読み込まれた、ボタンがクリックされた、キーボードが押された、といった行動をブラウザで行ったときにイベントは発生します。このイベントを受け取るのがイベントリスナーです。
イベントリスナーはイベントを受け取るまでは何もしません。受け取ったイベントの情報を元にイベントリスナーが、HTMLタグの属性を変更する、非同期にデータを読み込む、といった実際の処理を行います。
この考え方は、ActionScriptJavaGUIアプリケーションを作る時も同じです。

onloadやonclickなどをHTMLタグに書かない理由

JavaScriptに関する記述をHTMLと分けたほうが、HTMLの可読性が上がります。いわゆるビューとロジックの分離ですね。
また、JavaScriptも汎用的に書き易くなるので、再利用できるかもしれません。
ということで、できるだけ外部ファイルに書くようにしましょう。

実際に書く

リスナーは、windowというブラウザ自体をあらわすオブジェクトにwindow.onload=〜のような形で使うこともありますが、DOMで持ってきたエレメントにセットすることのほうが多いと思います。
例によってIEFirefoxではリスナーのセットの書きかたが違います。
以下、elementをクリックした時に、funcという関数を実行してもらいたい場合のそれぞれの例。

IE
//リスナー追加
element.attachEvent("onclick", func);
//リスナー削除
element.detachEvent("onclick", func);
FF
//リスナー追加
element.addEventListener("click", func, true);
//リスナー削除
element.removeEventListener("click", func, true);

onclickとかclickはイベントの名前です。
IEの場合はイベント名の前にonがいります。
以下よく使いそうなイベント名と対応するイベント発生条件。

  • load・・・読み込まれたとき
  • change・・・selectなどを変えたとき
  • click・・・クリックされたとき
  • keydown・・・キーが押されたとき(どのキーが押されたかもわかります)
  • keyup・・・キーが放されたとき
  • keypress・・・キーが押されたとき
  • mousedown・・・マウスがクリックされたとき
  • mouseup・・・マウスのクリックを放したとき
  • mouseover・・・マウスがエレメントの上に来たとき
  • mouseout・・・マウスがエレメントの上から離れたとき

毎回、ブラウザ判定するのは面倒なので、以下のような関数を用意してやるのが一般的なようです。

//追加
function addEventListener(element, type, func) {
    if(element.attachEvent) {
        element.attachEvent("on" + type, func);
    } else {
        element.addEventListener(type, func, true);
    }
}
//削除
function removeEventListener(element, type, func){
    if(element.attachEvent){
        element.detachEvent("on" + type, func);
    }else{
        element.removeEventListener(type, func, true);
    }
}

追記:勉強会補足 - about:blankid:kz_shikabaneによる補足)

addEventListenerの第三引数

リスナーの処理を実行する優先度を決めるものらしいです。
trueだと優先的に実行され、falseだと後回しにされます。
attachEventにはないので、順番を制御するには別の方法が必要です。

おまけ

どんな風にクラスを書くのかという質問をしたら、その場でJavaScriptのクラスの実現の話になりましたが、id:youzakaに「JavaScript OOP におけるクラス定義方法 - IT戦記」を紹介してもらったので、そこを参考にします。
後、id:kz_shikabaneはJSのライブラリを使うときは、ちゃんとソースを読んで動作を確認するそうです。やりますね。