Accordion Event delegation
Wir haben nun auf jeden einzelnen Accordeon-Header einen EventListener gelegt. Das ist okay bei vier Accordeons, aber wenn wir … viele haben, wird das ineffizient. Das ist ein Fall für das Event Delegation Pattern.
Where to attach the event listener
Section titled “Where to attach the event listener”Beim Event Delegation Pattern legen wir einen Event-Listener auf das nächstgelegene übergeordnete Element und schauen anschließend, wo genau das Event herkommt.
Ein übergeordnetes Element bauen wir uns jetzt noch schnell ein:
<div class="accordion-container"> <div class="accordion">...</div> <div class="accordion">...</div> <div class="accordion">...</div> <div class="accordion">...</div></div>Auf diesen Container legen wir jetzt unseren Event Listener:
const accordionContainer = document.querySelector('.accordion-container');
accordionContainer.addEventListener('click', e => { // okay, was jetzt? // loggen wir mal, woher der Event kommt: console.log(e.target);});Jetzt können wir auf alle Events innerhalb des Accordeon-Containers lauschen. Das e.target ist das Element, auf das geklickt wurde.
Making the accordions work
Section titled “Making the accordions work”Wenn ein Accordeon-Header geklickt wurde, möchten wir das zugehörige Accordeon öffnen oder schließen. Wenn irgendwo anders hingeklickt wurde (z.B. auf einen geöffneten Accordeon-Inhalte), soll nichts passieren.
Dafür müssen wir feststellen, ob .accordion-header ein Vorfahr von e.target ist (wir zielen dabei auf <h2>, <button>, <span class="accordion-title"> bzw. <div class="accordion-indicator"> ab).
accordionContainer.addEventListener('click'), e => { const accordionHeader = e.target.closest('.accordion-header'); if (accordionHeader) { // toggle acc } else { // do nothing - können wir uns hier sparen ... }}Wenn der Klick irgendwo in den Accordion-Header gegangen ist, dann wollen wir dem zugehörigen Accordion die Klasse is-open mitgeben (oder sie wieder wegnehmen). Im HTML sehen wir, dass <div class="accordion"> das Elternelement von <div class="accordion-header"> ist.
accordionContainer.addEventListener('click', e => { const accordionHeader = e.target.closest('.accordion-header'); if (accordionHeader) { const accordion = accordionHeader.parentElement; accordion.classList.toggle('is-open'); }});