恵比寿のWebサイト制作・Webデザインチームのブログ。Webデザインやコーディング、SEO対策まで幅広く手掛けています。

恵比寿のデザイン制作チームのブログです。

Webデザイン、
Web制作、
SEO対策の
ご依頼・ご相談

Contact

Javascriptでイベントリスナーの処理をキャンセルしたい時に扱うメソッドの使い分け

投稿日:2018-06-01 更新日:




javascript

今回はJavascriptでイベントをキャンセルする方法について書いていきたいと思います。

JavascriptではイベントオブジェクトのstopPropagation、stopImmediatePropagation、preventDefaultを扱うことによってイベントの処理をキャンセルすることができます。

イベントの伝播

まず、前提知識としてイベントの伝播について説明します。

イベントリスナーはイベントが発生した要素のみで実行されるわけではなく、3つのフェーズを通して実行されています。

phase02

キャプチャフェーズでは、windowオブジェクトから下位の要素にイベントが伝播していきます。

ターゲットフェーズでは、イベントの発生した要素を特定しています。

バブリングフェーズでは、イベントの発生した要素からwindowオブジェクトへ向かって上位の要素にイベントが伝播していきます。

 

なお、キャプチャフェーズとバブリングフェーズの途中で、関連するイベントリスナーがある場合には、それらのイベントも実行されるようになっています。

サンプルデモを使って実際の動作を見ていきましょう。

 

 

上記のサンプルデモではクリックされた要素から順に上部ノードへイベントが伝播します。

a要素であるlinkをクリックすると、イベントの最後にa要素によるページ移動のイベントが行われます。

この順序は、addEventListenerの第3引数をfalseにすることで逆にすることができます。

ただし、a要素のページ移動などのブラウザの標準で搭載された動作は最後に行われます。

また、ここではlinkに2つのイベントが登録されていますが、同じ要素に登録したイベントはjavascriptのコードの記述順に発生します。

document.addEventListener('DOMContentLoaded', function() {
  //1番目に登録
  document.getElementById('link').addEventListener('click', function(e) {
    window.alert('linkのイベントリスナーが発生');  
  }, false);
  //2番目に登録
  document.getElementById('link').addEventListener('click', function(e) 
    window.alert('linkのイベントリスナーが発生(2回目)');
  }, false);
}, false);

 

イベントリスナーのキャンセル

イベントの伝播について一通り触れたところで、ここからは実際にイベントをキャンセルする方法を記述していきます。

stopPropagationメソッド

ターゲットフェーズのイベントのみ実行させ、上位の要素にイベントを伝播させたくない場合にはstopPropagationメソッドを使います。

HTML

<div id="wrapper">
  <p>wrap</p>
  <div id="content">
    <p>content</p>
    <a id="link" href="https://www.google.co.jp/" target="_blank">Link</a>
  </div>
</div>

 

Javascript

document.addEventListener('DOMContentLoaded', function() {

  document.getElementById('link').addEventListener('click', function(e) {
    window.alert('linkのイベントリスナーが発生');
    e.stopPropagation();
  }, false);

  document.getElementById('link').addEventListener('click', function(e) {
    window.alert('linkのイベントリスナーが発生(2回目)');
  }, false);

  document.getElementById('content').addEventListener('click', function(e) {
    window.alert('contentのイベントリスナーが発生');
  }, false);

  document.getElementById('wrapper').addEventListener('click', function(e) {
    window.alert('wrapperのイベントリスナーが発生');
  }, false);

}, false);

 

上記のようにstopPropagationメソッドを設定すると、設定した要素から上位要素へのイベントの伝播はキャンセルされます。

ここでは、linkのイベントリスナーが発生した時に、上位のcontent/wrapperへの伝播をキャンセルしています。

※addEventListener()の第3引数をtrueに指定すると、stopPropagationメソッドを設定した要素から下位要素へのイベントの伝播がキャンセルされます。

stopImmediatePropagationメソッド

stopPropagationメソッドを用いて上位要素へのイベントの伝播はキャンセルできましたが、同じ要素に登録されているイベントはキャンセルできていません。

先ほどの例では、linkのイベントリスナーが2回発生しています。

これを防ぐにはstopImmediatePropagationメソッドを使用します。

Immediateは「即座に/直ちに」という意味で対象のイベントを発生させるとその場で即座にキャンセルさせるので、同じ要素に登録されたイベントリスナーも発生しません。

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('link').addEventListener('click', function(e) {
  window.alert('linkのイベントリスナーが発生');
  e.stopImmediatePropagation();
  }, false);

  document.getElementById('link').addEventListener('click', function(e) {
    window.alert('linkのイベントリスナーが発生(2回目)');
  }, false);

  document.getElementById('content').addEventListener('click', function(e) {
    window.alert('contentのイベントリスナーが発生');
  }, false);

  document.getElementById('wrapper').addEventListener('click', function(e) {
    window.alert('wrapperのイベントリスナーが発生');
  }, false);

}, false);

 

 

preventDefaultメソッド

イベント本来の挙動をキャンセルするにはpreventDefaultメソッドを使用します。

ここでは、a要素が標準で持っている「ページにリンクする」イベントが発生していますが、preventDefaultメソッドを用いることでそのイベント本来の挙動をキャンセルさせることができます。

下記の例ではこれまでの例とは異なり、最後にページ移動しないようになっています。

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('link').addEventListener('click', function(e) {
    window.alert('linkのイベントリスナーが発生');
    e.preventDefault();
  }, false);

  document.getElementById('link').addEventListener('click', function(e) {
    window.alert('linkのイベントリスナーが発生(2回目)');
  }, false);

  document.getElementById('content').addEventListener('click', function(e) {
    window.alert('contentのイベントリスナーが発生');
  }, false);

  document.getElementById('wrapper').addEventListener('click', function(e) {
    window.alert('wrapperのイベントリスナーが発生');
  }, false);

}, false);

 

 

キャンセルできないイベント

preventDefaultメソッドでもイベントをキャンセルできない場合があります。

イベントがキャンセル可能かどうかはcancelableプロパティで確認することができます。

キャンセル可能であれば、trueを返し、不可であればfalseを返します。

以下の例ではinputのテキストに対するクリックとフォーカスイベントのキャンセル可否を調べています。

フォーカス時のアラートイベントが無限ループに陥るため、blurメソッドでフォーカスを外すよう設定しています。

document.addEventListener('DOMContentLoaded', function() {
  //clickイベントをキャンセル可能か調べる
  document.getElementById('text-1').addEventListener('click', function(e) {
    if (e.cancelable === true) {
      window.alert("キャンセルできます。");
    } else if (e.cancelable === false) {
      window.alert("キャンセルできません。");
    } else {
      window.alert("エラーです。");
    }
  }, false);

  //focusイベントをキャンセル可能か調べる
  document.getElementById('text-2').addEventListener('focus', function(e) {
    if (e.cancelable === true) {
      window.alert("キャンセルできます。");
    } else if (e.cancelable === false) {
      window.alert("キャンセルできません。");
    } else {
      window.alert("エラーです。");
    }
    this.blur();
  }, false);
}, false);

 

まとめ

今回はイベントリスナーのキャンセルには主に3つのメソッドがあることを紹介しました。

注意する点は、preventDefaultメソッドだけではイベントの伝播はとめられないということです。

preventDefaultメソッドと、stopPropagation/stopImmediatePropagationメソッドを同時に活用することで特定のイベントのみを発生させることができます。

イベントのキャンセルは使われる頻度も多いので是非覚えておきましょう。




この記事をシェアする

  • Twitter
  • Facebook
  • BookmarkB!
  • Pocket

Related Entries

この記事を書いた人

TOM

TOM

Webデザイナー、UI/UXデザインと共にJavascript、PHP等のプログラミング言語について日々勉強中。