2009-11-18 4 views
1

J'ai un divdélégation événement click simple ne fonctionne pas

<div class="myDiv"> 
    <a href="#" class="myLink">somelink</a> 
    <div class="anotherDiv">somediv</div> 
</div> 

Maintenant, en utilisant la délégation de l'événement et le concept de bouillonnement, je voudrais intercepter les clics de l'un des myDiv, myLink et anotherDiv.

Selon les meilleures pratiques cela pourrait se faire en écoutant les clics à l'échelle mondiale (d'où le terme « délégation ») sur le document lui-même

$(document).click(function(e) { 
    var $eventElem = $(e.target); 
    var bStopDefaultClickAction = false; 

    if ($eventElem.is('.myDiv')) 
    { 
    alert('Never alerts when clicking on myLink or anotherDiv, why????'); 
    bStopDefaultClickAction = true; 
    } 

    return bStopDefaultClickAction; 
}); 

Voir ma question d'alerte ci-dessus. J'étais sous l'impression que les clics bulle. Et c'est un peu parce que le document reçoit mon clic et commence à déléguer. Mais le mécanisme de bulles pour les clics sur myLink et anotherDiv ne semble pas fonctionner car l'instruction if ne démarre pas.

Ou est-ce comme ceci: les clics ne font qu'un seul mouvement, de l'élément src cliqué à objet de délégation affecté (dans ce cas, le document)? Si tel est le cas, alors je dois gérer la délégation comme ceci:

$('.myDiv').click(function(e) { 
    //...as before 
}); 

Mais ce genre de defeates l'usage de la délégation que je dois maintenant avoir beaucoup de gestionnaires « myDiv » et peut-être d'autres ... il est mort facile d'avoir juste un objet de délégation d'événement 'document'.

Quelqu'un sait comment cela fonctionne?

+0

Je crois que vous devez faire 'var $ eventElem = $ (e.target);' pour pour le contrôle ci-dessous pour travailler. –

+0

Ce n'est pas vraiment une partie du problème car j'ai écrit ceci de mémoire, mais je l'ai édité maintenant. – Tommy

+1

Je pense que votre compréhension est légèrement éteinte. Je pense que vous croyez qu'il devrait invoquer un clic pour chaque élément. Vous n'obtiendrez qu'un seul événement de clic à chaque niveau de hiérarchie dans le dom. Essayez d'ajouter un gestionnaire de clic pour le div mydiv également. Vous verrez cet événement déclenché d'abord, puis le gestionnaire de clic de document, mais la cible est toujours la même. – redsquare

Répondre

0

La cible d'événement ne changera pas. Vous devez refléter ce que fait réellement jquery et vérifier si $ eventElem.closest ('. MyDiv') fournit une correspondance.

Essayez:

$(document).click(function(e) { 
    var $eventElem = $(e.target); 
    var bStopDefaultClickAction = false; 

    if ($eventElem.closest('.myDiv').length) 
    { 
    alert('Never alerts when clicking on myLink or anotherDiv, why????'); 
    bStopDefaultClickAction = true; 
    } 

    return bStopDefaultClickAction; 
}); 
+0

Mais qu'est-ce qui est arrivé à l'événement bouillonnant? Pourquoi chercher myDiv quand le mécanisme de bullage devrait résoudre ce problème? Ou ai-je complètement tort ici? Le pouvoir du bouillonnement est le mécanisme de la délégation d'événement. Sinon, le document n'aurait pas reçu le clic sur myDiv en premier lieu. – Tommy

+0

Eh bien, il n'invoque pas un événement click pour chaque élément parent. Rappelez-vous votre écoute sur l'événement le plus bouillonné. – redsquare

+0

Vous avez raison, merci de faire le tri! – Tommy

2

Vous devez utiliser l'événement en direct de JQuery (depuis 1.3), il utilise la délégation de l'événement:

http://docs.jquery.com/Events/live

donc votre code sera: Avec cela,

$(".myDiv").live("click", function(){ 
     alert('Alert when clicking on myLink elements. Event delegation powaa !'); 

}); 

vous avez toutes les bénéfices de la délégation d'événement (plus rapide, un écouteur d'événement etc.), sans la douleur ;-)

+0

Mais je le veux sur le document afin que je puisse gérer TOUS mes clics dans un seul endroit. Est-il vrai que live utilise le plus proche() en interne? Si oui, alors pourquoi? Pourquoi le concept de bouillonnement ne prend-il pas soin de cela? – Tommy

+1

live vient avec des pénalités de performance. Surtout quand vous commencez à ajouter plusieurs délégués en direct. délégation native toujours mieux - jusqu'à la prochaine version jq 1.4 où vous pouvez passer dans le contexte pour écouter sur plutôt que ce soit le document à chaque fois – redsquare

+0

Cela sonne bien. – Tommy

0

Event.target est toujours l'élément qui a déclenché l'événement, donc lorsque vous cliquez sur 'myLink' ou 'anotherDiv', vous stockez une référence à ces objets en utilisant $ (e.target); Donc ce que vous faites est: $ ('. MyLink'). Is ('. MyDiv') qui retourne false, et c'est pourquoi alert() n'est pas exécuté.

Si vous souhaitez utiliser la délégation de l'événement de cette manière, vous devriez vérifier wheter event.target est l'élément ou l'un de ses enfants, en utilisant jQuery cela pourrait se faire comme ceci:

$(e.target).is('.myDiv, .myDiv *') 
+0

Bien sûr, mais le clic sur myDiv devrait être suivi d'un appel répété de la délégation d'événement. Éventuellement eventElem sera (ou devrait être) myDiv. – Tommy

+0

event.target ne change pas pendant les phases de capture et de bullage - c'est toujours une référence à l'élément qui a déclenché l'événement. AFAIK il n'y a pas d'autre moyen de savoir si un événement a été déclenché par un enfant d'un élément donné autre que de traverser l'arbre DOM, ou d'utiliser certaines fonctions de la bibliothèque. – pawel

0

semble fonctionner très bien pour moi. Essayez-le ici: http://jsbin.com/uwari

+1

Cela fonctionne, mais la façon dont cela fonctionne est le problème exact que l'OP veut résoudre. – pawel

+0

Précisément. Je veux profiter de toute la puissance de la délégation événementielle et du bouillonnement, mais il semble que ce ne soit pas possible? – Tommy

0

Check this out: Un gestionnaire de clic sur une page

var page = document.getElementById("contentWrapper"); 
page.addEventListener("click", function (e) { 
    var target, clickTarget, propagationFlag;  
    target = e.target || e.srcElement; 
    while (target !== page) { 
     clickTarget = target.getAttribute("data-clickTarget"); 
     if (clickTarget) { 
      clickHandler[clickTarget](e); 
      propagationFlag = target.getAttribute("data-propagationFlag"); 
     } 
     if (propagationFlag === "true") { 
      break; 
     } 
     target = target.parentNode; 
    } 
}); 
Questions connexes