63 votes

Détecter un clic à l'intérieur ou à l'extérieur d'un élément avec un seul gestionnaire d'événements

Supposons que j'ai une div sur ma page. comment détecter le clic de l'utilisateur sur le contenu de la div ou à l'extérieur du contenu de la div via JavaScript ou jQuery. s'il vous plaît aider avec un petit extrait de code. merci.

Modifier : Comme indiqué dans l'une des réponses ci-dessous, je veux seulement attacher un gestionnaire d'événements à mon body, et aussi savoir quel élément a été cliqué.

0voto

Simbiat Points 55

J'ai trouvé une approche légèrement différente de la plus votée, bien que le concept soit assez similaire. Je vais utiliser mon code de barres latérales comme exemple. En HTML j'ai des trucs comme ça :

En CSS j'ai ceci :

/*Besoin de réinitialiser le padding, qui est par défaut de 1rem, afin que le contenu du dialog "recouvre" tout l'élément.*/
dialog {
    padding: 0;
}
/*Stylisation de l'élément enfant, dans mon cas j'ai `aside`*/
.sidebar aside {
    /*Cela peut varier, mais le point est de s'assurer que quelque soit l'élément enfant que vous avez, il recouvre complètement la taille de l'élément dialog.*/
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: inherit;
    /*Si vous voulez avoir un espacement autour du contenu du dialog principal réel, utilisez du padding, pas de la marge, car si vous cliquez sur la marge de l'élément, il considérera que vous cliquez sur l'élément "en dessous" de celui-ci, mais le padding sera traité comme faisant partie de l'élément sur lequel vous cliquez. En fait, en fonction de la stylisation ci-dessus ou d'autres éléments enfants, vous pourriez même avoir besoin d'utiliser cela.*/
    padding: 1rem;
}

Ensuite, dans mon code JS j'ai ceci :

//Gérer la fermeture du dialog en cliquant à l'extérieur du contenu du dialog
const dialogs = document.querySelectorAll('dialog');
if (!empty(dialogs)) {
    dialogs.forEach((dialog) => {
        dialogInit(dialog);
    });
}

function dialogInit(dialog)
{
    //Pour mes besoins je vérifie la classe `modal`, mais vous pouvez utiliser n'importe quelle autre classe ou faire cela pour tous les éléments dialog, si vous savez que tous seront modaux
    if (dialog.classList.contains('modal')) {
        dialog.addEventListener('click', (event) => {
            //Si nous avons configuré la stylisation correctement, cliquer "à l'extérieur" du dialog signifie cliquer sur sa marge. Comme il s'agit de la marge, la cible de l'événement est en fait un élément sous l'élément dialog, qui est son arrière-plan, qui est un pseudo-élément, et est donc toujours traité comme le fait de cliquer sur le dialog.
            if (event.target && event.target === dialog) {
                dialog.close();
            }
        });
    }
}

Encore une fois, le concept est pratiquement le même, mais inversé, et je pense que cela peut le rendre un peu plus universel, car vous n'êtes pas limité à quel type d'élément enfant vous avez dans le dialog, tant que vous définissez sa taille correctement.

0voto

Jupally Points 23

La plupart des solutions échouent dans le cas limite, c'est-à-dire lorsque n'importe quel enfant de parentDiv est cliqué et que l'enfant est supprimé du dom en raison de certaines logiques nécessaires, il devrait être traité comme un clickInside mais parentDiv.contains(event.target) sera faux et les solutions utilisant cela le traiteront comme un clic à l'extérieur, donc utiliser composedPath() donnera le comportement attendu :

const parentDiv = document.querySelector('#parentDiv')

document.addEventListener('click', (e) => {
  const isClickedInsideParent = e.composedPath().includes(parentDiv)

  if (isClickedInsideParent) {
    console.log('clic à l'intérieur du parent')
  } else {
    console.log('clic à l'extérieur du parent')
  } 
})

-1voto

Andre Points 928

Au lieu d'utiliser le corps, vous pourriez créer un rideau avec z-index de 100 (pour choisir un nombre) et donner à l'élément intérieur un z-index plus élevé tandis que tous les autres éléments ont un z-index inférieur au rideau.

Voir un exemple fonctionnel ici: http://jsfiddle.net/Flandre/6JvFk/

jQuery:

$('#curtain').on("click", function(e) {

    $(this).hide();
    alert("clic en dehors des éléments qui se démarquent");

});

CSS:

.aboveCurtain
{
    z-index: 200; /* doit avoir un indice supérieur à celui du rideau */
    position: relative;
    background-color: rose;
}

#curtain
{
    position: fixed;
    top: 0px;
    left: 0px;
    height: 100%;
    background-color: noir;
    width: 100%;
    z-index:100;   
    opacity:0.5 /* changer l'opacité à 0 pour obtenir un vrai effet verre */
}

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