Jedna obsluha pro celý seznam
Seznam může mít spoustu položek: deset, sto nebo i nové, které do něj váš skript přidá později. Dát každé položce vlastní obsluhu by bylo pracné. Jde to jednodušeji: jednou obsluhou pro celý seznam.
Funguje to proto, že události probublávají nahoru. Kliknutí na položku je zároveň kliknutím na všechno, v čem položka je: na seznam, na body i na celou stránku. Obsluha kliknutí na seznamu se tak spustí, kdykoli někdo klikne na kteroukoli jeho položku, a event.target řekne, na kterou:
<ul id="zvirata">
<li>Kočka</li>
<li>Pes</li>
</ul>const seznamZvirat = document.querySelector("#zvirata");
seznamZvirat.addEventListener("click", function (event) {
console.log(event.target.textContent);
});Kliknutí na Pes vypíše Pes. Obsluha je na seznamu, ale event.target je položka, na kterou se kliklo. A funguje to i pro položky, které do seznamu přibudou později, bez jakékoli nové obsluhy.
Má to jeden háček: event.target je ten nejvnitřnější prvek, na který se kliklo. Když jsou v položce další prvky, třeba <li><strong>Kočka</strong>, 3 roky</li>, kliknutí na slovo Kočka vám dá strong, ne li. A kliknutí vedle položek, na samotný seznam, vám dá ul.
Řeší to metoda closest() (anglicky nejbližší). Dáte jí selektor, stejně jako metodě querySelector(). Začne u samotného prvku a postupuje nahoru přes prvky, ve kterých je, dokud nenajde takový, který selektoru odpovídá:
seznamZvirat.addEventListener("click", function (event) {
const polozka = event.target.closest("li");
if (polozka === null) {
return;
}
console.log(polozka.textContent);
});Ať do položky kliknete kamkoli, v polozka bude li. Když se na žádnou položku nekliklo, closest() nic nenajde a vrátí null, a tak obsluha skončí pomocí return. Bez této kontroly by polozka.textContent skončilo chybou TypeError: Cannot read properties of null (reading 'textContent').
Svá data mají položky obvykle v datových atributech, třeba <li data-vek="3">, a obsluha je přečte pomocí polozka.dataset.vek.
Jak psát:
Pokyny
Dejte prvku seznamReceptu jednu obsluhu kliknutí. V ní najděte recept, na který se kliklo, pomocí event.target.closest("li"), a když žádný není, obsluhu ukončete. Jinak ukažte v prvku casText dobu z atributu data-minuty receptu: Doba přípravy: 15 minut pro palačinky. Zkuste kliknout na název receptu i na zbytek jeho řádku.
Zvýrazněte recept, na který se kliklo: dejte jeho li třídu vybrany. Zvýrazněný je vždy jen jeden recept, takže si zvýrazněnou položku pamatujte v proměnné let vybranaPolozka = null; mimo obsluhu. Než zvýrazníte novou položku, odeberte třídu té předchozí, pokud už nějaká je (vybranaPolozka není null), a novou si pak do proměnné uložte.