Web/DB プログラミング徹底解説

ホーム > JavaScript プログラミング > イベント処理の基本

イベント処理の基本

イベントバブリング (event bubbling) : 階層構造をとるDOM要素において、下層の要素が発生させたイベントを上方の要素へも伝播させることをイベントバブリングといいます。すべてのイベントがバブルアップするわけではありません。また、バブリングの連鎖を断ち切ることもできます。このためには stopPropagation()メソッドを使います。

: FireFox 1.5 で動作確認可
<html>
<body>
<div id="mydv">
    <ul id="myul">
    <li id="myli">Click me!</li>
</ul>
</div>
<script type="text/javascript">
function click_handler1 (e) {
    alert('1 ' + e.target + ' bubbles=' + e.bubbles + ' ' + e.type);
}

function click_handler2 (e) {
    alert('2 ' + e.target + ' bubbles=' + e.bubbles + ' ' + e.type);
    e.stopPropagation();
}

function click_handler3 (e) {
    alert('3 ' + e.target + ' bubbles=' + e.bubbles + ' ' + e.type);
}

document.getElementById("myli").addEventListener("click", click_handler1, false);
document.getElementById("myul").addEventListener("click", click_handler2, false);
document.getElementById("mydv").addEventListener("click", click_handler3, false);
</script>
</body>
</html>

尚このコードはイベントリスナー(event listener)のセットアップに関する非常に単純なサンプルコードにもなっています。この方法では HTML 要素より後側に JavaScriptコードを記述必要があります。イベントセットアップの時点でHTML要素を見つけられなければならないからです。この問題を回避するためには、ウィンドウのロード(load)イベントにてイベントリスナーをセットアップします。

: FireFox 1.5 or later で動作確認可能
<html>
<head>
<script type="text/javascript">
function click_handler1 (e) {
 
...

function setupEventListeners() {
    document.getElementById("myli").addEventListener("click", click_handler1, false);
    document.getElementById("myul").addEventListener("click", click_handler2, false);
    document.getElementById("mydv").addEventListener("click", click_handler3, false);
}

window.addEventListener("load", setupEventListeners, false);
</script>
</head>
<body>
    <div id="mydv">
        <ul id="myul">
            <li id="myli">Click me!</li>
        </ul>
    </div>
</body>
</html>

W3C DOM の イベントターゲットインターフェイスは、次のメソッドを定義します:

void addEventListener (
        in DOMString type,
        in EventListener listener,
        in boolean useCapture);
void removeEventListener (
        in DOMString type,
        in EventListener listener,
        in boolean useCapture);
boolean dispatchEvent(in Event evt)
        raises(EventException);

イベントリスナーが受け取っているのはイベントオブジェクト (event object)で、DOM Level 3 の Event interfaceで定義されます。

しかし残念なことに、シェアの大きい MS の Internet Explorer は標準のインターフェイスを実装しておらず、独自の実装をしています。このため、実際にインターネット環境で動作するコードにするためには、Internet Explorer 用のコードを差し挟まなければなりません。この問題を解決するには以下のような addEvent ファンクションを使います。



function addEvent(element, eventType, fn, useCapture) {

    if (element.addEventListener) { // W3C DOM 標準 - FireFox ...
        element.addEventListener(eventType, fn, useCapture);
        return true;
    }
    else if (element.attachEvent) { // Internet Explorer 専用
        var r = element.attachEvent('on' + eventType, fn);
        return r;   
    }
    else {
        element['on'+eventType] = fn;
    }
   
}

ここでは、メソッドの有無をチェックしてから、エレメントに対してイベントハンドラを設定しています。

さらにもう一点、クロスブラウザを意識する上で気をつけなければならないのは、イベントの渡され方が異なる点です。 Internet Explorer は W3C DOM の Event Object を正確には実装していないので、 イベントハンドラでその点についても考慮しなければなりません。上記コードでイベントハンドラをセットしますが、イベントハンドラは一般的に次の形をして います。

function foo(e) {
    if ( e && e.target ) { // W3C DOM Event Object
    }
    else if ( e && e.srcElement ) { // Internet Explorer (IHTMLEventObj 系)
    }
}

e はイベントオブジェクトが渡されます。MS の実装はMSDNに記載があります。一方、W3C DOM の Event Object は W3C のサイトにあります。

以上、まとめると以下のようなコードになります。こちらは FireFox 1.5, IE6, Opera 共に動作確認できます。

<html>
<head>
<script type="text/javascript">

function addEvent(element, eventType, fn, useCapture) {
    if (element.addEventListener) {
        element.addEventListener(eventType, fn, useCapture);
        return true;
    }
    else if (element.attachEvent) {
        var r = element.attachEvent('on' + eventType, fn);
        return r;    
    }
    else {
        element['on' + eventType] = fn;
    }
}

function click_handler1 (e) {
    if (e && e.target) {
        e.target.style.color = 'red';
        alert('target=' + e.target);
    }
    else if (e && e.srcElement) {
        e.srcElement.style.color = 'blue';
        alert('srcElement = ' + e.srcElement);
    }
}

function setupEventListeners() {
    var elm = document.getElementById("myli");
    addEvent(elm, "click", click_handler1, false);
}

addEvent(window, "load", setupEventListeners, false);

</script>
</head>
<body>
    <div id="mydv">
        <ul id="myul">
            <li id="myli">Click me!</li>
        </ul>
    </div>
</body>
</html>