Poznajemy Tree Walkery w JavaScript, czyli coś, czego jeszcze nie robiliśmy, a bardzo one upraszczają zaawansowaną kontrolę nad DOM. Do dzieła.

Ok, to nasz markup:

<ul id="list">
        My list:
        <li>List item 1</li>
        <li>List item 2</li>
        <li>List item 3</li>
    </ul>

A to nasz TreeWalker:

const treeWalker = document.createTreeWalker(
    document.querySelector("#list"),
    NodeFilter.SHOW_TEXT,
  );
  
while (treeWalker.nextNode()) {
    const node = treeWalker.currentNode;
    node.data = node.data.toUpperCase();
}

Podnosi wszystkie text nodes (także te wewnątrz li) do wielkiej litery. A gdybyśmy tak chcieli tylko textNodes poza li podnieść do wielkiej litery?

const treeWalker = document.createTreeWalker(
    document.querySelector("#list"),
    NodeFilter.SHOW_TEXT,
  );
  
while (treeWalker.nextNode()) {

    const node = treeWalker.currentNode;

    if(node.parentElement.matches("ul#list"))
        node.data = node.data.toUpperCase();    
  }

Możemy nawet zmodyfikować markup, aby zobaczyć, czy działa:

<ul id="list">
        My list:
        <li>List item 1</li>
        <li>List item 2</li>
        <li>List item 3</li>
        End of my list...
    </ul>

Ok, napiszmy sobie jakieś komentarze w HTMLu:

<ul id="list">
        <!-- comment one --> 
        My list:
        <li>List item 1 <!-- comment two --> </li>
        <li>List item 2</li>
        <li>List item 3</li>
        End of my list...
        <!-- comment three --> 
</ul>

I prosty skrypt, który nam odczyta te komentarze:

const treeWalker = document.createTreeWalker(
    document.querySelector("#list"),
    NodeFilter.SHOW_COMMENT,
  );
  
while (treeWalker.nextNode()) {

    const node = treeWalker.currentNode;
    console.log(node.data);
          
  }

Ok, zmieniamy nieco markup:

<ul id="list">
        <!-- comment one --> 
        My list:
        <li class="show">show me</li>
        <li class="skip">skip</li>
        <li class="reject">reject</li>
        <li class="show">show me, but you wont...</li>
        End of my list...
        <!-- comment three --> 
</ul>

Na początek wyświetlimy sobie wszystkie elementy:

const treeWalker = document.createTreeWalker(
    document.querySelector("#list"),
    NodeFilter.SHOW_ELEMENT,
  );
  
while (treeWalker.nextNode()) {

    const node = treeWalker.currentNode;
    console.log(node.textContent);
          
  }

Ok, a teraz wykorzystamy trzeci, opcjonalny argument dla tree walkera:

const treeWalker = document.createTreeWalker(
    document.querySelector("#list"),
    NodeFilter.SHOW_ELEMENT,
    (node) => {
        if(node.classList.contains("show"))
            return NodeFilter.FILTER_ACCEPT;
        else if(node.classList.contains("skip"))
            return NodeFilter.FILTER_SKIP;
        else if(node.classList.contains("reject"))
            return NodeFilter.FILTER_REJECT;
    }
  );
  
while (treeWalker.nextNode()) {

    const node = treeWalker.currentNode;
    console.log(node.textContent);
          
  }

Pokazuje show me, oraz show me, but you wont. Cóż, reject do czego innego służy:

<ul id="list">
        <li class="show"><span class="show">show me</span></li>
        <li class="skip">skip</li>
        <li class="reject">reject<span class="show">show me, but you wont</span></li>
        <li class="show">show me 2</li>
    </ul>

Reject odrzuca subtree danego elementu, ale iterator idzie dalej. Teraz mamy show me i show me 2. To warto sobie uświadomić – TreeWalker chodzi po strukturze drzewa.

Jeżeli chcemy prosty iterator, który chodzi po tablicy i nie patrzy jak zagnieżdżone są elementy, to mamy NodeIterator (document.createNodeIterator)…