Poznajemy kolejne metody klasy Element, plus w końcu wykonamy sobie jakąś delegacje eventów w praktyce, zamiast o niej gadać w teorii. Do dzieła.
Ok, markup:
<ul id="list">
Languages to learn:
<li>C# <button class="btn-del">X</button></li>
<li>Java <button class="btn-del">X</button></li>
<li>Scala <button class="btn-del">X</button></li>
<li>Perl <button class="btn-del">X</button></li>
<li>Ruby <button class="btn-del">X</button></li>
</ul>
Dobra, pamiętamy eventy:
- capture phase, czyli od window do targetu
- target phase / AT_TARGET, czyli target
- bubble phase, czyli od targetu w górę idąc po composedPath() – metoda klasy Event
Pamiętamy też:
- event.target – target, to co klikamy
- event.currentTarget – to, do czego przypięto event listener
- event.relatedTarget – to było w eventach myszy, polecam sobie przypomnieć, choć tutaj nie będziemy tego używać
Ok, to działamy. Delegacja eventów, ale wszystko co nie jest buttonem z klasą btn-del ma być ignorowane:
let ul = document.querySelector("#list");
ul.addEventListener("click", function(e){
if(!e.target.matches('button.btn-del'))
return;
console.log(e.target);
});
Ok, połączmy to z closest:
let ul = document.querySelector("#list");
ul.addEventListener("click", function(e){
if(!e.target.matches('button.btn-del'))
return;
console.log(e.target.closest("li").textContent);
});
Closest wyszukuje pierwszego rodzica, który odpowiada selektorowi. Teraz możemy użyć remove:
let ul = document.querySelector("#list");
ul.addEventListener("click", function(e){
if(!e.target.matches('button.btn-del'))
return;
e.target.closest("li").remove();
});
Podsumujmy:
- element.matches(selektor) – sprawdza, czy element odpowiada danemu selektorowi
- element.closest(selektor) – odnajduje rodzica, który odpowiada danemu selektorowi
- element.remove – usuwa element
Ok, a czy mamy jakiś sposób, aby pokazywać/usuwać textNode, gdy wszystkie języki zostaną usunięte? Cóż, mamy propagację, mamy currentTarget, mamy wiele różnych opcji.
Oto moje rozwiązanie:
let ul = document.querySelector("#list");
ul.addEventListener("click", function(e){
if(!e.target.matches('button.btn-del'))
return;
e.target.closest("li").remove();
if(e.currentTarget.childElementCount === 0)
e.currentTarget.removeChild(e.currentTarget.firstChild);
});