Utilisez jQuery pour masquer un DIV lorsque l'utilisateur clique en dehors de celui-ci


968

J'utilise ce code:

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

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

Et ce HTML :

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

Le problème est que j'ai des liens à l'intérieur du divet quand ils ne fonctionnent plus lorsqu'ils sont cliqués.


6
En utilisant du javascript simple, vous pouvez essayer quelque chose comme ceci: jsfiddle.net/aamir/y7mEY
Aamir Afridi

en utilisant $('html')ou $(document)serait mieux que$('body')
Adrien Be

Réponses:


2485

Eu le même problème, est venu avec cette solution facile. Cela fonctionne même récursivement:

$(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
Mettez-le simplement dans mon projet, mais avec un ajustement mineur, en utilisant un tableau d'éléments pour les parcourir tous en même temps. jsfiddle.net/LCB5W
Thomas

5
@mpelzsherman De nombreuses personnes ont indiqué que l'extrait de code fonctionne sur les appareils tactiles, mais depuis la publication du message, ces commentaires ont quelque peu disparu. TBH Je ne sais pas si j'ai utilisé "mouseup" pour une raison spécifique mais si cela fonctionne aussi avec "click", je ne vois aucune raison pour laquelle vous ne devriez pas utiliser "click".

6
J'avais besoin que le conteneur soit caché une fois avec cet événement, ce rappel devrait être détruit lorsqu'il est utilisé. Pour ce faire, j'ai utilisé un espace de noms sur l'événement click avec bind ("click.namespace") et lorsque l'événement s'est produit, j'appelle unbind ("click.namespace"). Et enfin, j'ai utilisé $ (e.target) .closest (". Container"). Length pour reconnaître le conteneur ... Donc, je n'ai utilisé aucune astuce de cette réponse: D
Loenix

80
N'oubliez pas d'utiliser $("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument );juste à côté .hide(). Alors documentne continuez pas à écouter les clics.
brasofilo

12
Pour les meilleures pratiques, j'avais écrit $(document).on("mouseup.hideDocClick", function () { ... });dans la fonction qui ouvre le conteneur et $(document).off('.hideDocClick');sur la fonction de masquage. En utilisant des espaces de noms, je ne supprime pas les autres mouseupécouteurs possibles attachés au document.
campsjos

204

Vous feriez mieux d'aller avec quelque chose comme ça:

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

Que c'est intelligent! Cette technique est-elle standard?
advait

@advait je ne l'ai pas vu utilisé auparavant. Tout tourne autour du hovergestionnaire d'événements, ce qui ouvre de nombreuses possibilités.
Makram Saleh

5
Je ne considère pas cela comme une bonne solution car cela laisse les gens penser qu'il est correct de remplir l'objet window (= en utilisant des variables globales).

1
Juste pour ajouter quelque chose à ce que @ prc322 a dit, vous pouvez encapsuler votre code avec une fonction anonyme et le faire appeler immédiatement. (function() { // ... code })(); Je ne me souviens pas du nom de ce modèle, mais c'est super utile! Toutes vos variables déclarées résideront à l'intérieur de la fonction et ne pollueront pas l'espace de noms global.
pedromanoel

3
@ prc322 Si vous ne savez même pas comment changer la portée d'une variable, alors vous avez raison, cette solution n'est pas bonne pour vous ... et JavaScript non plus. Si vous copiez et collez simplement du code à partir de Stack Overflow, vous allez avoir beaucoup plus de problèmes que d'écraser éventuellement quelque chose dans l'objet fenêtre.
Gavin

87

Ce code détecte tout événement de clic sur la page, puis masque l' #CONTAINERélément si et seulement si l'élément cliqué n'était ni l' #CONTAINERélément ni l'un de ses descendants.

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

C'est parfait!!
Mohd Abdul Mujib

@ 9KSoft Je suis content qu'il ait pu vous aider. Merci pour vos commentaires et bonne chance.
Affaire

Cette solution a parfaitement fonctionné pour moi en utilisant un div comme conteneur!
JCO9

76

Vous souhaiterez peut-être vérifier la cible de l'événement de clic qui se déclenche pour le corps au lieu de compter sur stopPropagation.

Quelque chose comme:

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

De plus, l'élément body peut ne pas inclure tout l'espace visuel affiché dans le navigateur. Si vous remarquez que vos clics ne sont pas enregistrés, vous devrez peut-être ajouter à la place le gestionnaire de clics pour l'élément HTML.


Oui, maintenant les liens fonctionnent! Mais pour une raison quelconque, lorsque je clique sur le lien, il le déclenche deux fois.
Scott Yu - construit des trucs le

J'ai fini par utiliser une variante de cela. Je vérifie d'abord si l'élément est visible puis si le target.hasClass je le cache.
Hawkee

et n'oubliez pas e.stopPropagation();si vous avez un autre auditeur de clics
Darin Kolev

2
-1. Cela masque le form_wrapperlorsque vous cliquez sur l'un de ses enfants, ce qui n'est pas le comportement souhaité. Utilisez plutôt la réponse de prc322.
Mark Amery

38

DÉMO en direct

Vérifier que la zone de clic n'est pas dans l'élément ciblé ou dans son enfant

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

MISE À JOUR:

jQuery stop propagation est la meilleure solution

DÉMO en direct

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

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

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

Merci pour la mise à jour, parfait! Cela fonctionne-t-il sur les appareils tactiles?
FFish

1
Dans le cas, vous avez plusieurs listes déroulantes sur une page. Je pense que vous devrez fermer toutes les listes déroulantes avant d'ouvrir celle- clickedci. Sinon, stopPropagationcela rendrait possible l'ouverture simultanée de plusieurs listes déroulantes.
T04435

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

2
Hmmm ... Si je clique sur quelque chose À L'INTÉRIEUR du div, le div entier disparaît pour une raison quelconque.
Scott Yu - construit des trucs le

11
Au lieu de vérifier si la cible a la classe, essayez: if ($ (event.target) .closest ('. Form_wrapper) .get (0) == null) {$ (". Form_wrapper"). Hide (); } Cela garantira que cliquer sur des éléments à l'intérieur du div ne masquera pas le div.
John Haager

17

Mise à jour de la solution pour:

  • utilisez plutôt mouseenter et mouseleave
  • de survoler utiliser la liaison d'événements en direct

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
.liveest désormais obsolète ; utiliser à la .onplace.
Brett


9

Démo en direct avec ESCfonctionnalité

Fonctionne à la fois sur ordinateur et sur mobile

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

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

Si dans certains cas, vous devez être sûr que votre élément est vraiment visible lorsque vous cliquez sur le document: if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();


8

Est-ce que quelque chose comme ça ne marcherait pas?

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

});

ou

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

});

4
Cette réponse n'est pas correcte. Comme beaucoup de réponses ici, cela masquera le .form_wrapperlorsque vous cliquez sur ses enfants (entre autres problèmes).
Mark Amery

6

Encore plus léger:

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

4
Cette réponse n'est pas correcte. Cela masquera le .wrappern'importe où vous cliquez sur la page, ce qui n'est pas ce qui a été demandé.
Mark Amery

6

Au lieu d'écouter chaque clic sur le DOM pour masquer un élément spécifique, vous pouvez définir tabindexle parent <div>et écouter les focusoutévénements.

Le réglage tabindexs'assurera que l' blurévénement est déclenché sur le <div>(normalement il ne le ferait pas).

Ainsi, votre HTML ressemblerait à:

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

Et votre JS:

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

5

Et pour les appareils tactiles comme IPAD et IPHONE, nous pouvons utiliser le code suivant

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

Voici un jsfiddle que j'ai trouvé sur un autre fil, fonctionne également avec la touche 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()
      }
    })

Je vois qu'il détecte si l'événement «click» se trouve dans l'élément #test .. a essayé les liens comme jsfiddle.net/TA96A et semble fonctionner.
Thomas W

Oui, il semble que jsfiddle bloque les liens externes. Si vous utilisez http: // jsfiddle.net, vous verrez que la page de résultats traite le lien :)
djv

5

Construit à partir de la réponse impressionnante de 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);
    }
  });
}

Cela ajoute quelques éléments ...

  1. Placé dans une fonction avec un rappel avec des arguments "illimités"
  2. Ajout d'un appel à .off () de jquery associé à un espace de noms d'événement pour dissocier l'événement du document une fois qu'il a été exécuté.
  3. Touchend inclus pour la fonctionnalité mobile

J'espère que ça aidera quelqu'un!



4

(Ajout juste à la réponse de prc322.)

Dans mon cas, j'utilise ce code pour masquer un menu de navigation qui apparaît lorsque l'utilisateur clique sur un onglet approprié. J'ai trouvé utile d'ajouter une condition supplémentaire, à savoir que la cible du clic en dehors du conteneur n'est pas un lien.

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

En effet, certains des liens de mon site ajoutent du nouveau contenu à la page. Si ce nouveau contenu est ajouté en même temps que le menu de navigation disparaît, il peut être désorientant pour l'utilisateur.


4

Tant de réponses, doit être un droit de passage pour en avoir ajouté une ... Je n'ai pas vu de réponses actuelles (jQuery 3.1.1) - donc:

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

pest le nom de l'élément. Où l'on peut également passer l'id ou le nom de classe ou d'élément.


3

Renvoyez false si vous cliquez sur .form_wrapper:

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

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

3

Attachez un événement de clic aux éléments de niveau supérieur en dehors de l'encapsuleur de formulaire, par exemple:

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

Cela fonctionnera également sur les appareils tactiles, assurez-vous simplement de ne pas inclure un parent de .form_wrapper dans votre liste de sélecteurs.


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

}); 

VIOLON


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

Copié de https://sdtuts.com/click-on-not-specified-element/

Démo en direct 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

je l'ai fait comme ça:

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

En utilisant ce code, vous pouvez masquer autant d'éléments que vous le souhaitez

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

Ce que vous pouvez faire est de lier un événement de clic au document qui masquera la liste déroulante si quelque chose en dehors de la liste déroulante est cliqué, mais ne le masquera pas si quelque chose à l'intérieur de la liste déroulante est cliqué, donc votre événement "show" (ou glissé ou autre) montre la liste déroulante)

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

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

    });

Ensuite, lorsque vous le cachez, dissociez l'événement de clic

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

0

Selon les documents , .blur()fonctionne plus que la <input>balise. Par exemple:

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

-1, ne fonctionne pas. Idée très intéressante, mais les documents jQuery sont erronés. Voir developer.mozilla.org/en-US/docs/Web/API/… , par exemple: "Contrairement à MSIE - dans lequel presque toutes sortes d'éléments reçoivent l'événement flou - presque toutes sortes d'éléments sur les navigateurs Gecko ne fonctionne PAS avec cet événement. " En outre, testé dans Chrome, et divs jamais flou - les événements de flou ne peuvent même pas leur venir de leurs enfants. Enfin, même si ce qui précède n'était pas vrai, cela ne fonctionnerait que si vous vous assuriez que le .form_wrapperétait au point avant que l'utilisateur ne clique dessus.
Mark Amery
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.