当用户在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/y7mEY
Aamir Afridi

使用$('html')$(document)会比$('body')
Adrien是

Answers:


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我不知道我是否出于特定原因使用过“ mouseup”,但是如果它也可以与“ click”一起使用,我看不出为什么不应该使用“ click”。

6
我需要用此事件隐藏一次容器,使用时应销毁此回调。为此,我在click事件上使用bind(“ click.namespace”)命名空间,并在事件发生时调用unbind(“ click.namespace”)。最后,我使用$(e.target).closest(“。container”)。length来识别容器...因此,我没有使用此答案的任何技巧:D
Loenix 2014年

80
记住$("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );在旁边使用.hide()。因此document,不要一直在听点击。
brasofilo

12
为了获得最佳实践,我将$(document).on("mouseup.hideDocClick", function () { ... });在打开容器的函数中以及$(document).off('.hideDocClick');在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也不适用。如果您只是从Stack Overflow复制和粘贴代码,那么与覆盖窗口对象中的内容相比,您将面临更多的问题。
加文

87

此代码检测到页面上的任何click事件,然后#CONTAINER仅当被单击的#CONTAINER元素既不是元素也不是其后代之一时,才隐藏元素。

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

太棒了!!
Mohd Abdul Mujib

@ 9KSoft很高兴它能够为您提供帮助。感谢您的反馈和好运。
案例

使用div作为容器,此解决方案对我来说非常理想!
JCO9

76

您可能要检查为主体触发的click事件的目标,而不是依赖stopPropagation。

就像是:

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

同样,主体元素可能不包括浏览器中显示的整个视觉空间。如果您发现点击没有注册,则可能需要为HTML元素添加点击处理程序。


是的,现在链接有效了!但是由于某种原因,当我单击链接时,它会触发两次。
于宇

我最终使用了这种形式。我首先检查该元素是否可见,然后将target.hasClass隐藏。
Hawkee

并且不要忘记e.stopPropagation();您是否还有其他点击监听器
Darin Kolev

2
-1。form_wrapper当您单击其子级之一时,这会隐藏,这不是您期望的行为。请改用prc322的答案。
Mark Amery

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();
});

感谢您的更新,完美!它可以在触摸设备上使用吗?
Fish

1
在这种情况下,页面上会有多个下拉菜单。我认为您需要先关闭所有下拉菜单,然后再打开clicked一个下拉菜单。否则,stopPropagation将有可能同时打开多个下拉菜单。
T04435 '19

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代替。
Brett 2015年


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在您单击其子级时将其隐藏(还有其他问题)。
Mark Amery

6

甚至是运动鞋:

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

4
这个答案是不正确的。.wrapper无论您在页面上的何处单击,这都将隐藏,这不是要求的。
Mark Amery

6

您可以设置tabindex为父级<div>并监听focusout事件,而不是监听DOM来隐藏一个特定元素,而无需每次单击。

设置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()
      }
    })

我看到它检测到'click'事件是否在#test元素内..尝试将链接选为jsfiddle.net/TA96A,看起来它们可能起作用。
Thomas 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. 放在带有“无限” args回调的函数中
  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

这么多的答案,一定是通过的权利,已经添加了一个答案...我没有看到最新的(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

将click事件附加到表单包装器外部的顶级元素,例如:

$('#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");  

}); 

小提琴


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

您可以做的是将click事件绑定到文档,如果单击了下拉菜单中的某些内容,则会隐藏该下拉列表,但是如果单击了下拉菜单中的某些内容,则不会隐藏该下拉列表,因此您的“ show”事件(或slidedown或其他事件)显示下拉菜单)

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

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

    });

然后在隐藏它时,取消绑定click事件

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

0

根据docs,其.blur()作用远超过<input>标记。例如:

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

-1,不起作用。这个想法很有趣,但是jQuery文档是错误的。例如,请参阅developer.mozilla.org/en-US/docs/Web/API/…:“与MSIE相比,MSIE几乎所有类型的元素都接受了模糊事件,而Gecko浏览器中几乎所有类型的元素不适用于此事件。” 而且,在Chrome中进行了测试,并且div永不模糊-模糊事件甚至不会从孩子身上冒出来。最后,即使以上情况都不成立,也只有.form_wrapper在用户单击鼠标框之前确保焦点对准焦点时,此方法才有效。
Mark Amery
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.