Wyszukiwarki wykorzystujące technologię Ajax stosują liczne udogodnienia. Częstymi rozwiązaniami są podpowiadanie, automatyczne uruchamianie wyszukiwania po upływie kilku sekund oraz animacje. Główną cechą, która odróżnia wyszukiwarkę ajaksową od rozwiązań tradycyjnych, nie są jednak atrakcje wizualne, a fakt, że wyniki wyszukiwania pojawiają się bez przeładowania strony.
Działanie tradycyjnej wyszukiwarki
Wyszukiwarka treści na witrynie WWW jest dostępna w postaci formularza, który zawiera wiersz wprowadzania danych oraz przycisk Szukaj. Przykładowa witryna zawierająca wyszukiwarkę jest przedstawiona na rys. 1.
Użytkownik wprowadza w formularzu dowolny wyraz, na przykład nie, po czym naciska przycisk Szukaj. Działanie takie powoduje przejście do nowej strony WWW, która zawiera wyniki wyszukiwania. Lista wyników wyszukiwania może obejmować tytuły podstron wraz z informacją o tym, ile razy podane słowo występuje w treści (rys. 2).
Znalezione informacje są przedstawiane w postaci listy hiperłączy. Po wybraniu jednego z hiperłączy przechodzimy do strony, która będzie zawierała wyszukiwane słowo. Innymi słowy ze strony z rys. 2 przechodzimy z powrotem do strony z rys. 1 (ewentualnie z treścią innej piosenki).
Rozwiązanie tradycyjne składa się z dwóch rodzajów podstron. Pierwszym rodzajem są podstrony z tekstem wybranej piosenki (rys. 1), a drugim podstrony prezentujące wyniki wyszukiwania (rys. 2).
Działanie wyszukiwarki ajaksowej
Gdy wyszukiwarkę wzbogacimy o technologię Ajax, wówczas wyniki wyszukiwania są prezentowane bez przeładowania strony. Po naciśnięciu przycisku Szukaj na stronie pojawia się nowy element div, zawierający wyniki wyszukiwania. Na rys. 3 element ten został otoczony obramowaniem.
Wyszukiwarkę ajaksową należy zaimplementować w taki sposób, by po wyłączeniu w JavaScripcie działała w sposób tradycyjny.
Implementacja wyszukiwarki tradycyjnej
Podstrony i adresy URL
Przygotowanie wyszukiwarki rozpoczynamy od ustalenia stosowanych adresów URL. Strony pierwszego rodzaju prezentują tekst wybranej piosenki (rys. 1). Adresy URL przyjmą postać:
index.php?id=2&id2=XXX
gdzie XXX jest identyfikatorem piosenki. Na przykład adres:
index.php?id=2&id2=1
dotyczy piosenki podtytułem Chodzi lisek koło drogi, gdyż piosenka ta ma identyfikator 1, zaś adres:
index.php?id=2&id2=5
wskazuje stronę z tekstem piosenki Kółko graniaste ( identyfikator 5).
Strony drugiego rodzaju prezentują wyniki wyszukiwania (rys. 2). Stosowane adresy mają strukturę:
index.php?id=3&szukaj=YYY
gdzie {stala}YYY{/stala} jest wyszukiwanym słowem. Na przykład wyniki wyszukiwania słowa nie są dostępne pod adresem:
index.php?id=3&szukaj=nie
zaś wyniki wyszukiwania słowa tak pod adresem:
index.php?id=3&szukaj=tak
Formularz wyszukiwania
Formularz wyszukiwania jest przetwarzany przez skrypt {stala}index.php{/stala}. Zawiera on jedno pole wprowadzania danych o nazwie szukaj i jedno pole ukryte o nazwie id:
W ten sposób, po zatwierdzeniu, formularz zostanie przekazany pod adres:
index.php?id=3&szukaj=...
W miejsce trzech kropek przeglądarka umieści wyraz wprowadzony w formularzu.
Menu strony
Menu strony powstaje na podstawie pliku {stala}00index.log{/stala}. Każda linijka pliku zawiera dane jednej piosenki: tytuł oraz nazwę pliku tekstowego z treścią piosenki:
Jawor, jawor|jawor_jawor.txt
Krasnoludki|krasnoludki.txt
Ojciec i syn|ojciec_i_syn.txt
...
Plik ten jest przetwarzany przez funkcję {stala}podaj_dane(){/stala} przedstawioną na listingu 1. Wynikiem działania funkcji {stala}podaj_dane(){/stala} jest tablica asocjacyjna, która pod indeksem ile zawiera liczbę piosenek, a pod indeksami nazwyplikow oraz tytuly – tablice z nazwami plików i tytułami piosenek.
function podaj_dane($ANazwapliku)
{
$tmp = array();
$p = file($ANazwapliku);
$pc = count($p);
$tmp[\'ile\'] = $pc;
$tytuly = array();
$nazwyplikow = array();
for ($i = 0; $i < $pc; $i++) {
$e = explode(\'|\', trim($p[$i]));
$tytuly[$i] = $e[0];
$nazwyplikow[$i] = $e[1];
}
$tmp[\'nazwyplikow\'] = $nazwyplikow;
$tmp[\'tytuly\'] = $tytuly;
return $tmp;
}
Wykorzystując funkcję {stala}podaj_dane(){/stala} menu strony drukujemy w pętli {stala}for{/stala}:
Wyszukiwanie
Za wyszukiwanie danych odpowiada przedstawiona na listingu 2 {stala}funkcja wyniki_szukaj(){/stala}. Posiada ona dwa parametry. Pierwszy, szukane słowo {stala}$ASzukaj{/stala}, pochodzi z formularza. Drugi, dane {stala}$ADane{/stala}, są wynikiem działania funkcji {stala}podaj_dane(){/stala}.
function wyniki_szukaj($ASzukaj, $ADane)
{
$dane = array();
$dane[0] = array();
$dane[1] = array();
$dane[2] = array();
for ($i = 0; $i < $ADane[\'ile\']; $i++) {
$t = file_get_contents(\'txt/\' . $ADane[\'nazwyplikow\'][$i]);
//tytul
$dane[0][$i] = $ADane[\'tytuly\'][$i];
//id
$dane[1][$i] = $i + 1;
//liczba wystapien slowa
$dane[2][$i] = substr_count($t, $ASzukaj);
}
array_multisort(
$dane[2], SORT_DESC, SORT_NUMERIC,
$dane[0], SORT_ASC, SORT_STRING,
$dane[1]
);
if ($dane[2][0] == 0) {
//nic nie znaleziono
return false;
} else {
for ($i = 0; ($i < $ADane[\'ile\']) && ($dane[2][$i] > 0); $i++);
$dane[\'ile\'] = $i;
$dane[\'pokazpelnalista\'] = false;
$dane[0] = array_slice($dane[0], 0, $i, true);
$dane[1] = array_slice($dane[1], 0, $i, true);
$dane[2] = array_slice($dane[2], 0, $i, true);
return $dane;
}
}
Gdy podane słowo nie zostało znalezione, to wynikiem funkcji {stala}wyniki_szukaj(){/stala} jest {stala}false{/stala}. W przeciwnym wypadku wynikiem funkcji jest tablica dwuwymiarowa, która zawiera informacje o tym, w których piosenkach ile razy wystąpiło podane słowo. Po wywołaniu:
$w = wyniki_szukaj(\'ala\', $dane);
tablica {stala}$w{/stala} będzie zawierała trzy składowe: {stala}$w[0]{/stala}, {stala}$w[1]{/stala} oraz {stala}$w[2]{/stala}. Pierwsza z nich będzie tablicą zawierającą tytuły piosenek. Druga - tablicą zawierającą identyfikatory piosenek, a trzecia - tablicą zawierającą liczbę wystąpień wyrazu ala w danej piosence. Jeśli:
$w[0][3] = \'Krasnoludki\'
$w[1][3] = \'6\'
$w[2][3] = \'17\'
to wynika z tego, że identyfikatorem piosenki Krasnoludki jest 6 oraz że szukane słowo występuje w piosence Krasnoludki 17 razy.
Wyniki wyszukiwania ustalone przez funkcję {stala}wyniki_szukaj(){/stala} przekształcamy w listę ol. Zadanie to realizuje przedstawiona na listingu 3 funkcja {stala}wyniki_html(){/stala}.
function wyniki_html($AWyniki)
{
if ($AWyniki) {
$wynik = \'\';
for ($i = 0; $i < $AWyniki[\'ile\']; $i++) {
$wynik .=
\'- \' .
$AWyniki[0][$i] .
\' (\' .
$AWyniki[2][$i] .
\')\' .
\'
\';
}
$wynik .= \'
\';
} else {
$wynik = \'Nic nie znaleziono!\';
}
return $wynik;
}
Wybór treści witryny
Skrypt {stala}index.php{/stala} zajmuje się wyborem odwiedzonej podstrony oraz przygotowaniem informacji. Wybór podstrony następuje na podstawie zmiennej URL o nazwie id. Gdy id jest równe 2, to wyświetlany jest tekst odpowiedniej piosenki. Jeśli natomiast id wynosi 3, wówczas wyświetlane są wyniki wyszukiwania. Zarys skryptu {stala}index.php{/stala} jest przedstawiony na listingu 4.
BĹ‚Ä…d!\';
}
?>
Domyślną stroną, jaką ujrzy użytkownik, jest strona błędu ({stala}$akcja == 1{/stala}). Stronę z tekstem piosenki lub z wynikami wyszukiwania wyświetlamy wyłącznie wtedy, gdy proces walidacji zmiennych URL zakończy się sukcesem.
Jeśli {stala}tablica $_GET{/stala} jest pusta, wówczas instrukcjami:
$_GET[\'id\'] = \'2\';
$_GET[\'id2\'] = \'1\';
wymuszamy przejście do strony z tekstem pierwszej piosenki.
Implementacja wyszukiwarki ajaksowej
Skrypt server.php
Pracę nad rozwiązaniem ajaksowym rozpoczynamy od przygotowania skryptu {stala}server.php{/stala} przedstawionego na listingu 5. Skrypt ten odpowiada za wyszukiwanie podanego słowa. Wyszukiwane słowo jest przekazywane do skryptu jako zmienna URL o nazwie co. Wyniki wyszukiwania są zwracane w postaci listy ol.
Skrypt {stala}server.php{/stala} możemy przetestować wprowadzając w polu adresowym przeglądarki następujący adres URL-e:
server.php?co=ja
W wyniku powinniśmy ujrzeć listę ol prezentującą wyniki wyszukiwania słowa {stala}ja{/stala}.
Zmiany w kodzie HTML
Formularz ajaksowej wyszukiwarki zawiera obsługę zdarzenia {stala}onsubmit{/stala}. Wywoływana funkcja {stala}pokaz_wyniki(){/stala} jest zdefiniowana w pliku {stala}ajax.js{/stala} dołączonym w nagłówku strony:
Wyszukiwanie nie może powodować przeładowania strony WWW. Odpowiada za to instrukcja {stala}return false{/stala} występująca w obsłudze zdarzenia {stala}onsubmit{/stala}. Jeśli kod JavaScript wywoływany w zdarzeniu {stala}onsubmit{/stala} zwraca wartość {stala}false{/stala}, to przeglądarka nie wysyła formularza na serwer. Takie zachowanie umożliwia nie tylko wykonanie ajaksowej wyszukiwarki, ale także walidację formularza.
Wyniki wyszukiwania będą umieszczane w elemencie:
Element ten jest początkowo niewidoczny. Odpowiadają za to style CSS:
#wyniki {
display: none;
}
Przeładowanie fragmentu
Za wyświetlenie wyników wyszukiwania odpowiadają dwie funkcje JavaScript: {stala}pokaz_wyniki(){/stala} oraz {stala}odbierz_dane(){/stala}:
Pierwsza z nich, {stala}pokaz_wyniki(){/stala}, wykonuje następujące akcje:
- tworzy obiekt {stala}XMLHttpRequest{/stala},
- pobiera do zmiennej co wyszukiwane słowo, które zostało wprowadzone w formularzu,
- ustala adres URL wyników wyszukiwania ({stala}\'server.php?co=\' + co{/stala}),
- ustala funkcję obsługi zdarzenia {stala}onreadystatechange{/stala},
- rozpoczyna transfer danych:
function pokaz_wyniki()
{
if (r = getXMLHttpRequest()) {
var co;
co = document.getElementById(\'sz\').value;
r.open(\'GET\', \'server.php?co=\' + co);
r.onreadystatechange = odbierz_dane;
r.send(null);
}
}
Funkcja {stala}odbierz_dane(){/stala} odpowiada za włączenie widoczności elementu {stala}div#wyniki{/stala} przeznaczonego na wyniki wyszukiwania oraz za umieszczenie w nim treści zwróconych przez skrypt {stala}server.php{/stala}:
function odbierz_dane()
{
if (r.readyState == 4 && r.status == 200) {
var wyn;
wyn = document.getElementById(\'wyniki\');
wyn.innerHTML = r.responseText;
wyn.style.display = \'block\';
}
}
Podsumowanie
Działanie wyszukiwarki ajaksowej możemy sprawdzić odwiedzając witrynę Bartosza Danowskiego http://danowski.pl oraz blog Piotra Petrusa http://perfectionorvanity.com.
Z powodu niewielkiej ilości dostępnej przestrzeni, liczbę wyników wyszukiwania prezentowaną bez przeładowania strony należy ograniczyć do kilku pozycji. Do pełnej listy może prowadzić hiperłącze: zobacz wszystkie wyniki.
Zwróćmy uwagę na ustalenie kodowania znaków w skrypcie {stala}server.php{/stala}:
header(\'Content-Type: text/html; charset=utf-8\');
Wywołanie funkcji {stala}header(){/stala} będzie konieczne, jeśli chcemy stosować inne kodowanie niż utf-8.