2723 votes

Comment détecter un clic à l'extérieur d'un élément ?

J'ai quelques menus HTML, que j'affiche complètement lorsqu'un utilisateur clique sur l'en-tête de ces menus. Je voudrais cacher ces éléments lorsque l'utilisateur clique en dehors de la zone des menus.

Est-ce que quelque chose comme cela est possible avec jQuery ?

$("#menuscontainer").clickOutsideThisElement(function() {
    // Hide the menus
});

47 votes

Voici un exemple de cette stratégie : jsfiddle.net/tedp/aL7Xe/1

21 votes

Comme Tom l'a mentionné, vous voudrez lire css-tricks.com/dangers-stopping-event-propagation avant d'utiliser cette approche. L'outil jsfiddle est cependant assez cool.

3 votes

Obtenir une référence à l'élément puis à event.target, et enfin != ou == les deux, puis exécuter le code en conséquence

19voto

Chu Yeow Points 751

J'ai eu du succès avec quelque chose comme ça :

var $menuscontainer = ...;

$('#trigger').click(function() {
  $menuscontainer.show();

  $('body').click(function(event) {
    var $target = $(event.target);

    if ($target.parents('#menuscontainer').length == 0) {
      $menuscontainer.hide();
    }
  });
});

La logique est la suivante : lorsque #menuscontainer est affiché, liez un gestionnaire de clics au corps qui masque #menuscontainer seulement si la cible (du clic) n'est pas un enfant de celui-ci.

19voto

Jovanni G Points 127

Je suis surpris que personne n'ait reconnu focusout événement :

var button = document.getElementById('button');
button.addEventListener('click', function(e){
  e.target.style.backgroundColor = 'green';
});
button.addEventListener('focusout', function(e){
  e.target.style.backgroundColor = '';
});

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <button id="button">Click</button>
</body>
</html>

17voto

Dan Philip Points 3193

L'événement a une propriété appelée event.path de l'élément qui est un "liste statique ordonnée de tous ses ancêtres dans l'ordre de l'arbre". . Pour vérifier si un événement provient d'un élément DOM spécifique ou de l'un de ses enfants, il suffit de vérifier le chemin de cet élément DOM spécifique. Il peut également être utilisé pour vérifier plusieurs éléments en contrôlant logiquement OR le contrôle de l'élément dans le some fonction.

$("body").click(function() {
  target = document.getElementById("main");
  flag = event.path.some(function(el, i, arr) {
    return (el == target)
  })
  if (flag) {
    console.log("Inside")
  } else {
    console.log("Outside")
  }
});

#main {
  display: inline-block;
  background:yellow;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
  <ul>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
  </ul>
</div>
<div id="main2">
  Outside Main
</div>

Donc, dans votre cas, ce devrait être

$("body").click(function() {
  target = $("#menuscontainer")[0];
  flag = event.path.some(function(el, i, arr) {
    return (el == target)
  });
  if (!flag) {
    // Hide the menus
  }
});

16voto

Bohdan Points 154

En tant que variante :

var $menu = $('#menucontainer');
$(document).on('click', function (e) {

    // If element is opened and click target is outside it, hide it
    if ($menu.is(':visible') && !$menu.is(e.target) && !$menu.has(e.target).length) {
        $menu.hide();
    }
});

Il n'a aucun problème avec arrêt de la propagation des événements et prend mieux en charge les menus multiples sur la même page, où le fait de cliquer sur un deuxième menu alors qu'un premier est ouvert laissera le premier ouvert dans la solution stopPropagation.

14voto

nazar kuliyev Points 79

J'ai trouvé cette méthode dans un plugin de calendrier jQuery.

function ClickOutsideCheck(e)
{
  var el = e.target;
  var popup = $('.popup:visible')[0];
  if (popup==undefined)
    return true;

  while (true){
    if (el == popup ) {
      return true;
    } else if (el == document) {
      $(".popup").hide();
      return false;
    } else {
      el = $(el).parent()[0];
    }
  }
};

$(document).bind('mousedown.popup', ClickOutsideCheck);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X