DOM イベント

イベントは、コードの実行に影響を与える可能性のある「興味深い変化」をコードに通知するために発行されます。これは、マウス操作やウィンドウのサイズ変更などのユーザー操作や、環境の変化(バッテリー残量の低下や OS のメディアイベントなど)、その他の原因によって発行されます。

それぞれのイベントは、 Event インターフェイスに基づいたオブジェクトで表現され、何が起こったかについての情報を提供するために、追加のカスタムフィールドや関数を持つことがあります。各イベントのドキュメントには、関連するイベントインターフェイスへのリンクや、その他の関連情報を含む表が (上部付近に) あります。イベントの種類の一覧は、イベント > Event を基にしたインターフェイスにあります。

この記事では、興味のありそうな主なイベントの種類 (アニメーション、クリップボード、ワーカーなど) と、それらの種類のイベントを実装する主なクラスの索引を提供します。最後には、文書化されているすべてのイベントの一覧を掲載しています。

イベント索引

イベントの種類 説明 ドキュメント
アニメーション

ウェブアニメーション API に関するイベント。

アニメーション状態の変化 (例えば、アニメーションの開始または終了) に応答するために使用される。

アニメーションイベントは Document, Window, HTMLElement で発行される。
非同期データ読み取り

データの読み取りに関するイベント。

イベントは AbortSignal, XMLHttpRequest, FileReader で発行される。
クリップボード

クリップボード API に関するイベント。

コンテンツが切り取り、コピー、貼り付けされたときを知るために使用。

イベントは Document, Element, Window で発行される。
変換

変換、すなわち (通常のキー押下を使用しない) テキストの「間接的な」入力に関するイベント。

例えば、音声入力エンジンからのテキスト入力、他の言語の新しい文字を表現するための特殊な装飾キー入力の組み合わせ。

訳注: 日本語のかな漢字変換も含む。

イベントは Element で発行される。
CSS トランジション

CSS トランジションに関するイベント。

CSS トランジションの開始、終了、キャンセルなどの時の通知イベントを提供する。

イベントは Document, HTMLElement, Window で発行される。
データベース

データベース操作時、開く、閉じる、トランザクション、エラーなどに関するイベント。

イベントは IDBDatabase, IDBOpenDBRequest, IDBRequest, IDBTransaction で発行される。
DOM 変化

Document Object Model (DOM) 階層やノードに対する変更に関するイベント。

警告: 変化イベントは非推奨です。 代わりに Mutation Observer を使用してください。

ドラッグ&ドロップ、ホイール

HTML ドラッグ&ドロップ API に関するイベントやホイールイベント

ドラッグイベントやホイールイベントは、マウスイベントから派生したものです。これらのイベントは、マウスホイールやドラッグ/ドロップを使用したときに発行されますが、他の適切なハードウェアでも使用されることがあります。

ドラッグイベントは Document で発行される。

ホイールイベントは Element で発行される。

フォーカス

要素がフォーカスを得たり失ったりすることに関するイベント。

イベントは Element, Window で発行される。
フォーム

フォームが構築されたり、リセットされたり、送信されたりすることに関するイベント。

イベントは HTMLFormElement で発行される。
全画面

全画面 API に関するイベント。

全画面モードとウィンドウモードの間で遷移したとき、この遷移の間でエラーが発生したときの通知に使用。

イベントは Document, Element で発行される。
ゲームパッド

ゲームパッド API に関するイベント。

イベントは Window で発行される。
ジェスチャー

ジェスチャーの実装にはタッチイベントが推奨されます。

イベントは Document, Element で発行される。

加えて、いくつもの標準外のジェスチャーイベントが存在する。

履歴

履歴 API に関するイベント。

イベントは Window で発行される。
HTML 要素コンテンツの表示管理

表示またはテキスト要素の状態の変更に関するイベント。

イベントは HTMLDetailsElement, HTMLDialogElement, HTMLSlotElement で発行される。
入力

HTML の input 要素、例えば <input>, <select>, <textarea> に関するイベント。

イベントは HTMLElement, HTMLInputElement で発行される。
キーボード

キーボードの使用に関するイベント。

キーが上がった、下がった、押された時の通知に使用する。

イベントは Document, Element で発行される。
文書の読み込み/アンロード

文書の読み込みやアンロードに関するイベント。

イベントは DocumentWindow で発行される。

マニフェスト

プログレッシブウェブアプリのマニフェストのインストールに関するイベント。

イベントは Window で発行される。
メディア

メディアの使用 (メディアキャプチャとストリーム APIウェブオーディオ APIピクチャインピクチャ API、など) に関するイベント。

イベントは ScriptProcessorNode, HTMLMediaElement, AudioTrackList, AudioScheduledSourceNode, MediaRecorder, MediaStream, MediaStreamTrack, VideoTrackList, HTMLTrackElement, OfflineAudioContext, TextTrack, TextTrackList, Element/audio, Element/video で発行される。
メッセージ

ウィンドウが他の閲覧コンテキストからメッセージを受け取ることに関するイベント。

イベントは Window で発行される。
マウス

コンピューターのマウスの使用に関するイベント。

マウスのクリック、ダブルクリック、離す、押すイベント、右クリック、要素内または要素外への移動、テキスト選択など。

ポインターイベントは、ハードウェアに依存しない、マウスイベントの代替となるものです。ドラッグイベント、ホイールイベントは、マウスイベントから派生したものです。

マウスイベントは Element で発行されます。
ネットワーク/接続

ネットワーク接続が得られた、または失われたことに関するイベント。

イベントは Window で発行される。

イベントは NetworkInformation (ネットワーク情報 API) で発行される。

決済

決済リクエスト API に関するイベント。

イベントは PaymentRequest, PaymentResponse で発行される。

パフォーマンス

パフォーマンス API に分類されたパフォーマンス関連仕様書に関するイベント。

イベントは Performance で発行される。

ポインター

ポインターイベント API に関するイベント。

マウス、タッチ、ペン/スタイラスなどのポインティングデバイスから、ハードウェアに依存しない通知を提供する。

イベントは Document, HTMLElement で発行される。
印刷

印刷に関するイベント。

イベントは Window で発行される。
プロミスの拒否

JavaScript のプロミスが拒否されたときにグローバルスクリプトコンテキストに送信されるイベント。

イベントは Window で発行される。
ソケット

WebSockets API に関するイベント。

イベントは Websocket で発行される。
SVG

SVG 画像に関するイベント。

イベントは SVGElement, SVGAnimationElement, SVGGraphicsElement で発行される。

テキスト選択

テキストの選択に関するイベント。

イベント (selectionchange) は、 HTMLTextAreaElementHTMLInputElement で発行される。

タッチ

Touch Events API に関するイベント。

タッチ反応画面 (すなわち指またはスタイラスを使用したもの) の操作による通知イベントを提供する。 Force Touch API に関するものではない。

イベントは Document, Element で発行される。
バーチャルリアリティ

WebXR 機器 API に関するイベント。

警告: WebVR API (および関連する Window イベント) は非推奨です。

イベントは XRSystem, XRSession, XRReferenceSpace で発行される。
RTC (リアルタイムコミュニケーション)

WebRTC API に関するイベント。

イベントは RTCDataChannel, RTCDTMFSender, RTCIceTransport, RTCPeerConnection で発行される。
サーバー送信イベント

サーバー送信イベント API に関するイベント。

イベントは EventSource で発行される。
発声

Web Speech API に関するイベント。

イベントは SpeechSynthesisUtterance で発行される。
ワーカー

ウェブワーカー API, サービスワーカー API, ブロードキャストチャンネル API, チャンネルメッセージング API に関するイベント。

新しいメッセージやメッセージ送信エラーに応答するために使用されます。サービスワーカーは、プッシュ通知、表示された通知をユーザーがクリックしたこと、プッシュ購読が無効になったこと、コンテンツインデックスからアイテムが削除されたことなど、その他のイベントを通知することもできます。

イベントは ServiceWorkerGlobalScope, DedicatedWorkerGlobalScope, SharedWorkerGlobalScope, WorkerGlobalScope, Worker, BroadcastChannel, MessagePort で発行されます。

イベントの作成と配信

組み込みインターフェイスによって発行されるイベントに加えて、DOM イベントを自分で作成して配信することができます。このようなイベントは、ブラウザーによって発行されるイベントとは対照的に、一般に「合成イベント」と呼ばれます。

カスタムイベントの作成

イベントは、次のように Event コンストラクターを使用して作成できます。

js
const event = new Event("build");

// イベントを待ち受けする
elem.addEventListener(
  "build",
  (e) => {
    /* … */
  },
  false,
);

// イベントを配信する
elem.dispatchEvent(event);

上記のコード例は EventTarget.dispatchEvent() メソッドを使用します。

カスタムデータの追加 – CustomEvent()

イベントオブジェクトにデータを追加するには、CustomEvent インターフェイスが存在し、detail プロパティを使用してカスタムデータを渡すことができます。 たとえば、イベントは次のようにして作成することができます。

js
const event = new CustomEvent("build", { detail: elem.dataset.time });

これにより、イベントリスナー内の追加データにアクセスすることができます。

js
function eventHandler(e) {
  console.log(`The time is: ${e.detail}`);
}

カスタムデータの追加 - Event のサブクラス化

Event インターフェイスもサブクラス化することができます。これは、再利用や、より複雑な独自のデータ、あるいはイベントにメソッドを追加する場合などに特に有益です。

js
class BuildEvent extends Event {
  #buildTime;

  constructor(buildTime) {
    super("build");
    this.#buildTime = buildTime;
  }

  get buildTime() {
    return this.#buildTime;
  }
}

このサンプルコードは、読み取り専用のプロパティと固定イベント型を持つ BuildEvent クラスを定義しています。

このイベントは、次のように作成できます。

js
const event = new BuildEvent(elem.dataset.time);

追加のデータは、独自のプロパティを使用して、イベントリスナーでアクセスすることができます。

js
function eventHandler(e) {
  console.log(`時刻: ${e.buildTime}`);
}

イベントのバブリング

子要素からイベントを起動させ、祖先要素がそれを、任意でデータも、受け取りたい場合がよくあります。

html
<form>
  <textarea></textarea>
</form>
js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

// 新しいイベントを生成し、バブリングを許可し、 "detail" プロパティに渡したいデータを設定する
const eventAwesome = new CustomEvent("awesome", {
  bubbles: true,
  detail: { text: () => textarea.value },
});

// フォームイベントが "awesome" カスタムイベントを待ち受けし、渡されたものの text() メソッドをコンソールに出力する
form.addEventListener("awesome", (e) => console.log(e.detail.text()));

// ユーザー型の場合、 form 内の textarea は発生させるイベントを起動・処理し、それを開始点として使用する
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));

イベントの動的な生成と処理

要素はまだ作成されていないイベントを待ち受けすることができます。

html
<form>
  <textarea></textarea>
</form>
js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

form.addEventListener("awesome", (e) => console.log(e.detail.text()));

textarea.addEventListener("input", function () {
  // イベントをその場で作成、配信/起動する
  // メモ: オプションとして、「アロー関数式」の代わりに「関数式」を活用して、 "this" が要素を表すようにしています。
  this.dispatchEvent(
    new CustomEvent("awesome", {
      bubbles: true,
      detail: { text: () => textarea.value },
    }),
  );
});

組み込みイベントの起動

この例では、 DOM メソッドを使用してチェックボックスでクリック (プログラムでクリックイベントを生成する) をシミュレートする方法を示します。デモを見る

js
function simulateClick() {
  const event = new MouseEvent("click", {
    view: window,
    bubbles: true,
    cancelable: true,
  });
  const cb = document.getElementById("checkbox");
  const cancelled = !cb.dispatchEvent(event);

  if (cancelled) {
    // preventDefault というハンドラーが呼び出されます。
    alert("キャンセルされました");
  } else {
    // 呼び出されたハンドラーはどれも preventDefault を呼び出していません。
    alert("キャンセルされていません");
  }
}

イベントハンドラーの登録

ハンドラーの登録には、推奨される方法が 2 つあります。イベントハンドラーのコードは、ターゲットとなる要素の対応する onイベント名 プロパティに代入して、イベントが起動されたときに実行されるようにするか、 addEventListener() メソッドを使用して、ハンドラーを要素のリスナーとして登録するかすることができます。いずれの場合も、ハンドラーは Event インターフェイス (または派生インターフェイス) に準拠したオブジェクトを受け取ります。主な違いは、イベントリスナーのメソッドを使うと、複数のイベントハンドラーを追加 (または削除) できることです。

警告: 第 3 の方法として、 HTML の onイベント名 属性を使ってイベントハンドラーを設定する方法がありますが、お勧めしません。これはマークアップを膨張させ、可読性を低下させ、デバッグを困難にします。詳しくは、インラインイベントハンドラーを参照してください。

onevent プロパティの使用

慣習上、イベントを発行する JavaScript オブジェクトには、それに対応する "onevent" プロパティ (イベント名の前に "on" を付けて命名) があります。これらのプロパティは、イベントが発行されたときに、関連するハンドラーコードを実行するために呼び出されます。

イベントハンドラーのコードを設定するには、適切な onevent プロパティに代入してください。 1 つの要素のそれぞれのイベントに対して、割り当てることができるイベントハンドラーは 1 つだけです。必要に応じて、同じプロパティに別の関数を代入することで、ハンドラーを置き換えることができます。

以下の例では、 greet() 関数を click イベントに割り当てるために onclick プロパティを使用しています。

js
const btn = document.querySelector("button");

function greet(event) {
  console.log("greet:", event);
}

btn.onclick = greet;

なお、イベントハンドラーの第一引数には、イベントを表すオブジェクトが渡されます。このイベントオブジェクトは、 Event インターフェイスを実装しているか、またはそれを継承しています。

EventTarget.addEventListener

要素にイベントハンドラーを設定する最も柔軟な方法は、 EventTarget.addEventListener メソッドを使用することです。この方法では、複数のリスナーを 1 つの要素に割り当てることができ、必要に応じて (EventTarget.removeEventListener を使用して) リスナーを削除することができます。

メモ: イベントハンドラーの追加と削除ができることで、例えば、同じボタンで状況によって異なるアクションを実行することができます。また、より複雑なプログラムでは、古い、使われていないイベントハンドラーを整理することで、効率を上げることができます。

以下では、単純な greet() 関数をクリックイベントのリスナーまたはイベントハンドラーとして設定する方法を示します (必要に応じて、名前付き関数の代わりにラムダ関数を使用することもできます)。繰り返しますが、イベントは、イベントハンドラーの第一引数として渡されます。

js
const btn = document.querySelector("button");

function greet(event) {
  console.log("greet:", event);
}

btn.addEventListener("click", greet);

このメソッドは、イベントのキャプチャおよび削除の制御をするために、追加の引数/オプションを取ることもできます。詳細については、 EventTarget.addEventListener のリファレンスページを参照してください。

中止シグナルの使用

イベントリスナーの注目すべき機能は、中止シグナルを使って複数のイベントハンドラーを同時にクリーンアップできることです。

これは、同じ AbortSignal を、一緒に削除できるようにしたいすべてのイベントハンドラーの addEventListener() 呼び出しに渡すことで行われます。その後、 AbortSignal を所有するコントローラーで abort() を呼び出すと、そのシグナルで追加されたすべてのイベントハンドラーが削除されます。例えば、 AbortSignal で削除できるイベントハンドラーを追加するには、次のようにします。

js
const controller = new AbortController();

btn.addEventListener(
  "click",
  (event) => {
    console.log("greet:", event);
  },
  { signal: controller.signal },
); // このハンドラーに AbortSignal を渡す

上記のコードで生成したイベントハンドラーは、次のようにして削除することができます。

js
controller.abort(); // このコントローラーに関連付けられたすべてのイベントハンドラーを削除

仕様書

Specification
DOM
# events
HTML
# events-2

関連情報