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é.

141voto

KhalilRavanna Points 821

Voici une ligne qui ne nécessite pas jquery en utilisant Node.contains :

// Obtenir l'élément arbitraire avec l'ID "my-element"
var myElementToCheckIfClicksAreInsideOf = document.querySelector('#my-element');
// Écouter les événements click sur le body
document.body.addEventListener('click', function (event) {
    if (myElementToCheckIfClicksAreInsideOf.contains(event.target)) {
        console.log('clic à l'intérieur');
    } else {
        console.log('clic à l'extérieur');
    }
});

Si vous vous demandez le cas limite de vérifier si le clic est sur l'élément lui-même, Node.contains renvoie true pour l'élément lui-même (par exemple element.contains(element) === true) donc ce code devrait fonctionner à chaque fois.

Le support du navigateur semble couvrir à peu près tout selon cette page MDN également.

98voto

amosrivera Points 11654

Utilisation de jQuery :

$(function() {
  $("body").click(function(e) {
    if (e.target.id == "myDiv" || $(e.target).parents("#myDiv").length) {
      alert("À l'intérieur de la div");
    } else {
      alert("À l'extérieur de la div");
    }
  });
})

#myDiv {
  background: #ff0000;
  width: 25vw;
  height: 25vh;
}

9 votes

Cela ne gérera pas les cas où l'utilisateur clique sur un enfant de la div ; il signalera "hors de la div".

0 votes

Bien. Votre utilisation de parents() m’a inspiré à mettre à jour ma réponse pour utiliser plus de jQuery et moins de parcours à l’ancienne.

1 votes

Cela ne fonctionnera pas s'il y a des éléments en dehors de la div qui utilisent stopPropagation, voir l'exemple ici : jsfiddle.net/Flandre/YdrTA

14voto

Phrogz Points 112337
En utilisant jQuery, et en supposant que vous avez

jQuery(function($){ $('#foo').click(function(e){ console.log( 'cliqué sur la div' ); e.stopPropagation(); // Empêcher la propagation }); $('body').click(function(e){ console.log( 'cliqué en dehors de la div' ); }); });

Éditer : Pour un seul gestionnaire :

jQuery(function($){
  $('body').click(function(e){
    var clickedOn = $(e.target);
    if (clickedOn.parents().andSelf().is('#foo')){
      console.log( "Cliqué sur", clickedOn[0], "à l'intérieur de la div" );
    }else{
      console.log( "Cliqué en dehors de la div" );
  });
});

0 votes

Merci pour vos efforts mais je le veux différemment. Je veux capturer l'identifiant de l'élément où le clic s'est produit et je veux le gérer au niveau du corps sans attacher de gestionnaire d'événement de clic à la division.

0 votes

Si je clique sur #foo, cela déclenche également les gestionnaires du body car foo est à l'intérieur du body

1 votes

@amosrivera Non, ce n'est pas le cas, car l'appel à stopPropagation l'empêche de se propager. Vous pouvez tester cela par vous-même ici: jsfiddle.net/Qh2MN

13voto

RayOnAir Points 734

Au lieu d'utiliser la fonction jQuery .parents (comme suggéré dans la réponse acceptée), il est préférable d'utiliser .closest à cette fin. Comme expliqué dans la documentation de l'api jQuery, .closest vérifie l'élément passé et tous ses parents, tandis que .parents vérifie simplement les parents. En conséquence, ceci fonctionne :

$(function() {
    $("body").click(function(e) {
        if ($(e.target).closest("#myDiv").length) {
            alert("Cliqué à l'intérieur de #myDiv");
        } else { 
            alert("Cliqué à l'extérieur de #myDiv");
        }
    });
})

8voto

buildsucceeded Points 1252

Qu'en est-il de cela?

div {border: 1px solid red; color: black; background-color: #9999DD;
width: 20em; height: 40em;}

function sayLoc(e) {
  e = e || window.event;
  var tgt = e.target || e.srcElement;

  // Obtenir les coordonnées en haut à gauche du div
  var divX = findPosX(tgt);
  var divY = findPosY(tgt);

  // Déterminer si la page a été défilée
  var pXo = getPXoffset();
  var pYo = getPYoffset();

  // Soustraire les coordonnées du div des coordonnées de l'événement
  var clickX = e.clientX - divX + pXo;
  var clickY = e.clientY - divY + pYo;

  alert('Coordonnées à l'intérieur du div (x, y) : ' + clickX + ', ' + clickY);
}

function findPosX(obj) {
  var curleft = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      curleft += obj.offsetLeft;
      obj = obj.offsetParent;
    }
  } else if (obj.x) {
    curleft += obj.x;
  }
  return curleft;
}

function findPosY(obj) {
  var curtop = 0;
  if (obj.offsetParent) {
    while (obj.offsetParent) {
      curtop += obj.offsetTop;
      obj = obj.offsetParent;
    }
  } else if (obj.y) {
    curtop += obj.y;
  }
  return curtop;
}

function getPXoffset() {
  if (self.pageXOffset) {
    // tout sauf Explorer
    return self.pageXOffset;
  } else if (
    document.documentElement &&
    document.documentElement.scrollTop
  ) {
    // Explorer 6 Strict
    return document.documentElement.scrollLeft;
  } else if (document.body) {
    // tous les autres Explorateurs
    return document.body.scrollLeft;
  }
}

function getPYoffset() {
  if (self.pageYOffset) {
    // tout sauf Explorer
    return self.pageYOffset;
  } else if (
    document.documentElement &&
    document.documentElement.scrollTop
  ) {
    // Explorer 6 Strict
    return document.documentElement.scrollTop;
  } else if (document.body) {
    // tous les autres Explorateurs
    return document.body.scrollTop;
  }
}

(de http://bytes.com/topic/javascript/answers/151689-detect-click-inside-div-mozilla, en utilisant le Google.)

4 votes

C'est une quantité insensée de code pour quelque chose qui peut maintenant être réalisé en une seule ligne : stackoverflow.com/a/28432139/288906

1 votes

C'est exactement ce dont j'ai besoin, même la quantité insensée de code.

0 votes

@fregante Ce code détecte précisément "Géométrique à l'intérieur", et non pas "hiérarchiquement à l'intérieur".

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