jQuery: cliquez sur la fonction exclure les enfants.

144

Essayer de comprendre la fonction jQuery ".not ()" et rencontrer un problème. Je voudrais que le div parent soit "cliquable" mais si un utilisateur clique sur un élément enfant, le script n'est pas appelé.

$(this).not(children()).click(function(){
   $(".example").fadeOut("fast");
});

le html:

<div class="example">
   <div>
      <p>This content is not affected by clicks.</p>
   </div>
</div>
superSans titre
la source

Réponses:

198

Pour ce faire, arrêtez le clic sur l'enfant en utilisant .stopPropagation :

$(".example").click(function(){
  $(this).fadeOut("fast");
}).children().click(function(e) {
  return false;
});

Cela empêchera les clics enfants de dépasser leur niveau afin que le parent ne reçoive pas le clic.

.not() est utilisé un peu différemment, il filtre les éléments de votre sélecteur, par exemple:

<div class="bob" id="myID"></div>
<div class="bob"></div>

$(".bob").not("#myID"); //removes the element with myID

Pour le clic, votre problème est que le clic sur un enfant fait une bulle jusqu'au parent , non pas que vous avez attaché par inadvertance un gestionnaire de clic à l'enfant.

Nick Craver
la source
merci nick, je ne pense pas que ce soit ce que je cherchais. Je suis désolé de ne pas avoir été clair dans ma question. Je veux que le div.example entier se fadeOut, uniquement lorsque l'utilisateur clique sur l'élément parent, pas lorsque l'utilisateur clique sur le div enfant. La raison en est que je voudrais que l'utilisateur puisse cliquer sur le texte du paragraphe et ne pas avoir le texte fadeOut. Si l'utilisateur clique sur le div externe (div parent), tout disparaîtra.
superUntitled
@superUntitled - Merci pour la clarification ... la réponse a été mise à jour pour ce faire, essayez-la.
Nick Craver
18
@Asaf - utilisez à la e.stopPropagation();place de return false;pour ce cas.
Nick Craver
2
Vous pouvez également utiliser }).find('.classes-to-ignore').click(function(e) {pour sélectionner des éléments enfants spécifiques
Paul Mason
5
Je ne comprends pas pourquoi vous lui dites d'utiliser e.stopPropagation()puis d'utiliser à la return falseplace. return falseéquivaut e.preventDefault(); e.stopPropagation()donc à des effets secondaires inattendus.
Steen Schütt
183

J'utilise le balisage suivant et j'ai rencontré le même problème:

<ul class="nav">
    <li><a href="abc.html">abc</a></li>
    <li><a href="def.html">def</a></li>
</ul>

Ici, j'ai utilisé la logique suivante:

$(".nav > li").click(function(e){
    if(e.target != this) return; // only continue if the target itself has been clicked
    // this section only processes if the .nav > li itself is clicked.
    alert("you clicked .nav > li, but not it's children");
});

En termes de question exacte, je peux voir que cela fonctionne comme suit:

$(".example").click(function(e){
   if(e.target != this) return; // only continue if the target itself has been clicked
   $(".example").fadeOut("fast");
});

ou bien sûr l'inverse:

$(".example").click(function(e){
   if(e.target == this){ // only if the target itself has been clicked
       $(".example").fadeOut("fast");
   }
});

J'espère que cela pourra aider.

MatCarey
la source
28
Je pense que c'est la meilleure solution. Il n'interfère en aucun cas avec les enfants et devrait être plus performant car il n'enregistre pas potentiellement des milliers de rappels s'il y a des milliers d'enfants.
LucasB
4
@ l2aelba - vous devriez utiliser .on("click", ...)dans les versions récentes de jQuery car il .live()est obsolète depuis la v1.7. Voir api.jquery.com/live
Chris
Oui, @Chris J'ai posté le 16 novembre 12 à 10:12
l2aelba
Désolé, vous n'avez probablement pas besoin de mentionner votre pièce d'identité. J'ai ajouté le commentaire en grande partie pour quiconque lisant cette réponse.
Chris
1
Cette réponse est meilleure que la réponse acceptée car elle n'interrompt aucun événement de clic sur les éléments enfants
cameronjonesweb
24

Ou vous pouvez faire aussi:

$('.example').on('click', function(e) { 
   if( e.target != this ) 
       return false;

   // ... //
});
dani24
la source
Vous devez renvoyer false pour éviter l'événement click dans les éléments enfants. La révision était erronée
dani24
6

Ma solution:

jQuery('.foo').on('click',function(event){
    if ( !jQuery(event.target).is('.foo *') ) {
        // code goes here
    } 
});
npl len
la source
Similaire à la solution ci-dessus la vôtre.
user460114
3

Personnellement, j'ajouterais un gestionnaire de clics à l'élément enfant qui ne faisait rien d'autre que stopper la propagation du clic. Cela ressemblerait donc à quelque chose comme:

$('.example > div').click(function (e) {
    e.stopPropagation();
});
Noahone
la source
Quelle est la différence entre stopPropagationet renvoyer false comme le suggèrent d'autres réponses?
Crashalot
Je crois que dans ce cas, ils seraient fonctionnels de la même manière, mais je pense que l'arrêt de la propagation est plus clair pour ce qui est fait et laisse une meilleure chance de comprendre pourquoi cela est fait plus tard. Mais c'est discutable.
Noahone
Merci pour la clarification. cela semble stopPropagationêtre plus propre car cela n'empêchera pas les événements sur les éléments enfants de se produire, ce qui peut arriver avec return false.
Crashalot
0

Voici un exemple. Le carré vert est le parent et le carré jaune est l'élément enfant.

J'espère que cela aide.

var childElementClicked;

$("#parentElement").click(function(){

		$("#childElement").click(function(){
		   childElementClicked = true;
		});

		if( childElementClicked != true ) {

			// It is clicked on parent but not on child.
      // Now do some action that you want.
      alert('Clicked on parent');
			
		}else{
      alert('Clicked on child');
    }
    
    childElementClicked = false;
	
});
#parentElement{
width:200px;
height:200px;
background-color:green;
position:relative;
}

#childElement{
margin-top:50px;
margin-left:50px;
width:100px;
height:100px;
background-color:yellow;
position:absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="parentElement">
  <div id="childElement">
  </div>
</div>

Nole
la source