分類 | イベントハンドラ | 発生タイミング |
---|---|---|
ウィンドウ | onresize | ウィンドウのサイズが変更されたとき (Windowオブジェクトのみ) |
onscroll | 要素のコンテンツがスクロールされたとき | |
ドキュメント | onload | リソースのロードが完了したとき |
onunload | アンロードされるとき (ロードする前) | |
onreadystatechange | documentのreadyState属性が変化したとき | |
フォーム | onsubmit ※1 | フォームの送信が要求されたとき |
onreset | フォームのリセットが要求されたとき | |
onchange ※1 | 要素の値が変更され、要素が入力フォーカスを失ったとき | |
onselect | テキストが選択されたとき | |
onfocus ※1 | 要素が入力フォーカスを得たとき | |
onblur ※1 | 要素が入力フォーカスを失ったとき | |
oninput | inputまたはtextarea要素のValueが変化したとき | |
マウス | onclick | マウスでクリックされたとき |
ondblclick | マウスでダブルクリックされたとき | |
onmousedown | マウスボタンが押されたとき | |
onmouseup | マウスボタンが離されたとき | |
onmouseover | マウスポインタが要素に乗ったとき | |
onmouseout | マウスポインタが要素から離れたとき | |
onmousemove | マウスポインタが要素の上を移動したとき | |
oncontextmenu | マウスで右クリック、またはアプリケーションキーが押されるなどして、コンテキストメニューが表示されるとき | |
キー | onkeydown | ユーザーがキーを押したとき |
onkeypress | ユーザーがキーを押して離したとき | |
onkeyup | ユーザーがキーを離したとき | |
リソース | onabort | リソースのロードが中断されたとき |
onerror | リソースのロード中にエラーが発生したとき |
onloadやonclickなど、イベントハンドラはすべて小文字で記述します。
要素で発生するイベントやそのタイミングは、FirebugのコマンドラインAPIであるmonitorEvents()で確認できます。
登録されたイベントハンドラは、JavaScript デバッガのイベントペインで確認できます。
HTMLの要素の属性として記述します。
<a onclick="FunctionName();"></a>
属性値はJavaScriptのコードであり、関数名ではありません。よって関数名の後にかっこが必要となります。
JavaScriptで要素のプロパティとして記述します。DOMレベル0では、オブジェクトの1つのイベントに対して、1つのハンドラしか登録できません。同一のイベントに後から登録すると、先の登録が上書きされます。
element.onclick = Function1;
element.onclick = Function2; // Function1が上書きされる
たとえば次のように、1つのa要素に2つのハンドラを登録すると、
var a = document.createElement( 'a' ); a.onclick = function() { alert( '1' ) }; a.onclick = function() { alert( '2' ) };
この要素をクリックしたときには、'2'と表示されるダイアログだけが表示されます。
また、DOM0レベルではイベントフェーズの指定ができず、DOM階層の上位にある要素のハンドラが呼び出されることはありません。
ハンドラを削除するには、nullを代入します。
element.onclick = null;
target.addEventListener( type, listener [, useCapture ] );EventTarget.addEventListener - DOM | MDN addEventListener method (Internet Explorer) | MSDN
typeでイベント名を指定します。これは「click」などのイベントの名前であり、「onclick」のようなイベントハンドラの名前ではありません。この文字列は大文字/小文字の区別はされません。
listenerには、イベントを処理する関数、もしくはhandleEvent()メソッドを実装するオブジェクトを渡します。
useCaptureでは、listenerが呼び出されるイベントフローのフェーズを指定します。
Internet Explorer 9より前はuseCaptureは省略不可であり、省略した場合には例外が発生します。よって互換性を考慮するならば、既定値である場合にも省略をせずfalseと明示します。ブラウザ実装状況 - EventTarget.addEventListener - Web API インターフェイス | MDN
DOMレベル2では、同一オブジェクトの同一イベントに対して、複数のハンドラを登録できます。たとえば次のように、1つのa要素に2つのハンドラを登録すると、
var a = document.createElement( 'a' ); a.addEventListener( 'click', function() { alert( '1' ) }, false ); a.addEventListener( 'click', function() { alert( '2' ) }, false );
この要素をクリックしたときには、'1'と'2'の2つのダイアログが表示されます。
ただし同一イベントに同一のハンドラを重複して登録すると、後の登録は無視されます。よって次のようにすると、
var a = document.createElement( 'a' ); var func = function() { alert( 'Hello' ) } a.addEventListener( 'click', func, false ); a.addEventListener( 'click', func, false );
要素のクリックでは、ダイアログが1度だけ表示されます。複数の同一のイベントリスナー - EventTarget.addEventListener - Web API インターフェイス | MDN
イベントハンドラはイベントを捕捉し処理する関数であり、イベントリスナはそのハンドラ関数を処理する仕組みです。ただし文脈によっては区別されません。 event handler - Document Object Model (DOM) Level 3 Events Specification
addEventListener()の第2引数にオブジェクトを渡すと、イベント発生時にはそのオブジェクトのhandleEvent()メソッドが呼び出されます。
var obj = {
handleEvent: function( event )
{
}
};
window.addEventListener( 'load', obj, false );
// 'load'イベント発生時、obj.handleEvent()が呼び出される。
複数のイベントを登録したときには、handleEvent()の引数のEvent.typeプロパティから、イベントの種類を判別できます。
function handleEvent( event ) { switch( event.type ) { case 'load': break; case 'unload': break; } } window.addEventListener( 'load', this, false ); window.addEventListener( 'unload', this, false );
この例ではハンドラとしてthisを渡しています。これはメソッド外ではthisはグローバルオブジェクトへの参照であるためで、これにより同じスコープにあるhandleEvent()が呼ばれます。
上書きされる恐れがあるため、実際にはhandleEvent()をグローバルスコープで定義すべきではありません。
ハンドラを削除するには、removeEventListener()を呼びます。
element.removeEventListener( type, listener[, useCapture] );EventTarget.removeEventListener - Web API Interfaces | MDN
typeはハンドラ登録時にaddEventListener()で指定したイベントと同名で、さらにlistenerは登録時の関数と同一でなければなりません。よって、たとえば次のようにしてもハンドラを削除できません。
function Func( flag ) { function EventHandler() { alert( '' ); } if( flag ) { button.addEventListener( 'click', EventHandler, false ); } else { button.removeEventListener( 'click', EventHandler, false ); } } Func( true ); // ハンドラを登録する Func( false ); // ハンドラを削除する
これはハンドラとして登録される関数EventHandler()がローカルスコープで定義されているため、2度目の関数呼び出し時には異なるオブジェクトとなるためです。
ところでハンドラ内でそのイベントを削除するならば、イベントのプロパティを参照する方法が使えます。この方法ならば、ハンドラが匿名関数であっても削除できます。
Internet Explorer 9より前はaddEventListener()をサポートしておらず、attachEvent()がその代替となります。attachEvent method (Internet Explorer) | MSDN
element.attachEvent( 'onclick', Function1 );※IEのイベントモデルでは、イベントフローの呼び出しフェーズの制御がサポートされません。
attachEvent()ではハンドラ内でのthisの値が、addEventListener()と異なります。
attachEvent()は、Internet Explorer 11以降ではサポートされません。Compatibility changes in IE11 (Windows) | MSDN
ハンドラを削除するには、detachEvent()を呼びます。
element.detachEvent( 'onclick', Function1 );
クロスブラウザとするために、各メソッドが実装されているか確認しながら順に試行します。ブラウザ実装状況 - EventTarget.addEventListener - Web API インターフェイス | MDN
var element = document.createElement( 'a' ); if( element.addEventListener ) { // DOMレベル2 element.addEventListener( 'click', FunctionName, false ); } else if( element.attachEvent ) { // IEイベントモデル element.attachEvent( 'onclick', FunctionName ); } else { // DOMレベル0 element.onclick = FunctionName; }
より汎用的には、
function AddEventListener( element, type, listener )
{
if( element.addEventListener )
{
element.addEventListener( type, listener, false );
}
else if( element.attachEvent )
{
element.attachEvent( 'on' + type,
function() { listener.apply( element, arguments ); } );
}
else
{
// not support.
}
}
のように関数化します。
var element = document.createElement( 'a' ); if( element.removeEventListener ) { // DOMレベル2 element.removeEventListener( 'click', FunctionName, false ); } else if( element.detachEvent ) { // IEイベントモデル element.detachEvent( 'onclick', FunctionName ); } else { // DOMレベル0 element.onclick = null; }
イベントハンドラのプロパティを関数のように実行することで、イベントハンドラを明示的に呼び出せます。たとえばonsubmitイベントハンドラは、onsubmit()として呼び出せます。
// イベントハンドラの登録 element.onsubmit = function() {} // イベントハンドラの呼び出し element.onsubmit();
Form.submit()の呼び出しではsubmitイベントは発生しないため、イベントハンドラは呼び出されません。
イベントハンドラが匿名関数でなければ、当然その関数名で呼び出せます。
function Func() {} // イベントハンドラの登録 element.onsubmit = Func; // 関数の呼び出し Func();
addEventListener()で登録された関数を、後から参照する方法はありません。よってハンドラを呼ぶ必要があるならば、その関数は名前を付けて定義するようにします。そうすれば、その関数名で呼び出すことが可能です。
function Func() {} // イベントハンドラの登録 element.addEventListener( 'click', Func, false ); // 関数の呼び出し Func();
ただし、
の3つのイベントは、それを発生させるメソッドが用意されています。よって、これらのメソッドの効果がある要素ならば、メソッドを呼ぶことで対応するイベントハンドラを呼び出せます。
element.addEventListener( 'click', function() {}, false ); element.click();
イベントハンドラ内でthisキーワードが参照する値は、イベントモデルによって異なります。
イベントモデル | 参照するオブジェクト |
---|---|
DOMレベル0 | ハンドラが登録されたオブジェクト |
DOMレベル2 | 未定義 (一般的に、ハンドラが登録されたオブジェクト) |
IEイベントモデル | Windowオブジェクト |
DOMレベル2とIEイベントモデルで、汎用的にハンドラが登録されたオブジェクトを参照するには、EventオブジェクトのcurrentTargetプロパティを使用します。
function EventHandler( event ) { var e = event || window.event; var obj = e.currentTarget; }
<a onclick="alert( Object.prototype.toString.call( this ) );" href="javascript:;">Click me!</a>
イベントハンドラ内での、thisの型名を表示します。
a要素 | Click me! |
---|---|
input要素 |
ハンドラが登録されたオブジェクトをthisが参照するのは、ハンドラ内だけです。そのハンドラ内から呼ばれた関数内では、グローバルオブジェクトを参照します。
var input = document.createElement( 'input' ); input.onclick = Func; // object HTMLInputElement input.onkeydown = function() { Func() } // object Window (ハンドラ内からの関数の呼び出し) document.body.appendChild( input ); function Func() { alert( Object.prototype.toString.call( this ) ); }
つねにthisが同じオブジェクトを参照するようにするには、イベントをhandleEvent()で受け取るようにします。
イベントハンドラのスコープを調べるため、3つのボタンにonclickイベントを設定し、それをクリックしたときの動作を検証します。
function Func( x ) { var button = document.createElement( 'input' ); button.type = 'button'; button.value = x; button.onclick = function() { alert( x ); } document.body.appendChild( button ); } Func( 0 ); Func( 1 ); Func( 2 );
変数xのスコープは関数Func()の中にあり、関数内では値を変更されません。このとき3つのボタンをクリックすると、それぞれ0、1、2と引数の値をそのまま表示します。
function Func() { for( var x = 0; x < 3; x++ ) { var button = document.createElement( 'input' ); button.type = 'button'; button.value = x; button.onclick = function() { alert( x ); } document.body.appendChild( button ); } } Func();
変数xのスコープは関数Func()の中にあり、forループで0、1、2、3の値をとります。このとき3つのボタンをクリックすると、いずれも3と表示します。これはこの関数のスコープを外れた時点での、変数xの値です。
たとえば、
<input type="button" onclick="alert( 'OK' );" />
のようにHTML属性として定義されたイベントは、通常の関数とは異なるスコープを持ちます。