範囲外クリックでポップアップを閉じる正しい JQuery

  • 30
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

ポップアップを表示して、その領域外をクリックされた時にそのポップアップを閉じたい、といった処理はよくあります。しかしこれを実装する時にちょっとした気をつける点があります。

よく見かけて気になっている悪い例

Stackoverflow などでよくある処理としては、クリックイベントを全検知して、Pop up を閉じるような処理をしてしまう。もし自分自身だったら stopPropagation()1 して、イベント伝播しなくする。理由としては stopPropagation() しないと、ポップアップそのものをクリックした時に閉じてしまうのを防ぎたいからです。

例えばこういったコードです。

$('#target_element').click(function(event) {  
  event.stopPropagation();  
});

正しいアプローチ

アプローチとしては、クリックイベントを全検知 (ついでに touch device も対応)。もし、そのクリックが自分を含まないものであれば2閉じる処理をするようにします。


$(document).on('click touchend', function(event) {
  if (!$(event.target).closest('#target').length) {
    // ここに処理;
  }
});

なぜ悪い例としてあげたのか?

安易に stopPropagation() するべきではないのかということなのですが、https://css-tricks.com/dangers-stopping-event-propagation/ に詳しく解説があります。かいつまむと、

In the "How to detect a click outside of an element?" example above, the purpose of calling stopPropagation isn't to get rid of the click event altogether, it's to avoid running some other code on the page.

「stopPropagation が、クリックイベント自体を取り除くだけではなく、なにか他のコードが実行されることを妨げている効果も持もたらす。」
例えば、ポップアップがオープンな時に、他のクリックイベントを検知して動作するボタンをクリックしても、クリックイベントが伝わらないようなことが起こりえます。

To avoid bugs, it's almost always best to leave events alone and let them propagate as the browser intended.

「イベント自体はそのまま発生させて、ブラウザが意図したようにイベントを伝播させたほうがこのましい。」


※本投稿は http://d.hatena.ne.jp/mabots/20151120/1448003977Coubic Advent Calendar 2015 に向けて、加筆・再編したものです。


  1. stopPropagation()、preventDefault()、return false 各々についてわかりやすいのは http://blog.neo.jp/dnblog/index.php?module=Blog&action=Entry&blog=pg&entry=3107&rand=ef81c 

  2. こちらも参照 https://api.jquery.com/closest/