Arrêtez la propagation sur des éléments en direct

J'ai un problème avec l'arrêt de la propagation des événements. Imaginez ce scénario:

<table id="test"> <tbody> <tr> <td class="row"> </td> <td class="row"> </td> <td class="row"> </td> <td class="row"> </td> <td class="row"> </td> </tr> <tr> <td class="row"> </td> <td class="row"> </td> <td class="row"> </td> <td class="row"> </td> </tr> </tbody> </table>​ 

Et puis ce code:

 (function(){ $('td.row').on('click', function(e){ if (! e.isPropagationStopped()) alert('Row clicked!'); }); $('table#test').on('click', 'img.live', function(e){ e.stopPropagation(); alert('Image clicked!'); }); $('td.row').html('<img src="http://fc03.deviantart.net/fs71/f/2011/161/f/c/nyan_cat_avatar_by_oxoxnaminemayxoxo-d3il6gm.gif" class="live">'); })();​ 

Chaque fois qu'une image est cliquée, les deux événements sont déclenchés. Je veux que cela déclenche l'événement sur l'élément cliqué. Je sais que, car ils sont en direct, ils sont tirés une fois que la propagation s'est terminée, mais est-ce qu'il y a une solution de contournement?

Dans la mesure où j'ai étudié, les deux événements sont pratiquement les mêmes, mais srcElement change de HTMLTableCellElement à HTMLImageElement . Ce cross-browser est-il cohérent?

J'ai mis une démo dans jsFiddle au cas où vous voulez regarder en action.

Voici une démo

Le problème est que l'événement doit grimper au parent pour trouver un gestionnaire pour <img> . Il doit donc traverser <td> et déclenche son gestionnaire immédiatement car ce n'est pas un gestionnaire délégué.

 *click* ,-----------------> (1) fire direct td handler img -> td -> tr -> table '----> (2) fire delegated img handler X<---- (3) e.stopPropagation() //too late! 

Une façon d'éviter l'événement double est également d'ajouter le gestionnaire de <td> à la table aussi. JQuery évaluera les deux gestionnaires, commencera par l'événement le plus profond et si l'un de ces gestionnaires a e.stopPropagation() , les événements plus haut ne déclencheront pas.

 $('table#test').on('click', 'img.live', function(e){ e.stopPropagation(); alert('Image clicked!'); }); $('table#test').on('click','td.row', function(e){ alert('Row clicked!'); }); *click* img -> td -> tr -> table '----> (1) fire delegated img handler X<---- (2) e.stopPropagation() '----> (3) fire delegated td handler //never gets fired 

Peut-être que je me trompe, mais ne peux-tu pas utiliser la délégation d'événements ici?

 (function(){ $('#test').on('click', function(e){ if ( !/img$/i.test((e.target || e.eventSrc).nodeName)){ alert('row clicked'); } else { alert('image clicked'); } }); $('td.row').html('<img src="'+ 'http://fc03.deviantart.net/fs71/f/2011/'+ '161/f/c/nyan_cat_avatar_by_'+ 'oxoxnaminemayxoxo-d3il6gm.gif" class="live">'); })();​ 

Cela vous fait économiser les tracas avec la propagation. Voici un jsfiddle