イベント割り当て

onclick属性等にハンドラを割り当てる

この方法は現在ではレガシーとされ、あまり推奨されていない。理由は、1つの要素の1つの属性に対して1つのハンドラしか割り当てられないから。また、HTMLとJavaScriptが混在するから。

 <html>
 <head>
 <script type="text/javascript">
 function func(evt) {
   var evt = evt || window.event;          // (注1)
   var elm = evt.target || evt.srcElement; // (注2)
   alert(evt.type + " " + elm.name + " " + elm.value);
 }
 window.onload = function () {
   var elm = document.getElementById('btn');
   elm.onclick = func;
 }
 </script>
 </head>
 <body>
 <input id="btn" name="btn_name" type="button" value="btn_val"/>
 </body>
 </html>

(注1) ハンドラ関数内でのイベントオブジェクト

  • IE以外のブラウザではハンドラ関数の引数としてイベントオブジェクトを受け取る。
  • IEでは引数が渡らないので、グローバルのwindow.eventオブジェクトをコピーして使う。
  • なお、下のようにハンドラをインラインで割り当てれば、IEでもハンドラ関数の引数にイベントオブジェクトを渡せる。
     <input id="btn" name="btn_name" type="button" value="btn_val" onclick="func(event)"/>

(注2) ハンドラ関数内でのイベントのターゲット要素

  • IE以外のブラウザでは、イベントオブジェクトのtargetプロパティを使う。
  • IEでは、イベントオブジェクトのsrcElementプロパティを使う。

addEventListener()/attachEvent()でハンドラを割り当てる

IE以外ではaddEventListener()、IEではattachEvent()を使うので、それを吸収するクロス関数attach()を用意する。

 <html>
 <head>
 <script type="text/javascript">
 function attach(elm, type, handler) {
   if (elm.addEventListener) {
     elm.addEventListener(type, handler, false);
   } else {
     elm.attachEvent('on' + type, handler);
   }
 }
 function func(evt) {
   var evt = evt || window.event; 
   var elm = evt.target || evt.srcElement;
   alert(evt.type + " " + elm.name + " " + elm.value);
 }
 window.onload = function () {
   attach(document.getElementById('btn'),'click',func);
 }
 </script>
 </head>
 <body>
 <input id="btn" name="btn_name" type="button" value="btn_val" />
 </body>
 </html>

複数のハンドラを割り当てる

ハンドラ関数func1とfunc2を用意し、下のようにイベント割り当てを2度行うと、ボタンクリックでfunc1()とfunc2()両方実行出来る。これがonlclick属性に直接イベント割り当てする方法に比べてのメリット。

 window.onload = function () {
   attach(document.getElementById('btn'),'click',func1); 
   attach(document.getElementById('btn'),'click',func2);
 }

attachEvent()で割り当てたハンドラ関数内でのthisをターゲット要素にする

ハンドラ関数内で、以下のようにthisを参照すると、

 function func(evt) {
   alert(this.type + " " + this.name + " " + this.value);
 }

IE以外のブラウザではthisはターゲット要素(この場合INPUTタグ)だが、IEではwindowオブジェクトになる。この違いを吸収するため、次のようにattachEvent()の引数を修正する。

 elm.attachEvent('on' + type, function() { handler.call(elm, window.event); });

ハンドラ関数を直接渡さず、「ターゲット要素に対してcall()を使ってハンドラ関数を実行する」無名関数を渡す。その際、window.eventオブジェクトも引数にする。これによって、handler()内でthisがelmを表すようになり、引数のevtにイベントオブジェクトが入るようになる。

ハンドラ関数が引数を取れるようにする

  • ハンドラ関数func()の仮引数にargsを加える。
  • クロス関数attach()の仮引数にargsを加える。
  • ハンドラを割り当てる時に、ハンドラ関数を直接渡さず、call()を使ってハンドラ関数を実行する無名関数を渡す。その際、argsも引数で渡す。

これまでの処理もまとめると、プログラム全文は次のようになる。

 <html>
 <head>
 <script type="text/javascript">
 function attach(elm, type, handler, args) {
   if (elm.addEventListener) {
     elm.addEventListener(type, function (evt) { handler.call(this, evt, args); }, false);
   } else {
     elm.attachEvent('on' + type, function() { handler.call(elm, window.event, args); });
   }
 }
 function func(evt, args) {
   alert(this.name + " " + args[0]);
 }
 window.onload = function () {
   attach(document.getElementById('btn'), 'click', func, ['TEST']);
 }
 </script>
 </head>
 <body>
 <input id="btn" name="btn_name" type="button" value="btn_val" />
 </body>
 </html>

これでクロスブラウザなイベント割り当ての処理が実現したが、さらに複雑なイベント割り当てを行いたい場合、jQuery等のライブラリの使用を検討する。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS