• このエントリーをはてなブックマークに追加
DeLLa.JS 「JavaScript第5版」読書会 #10 on Flickr

はじめに

1月31日(土),2009年最初の DeLLa.JS,「JavaScript第5版」 読書会の10回目を,日本ダイナシステム株式会社様の会議室にて行いました.

今回は,p.405 「17章 イベントとイベント処理」 の最初から読み始め, 「17.4 マウスイベント」 の最後(p.443) で区切りを入れました.

それでは以下,個人的な気づき,というかメモです.

読書会 午前の部

DeLLa.JS 「JavaScript第5版」読書会 #10 on Flickr

冒頭

  • オリジナルイベントモデル: DOM レベル0
  • 標準イベントモデル: DOM レベル2
  • InternetExplorer イベントモデル
  • IE7でもそのままっぽい

17.1 基本的なイベント処理

  • p.407 表17-1 要チェック.
  • img要素がサポートするイベント

    • onabortonerror は知らなかったというかほとんど忘れていた
    • onload もサポートしているのね
  • 入力イベント・セマンティックイベント
  • デバイス依存イベント・デバイス独立イベント
  • onclickイベントはデバイス独立イベント,キーボード操作時にも発生
  • さすがにキーボードでダブルクリック的なことはできなかった
  • イベントハンドラで false を返すことで,その要素のデフォルトの動作を取り消すことができる
  • デフォルトの動作を取り消しできるイベントタイプ:onclickonkeydownonkeypressonmouseuponmousedownonsubmitonreset
  • イベントハンドラの this に注意

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    <a id="hoge">click</a>
    <script type="text/javascript">
    var a = document.getElementById( 'hoge' );
    var o = {
      innerHTML: 'fugafuga',
      mymethod: function() {
        alert( this.innerHTML );
        return false;
      }
    };
     
    a.onclick = function() {
      alert( this.innerHTML );
      return false;
    };
    a.onclick();  // click
    o.mymethod(); // fugafuga
     
    a.onclick = o.mymethod;
    a.onclick();  // click
    </script>
  • HTML属性としてイベントハンドラを定義するときは気をつけろ → 「控えめなJavaScript」の精神で

昼食

DeLLa.JS 「JavaScript第5版」読書会 #10 on Flickr

読書会 午後の部

17.2 DOM レベル2 の高度なイベント処理

  • キャプチャリング → 自身 → バブリング
  • デフォルトの動作は,イベントの3段階の伝播処理の後に行われる
  • 同じオブジェクトの同じ種類のイベントに対して複数のハンドラを登録可能
  • DOM標準ではイベントハンドラが呼び出される順序まで規定していない → 登録順にハンドラが呼び出される保証はない
  • removeEventListener()メソッドは,addEventListener()したときのハンドラ関数と「==」な場合のみ除去されるっぽい,振る舞いが同じ別の関数ではダメ
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    var f1 = function( e ) { alert( 'hoge' ); };
    var f2 = function( e ) { alert( 'hoge' ); };
     
    alert( f1 == f1 ); // true
    alert( f1 == f2 ); // false
    alert(
      function( e ) { alert( 'fuga' ); }  ==  function( e ) { alert( 'fuga' ); }
    ); // false
     
    var hoge = document.getElementById( 'hoge' );
     
    hoge.addEventListener   ( 'click', f1, false );
    hoge.removeEventListener( 'click', f1, false );
     
    hoge.addEventListener   ( 'click', f1, false );
    hoge.removeEventListener( 'click', f2, false );
     
    hoge.addEventListener   ( 'click', function() { alert( 'fuga' ); }, false );
    hoge.removeEventListener( 'click', function() { alert( 'fuga' ); }, false );
     
    // hoge が指す要素をクリックすると
    // 「hoge」「fuga」 がいずれかの順で一度ずつアラートされる
  • Eventインタフェイスの targetプロパティと currentTargetプロパティとの違い
  • timestampプロパティとか便利そう
  • MouseEventインタフェイスの relatedTargetプロパティも便利そう

    switch( type ) {
    case 'mouseover':  return ターゲットにマウスが移動したときに,マウスが離れたノード;
    case 'mouseout':   return ターゲットを離れたときに,マウスの移動先のノード;
    }

17.3 Internet Explorer のイベントモデル

ここは簡単にw

  • IEのイベントオブジェクト

    • srcElementプロパティ
    • metaKeyプロパティが存在しない
    • fromElementプロパティ,toElementプロパティ
    • cancelBubbleプロパティ
    • returnValueプロパティ
  • attachEvent()メソッド,detachEvent()メソッド
  • setCapture()メソッド,releaseCapture()メソッド

17.4 マウスイベント

  • マウスイベント時の座標はこんな感じで取得できる?

    // ev はマウスイベント
    var mouseX = ev.clientX + ( window.pageXOffset  ||  ( document.documentElement  ||  document.body ).scrollLeft )
      , mouseY = ev.clientY + ( window.pageYOffset  ||  ( document.documentElement  ||  document.body ).scrollTop )
    ;
  • 例 17-4 のソースコード,IE対策を削るととても短くなるw

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    function drag( elementToDrag, event ) {
      var startX = event.clientX
        , startY = event.clientY
      ;
      var origX = elementToDrag.offsetLeft
        , origY = elementToDrag.offsetTop
      ;
      var deltaX = startX - origX
        , deltaY = startY - origY
      ;
     
      document.addEventListener( 'mousemove', moveHandler, true );
      document.addEventListener( 'mouseup', upHandler, true );
      event.stopPropagation();
      event.preventDefault();
     
      function moveHandler( e ) {
        elementToDrag.style.left = ( e.clientX - deltaX ) + 'px';
        elementToDrag.style.top  = ( e.clientY - deltaY ) + 'px';
        e.stopPropagation();
      }
     
      function upHandler( e ) {
        document.removeEventListener( 'mouseup', upHandler, true );
        document.removeEventListener( 'mousemove', moveHandler, true );
        e.stopPropagation();
      }
    }

Lightning Talks?

JavaScriptから少し離れ,会場を提供していただいた日本ダイナシステム株式会社の嶋社長さんに,データベース Caché についてお話しいただきました.何かとてつもなくスゴイものを見てしまった気がします.

最後に少しだけ時間があったので,この辺 のデモをさせていただきました.(当時からまったく進展がありませんが ><)

懇親会

DeLLa.JS 「JavaScript第5版」読書会 #10 on Flickr

沢田さん,嶋社長もご同行いただいて,会場の近く 世界の山ちゃん 葵店 にて行いました.

Lightning Talks? から引き続き,データベース色の濃い話題が尽きませんでした.

おわりに

「イベント」はJavaScriptにおけるもっとも重要な部分の1つであり,個人的にまだ理解が足りないところだらけということもあり,後日同範囲を再度読み直してからのエントリとなりました.(まぁ言い訳ですが ><)

しかしそのおかげで,苦手意識のずっとあった「イベント伝播」まわりに対する理解をそれなりに深められた,そんな手応えが得られました.今後の実装に活かせられそうです.(DQWindowManager のアプリとかも大幅な改良が必要になりそうだ...)

最後に,同社の嶋社長と,今回の会場の件で最初にご連絡くださった NPUG (日本PostgreSQLユーザ会 名古屋支部) 沢田さんのご両名に,改めてお礼を申し上げます.(もちろん参加していただいた皆様にも.)

なお,次回は p.443 「17.5 キーイベント」 からとなります.

参考