[JS] Wykrywanie selektora wybranego elementu strony za pomocą JavaScript
Właśnie przygotowuję się do tworzenia aplikacji w której może być przydatne wykrywanie selektora CSS elementu znajdującego się na stronie i postanowiłem się podzielić z Tobą swoim pomysłem. Możesz się zastanawiać, w jakich sytuacjach może się przydać coś takiego? Skoro do tego równie dobrze można wykorzystać Web Developer Tools zaimplementowane w każdej przeglądarce. To jest dobre pytanie.
Taka funkcjonalność może się przydać, gdy zależy nam na tym, aby użytkownik był w stanie wskazać jakiś element na stronie lub aplikacji a następnie móc odpowiednio przekazać informację dotyczącą tego elementu, na przykład jakąś konfigurację bądź feedback. Nie każda osoba jest na tyle obznajomiona z Narzędziami dla Webmasterów aby móc swobodnie się nimi posługiwać.
Detektor selektorów CSS
Do zobrazowania przykładowego kodu JS do generowania selektorów CSS na podstawie wybranego elementu strony zamierzam wykorzystać możliwości pochodzące z najnowszych wersji języka JavaScript (JS >= ES6) . Jeśli będzie istniała potrzeba przedstawienia wersji w poprzedniej generacji języka (ES5) to daj mi znać w komentarzu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | function getCssSelector(element, callback) { let fullSelector = ''; // funkcja sprawdzająca czy wybrany obiekt jest typu undefined const isUndefined = (item) => typeof item === 'undefined'; // funkcja generująca selektor dla elementu const generateSelector = function (el, cb) { // najpierw pobieramy nazwę tagu HTML, np. div let elementSelector = el.tagName.toLowerCase(); // jeśli element posiada atrybut id if (!isUndefined(el.id) && el.id.length) { { // tworzymy selektor id elementSelector = elementSelector + '#' + el.id; } // jeśli element posiada klasy CSS if (!isUndefined(el.className)) { // tworzymy selektor klas CSS i dołączamy do poprzednio utworzonej części selektora elementSelector = [elementSelector, [...el.classList].join('.')].join('.'); } // dołączamy wygenerowany selektor elementu do pełnego selektora wybranego przez nas elementu fullSelector = elementSelector + ' ' + fullSelector; // sprawdzamy czy element ma rodzica if (!isUndefined(el.parentNode.tagName)) { // generujemy selektor rodzica generateSelector(el.parentNode, cb); } else { // zwracamy wygenerowany selektor do funkcji zwrotnej (callback) cb(fullSelector); } }; // generujemy selektor dla wybranego przez nas elementu // i przekazujemy callback generateSelector(element, callback); } |
W kodzie powyżej zamieściłem komentarze opisujące co się dzieje po kolei. Warto zwrócić uwagę na użycie operatora spread - [...el.classList]]
, który pozwala robić rzutowanie na tablicę każdego obiektu niebędącego tablicą, ale mającego własność length
. Bardzo przydatna rzecz.
Oprócz operatora spread wykorzystałem też tzw. arrow functions, czyli funkcje ze strzałką, które zachowują kontekst miejsca w którym zostały wywołane. Jeśli chcesz się dowiedzieć więcej na temat nowych rzeczy użytych w kodzie powyżej, to daj znać w komentarzu.
Na koniec wystarczy teraz wywołać funkcję z odpowiednimi parametrami:
1 | getCssSelector(document.querySelector('#ezs-studio-preview'), path => console.log('path', path)); |
Jako pierwszy parametr, przekazałem wybrany element. W tym przypadku jest to odrobinę niefortunne, bo już znamy odpowiedni selektor (którym jest id i który powinien być unikalny), ale w przypadku gdy interesuje nas selektor elementu, który właśnie został kliknięty to zamiast document.querySelector('#ezs-studio-preview')
wystarczy dać event.target
i już selektor nie jest taki oczywisty.
Jako drugi parametr przekazano funkcję, która ma przyjąć wygenerowany selektor jako swój parametr. W przykładzie powyżej, w konsoli zostanie wypisany wygenerowany selektor.
Przykładowy wygenerowany selektor może wyglądać następująco: html.ez-platformui-app-page.yui3-js-enabled.ez-platformui-app-ready body.ez-platformui-app-body.yui3-skin-platformui div#yui_3_18_1_1_1487242089504_294.ez-platformui-app.pure.is-menu-hidden.is-universaldiscovery-hidden.is-contentpeek-hidden.is-confirmbox-hidden.is-languageselectionbox-hidden.yui3-app.is-app-open.is-studio-loaded div.ez-mainviews.pure-g div.ez-view-container.pure-u.yui3-app-views div#yui_3_18_1_1_1487242089504_2335.ez-view-browserview div.ezs-appview.pure-g div.ezs-appview__workspace.pure-u iframe#ezs-studio-preview.ezs-appview__workspace__preview
. Jest on bardzo długi i na pewno dałoby się go uprościć, ale nie to było celem tego wpisu.
Podsumowanie
W tym krótkim wpisie przedstawiłem sposób na wykorzystanie najnowszej składni JS do rozwiązania problemu jaki miałem. Mam nadzieję, że przygotowany przeze mnie kawałek kodu okaże się przydatny w Twoim projekcie. Zapraszam do komentowania 🙂