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.

Scott Yu - buduje rzeczy
źródło
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();
    }
});

źródło
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();
    });
});
Makram Saleh
źródło
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();
    }
});
Walizka
źródło
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.

David Andres
źródło
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();
});
MaxEcho
źródło
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();
    }
});
meder omuraliev
źródło
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');
    }
});
Benvds
źródło
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();

Roko C. Buljan
źródło
8

Czy coś takiego nie zadziałałoby?

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

});

lub

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

});
MRVDOG
źródło
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();
});
Olivenbaum
źródło
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();
});
Oscar
źródło
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();
    }
});
Code Spy
źródło
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()
      }
    })
djv
źródło
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!

WiseOlMan
źródło
4

jeśli masz problemy z iOS, mouseup nie działa na urządzeniu Apple.

czy mousedown / mouseup w jquery działa na iPadzie?

używam tego:

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

          if (container.has(e.target).length === 0)
          {
              container.hide();
          }
      });
użytkownik2271066
źródło
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.

shngrdnr
źródło
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();
    });
});
zak
źródło
3
var n = 0;
$("#container").mouseenter(function() {
n = 0;

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

$("html").click(function(){ 
if (n == 1) {
alert("clickoutside");
}
});
Gary
źródło
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.

Abhishek
źródło
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();
//});
bogo
źródło
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.

ThornberryPie
źródło
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

SharmaPattar
źródło
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>

RustBeard
źródło
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");
        }
    })
})
użytkownik3151197
źródło
2

zrobiłem to tak:

var close = true;

$(function () {

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

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


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

});
użytkownik 2822517
źródło
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);
    }
});
Abed Yaseen
źródło
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';
    }
   }
})
Mahdi Younesi
źródło
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');
jeffsaracco
źródło
0

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

$('.form_wrapper').blur(function(){
   $(this).hide();
});
Bizley
źródło
-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