Termin „AJAX” przewija się ostatnio bardzo często w świecie programistów, ludzi związanych na co dzień z internetem, ale także osób, którzy chcą wykorzystać jego funkcjonalność w swoim serwisie. I faktycznie jest coraz częściej z powodzeniem wykorzystywany, zarówno w dużych komercyjnych projektach internetowych, jak i w małych, prywatnych serwisach. Czym tak naprawdę jest AJAX, a co ważniejsze, czy warto zaprzątać sobie nim głowę?
Rozwinięciem skrótu AJAX jest Asynchroniczny JavaScript i XML (ang. Asynchronous JavaScript And XML). Jest to technika pozwalająca na tworzenie aplikacji internetowych, w których możliwe jest dokonywanie dynamicznych zmian w strukturze i treści dokumentu w sposób całkowicie niewidoczny dla użytkownika, bez przeładowania treści strony. Fakt ten pozwala na tworzenie interaktywnych i przyjaznych aplikacji internetowych, szybciej reagujących na żądania użytkownika. Główna funkcjonalność AJAX-a składa się z czterech części:
- języków XHTML i CSS do wprowadzania i modyfikacji wyglądu treści dokumentu,
- języka JavaScript do przetwarzania struktury DOM dokumentu, dokonywania w nim modyfikacji i dodawania nowych elementów, a także do obsługi zdarzeń związanych z działaniami użytkownika,
- obiektu XMLHttpRequest pozwalającego na asynchroniczną komunikację z serwerem w tle,
- języka XML służącego jako uniwersalny format wymiany danych, a w praktyce może to być dowolny format danych możliwy do przetworzenia po stronie przeglądarki przez JavaScript.
Plusy AJAX-a
Chcesz wiedzieć, co zyskasz dzięki AJAX-owi? Otóż AJAX pozwala m.in. na:
- wykonywanie połączeń z serwerem HTTP asynchronicznie, czyli w tle
- pobieranie informacji o dowolnej treści i strukturze
- korzystanie z metod GET, POST, HEAD i innych
- wprowadzenie dynamicznych reakcji na zachowania użytkownika
- tworzenie aplikacji internetowych Web 2.0
Tak więc do stworzenia elementów naszego serwisu, opartych o AJAX, potrzebna jest znajomość języka JavaScript i wiedza o zasadach funkcjonowania obiektu XMLHttpRequest, co zostanie przedstawione w dalszej części tego artykułu.
Wady i zalety
Przyjrzyjmy się bliżej zaletom, jakie niesie ze sobą wykorzystanie AJAX-a. Jedną z nich jest niewątpliwie fakt, że daje on nam możliwość tworzenia prawdziwych aplikacji internetowych. Reagując na interakcje użytkownika ze stroną, możemy w sposób dynamiczny uzyskać połączenie z serwerem i pobrać dowolną, zależną od potrzeb porcję danych, a następnie wyświetlić ją użytkownikowi.
Działanie aplikacji tego typu opiera się głównie na przeglądarce użytkownika, co w praktyce oznacza odciążenie serwera. Inną pozytywną cechą tej techniki jest to, że pobierane są jedynie niewielkie porcje danych (w porównaniu z przeładowaniem całej strony), zależne od aktualnej akcji wykonanej przez użytkownika lub rodzaju komponentu, który stworzyliśmy. Jednocześnie wszystkie dane ciasteczek są nadal dostępne, co w praktyce pozwala nam na bezproblemowe korzystanie np. z mechanizmu sesji.
Jeśli chodzi o dostępność AJAX-a, to działa on bez większych problemów na wszystkich najpopularniejszych obecnie przeglądarkach internetowych. Warto również pamiętać, że AJAX nie jest żadnym rozszerzeniem czy wtyczką przeglądarki internetowej, a swoje działanie opiera głównie na języku JavaScript, bardzo rzadko, w obecnych czasach, blokowanym przez użytkowników.
Zalet jest wiele. Istnieją również jednak wady, o których należy i trzeba wiedzieć. Jedną z tych najczęściej wytykanych jest fakt, że modyfikacje wewnątrz struktury czy treści dokumentu nie są rejestrowane przez mechanizm historii przeglądarki. Użytkownik jest przecież przyzwyczajony, że po tym, jak wykonał jakąś akcję i nastąpiła modyfikacja strony, może w prosty sposób wrócić do poprzedniego stanu, naciskając przycisk Wstecz. W przypadku AJAX-a niestety tak to nie wygląda. W praktyce jest wręcz przeciwnie, bo mechanizm historii przeglądanych stron w ogóle nie reaguje na zmiany.
AJAX a przeglądarki internetowe
Przeglądarki wspierające AJAX-a:
- Microsoft Internet Explorer w wersji 5.0 lub wyższej
- Przeglądarki oparte o Gecko, m.in. Mozilla, Mozilla Firefox, Netscape 7.1 lub wyższy
- Przeglądarki posiadające mechanizmy KHTML API przynajmniej w wersji 3.2, m.in. Konqueror w wersji 3.2 lub wyższej oraz Apple Safari w wersji 1.2 lub wyższej
- Opera i Opera Mobile Browser w wersji 8.0 lub wyższej
Przeglądarki niewspierające AJAX-a:
- Microsoft Internet Explorer w wersji 5.0 lub niższej
- Opera 7 i starsze
- Przeglądarki tekstowe, m.in. Lynx oraz Links
- Przeglądarki przystosowane dla osób niepełnosprawnych
Innym problemem jest brak możliwości dodania dokumentu do zakładek, celem późniejszego wczytania. Jeśli komponenty wykorzystujące AJAX-a nie zostały prawidłowo zaprogramowane, może się okazać, że po ponownym wejściu na tę samą stronę, użytkownik uzyska domyślny jej stan i będzie musiał za każdym razem przystosowywać jej wygląd i zawartość.
Należy również pamiętać, że przed jakimikolwiek zmianami na stronie, przed pobraniem nowej treści poprzez obiekt XMLHttpRequest, powinniśmy to zakomunikować użytkownikowi poprzez komunikat lub plik graficzny. Jest to również związane z przyzwyczajeniami internautów, bo przecież każda przeglądarka internetowa wyświetla pasek postępu i przetwarzania aktualnie pobieranego dokumentu. Brak takiego elementu w połączeniu z długim czasem pobierania treści może spowodować zrozumiałą reakcję przeładowania dokumentu przez użytkownika.
Ostatnią, jednak wcale nie mniej istotną wadą AJAX-a jest fakt, że do działania wymaga aktywnej opcji wykonywania skryptów, a w przypadku przeglądarki Microsoftu (w wersji 6 lub niższej) dodatkowo opcji tworzenia obiektów ActiveX. Obydwie są jednak domyślnie włączone i dość rzadko spotyka się sytuację, w której któryś z tych elementów byłby niedostępny.
Dostępność
Przy każdej technice, tak popularnej obecnie jak AJAX, wraca temat dostępności – i prawidłowo. Nie wolno nam bowiem zapominać o tym, że w miejscach kluczowych naszego serwisu, w których planujemy wykorzystać AJAX-a, powinniśmy umieścić alternatywę, wyświetlaną, gdy z jakiegoś powodu nie będzie on dostępny. Dotyczy to głównie przeglądarek w starszych wersjach, ale również przeglądarek tekstowych lub, co ważniejsze, aplikacji przeznaczonych dla osób niepełnosprawnych.
Zarówno język HTML, jak i JavaScript udostępniają nam elementy i struktury, które możemy w tym wypadku wykorzystać. Dla języka HTML jest to głównie znacznik {stala}noscript{/stala}, którego zawartość wyświetlana jest wyłącznie w przypadku wyłączonej opcji wykonywania skryptów client-side. W przypadku JavaScript jest to blok {stala}try… catch{/stala}, który pozwala nam na wyłapanie błędów przy tworzeniu obiektu XMLHttpRequest i ewentualne wyświetlenie alternatywnej treści. W pewnych sytuacjach błąd podczas tworzenia tego obiektu sygnalizowany jest zwróceniem przez konstruktor wartości false, co również można bez problemów wykryć.
Ogólne rzecz biorąc, w przypadku użytkowników, u których z jakiegoś powodu nie jesteśmy w stanie zainicjować mechanizmów AJAX-a, powinniśmy umożliwić korzystanie z serwisu w tradycyjny sposób, za każdym razem przeładowując całą zawartość dokumentu. Nie będzie to może już tak dynamiczne i efektowne, ale nadal użyteczne.
Nic na siłę
Po lekturze poprzednich rozdziałów wielu z was ma już na pewno szereg pomysłów, gdzie można by wykorzystać opisywaną technikę do stworzenia nowej funkcjonalności lub zastąpienia starej, mniej dynamicznej. Warto jednak zastanowić się jeszcze raz, zanim przystąpimy do realizacji pomysłu.
AJAX jest bardzo użytecznym narzędziem, ale jego nieumiejętnie wykorzystanie może dać efekt przeciwny do zaplanowanego, powodując, że serwis stanie się mniej użyteczny i przyjazny dla użytkownika.
Przykładem bardzo złego, wręcz tragicznego, pomysłu jest wykonanie w oparciu o niego elementów nawigacyjnych serwisu. Oczywiście, mądre i przemyślane zaprojektowanie, a później zaprogramowanie czegoś takiego, pamiętając o wadach i aspektach użyteczności, spełni swoją rolę, gdy będzie zawsze w pełni funkcjonalne, niezależnie od konfiguracji przeglądarki. Jednak nie możemy dopuścić do sytuacji, w której wszyscy użytkownicy, u których AJAX z jakiegoś powodu nie funkcjonuje, nie mają możliwości przeglądania podstron i cały serwis staje się dla nich kompletnie bezużyteczny.
Z drugiej strony, bardzo dobrym miejscem jest na przykład formularz ankiety czy logowania, który w przypadku braku funkcjonalności AJAX-a wysłany zostanie w tradycyjny sposób. Zyskujemy w tym miejscu na efektywności, bo cała strona nie jest przeładowywana, a wyświetlany zostaje jedynie komunikat np. z podziękowaniem za wzięcie udziału w ankiecie.
Zyskujemy także na optymalizacji, bo zamiast zawartości całej strony przesłany zostaje, przykładowo, jeden bajt, określający powodzenie logowania. W tym konkretnym wypadku zysk jest ogromny, bo rzędu kilku tysięcy procent w porównaniu ze średniej wielkości dokumentem HTML o rozmiarze 2, 3KB.
AJAX z powodzeniem spełnia swoją rolę w serwisach internetowych takich firm jak Google, Yahoo czy Microsoft. Jednym z bardziej popularnych przykładów jest serwis Google Maps (http://maps.google.com), udostępniający każdemu mapy satelitarne prawie całego świata. AJAX jest w nim wykorzystywany niemal wszędzie, co spowodowało, że aplikacja szybko i sprawnie reaguje na wszelkie akcje użytkownika, ładując co raz żądany kawałek mapy.
Spróbujmy sobie wyobrazić teraz Google Maps bez AJAX-a – aplikację, w której poruszanie po mapie odbywa się za pomocą strzałek pozwalających na przesunięcie mapy w wybranym kierunku, jednak oczywiście po przeładowaniu całej strony. Do tego wszystkiego w jednej chwili możemy oglądać tylko aktualnie wyświetlany kawałek, a powrót do poprzednio przeglądanej części wiąże się z wygenerowaniem całego dokumentu od nowa. Kiepsko? Nawet bardzo.
Praktyka
Mając już teoretyczną wiedzę na temat możliwości opisywanej w tym artykule techniki, warto spojrzeć na temat od strony praktycznej. Zanim jednak przystąpimy do pisania kodu źródłowego, przyjrzyjmy się szczegółowo metodom i atrybutom obiektu XMLHttpRequest, na którym AJAX opiera całą komunikację i wymianę danych z serwerem.
Wszystkie przeglądarki internetowe udostępniają natywnie obiekt XMLHttpRequest, wyjątkiem jest Internet Explorer, w przypadku którego musimy utworzyć obiekt ActiveX. Lecz pomimo rozbieżności na etapie tworzenia obiektu, jego funkcjonalność pozostaje w obydwu przypadkach taka sama, a w wersji siódmej aplikacji Microsoftu obiekt ten został już zaimplementowany natywnie. Napiszmy więc funkcję, która będzie zwracać instancję XMLHttpRequest.
function createXHR() {
if (typeof XMLHttpRequest != \"undefined\")
return new XMLHttpRequest();
var xhrVersion = [ \"MSXML2.XMLHttp.5.0\", \"MSXML2.XMLHttp.4.0\",
\"MSXML2.XMLHttp.3.0\", \"MSXML2.XMLHttp\", \"Microsoft.XMLHttp\" ];
for (var i = 0; i < xhrVersion.length; i++) {
try {
var xhrObj = new ActiveXObject(xhrVersion[i]);
return xhrObj;
} catch (e) {}
}
return false;
}
W pierwszych linijkach sprawdzamy dostępność obiektu udostępnianego natywnie, na tym etapie, w wypadku przeglądarek takich jak Firefox, Opera czy Safari, funkcja zakończy działanie zwracając nam egzemplarz obiektu. Pozostały kod, widoczny poniżej, przeznaczony jest wyłącznie dla przeglądarki Internet Explorer. Wykorzystując prostą pętlę, próbujemy utworzyć instancję o możliwie jak najnowszej wersji. W razie niepowodzenia, funkcja zwraca wartość false.
XMLHttpRequest zawiera szereg metod i atrybutów, które musimy poznać, zanim przystąpimy do etapu łączenia z serwerem. Metoda {stala}open{/stala}, wykorzystując tryb przesyłania danych przekazany w postaci łańcucha znaków w pierwszym parametrze (przykładowo {stala}GET{/stala} lub {stala}POST{/stala}), nawiązuje połączenie z serwerem w celu pobrania zawartości umieszczonego w kolejnym parametrze adresu URL. Trzeci argument wywołania określa, czy przesyłanie danych powinno być przeprowadzane asynchronicznie i w większości przypadków będzie przyjmował wartość true.
Z kolei metoda {stala}send{/stala} przesyła przygotowane żądanie do serwera, wywołując przy tym akcję {stala}onreadystatechange{/stala} przy każdej zmianie wewnętrznego stanu obiektu, zapisanego pod atrybutem {stala}readyState{/stala}.
Nas interesuje jedynie stan o wartości 4, oznaczający zakończenie pobierania danych, wszystkie pozostałe ignorujemy. Po wystąpieniu tego stanu musimy sprawdzić, czy pobieranie danych zakończyło się powodzeniem, co jest jednoznaczne z kodem odpowiedzi serwera o wartości 200, zapisanej w atrybucie {stala}status{/stala} (odpowiedź serwera HTTP/1.0 200 Ok). Jeśli i w tym miejscu wszystko poszło po naszej myśli, atrybut {stala}reasponseText{/stala} zawiera ściągnięte z serwera informacje w postaci ciągu znaków.
Warto w tym miejscu wspomnieć, że istnieje również atrybut {stala}responseXML{/stala}, zawierający obiekt typu XMLDocument, który można dowolnie przetwarzać przy użyciu funkcji DOM, jednak tylko wtedy, gdy pobrane dane są poprawnym dokumentem XML. Korzystając z powyższych informacji, napiszmy funkcję, której argumentami będą adres URL dokumentu oraz funkcja, która zostanie wywołana po jego pobraniu. Pamiętajmy, że ze względów bezpieczeństwa adres URL musi wskazywać na plik umieszczony na lokalnym serwerze.
function makeRequest(url, resultFunction) {
var xhr = createXHR();
if (xhr === false)
return false;
xhr.open(\'GET\', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState != 4)
return;
delete xhr[\'onreadystatechange\'];
if (xhr.status == 200)
resultFunction(xhr.responseText);
delete xhr;
};
xhr.send(null);
}
Funkcja ta pozwala nam w sprawny i prosty sposób wykonywać żądania typu {stala}GET{/stala}, bez potrzeby zagłębiania się w jakiekolwiek mechanizmy XMLHttpRequest. Spróbujmy na jej podstawie stworzyć nasz pierwszy komponent opierający swoje działanie o AJAX-a.
Przykład 1 - Hello World
Zaczniemy oczywiście od tradycyjnego \"Hello World\", do którego dołączymy pobraną z serwera datę i godzinę. Wszystkie te informacje ukażą się w postaci okna dialogowego po naciśnięciu przycisku. Zacznijmy od napisania funkcji, która będzie wtedy wywoływana.
function helloWorld() {
makeRequest(\'1.php\', function(text) {
alert(text);
});
}
Wykorzystując znaną już funkcję {stala}makeRequest{/stala}, pobieramy zawartość pliku 1.php, którego działanie sprowadza się jedynie do wyświetlenia wspomnianego ciągu znaków. Zauważmy, że za każdym naciśnięciem klawisza wyświetlana w oknie godzina jest inna, co świadczy jedynie o tym, że dane są naprawdę za każdym razem w dynamiczny sposób pobierane z serwera.
Przykład 2 - Formularz logowania
Podstawy już za nami, spróbujmy napisać bardziej zaawansowany przykład. Naszym celem jest stworzenie panelu logowania do panelu administratora, w którym nazwa użytkownika i hasło przesyłane będą przez AJAX-a. Musimy więc mieć tradycyjny formularz logowania z polami nazwy użytkownika i hasła.
To, co wyróżnia ten formularz, to dodatkowy element {stala}onsubmit{/stala} znacznika {stala}form{/stala}, wskazujący na funkcję, która zostanie wywołana przed próbą jego wysłania. Kod tej funkcji jest kluczowy dla tego przykładu i przedstawia się następująco:
function ajaxLogin() {
if (makeRequest(\'ajaxlogin.php?u=\' +
encodeURIComponent(document.getElementById(\'u\').value) +
\'&p=\' + encodeURIComponent(document.getElementById(\'p\').value), function(text) {
if (text != 1) {
alert(\'Nieprawidłowa nazwa użytkownika lub hasło.\');
return;
}
document.location = \'admin.php\';
}) === false)
return true;
return false;
}
Wywołujemy skrypt 2.php, przekazując mu dodatkowo wpisane przez użytkownika dane logowania. Pobrana w wyniku takiego zapytania wartość 1 oznacza, że wpisane dane są poprawne, więc możemy przekierować użytkownika na stronę panelu administracyjnego (po stronie serwera musimy oczywiście utworzyć sesję określającą uprawnienia użytkownika dostępu do panelu). W innym wypadku wyświetlamy komunikat o błędzie i pozwalamy użytkownikowi na ponowne wpisanie danych.
Warto zauważyć, że w przypadku, gdy inicjacja mechanizmów AJAX-a zakończy się niepowodzeniem (funkcja {stala}makeRequest{/stala} zwróci wartość false), formularz zostanie przesłany w tradycyjny sposób. Za taki stan rzeczy odpowiedzialna jest instrukcja warunkowa umieszczona na samym początku kodu funkcji.
AJAX w sieci
Na naukę nigdy za późno! Więcej informacji na temat AJAX-a znajdziesz na tych stronach:
Ogromne źródło wiedzy na temat nowości w świecie AJAX-a, jeden z pierwszych serwisów, prowadzony w formie bloga.
2. http://developer.mozilla.org/en/docs/AJAX
Lektura obowiązkowa, czyli przewodnik po AJAX-ie dla webmasterów.
Strona projektu AdvancedAJAX 1.1, dostępnego z dokumentacją w języku polskim.
AJAX dla zaawansowanych
AdvancedAJAX (http://advajax.anakin.us) jest obiektem języka JavaScript zbudowanym w oparciu o XMLHttpRequest. Z jego pomocą możemy szybko, sprawnie i w pełni skorzystać z funkcjonalności AJAX-a w naszych projektach. Posiada dodatkowe właściwości, takie jak mechanizm przedawniania i wznawiania połączeń, obsługę błędów czy pełną współpracę z formularzami HTML. Autor obiektu AdvancedAJAX jest jednocześnie autorem tego artykułu.
Podsumowanie
Nietrudno zauważyć, że AJAX jest naprawdę potężnym narzędziem. Jest to w końcu jeden z filarów serwisów internetowych nowej generacji, nazywanych powszechnie Web 2.0. Jego umiejętne wykorzystanie pozwala uzyskać w pełni efekt interaktywności, co na pewno docenią internauci przeglądający nasz serwis.