Використовуйте 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
Аамір Афріді

використовуючи $('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
Томас

5
@mpelzsherman Багато людей коментували, що фрагмент працює на сенсорних пристроях, але після редагування публікації ці коментарі дещо зникли. TBH Я не знаю, чи використовував я "мишу" з певної причини, але якщо він також працює з "клацанням", я не бачу причини, чому не слід використовувати "натискання".

6
Мені потрібно, щоб контейнер ховався один раз з цією подією, цей зворотний виклик повинен бути знищений при використанні. Для цього я використав простір імен у події click with bind ("click.namespace"), а коли відбулася подія, я закликаю unbind ("click.namespace"). І нарешті, я використав $ (e.target) .closest (". Контейнер"). Довжина, щоб розпізнати контейнер ... Отже, я не використав жодної хитрості з цієї відповіді: D
Loenix

80
Пам’ятайте, щоб використовувати $("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );просто поруч .hide(). Тому documentне продовжуйте слухати кліки.
brasofilo

12
Для найкращих практик я писав $(document).on("mouseup.hideDocClick", function () { ... });у функції, що відкриває контейнер, і $(document).off('.hideDocClick');у функції приховати. Використовуючи простори імен, я не видаляю інших можливих mouseupслухачів, приєднаних до документа.
Campjos

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

Як розумний! Ця методика є стандартною?
авансування

@advait Я раніше не бачив, як це використовувалося. Вся справа в hoverобробці подій, що відкриває багато можливостей.
Макрам Салех

5
Я не вважаю це гарним рішенням, оскільки воно дозволяє людям думати, що це нормально заповнити вікно-об’єкт (= за допомогою глобальних змінних).

1
Просто щоб додати щось до того, що сказав @ prc322, ви можете зв'язати свій код з анонімною функцією і негайно викликати його. (function() { // ... code })(); Я не пам'ятаю назву цієї картини, але це дуже корисно! Усі заявлені змінні будуть знаходитись у функції та не забруднюватимуть глобальний простір імен.
pedromanoel

3
@ prc322 Якщо ви навіть не знаєте, як змінити область змінної, тоді ви маєте рацію, це рішення для вас не підходить ... і це не JavaScript. Якщо ви просто копіюєте та вставляєте код із переповнення стека, у вас виникне набагато більше проблем, ніж можливо, перезапис чогось у об’єкт вікна.
Гавін

87

Цей код виявляє будь-яку подію клацання на сторінці, а потім приховує #CONTAINERелемент, якщо і лише в тому випадку, якщо натиснутий елемент не був ні #CONTAINERелементом, ні одним з його нащадків.

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

Це ідеально!!
Мохд Абдул Муджіб

@ 9KSoft Я радий, що зміг вам допомогти. Дякую за відгуки та найкращу удачу.
Справа

Це рішення прекрасно працювало для мене, використовуючи div як контейнер!
JCO9

76

Можливо, ви захочете перевірити ціль події клацання, яка спрацьовує для тіла, а не покладатися на stopPropagation.

Щось на зразок:

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

Також елемент тіла може не включати весь візуальний простір, показаний у браузері. Якщо ви помітили, що ваші кліки не реєструються, можливо, вам доведеться замість цього додати обробник кліків для елемента HTML.


Так, зараз посилання працюють! Але чомусь, коли я натискаю посилання, воно запускається двічі.
Скотт Ю - будує речі

Я в кінцевому підсумку використовував варіацію цього. Я спочатку перевіряю, чи елемент видно, потім, якщо target.hasClass я його приховую.
Хокі

і не забувайте, e.stopPropagation();якщо у вас є інший слухач
клацань

2
-1. Це приховує, form_wrapperколи ви клацаєте одного з його дітей, що не є бажаною поведінкою. Використовуйте натомість відповідь prc322.
Марк Амері

38

Live DEMO

Перевірте, чи область клацань не в націленому елементі або в дочірньому

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

ОНОВЛЕННЯ:

Поширення зупинки jQuery - найкраще рішення

Live DEMO

$(".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
Хм-м-м ... Якщо я натиснув щось на ВІДНІВ дива, весь дів чомусь зникає.
Скотт Ю - будує речі

11
Замість того, щоб перевірити, чи є у класу клас, спробуйте: if ($ (event.target) .closest ('. Form_wrapper) .get (0) == null) {$ (". Form_wrapper"). Hid (); } Це дозволить гарантувати, що натискання на речі всередині div не приховає діва.
Джон Хагер

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замість цього.
Бретт

15

Рішення без 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


bindтам не працює. Чи можете ви виправити функцію, щоб вона працювала?
Меммо

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коли ви натискаєте його дітей (серед інших проблем).
Марк Амері

6

Навіть хустку:

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

4
Ця відповідь не правильна. Це дозволить приховати .wrapperнезалежно від того, де ви натискаєте сторінку, а це не те, що просили.
Марк Амері

6

Замість того, щоб прослуховувати кожен натискання кнопки 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();
});

5

А для пристроїв 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();
    }
});

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 і виглядає, що вони можуть працювати.
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. Розміщений у межах функції із зворотним дзвінком з "необмеженими" арг
  2. Додано виклик до jquery's .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назва елемента. Де також можна передати ідентифікатор, або ім’я класу, або елемента.


3

Повернути помилково, якщо натиснути .form_wrapper:

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

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

Що ви можете зробити - прив’язати подію клацання до документа, який буде приховувати спадне меню, якщо щось натиснене, що не знаходиться в спадному меню, але не приховуватиме його, якщо щось натиснене всередині спадного меню натисне, тож ваша подія "показу" (або слайд-хаун або інше) показує спадне меню)

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

Згідно з документами , .blur()працює більше, ніж <input>тег. Наприклад:

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

-1, не працює. Дуже цікава ідея, але документи jQuery помиляються. Наприклад, див. Розробник.mozilla.org/ en-US/docs/Web/API/…: "На відміну від MSIE - в якому майже всі види елементів отримують подію розмиття - майже всі види елементів у веб-переглядачах Gecko НЕ працюйте з цією подією ". Крім того, перевірені в Chrome, і вони divніколи не розмиваються - події розмивання не можуть навіть перекинути їх на дітей. Нарешті, навіть якщо вищезгадане не було правдою, це діятиме лише в тому випадку, якщо ви переконалися, що .form_wrapperфокус був у фокусі, перш ніж користувач натиснув його.
Марк Амері
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.