ユーザーがDIVの外側をクリックしたときにjQueryを使用してDIVを非表示にする


967

私はこのコードを使用しています:

$('body').click(function() {
   $('.form_wrapper').hide();
});

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

そして、このHTML

<div class="form_wrapper">
   <a class="agree" href="javascript:;">I Agree</a>
   <a class="disagree" href="javascript:;">Disagree</a>
</div>

問題は、内部にリンクがあり、divクリックしてもリンクが機能しなくなることです。


6
プレーンなjavascriptを使用すると、次のようなことを試すことができます。jsfiddle.net
Aamir Afridi

を使用している$('html')か、それ$(document)より優れている$('body')
Adrien Be

回答:


2484

同じ問題を持っていた、この簡単な解決策を思いついた。それは再帰的にも機能します:

$(document).mouseup(function(e) 
{
    var container = $("YOUR CONTAINER SELECTOR");

    // if the target of the click isn't the container nor a descendant of the container
    if (!container.is(e.target) && container.has(e.target).length === 0) 
    {
        container.hide();
    }
});

19
それを私のプロジェクトに入れるだけですが、要素の配列を使用してそれらを一度にすべてループするというマイナーな調整を行います。jsfiddle.net/LCB5W
Thomas

5
@mpelzsherman多くの人々が、スニペットはタッチデバイスで機能するとコメントしましたが、投稿が編集されたため、これらのコメントはやや消滅しました。TBH特定の理由で「マウス」を使用したかどうかはわかりませんが、「クリック」でも機能する場合は、「クリック」を使用しない理由はわかりません。

6
コンテナがこのイベントで一度非表示になる必要がありました。このコールバックは使用時に破棄する必要があります。そのために、bind( "click.namespace")でクリックイベントのネームスペースを使用し、イベントが発生したときにunbind( "click.namespace")を呼び出しました。そして最後に、コンテナーを認識するために$(e.target).closest( "。container")。lengthを使用しました...したがって、私はこの答えからトリックを使用しませんでした:D
Loenix '27年

80
$("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );すぐ横で使用することを忘れないでください.hide()。だからdocument、クリックを聞き続けないでください。
ブラソフィロ2014年

12
ベストプラクティスについて$(document).on("mouseup.hideDocClick", function () { ... });は、コンテナーを開く関数と$(document).off('.hideDocClick');on hide関数で記述しました。名前空間を使用mouseupして、ドキュメントに添付されている他の可能なリスナーを削除していません。
campsjos 2015

204

あなたはこのようなもので行くほうがいいです:

var mouse_is_inside = false;

$(document).ready(function()
{
    $('.form_content').hover(function(){ 
        mouse_is_inside=true; 
    }, function(){ 
        mouse_is_inside=false; 
    });

    $("body").mouseup(function(){ 
        if(! mouse_is_inside) $('.form_wrapper').hide();
    });
});

なんて賢い!このテクニックは標準ですか?
2010年

@advait以前に使用したことはありませんでした。hoverイベントハンドラーがすべてであり、多くの可能性が開かれます。
Makram Saleh 2010

5
これは、ウィンドウオブジェクト(=グローバル変数を使用)にデータを入力してもよいと人々に思わせるため、これは良い解決策だとは思いません。

1
@ prc322が言ったことに何かを追加するために、コードを匿名関数でラップして、すぐに呼び出すことができます。 (function() { // ... code })(); このパターンの名前は覚えていませんが、とても便利です。宣言したすべての変数は関数内に存在し、グローバル名前空間を汚染しません。
pedromanoel 2013年

3
@ prc322変数のスコープを変更する方法さえわからない場合は、そのとおりです。このソリューションは適切ではありません... JavaScriptも同様です。スタックオーバーフローからコードをコピーして貼り付けるだけの場合は、ウィンドウオブジェクトの何かを上書きするよりも、はるかに多くの問題が発生します。
Gavin

87

このコードは、ページ上のクリックイベントを検出し、クリックされ#CONTAINER#CONTAINER要素が要素でもその子孫でもない場合にのみ要素を非表示にします。

$(document).on('click', function (e) {
    if ($(e.target).closest("#CONTAINER").length === 0) {
        $("#CONTAINER").hide();
    }
});

これは完璧です!!
Mohd Abdul Mujib

@ 9KSoftお役に立ててよかったです。フィードバックと幸運をありがとう。
ケース

このソリューションは、コンテナーとしてdivを使用する私にとって完璧に機能しました!
JCO9

76

stopPropagationに依存するのではなく、本体に対して発生するクリックイベントのターゲットを確認することができます。

何かのようなもの:

$("body").click
(
  function(e)
  {
    if(e.target.className !== "form_wrapper")
    {
      $(".form_wrapper").hide();
    }
  }
);

また、body要素には、ブラウザに表示される視覚空間全体が含まれない場合があります。クリックが登録されていないことに気付いた場合は、代わりにHTML要素のクリックハンドラーを追加する必要があります。


はい、リンクが機能します!しかし、何らかの理由で、リンクをクリックすると、2回起動します。
スコットユー-

私はこれのバリエーションを使用してしまいました。最初に要素が表示されるかどうかをチェックし、次にtarget.hasClassの場合は非表示にします。
Hawkee 2012

e.stopPropagation();他のクリックリスナーがある場合は忘れないでください
Darin Kolev

2
-1。これform_wrapperにより、その子の1つをクリックするとが非表示になりますが、これは望ましい動作ではありません。代わりにprc322の回答を使用してください。
マークアメリー

38

ライブデモ

クリック領域がターゲット要素またはその子にないことを確認してください

$(document).click(function (e) {
    if ($(e.target).parents(".dropdown").length === 0) {
        $(".dropdown").hide();
    }
});

更新:

jQueryの伝播停止が最良のソリューションです

ライブデモ

$(".button").click(function(e){
    $(".dropdown").show();
     e.stopPropagation();
});

$(".dropdown").click(function(e){
    e.stopPropagation();
});

$(document).click(function(){
    $(".dropdown").hide();
});

更新ありがとうございます、完璧です!タッチデバイスで動作しますか?
FFish

1
この場合、ページに複数のドロップダウンがあります。ドロップダウンを開く前に、すべてのドロップダウンを閉じる必要があると思いますclicked。それ以外の場合は、stopPropagation複数のドロップダウンが同時に開いていることが可能になります。
T04435

19
$(document).click(function(event) {
    if ( !$(event.target).hasClass('form_wrapper')) {
         $(".form_wrapper").hide();
    }
});

2
うーん... div内の何かをクリックすると、何らかの理由でdiv全体が消えます。
スコットユー-

11
ターゲットにクラスがあるかどうかを確認する代わりに、次のことを試してください:if($(event.target).closest( '。form_wrapper).get(0)== null){$( "。form_wrapper")。hide(); これにより、divの内側をクリックしても、divが非表示になりません。
John Haager 2010

17

ソリューションを更新しました:

  • 代わりにmouseenterとmouseleaveを使用してください
  • ホバー使用のライブイベントバインディング

var mouseOverActiveElement = false;

$('.active').live('mouseenter', function(){
    mouseOverActiveElement = true; 
}).live('mouseleave', function(){ 
    mouseOverActiveElement = false; 
});
$("html").click(function(){ 
    if (!mouseOverActiveElement) {
        console.log('clicked outside active element');
    }
});

1
.live非推奨になりました.on代わりに使用してください。
ブレット


9

ESC機能を備えたライブデモ

デスクトップとモバイルの両方で機能します

var notH = 1,
    $pop = $('.form_wrapper').hover(function(){ notH^=1; });

$(document).on('mousedown keydown', function( e ){
  if(notH||e.which==27) $pop.hide();
});

場合によっては、ドキュメントをクリックしたときに要素が本当に表示されることを確認する必要があります。 if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();


8

このようなものではないでしょうか?

$("body *").not(".form_wrapper").click(function() {

});

または

$("body *:not(.form_wrapper)").click(function() {

});

4
この答えは正しくありません。ここでの多くの回答と同様に、これは.form_wrapper(他の問題の中でも)その子をクリックしたときにを非表示にします。
マークアメリー2013

6

たるみさえ:

$("html").click(function(){ 
    $(".wrapper:visible").hide();
});

4
この答えは正しくありません。これ.wrapperにより、ページのどこをクリックしても非表示になります。これは要求されたものではありません。
Mark Amery 2013

6

DOMを1回クリックするたびに1つの特定の要素を非表示にするのではtabindexなく、親に設定<div>してfocusoutイベントをリッスンすることもできます。

設定tabindexにより、blurイベントが確実に発生し<div>ます(通常は発生しません)。

したがって、HTMLは次のようになります。

<div class="form_wrapper" tabindex="0">
    <a class="agree" href="javascript:;">I Agree</a>
    <a class="disagree" href="javascript:;">Disagree</a>
</div>

そしてあなたのJS:

$('.form_wrapper').on('focusout', function(event){
    $('.form_wrapper').hide();
});

5

IPADやIPHONEなどのタッチデバイスの場合、次のコードを使用できます

$(document).on('touchstart', function (event) {
var container = $("YOUR CONTAINER SELECTOR");

if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
    {
        container.hide();
    }
});

5

ここに私が別のスレッドで見つけたjsfiddleがあり、escキーでも動作します:http://jsfiddle.net/S5ftb/404

    var button = $('#open')[0]
    var el     = $('#test')[0]

    $(button).on('click', function(e) {
      $(el).show()
      e.stopPropagation()
    })

    $(document).on('click', function(e) {
      if ($(e.target).closest(el).length === 0) {
        $(el).hide()
      }
    })

    $(document).on('keydown', function(e) {
      if (e.keyCode === 27) {
        $(el).hide()
      }
    })

「クリック」イベントが#test要素内にあるかどうかを検出します。jsfiddle.net / TA96Aとしてリンクをテストしてみましたが、機能する可能性があります。
トーマスW

はい、jsfiddleがリンクの外側をブロックしているようです。http:// jsfiddle.netを使用すると、結果ページがリンクを処理することがわかります:)
djv

5

prc322の素晴らしい答えから構築されました。

function hideContainerOnMouseClickOut(selector, callback) {
  var args = Array.prototype.slice.call(arguments); // Save/convert arguments to array since we won't be able to access these within .on()
  $(document).on("mouseup.clickOFF touchend.clickOFF", function (e) {
    var container = $(selector);

    if (!container.is(e.target) // if the target of the click isn't the container...
        && container.has(e.target).length === 0) // ... nor a descendant of the container
    {
      container.hide();
      $(document).off("mouseup.clickOFF touchend.clickOFF");
      if (callback) callback.apply(this, args);
    }
  });
}

これはいくつかのことを追加します...

  1. 「無制限」引数を持つコールバックを使用して関数内に配置
  2. イベントネームスペースとペアになっているjqueryの.off()への呼び出しを追加して、実行後にドキュメントからイベントをバインド解除します。
  3. モバイル機能に含まれるタッチエンド

これが誰かを助けることを願っています!



4

(prc322の答えに追加するだけです。)

私の場合、このコードを使用して、ユーザーが適切なタブをクリックしたときに表示されるナビゲーションメニューを非表示にしています。コンテナの外側のクリックのターゲットがリンクではないという条件を追加すると便利だと思いました。

$(document).mouseup(function (e)
{
    var container = $("YOUR CONTAINER SELECTOR");

    if (!$("a").is(e.target) // if the target of the click isn't a link ...
        && !container.is(e.target) // ... or the container ...
        && container.has(e.target).length === 0) // ... or a descendant of the container
    {
        container.hide();
    }
});

これは、私のサイトの一部のリンクがページに新しいコンテンツを追加するためです。ナビゲーションメニューが消えると同時にこの新しいコンテンツが追加された場合、ユーザーの混乱を招く可能性があります。


4

非常に多くの回答、1つを追加するための通過権である必要があります...現在(jQuery 3.1.1)の回答は表示されませんでした。

$(function() {
    $('body').on('mouseup', function() {
        $('#your-selector').hide();
    });
});

3
var n = 0;
$("#container").mouseenter(function() {
n = 0;

}).mouseleave(function() {
n = 1;
});

$("html").click(function(){ 
if (n == 1) {
alert("clickoutside");
}
});

3
 $('body').click(function(event) {
    if (!$(event.target).is('p'))
    {
        $("#e2ma-menu").hide();
    }
});

p要素名です。ID、クラス、または要素名を渡すこともできます。


3

.form_wrapperをクリックした場合はfalseを返します。

$('body').click(function() {
  $('.form_wrapper').click(function(){
  return false
});
   $('.form_wrapper').hide();
});

//$('.form_wrapper').click(function(event){
//   event.stopPropagation();
//});

3

フォームラッパーの外側のトップレベルの要素にクリックイベントを添付します。次に例を示します。

$('#header, #content, #footer').click(function(){
    $('.form_wrapper').hide();
});

これはタッチデバイスでも機能します。セレクターのリストに.form_wrapperの親を含めないようにしてください。


3

var exclude_div = $("#ExcludedDiv");;  
$(document).click(function(e){
   if( !exclude_div.is( e.target ) )  // if target div is not the one you want to exclude then add the class hidden
        $(".myDiv1").addClass("hidden");  

}); 

FIDDLE


3

$(document).ready(function() {
	$('.modal-container').on('click', function(e) {
	  if(e.target == $(this)[0]) {
		$(this).removeClass('active'); // or hide()
	  }
	});
});
.modal-container {
	display: none;
	justify-content: center;
	align-items: center;
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(0,0,0,0.5);
	z-index: 999;
}

.modal-container.active {
    display: flex;  
}

.modal {
	width: 50%;
	height: auto;
	margin: 20px;
	padding: 20px;
	background-color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="modal-container active">
	<div class="modal">
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac varius purus. Ut consectetur viverra nibh nec maximus. Nam luctus ligula quis arcu accumsan euismod. Pellentesque imperdiet volutpat mi et cursus. Sed consectetur sed tellus ut finibus. Suspendisse porttitor laoreet lobortis. Nam ut blandit metus, ut interdum purus.</p>
	</div>
</div>


3

https://sdtuts.com/click-on-not-specified-element/からコピー

ライブデモhttp://demos.sdtuts.com/click-on-specified-element

$(document).ready(function () {
    var is_specified_clicked;
    $(".specified_element").click(function () {
        is_specified_clicked = true;
        setTimeout(function () {
            is_specified_clicked = false;
        }, 200);
    })
    $("*").click(function () {
        if (is_specified_clicked == true) {
//WRITE CODE HERE FOR CLICKED ON OTHER ELEMENTS
            $(".event_result").text("you were clicked on specified element");
        } else {
//WRITE CODE HERE FOR SPECIFIED ELEMENT CLICKED
            $(".event_result").text("you were clicked not on specified element");
        }
    })
})

2

私はそれをこのようにしました:

var close = true;

$(function () {

    $('body').click (function(){

        if(close){
            div.hide();
        }
        close = true;
    })


alleswasdenlayeronclicknichtschliessensoll.click( function () {   
        close = false;
    });

});

2
dojo.query(document.body).connect('mouseup',function (e)
{
    var obj = dojo.position(dojo.query('div#divselector')[0]);
    if (!((e.clientX > obj.x && e.clientX <(obj.x+obj.w)) && (e.clientY > obj.y && e.clientY <(obj.y+obj.h))) ){
        MyDive.Hide(id);
    }
});

2

このコードを使用すると、必要な数のアイテムを非表示にできます

var boxArray = ["first element's id","second element's id","nth element's id"];
   window.addEventListener('mouseup', function(event){
   for(var i=0; i < boxArray.length; i++){
    var box = document.getElementById(boxArray[i]);
    if(event.target != box && event.target.parentNode != box){
        box.style.display = 'none';
    }
   }
})

1

できることは、ドロップダウンの外側の何かがクリックされた場合にドロップダウンを非表示にするドキュメントにクリックイベントをバインドすることですが、ドロップダウンの内側の何かがクリックされた場合は非表示にしないため、「show」イベント(またはスライドダウンなど)ドロップダウンを表示します)

    $('.form_wrapper').show(function(){

        $(document).bind('click', function (e) {
            var clicked = $(e.target);
            if (!clicked.parents().hasClass("class-of-dropdown-container")) {
                 $('.form_wrapper').hide();
            }
        });

    });

次に、それを非表示にするときに、クリックイベントのバインドを解除します

$(document).unbind('click');

0

docsよると、タグ.blur()以上に機能します<input>。例えば:

$('.form_wrapper').blur(function(){
   $(this).hide();
});

-1は機能しません。非常に興味深いアイデアですが、jQueryドキュメントは間違っています。たとえば、developer.mozilla.org / en-US / docs / Web / API /…を参照してください。「MSIEとは対照的に、ほとんどすべての種類の要素がぼかしイベントを受信します。ほとんどすべての種類の要素がGeckoブラウザー上にあります。このイベントを処理しないでください。」また、Chromeでテストされており、divぼかしは発生しません。ぼかしイベントは、子供たちから吹き飛ばすことさえできません。最後に、上記が当てはまらない場合でも.form_wrapper、ユーザーがクリックする前にフォーカスがあることを確認した場合にのみ機能します。
マークアメリー2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.