Rolf B: removeEventListener funktioniert nicht mit Funktionsparametern

Beitrag lesen

Hallo Nico R.,

das Problem ist: Woher soll JavaScript wissen, dass die anonyme Funktion, die Du beim add übergibst, die gleiche ist wie die, die Du beim remove übergibst?

Deswegen schrieb Jörg, dass dein Vorhaben mit anonymen Funktionen "eher schwierig" ist. Genauer gesagt: unmöglich.

Leider bekommst Du von addEventListener kein "remove handle" oder sowas in der Art. Du hast darum nur eine Möglichkeit:

function click_view_person(event) {
   // view me 
}

element.addEventListener(click_view_person);
element.removeEventListener(click_view_person);

Jetzt ist's beide Male das gleiche Funktionsobjekt und der Remove wird funktionieren.

Nun gibt es noch einen weiteren Modus, der den Listeneintrag nicht öffnet, sondern auswählt.

Ist das ein Modus, der für die ganze Liste gilt? Oder nur für dieses Element?

Je nach dem gib dem Listencontainer (ul, ol) oder dem li Element eine Klasse "selection-mode" oder ähnlich und frage im click-Handler ab, ob die Klasse vorhanden ist. Je nach Ergebnis machst Du view oder select.

Umregistrieren von Eventhandlern sollte man eher unterlassen, das ist zu umständlich.

Und nun zu deiner wichtigsten Frage:

Gehe ich das grundsätzlich falsch an

Ja.

li Elemente sind keine interaktiven Elemente. Eine Klick-Behandlung für li ist grundsätzlich falsch. Technisch geht es, aber technisch kann ich auch bei Tempo 200 den Zündschlüssel rausziehen und aus dem Fenster werfen. Oder eine Zigarette am Filterende anzünden. Kann man machen, wäre aber grundsätzlich falsch.

Wenn Du auf einen Klick reagieren willst, brauchst Du interaktive Elemente wie a oder button. Da Du auch markieren können willst, riecht das nach einem Button. Dem kannst Du mit CSS alles wegnehmen, was ihn wie einen Button aussehen lässt. Aber dann stimmt die Semantik, und eine Tastaturbedienung wird möglich.

Es ist auch umständlich, den Eventhandler auf jedem einzelnen li oder button zu registrieren. Kennst Du "Event Bubbling"? Du kannst den Handler auf dem Listencontainer einmal registrieren und die Events für alle Listenelemente dort behandeln. Das Event-Objekt, das Du im Eventhandler bekommst, hat zwei wichtige Eigenschaften:

currentTarget
Wohin ist das Event gerade gebubbelt - sprich: das ist das Element, auf dem der Handler registriert ist
target
Wo wurde das Element ausgelöst - bei Maus- oder Touch-Bedienung das Element, über dem die Mausspitze war oder die Fingerspitze zugestoßen hat. Bei Tastaturbedienung zwangsläufig der Button selbst.
<ul id="liste">
  <li><button type="button">Erika Mustermann</button></li>
  <li><button type="button">Otto Normalprogrammierer</button></li>
  <li><button type="button">Ada Lovelace</button></li>
</ul>
const liste = document.querySelector("#liste");
liste.addEventListener("click", function(event) {
   const button = event.target.closest("button");
   if (button) {
      if (liste.classList.contains("selection-mode")) {
        // Selektiere Listeneintrag
      }
      else {
        // Zeige Listeneintrag
      }
   }
});

Die closest-Abfrage brauchst Du nur, wenn deine Buttons HTML Elemente enthalten. event.target liefert Dir das geclickte HTML Element - das könnte auch ein <strong> innerhalb des Buttons sein. Mit closest gehst Du die Elternkette hoch und suchst den Button heraus. Oder mit der parentElement Eigenschaft das li Element - je nach Bedarf.

Wenn Du neben einen Button klickst, aber immer noch in den Bereich des ul Elements, würde die closest-Methode null liefern. Deshalb die Abfrage, ob ein Button gefunden wurde.

In meinem Beispiel wäre dann auch gleich die Weiche für die Betriebsarten "Anzeigen" oder "Auswählen" drin. Denk dran, dass Du beim Auswählen ggf. Aria-Attribute setzen musst, damit Assistenztechniken damit klar kommen. Ich frag mich nur, welche. aria-checked oder aria-selected sind für die Rolle listitem nicht vorgesehen, und ob man deinen li eine andere Rolle geben sollte, weiß ich nicht so recht. @Gunnar Bittersmann, wie sollte man hier aria-mäßig vorgehen? Oder würdest Du die Selected-Eigenschaft der Listen durch eine visuell versteckte Checkbox implementieren? Käme mir eigentlich auch falsch vor, vor allem müsste die ja auch ggf. das Styling des li beeinflussen, in dem sie steckt (was heute mit :has() natürlich machbar wäre, aber ist das richtig so?)

Rolf

--
sumpsi - posui - obstruxi