Document Object Model
Written 11/23/00
5. Event(1)
ここではイベントに関する一般的なことについて述べています。 できるだけクロスブラウザをこころがけています。
eventを捕まえる
マウスをクリックしたとかキーを押したなどのイベントが発生したときに スクリプトが動くようにするには次のようにします。
  object.eventhandler = function
 
例えば、
  window.onload = main
 
とすると、ウィンドウがロードされたあとに main という関数が動きます。 また、
  <INPUT TYPE="button" VALUE="押してね☆" ONCLICK="test1(this.form)">
 
などとすると、ボタンが押されたとき
  "test1(this.form)"
 
が評価されて、結果 test1 が動きます。
逆にスクリプトが動かないようにするには、
  object.eventhandler = ""
 
としておけばよいでしょう。
  function test1() {
    if(document.onclick)
        document.onclick = "";
    else
        document.onclick = test2;
  }

  function test2(e) {
    var evt;
    if(document.all)
        evt = window.event;
    else if(document.layers)
        evt = e;
    else
        return;
    
    alert(evt.x);
  }
 
上のボタンを押すと test1 が動き、document のどこかをクリックすると test2 が動くようになります。 もう1度ボタンを押すと、クリックしても test2 は動かないようになります。
ネスケではクリックして test2 が動く範囲は一部に限られています。
eventオブジェクトを得る
event オブジェクトはそのイベントの様々な情報を持つオブジェクトです。
IE4以上では次のように event オブジェクトを得ます。
  [window.]event
 
ネスケ4以上では次のようにイベントハンドラの引数として得られます。
  function func(e) {
    …
  }
 
IEとネスケを両立するには、上にも書きましたが、次のようにコードを書きましょう。
  function test2(e) {
    var evt;
    if(document.all)
        evt = window.event;
    else if(document.layers)
        evt = e;
    else
        return;
    
    ...
  }
 
変数 evt が event オブジェクトを指すことになります。

先ほどのボタンのようにオブジェクトの定義の中でイベントとイベントハンドラを 結び付けられた場合に、ネスケで event オブジェクトを得るには、次のようにします。

  <INPUT TYPE="button" VALUE="押してね☆" ONCLICK="test3(event)">
 
このように評価される文字列の中で event としておくと、 それは event オブジェクトを指すと解釈されます。 IE でも動くようです。まあ、当たり前ですが。
 function test3(e) {
    alert(e.type);      //click
 }
 
イベントの伝播(Internet Explorer)
IE ではイベントは下の階層のオブジェクトから上へ伝播していきます。
例えば次のような DIV オブジェクトがあるとします。

押してね☆

コードは次のようです。

  <DIV ID=div1 style="color:darkorange">押してね☆</DIV>
 
そして下のボタンを押すと下のスクリプトが働いて、 上の DIV をクリックすると test2 が、 document をクリックすると test5 が動くようになります。
  if(div1.onclick) {
    div1.onclick = "";
    document.onclick = "";
  }
  else {
    div1.onclick = test2;
    document.onclick = test5;
  }
  
  function test5() {
    alert(event.type);
  }
 
上の DIV をクリックすると、まず test2 が動き、その次に test5 が動くことが分かると思います。

逆にイベントが伝播しないようにするには、cancelBubble プロパティを用います。

  event.cancelBubble = boolean
 
false(default) なら イベントは上の階層に伝播し、 true なら伝播しなくなります。

押してね☆

  function test6() {
    alert(event.cancelBubble);      //false
    event.cancelBubble = true;
  }
  
  function test7() {
    if(div2.onclick) {
        div2.onclick = "";
        document.onclick = "";
    }
    else {
        div2.onclick = test6;
        document.onclick = test5;
    }
  }
 
上のボタンをクリックすると、上の DIV をクリックすると test6 が、 document をクリックすると test5 が動くようになりますが、 そのとき上の DIV をクリックすると test6 は動きますが、 イベントは上の階層に伝わらず test5 は動きません。
イベントの伝播(Netscape Navigator)
ネスケではこのあたりはバグが多いらしく、 ドキュメントに書いてあるとおり動かなかったりします。

ネスケではイベントを拾うには captureEvents を用います。

  obj.captureEvents(eventType)
 
こうするとその eventType のイベントが拾えるようになり、 さらにイベントと関数が結び付けられて、 イベントが起こると実行されるようになります。
objwindowlayerdocument で、 引数は定数で、
  Event.MOUSEDOWN | Event.MOUSEUP
 
のようにすると、 色々なイベントが拾えるようになります。
ただ、上で見てきたようにそうしなくてもイベントが拾えることがあります。

イベントは IE と逆で上の階層から順に伝わります。 そのままでは伝わりませんが、 routeEvent を使うと伝わるようになります。

  obj.routeEvent(event)
 
releaseEvents を使うとイベントを拾わなくなります。
  obj.releaseEvents(eventType)
 
  function test8(e) {
    alert(e.type);
    document.routeEvent(e);
  }
  
  function test9(e) {
    alert(e.target);
  }
  
  function test10() {
    if(document.form1.elements[0].onclick) {
        document.releaseEvents(Event.CLICK);
        document.onclick = "";
        document.form1.elements[0].onclick = "";
    }
    else {
        document.captureEvents(Event.CLICK);
        document.onclick = test8;
        document.form1.elements[0].onclick = test9;
    }
  }
 
下のボタンを押すと test10 が走り、document と上のボタンの onclick がそれぞれ test8 と test9 に結びつきます。 上のボタンを押すとまず test8 が走り、 routeEvent によってイベントは次に移り、 test9 が走ります。
この場合、captureEvents がないと、うまく動きません。

handleEvent を使うと指定したオブジェクトにイベントを送ることができます。

  obj.handleEvent(event)
 
 function test11(e) {
    alert(e.x);
 }
 
 function test12(e) {
    alert(e.type);
    document.form1.elements[0].handleEvent(e);
 }
 
 function test13() {
    if(document.onclick) {
        document.onclick = "";
        document.form1.elements[0].onclick = "";
    }
    else {
        document.onclick = test12;
        document.form1.elements[0].onclick = test11;
    }
 }
 
下のボタンを押すと test13 が走り、document と上のボタンの onclick がそれぞれ test11 と test12 に結びつきます。 適当なところを押すとまず test12 が走り、 handleEvent によってイベントはボタンに送られ、 test11 が走ります。
デフォルトアクションを避ける
イベントハンドラの参照する関数が false を返すと、 デフォルトのアクションが起こらなくなります。
  document.form2.elements[0].onkeydown = test14;
  
  function test14(e) {
    var key = document.all ? event.keyCode : e.which;   //キーコード
    return 65 <= key && key <= 90;                      //A〜Zならtrue
  }
 
下のテキストボックスにキー入力をしようとすると、 onkeydown で test14 が走り、 押したキーがAからZなら true が返りそのまま入力されます。 それ以外のキーなら false が返り入力されません。
それでは文字列が評価されてイベントが処理されるパターンの場合はどうでしょう。
  <INPUT TYPE="text" ONKEYDOWN="test15()">
 
この場合は test15() が truefalse と評価されるだけで onkeydown が参照する関数がそれを返すわけではないので、 デフォルトアクションを避けることができません。
このようなときのために IE では returnValue というプロパティが用意されています。
  event.returnValue = boolean
 
  function test15() {
    if(!document.all)
        return;
    event.returnValue = 48 <= event.keyCode && event.keyCode <= 57;
  }
 
false がセットされると false が返るのと同じことになり、キー入力されません。
下のテキストボックスには0から9しか入力されません。
それではネスケの場合はどうするのでしょう。
上の例で、テキストボックスの onkeydownalert で見てみると次のようになります。
  //ネスケ
  function onkeydown(event) {
    test15();
  }
  
  //IE
  function anonymous() {
    test15()
  }
 
これらが false を返せばいいわけですから、 もうお分かりですね、次のようにします。
  <INPUT TYPE="text" ONKEYDOWN="return test14(event)">
 
これでAからZ以外のキーは受け付けなくなります。もちろん IE でも動作します。
Back