web-dev-qa-db-fra.com

Comment empêcher un événement onclick d'un parent de se déclencher lorsqu'un clic est effectué sur un ancre enfant?

J'utilise actuellement jQuery pour rendre une div cliquable et dans cette div, j'ai aussi des ancres. Le problème que je rencontre est que lorsque je clique sur une ancre, les deux événements de clic se déclenchent (pour la div et l’ancre). Comment puis-je empêcher le déclenchement de l'événement onclick de la div lorsqu'un clic est effectué sur une ancre?

Voici le code cassé:

JavaScript

var url = $("#clickable a").attr("href");

$("#clickable").click(function() {
    window.location = url;
    return true;
})

HTML

<div id="clickable">
    <!-- Other content. -->
    <a href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>
274
Jonathon Watney

Les événements atteignent le point le plus élevé du DOM auquel un événement de clic a été associé. Ainsi, dans votre exemple, même si vous ne disposiez d'aucun autre élément explicitement cliquable dans la div, chaque élément enfant de la div masquera son événement de clic dans le DOM jusqu'à ce que le gestionnaire d'événements de clic du DIV le détecte.

Il y a deux solutions à cela: vérifier qui est à l'origine de l'événement. jQuery passe un objet eventargs avec l'événement:

$("#clickable").click(function(e) {
    var senderElement = e.target;
    // Check if sender is the <div> element e.g.
    // if($(e.target).is("div")) {
    window.location = url;
    return true;
});

Vous pouvez également attacher à vos liens un gestionnaire d’événements clic qui leur dit d’arrêter l’événement bouillonnant après l’exécution de leur propre gestionnaire:

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});
379
Rex M

Utilisez la méthode stopPropagation , voir un exemple:

$("#clickable a").click(function(e) {
   e.stopPropagation();
});

Comme l'a dit jQuery Docs:

La méthode stopPropagation empêche l'événement de remonter dans le DOM arborescence, empêchant les gestionnaires parents d’être avertis de l’événement.

Gardez à l'esprit que cela n'empêche pas empêcher les autres écouteurs de gérer cet événement} (ex. Plus d'un gestionnaire de clic pour un bouton), si ce n'est pas l'effet désiré, vous devez utiliser stopImmediatePropagation à la place.

90
Cleiton

Voici ma solution pour tous ceux qui recherchent un code non-jQuery (javascript pur)

document.getElementById("clickable").addEventListener("click", function( e ){
    e = window.event || e; 
    if(this === e.target) {
        // put your code here
    }
});

Votre code ne sera pas exécuté si vous cliquez sur l'enfant du parent

40
Sabaz

vous pouvez aussi essayer ceci

$("#clickable").click(function(event) {
   var senderElementName = event.target.tagName.toLowerCase();
   if(senderElementName === 'div')
   {
       // do something here 
   } 
   else
   {
      //do something with <a> tag
   }
});
13
Rashad Annara

Si, dans tous les cas, vous n’avez pas l’intention d’interagir avec le ou les éléments internes, une solution CSS peut vous être utile.

Il suffit de définir l'élément interne/s à pointer-events: none

dans ton cas:

.clickable > a {
    pointer-events: none;
}

ou pour cibler tous les éléments internes en général:

.clickable * {
    pointer-events: none;
}

Ce hack facile m'a fait gagner beaucoup de temps en développant avec ReactJS

Le support du navigateur peut être trouvé ici: http://caniuse.com/#feat=pointer-events

10
Hooman Askari

Utiliser return false; ou e.stopPropogation(); ne permettra pas l’exécution de code supplémentaire. Il cessera de couler à ce stade même.

8
Imamudin Naseem

Si vous avez plusieurs éléments dans la div cliquable, procédez comme suit:

$('#clickable *').click(function(e){ e.stopPropagation(); });
7
Ivan Ivković

Écrire si quelqu'un a besoin (a travaillé pour moi):

event.stopImmediatePropagation()

De this solution.

5
Bahadir Tasdemir

Voici un exemple utilisant Angular 2+

Par exemple, si vous souhaitez fermer un composant modal si l'utilisateur clique en dehors de celui-ci:

// Close the modal if the document is clicked.

@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
  this.closeModal();
}

// Don't close the modal if the modal itself is clicked.

@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
  event.stopPropagation();
}
3
Steve Brush

Vous devez empêcher l’événement d’atteindre (communiquer avec) le parent (le div) . Voir la partie consacrée à la création de bulles ici et aux informations d’API spécifiques à jQuery ici .

1
Matt Ball

var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);

function innerFunction(event){
  event.stopPropagation();
  console.log("Inner Functiuon");
}

function outerFunction(event){
  console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
  <div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>

1
Pramod Kharade

ignoreParent () est une solution JavaScript pure.

Il fonctionne comme une couche intermédiaire qui compare les coordonnées du clic de souris avec les coordonnées du ou des éléments enfants. Deux étapes simples de mise en œuvre:

1. Mettez le code ignoreParent () sur votre page.

2. Au lieu de l'original du parent onclick = "parentEvent ();" , écris:

onclick="ignoreParent(['parentEvent()', 'child-ID']);"

Vous pouvez transmettre des identifiants d'un nombre quelconque d'éléments enfants à la fonction et en exclure d'autres.

Si vous avez cliqué sur l'un des éléments enfants, l'événement parent ne se déclenche pas. Si vous avez cliqué sur parent mais sur aucun des éléments enfants [fournis en tant qu'arguments], l'événement parent est déclenché.

Code ignoreParent () sur Github

0
Fom

Alternative en ligne:

<div>
    <!-- Other content. -->
    <a onclick='event.stopPropagation();' href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>
0
Matt Wyeth

Au cas où quelqu'un aurait eu ce problème en utilisant React, voici comment je l'ai résolu.

scss:

#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }

#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }

Le composant du rendu ():

render() {
    ...
    return (
        <div id='loginBackdrop' onClick={this.props.closeLogin}>
            <div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
             ... [modal content] ...
            </div>
        </div>
    )
}

En ajoutant une fonction onClick pour l'enfant modal (content div), les événements de clic de souris sont empêchés d'atteindre la fonction 'closeLogin' de l'élément parent.

Cela a fait l'affaire pour moi et j'ai pu créer un effet modal avec 2 div simples. 

0
Claudio

Pour spécifier un sous-élément non cliquable, écrivez la hiérarchie css comme dans l'exemple ci-dessous.

Dans cet exemple, je stoppe la propagation vers tous les éléments (*) dans td dans tr dans un tableau avec la classe ".subtable"

$(document).ready(function()
{    
   $(".subtable tr td *").click(function (event)
   {
       event.stopPropagation();
   });

});
0
user3202819