Délégation d’événements avec event.target, event.target.closest si on écoute le clic sur un lien ou un bouton qui contient une icône SVG
Mise à jour: 09/12/2021
Nouvelle source avec deux solutions proposées (la 1ère fonctionne, je l’ai testée): Codepen: CodePen Home
Event delegation with SVGs and closest() et Codepen: CodePen Home
Event Delegation with an SVG.
1 2 3 4 5 6 |
<button class="click-me"> <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 800 800" aria-describedby="menu-title"> <title id="menu-title">User Menu</title> <path fill="currentColor" d="M725 0H75C33.75 0 0 33.75 0 75v450c0 41.25 33.75 75 75 75h125v200l240-200h285c41.25 0 75-33.75 75-75V75c0-41.25-33.75-75-75-75zM400 100.258c55.086 0 99.742 44.656 99.742 99.742S455.086 299.742 400 299.742 300.258 255.086 300.258 200s44.656-99.742 99.742-99.742zM550 500H250v-50c0-55.231 44.772-100 100-100h100c55.231 0 100 44.769 100 100v50z"/> </svg> </button> |
1 2 3 4 |
document.addEventListener('click', function (event) { if (!event.target.closest('.click-me')) return; console.log(event.target); }, false); |
Sources:
- jQuery click event on parent, but finding the child (clicked) element
- event.target sur developer.mozilla.org
- event.target.className sur developer.mozilla.org
Description du problème
J’ai le markup HTML suivant:
1 2 3 4 5 6 7 8 |
<div id="p"> <div id="c1"> <div id="c2"></div> <div id="c3"></div> </div id="c4"> <div id="c5"></div> </div> </div> |
…et je souhaite récupérer l’ID de l’élément enfant qui est cliqué lorsque je clique sur l’ensemble de la zone #p
. Mais c’est systématiquement l’ID #p
qui m’est remonté.
1 2 3 |
$('#p').bind('click', function() { alert($(this).attr('id')); }); |
Solution en passant event en paramètre de fonction et en utilisant event.target pour récupérer les informations sur le noeud du DOM qui est effectivement cliqué
1 2 3 |
$('#p').bind('click', function(event) { alert(event.target.id); }); |
Note importante: ne pas tenter de passer this
ou thisobj
à la place de event
en paramètre de la fonction. Le libellé du paramètre est important et doit rester event
à cet endroit là. Plus d’info ici: Difference between this and event.target.
Cas plus complexe où la fonction est déclenchée via un attribut onClick
dans la source HTML…
…et où une classe précise doit être mise à l’écart.
1 2 3 4 5 6 7 8 |
<tr onClick="jQuery(this).toggleAssociatedDetailByClickingRow(event);" ng-repeat-start="(lineIndex, lineData) in supplierData.stockV2" class="product-isContacto product-isLens row-triggersExpandableContent"> <td class="col-item"></td> <td class="col-toggleDetail"> <button class="btn-showChildrenTable"><svg><path /></svg></button> </td> <td class="col-description"></td> [...] </tr> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * Afficher/Masquer un détail en cliquant n'importe où dans la rangée concernée */ $.fn.toggleAssociatedDetailByClickingRow = function(event){ const TARGET = $(event.target); if (TARGET.is('.btn-showChildrenTable, svg, path', '.col-toggleDetail')) { return false; } else { $(this) .children('.col-toggleDetail') .find('.btn-showChildrenTable') .toggleAssociatedDetail(); } } // fin: Afficher/Masquer un détail en cliquant n'importe où dans la rangée concernée |