Используйте jQuery, чтобы скрыть DIV, когда пользователь нажимает за его пределами

794

Я использую этот код:

$('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
  • 0
    использование $('html') или $(document) было бы лучше, чем $('body')
Теги:
styling
hide

33 ответа

2045
Лучший ответ

У той же проблемы возникло это простое решение. Он даже работает рекурсивным:

$(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();
    }
});
  • 15
    Просто поместите это в мой проект, но с незначительной корректировкой, используя массив элементов, чтобы пройти через них все сразу. jsfiddle.net/LCB5W
  • 3
    2 вопроса: 1) это работает с сенсорными устройствами? и 2) есть ли причина использовать mouseup против click?
Показать ещё 28 комментариев
193

Вам лучше пойти с чем-то вроде этого:

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();
    });
});
  • 0
    Как умно! Эта техника стандартная?
  • 0
    @advait Я не видел его раньше. Все дело в обработчике событий при hover , который открывает множество возможностей.
Показать ещё 8 комментариев
58

Возможно, вы захотите проверить цель события клика, который срабатывает для тела, вместо того, чтобы полагаться на stopPropagation.

Что-то вроде:

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

Кроме того, элемент body может не включать все видимое пространство, отображаемое в браузере. Если вы заметили, что ваши клики не регистрируются, вам может потребоваться добавить обработчик кликов для HTML-элемента.

  • 0
    Да, теперь ссылки работают! Но по какой-то причине, когда я нажимаю на ссылку, она запускается дважды.
  • 0
    Я закончил тем, что использовал вариант этого. Сначала я проверяю, видим ли элемент, затем, если target.hasClass, я его скрываю.
Показать ещё 2 комментария
55

Этот код обнаруживает любое событие клика на странице, а затем скрывает элемент #CONTAINER тогда и только тогда, когда элемент, нажатый, не был ни элементом #CONTAINER, ни одним из его потомков.

$(document).on('click', function (e) {
    if ($(e.target).closest("#CONTAINER").length === 0) {
        $("#CONTAINER").hide();
    }
});
  • 0
    Это потрясающе!!
  • 0
    @ 9KSoft Я рад, что смог вам помочь. Спасибо за ваш отзыв и удачи.
Показать ещё 1 комментарий
17

Live DEMO

Проверить область клика не в целевом элементе или в нем дочерний

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

UPDATE:

jQuery прекращение распространения - лучшее решение

Live DEMO

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

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

$(document).click(function(){
    $(".dropdown").hide();
});
  • 0
    Спасибо за обновление, отлично! Работает ли на сенсорных устройствах?
17
$(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.
15

Обновлено решение:

  • используйте 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

Решение без jQuery для самого популярного ответа:

document.addEventListener('mouseup', function (e) {
    var container = document.getElementById('your container ID');

    if (!container.contains(e.target)) {
        container.style.display = 'none';
    }
}.bind(this));

MDN: https://developer.mozilla.org/en/docs/Web/API/Node/contains

7

Живая демонстрация с 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();

6

Не было бы такого, как эта работа?

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

});

или

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

});
  • 4
    У него есть и обратная сторона: производительность.
  • 4
    Этот ответ не верен. Как и многие ответы здесь, это будет скрывать .form_wrapper когда вы щелкаете по его .form_wrapper (среди других проблем).
4

Построен для превосходного ответа 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);
    }
  });
}

Это добавляет пару вещей...

  • Размещается внутри функции с обратным вызовом с "неограниченными" аргументами
  • Добавлен вызов jquery.off() в паре с пространством имен событий, чтобы отменить событие из документа после его запуска.
  • Включено касание для мобильных функций.

Надеюсь, это поможет кому-то!

4

Здесь 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()
      }
    })
  • 0
    Я вижу, что он определяет, находится ли событие click в элементе #test ... пробовал проверять ссылки как jsfiddle.net/TA96A и похоже, что они могут работать.
  • 0
    Да, похоже, что jsfiddle блокирует внешние ссылки. Если вы используете http: // jsfiddle.net, вы увидите, что страница результатов обрабатывает ссылку :)
4

Даже омыватель:

$("html").click(function(){ 
    $(".wrapper:visible").hide();
});
  • 3
    Этот ответ не верен. Это будет скрывать .wrapper независимо от того, где вы нажимаете на страницу, а это не то, о чем просили.
3

А для устройств Touch, таких как 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();
    }
});
2

Вместо того, чтобы прослушивать каждый щелчок по DOM, чтобы скрыть один конкретный элемент, вы можете установить 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();
});
2

Возвращает false, если вы нажмете на .form_wrapper:

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

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

p - это имя элемента. Там, где можно передать идентификатор или имя класса или элемента.

2

Если у вас проблемы с ios, mouseup не работает на яблочном устройстве.

делает mousedown/mouseup в jquery для ipad?

i использую это:

$(document).bind('touchend', function(e) {
        var container = $("YOURCONTAINER");

          if (container.has(e.target).length === 0)
          {
              container.hide();
          }
      });
2
var n = 0;
$("#container").mouseenter(function() {
n = 0;

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

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

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

Используя этот код, вы можете скрыть столько элементов, сколько хотите

var boxArray = ["first element id","second element id","nth element 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

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

1

(Просто добавьте ответ 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();
    }
});

Это связано с тем, что некоторые ссылки на моем сайте добавляют новый контент на страницу. Если этот новый контент добавляется одновременно с исчезновением меню навигации, он может быть дезориентирован для пользователя.

1

Мне хотелось понравиться самому проголосовавшему за предложение, но это не сработало для меня.

Этот метод почти такой же, но работал у меня. http://www.codesynthesis.co.uk/code-snippets/use-jquery-to-hide-a-div-when-the-user-clicks-outside-of-it

1
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js">
</script>
<script>
$(document).ready(function(){
  $("#hide").click(function(){
    $("p").hide();
  });
  $("#show").click(function(){
    $("p").show();
  });
});
</script>
</head>
<body>
<p>If you click on the "Hide" button, I will disappear.</p>
<button id="hide">Hide</button>
<button id="show">Show</button>
</body>
</html>
1

Прикрепите элемент click к элементам верхнего уровня вне оболочки формы, например:

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

Это также будет работать на сенсорных устройствах, просто убедитесь, что вы не включили родительский элемент .form_wrapper в свой список селекторов.

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

я сделал это так:

var close = true;

$(function () {

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

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


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

});
0

Переключение для обычных и сенсорных устройств

Я прочитал несколько ответов здесь некоторое время назад и создал некоторый код, который я использую для div, который функционирует как всплывающие пузырьки.

$('#openPopupBubble').click(function(){
    $('#popupBubble').toggle();

    if($('#popupBubble').css('display') === 'block'){
        $(document).bind('mousedown touchstart', function(e){
            if($('#openPopupBubble').is(e.target) || $('#openPopupBubble').find('*').is(e.target)){
                $(this).unbind(e);
            } 
            else if(!$('#popupBubble').find('*').is(e.target)){
                $('#popupBubble').hide();
                $(this).unbind(e);
            }
        });
    }
});

Вы также можете сделать это более абстрактным с помощью классов и выбрать правильный всплывающий пузырь на основе кнопки, которая вызвала событие click.

$('body').on('click', '.openPopupBubble', function(){
    $(this).next('.popupBubble').toggle();

    if($(this).next('.popupBubble').css('display') === 'block'){
        $(document).bind('mousedown touchstart', function(e){
            if($(this).is(e.target) || $(this).find('*').is(e.target)){
                $(this).unbind(e);
            } 
            else if(!$(this).next('.popupBubble').find('*').is(e.target)){
                $(this).next('.popupBubble').hide();
                $(this).unbind(e);
            }
        });
    }
});
0

Что вы можете сделать, это привязать событие клика к документу, которое скроет раскрывающийся список, если щелкнуть что-либо за пределами выпадающего списка, но не скроет его, если щелкнуто что-то внутри выпадающего списка, поэтому ваше событие "показать" (или 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

В соответствии с документами .blur() работает больше, чем тег <input>. Например:

$('.form_wrapper').blur(function(){
   $(this).hide();
});
  • 1
    Не работает на меня
  • 0
    -1, не работает. Очень интересная идея, но документы JQuery неверны. См. Например, developer.mozilla.org/en-US/docs/Web/API/… «В отличие от MSIE, в которой почти все виды элементов получают событие размытия, - почти все виды элементов в браузерах Gecko НЕ работать с этим событием. " Кроме того, проверено в Chrome, и div никогда не размываются - события размытия не могут даже пузыриться от их детей. Наконец, даже если вышеупомянутое не соответствует действительности, это будет работать, только если вы убедитесь, что .form_wrapper был в фокусе, прежде чем пользователь щелкнул его.
-1
$(document).ready(function() {

$('.headings').click(function () {$('#sub1').css("display",""); });
$('.headings').click(function () {return false;});
$('#sub1').click(function () {return false;});
$('body').click(function () {$('#sub1').css("display","none");

})});
  • 2
    Пожалуйста, добавьте некоторые детали вашего ответа, например, что вы сделали.
-4

Я думаю, что это может быть намного проще. Я сделал это так:

$(':not(.form_wrapper)').click(function() {
    $('.form_wrapper').hide();
});
  • 1
    Я бы избежал этого, вы собираетесь добавить обработчики событий щелчка для каждого элемента в вашем документе, кроме .form_wrapper.
  • 0
    @ JayD3e Кроме того, при .form_wrapper элемента внутри него будет .form_wrapper .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню