イベント

イベント #

Javascriptのイベントについてを記す。

イベントとは、ユーザーの画面上での何らかの操作を、プログラム上で検知し、利用できるようにする機能である。

画面上での操作とは、例えばあるボタンを押した、あるテキストをフォーカスした、などがある。

例として、以下のようなコードを記載する。

html

<p id="target">ここにカーソルを持ってくると・・</p>

javascript

window.onload = function() {
    var target = document.getElementById('target');

    target.addEventListener('mousemove',function(){
        this.innerText = 'ここにカーソルを持ってくると・・ → 赤くなる!';
        this.style.color = "red";
    });
};

表示例


ここにカーソルを持ってくると・・


上記のテキストの上にカーソルを持ってくると、指定したイベントが発動してテキストの内容と色が変化する。

イベントに対応して処理を実行する仕組みをイベントハンドラという。イベントハンドラには処理を1つのみ定義できる。

1つのイベントに処理を複数定義する仕組みもあり、そちらはイベントリスナという。

イベントハンドラの種類 #

イベントの種類としては、主に以下のようなものがある。

  • ウィンドウイベント
  • フォームイベント
  • キーボードイベント
  • マウスイベント
  • タッチイベント
  • ドラッグ&ドロップイベント

ウィンドウイベント #

ウィンドウイベントとは、ブラウザのボタンが押された時、ページが遷移した時などといった、ウィンドウの状態が変化したときに発生する。

ウィンドウイベントのイベントハンドラの種類を以下に記載する。

onafterprint ・・ 印刷直後
onbeforeprint ・・ 印刷直前
onbeforeunload ・・ ページ遷移直前
onblur ・・ フォーカスが外れた時
onerror ・・ Javascriptエラーが発生した時
onfocus ・・ フォーカスされた
onhashchange ・・ URLのハッシュが変更
onload ・・ ページの読み込みが完了した時
onmessage ・・ メッセージを受信
onoffline ・・ ネットワークがオンラインからオフラインになった時
ononline ・・ ネットワークがオフラインからオンラインになった時
onpagehide ・・ 他のページへの遷移などで元のページが隠された時
onpageshow ・・ ページの読み込みが完了した時
onpopstate ・・ 履歴が取り出された時
onredo ・・ やり直す(redo)ボタンが押された時
onresize ・・ ウィンドウのサイズが変更された時
onstorage ・・ ローカルストレージまたはセッションストレージが変更された時
onundo ・・ やり直す(redo)ボタンが押された時
onunload ・・ 他ページに移動した時

フォームイベント #

フォームイベントとは、フォーム上をフォーカスした、フォームを入力した場合など、フォームの状態が変化した場合に発生するイベントである。

フォームイベントのイベントハンドラの種類を以下に記載する。

onblur ・・ フォーカスが外れた時
onchange ・・ 変更された時
onfocus ・・ フォーカスされた
onformchange ・・ フォームの値が変更された時
onforminput ・・ フォームの値が入力された時
onselect ・・ 要素が選択された時
onsubmit ・・ 送信(submit)ボタンが押された時

キーボードイベント #

キーボードイベントとはキーを押すなど、キーボードの状態が変化した場合に発生するイベントである。

イベントハンドラは以下の通り。

onkeydown ・・ キーが押された
onkeypress ・・ キーが押して離された
onkeyup ・・ キーが離された

マウスイベント #

マウスイベントはマウスのボタンを押す、ドラッグするなど、マウスの状態が変化した場合に生ずるイベントである。

イベントハンドラは以下の通り。

onclick ・・ ボタンがクリックされた
oncontextmenu ・・ マウスの右ボタンが押された
ondblclick ・・ ダブルクリックされた時
ondrag ・・ ドラッグされた時
ondragend ・・ ドラッグが終わった時
ondragstart ・・ ドラッグが始まった時
onmousedown ・・ ボタンが押された時
onmousemove ・・ マウスポインタが移動された時
onmouseout ・・ マウスポインタが要素から外れた時
onmouseover ・・ マウスポインタが要素上に入った時
onmousemove ・・ マウスポインタが移動された時
onscroll ・・ スクロールバーを操作した時

タッチイベント #

タッチイベントは、タッチパネルの画面を触るなど、タッチパネルの状態が変化した場合に発生する。

イベントハンドラを以下に示す。

ontouchstart ・・ 指が置かれた時
ontouchmove ・・ 指がドラッグされた時
ontouchend ・・ 指が離れた時

ドラッグ&ドロップイベント #

ドラッグ&ドロップイベントは先述したマウスイベントの一種である。

設定方法は、以下の通り。

  • ドラッグする要素にdraggable属性を設定
  • ドラッグする要素にドラッグ開始時のハンドラを設定
  • ハンドラにドラッグ(・ドロップ)時の処理を記述

サンプルコードを以下に示す。

javascript

function dragHandler(event){
    //動作結果を表示するオブジェクトを取得
    var p = document.getElementById("status");

    //ドラッグするデータの識別子をDataTransferオブジェクトにセット
    event.dataTransfer.setData("text","ドラッグされました!");

    //動作結果を表示
    p.innerHTML="ドラッグされました!";
}

function dropHandler(event){
    var p = document.getElementById("status");
    textdata = event.dataTransfer.getData('text');
    p.innerHTML = textdata + ' → ドロップされました!'
    event.preventDefault();
}

html

<div id="from" draggable="true" ondragstart="dragHandler(event);">
<p>この要素を下にドラッグして・・</p>
</div>
<br>
<div id="to" ondragover="event.preventDefault();" ondrop="dropHandler(event);">
<p>ここにドロップしてみよう!</p>
</div>
<br>
<div>
<p id="status">まだドラッグ&ドロップされてません</p>
</div>

表示例



この要素を下にドラッグして・・


ここにドロップしてみよう!


まだドラッグ&ドロップされてません



イベントリスナ #

先程の例でもあったように、イベントハンドラでは処理を1つしか定義できない。複数定義するにはどうすれば良いか。

ここで、**addEventListener()**を利用すると、1つのイベントに複数の処理を登録できる。

要素.addEventListener(イベント名,イベントリスナ,伝播の可否)

先述したドラッグ&ドロップの例をイベントリスナで実装してみよう。以下のようになる。

javascript

window.onload = function() {
    addHandler();
}

function dragHandler2(event){
    //動作結果を表示するオブジェクトを取得
    var p = document.getElementById("status2");

    //ドラッグするデータの識別子をDataTransferオブジェクトにセット
    event.dataTransfer.setData("text","ドラッグされました!");

    //動作結果を表示
    p.innerHTML="ドラッグされました!";
}

function dropHandler2(event){
    var p = document.getElementById("status2");
    textdata = event.dataTransfer.getData('text');
    p.innerHTML = textdata + ' → ドロップされました!';
    event.preventDefault();
}

//追加処理、テキストを緑色に変更
function dropHandler2_2(event){
    var p = document.getElementById("status2");
    p.style.color = 'green';
}

//イベントリスナを追加する
function addHandler(){
    var to2 = document.getElementById("to2");
    to2.addEventListener("drop",dropHandler2_2,false);
}

html

<div id="from2" draggable="true" ondragstart="dragHandler2(event);">
<p>この要素を下にドラッグして・・</p>
</div>
<br>
<div id="to2" ondragover="event.preventDefault();" ondrop="dropHandler2(event);">
<p>ここにドロップしてみよう!</p>
</div>
<br>
<div>
<p id="status2">まだドラッグ&ドロップされてません</p>
</div>

表示例



この要素を下にドラッグして・・


ここにドロップしてみよう!


まだドラッグ&ドロップされてません



イベントリスナの削除 #

イベントリスナを削除するには、**removeEventListener()**メソッドを利用する。

要素.removeEventListener(イベント名,イベントハンドラ,伝播の可否);

イベントの発火と伝播 #

今度は以下のような例を考えてみる。

html

<div id="main2">
    <p>このp要素にカーソルを置くと・・・・</p>
    <p id="target2">このp要素(target)にカーソルを持ってくると・・</p>
</div>

javascript(main->main2,target->target2と変更)

window.onload = function() {
    var target = document.getElementById('target2');

    target.addEventListener('mousemove',function(){
        this.innerText = 'このp要素(target)にカーソルを持ってくると・・ → 赤くなる!';
        this.style.color = "red";
    });

    var main = document.getElementById('main2');

    main.addEventListener('mousemove',function(){
        this.innerText = 'このp要素にカーソルを置くと・・・・ → 青くなる!';
        this.style.color = "blue";
    });
};

表示例


このp要素にカーソルを置くと・・・・

このp要素(target)にカーソルを持ってくると・・


この例では、id=“main"の中にid=“target"の要素があり、またその両方にイベントが設定されている。

この時に、id=“target"の部分にカーソルを持ってくると、親のid=“main"のイベントも走ってしまう。

このような事象はなぜ発生してしまうのだろうか?

ここにはイベントのメカニズムが関わっている。ユーザーの操作でイベントが発生した時、ブラウザはDOMツリーの上の方からそのターゲットを探しにいく。

そこで、対象の要素を発見した時、イベントが発火し、設定された処理が動く。

実はここで終わらず、今度はその箇所から親要素に向けてイベントは伝播していく。その際に、設定されているイベントがある場合、そのタイミングでそのイベントの処理が走ってしまう。

図に示すと以下の通り。まずはDOMツリーの一番上から探して行き、

該当のイベントが発火すると、その場所から上へと辿って行き(伝播)、途上でイベントがあった場合はそれも走る。

このような、イベントの伝播をさせたくない場合は、javascriptのaddEventListenerでの処理関数の引数にeventを指定し、さらに処理内容に**event.stopPropagation()**を追加させる。これにより、伝播をストップできる。

javascript例(main->main3,target->target3と変更)

window.onload = function() {
    var target = document.getElementById('target3');

    target.addEventListener('mousemove',function(event){
        this.innerText = 'このp要素(target)にカーソルを持ってくると・・ → 赤くなる!';
        this.style.color = "red";
        event.stopPropagation();  //伝播をストップさせる。
    });

    var main = document.getElementById('main3');

    main.addEventListener('mousemove',function(){
        this.innerText = 'このp要素にカーソルを置くと・・・・ → 青くなる!';
        this.style.color = "blue";
    });
};

表示例


このp要素にカーソルを置くと・・・・

このp要素(target)にカーソルを持ってくると・・


カスタムイベント #

これまで述べたものではイベントの発生はブラウザ上での特定の操作が行われた時に限られていたが、任意のタイミングでイベントを発生させることもできる。(テストなどで利用する)

その方法がここで述べるカスタムイベントであり、やり方は以下の2つである。

  • Eventコンストラクタでイベントオブジェクトを生成
  • イベントリスナを登録した要素オブジェクトのdispatchEvent()でイベントを発生させる

**dispatchEvent()**は、任意にイベントを発生するメソッドである。

要素.dispatchEvent(イベントオブジェクト)

例えば先程の例において、カスタムイベントを適用してみよう。下の例では、指定した要素がドラッグされると、テキストが「ドラッグされました」と変わるが、ここではウィンドウがロードされると同時にドラッグイベントが発生し、実際にドラッグしなくても処理が実行される。それにより、自動で「ドラッグされました」に変わる。

javascript

window.onload = function() {
    
    //イベントリスナ登録(dragHandlerと同じ)
    document.getElementById("from3").addEventListener('drag',function(){
        //動作対象のオブジェクトを取得
        var p = document.getElementById("status3");

        //ドラッグするデータの識別子をDataTransferオブジェクトにセット
        event.dataTransfer.setData("text","ドラッグされました!");

        //動作結果を表示
        p.innerHTML="ドラッグされました!";

    },false);

    //ドラッグイベントの作成
    var customEvent = new Event('drag');

    //イベント発生
    document.getElementById('from3').dispatchEvent(customEvent);
}

html

<div id="from3" draggable="true">
<p>この要素をドラッグすると・・</p>
</div>
<br>
<div>
<p id="status3">まだドラッグされてません</p>
</div>

表示例



この要素をドラッグすると・・


まだドラッグされてません