イベント
DOM Event
イベントリスナーの登録
以下の3種類の方法があります。いずれもクリックで関数が呼ばれるパターンで紹介します。結論から言うと 3) 以降の addEventListener を使う方法がおすすめです。
- 1) HTMLに直接書く
<button onclick="alert('Hello world!')">ABC</button>
- クリックで 'Hello world!' と書かれたアラートボックスが表示されます。
- onclick の部分には様々なイベントタイプを指定できます。
- 2) DOM要素に書く
element.onclick = function( event ){ // ここに処理; };
- クリックで処理が実行されます。
- onclick の部分には様々なイベントタイプを指定できます。
- 3) addEventListener を使う1
element.addEventListener( 'click', function( event ){ // ここに処理; }, false);
- クリックで function( event ){} に記載された処理が実行されます。
- 最初の引数は 'click' 以外にも様々なイベントタイプを指定できます。
- event はイベントオブジェクト(後述)で、イベントに関わる様々な情報がまとめて渡されます。
- 関数内では this が event.target と同じで「クリックされたオブジェクト」を示すことができます。
- 4) addEventListener を使う2
element.addEventListener( 'click', listener, false);
- クリックで listener に定義された処理が実行されます。
- listener はイベントハンドラ関数で、イベントオブジェクト(後述)をデフォルト引数として持ちます。
- この形式では、listener に独自の引数を渡すことはできません。
- 5) addEventListener を使う3
element.addEventListener( 'click', function(){ listener( 引数 ) }, false);
- クリックで listener に定義された処理が実行されます。
- この書き方では、listenerに引数を持たせることができます。
- 6) addEventListener を使う4
element.addEventListener( 'click', listenerObject, false);
- クリックで listenerObject の handleEvent に定義された処理が実行されます。
- listenerObject は EventListener インタフェースを実装するリスナーオブジェクトで { 引数名 : 引数 , handleEvent : listener } のように記述します。
事例 4), 5) の listener とは
- 指定された型のイベントが発生するときに、通知を受け取るコールバック関数です。イベント発生時に行うべき処理を記述します。
- listener 関数は、イベントオブジェクトを引数として持ちます。
事例 6) の listenerObject とは
listenerObject は イベントリスナーインタフェースを実装するオブジェクトで、引数を利用したい場合などに、この方法が使われます。以下の例では、イベントハンドラ関数 myFunction の中で this.number を使うことによって i の値を参照することができます。
function myFunction(event) { : let n = this.number; ← 引数として渡された i の値が入ります。
:
} element.addEventListener( 'click', { number : i , handleEvent :myFunction }, false);
参考:6) の方法を使ったサンプル > JavaScript/ImageSwitcher
イベントオブジェクトとは
イベントが発生した際、listener(登録したコールバック関数)には、発生したイベントの情報が格納された「イベントオブジェクト(一般に e や event を用いることが多い)」が一番目の引数として渡されます。 例えば、'click' イベントに対する listener関数の名前が myFunction とすると、以下のように記述することでイベントが発生した要素のIDを確認できます。
function myFunction( event ){ alert(event.target.id); } element.addEventListener( 'click', myFunction, false);
イベントオブジェクトからは以下のような情報が取得できます。
プロパティ名 | 説明 |
event.target | イベントが発生したDOM要素 |
event.target.id | ID名 |
event.target.className | クラス名 |
event.target.innerHTML | HTML要素 |
event.target.style | 要素のスタイル |
event.target.childNodes | 子要素 |
event.target.parentNodes | 親要素 |
event.target.nextElementSibling | 次の要素 |
event.type | イベントの種類を表す文字列 |
event.screenX / event.screenY | モニタ画面上の座標 |
event.pageX / event.pageY | モニタ画面上の座標 |
event.clientX / event.clientY | ウインドウ上の座標 |
event.offsetX / event.offsetY | 要素上の座標 |
event.target.offsetWidth / event.target.offsetHeight | 幅と高さ |
event.timeStamp | イベント発生までの経過時間(ミリ秒) |
event.eventPhase | イベントのフェーズ |
イベント伝搬について
ひとつの要素をクリックすると clickイベントが生成されますが、このとき当該要素から windowオブジェクトに至るまで、要素の先祖をさかのぼってイベントが生成されることを「イベント伝播」と言います。イベント伝搬は、DOMブランチ上のノードに定義されたイベントリスナーを event オブジェクトとともに呼び出します。以下の3つのフェーズに分類できます。
- イベントバブリングフェーズ
addEventListener()の3番目のパラメータが false(デフォルト)のケースelement.addEventListener( 'click', listener, false ) element.addEventListener( 'click', listener )
以下の図をご覧ください。
https://www.w3.org/TR/DOM-Level-3-Events/images/eventflow.svg
引用元:https://www.w3.org/TR/DOM-Level-3-Events/
- イベントターゲットフェーズ
イベントターゲットに登録されたすべてのリスナーが captureフラグにかかわらず呼び出されます。
- イベントキャプチャーフェーズ
addEventListenerの3番目のパラメータが trueのケースelement.addEventListener( 'click', listener, true )
イベント一覧資料
- MDN イベントリファレンス
https://developer.mozilla.org/ja/docs/Web/Events - UI Events:W3C Working Draft, 04 August 2016
https://www.w3.org/TR/DOM-Level-3-Events/
APPENDIX
モバイル特有のイベント
- touchstart
- touchend
- touchmove
- touchcancel
- touchenter
- touchleave
レスポンシブなサイトを作る際の考え方(jQuery)
とりあえず、PCのマウスのホバーにあたるものがスマホでは存在しないので、この点については、PCとスマホで書き分ける必要があります。一方、マウスのクリックイベントとスマホのタッチイベントについては・・・
- デバイスがタッチイベントに対応するか否かを判定し、 touchstart と click を使いわける方法がよく紹介されています。
var event = 'ontouchstart' in window ? 'touchstart' : 'click'; $('.button').on(event, function() { // ここに処理; });
ただしこの方法は、タッチとクリックの両方に反応する Windowsタブレットなどではタッチが優先されてマウス操作ができなくなる・・という問題があります。
- touch 系は使わずシンプルに click のみで設計するのもありです。
上記の使い分けは、clickイベントだと反応が遅い( touchend と click イベント間で 300〜350ms 遅延)ということが理由でしたが、スマホもタッチ操作において clickイベントを発生させるので、煩雑な UI 設計は避け、clickイベントだけで実装するという発想もありだと思います。