Verwenden Sie jQuery, um einen DIV auszublenden, wenn der Benutzer außerhalb des DIV klickt

967

Ich benutze diesen Code:

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

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

Und dieser HTML :

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

Das Problem ist, dass ich Links innerhalb der habe divund wenn sie beim Klicken nicht mehr funktionieren.

Scott Yu - baut Sachen
quelle
6
Mit einfachem Javascript können Sie so etwas versuchen: jsfiddle.net/aamir/y7mEY
Aamir Afridi
mit $('html')oder $(document)wäre besser als$('body')
Adrien Be

Antworten:

2484

Hatte das gleiche Problem, kam mit dieser einfachen Lösung. Es funktioniert sogar rekursiv:

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

quelle
19
Fügen Sie es einfach in mein Projekt ein, aber mit einer geringfügigen Anpassung, indem Sie eine Reihe von Elementen verwenden, um sie alle gleichzeitig zu durchlaufen. jsfiddle.net/LCB5W
Thomas
5
@mpelzsherman Viele Leute haben kommentiert, dass das Snippet auf Touch-Geräten funktioniert, aber seit der Bearbeitung des Beitrags sind diese Kommentare etwas verschwunden. TBH Ich weiß nicht, ob ich "mouseup" aus einem bestimmten Grund verwendet habe, aber wenn es auch mit "click" funktioniert, sehe ich keinen Grund, warum Sie "click" nicht verwenden sollten.
6
Ich brauchte, dass der Container bei diesem Ereignis einmal ausgeblendet wird. Dieser Rückruf sollte bei Verwendung zerstört werden. Dazu habe ich den Namespace beim Klickereignis mit bind ("click.namespace") verwendet, und als das Ereignis auftrat, habe ich unbind ("click.namespace") aufgerufen. Und schließlich habe ich $ (e.target) .closest (". Container"). Length verwendet, um den Container zu erkennen ... Also habe ich keinen Trick aus dieser Antwort verwendet: D
Loenix
80
Denken Sie daran, $("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );nur neben zu verwenden .hide(). So documenthalten Sie nicht für Klicks zu hören.
Brasofilo
12
Für Best Practices habe ich $(document).on("mouseup.hideDocClick", function () { ... });in der Funktion, die den Container öffnet, und in der Funktion $(document).off('.hideDocClick');zum Ausblenden geschrieben. Verwenden von Namespaces Ich entferne keine anderen möglichen mouseupListener, die an das Dokument angehängt sind.
Campsjos
204

Du solltest besser so etwas machen:

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
quelle
Wie schlau! Ist diese Technik Standard?
Advait
@advait Ich habe es vorher nicht benutzt gesehen. Es geht um den hoverEvent-Handler, der viele Möglichkeiten eröffnet.
Makram Saleh
5
Ich halte dies nicht für eine gute Lösung, da die Leute denken, es sei in Ordnung, das Fensterobjekt zu füllen (= globale Variablen verwenden).
1
Um etwas zu dem hinzuzufügen, was @ prc322 gesagt hat, können Sie Ihren Code mit einer anonymen Funktion umschließen und sofort aufrufen lassen. (function() { // ... code })(); Ich erinnere mich nicht an den Namen dieses Musters, aber es ist super nützlich! Alle Ihre deklarierten Variablen befinden sich in der Funktion und verschmutzen den globalen Namespace nicht.
Pedromanoel
3
@ prc322 Wenn Sie nicht einmal wissen, wie Sie den Gültigkeitsbereich einer Variablen ändern können, haben Sie Recht, diese Lösung ist nicht gut für Sie ... und JavaScript auch nicht. Wenn Sie nur Code aus dem Stapelüberlauf kopieren und einfügen, treten viel mehr Probleme auf, als möglicherweise etwas im Fensterobjekt zu überschreiben.
Gavin
87

Dieser Code erkennt jedes Klickereignis auf der Seite und blendet das #CONTAINERElement nur dann aus, wenn das angeklickte Element weder das #CONTAINERElement noch einer seiner Nachkommen war.

$(document).on('click', function (e) {
    if ($(e.target).closest("#CONTAINER").length === 0) {
        $("#CONTAINER").hide();
    }
});
Fall
quelle
Dies ist perfekt!!
Mohd Abdul Mujib
@ 9KSoft Ich bin froh, dass es Ihnen helfen konnte. Vielen Dank für Ihr Feedback und viel Glück.
Fall
Diese Lösung funktionierte perfekt für mich mit einem Div als Container!
JCO9
76

Möglicherweise möchten Sie das Ziel des Klickereignisses überprüfen, das für den Body ausgelöst wird, anstatt sich auf stopPropagation zu verlassen.

Etwas wie:

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

Außerdem enthält das Körperelement möglicherweise nicht den gesamten visuellen Bereich, der im Browser angezeigt wird. Wenn Sie feststellen, dass Ihre Klicks nicht registriert werden, müssen Sie möglicherweise stattdessen den Klick-Handler für das HTML-Element hinzufügen.

David Andres
quelle
Ja, jetzt funktionieren die Links! Aber wenn ich auf den Link klicke, wird er aus irgendeinem Grund zweimal ausgelöst.
Scott Yu - baut Sachen
Am Ende habe ich eine Variation davon verwendet. Ich überprüfe zuerst, ob das Element sichtbar ist, und dann, ob die target.hasClass ich es verstecke.
Hawkee
und vergessen e.stopPropagation();Sie nicht, wenn Sie andere Klick-Listener haben
Darin Kolev
2
-1. Dies verbirgt das, form_wrapperwenn Sie auf eines seiner untergeordneten Elemente klicken, was nicht das gewünschte Verhalten ist. Verwenden Sie stattdessen die Antwort von prc322.
Mark Amery
38

Live DEMO

Überprüfen Sie, ob sich der Klickbereich nicht im Zielelement oder in seinem untergeordneten Element befindet

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

AKTUALISIEREN:

jQuery Stop Propagation ist die beste Lösung

Live DEMO

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

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

$(document).click(function(){
    $(".dropdown").hide();
});
MaxEcho
quelle
Danke für das Update, perfekt! Funktioniert es auf Touch-Geräten?
FFish
1
In diesem Fall haben Sie mehrere Dropdowns auf einer Seite. Ich denke, Sie müssen alle Dropdowns schließen, bevor Sie die öffnen clicked. Andernfalls stopPropagationwürde es möglich sein, dass mehrere Dropdowns gleichzeitig geöffnet sind.
T04435
19
$(document).click(function(event) {
    if ( !$(event.target).hasClass('form_wrapper')) {
         $(".form_wrapper").hide();
    }
});
meder omuraliev
quelle
2
Hmmm ... Wenn ich auf etwas INNERHALB des Div klicke, verschwindet das gesamte Div aus irgendeinem Grund.
Scott Yu - baut Sachen
11
Anstatt zu überprüfen, ob das Ziel die Klasse hat, versuchen Sie: if ($ (event.target) .closest ('. Form_wrapper) .get (0) == null) {$ (". Form_wrapper"). Hide (); } Dadurch wird sichergestellt, dass durch Klicken auf Elemente innerhalb des Div das Div nicht ausgeblendet wird.
John Haager
17

Die Lösung wurde aktualisiert auf:

  • Verwenden Sie stattdessen Mouseenter und Mouseleave
  • Hover verwenden Live-Event-Bindung

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
quelle
1
.liveist jetzt veraltet ; Verwenden Sie .onstattdessen.
Brett
15

Eine Lösung ohne jQuery für die beliebteste Antwort :

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

Martin Vseticka
quelle
bindda funktioniert nicht Könnten Sie die Funktion korrigieren, damit sie funktioniert?
Memmo
9

Live-Demo mit ESCFunktionalität

Funktioniert sowohl auf dem Desktop als auch auf dem Handy

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

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

Wenn Sie in einigen Fällen sicherstellen müssen, dass Ihr Element wirklich sichtbar ist, wenn Sie auf das Dokument klicken: if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();

Roko C. Buljan
quelle
8

Würde so etwas nicht funktionieren?

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

});

oder

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

});
MRVDOG
quelle
4
Diese Antwort ist nicht korrekt. Wie bei vielen Antworten hier wird dies .form_wrapperbeim Klicken auf die untergeordneten Elemente (unter anderem) ausgeblendet.
Mark Amery
6

Noch schlanker:

$("html").click(function(){ 
    $(".wrapper:visible").hide();
});
Olivenbaum
quelle
4
Diese Antwort ist nicht korrekt. Dadurch wird das .wrapperausgeblendet, egal wo Sie auf die Seite klicken, was nicht gewünscht wurde.
Mark Amery
6

Anstatt jeden einzelnen Klick auf das DOM anzuhören, um ein bestimmtes Element auszublenden, können Sie tabindexdas übergeordnete Element festlegen <div>und die focusoutEreignisse anhören .

Durch die Einstellung tabindexwird sichergestellt, dass das blurEreignis auf dem ausgelöst wird <div>(normalerweise nicht).

Ihr HTML würde also so aussehen:

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

Und dein JS:

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

Und für Touch-Geräte wie IPAD und IPHONE können wir folgenden Code verwenden

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

Hier ist eine jsfiddle, die ich in einem anderen Thread gefunden habe und die auch mit dem Esc-Schlüssel funktioniert: 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
quelle
Ich sehe, dass es erkennt, ob sich das 'click'-Ereignis innerhalb des # test-Elements befindet. Es wurde versucht, Links als jsfiddle.net/TA96A zu testen und es sieht so aus, als ob sie funktionieren könnten.
Thomas W
Ja, es sieht so aus, als ob jsfiddle externe Links blockiert. Wenn Sie http: // jsfiddle.net verwenden, sehen Sie, dass die Ergebnisseite den Link verarbeitet :)
djv
5

Erbaut aus der fantastischen Antwort von 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);
    }
  });
}

Dies fügt ein paar Dinge hinzu ...

  1. Platziert in einer Funktion mit einem Rückruf mit "unbegrenzten" Argumenten
  2. Es wurde ein Aufruf von .off () von jquery in Verbindung mit einem Ereignis-Namespace hinzugefügt, um das Ereignis nach seiner Ausführung vom Dokument zu trennen.
  3. Inklusive Touchend für mobile Funktionen

Ich hoffe das hilft jemandem!

WiseOlMan
quelle
4

Wenn Sie Probleme mit iOS haben, funktioniert mouseup auf einem Apple-Gerät nicht.

funktioniert mousedown / mouseup in jquery für das ipad?

ich benutze das:

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

          if (container.has(e.target).length === 0)
          {
              container.hide();
          }
      });
user2271066
quelle
4

(Nur zur Antwort von prc322 hinzufügen.)

In meinem Fall verwende ich diesen Code, um ein Navigationsmenü auszublenden, das angezeigt wird, wenn der Benutzer auf eine entsprechende Registerkarte klickt. Ich fand es nützlich, eine zusätzliche Bedingung hinzuzufügen, dass das Ziel des Klicks außerhalb des Containers kein Link ist.

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

Dies liegt daran, dass einige der Links auf meiner Website der Seite neuen Inhalt hinzufügen. Wenn dieser neue Inhalt gleichzeitig mit dem Verschwinden des Navigationsmenüs hinzugefügt wird, kann dies für den Benutzer verwirrend sein.

shngrdnr
quelle
4

So viele Antworten müssen ein Durchgangsrecht sein, um eine hinzugefügt zu haben ... Ich habe keine aktuellen (jQuery 3.1.1) Antworten gesehen - also:

$(function() {
    $('body').on('mouseup', function() {
        $('#your-selector').hide();
    });
});
zak
quelle
3
var n = 0;
$("#container").mouseenter(function() {
n = 0;

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

$("html").click(function(){ 
if (n == 1) {
alert("clickoutside");
}
});
Gary
quelle
3
 $('body').click(function(event) {
    if (!$(event.target).is('p'))
    {
        $("#e2ma-menu").hide();
    }
});

pist der Elementname. Wo man auch die ID oder den Klassen- oder Elementnamen übergeben kann.

Abhishek
quelle
3

Geben Sie false zurück, wenn Sie auf .form_wrapper klicken:

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

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

Fügen Sie ein Klickereignis an Elemente der obersten Ebene außerhalb des Formular-Wrappers hinzu, z. B.:

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

Dies funktioniert auch auf Touch-Geräten. Stellen Sie jedoch sicher, dass Sie kein übergeordnetes Element von .form_wrapper in Ihre Auswahlliste aufnehmen.

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

}); 

GEIGE

SharmaPattar
quelle
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
quelle
3

Kopiert von https://sdtuts.com/click-on-not-specified-element/

Live-Demo 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");
        }
    })
})
user3151197
quelle
2

Ich habe es so gemacht:

var close = true;

$(function () {

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

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


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

});
user2822517
quelle
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
quelle
2

Mit diesem Code können Sie so viele Elemente ausblenden, wie Sie möchten

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
quelle
1

Sie können ein Klickereignis an das Dokument binden, das die Dropdown-Liste ausblendet, wenn auf etwas außerhalb der Dropdown-Liste geklickt wird. Es wird jedoch nicht ausgeblendet, wenn auf etwas innerhalb der Dropdown-Liste geklickt wird zeigt das Dropdown)

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

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

    });

Binden Sie dann beim Ausblenden das Klickereignis auf

$(document).unbind('click');
Jeffsaracco
quelle
0

Nach der docs , .blur()arbeitet für mehr als den <input>Tag. Zum Beispiel:

$('.form_wrapper').blur(function(){
   $(this).hide();
});
Bizley
quelle
-1, funktioniert nicht. Sehr interessante Idee, aber die jQuery-Dokumente sind falsch. Siehe developer.mozilla.org/en-US/docs/Web/API/… zum Beispiel: "Im Gegensatz zu MSIE - bei dem fast alle Arten von Elementen das Unschärfeereignis erhalten - fast alle Arten von Elementen in Gecko-Browsern arbeite NICHT mit diesem Ereignis. " Außerdem in Chrome getestet und divnie verwischt - Unschärfeereignisse können nicht einmal von ihren Kindern zu ihnen sprudeln. Selbst wenn das oben Gesagte nicht zutrifft, würde dies nur funktionieren, wenn Sie sicherstellen, dass das .form_wrapperim Fokus ist, bevor der Benutzer darauf klickt.
Mark Amery