Jak filtrować tabelę danych - budujemy prostą wyszukiwarkę
| Robert | komentarze | JavaScriptZałóżmy, że posiadamy tabelę z danymi i chcieli byśmy w niej wyszukiwać informację w czasie rzeczywistym, przychodzi nam na ratunek JavaScript. Język ten (podobno) jest najbardziej niezrozumiałym językiem na świecie, ale nic bardziej mylnego, bo są osoby (w tym ja) które odnajdą się w nim bez problemu. Dziś zrobimy prostą wyszukiwarkę w czystym JS'ie na bazie inputa i danych z tabeli.
Zrobiłem jakiś czas temu skrypt w php który pobiera kompletną listę odcinków pewnego programu rozrywkowego z player.pl, a następnie grupuje je wg. gościa. W rezultacie można szybko sprawdzić w których Jan Kowalski odcinkach występował (tytuł odcinka, sezon, odcinek, data) - Kowalski akurat nie występował. ;) Potrzeba matką wynalazków, a nowicjuszom może się to przydać, także do dzieła!
Tabela ma strukturę:
<table id="episodesTable">
<tr>
<th>Osoba</td>
<th>Odcinki</td>
</tr>
<tr>
<td>{Imię Nazwisko}</td>
<td>
<ul>
<li><a href="{url}" target="_blank"><span class="episodeTitle">{TYTUŁ}</span> (sezon {numer}, odcinek {numer}, {data})</a></li>
</ul>
</td>
</tr>
</table>
Od czego zacząć? Definiujemy kluczowe zmienne
var si, //searchInput
t, //table
tr; //wszystkie wiersze z tabeli
Następnie przypisujemy do nich wartości, korzystamy przy tym z querySelectora.
si = document.querySelector('#searchPlace');
t = document.querySelector('#episodesTable');
tr = t.querySelectorAll('tr');
Przed tabelą wstawiamy prosty input w którym będziemy wprowadzać zapytanie
<input type="text" placeholder="Wyszukaj w tytułach..." id="searchPlace" />
Definiujemy funkcję wyszukiwania search(e) oraz dodajemy do si w momencie kiedy zostanie "podniesiony" przycisk.
function search(e) {
...
};
si.addEventListener('keyup', search);
Skupmy się teraz na funkcji wyszukiwania. Dla uproszczenia dodajemy w stylach klasę która ma za zadanie ukryć element wówczas kiedy zostanie do niego przypisana ta klasa:
.hide {
display: none;
}
Pobieramy wartość z pola wyszukiwania oraz zmniejszamy wszystkie znaki, dzięki temu ułatwieniu bez znaczenia będzie czy użytkownik będzie wpisywać wartość z małej czy z dużej litery. Później w trakcie porównywania docenisz ten zabieg. Iterujemy wszystkie wiersze w pętli for każdorazowo pobierając wartość do porównania z odpowiedniego elementu. W moim przypadku celowo wyodrębniłem tytuł od informacji o odcinku w celu eliminacji zamieszania w trakcie wyszukiwania:
for (let row of tr) {
let title = row.querySelector('.episodesTitle');
if (title === null) {
continue;
}
...
}
W moim przypadku zdarzały się elementy które nie zawierały elementu .episodesTitle z tego względu, że nie ma ich po prostu w nagłówku tabeli, w tym przypadku pomijamy wykonywanie kodu słowem continue, w innym przypadku kod generował by błąd.
Dalej w pętli pobieramy zawartość elementu z tytułem oraz zmniejszamy znaki w celu porównania:
let titleContent = title.innerHTML.toLowerCase();
if (!titleContent.includes(val)) {
row.classList.add('hide');
}
else {
row.classList.remove('hide');
}
Funkcja includes sprawdza, podciąg czy znajduje się w ciągu. Jeśli nie, dodaje do wiersza klasę stylu hide która ma na celu ukrycie go, w przeciwnym przypadku usuwa tą klasę. Tak oto każdorazowo po każdym wciśnięciu przycisku na klawiaturze wykonywana jest ta funkcja, a tabela jest przeszukiwania dynamicznie, od razu pokazując wynik wyszukiwania. Metoda ta jest dobra dla wyszukiwania elementów z małych zbiorów.
Dla podsumowania przedstawiam cały kod js:
(function(){
var si,t,tr;
si = document.querySelector('#searchPlace');
t = document.querySelector('#episodesTable');
tr = t.querySelectorAll('tr');
function search(e) {
let val = e.target.value.toLowerCase();
for (let row of tr) {
let title = row.querySelector('.episodeTitle');
if (title === null)
continue;
let titleContent = title.innerHTML.toLowerCase();
if (!titleContent.includes(val)) {
row.classList.add('hide');
}
else {
row.classList.remove('hide');
}
}
};
si.addEventListener('keyup', search);
})();
Przypominam początkującym, że aby kod poprawnie działał, należy go umieścić na końcu strony tuż przed tagiem body.