ホーム > HTMLサンプル

2015/04-2017/12/28

JavaScript イベント処理,その1

table の各td にイベント処理を付ける例でいろいろ
tableタグ,JavaScriptサンプル
目次
  1. td タグに直接 onclick="関数"を入れる
  2. JavaScript でtdにイベント処理をつける
  3. イベント処理がクラスの prototype関数だった場合
  4. ul,liのツリーにイベント処理を付ける例
  5. 関連

td タグに直接 onclick="関数"を入れる

初歩的なサンプルでよく使います。
td タグに直接 onclick= を記述して関数を呼び出します。
<td onclick="関数名(引数)">
例:
  onclickTd(123, '文字列1'); //ユーザー指定の引数。
  onclickTd(this);           //this は td になる。
  onclickTd(event);          //マウスイベントを引数にする。
TestHTML_table_td_event01.html
関数の引数いろいろ。

TestHTML_table_td_event02.html
td 内に別の要素(p や spanなど)があるときのイベントの発生の仕方など。
上の方法では不都合な場合も出てきます。たとえば、td タグだと
1) たくさんの td がある table で、個別に onlick=... を書くのは面倒。
  繰り返し同じ記述が出てくる。まとめて処理したいと思うのも人情で・・・

2) table 自体を JavaScript で作成する場合は上の方法が使えない。
  HTML に table タグ、td タグが存在していない場合。
ということで、td に onlick= をつける処理もJavaScript化します。 下に続く。

JavaScript でtdにイベント処理をつける

先に要点

サンプル:TestHTML_table_td_event13.html
下の 3) のサンプル。window.onload で初期化, addEventListener でイベント処理(リスナー関数)を登録する。 関数は無名関数。

サンプル:TestHTML_table_td_event15.html
下の 4) のサンプル。addEventLisnter と bind() を併用。無名関数では間に合わない大きな処理やクラスと併用する場合など。

1)元のサンプル

最初に元のサンプル。td タグに onclick= をつけて関数を呼び出しています。

TestHTML_table_td_event11.html
table の各tdに onclick="onclickTd(this)" という記述が繰り返し出てきます。
<tr>
<td onclick="onclickTd(this)">0-0</td>
<td onclick="onclickTd(this)">0-1</td>
...
イベントを付ける処理も JavaScript でまとめてみる。

2)onclick を付ける処理を JavaScript でまとめる

サンプル:TestHTML_table_td_event12.html
td.onclick= でイベント処理を付けるサンプル。 初期化処理は body の onload= で呼び出す。一昔前風のサンプル。

onclick の処理を付けるときに、書き間違いでよく出てくるトラブルがあるので注意。
・2)だと、どのtdをクリックしても一番最後のtd (2,3) しか処理されなくなる。

  var td = a[i];
  td.onclick = function(){
      onclickTd(this); //1)正しい
      //onclickTd(td); //2)誤り
  };

3)addEventListenerでイベント処理をつける

td.onclick=... の代わりに、td.addEventListener() を使います。
初期化処理も body の onload= ではなくて、window.onload で行っています。
サンプル:TestHTML_table_td_event13.html
(ノート)
・addEventListener は古いブラウザでは使えない関数だった。
・addEventListener の方が汎用性があり、複数のリスナーを登録することも
 できます。

  td.onclick = .... だと 1つの関数しか付けられない点に注意。
  関数を2つ以上付けると、先に付けた関数が上書きされ、処理されなくなります。

  td.onclick = func1;
  td.onclick = func2;  //func1 は無効になり処理されない。

・window.onload も addEventListener("load", ...); が使える。

4)関数ポインタ渡し、bind()を使用

サンプル:TestHTML_table_td_event14.html
onclick= でいろいろ。

サンプル:TestHTML_table_td_event15.html
addEventLisnter() でいろいろ。
td.onclick = function(){  onclickTd(this); }; ではなく、下のようにした場合。

1) td.onclick = onclickTd;
   td.addEventListener("click", onclickTd);

  上の記述は関数のある場所(関数ポインタ)をセットしている。
  その場では実行しない。
  onclickTd(param) の引数 param はマウスイベントになる。暗黙で渡される。

  onclickTd()内の this は td になる点に注意。windowではない。
  onclickTd()内で他の関数を呼んで未定義(undefined)エラーが出る場合は、
 たいてい this 違いが原因。bind() で thisが何を指しているのかコンテ
 キストの明示が必要。下の話に続く。

2) td.onclick = onclickTd.bind(this, td);
   td.addEventLisnter("click", onclickTd.bind(this, td));

  bind() で引数渡し。
  bind() は IE8 など古いブラウザで使えなかった。

  td.onclick = function(){  onclickTd(this); }; とほぼ同じ。
  関数 onclickTd() の引数は td になる。(暗黙のうちにマウスイベントも
 引数の末尾に追加される)。

  bind() の最初のパラメータの this は関数onclickTd()内の this が何を
 指すか、コンテキストを指定している。
  このサンプルの場合は関数 onclickTd() 内の this は window になる。

  もし、アプリケーションのオブジェクト app があり、
  onclickTd.bind(app, td); とすれば、
  関数 onclickTd() 内の this は app、引数は td (とマウスイベント)になる。

・暗黙のうちにつくマウスイベントの引数は、暗黙に頼らず明示した方がいいかも。
  暗黙に頼って省略すると誤解・錯覚の原因になりやすい。

以上、要約

TestHTML_table_js_addEventListener01.html
いろんな書き方の詰め合わせ。
■1-1)近年風 td.addEventLisnter()
  addEventLisnter は古いブラウザで使えなかった。

for (var i=0; i<a.length; i++){
	var td = a[i];
		td.addEventListener("click", function(){
		onclickTd(this); //引数の this に注意。td にしないこと
	};
}

■1-2)昔風 td.onlick=...
	td.onclick = function(){
		onclickTd(this); //引数の this に注意。td にしないこと
	};


■2)誤り: onclickTd(td);
  1-1),1-2)と似ているが誤動作する。間違いやすい記述。

	var td = a[i];
	td.onclick = function(){
		onclickTd(td); //誤り, td ではなくて this
	};

■3) 誤り: td.onclick = onclickTd(td);
  関数をその場で実行しているだけ。
  関数の戻り値を onlick にセットしている。

■4-1) td.onclick = onclickTd;
       td.addEventListener("click", onclickTd);

  こちらは関数のコード(あるいは関数のある場所、関数ポインタ)を
 セットしている。その場では実行しない。

  onclickTd(param) の引数 param はマウスイベントになる。

■4-2) td.onlick = onclickTd.bind(this, td);
       td.addEventLisnter("click", onclickTd.bind(this, td));

  bind() は古いブラウザで使えなかった。
  上の 1-1),1-2)とほぼ同じ。
  bind() で関数 onclickTd() のコンテキスト(関数内でthisが何を指すか)
 と引数を指定。

その他

サンプルTestHTML_table_td_event12.html で、プログラムの書き方を誤ると、正しく処理されない話が出てきました。
var td = a[i];
td.onclick = function(){
    //1)正しい, 関数の引数には 個別のtd が渡される。
    onclickTd(this);

    //2)誤り, tdは1つしか用意されず、a[] の一番最後の要素が渡される。
    //  そのため、どの td をクリックしても一番最後の td の処理になる。
    //onclickTd(td);
};

このあたりの話で混乱する人も多いと思うので、 上の処理を無名関数を使った省略ではない書き方をするとどうなるか?。

サンプル:TestHTML_table_td_event12_1.html

上の話は、暗黙のうちにクラスのオブジェクトを介して処理している話に相当します。 JavaやC#だと無名関数とは呼ばず、無名クラスと呼びます。 関数とクラスのオブジェクトはまったく別物で区別します。 JavaScriptだとこの話があいまいに隠蔽されているので混乱しやすい原因になる。

イベント処理がクラスの prototype関数だった場合

上の addEventLisnter と bind() を併用する話からの続き。

クラスを使った処理になると、クラスの関数(メソッド)を呼び出すときにも this.関数名() のように this を使います。このとき、 this がクラスのオブジェクトではなく、 window や HTML要素など別のオブジェクトを指していると、 オブジェクトの変数(フィールド)や関数(メソッド) にアクセスしたときに見つからない(undefined) エラーが起こります。 上の td などの話も加わって、 期待したとおりの動作をしないトラブルが起こりやすい部分です。 this が指す意味 (コンテキスト) や引数が適切になるように bind() で明示します。

TestHTML_table_js_addEventListener02_3.html
(2017/12)イベントを付ける処理やイベント処理が JavaScriptのクラス、prototype関数の場合。
thisの指す内容に注意、bind() のサンプル

ul,liのツリーにイベント処理を付ける例

TestHTML_ul_li_jstree02.html
ul,liでツリー表示。フォルダを開いたり閉じたりする。

TestHTML_ul_li_jstree03.html
イベント処理や初期化処理を JavaScript のクラス、prototype関数でまとめている例。this が混乱しやすいので注意。
ul,liタグ, ツリービューのサンプル

関連

目次
gorogoronyan@gmail.com
inserted by FC2 system