Użyj jQuery, aby ukryć DIV, gdy użytkownik kliknie poza nim


967

Używam tego kodu:

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

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

A ten HTML :

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

Problem polega na tym, że mam linki wewnątrz divi kiedy przestają działać po kliknięciu.


6
Za pomocą zwykłego javascript możesz wypróbować coś takiego: jsfiddle.net/aamir/y7mEY
Aamir Afridi

używając $('html')lub $(document)byłoby lepiej niż$('body')
Adrien Be

Odpowiedzi:


2484

Miałem ten sam problem, wymyśliłem to łatwe rozwiązanie. Działa nawet rekurencyjnie:

$(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
Po prostu umieść to w moim projekcie, ale z niewielką korektą, używając szeregu elementów, aby przejść przez nie wszystkie naraz. jsfiddle.net/LCB5W
Thomas

5
@mpelzsherman Wiele osób skomentowało, że fragment działa na urządzeniach dotykowych, ale od czasu edycji postu komentarze te zniknęły. TBH Nie wiem, czy użyłem „mouseup” z konkretnego powodu, ale czy działa on również z „kliknięciem”, nie widzę powodu, dla którego miałbyś nie używać „kliknięcia”.

6
Potrzebowałem ukrycia kontenera jeden raz przy tym zdarzeniu, to wywołanie zwrotne powinno zostać zniszczone, gdy jest używane. Aby to zrobić, użyłem przestrzeni nazw na zdarzeniu kliknięcia z opcją bind („click.namespace”), a kiedy zdarzenie miało miejsce, wywołuję unbind („click.namespace”). I na koniec użyłem $ (e.target) .closest (". Container"). Length do rozpoznania kontenera ... Więc nie
użyłem

80
Pamiętaj, aby użyć $("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );tuż obok .hide(). Więc documentnie słuchaj kliknięć.
brasofilo

12
Dla najlepszych praktyk napisałem $(document).on("mouseup.hideDocClick", function () { ... });w funkcji otwierającej kontener oraz $(document).off('.hideDocClick');w funkcji ukrywania. Używając przestrzeni nazw nie usuwam innych możliwych mouseupnasłuchiwaczy dołączonych do dokumentu.
campsjos

204

Lepiej skorzystaj z czegoś takiego:

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

Jak mądrze! Czy ta technika jest standardowa?
advait

@advait Nie widziałem tego wcześniej. Chodzi o hoverobsługę zdarzeń, która otwiera wiele możliwości.
Makram Saleh,

5
Nie uważam tego za dobre rozwiązanie, ponieważ pozwala ludziom myśleć, że wypełnienie obiektu okna jest w porządku (= używanie zmiennych globalnych).

1
Aby dodać coś do tego, co powiedział @ prc322, możesz owinąć swój kod anonimową funkcją i natychmiast go wywołać. (function() { // ... code })(); Nie pamiętam nazwy tego wzoru, ale jest to bardzo przydatne! Wszystkie zadeklarowane zmienne będą znajdować się wewnątrz funkcji i nie będą zanieczyszczać globalnej przestrzeni nazw.
pedromanoel

3
@ prc322 Jeśli nawet nie wiesz, jak zmienić zakres zmiennej, masz rację, to rozwiązanie nie jest dla ciebie dobre ... i nie jest też JavaScript. Jeśli tylko kopiujesz i wklejasz kod z Przepełnienia stosu, będziesz miał o wiele więcej problemów niż możliwe nadpisanie czegoś w obiekcie okna.
Gavin

87

Ten kod wykrywa każde zdarzenie kliknięcia na stronie, a następnie ukrywa #CONTAINERelement wtedy i tylko wtedy, gdy kliknięty element nie był ani #CONTAINERelementem, ani jednym z jego potomków.

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

To jest doskonałe!!
Mohd Abdul Mujib

@ 9KSoft Cieszę się, że mógł ci pomóc. Dziękujemy za opinie i powodzenia.
Sprawa

To rozwiązanie działało idealnie dla mnie przy użyciu div jako kontenera!
JCO9

76

Możesz chcieć sprawdzić cel zdarzenia kliknięcia, które uruchamia się dla ciała, zamiast polegać na stopPropagation.

Coś jak:

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

Ponadto element body może nie obejmować całej przestrzeni wizualnej pokazanej w przeglądarce. Jeśli zauważysz, że Twoje kliknięcia się nie rejestrują, może być konieczne dodanie modułu obsługi kliknięć dla elementu HTML.


Tak, teraz linki działają! Ale z jakiegoś powodu, kiedy klikam link, uruchamia go dwa razy.
Scott Yu - tworzy rzeczy

Skończyło się na tym wariancie. Najpierw sprawdzam, czy element jest widoczny, a następnie czy cel.hasClass go ukrywam.
Hawkee,

i nie zapomnij, e.stopPropagation();jeśli masz innego słuchacza kliknięć
Darin Kolev

2
-1. Ukrywa to, form_wrapperkiedy klikniesz jedno z jego dzieci, co nie jest pożądanym zachowaniem. Zamiast tego użyj odpowiedzi prc322.
Mark Amery

38

DEMO na żywo

Sprawdź, czy obszar kliknięcia nie znajduje się w elemencie docelowym ani w jego elemencie potomnym

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

AKTUALIZACJA:

jQuery stop propagacja jest najlepszym rozwiązaniem

DEMO na żywo

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

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

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

Dzięki za aktualizację, idealnie! Czy to działa na urządzeniach dotykowych?
FFish,

1
W przypadku masz wiele menu rozwijanych na stronie. Myślę, że będziesz musiał zamknąć wszystkie listy rozwijane przed otwarciem clickedjednego. W przeciwnym razie stopPropagationmożliwe byłoby otwarcie wielu list rozwijanych w tym samym czasie.
T04435

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

2
Hmmm ... Jeśli kliknę na coś WEWNĄTRZ div, cała div zniknie z jakiegoś powodu.
Scott Yu - tworzy rzeczy

11
Zamiast sprawdzać, czy cel ma klasę, spróbuj: if ($ (event.target) .closest ('. Form_wrapper) .get (0) == null) {$ (". Form_wrapper"). Hide (); } Zapewni to, że klikanie elementów wewnątrz div nie ukryje div.
John Haager

17

Zaktualizowałem rozwiązanie do:

  • zamiast tego użyj mouseenter i mouseleave
  • najedź kursorem na powiązanie wydarzenia na żywo

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
.livejest teraz przestarzałe ; użyj .onzamiast tego.
Brett,


9

Demo na żywo z ESCfunkcjonalnością

Działa na komputerach i urządzeniach mobilnych

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

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

Jeśli w niektórych przypadkach musisz upewnić się, że element jest naprawdę widoczny po kliknięciu dokumentu: if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();


8

Czy coś takiego nie zadziałałoby?

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

});

lub

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

});

4
Ta odpowiedź jest nieprawidłowa. Podobnie jak wiele odpowiedzi tutaj, ukryje to, .form_wrapperkiedy klikniesz jego dzieci (wśród innych problemów).
Mark Amery

6

Nawet lepsza:

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

4
Ta odpowiedź jest nieprawidłowa. To ukryje, .wrapperbez względu na to, gdzie klikniesz na stronie, co nie jest wymagane.
Mark Amery

6

Zamiast słuchać każdego kliknięcia DOM, aby ukryć jeden konkretny element, możesz ustawić tabindexelement nadrzędny <div>i słuchaćfocusout zdarzeń.

Ustawienie tabindexupewni się, że blurzdarzenie zostanie uruchomione na<div> (normalnie nie będzie).

Twój HTML mógłby wyglądać następująco:

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

A twój JS:

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

5

W przypadku urządzeń dotykowych, takich jak IPAD i IPHONE, możemy użyć następującego kodu

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

Oto jsfiddle, który znalazłem w innym wątku, działa również z klawiszem 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()
      }
    })

Widzę, że wykrywa, czy zdarzenie „kliknięcie” mieści się w elemencie #test. Próbowałem tesingować linki jako jsfiddle.net/TA96A i wygląda na to, że mogą działać.
Thomas W

Tak, wygląda na to, że jsfiddle blokuje linki zewnętrzne. Jeśli użyjesz http: // jsfiddle.net, zobaczysz, że strona wyników przetwarza link :)
djv

5

Zbudowany z niesamowitej odpowiedzi 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);
    }
  });
}

To dodaje kilka rzeczy ...

  1. Umieszczony w funkcji z wywołaniem zwrotnym z „nielimitowanymi” argumentami
  2. Dodano wywołanie do .off () jquery sparowanego z przestrzenią nazw zdarzeń, aby odłączyć wydarzenie od dokumentu po jego uruchomieniu.
  3. W zestawie touchend dla funkcji mobilnych

Mam nadzieję, że to komuś pomoże!



4

(Tylko dodając do odpowiedzi prc322.)

W moim przypadku używam tego kodu, aby ukryć menu nawigacyjne, które pojawia się, gdy użytkownik kliknie odpowiednią kartę. Zauważyłem, że warto dodać dodatkowy warunek, że celem kliknięcia poza kontenerem nie jest link.

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

Wynika to z faktu, że niektóre linki w mojej witrynie dodają nową treść do strony. Jeśli ta nowa zawartość zostanie dodana w tym samym czasie, gdy zniknie menu nawigacji, może to być dezorientujące dla użytkownika.


4

Tak wiele odpowiedzi musi być prawem do przejścia, aby je dodać ... Nie widziałem aktualnych (jQuery 3.1.1) odpowiedzi - więc:

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

pto nazwa elementu. Gdzie można przekazać także identyfikator, nazwę klasy lub elementu.


3

Zwróć false, jeśli klikniesz .form_wrapper:

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

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

3

Dołącz zdarzenie click do elementów najwyższego poziomu poza opakowaniem formularza, na przykład:

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

Działa to również na urządzeniach dotykowych, upewnij się tylko, że na liście selektorów nie ma elementu nadrzędnego .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");  

}); 

SKRZYPCE


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

Skopiowano z https://sdtuts.com/click-on-not-specified-element/

Demo na żywo 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

zrobiłem to tak:

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

Korzystając z tego kodu, możesz ukryć dowolną liczbę pozycji

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

Możesz powiązać zdarzenie kliknięcia z dokumentem, który ukryje menu rozwijane, jeśli klikniesz coś poza menu rozwijanym, ale nie ukryje go, jeśli klikniesz coś w menu rozwijanym, więc Twoje zdarzenie „pokaż” (lub pokaz slajdów lub cokolwiek innego pokazuje menu rozwijane)

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

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

    });

Następnie, ukrywając to, odznacz zdarzenie kliknięcia

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

0

Zgodnie z docs , .blur()działa dłużej niż <input>tagu. Na przykład:

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

-1, nie działa. Bardzo ciekawy pomysł, ale dokumenty jQuery są błędne. Zobacz na przykład developer.mozilla.org/en-US/docs/Web/API/… , na przykład: „W przeciwieństwie do MSIE - w którym prawie wszystkie rodzaje elementów otrzymują zdarzenie rozmycia - prawie wszystkie rodzaje elementów w przeglądarkach Gecko NIE pracuj z tym wydarzeniem. ” Ponadto przetestowane w Chrome i divnigdy nie rozmazują się - zdarzenia rozmycia nie mogą nawet wywoływać bańki wobec ich dzieci. Wreszcie, nawet jeśli powyższe nie byłyby prawdą, działałoby to tylko wtedy, gdy upewnisz się, że .form_wrapperostrość była ustawiona, zanim użytkownik ją kliknie.
Mark Amery
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.