Sử dụng jQuery để ẩn DIV khi người dùng nhấp vào bên ngoài nó


967

Tôi đang sử dụng mã này:

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

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

HTML này :

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

Vấn đề là tôi có các liên kết bên trong divvà khi chúng không còn hoạt động khi nhấp vào.


6
Sử dụng javascript đơn giản, bạn có thể thử một cái gì đó như thế này: jsfiddle.net/aamir/y7mEY
Aamir Afridi

sử dụng $('html')hoặc $(document)sẽ tốt hơn$('body')
Adrien Be

Câu trả lời:


2484

Có cùng một vấn đề, đã đưa ra giải pháp dễ dàng này. Nó thậm chí còn hoạt động đệ quy:

$(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
Chỉ cần đặt nó trong dự án của tôi, nhưng với một điều chỉnh nhỏ, sử dụng một loạt các yếu tố để lặp qua tất cả chúng cùng một lúc. jsfiddle.net/LCB5W
Thomas

5
@mpelzsherman Nhiều người nhận xét rằng đoạn trích hoạt động trên các thiết bị cảm ứng nhưng vì bài đăng đã được chỉnh sửa nên những bình luận này đã phần nào biến mất. TBH Tôi không biết liệu tôi đã sử dụng "mouseup" vì một lý do cụ thể nhưng nếu nó cũng hoạt động với "nhấp chuột" thì tôi không thấy lý do tại sao bạn không nên sử dụng "nhấp chuột".

6
Tôi cần rằng container được ẩn một lần với sự kiện này, cuộc gọi lại này sẽ bị hủy khi sử dụng. Để làm điều đó, tôi đã sử dụng không gian tên trên sự kiện nhấp bằng liên kết ("click.namespace") và khi sự kiện xảy ra, tôi gọi unbind ("click.namespace"). Và cuối cùng, tôi đã sử dụng $ (e.target) .closest (". Container"). Chiều dài để nhận ra container ... Vì vậy, tôi đã không sử dụng bất kỳ mẹo nào từ câu trả lời này: D
Loenix

80
Nhớ sử dụng $("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );ngay bên cạnh .hide(). Vì vậy, documentđừng tiếp tục lắng nghe nhấp chuột.
brasofilo

12
Đối với các hoạt động tốt nhất tôi đã viết $(document).on("mouseup.hideDocClick", function () { ... });trong hàm mở container và $(document).off('.hideDocClick');trên hàm ẩn. Sử dụng không gian tên Tôi không xóa các trình mouseupnghe có thể khác được đính kèm vào tài liệu.
campsjos 4/2/2015

204

Bạn nên đi với một cái gì đó như thế này:

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

Thật thông minh làm sao! Đây có phải là tiêu chuẩn kỹ thuật?
ủng hộ

@advait Tôi không thấy nó được sử dụng trước đây. Đó là tất cả về hoverxử lý sự kiện, mở ra nhiều khả năng.
Makram Saleh

5
Tôi không coi đây là một giải pháp tốt vì nó cho phép mọi người nghĩ rằng việc cư trú đối tượng cửa sổ (= sử dụng biến toàn cục) là ổn.

1
Chỉ cần thêm một cái gì đó vào những gì @ prc322 đã nói, bạn có thể bọc mã của mình bằng một hàm ẩn danh và gọi nó ngay lập tức. (function() { // ... code })(); Tôi không nhớ tên os mẫu này, nhưng nó siêu hữu ích! Tất cả các biến được khai báo của bạn sẽ nằm trong hàm và sẽ không gây ô nhiễm không gian tên toàn cầu.
pedromanoel

3
@ prc322 Nếu bạn thậm chí không biết cách thay đổi phạm vi của một biến, thì bạn đã đúng, giải pháp này không tốt cho bạn ... và JavaScript cũng không. Nếu bạn chỉ sao chép và dán mã từ Stack Overflow, bạn sẽ gặp nhiều vấn đề hơn là có thể ghi đè lên một cái gì đó trong đối tượng cửa sổ.
Gavin

87

Mã này phát hiện bất kỳ sự kiện nhấp chuột nào trên trang và sau đó ẩn #CONTAINERphần tử khi và chỉ khi phần tử được nhấp không phải là #CONTAINERphần tử cũng không phải là một trong các hậu duệ của nó.

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

Đây là hoàn hảo!!
Mohd Abdul Mujib

@ 9KSoft Tôi rất vui vì nó đã có thể giúp bạn. Cảm ơn bạn đã phản hồi và may mắn nhất.
Trường hợp

Giải pháp này hoạt động hoàn hảo cho tôi bằng cách sử dụng div làm container!
JCO9

76

Bạn có thể muốn kiểm tra mục tiêu của sự kiện nhấp vào cơ thể thay vì dựa vào stopPropagation.

Cái gì đó như:

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

Ngoài ra, phần tử cơ thể có thể không bao gồm toàn bộ không gian hình ảnh được hiển thị trong trình duyệt. Nếu bạn nhận thấy rằng các nhấp chuột của bạn không đăng ký, bạn có thể cần thêm trình xử lý nhấp chuột cho phần tử HTML thay thế.


Đúng, bây giờ các liên kết làm việc! Nhưng vì một số lý do, khi tôi nhấp vào liên kết, nó sẽ kích hoạt nó hai lần.
Scott Yu - xây dựng công cụ

Tôi đã kết thúc bằng cách sử dụng một biến thể của điều này. Trước tiên tôi kiểm tra xem phần tử có hiển thị không sau đó nếu target.hasClass tôi ẩn nó.
Hawkee

và đừng quên e.stopPropagation();nếu bạn có người nghe nhấp chuột khác
Darin Kolev

2
-1. Điều này ẩn form_wrapperkhi bạn nhấp vào một trong những con của nó, đây không phải là hành vi mong muốn. Sử dụng câu trả lời của prc322 thay thế.
Mark Amery

38

Bản thử trực tiếp

Kiểm tra khu vực nhấp không nằm trong thành phần được nhắm mục tiêu hoặc trong đó là con

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

CẬP NHẬT:

jQuery dừng lan truyền là giải pháp tốt nhất

Bản thử trực tiếp

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

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

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

Cảm ơn đã cập nhật, hoàn hảo! Nó hoạt động trên các thiết bị cảm ứng?
FFish

1
Trong trường hợp, bạn có nhiều danh sách thả xuống trên một trang. Tôi nghĩ bạn sẽ cần phải đóng tất cả các danh sách thả xuống trước khi mở clicked. Nếu không, stopPropagationcó thể làm cho nhiều danh sách thả xuống được mở cùng một lúc.
T04435

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

2
Hmmm ... Nếu tôi nhấp vào cái gì đó bên trong div, toàn bộ div biến mất vì một số lý do.
Scott Yu - xây dựng công cụ

11
Thay vì kiểm tra xem mục tiêu có lớp hay không, hãy thử: if ($ (event.target) .closest ('. Form_wrapper) .get (0) == null) {$ (". Form_wrapper"). Hide (); } Điều này sẽ đảm bảo rằng việc nhấp vào những thứ bên trong div sẽ không ẩn div.
John Haager

17

Cập nhật giải pháp cho:

  • sử dụng mouseenter và mouseleave thay thế
  • sử dụng di chuột ràng buộc sự kiện trực tiếp

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
.livebây giờ bị phản đối ; sử dụng .onthay thế.
Brett


9

Bản demo trực tiếp với ESCchức năng

Hoạt động trên cả Desktop và Mobile

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

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

Nếu trong một số trường hợp, bạn cần chắc chắn rằng phần tử của bạn thực sự hiển thị khi bạn nhấp vào tài liệu: if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();


8

Sẽ không có cái gì đó như công việc này?

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

});

hoặc là

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

});

4
Câu trả lời này không đúng. Giống như nhiều câu trả lời ở đây, điều này sẽ ẩn .form_wrapperkhi bạn nhấp vào con của nó (trong số các vấn đề khác).
Mark Amery

6

Ngay cả giày lười:

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

4
Câu trả lời này không đúng. Điều này sẽ ẩn .wrapperbất kể bạn nhấp vào trang nào, đây không phải là điều được yêu cầu.
Đánh dấu Amery

6

Thay vì lắng nghe từng cú nhấp chuột vào DOM để ẩn một yếu tố cụ thể, bạn có thể đặt thành tabindexphụ huynh <div>và lắng nghe các focusoutsự kiện.

Cài đặt tabindexsẽ đảm bảo rằng blursự kiện được kích hoạt trên <div>(thông thường nó sẽ không).

Vì vậy, HTML của bạn sẽ trông như sau:

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

Và JS của bạn:

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

5

Và đối với các thiết bị Touch như IPAD và IPHONE, chúng ta có thể sử dụng mã sau

$(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

Đây là một jsfiddle tôi tìm thấy trên một chủ đề khác, cũng hoạt động với khóa 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()
      }
    })

Tôi thấy nó phát hiện xem sự kiện 'nhấp chuột' có nằm trong phần tử #test không .. đã thử các liên kết tesing như jsfiddle.net/TA96A và có vẻ như chúng có thể hoạt động.
Thomas W

Vâng, có vẻ như các khối jsfiddle bên ngoài các liên kết. Nếu bạn sử dụng http: // jsfiddle.net, bạn sẽ thấy trang kết quả xử lý liên kết :)
djv

5

Được xây dựng từ câu trả lời tuyệt vời của 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);
    }
  });
}

Điều này thêm một vài điều ...

  1. Được đặt trong một hàm với một cuộc gọi lại với các đối số "không giới hạn"
  2. Đã thêm một lệnh gọi đến .off () của jquery được ghép nối với một không gian tên sự kiện để hủy liên kết sự kiện khỏi tài liệu khi nó được chạy.
  3. Bao gồm touchend cho chức năng di động

Tôi hi vọng điêu nay se giup được ai đo!



4

(Chỉ cần thêm vào câu trả lời của prc322.)

Trong trường hợp của tôi, tôi đang sử dụng mã này để ẩn menu điều hướng xuất hiện khi người dùng nhấp vào tab thích hợp. Tôi thấy thật hữu ích khi thêm một điều kiện bổ sung, rằng mục tiêu của nhấp chuột bên ngoài vùng chứa không phải là một liên kết.

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

Điều này là do một số liên kết trên trang web của tôi thêm nội dung mới vào trang. Nếu nội dung mới này được thêm vào cùng lúc với menu điều hướng biến mất, nó có thể gây mất phương hướng cho người dùng.


4

Rất nhiều câu trả lời, phải là một quyền của đoạn văn đã thêm một ... Tôi không thấy câu trả lời hiện tại (jQuery 3.1.1) - vì vậy:

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

plà tên thành phần Trường hợp người ta có thể vượt qua id hoặc lớp hoặc tên thành phần.


3

Trả về false nếu bạn nhấp vào .form_wrapper:

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

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

3

Đính kèm một sự kiện nhấp chuột vào các yếu tố cấp cao nhất bên ngoài trình bao bọc biểu mẫu, ví dụ:

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

Điều này cũng sẽ hoạt động trên các thiết bị cảm ứng, chỉ cần đảm bảo bạn không bao gồm cha mẹ của .form_wrapper trong danh sách các công cụ chọn.


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");  

}); 

VĨ CẦM


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

Sao chép từ https://sdtuts.com/click-on-not-specified-element/

Bản demo trực tiếp 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

tôi đã làm nó như thế này:

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

Bằng cách sử dụng mã này, bạn có thể ẩn bao nhiêu mục bạn muốn

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

Những gì bạn có thể làm là liên kết một sự kiện nhấp chuột vào tài liệu sẽ ẩn danh sách thả xuống nếu một cái gì đó bên ngoài danh sách được nhấp vào, nhưng sẽ không ẩn nó nếu một cái gì đó bên trong danh sách thả xuống, vì vậy sự kiện "hiển thị" của bạn (hoặc trượt hoặc bất cứ điều gì hiển thị thả xuống)

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

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

    });

Sau đó, khi ẩn nó, hủy liên kết sự kiện nhấp

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

0

Theo các tài liệu , .blur()hoạt động nhiều hơn <input>thẻ. Ví dụ:

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

-1, không hoạt động. Ý tưởng rất thú vị, nhưng các tài liệu jQuery đã sai. Ví dụ, xem developer.mozilla.org/en-US/docs/Web/API/ , ví dụ: "Trái ngược với MSIE - trong đó hầu hết tất cả các loại yếu tố đều nhận được sự kiện mờ - gần như tất cả các loại yếu tố trên trình duyệt Gecko KHÔNG làm việc với sự kiện này. " Ngoài ra, đã được thử nghiệm trong Chrome và divkhông bao giờ làm mờ - các sự kiện mờ thậm chí không thể tạo bong bóng cho chúng từ con cái của chúng. Cuối cùng, ngay cả khi những điều trên không đúng, điều này sẽ chỉ hoạt động nếu bạn chắc chắn rằng đó .form_wrapperlà tiêu điểm trước khi người dùng nhấp vào nó.
Đánh dấu Amery
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.