Obsługa górnej warstwy w Narzędziach deweloperskich w Chrome

Alina Varkki
Alina Varkki

W Narzędziach deweloperskich w Chrome dodaliśmy obsługę elementów górnej warstwy. Ułatwia ona deweloperom debugowanie kodu, który korzysta z takich elementów.

Z tego artykułu dowiesz się, czym są elementy najwyższego poziomu, jak Narzędzia deweloperskie pomagają wizualizować zawartość najwyższego poziomu w celu zrozumienia i debugowania struktury DOM, która zawiera elementy górnej warstwy, oraz jak jest implementowana obsługa górnej warstwy w Narzędziach deweloperskich.

Czym są elementy górna i górna warstwa?

Co dokładnie dzieje się wewnętrznie, gdy otwierasz <dialog> jako okno modalne? 🤔

Nakładane są na górną warstwę. Zawartość górnej warstwy jest renderowana nad wszystkimi innymi treściami. Na przykład okno modalne musi pojawić się nad wszystkimi innymi treściami DOM, tak aby przeglądarka automatycznie renderowała ten element jako „górną warstwę”. zamiast zmuszać autorów do ręcznego walki z z-index. Element górnej warstwy pojawia się na elemencie nawet o najwyższym wskaźniku z-index.

Górną warstwę można opisać jako „najwyższą warstwę nakładającą”. Z każdym dokumentem powiązany jest jeden widoczny obszar, a tym samym również 1 górna warstwa. W górnej warstwie jednocześnie może znajdować się wiele elementów. W takim przypadku są one umieszczane jeden nad drugim. Inaczej mówiąc, wszystkie elementy górnej warstwy są umieszczane w stosie ostatni w, pierwszy w dół (LIFO) w górnej warstwie.

Element <dialog> nie jest jedynym elementem, który przeglądarka renderuje w górnej warstwie. Obecnie elementy górnej warstwy to: wyskakujące okienka, okna modalne i elementy w trybie pełnoekranowym.

Sprawdź implementację okien:

<main>
  <button onclick="window.dialog.showModal();">Open Dialog</button>
</main>
<dialog id="dialog"></dialog>

Oto wersja demonstracyjna z kilkoma oknami, w których tło zastosowano style (opisane poniżej):

Co to jest tło?

Na szczęście istnieje sposób na dostosowanie zawartości znajdującej się poniżej elementu górnej warstwy.

Każdy element w górnej warstwie ma pseudoelement CSS nazywany tłem.

Tło to pole o rozmiarze widocznego obszaru, które jest renderowane bezpośrednio pod każdym elementem górnej warstwy. Pseudoelement ::backdrop umożliwia zasłonięcie, określenie stylu lub całkowite ukrycie wszystkich elementów znajdujących się pod elementem, gdy jest on najwyższym elementem w górnej warstwie.

Jeśli ustawisz wiele elementów w trybie modalnym, przeglądarka rysuje tło tuż pod takim elementem z przodu i nad innymi elementami pełnoekranowymi.

Tło możesz określić w ten sposób:

/* The browser displays the backdrop only when the dialog.showModal() function opens the dialog.*/
dialog::backdrop {
    background: rgba(255,0,0,.25);
}

Jak wyświetlić tylko pierwsze tło?

Każdy element górnej warstwy ma tło, które należy do stosu górnej warstwy. Są one zaprojektowane tak, aby nakładać się na siebie, więc jeśli przezroczystość tła nie jest ustawiona na 100%, widoczne są zawartość znajdującą się pod spodem.

Jeśli powinno być widoczne tylko pierwsze tło w stosie warstwy najwyższego poziomu, można to osiągnąć, śledząc identyfikatory elementów w stosie warstwy górnej.

Jeśli dodany element nie jest pierwszym elementem w górnej warstwie, funkcja wywoływana po umieszczeniu elementu w górnej warstwie nakłada na ::backdrop klasę hiddenBackdrop. Ta klasa jest usuwana po usunięciu elementu z górnej warstwy.

Zapoznaj się z kodem w tej przykładowej demonstracji:

Projektowanie obsługi najwyższego poziomu w Narzędziach deweloperskich

Obsługa górnej warstwy w Narzędziach deweloperskich ułatwia programistom zrozumienie koncepcji tej warstwy i wizualizację zmian w jej zawartości. Te funkcje pomagają deweloperom identyfikować:

  • Elementy na górze warstwy w dowolnym momencie i w ich kolejności.
  • Element na górze stosu w dowolnym momencie.

Ponadto obsługa górnej warstwy w Narzędziach deweloperskich pomaga wizualizować położenie pseudoelementu tła w stosie warstwy najwyższego poziomu. Chociaż nie jest to element drzewa, odgrywa ważną rolę w działaniu górnej warstwy i może być przydatny dla programistów.

Funkcje obsługi najwyższego poziomu umożliwiają:

  1. Obserwuj w dowolnym momencie, które elementy znajdują się na stosie warstw górnego. Stos reprezentacji górnej warstwy zmienia się dynamicznie w miarę dodawania elementów do górnej warstwy lub ich z niej usuwania.
  2. Sprawdź pozycję elementu w stosie górnych warstw.
  3. Przeskocz z górnego elementu warstwy lub elementów pseudoelementu tła w drzewie do elementu lub pseudoelementu tła w kontenerze reprezentującym górną warstwę i z tyłu.

Zobaczmy, jak korzystać z tych funkcji.

Kontener górnej warstwy

Aby ułatwić wizualizację elementów najwyższego poziomu, Narzędzia deweloperskie dodają do drzewa elementów kontener warstwy najwyższego poziomu. Jest on widoczny po zamykającym tagu </html>.

Ten kontener umożliwia obserwowanie elementów na stosie warstwy górnej w dowolnym momencie. Kontener górnej warstwy to lista linków do elementów górnej warstwy i ich tła. Stos reprezentacji górnej warstwy zmienia się dynamicznie w miarę dodawania elementów do górnej warstwy lub ich z niej usuwania.

Aby znaleźć elementy górnej warstwy w drzewie elementów lub w kontenerze warstwy najwyższego poziomu, klikaj linki z reprezentacji elementu górnej warstwy w kontenerze górnej warstwy do tego samego elementu w drzewie elementów i z tyłu.

Aby przeskoczyć z elementu kontenera górnej warstwy do elementu drzewa warstwy, kliknij przycisk Pokaż obok elementu w kontenerze górnej warstwy.

Przechodzimy z linku do elementu w kontenerze górnej warstwy.

Aby przeskoczyć z elementu drzewa górnej warstwy do linku w kontenerze górnej warstwy, kliknij obok niego plakietkę Górna warstwa.

Przechodzenie z elementu do linku do kontenera warstwy najwyższego poziomu.

Możesz wyłączyć dowolną plakietkę, w tym tę górną warstwę. Aby wyłączyć plakietki, kliknij je prawym przyciskiem myszy, wybierz Ustawienia plakietek i usuń zaznaczenie pól wyboru obok plakietek, które chcesz ukryć.

Wyłączenie plakietki.

Kolejność elementów w stosie warstw górnego

Kontener górnej warstwy pokazuje elementy w takiej postaci, w jakiej są wyświetlane na stosie, ale w odwrotnej kolejności. Górna część elementu stosu jest ostatnia na liście elementów kontenera górnej warstwy. Oznacza to, że ostatnim elementem na liście kontenerów górnej warstwy jest element, z którym możesz obecnie korzystać w dokumencie.

Plakietki obok elementów drzewa wskazują, czy elementy należą do górnej warstwy i zawierają numer pozycji elementu w grupie.

Na tym zrzucie ekranu górny stos warstw składa się z 2 elementów, z których drugi znajduje się u góry. Jeśli usuniesz drugi element, pierwszy zostanie przeniesiony na górę.

Kolejność elementów w stosie.

Tło w kontenerze górnej warstwy

Jak wspomnieliśmy powyżej, każdy element górnej warstwy ma pseudoelement CSS nazywany tłem. Możesz zmienić styl tego elementu, więc warto go zbadać i zobaczyć jego reprezentację.

W drzewie elementów element tła znajduje się przed tagiem zamykającym elementu, do którego należy. Jednak w kontenerze górnej warstwy tuż nad górnym elementem warstwy, do którego należy on, jest wyświetlany link tła.

Pozycja na stosie Tła.

Zmiany w drzewie DOM

ElementsTreeElement, klasa odpowiedzialna za tworzenie poszczególnych elementów drzewa DOM w Narzędziach deweloperskich i zarządzanie nimi, nie wystarczyła do zaimplementowania kontenera górnej warstwy.

Aby wyświetlić kontener warstwy najwyższego poziomu jako węzeł w drzewie, dodaliśmy nową klasę, która tworzy węzły elementów drzewa w Narzędziach deweloperskich. Wcześniej klasa odpowiadała za tworzenie drzewa elementów Narzędzi deweloperskich zainicjowanych co TreeElement przy użyciu klasy DOMNode, która jest klasą z backendNodeId i innymi właściwościami związanymi z backendem. Z kolei projekt backendNodeId jest przypisany w backendzie.

Węzeł kontenera górnej warstwy, który zawiera listę linków do elementów górnej warstwy, musi zachowywać się jak zwykły węzeł elementów drzewa. Ten węzeł nie jest jednak „prawdziwy” Węzeł DOM i backend nie muszą tworzyć węzła kontenera górnej warstwy.

Aby utworzyć węzeł frontendu reprezentujący górną warstwę, dodaliśmy nowy typ węzła frontendu utworzony bez obiektu DOMNode. Ten element kontenera górnej warstwy to pierwszy węzeł frontendu, który nie ma parametru DOMNode. Oznacza to, że istnieje on tylko we frontendzie, a backend nie ma informacji o tym. na ten temat. Aby uzyskać takie samo działanie jak inne węzły, utworzyliśmy nową klasę TopLayerContainer, która rozszerza klasę UI.TreeOutline.TreeElement, która odpowiada za działanie węzłów frontendu.

Aby osiągnąć żądane miejsce docelowe, klasa renderująca element dołącza element TopLayerContainer jako kolejny odpowiednik tagu <html>.

Nowa plakietka górnej warstwy wskazuje, że element jest w górnej warstwie, i służy jako link do skrótu do tego elementu w elemencie TopLayerContainer.

Wstępny projekt

Początkowo planowano zduplikować elementy górnej warstwy do kontenera górnej warstwy, zamiast utworzyć listę linków do tych elementów. Nie wdrożyliśmy tego rozwiązania ze względu na sposób, w jaki działa pobieranie elementów podrzędnych elementów w Narzędziach deweloperskich. Każdy element ma wskaźnik nadrzędny używany do pobierania elementów podrzędnych. Nie można mieć wielu wskaźników. W związku z tym nie możemy mieć węzła, który prawidłowo się rozwija i zawiera wszystkie elementy podrzędne znajdujące się w wielu miejscach w drzewie. Zasadniczo system nie został zaprojektowany z myślą o zduplikowanych poddrzewach.

Odebraliśmy połączenie polegające na utworzeniu połączeń z węzłami DOM frontendu zamiast ich duplikowania. Klasa odpowiedzialna za tworzenie linków do elementów w Narzędziach deweloperskich to ShortcutTreeElement, która rozszerza zakres UI.TreeOutline.TreeElement. ShortcutTreeElement działa tak samo jak inne elementy drzewa DOM Narzędzi deweloperskich, ale nie ma odpowiadającego mu węzła w backendzie i znajduje się przycisk, który prowadzi do ElementsTreeElement. Każdy element ShortcutTreeElement poprzedzający węzeł warstwy najwyższego poziomu ma element podrzędny ShortcutTreeElement, który prowadzi do reprezentacji pseudoelementu ::backdrop w drzewie DOM Narzędzi deweloperskich.

Projekt początkowy:

Wstępny projekt.

Zmiany CDP

Aby wdrożyć obsługę górnej warstwy, należy wprowadzić zmiany w protokole Chrome DevNarzędzia (CDP). CDP to protokół komunikacyjny między Narzędziami deweloperskimi a Chromium.

Musimy dodać:

  • Polecenie do wywołania z frontendu w dowolnym momencie.
  • Zdarzenie, które będzie aktywowane po stronie backendu po stronie backendu.

CDP: polecenie DOM.getTopLayerElements

Aby wyświetlić bieżące elementy górnej warstwy, potrzebujemy nowego, eksperymentalnego polecenia CDP, które zwraca listę identyfikatorów węzłów tych elementów, które znajdują się w górnej warstwie. Narzędzia deweloperskie wywołują to polecenie za każdym razem, gdy są one otwarte lub gdy zmieniają się górne elementy warstwy. Polecenie wygląda tak:

  # Returns NodeIds of the current top layer elements.
  # Top layer renders closest to the user within a viewport, therefore, its elements always
  # appear on top of all other content.
  experimental command getTopLayerElements
    returns
      # NodeIds of the top layer elements.
      array of NodeId nodeIds

CDP: DOM.topLayerElementsUpdated zdarzenie

Aby uzyskać aktualną listę elementów górnej warstwy, musimy mieć pewność, że każda zmiana tego elementu wywołuje eksperymentalne zdarzenie CDP. To zdarzenie informuje frontend o zmianie, która następnie wywołuje polecenie DOM.getTopLayerElements i otrzymuje listę nowych elementów.

Zdarzenie wygląda tak:

  # Called by the change of the top layer elements.
  experimental event topLayerElementsUpdated

Uwagi na temat CDP

Wdrożenie obsługi CDP w górnej warstwie było różne. Inną opcją, którą rozważaliśmy, jest utworzenie zdarzenia, które zwróciłoby listę elementów górnej warstwy, zamiast informować interfejs o dodaniu lub usunięciu tego elementu.

Zamiast polecenia możemy też utworzyć 2 zdarzenia: topLayerElementAdded i topLayerElementRemoved. W tym przypadku otrzymujemy element i musimy zarządzać tablicą elementów górnej warstwy w interfejsie.

Obecnie zdarzenie frontendu wywołuje polecenie getTopLayerElements, aby pobrać listę zaktualizowanych elementów. Gdybyśmy wysyłali listę elementów lub konkretnego elementu, które powodują zmianę przy każdym wywołaniu zdarzenia, moglibyśmy uniknąć jednego kroku wywoływania polecenia. W takim przypadku frontend utraci jednak kontrolę nad tym, które elementy są wypychane.

Wprowadziliśmy go w ten sposób, ponieważ naszym zdaniem lepiej będzie, gdy frontend zdecyduje, kiedy zażądać węzłów najwyższego poziomu. Jeśli na przykład górna warstwa jest zwinięta w interfejsie lub użytkownik korzysta z panelu Narzędzi deweloperskich, który nie ma drzewa elementów, nie ma potrzeby pobierania dodatkowych węzłów, które mogłyby się znajdować głębiej w drzewie.