Wymiana fragmentu strony WWW bez przeładowania całego dokumentu wiąże się z kilkoma problemami. Stosując takie rozwiązania należy sprawdzić m.in. czy witryna jest dostępna dla robotów, jak się zachowuje przy wyłączonej interpretacji JavaScript oraz jak stosowane rozwiązanie wpływa na transfer. Artykuł opisuje sześć przykładowych implementacji wymiany fragmentu oraz przedstawia szczegółową analizę cech proponowanych rozwiązań.
Asynchroniczna wymiana fragmentu witryny
Wymiana fragmentu witryny bez przeładowywania całej strony jest popularnym rozwiązaniem, które znajdziemy m.in. w serwisach http://www.yahoo.com oraz http://www.fotozakupy.pl. Menu zaznaczone czerwoną obwódką powoduje wymianę treści fragmentu zaznaczonego zieloną obwódką.
{z9864} |
Rozwiązanie zastosowane w Yahoo! wykorzystuje Ajax i działa także przy wyłączonym JavaScripcie (oczywiście strona jest wówczas przeładowywana w całości).
Natomiast serwis Fotozakupy stosuje zmianę widoczności warstw bez użycia Ajaksa (komplet tekstów jest zawarty w głównym dokumencie HTML). Rozwiązanie takie nie działa, gdy wyłączymy JavaScript.
Przykład
Omawiane zagadnienie przedstawię od strony praktycznej. Menu strony jest zaznaczone czerwoną obwódką. Po aktywacji jednej z opcji menu odpowiednia treść jest ładowana do pojemnika oznaczonego zieloną obwódką.
Kod HTML przykładu ma postać:
< div id=\"pojemnik\">
Dane w formacie HTML
Przykład prezentuje zawartość pięciu płyt muzycznych:
- ABBA: Super Trouper,
- AC/DC: Flick of the Switch,
- Aerosmith: Draw the Line,
- Black Sabbath: Eternal Idol,
- Bob Dylan: Basement Tapes.
Pliki:
- fragment-abba.html
- fragment-ac_dc.html
- fragment-aerosmith.html
- fragment-black_sabbath.html
- fragment-bob_dylan.html
zawierają kod HTML. Nie są to kompletne strony WWW, a jedynie fragmenty, które należy umieścić w pojemniku {stala}div#content{/stala} przeznaczonym na treść.
O to zarys pliku {stala}fragment-bob_dylan.html{/stala}:
< h1>Bob Dylan
< h2>Basement Tapes
< h2>1975
lp. | title | czas |
---|---|---|
1. | Odds and Ends | 1:46 |
2. | Orange Juice Blues (Blues for Breakfast) | 3:37 |
Każdy plik z opisem płyty zawiera jeden element h1 (nazwa zespołu), dwa elementy h2 (tytuł płyty oraz rok jej wydania) oraz tabelę z listą utworów. Po wstawieniu pliku {stala}fragment-bob_dylan.html{/stala} otrzymamy kod:
Bob Dylan
Basement Tapes
1975
...
Rozwiązanie pierwsze: Ajax
Przeprowadzenie wymiany fragmentu strony WWW przy użyciu Ajaksa wymaga ustalenia dla każdej opcji menu dwóch parametrów:
- adresu URL dokumentu, który będzie załadowany,
- identyfikatora id elementu XHTML, w którym należy umieścić pobraną treść.
Ładowanymi dokumentami są pliki:
fragment-abba.html
fragment-ac_dc.html
...
Każde hiperłącze ładuje treść do tego samego elementu: pojemnika div o identyfikatorze content.
Wymianę treści realizuje funkcja {stala}wymienTresc(){/stala}. Ma ona dwa parametry: adres url oraz identyfikator id:
wymienTresc(url, id)
Hiperłącza w menu przyjmą postać:
ABBA: Super Trouper
Bob Dylan: Basement Tapes
Funkcja {stala}wymienTresc(){/stala} pochodzi z pliku {stala}ajax.js{/stala}. Jest ona zaimplementowana przy użyciu obiektu {stala}XMLHttpRequest{/stala}:
var r;
var e;
function odbierzDane()
{
if (r.readyState == 4) {
if (r.status == 200 || r.status == 304) {
e.innerHTML = r.responseText;
}
}
}
function wymienTresc(adresurl, htmlid)
{
if (r = getXMLHttpRequest()) {
e = document.getElementById(htmlid);
r.open(\'GET\', adresurl);
r.onreadystatechange = odbierzDane;
r.send(null);
}
}
Rozwiązanie takie działa tylko wtedy, gdy w przeglądarce włączona jest obsługa JavaScript. Wykorzystując okno dialogowe Narzędzia → Opcje → Treść wyłączamy obsługę języka JavaScript. Przykład przestanie działać.
Cechy rozwiązania
Główną wadą podanego rozwiązania jest to, że nie działa ono przy wyłączonym JavaScripcie. Treść podstron jest niedostępna dla robotów wyszukiwarek.
Ponadto strona taka wymaga korzystania z serwera HTTP. Pomimo że są to statyczne pliki HTML, przykład nie będzie działał offline, czyli np. po nagraniu na płycie CD.
Kolejnym minusem jest to, że ładowanie podstron z sieci będzie powodowało mrugnięcie lub chwilowe zatrzymanie aplikacji.
Cały przykład jest widoczny w sieci pod jednym adresem {stala}URL: index.html{/stala}. Należy pilnować, by adresy {stala}fragment-xxx.html{/stala} nie stały się dostępne publicznie, gdyż w przeciwnym razie grozi nam ten sam problem, co w przypadku ramek HTML. Użytkownicy mogą trafić na dziwne fragmentaryczne strony, nie mając żadnego odsyłacza prowadzącego do dokumentu macierzystego.
Takie podejście minimalizuje transfer danych: za każdym razem z serwera pobierane są tylko konieczne informacje. Fragmenty, które się nie zmieniają (np. menu), nie są pobierane przy każdym żądaniu HTTP.
Rozwiązanie drugie: Ajax i hiperłącza
W jaki sposób zapewnić, by witryna działała po wyłączeniu JavaScriptu? Najpierw przygotowujemy tradycyjną witrynę, która w menu zawiera zwykłe hiperłącza. Należy przygotować pięć plików:
- abba.html,
- ac_dc.html,
- aerosmith.html,
- black_sabbath.html,
- bob_dylan.html.
Każda z tych stron zawiera identyczne menu oraz opis jednej z płyt. Hiperłącza menu są tradycyjnymi hiperłączami, które dodatkowo obsługują zdarzenia {stala}onclick{/stala}:
ABBA: Super Trouper
Przy wyłączonej interpretacji kodu JavaScript hiperłącze będzie działało w tradycyjny sposób.
Jeśli natomiast obsługa JavaScriptu jest włączona, wówczas zostanie dodatkowo wywołana funkcja {stala}wymienTresc(){/stala}. Należy w niej wykonać kod, który wyłączy przeładowanie strony.
Przeładowanie strony możemy wyłączyć zmieniając adres href hiperłącza na #. W tym celu funkcja {stala}wymienTresc(){/stala} otrzymała trzeci parametr: {stala}this{/stala}. Jest to obiekt DOM – kliknięte hiperłącze menu. Przeładowanie dokumentu wyłączamy ustalając wartość atrybutu href klikniętego hiperłącza:
function wymienTresc(adresurl, htmlid, hiperlacze)
{
if (r = getXMLHttpRequest()) {
e = document.getElementById(htmlid);
r.open(\'GET\', adresurl);
r.onreadystatechange = odbierzDane;
r.send(null);
hiperlacze.href = \'#\';
}
}
Cechy rozwiązania
Drugi przykład działa poprawnie bez względu na to, czy obsługa JavaScript jest włączona czy wyłączona. Odbywa się to kosztem tego, że witryna składa się teraz z dziesięciu plików. Pięć z nich zawiera tradycyjne kompletne strony WWW. Pozostałe pięć – fragmenty, które należy umieścić wewnątrz pojemnika {stala}div#content{/stala}. Można powiedzieć, że każda podstrona jest wykonywana dwukrotnie: raz jako pełna strona WWW (np. {stala}abba.html{/stala}) wykorzystywana przy wyłączonym JavaScripcie, drugi raz jako fragment (np. {stala}fragment-abba.html{/stala}) użyty przez Ajaksa.
Tak wykonany przykład wymaga serwera HTTP. Wersja offline witryny będzie działała wyłącznie po wyłączeniu obsługi JavaScriptu. Ładowanie podstron przez Ajaksa powoduje chwilowy przestój.
Rozwiązanie trzecie: tablica danych JavaScript
W celu eliminacji mrugnięcia powodowanego pobieraniem danych przez Ajaksa oraz udostępnienia działającej witryny offline należy zrezygnować z Ajaksa i umieścić komplet danych wewnątrz pobieranej witryny. Można do tego wykorzystać tablice JavaScript.
Cała witryna składa się tym razem z dwóch plików: {stala}index.html{/stala} oraz {stala}tab.js{/stala}. Plik {stala}index.html{/stala} zawiera menu oraz pojemnik {stala}div#content{/stala}, zaś {stala}tab.js{/stala} – treść wszystkich podstron oraz skrypt przeładowujący zawartość pojemnika {stala}div#content{/stala}.
Hiperłącza menu mają postać:
ABBA: Super Trouper
Funkcja {stala}wymienTresc(){/stala} pobiera zamiast adresu URL identyfikator podstrony.
W pliku tab.js znajduje się tablica dane oraz funkcja {stala}wymienTresc(){/stala}. Tablica dane zawiera kompletną treść wszystkich podstron (tj. zawartość pięciu plików {stala}fragment-abba.html{/stala}, {stala}fragment- c_dc.html{/stala} itd.):
var dane = new Array;
dane[1] = \'ABBA
...
AC/DC
...Aerosmith
...Wymiana treści sprowadza się do jednej instrukcji przypisania:
function wymienTresc(id, htmlid)
{
document.getElementById(htmlid).innerHTML = dane[id];
}
Cechy rozwiązania
Przykład ten oczywiście nie działa po wyłączeniu JavaScriptu. Nie wymaga on stosowania serwera HTTP i będzie działał w wersji offline, ale tylko przy włączonym JavaScripcie.
Ponieważ komplet danych jest zawarty w dwóch plikach i po kliknięciu opcji menu nie są wysyłane żadne żądania HTTP, w przykładzie nie występują żadne przestoje ani mrugnięcia.
Ocena wpływu rozwiązania na transfer zależy od rodzaju wizyty. Jeśli ktoś wejdzie na jedną tylko podstronę, to transfer będzie większy niż przy tradycyjnie wykonanej stronie z jednym menu, gdyż pobrana zostanie treść wszystkich pozycji menu. Jeśli natomiast podczas wizyty użytkownik odwiedzi wiele różnych pozycji menu, to transfer będzie niższy niż przy rozwiązaniu tradycyjnym. Wynika to stąd, że skrypt tab.js jest zapisywany przez przeglądarkę w pamięci podręcznej i będzie pobrany tylko raz.
Rozwiązanie czwarte: tablica JavaScript i hiperłącza
Rozwiązanie stosujące tablicę JavaScript możemy wzbogacić o obsługę tradycyjnych hiperłączy. Rozwiązanie składa się wówczas z pięciu statycznych plików HTML: {stala}abba.html{/stala}, {stala}ac_dc.html{/stala} itd. oraz pliku {stala}tab.js{/stala}.
Hiperłącza menu mają postać:
ABBA: Super Trouper
Cechy
Przykład ten działa w wersji offline i nie wymaga JavaScriptu. Komplet danych stosowanych do przeładowania zawartości jest zawarty w pliku {stala}tab.js{/stala}. Zatem w przykładzie uruchomionym z obsługą JavaScriptu nie zauważymy przestoju związanego z pobieraniem danych z serwera.
Rozwiązanie piąte: zmiana widoczności warstw
Innym rozwiązaniem jest umieszczenie kompletu danych wewnątrz kodu HTML:
ABBA
...
...
AC/DC
...
...
...
Obsługa aktywacji opcji menu sprowadzi się wówczas do przełączenia widoczności warstw.
Hiperłącza menu wymagają jedynie jednego parametru:
ABBA: Super Trouper
Funkcja {stala}wymienTresc(){/stala} wyłącza widoczność wszystkich opcji, po czym ponownie włącza widoczność opcji przekazanej jako parametr:
function wymienTresc(id)
{
ukryj();
document.getElementById(id).style.display = \'block\';
}
Natomiast funkcja ukryj() wyłącza widoczność wszystkich opcji:
function ukryj()
{
document.getElementById(\'opcja1\').style.display = \'none\';
document.getElementById(\'opcja2\').style.display = \'none\';
...
}
Cechy rozwiązania
Rozwiązanie to działa wyłącznie przy włączonym JavaScripcie. Będzie ono poprawne także w wersji offline.
Wprawdzie cała treść zawarta w dokumencie jest dostępna dla robotów, jednak wiąże się z tym pewien kłopot. Wyszukiwarka może zwrócić wyniki wyszukiwania, które wprawdzie zawierają żądane frazy, jednak frazy te nie są widoczne.
Pod względem transferu rozwiązanie takie będzie niekorzystne. Każda wizyta na dowolnej podstronie będzie powodowała pobieranie kompletu danych.
Rozwiązanie szóste: warstwy i hiperłącza
W rozwiązaniu stosującym tradycyjne hiperłącza wraz ze zmianą widoczności warstw hiperłącza menu przyjmą postać:
ABBA: Super Trouper
Wewnątrz funkcji {stala}wymienTresc(){/stala} należy zmienić widoczność warstw oraz zmieniając adres href klikniętego hiperłącza wyłączyć przeładowanie witryny.
Cechy
Oczywiście rozwiązanie to działa przy wyłączonym JavaScripcie. Może ono być stosowane offline.
Podsumowanie
W charakterystyce podanych rozwiązań należy uwzględniać odpowiedzi na następujące pytania:
- czy rozwiązanie działa bez JavaScriptu?
- czy rozwiązanie działa w trybie offline (bez serwera HTTP, np. z płyty CD)?
- czy występuje chwilowa przerwa (mrugnięcie) spowodowana transferem danych z serwera?
- czy treść podstron jest dostępna dla robotów, które nie interpretują JavaScriptu?
- czy wyszukiwarka ma szanse zwrócić dobre wyniki wyszukiwania?
- czy stronę można dodać do zakładek?
- jaka jest liczba przygotowywanych podstron oraz stosowanych adresów URL?
- czy występują adresy fragmentaryczne, które należy ukrywać?
- jak rozwiązanie wpływa na transfer danych?
Dostępność dla robotów jest tożsama z działaniem przy wyłączonym JavaScripcie, zaś kwestie transferu należy osobno rozpatrywać dla stron przy włączonym, a osobno przy wyłączonym JavaScripcie.
Tabela znajdująca się poniżej zawiera pełną charakterystykę omówionych przykładów. Podany transfer należy traktować orientacyjnie. Duże znaczenie będzie miała liczba opcji menu, rozmiar kodu HTML każdej opcji, jak również to, które podstrony i ile razy zostaną pobrane.
W zależności czy przygotowywany dokument będzie publikowany w sieci czy umieszczany na płycie CD, otrzymamy zupełnie inne wymagania.
Odnośnie dokumentów publikowanych w internecie najlepszym wydaje mi się rozwiązanie drugie: tradycyjne hiperłącza wzbogacone o przeładowanie fragmentu wykorzystujące Ajax. Witryna działa przy wyłączonym JavaScripcie, jest dostępna dla robotów, a transfer zostaje zminimalizowany. Niestety, dodawanie podstron do zakładek przeglądarki nie będzie działało poprawnie.
W przypadku stron nagrywanych na CD rozwiązaniami równorzędnymi są czwarte oraz szóste.