Lekcja 3: jQuery - Przechodzenie po DOM (DOM Traversal)

Po wybraniu jednego lub więcej elementów za pomocą selektorów jQuery, często chcemy nawigować po drzewie DOM, aby znaleźć powiązane elementy – rodziców, dzieci, rodzeństwo itp. jQuery dostarcza bogaty zestaw metod do przechodzenia po strukturze dokumentu (DOM Traversal), co pozwala na precyzyjne docieranie do potrzebnych elementów.

Przechodzenie w górę drzewa DOM

Metody te pozwalają poruszać się od wybranych elementów w kierunku ich przodków.

Przechodzenie w dół drzewa DOM

Metody te pozwalają poruszać się od wybranych elementów w kierunku ich potomków.

Przechodzenie na boki (po rodzeństwie)

Metody te pozwalają poruszać się między elementami na tym samym poziomie hierarchii (mającymi tego samego rodzica).

Filtrowanie

Metody te pozwalają zawęzić (przefiltrować) bieżący zbiór wybranych elementów.

Łańcuchowanie Metod (Chaining)

Większość metod jQuery zwraca obiekt jQuery (często zmodyfikowany zbiór elementów), co pozwala na wywoływanie kolejnych metod jQuery na wyniku poprzedniej. Nazywa się to łańcuchowaniem (chaining) i pozwala pisać zwięzły i czytelny kod.

$("ul.menu") // Wybierz listę z klasą "menu"
    .children("li") // Wybierz jej bezpośrednie dzieci <li>
    .first() // Weź tylko pierwszy element <li>
    .addClass("pierwszy-element") // Dodaj mu klasę
    .next() // Przejdź do następnego rodzeństwa (<li>)
    .css("color", "red"); // Zmień jego kolor na czerwony

Zadanie praktyczne

Stwórz strukturę HTML z zagnieżdżonymi listami:

<div id="kontener">
    <ul class="lista-glowna">
        <li>Punkt 1</li>
        <li class="aktywny">
            Punkt 2
            <ul class="podlista">
                <li>Podpunkt 2.1</li>
                <li>Podpunkt 2.2</li>
            </ul>
        </li>
        <li>Punkt 3</li>
    </ul>
    <p>Jakiś tekst poza listą.</p>
</div>

Używając metod przechodzenia po DOM w jQuery:

  1. Znajdź element <li> z klasą "aktywny".
  2. Od tego elementu, znajdź jego rodzica <ul> i dodaj mu klasę "rodzic-aktywnego".
  3. Od elementu "aktywny", znajdź jego bezpośrednie dzieci <ul> (podlistę) i dodaj jej klasę "podlista-aktywna".
  4. Od elementu "aktywny", znajdź jego następne rodzeństwo <li> (Punkt 3) i zmień jego tekst na "Następny po aktywnym".
  5. Wybierz wszystkie elementy <li> wewnątrz elementu o id "kontener" i dodaj im klasę "element-kontenera".
Pokaż rozwiązanie
$(function() {
    // 1. Znajdź element li.aktywny
    const aktywnyLi = $("li.aktywny");
    console.log("Znaleziono aktywny element:", aktywnyLi);

    // 2. Znajdź rodzica ul i dodaj klasę
    aktywnyLi.parent().addClass("rodzic-aktywnego");
    console.log("Dodano klasę rodzicowi aktywnego elementu.");

    // 3. Znajdź podlistę ul i dodaj klasę
    aktywnyLi.children("ul").addClass("podlista-aktywna");
    console.log("Dodano klasę podliście aktywnego elementu.");

    // 4. Znajdź następne rodzeństwo li i zmień tekst
    aktywnyLi.next().text("Następny po aktywnym");
    console.log("Zmieniono tekst następnego rodzeństwa.");

    // 5. Wybierz wszystkie li w kontenerze i dodaj klasę (używając find)
    $("#kontener").find("li").addClass("element-kontenera");
    console.log("Dodano klasę wszystkim li w kontenerze.");
});

Możesz dodać odpowiednie style CSS dla klas "rodzic-aktywnego", "podlista-aktywna" i "element-kontenera", aby zobaczyć efekty wizualne.

Zadanie do samodzielnego wykonania

Mając strukturę HTML z poprzedniego zadania, wykonaj następujące operacje używając jQuery:

  1. Wybierz "Podpunkt 2.2".
  2. Używając .closest(), znajdź najbliższy element <div> będący jego przodkiem i dodaj mu klasę "najblizszy-div".
  3. Używając .siblings(), znajdź rodzeństwo "Podpunktu 2.2" (czyli "Podpunkt 2.1") i zmień jego kolor tekstu na czerwony.
  4. Wybierz wszystkie elementy <li> w głównej liście (.lista-glowna) i używając .not(), usuń ze zbioru element z klasą "aktywny", a pozostałym dodaj klasę "nieaktywny".

FAQ - Przechodzenie po DOM w jQuery

Jaka jest różnica między .children() a .find()?

.children() przeszukuje tylko bezpośrednie dzieci wybranego elementu. .find() przeszukuje wszystkich potomków na dowolnym poziomie zagnieżdżenia. .find() wymaga podania selektora, podczas gdy .children() może go nie mieć (zwróci wtedy wszystkie bezpośrednie dzieci).

Jaka jest różnica między .parent() a .parents()?

.parent() zwraca tylko bezpośredniego rodzica. .parents() zwraca wszystkich przodków aż do korzenia dokumentu (<html>). Obie metody mogą być opcjonalnie filtrowane przez selektor.

Do czego przydaje się .closest()?

.closest() jest bardzo użyteczne, gdy mamy element (np. kliknięty przycisk wewnątrz złożonej struktury) i chcemy znaleźć najbliższy element nadrzędny określonego typu (np. cały wiersz tabeli <tr>, kontener produktu <div class="produkt">), aby wykonać na nim operację.

Czy metody przechodzenia modyfikują oryginalny zbiór elementów?

Nie, metody przechodzenia (np. .parent(), .children(), .next()) zwracają nowy obiekt jQuery zawierający znalezione elementy. Oryginalny obiekt jQuery pozostaje niezmieniony, chyba że użyjesz metod modyfikujących w miejscu, jak np. .add() (rzadziej używane).

Jak wrócić do poprzedniego zbioru elementów po przejściu (np. po .find())?

jQuery udostępnia metodę .end(). Przywraca ona stan obiektu jQuery do tego sprzed ostatniej operacji przechodzenia, która modyfikowała zbiór elementów. Pozwala to kontynuować łańcuchowanie na poprzednim zbiorze.

$("ul")
  .find("li") // Wybiera wszystkie li wewnątrz ul
    .addClass("podpunkt") // Dodaje klasę do li
  .end() // Wraca do zbioru ul
  .addClass("przetworzona-lista"); // Dodaje klasę do ul