Eventオブジェクト(に対する拡張)(1)

【抜粋】一部省略
if (!window.Event) {
  var Event = new Object();
}

Object.extend(Event, {
(省略)
  }
});

window.Eventがあればそれに対して拡張、なければ新たにオブジェクトを作成してメンバを追加します。

window.Eventはブラウザによって実装が異なります。Netscape7.1とFirefox1.5.0.4、Opera9.0には存在します。IE6には存在しません(window.eventではないので注意)。興味のある方は以下のコードで確かめてみてください。

【参考】既存window.Eventのメンバを見る
<html>
<head>
<title></title>
<script>
<!--
function init(){
  var str = "";
  if(window.Event){
    str += "<table border><caption>window.Event</caption>";
    str += "<tr><th>name</th><th>value</th></tr>";
    for(var i in window.Event){
      str += "<tr><td>" + i + "</td><td>" + window.Event[i] + "</td></tr>";
	}
    str += "</table>";
  }
  if(window.Event.prototype){
    str += "<table border><caption>window.Event.prototype</caption>";
    str += "<tr><th>name</th><th>value</th></tr>";
    for(var i in window.Event.prototype){
      str += "<tr><td>" + i + "</td><td>" + window.Event[i] + "</td></tr>";
	}
    str += "</table>";
  }
  document.getElementById('test').innerHTML = str;
}
//-->
</script>
</head>
<body onload="init();">
<div id="test"></div>
</body>
</html>

Netscape等では、onclick等のイベントに登録された関数へ渡されるイベントオブジェクトが、このwindow.Eventのインスタンスになります。興味のある方は以下のコードで確かめてみてください。

【参考】イベントオブジェクトを調べる
<html>
<head>
<title></title>
<script>
<!--
function init(){
  document.getElementById('btn').onclick = test;
}
function test(event){
  event = (event || window.event);
  var str = "";
  if(window.Event)
    str += "event instanceof window.Event : " + (event instanceof window.Event) + "<br/>";
  if(event.constructor)
    str += "event.constructor : " + (event.constructor.toString()) + "<br/>";
  str += "<table border><caption>event</caption>";
  str += "<tr><th>name</th><th>value</th></tr>";
  for(var i in event){
    str += "<tr><td>" + i + "</td><td>" + event[i] + "</td></tr>";
  }
  str += "</table>";
  document.getElementById('test').innerHTML = str;
}
//-->
</script>
</head>
<body onload="init();">
<div id="test"></div>
<button id="btn">TEST</button>
</body>
</html>

TESTボタンを押すと、イベントオブジェクトがwindow.Eventのインスタンスであるかどうかと、constructorプロパティのtoString結果、およびメンバを表示します(IEはメンバのみ)。

prototypeプロパティへの追加ではないので、イベントオブジェクトのメンバが増えるわけではありません。Event.methodのように使用します。

イベント・イベントオブジェクトに関しては以下を参照してください。

【参考サイト】
イベントハンドラ
イベント(Event)

KEY_BACKSPACE〜KEY_DELETEプロパティ

【抜粋】
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,

イベントオブジェクトに設定されるキーコードのいくつかをリテラルで持っています。どのキーであるかは名前の通り^^; prototype.js内では使われていないみたいなので、プログラマのために用意されているようです。

【例】
<html>
<head>
<title></title>
<script language="javascript" src="prototype.js" charset="utf-8"></script>
<script>
<!--
document.onkeyup = function(e){
  e = (e || window.event);
  var code = (e.keyCode || e.which);
  var str = code.toString();
  switch(code){
    case Event.KEY_BACKSPACE:
      str += "KEY_BACKSPACE";
      break;
    case Event.KEY_TAB:
      str += ":KEY_TAB";
      break;
    case Event.KEY_RETURN:
      str += ":KEY_RETURN";
      break;
    case Event.KEY_ESC:
      str += ":KEY_ESC";
      break;
    case Event.KEY_LEFT:
      str += ":KEY_LEFT";
      break;
    case Event.KEY_UP:
      str += ":KEY_UP";
      break;
    case Event.KEY_RIGHT:
      str += ":KEY_RIGHT";
      break;
    case Event.KEY_DOWN:
      str += ":KEY_DOWN";
      break;
    case Event.KEY_DELETE:
      str += ":KEY_DELETE";
      break;
  }
  Element.update('test', str);
  return false;
};
//-->
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>

表示後に何かキーを押すと、対応したキーコードを表示します。このとき、設定されているキーコードであれば、対応した文字列を加えて表示しています。

elementメソッド

【抜粋】
  element: function(event) {
    return event.target || event.srcElement;
  },

イベントオブジェクトを引数とし、イベントの起因となった要素を返却します。Netscape等ではtargetプロパティ、IEではsrcElementプロパティに格納されています。

「イベントが登録されている要素」ではないので注意してください(後述の例を参照してください)。

例は後述stopメソッドでまとめます。

isLeftClickメソッド

【抜粋】
  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

イベントオブジェクトを引数とし、左クリックによりイベントが発生してていればtrue、そうでなければfalseを返却するメソッド*1Netscape等ではwhichプロパティ、IEではbuttonプロパティを使用します。

ただ、なぜかIE6でうまく動かないのですが。。。 何が原因か分からず・・・;;

例は後述stopメソッドでまとめます。

pointerXメソッド

【抜粋】
  pointerX: function(event) {
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

イベントオブジェクトを引数とし、イベント発生時のページ上でのマウスポインタの横位置をpx値で返却するメソッド*2Netscape等ではpageXプロパティを使用します。IEではclientXプロパティを使用しますが、これはウィンドウ上での位置になるため、スクロール分を加算しています。

例は後述stopメソッドでまとめます。

pointerYメソッド

【抜粋】
  pointerY: function(event) {
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

イベントオブジェクトを引数とし、イベント発生時のページ上でのマウスポインタの縦位置をpx値で返却するメソッド。Netscape等ではpageYプロパティを使用します。IEではclientYプロパティを使用しますが、こちらもウィンドウ上での位置になるため、スクロール分を加算しています。

例は後述stopメソッドでまとめます。

stopメソッド

【抜粋】
  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

イベントオブジェクトを引数とし、そのイベントを「止める」メソッド。手抜きで「http://www.imgsrc.co.jp/~kuriyama/prototype/prototype.js.html#Reference.Extensions.Event」から表現を引用すると、「イベントのデフォルトの挙動を中断し、他に伝播しないようにする」ということ、らしいです。

「イベントのデフォルトの挙動を中断」の例としては、onsubmitイベントで、入力内容に不備があった場合にsubmitさせない、というものがあります。この場合によく使われるのはreturn falseさせる、という方法ですが、イベントオブジェクトのメソッド・プロパティでもできるみたいです。Netscape等ではpreventDefaultメソッドを使用、IEではreturnValueプロパティにfalseを設定します。

「他に伝播しないようにする」とは、親または子要素の同じイベントに登録されている他の関数の実行を、その時点で中止するという意味です。Netscape等ではstopPropagationメソッドを使用、IEではcancelBubbleプロパティにtrueを設定します。

【例】
<html>
<head>
<title></title>
<style>
<!--
div{
  margin:20px;
  padding:10px;
}
#parent{
  background-color:blue;
  width:2000px;
  height:2000px;
  color:white;
}
#child1{
  background-color:yellow;
  width:200px;
  height:200px;
}
#child2{
  background-color:red;
  width:200px;
  height:200px;
}
td{
  border:solid blue 2px;
  height:100px;
  width:150px;
}
a{
  color:white;
}
-->
</style>
<script language="javascript" src="prototype.js" charset="utf-8"></script>
<script>
<!--
function parent(event){
  event = event || window.event;
  Element.update($('parent_v'), test(event));
}
function child(event){
  event = event || window.event;
  Element.update($('child_v'), test(event));
  if($('stop').checked){
    Event.stop(event);
  }
}
function test(event){
  var str = "";
  var element = Event.element(event);
  str += "element.id : " + element.id + "<br/>";
  str += "isLeftClick : " + Event.isLeftClick(event) + "<br/>";
  str += "pointerX : " + Event.pointerX(event) + "<br/>";
  str += "pointerY : " + Event.pointerY(event) + "<br/>";
  return str;
}
function submitF(event){
  event = event || window.event; 
  if($('stop').checked){
    alert("not move page");
    Event.stop(event);
  }
}
function init(){
  $('parent').onclick = parent;
  $('child1').onclick = child;
  //$('child1').onblur = child;
  $('child2').onclick = child;
  $('fm').onsubmit = submitF;
}
//-->
</script>
</head>
<body onload="init();">
<table>
<tr><th>parent onclick</th><th>child onclick</th></tr>
<tr><td id="parent_v">&nbsp;</td>
<td id="child_v">&nbsp;</td></tr>
</table>
<input type="checkbox" id="stop"/>STOP
<div id="parent">id:parent<br/>
<button id="child1">id:child1</button>
<button id="child2">id:child2</button><br/>
<form action="about:blank" id="fm">
<input type="submit" id="submit" value="SUBMIT"/>
</form>
</div>
</body>
</html>

DIV要素parentと、その子要素にBUTTON要素child1とchild2があります。それぞれonclickイベントに関数を登録しています。

どちらかのボタンを押すと、上の2つの枠にイベントオブジェクトから取得した値を表示します。左がparentのonclick、右がchild1またはchild2のonclickで発生したイベントオブジェクトです。両方同じ表示になると思います。

この場合、parentのonclickのイベントオブジェクトも、elementメソッドで取れる要素はchild1またはchild2になります。

parentのボタン以外の部分をクリックすると、左の枠だけが更新されます。

STOPのチェックボックスにチェックを入れて、どちらかのボタンを押すと、右の枠だけが更新されます。これは、child1、child2のonclickイベントで使用されるEvent.stopメソッドにより、parentのonclickイベントが抑制されるためです。*3

なぜかisLeftClickメソッドがIE6でうまく動きません。。。 window.event.buttonそのものも調べてみたんですが「0」です。検索をかけてみたけど同様の現象についての記述は見当たらず。分からんTT

SUBMITボタンは、STOPにチェックなしだと空白ページ(about:blank)へ飛びます。STOPにチェックを入れると、alertを出して、画面遷移しません。

*1:ボタンをフォーカスしてENTERでも同じとみなされます

*2:マウスクリックがイベントに関係ない場合はとれません

*3:通常はイベントバブル(イベント発生要素から親要素へ(documentまで) )で実行される。