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);
    
});