R-21-07, Programowanie, ! HTML, HTML 4 - Vademecum


Rozdział 21.
Użycie
Dynamicznego HTML-a

W poprzednim rozdziale dowiedziałeś się, jak można tworzyć formularze służące do zbierania informacji od osób odwiedzających witrynę WWW. Pod różnymi postaciami formularze były dostępne od samego początku istnienia języka HTML, a ich działanie i wygląd jest niemal identyczne we wszystkich rodzajach przeglądarek. W rzeczywistości nie musisz się zbytnio przejmować tym, kto będzie, a kto nie będzie mógł poprawie wyświetlić witryny.

W tym rozdziale zostawimy za sobą stosunkowo spokojne wody formularzy i obierzemy kurs na burzliwe morza Dynamicznego HTML-a. A zatem, przygotuj się dobrze!

Dynamiczny HTML udostępnia całkowicie unikalną możliwość, pozwala bowiem na modyfikowanie stron WWW w czasie, gdy są one wyświetlane w przeglądarce. Przy użyciu standardowego języka HTML strony WWW są pobierane przez przeglądarkę, wyświetlane i pozostają w niezmienionej postaci, aż do momentu kliknięcia hiperpołączenia lub przesłania formularza. To bardzo prosty schemat działania, który jest jednak dosyć statyczny i nieco nużący.

Twórcy witryn starali się ulepszać statyczne strony WWW, używając wielu różnych technologii, wykraczających poza ramy języka HTML. Przez długie lata skrypty CGI stanowiły metodę zapewnienia interakcji z użytkownikami odwiedzającymi strony WWW. Można także umieszczać w stronach specjalne pliki obsługiwane przez aplikacje Shockwave oraz Flash zapewniające możliwość wyświetlania animacji i prowadzenia interakcji z użytkownikami. Możliwości funkcjonalne porównywalne z aplikacjami dają aplety pisane w języku Java oraz komponenty ActiveX. Jednak wszystkie te metody wymagają użycia specjalnych dodatków lub „wirtualnych maszyn” (co może być dosyć trudne) i zazwyczaj wydłużają czas ładowania strony.

Dynamiczny HTML to jednak coś zupełnie innego. Powszechnie wiadomo, że DHTML pozwala tworzyć strony WWW, które wyglądają i działają, podobnie jak zwyczajne programy używane na komputerze, przy czym interfejsem użytkownika jest przeglądarka WWW, a dodatkowo wykorzystywane są zewnętrzne rozwiązania programistyczne. Czy wyobrażasz sobie, jakie to daje możliwości?

Mam nadzieję, że tak, gdyż przyda Ci się ten entuzjazm, aby poradzić sobie z wadami DHTML-a. Szczerze mówiąc, wprowadzają one czasami wiele zamieszania. Aby dotrzeć do jak najszerszej publiczności (oczywiście w rozsądnych granicach), należy wziąć pod uwagę różnice pomiędzy poszczególnymi przeglądarkami oraz sposobem implementacji różnych technologii internetowych, takich jak HTML, kaskadowe arkusze stylów oraz skrypty.

W tym rozdziale znajdziesz bardzo wiele informacji, a zatem zabierzmy się do pracy. W tym rozdziale:

Czym w zasadzie jest DHTML?

Najprościej rzecz ujmując, Dynamiczny HTML używa elementów klasycznego języka HTML w celu tworzenia stron WWW, w których postać i położenie elementów określane są za pomocą kaskadowych arkuszy stylów i których zawartość oraz wygląd można zmieniać przy użyciu skryptów, bez konieczności ponownego pobierania strony z serwera. Dynamiczny HTML nie jest pojedynczym rozwiązaniem, to grupa techno-logii, które można wykorzystywać do uzyskania efektów interaktywności. Azatem co można zrobić, wykorzystując DHTML? Możliwości są wręcz nieskończone! Poniżej podam kilka z nich, aby dodatkowo wzbudzić Twoje zainteresowanie:

Dynamiczny HTML pojawił się w momencie udostępnienia tak zwanych „czwórek”. World Wide Web Consortium (W3C) udostępniło HTML 4 oraz wydało jego oficjalną rekomendację mniej więcej w tym samym czasie, gdy na rynku pojawiły się czwarte wersje przeglądarek współzawodniczących ze sobą firm Netscape oraz Microsoft, czyli Netscape Navigator 4 oraz Internet Explorer 4. W tym czasie przypada okres największej aktywności związanej z rozwojem HTML. Czwarta wersja tego języka promowała kilka nowych możliwości, które miały zapewnić lepszą integrację z CSS —kaskadowymi arkuszami stylów oraz usprawnioną obsługę zdarzeń generowanych przez czynności wykonywane przez użytkownika. Firmy Microsoft i Netscape bardzo mocno współzawodniczyły ze sobą w „wojnie przeglądarek”, prowadzonej o zdobycie jak największego udziału na rynku. Jednak wynik tej batalii był zupełnie inny, w efekcie doprowadziła ona do powstania poziomu interaktywności stron WWW, który wcześniej mogło zapewnić wyłącznie użycie oprogramowania niezależnego od przeglądarek. Tak właśnie powstał DHTML.

0x01 graphic

Dynamiczny HTML (DHTML) to grupa technologii rozszerzających interaktywność oraz dynamizm stron WWW, bez konieczności wykorzystania zewnętrznych obiektów bądź programów.

Aby możliwe było wykorzystanie DHTML, przeglądarka WWW musi obsługiwać trzy kluczowe technologie internetowe:

Konieczność użycia języka HTML jest zupełnie oczywista. Pamiętaj jednak, że HTML 4 wprowadzał nowe elementy, takie jak div i span oraz atrybuty, takie jak id oraz name. Te znaczniki i atrybuty pozwalają na lepszą strukturalizację i łatwiejsze formatowanie stron WWW, a jednocześnie zapewniają lepszą integrację z arkuszami stylów oraz ułatwiają możliwości manipulowania elementami stron przy użyciu skryptów. Niemniej jednak to poszerzenie możliwości języka miało swoje wady. Nawet jeszcze dzisiaj nie wszyscy twórcy najczęściej używanych przeglądarek w spójny sposób zaimplemen-towali język HTML 4. Ten wątek bardzo często będzie się pojawiał w tym rozdziale.

0x01 graphic

Największym wyzwaniem, wiążącym się z użyciem DHTML, jest ominięcie wszelkich różnic występujących nie tylko w języku HTML, lecz także we wszystkich innych technologiach związanych z DHTML. Tylko w ten sposób można bowiem tworzyć strony działające identycznie we wszystkich przeglądarkach. To zadanie, choć trudne, jest jednak wykonalne.

Arkusze stylów są wspaniałym narzędziem, zwłaszcza gdy nauczysz się z nich korzystać; stanowią także kluczowy element DHTML. Choć z technicznego punktu widzenia, DHTML nie jest zależny od żadnego konkretnego typu arkuszy stylów, to jednak standardem jest oficjalna technologia W3C, czyli kaskadowe arkusze stylów (CSSCascading Style Sheets). Arkusze stylów CSS poziomu 2 (CSS2) pozwalają na formatowanie elementów stron WWW przy użyciu właściwości określających takie parametry wyglądu, jak kolor, wielkość, czcionka, odstępy oraz położenie elementu na stronie. Dokładniejszy opis CSS znajdziesz w rozdziale 10. — „HTML i arkusze stylów”.

DHTML przenosi jednak arkusze stylów na nowy, wyższy poziom. Wcześniej tworzyłeś reguły stylów lub umieszczałeś element strony w konkretnym miejscu i zapominałeś o nim. Teraz, dzięki DHTML, możesz dynamicznie zmieniać styl elementu oraz jego położenie. Wciąż jednak istnieją różnice pomiędzy implementacjami CSS w Internet Explorerze oraz Netscepe Navigatorze. W obu przeglądarkach implementacja specyfikacji CSS nie tylko nie jest pełna, lecz co gorsza, jej zaimplementowane fragmenty różnią się od siebie. Okropność!

Ostatnim elementem, stanowiącym rodzaj spoiwa łączącego wszystkie części składające się na DHTML, są technologie skryptowe. Dzięki możliwości uruchamiania skryptów w momencie załadowania strony, w odpowiedzi na poczynania użytkownika a nawet po opuszczeniu witryny, technologie te zapewniają dynamiczny charakter DHTML.

0x01 graphic

Jeśli nie w pełni zrozumiałeś, co miałam na myśli, mówiąc o „niespójnych implementacjach standardów w poszczególnych przeglądarkach”, to spieszę wyjaśnić, iż właśnie ze względu na te różnice poleganie na „oficjalnych” specyfikacjach standardów DHMTL jest bardzo niebezpieczne. Oznacza to, że zawsze należy przeczytać dokumentacją przeglądarki, na której mają być wyświetlane strony WWW i sprawdzić, czy dana przeglądarka obsługuje rozwiązania, których chcesz użyć.

Najczęściej stosowanym językiem skryptowym jest JavaScript. Był to pierwszy język skryptowy używany do obsługi stron WWW i aktualnie jest obsługiwany przez największą ilość różnych przeglądarek. Choć można tworzyć rozwiązania DHTML, wykorzystując inne języki skryptowe, takie jak VBScript, to polecałabym raczej użycie języka JavaScript, chyba że tworzony produkt przeznaczony jest do środowiska, w którym wykorzystywana jest wyłącznie przeglądarka firmy Microsoft (z czym się w praktyce jeszcze nigdy nie spotkałam).

Gdy przedstawię przykłady wykorzystania DHTML, przekonasz się, że w większości przypadków polega ono na tworzeniu skryptów modyfikujących styl elementów stron WWW, ich położenie oraz wykonujących różnego typu obliczenia gwarantujące „dynamizm” stron. Z tego względu, w dalszej części rozdziału umieściłam krótkie omówienie języka JavaScript. Choć bez wątpienia nie jest to wyczerpujące omówienie języka JavaScript, to jednak powinno Ci pozwolić przeanalizować i zrozumieć podane przykłady.

I jeszcze dwie, ostatnie informacje dotyczące tego, czym jest DHTML. DHTML (a w za-sadzie jego skryptowa część) bazuje na wykorzystaniu modelu obiektów dokumentu (DOMDocument Object Model). Służy on do identyfikacji, tworzenia i manipulowania obiektami umieszczonymi na stronie WWW. Na przykład, aby móc manipulować jakimkolwiek elementem strony WWW, dajmy na to obrazkiem, musisz go najpierw zidentyfikować. Podobnie, konieczne jest określenie stylu elementu strony, aby można go było zmienić. Do tego właśnie służy DOM. Stanowi on swoisty pomost łączący skrypt oraz elementy strony WWW. Choć W3C aktualnie pracuje nad oficjalną specyfikacją DOM, to jednak każda z przeglądarek opracowała swój własny, unikalny DOM. W dalszej części rozdziału omówiłam różne wersje DOM.

Do śledzenia czynności wykonywanych przez przeglądarkę oraz poczynań użytkownika, DHTML wykorzystuje obsługę zdarzeń. Po załadowaniu strony generowane jest zdarzenie onLoad. Podobnie, gdy użytkownik kliknie przycisk umieszczony na formularzu, generowanych jest kilka zdarzeń, które Ty, jako autor stron DHTML, możesz wykorzystać do uruchomienia odpowiednich skryptów. Jak niemal wszystkie aspekty DHTML, także i obsługa zdarzeń w przeglądarkach Microsoft Internet Explorer oraz Netscape Navigator została zaimplementowana w całkowicie odmienny sposób. Zagadnienia związane z obsługą zdarzeń omówię szczegółowo w dalszej części rozdziału.

Prezentacja języka JavaScript

JavaScript jest językiem skryptowym opracowanym przez firmy Netscape oraz Sun Microsystems (w której powstał język Java). Jego przeznaczeniem jest udostępnienie możliwości funkcjonalnych, których nie daje sam język HTML. HTML jest bowiem językiem formatowania dokumentu i sam w sobie nie dysponuje żadnymi mechanizmami umożliwiającymi wykonywanie zadań „programistycznych”. Weźmy, na przykład, poniższy fragment kodu HTML:

<img src="obrazek.gif" height="100" width="300" />

Powyższy kod HTML informuje przeglądarkę, iż ma wyświetlić obrazek zapisany w pliku obrazek.gif, w obszarze o szerokości 300 i wysokości 100 pikseli. Jeśli się nad tym głębiej zastanowisz, to dojdziesz to wniosku, iż jest to dosyć poważne ograniczenie. Oprócz hiperpołączeń oraz elementów formularzy, nie można bowiem manipulować żadnymi informacjami oraz obiektami wyświetlonymi na stronie WWW, ani odpowiadać na poczynania użytkowników.

0x01 graphic

JavaScript to język pozwalający na pisanie skryptów, niewielkich programów, których nie trzeba kompilować, umieszczanych w stronach WWW i wykonywanych przez przeglądarkę.

Języki skryptowe, a w szczególności JavaScript, mają całkowicie odmienne zadanie niż język HTML. Z założenia są to bowiem języki programowania. Oznacza to, że skrypty mogą przeprowadzać obliczenia, manipulować obiektami oraz odpowiadać na przeróżne czynności wykonywane przez użytkownika. Na przykład, skrypty mogą sprawdzać poprawność danych wpisanych w formularzach HTML, odpowiadać na czynności wykonywane przy użyciu myszy i klawiatury oraz dynamicznie zmieniać położenie i styl elementów wyświetlanych na stronach WWW.

W odróżnieniu od formalnych języków programowania, takich jak C, C++ oraz Java, języki skryptowe nie wymagają kompilacji programów do postaci kodu maszynowego przed ich wykonaniem. Skrypty są pisane w formie zwyczajnego tekstu, za ich interpretację i wykonanie odpowiada program, a nie procesor komputera. W przypadku stron WWW programem odpowiedzialnym za interpretację i wykonanie skryptów umieszczonych lub dołączonych do strony WWW jest przeglądarka. Skrypty są interpretowane i wykonywane podczas ładowania strony.

0x01 graphic

To bardzo ważna informacja, którą warto powtórzyć i zapamiętać. Niektóre starsze modele przeglądarek nie są w stanie wyświetlać wielu nowych elementów dostępnych w języku HTML 4. Podobnie nie wszystkie przeglądarki są w stanie interpretować najnowsze wersje języka JavaScript. Pamiętaj, że za wykonanie skryptu odpowiada przeglądarka. Nie będziesz w stanie zmusić przeglądarki do wykonania skryptu, którego nie rozumie.

Podstawy języka JavaScript

Niestety, w tak krótkim rozdziale nie jestem w stanie przekazać wszystkich informacji dotyczących języka JavaScript. Będę się jednak starała, aby przekazane informacje pozwoliły Ci zrozumieć zasady działania języka, abyś mógł przeanalizować podane przykłady i zrozumieć sposób ich działania.

W zasadzie skrypty są sekwencją instrukcji, które informują program wykonujący skrypt (w naszym przypadku jest to przeglądarka), jakie czynności należy wykonać. Instrukcjami tymi mogą być proste polecenia określające wartość zmiennej, na przykład:

var x = 14;

lub bardziej złożone konstrukcje, takie jak definicje funkcji:

function init() {

if (x == 14) {

alert(x);

}

else {

alert("X jest różne od 14!");

}

}

Zwróć uwagę, iż każda instrukcja jest zakończona znakiem średnika (;). Dodatkowo instrukcje można grupować, zapisując je wewnątrz nawiasów klamrowych ({}). W przedstawionym powyżej fragmencie kodu nawiasy klamrowe zostały użyte do zgrupowania instrukcji w funkcji o nazwie init(). Nawiasy klamrowe zostały także wykorzystane w instrukcjach if oraz else, gdzie służą do określenia kodu przynależnego do każdej z tych instrukcji.

W kodzie skryptów pisanych w języku JavaScript można także umieszczać informacje, które nie będą interpretowane. Są to tak zwane komentarze. Służą do wyjaśniania przeznaczenia i sposobu działania fragmentów skryptu. Komentarze obejmujące jedną linię tekstu rozpoczynają się od dwóch znaków ukośnika (//). Można je umieszczać na samym początku linii, na przykład:

// Ta zmienna służy do przechowywania informacji tymczasowych

var x;

lub po zakończeniu instrukcji, jak pokazałam na poniższym przykładzie:

var x; // Zmienna pomocnicza

Interpreter skryptu pomija wszystkie znaki umieszczone po dwóch znakach ukośnika, należy zatem być ostrożnym i nie poprzedzać komentarzem żadnego istotnego kodu.

Przy użyciu jednoliniowych komentarzy można także tworzyć długie bloki komentarzy, takie jak ten przedstawiony poniżej:

// Skrypt stworzony 9 października 1999 roku

// Copyright HELION

// Wszystkie prawa zastrzeżone

Innym rozwiązaniem jest użycie specjalnych komentarzy wieloliniowych. Tworzy się je, umieszczając w pierwszej linii komentarza kombinację znaków składającą się ze znaku ukośnika i gwiazdki (/*) oraz kończąc komentarz kombinacją znaków: gwiazdka, ukośnik (*/). Taki wieloliniowy komentarz przedstawiłam na poniższym przykładzie:

/* Skrypt stworzony 9 października 1999 roku

Copyright HELION

Wszystkie prawa zastrzeżone */

Jednym z najwygodniejszych narzędzi programistycznych są zmienne. Pozwalają one na zapisanie wartości w umownym „pojemniku” i operowanie na danych poprzez odwoływanie się do tych „pojemników”. Aby zadeklarować zmienną, wystarczy podać słowo kluczowe var a po nim nazwę zmiennej, na przykład:

var mojaZmienna;

0x01 graphic

W języku JavaScript uwzględniana jest wielkość znaków, oznacza to, że zmienna mojaZmienna to nie to samo co mojazmienna ani Mojazmienna.

Równie łatwo można zadeklarować zmienną i jednocześnie zapisać w niej wartość. W tym przypadku należy posłużyć się kodem o następującej postaci:

var mojaZmienna = 1999;

JavaScript udostępnia także operatory pozwalające na przeprowadzanie obliczeń matematycznych oraz porównań. Najczęściej stosowane operatory oraz ich działanie opisałam w tabeli 20.1.

Tabela 21.1.

Najczęściej używane operatory matematyczne oraz operatory porównań

Operatory matematyczne

Operatory porównania oraz logiczne

Symbol

Opis

Symbol

Opis

+

Dodawanie

=

Przypisanie

-

Odejmowanie

==

Równy

*

Mnożenie

<

Mniejszy niż

/

Dzielenie

>

Większy niż

++

Inkrementacja (+1)

<=

Mniejszy lub równy

--

Dekrementacja (-1)

>=

Większy lub równy

!=

Różny

&&

Logiczna koniunkcja (AND)

||

Logiczna alternatywa (OR)

Przedstawiony poniżej fragment kodu deklaruje trzy zmienne, określa wartości dwóch spośród nich, a następnie przypisuje trzeciej zmiennej sumę wartości dwóch pozostałych zmiennych:

var xPos = 142;

var yPos = 15;

var Pos;

Pos = xPos + yPos;

Aby powiększyć (inkrementować) lub pomniejszyć (dekrementować) o jeden wartość zmiennej, należy użyć odpowiedniego operatora wraz z nazwą zmiennej, jak pokazałam w poniższym przykładzie:

Pos++;

Poniższa instrukcja powiększa o jeden wartość zmiennej Pos.

Do porównywania wartości służą operatory logiczne.

if (Pos == 150) {

wywołajInnąFunckję();

}

I tak dotarliśmy do kolejnego, niesłychanie ważnego punktu: rozgałęzień warunkowych. Najpopularniejszą instrukcją tego typu dostępną w języku JavaScript jest instrukcja if. Można jej użyć do porównania dwóch wartości (lub przeprowadzenia kilku porównań) i wykonania odpowiednich czynności w zależności od wyniku porównania. Przedstawiony powyżej fragment kodu porównuje wartość zmiennej Pos z liczbą 150. Jeśli wartość zmiennej jest równa 150, to wykonywany jest kod umieszczony w nawiasach klamrowych. Jeśli jednak wartość zmiennej nie będzie równa 150, to skrypt będzie wykonywany dalej, jakby się nic nie stało. Gdy chcesz obsłużyć wszystkie możliwe sytuacje, to możesz wykorzystać kilka instrukcji if lub posłużyć się instrukcją else, przedstawioną w poniższym przykładzie:

if ((Pos >= 150) && (Pos <= 200)) {

funkcja1();

}

else {

funkcja2();

}

W instrukcji if wartość zmiennej Pos jest porównywana z dwiema wartościami: 150 oraz 200. Jeśli wartość zmiennej jest większa lub równa 150 i jednocześnie mniejsza lub równa 200 (innymi słowy, jeśli wartość zmiennej Pos należy do przedziału od 150 do 200), to zostanie wykonana funkcja1. Jeśli warunek logiczny umieszczony w instrukcji if nie zostanie spełniony, to zostanie wykonana funkcja2.

0x01 graphic

Rozgałęzienia warunkowe dają możliwość utworzenia kilku alternatywnych ścieżek wykonania skryptu. Ścieżka, według której zostanie wykonany skrypt, będzie wybrana na podstawie wartości zwróconej przez wyrażenie logiczne, jak, na przykład, (X > Y).

Podczas wykonywania obliczeń i porównań można używać nawiasów; służą one do grupowania wartości i zmiennych oraz umożliwiają określenie kolejności, w jakiej należy wykonać obliczenia lub porównania. W poniższym przykładzie wyrażenia Pos >= 150 oraz Pos <= 200 są interpretowane w pierwszej kolejności, a następnie ich wyniki są ze sobą porównywane przy użyciu logicznego operatora AND:

((Pos >= 150) && (Pos <= 200))

Podobnie przy obliczaniu wartości wyrażenia:

(((156 * 4 / 24) + 99) * 24)

są uwzględniane nawiasy. W tym przypadku liczba 156 jest mnożona razy 4, następnie iloczyn obu liczb jest dzielony przez 24. Do otrzymanej wartości jest następnie dodawana liczba 99, a otrzymany wynik jest mnożony przez 24. W wyniku otrzymujemy liczbę 3000 (która przez całkowicie nieprawdopodobny, choć szczęśliwy przypadek, jest całkiem „okrągłą” liczbą).

0x01 graphic

Jeśli spotkasz się z wyrażeniami zawierającymi wiele poziomów zagnieżdżonych nawiasów, powinieneś je analizować od wewnątrz. Tworząc takie skomplikowane wyrażenia, pamiętaj także, iż liczba nawiasów zamykających musi odpowiadać liczbie nawiasów otwierających.

Prócz skomplikowanych wyrażeń nawiasy są także używane przy tworzeniu oraz wywoływaniu funkcji. W tym przypadku, w nawiasach podaje się parametry, tak zwane argumenty, konieczne do wykonania funkcji. W poniższym przykładzie przedstawiona została prosta funkcja, wyświetlająca okienko dialogowe prezentujące wartość zmiennej uzytkownik, która w tym przypadku zawiera łańcuch znaków Laura:

var uzytkownik = "Laura";

function wyswietlUzytkownika(uzytkownik) {

alert(uzytkownik);

}

Aby wywołać tę funkcję, wystarczy podać w skrypcie jej nazwę oraz umieszczoną w nawiasach nazwę zmiennej uzytkownik:

wyswietlUzytkownika(uzytkownik);

Wiele funkcje nie ma żadnych argumentów, jednak przy ich tworzeniu i tak trzeba wpisać nawiasy. Na przykład, podana poniżej funkcja init() nie wymaga podania żadnych argumentów, lecz w jej wywołaniu i tak trzeba będzie umieścić parę nawiasów.

function init() {

tworzTablice();

animujTytul();

}

I tak oto dotarliśmy do kolejnego zagadnienia, którym są funkcje. Zazwyczaj skrypty są wykonywane od góry do dołu, w kolejności, w jakiej zostały podane poszczególne instrukcje. Funkcje pozwalają jednak na złamanie tego naturalnego toku wykonywania skryptu i stworzenie bloków kodu wywoływanych wyłącznie w momencie jawnego odwołania się do nich z innej części skryptu. Przyjrzyj się ostatniemu podanemu przykładowi. Funkcja init() jest oddzielona od pozostałej części skryptu i jest wykonywana wyłącznie w momencie, gdy zostanie wywołana. Właśnie dlatego przy pisaniu skryptów funkcje są używane do kontroli przebiegu wykonywania skryptu oraz odpowiadania na unikalne zdarzenia.

0x01 graphic

Funkcja to blok kodu oddzielony od normalnego toku wykonywania skryptu. Funkcje są wykonywane wyłącznie w przypadku ich jawnego wywołania z innej części skryptu lub z kodu strony HTML.

Jeśli jeszcze nie zauważyłeś, to chciałam Ci zwrócić uwagę, iż funkcje tworzy się, podając słowo kluczowe function oraz nazwę funkcji. Pamiętaj także o podaniu pary nawiasów, otwierającego i zamykającego, w których zapisywana jest lista argumentów. Nawiasy te należy podać nawet, jeśli konkretna funkcja nie pobiera żadnych argumentów. Za listą argumentów należy zapisać otwierający nawias klamrowy. Po nim podawane są wszelkie instrukcje, które funkcja ma wykonać. Później należy zakończyć ją zamykającym nawiasem klamrowym.

Wewnątrz funkcji można umieszczać dowolne instrukcje, na przykład, instrukcję warunkową if lub pętle:

function okreslPolozenie() {

if ((Pos >= 150) && (Pos <= 200)) {

funkcja1();

}

else {

funkcja2();

}

}

Upewnij się, że ilość otwierających i zamykających nawiasów klamrowych użytych wewnątrz funkcji jest identyczna. W powyższym przykładzie jedna para nawiasów klamrowych rozpoczyna i kończy funkcję okreslPolozenie. Wewnątrz niej instrukcje if oraz else także mają po jednej parze odpowiadających sobie nawiasów klamrowych. A zatem wszystko się zgadza. Są trzy otwierające nawiasy klamrowe oraz trzy nawiasy zamykające. W przeciwnym przypadku, gdyby ilość nawiasów zamykających nie odpowiadała ilości nawiasów otwierających, podczas wykonywania skryptu zostałby zgłoszony błąd.

Jak na razie poznałeś podstawy składni języka JavaScript oraz kilka bardziej szczegółowych informacji na jego temat. Umiesz dodawać wartości i zapisywać je w zmiennych, musisz nauczyć się, jak napisać jakikolwiek przydatny skrypt. Brakującym ogniwem jest obiekt. Obiekty to proste kolekcje właściwości i metod. Należy je sobie wy­obrazić jako „pojemniki” przechowujące informacje i jednocześnie wyposażone w sposoby manipulowania nimi.

0x01 graphic

Obiekty to kolekcje właściwości i metod, które przechowują informacje oraz dysponują możliwością manipulowania nimi.

Właściwości opisują obiekt, natomiast metody udostępniają możliwości manipulowania właściwościami z poziomu skryptu. Załóżmy, że dysponujemy obiektem o nazwie Samochod. Obiekt ten może posiadać takie właściwości, jak kolor, rok oraz wartosc. Obiekt może także posiadać metodę obliczającą jego wartość na podstawie roku produkcji. Aby odwołać się do obiektu należy podać jego nazwę, kropkę, a następnie nazwę właściwości. I tak, aby przypisać wartość niebieski właściwości kolor obiektu Samochod, należy posłużyć się następującym fragmentem kodu:

Samochod.kolor = "niebieski";

Aby wywołać metodę, należy podać jej nazwę po nazwie obiektu, jak pokazałam na poniższym przykładzie:

Samochod.obliczWartosc();

Omawiamy technologię skryptową przeznaczoną do obsługi WWW, a zatem większość obiektów zawiera właściwości i metody związane z przeglądarką oraz dokumentami HTML. Jednym z najważniejszych obiektów jest document. Zawiera on informacje dotyczące dokumentu HTML wyświetlonego w przeglądarce, posiada metody umożliwiające odpowiadanie na poczynania użytkownika oraz jest w stanie wykonywać inne czynności.

Niestety, w tym miejscu sprawy się komplikują. Każda przeglądarka definiuje bowiem grupę odmiennych obiektów, które posiadają różne właściwości i metody. Co więcej, każda przeglądarka dysponuje zbiorem procedur obsługi zdarzeń, służącym do obsługi czynności wykonywanych przez użytkownika, na przykład, kliknięcia myszą lub naciśnięcia klawisza.

0x01 graphic

W przeglądarce Netscape Navigator nie wszystkie obiekty dysponują wszystkimi procedurami obsługi zdarzeń. A zatem, aby określić, jakie procedury obsługi zdarzeń są dostępne w konkretnych obiektach, powinieneś przejrzeć dokumentację języka JavaScript zaimplementowanego w przeglądarce Netscape Navigator.

Dostępne obiekty oraz zdarzenia różnią się od siebie w poszczególnych typach przeglądarek, dlatego też omówię te zagadnienia bardziej szczegółowo w dalszej części rozdziału. Najpierw jednak przedstawię sposób umieszczania skryptów w dokumentach HTML.

Umieszczanie skryptów w dokumentach HTML

Oczywiście JavaScript to nie to samo co HTML. Są to dwa całkowicie odmienne języki, przeznaczone do zupełnie innych celów. Nie można umieszczać skryptów w dokumentach HTML, ot tak sobie i oczekiwać, że przeglądarka sama domyśli się, co należy z nimi zrobić. Pierwszą rzeczą, jaką należy wykonać, jest określenie domyślnego języka skryptowego. Służy do tego znacznik meta umieszczany w nagłówku dokumentu:

<meta http-equiv="Content-Script-Type" content="text/javascript" />

Choć użycie znacznika meta jest opcjonalne, to jednak, stosując go, można zapewnić, że przeglądarka będzie wiedziała, iż wszystkie skrypty są napisane w języku JavaScript i będą odpowiednio interpretowane. To domyślne założenie, co do użytego języka skry-ptowego można zmienić, określając język w konkretnym skrypcie.

To rozróżnienie jest niesłychanie istotne, gdyż nie należy dopuścić do sytuacji, w której przeglądarka będzie miała jakiekolwiek wątpliwości, jakiego języka skryptowego użyto. Teraz możemy się już zająć umieszczaniem skryptów w dokumentach HTML.

Skrypty napisane w języku JavaScript można umieszczać w dokumentach HTML na trzy różne sposoby:

Zdarzenia wewnętrzne są generowane, gdy na stronie WWW coś się stanie. Na przykład, znacznik body dysponuje wewnętrznym zdarzeniem o nazwie onload, które jest generowane, gdy dokument zostanie pobrany przez przeglądarkę. Te zdarzenia są podawane jako atrybuty znaczników HTML. Wartością takiego atrybutu może być pojedyncza instrukcja skryptu lub cała seria instrukcji. Na przykład, przedstawiony poniżej fragment kodu HTML definiuje zdarzenie onload znacznika body i określa, że w momencie zgłoszenia tego zdarzenia należy wykonać pojedynczą instrukcję powodującą wyświetlenie okienka informacyjnego:

<body onload="alert('Strona została załadowana.')">

Zauważ, że cała instrukcja wpisanego skryptu jest zapisywana pomiędzy dwoma znakami cudzysłowu, z tego względu wszystkie łańcuchy znaków, umieszczone wewnątrz niej, muszą być oznaczane przy użyciu znaków apostrofu. Pierwszy znak cudzysłowu rozpoczyna wartość atrybutu; kolejny odnaleziony cudzysłów zostanie potraktowany przez przeglądarkę jako zakończenie tej wartości. Jeśli przez pomyłkę wpisałbyś podany poniżej fragment kodu, to cały skrypt miałby postać alert(, a z pewnością nie o to Ci chodziło.

<body onload="alert("Strona została załadowana. ")">

0x01 graphic

Rozpatrując wewnętrzne zdarzenia, nie należy sugerować się oficjalną specyfikacją W3C. Choć wymienia ona wiele zdarzeń, które można stosować z konkretnymi elementami, to trzeba pamiętać, iż implementacja tych możliwości funkcjonalnych w całości zależy od przeglądarki. W szczególności dotyczy to przeglądarki Netscape Navigator, która nie obsługuje bardzo wielu zdarzeń wewnętrznych dostępnych w Internet Explorerze. Niestety, w znacznym stopniu utrudnia to tworzenie dokumentów DHTML przeznaczonych dla przeglądarki Netscape Navigator.

Obsługując zdarzenia wewnętrzne, można także użyć sekwencji kilku instrukcji. Spójrz na poniższy przykład:

<body onload="var tekst = 'Strona została załadowana.'; alert(tekst)">

W tym niewielkim skrypcie obsługującym zdarzenie onload umieszczone zostały dwie instrukcje. Pierwsza z nich deklaruje zmienną i przypisuje jej podany łańcuch znaków, natomiast druga wyświetla okienko dialogowe zawierające podany komunikat.

Drugą metodą umieszczania skryptów w dokumentach HTML jest zapisanie ich wewnątrz znacznika head lub body. W tym przypadku kod skryptu umieszczany jest wewnątrz specjalnego znacznika script; typ skryptu określany jest przy użyciu atrybutu type lub language tego znacznika. Oba te atrybuty spełniają tę samą funkcję, czyli informują przeglądarkę, jaki język skryptowy został użyty. Choć oficjalny standard zaleca użycie atrybutu type, to atrybut language jest częściej stosowany. Ja jednak zachęcam do używania obu tych atrybutów jednocześnie, gdyż w niczym to nie przeszkadza:

<script type="text/javascript" language="javascript">

Kod skryptu podawany jest po otwierającym znaczniku script, na zakończenie skryptu wpisujemy zamykający znacznik script.

<head>

<title>Przykładowy skrypt</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" /> <script type="text/javascript" language="javascript">

var komunikat = "Strona została załadowana.";

alert(komunikat);

</script>

</head>

Choć powyższy skrypt będzie poprawnie działał w przeglądarkach dysponujących moż­liwością wykonywania skryptów, to jednak powszechnie stosowaną praktyką jest umieszczenie kodu skryptu wewnątrz komentarzy języka HTML, jak pokazałam w poniższym przykładzie:

<script type="text/javascript" language="javascript">

<!-- Ukrywa skrypt w starszych przeglądarkach

var komunikat = "Strona została załadowana.";

alert(komunikat);

// zakończ ukrywanie skryptu -->

</script>

Zwróć szczególną uwagę na ostatnią linię skryptu. Rozpoczyna się od komentarza języka JavaScript, umieściłam go tam, aby zapewnić, że interpreter JavaScriptu nie potraktuje tej linii jako kodu skryptu. Gdybym nie użyła komentarza, to interpreter potraktowałby zawartość linii jako kod skryptu i spróbował go wykonać:

zakończ ukrywanie skryptu -->

Inną metodą zapewnienia zgodności ze starszymi wersjami przeglądarek jest użycie znacznika noscript. Znacznik ten umożliwia stworzenie alternatywnej wersji dokumentu, przeznaczonej dla przeglądarek, które nie są w stanie wykonywać skryptów. Alternatywną wersję strony należy rozpocząć od otwierającego znacznika noscript, po którym można podać kod HTML. Alternatywny blok kodu, kończy się zamykającym znacznikiem noscript, jak pokazałam w poniższym przykładzie:

<script type="text/javascript" language="javascript">

<!-- Ukrywa skrypt w starszych przeglądarkach

var komunikat = "Strona została załadowana.";

alert(komunikat);

// zakończ ukrywanie skryptu -->

</script>

<noscript>

<p>Używasz przeglądarki, która nie obsługuje skryptów.</p>

</noscript>

Zgodnie z informacjami podanymi wcześniej, skrypty można umieszczać wewnątrz znaczników head oraz body. Należy zauważyć, iż kolejność wykonywania skryptów odpowiada kolejności, w jakiej są one umieszczone w dokumencie HTML. Z tego względu, skrypty umieszczone wewnątrz znacznika head zostaną wykonane przed skryptami zapisanymi wewnątrz znacznika body. Jeśli kontrolujesz przebieg wykonywania skryptu, używając w tym celu funkcji, to w bardzo łatwy sposób możesz ominąć tę regułę i zagwarantować, że skrypt zostanie wykonany dokładnie, tak jak sobie tego życzysz.

Ostatnią metodą umieszczania skryptów w dokumentach HTML jest dołączenie zewnętrznego pliku (zapisanego z rozszerzeniem .js). Służy do tego atrybut src znacznika script. Na poniższym przykładzie przedstawiłam sposób dołączenia do dokumentu skryptów zapisanych w dwóch plikach:

<script type="text/javascript" language="javascript" src="detect1.js"> </script>

<script type="text/javascript" language="javascript" src="animate.js"> </script>

Dołączanie zewnętrznych plików zawierających skrypty do dokumentów HTML umożliwia łatwiejsze zarządzanie skryptami wykorzystywanymi przez wiele różnych stron wchodzących w skład witryny.

Teraz już wiesz, jak można umieszczać skrypty w stronach WWW. Aby zakończyć tę część rozdziału chciałabym jeszcze zaznaczyć, iż aktualnie dostępna jest wersja 1.3 języka JavaScript, jednak już wkrótce pojawi się wersja 1.4. W tabeli 21.2 zestawiłam informacje dotyczące wersji języka JavaScript dostępnych w różnych wersjach przeglądarek Netscape Navigator i Microsoft Internet Explorer.

Tabela 21.2.

Wersje języka JavaScript dostępne w przeglądarkach Netscape Navigator oraz Internet Explorer

JavaScript

Navigator

Internet Explorer

1.0

2.0x

3.0x

1.1

3.0x

4.0x

1.2

4.0-4.05

4.0x

1.3

4.06-4.61

5.0x

1.4

niedostępna

niedostępna

0x01 graphic

Z technicznego punktu widzenia przeglądarka Microsoft Internet Explorer nie interpretuje języka JavaScript, lecz język skryptowy JScript, bazujący na języku JavaScript i stworzony przez firmę Microsoft. Powinieneś o tym pamiętać
i nie dać się zaskoczyć. Niemniej jednak wciąż powinieneś pisać skrypty bazujące na dokumentacji języka JavaScript.

Wykorzystanie modelu obiektów dokumentu

Jak już wspominałam wcześniej, obie przeglądarki, Microsoft Internet Explorer oraz Netscape Navigator, dysponują odmiennymi implementacjami modelu obiektów dokumentu. Każdy obiekt umieszczony na stronie WWW (a dodatkowo także wiele obiektów przeglądarki) posiada wiele właściwości (opisujących te obiekty), metod (pozwalających nimi manipulować) oraz procedur obsługi zdarzeń (służących do reakcji na czynności wykonywane przez użytkownika). W dalszej części rozdziału omówię modele obiektów dokumentu dostępne w każdej z przeglądarek i postaram się wskazać ich podobieństwa.

0x01 graphic

Zrozumienie pełnych możliwości, jakie daje DOM, wymaga głębokiej wiedzy, której, niestety, nie jestem w stanie przekazać w niniejszej książce. Niemniej jednak bardzo wiele możesz się nauczyć, kopiując skrypty umieszczone na innych stronach WWW i analizując ich kod, jest to zresztą doskonała metoda nauki wszelkich technologii związanych z WWW.

DOM Netscape Navigatora

DOM Netscape Navigatora w pełni odpowiada modelowi obiektów dokumentu przedstawionemu w oficjalnej specyfikacji JavaScript. To może być niezwykle mylące, zwłaszcza przy tworzeniu dokumentów DHTML, które mają działać w wielu przeglądarkach. Problem wynika z faktu, iż Internet Explorer, interpretując skrypty pisane w języku JavaScript, robi to w kontekście innego, własnego, DOM-u. Innymi słowy, czytając oficjalną dokumentację języka JavaScript, powinieneś zachować dużą ostrożność, gdyż zawarte w niej informacje będą dotyczyły wyłącznie przeglądarki Netscape Navigator.

Oprócz kilku obiektów najwyższego poziomu, takich jak, na przykład, screen, DOM Netscape Navigatora ma postać drzewiastą, w której obiektem najwyższego poziomu jest obiekt window. Reprezentuje on okno przeglądarki lub ramkę wyświetloną w tym oknie. Z tego względu właściwości i metody tego obiektu dotyczą właśnie okna przeglądarki.

Obiekt window posiada kilka obiektów niższego poziomu, a niektóre z nich posiadają własną strukturę obiektów kolejnych, jeszcze niższych poziomów. Jednym z obiektów leżących w hierarchii „poniżej” obiektu window jest obiekt document. Jest to obiekt, który będzie nas najbardziej interesował. Obiekt ten jest tworzony w Netscape Navigatorze przez znacznik body dokumentu HTML, oznacza to, że nie będziesz musiał się niczym przejmować, gdyż zostanie on utworzony automatycznie przez przeglądarkę.

W hierarchii obiektów dokumentu, poniżej obiektu document może się znaleźć bardzo wiele różnego typu innych obiektów, z których każdy będzie posiadał charakterystyczne właściwości i metody. Znaczna większość obiektów, których będziesz używał, odpowiada elementom HTML, takim jak obrazki, obiekty arkuszy stylów czy też elementy formularzy.

Tworząc dokumenty DHTML, wciąż będziesz się odwoływał do obiektu document, z tego względu koniecznie musisz wiedzieć, jak należy to robić. Odwołując się do obiektów w języku JavaScript, należy posługiwać się notacją kropkową i odwoływać się po kolei do każdego obiektu w hierarchii DOM, aż do momentu dotarcia do obiektu docelowego. W poniższym przykładzie przedstawiłam odwołanie do obrazka o nazwie mojobraz:

document.mojobraz

Aby odwołać się do którejkolwiek z właściwości tego obiektu, wystarczy dopisać ją na końcu wyrażenia:

document.mojobraz.src

A teraz spróbuj wykonać bardzo prosty eksperyment. Stwórz stronę WWW zawierającą jeden obrazek. (Możesz mu nadać nazwę użytą przeze mnie w powyższym przykładzie lub jakąkolwiek inną. Pamiętaj tylko, aby podać odpowiednią nazwę w atrybucie src znacznika obrazka.) Obrazek jest umieszczony wewnątrz znacznika body dokumentu HTML. Poniżej obrazka umieścimy skrypt, który wyświetli okienko informacyjne prezentujące szerokość obrazka, określoną atrybutem width znacznika img. W tym przykładzie ważne jest, aby umieścić skrypt po obrazku, gdyż, aby został utworzony odpowiedni obiekt, przeglądarka musi wcześniej załadować obrazek.

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Test DOM w Navigatorze</title>

<meta http-equiv="Content-Script-Type" content="text/javascript"/>

</head>

<body>

<img id="mojobraz" name="mojobraz" src="barn.jpg" height="100" width="150"/>

<script language="JavaScript" type="text/javascript">

<!-- Ukryj kod skryptu

alert(document.mojobraz.width);

// koniec ukrywania -->

</script>

</body>

</html>

Wynikowe okienko dialogowe, wyświetlone przez przeglądarkę Netscape Navigator, zostało przedstawione na rysunku 21.1. Zauważ, że sam obrazek nie został wyświetlony przed pojawieniem się okienka dialogowego.

0x01 graphic

Rysunek 21.1.

Dostęp do właściwości obrazka przy wykorzystaniu języka JavaScript oraz DOM programu Netscape Navigator

0x01 graphic

Dostęp do wszelkich innych właściwości obrazka jest równie prosty, wystarczy zamienić właściwość width na jakąkolwiek inną, na przykład, src.

Aby wywołać którąś z metod obiektu, wystarczy zastąpić nazwę właściwości nazwą metody i dopisać do takiego wyrażenia wszelkie argumenty, których wymaga metoda. Przedstawiony poniżej przykład demonstruje sposób dopisania kodu HTML do wyświetlanej strony, możliwy dzięki wykorzystaniu metody write obiektu document:

document.write("Witaj Świecie!");

Niektóre właściwości, takie jak wysokość obrazka, są przeznaczone wyłącznie do odczytu. Oznacza to, że można pobrać wartość, lecz nie można jej zmienić. Wartości innych właściwości, a w szczególności właściwości CSS (dostępnych w hierarchii DOM bezpośrednio „poniżej” konkretnego obiektu), można modyfikować. Aby zmienić wartość właściwości obiektu, należy podać nazwę tego obiektu oraz właściwości (w taki sam sposób, jak przy odwoływaniu się do właściwości), a następnie zapisać znak równości i wartość przypisywaną właściwości. Instrukcja podana w poniższym przykładzie modyfikuje położenie obiektu obrazka mojobraz, umieszczając go 150 pikseli poniżej górnej krawędzi okna lub poprzedniego elementu, w zależności od tego czy obraz został umiejscowiony względnie, czy bezwzględnie:

document.mojobraz.top = "150";

I jeszcze ostatnia informacja dotycząca modelu obiektów dokumentu Netscape Navigatora. Otóż wszystkie obiekty znajdujące się w hierarchii DOM „poniżej” jakiegoś obiektu, są przechowywane w tablicy. Na przykład, wszystkie obrazki umieszczone na stronie WWW są zapisane we właściwości document.images, która jest tablicą. Pierwszy obrazek umieszczony na stronie jest zapisywany w elemencie tablicy o indeksie 0, a kolejne obrazki — w następnych elementach tablicy. Poniższe wyrażenie pozwala odwołać się do pierwszego obrazka zapisanego w tablicy:

document.images[0].width

Użycie tego wyrażenia w poprzednim przykładzie (wyświetlającym szerokość obrazka w okienku dialogowym), dałoby te same wyniki, czyli spowodowało wyświetlenie wartości 150.

DOM Internet Explorera

Model obiektów dokumentu tworzony w przeglądarkach Internet Explorer 4 oraz 5 także składa się z obiektów posiadających właściwości, metody i zdarzenia. Pod tym względem przypomina on DOM stosowany w Netscape Navigatorze. Różnice pomiędzy modelami obiektów dokumentu obu przeglądarek wynikają jednak z odmiennego sposobu organizacji obiektów oraz sposobu odwoływania się do nich w skryptach.

Podobnie jak Netscape Navigator, także i Internet Explorer posiada obiekt document. Niemniej jednak wszystkie obiekty znajdujące się w hierarchii „poniżej” obiektu document, są umieszczone w kolekcji all; zawiera ona obiekty odpowiadające wszystkich elementom strony WWW. A zatem, aby odwołać się do obrazka w Internet Explorerze, należy użyć wyrażenia o postaci:

document.all.mojobraz

Aby odwołać się do właściwości lub metody, należy dodać ją do nazwy obiektu, zupełnie tak samo, jak w Netscape Navigatorze:

document.all.mojobraz.src

Internet Explorer zupełnie inaczej obsługuje obiekty stylu. Wszystkie odwołania do nich należy poprzedzić właściwością style, zapisaną po nazwie obiektu; dopiero po niej można podać nazwę właściwości stylu:

document.all.mojobraz.style.top

Prezentacje modelu obiektów dokumentu stosowanego w Internet Explorerze chciałabym zakończyć przykładem wyświetlającym szerokość obrazka, w wersji przeznaczonej dla Internet Explorera:

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Test DOM w Internet Explorerze</title>

<meta http-equiv="Content-Script-Type" content="text/javascript"/>

</head>

<body>

<img id="mojobraz" name="mojobraz" src="barn.jpg" height="100" width="150"/>

<script language="JavaScript" type="text/javascript">

<!-- Ukryj kod skryptu

alert(document.all.mojobraz.width);

// koniec ukrywania -->

</script>

</body>

</html>

Wynikowe okienko dialogowe przedstawiłem na rysunku 21.2. Zauważ, iż w Internet Explorerze obrazek jest wyświetlany na stronie przed pojawieniem się okienka dialogowego.

0x01 graphic

Rysunek 21.2.

Dostęp do właściwości obrazka przy wykorzystaniu języka JavaScript oraz DOM programu Internet Explorer

0x01 graphic

Obsługa zdarzeń

Zdarzenia zachodzą w momencie, gdy przeglądarka lub użytkownik wykona jakąś czynność. Znaczenie zdarzeń polega na tym, iż pozwalają na tworzenie skryptów, które reagują na te wykonywane czynności. Niestety, istnieją bardzo poważne różnice pomiędzy sposobami śledzenia i wykrywania zdarzeń w Internet Explorerze oraz Netscape Navigatorze. Ogólnie rzecz biorąc, Netscape Navigator znacznie ogranicza ilość elementów HTML, które mogą wyzwalać zdarzenia. W odróżnieniu od Navigatora, w Internet Explorerze niemal wszystkie elementy HTML mogą generować zdarzenia.

0x01 graphic

Ze względu na ilość zdarzeń oraz różnice ich implementacji w poszczególnych przeglądarkach, nie jestem w stanie podać w niniejszej książce szczegółowych informacji na ich temat. Informacji tych powinieneś szukać w dokumentacjach przeglądarek Netscape Navigator oraz Internet Explorer.

Kolejna różnica pomiędzy obsługą zdarzeń w obu przeglądarkach jest związana z miejscem, w którym zdarzenie jest wykrywane oraz kierunkiem przekazywania zdarzenia w hierarchii obiektów dokumentu (zdarzenie może być przekazywane w górę lub ku dołowi tej hierarchii). W przeglądarce Netscape Navigatorze zdarzenia są wykrywane na samej górze hierarchii obiektów dokumentu, w obiekcie window, po czym są przekazywane ku dołowi hierarchii aż do momentu, gdy zostanie odnaleziona procedura, która je obsłuży. Internet Explorer obsługuje zdarzenia dokładnie w przeciwny sposób, co zresztą chyba już nikogo nie dziwi. W Internet Explorerze zdarzenia wędrują ku górze hierarchii obiektów, jak „bąbelki powietrza”. W tej przeglądarce zdarzenia są wykrywane przez obiekt, który wygenerował zdarzenie (na przykład, obrazek lub element div), po czym są przekazywane ku górze hierarchii obiektów aż do momentu, gdy zostaną obsłużone lub usunięte.

W praktyce oznacza to, że obsługa zdarzeń w przeglądarce Internet Explorer jest stosunkowo prosta i znacznie bardziej skomplikowana w przeglądarce Netscape Navigator.

Walka z rzeczywistością:
techniki DHTML działające w wielu przeglądarkach

Jak do tej pory, znaczna część tego rozdziału zawierała informacje o technologiach wykorzystywanych przez DHTML oraz sposobach ich wykorzystania (niezależnie od pozostałych technologii DHTML). Nadszedł czas, aby rozpocząć tworzenie prawdziwych dokumentów DHTML. Jak już wspominałam, największym wyzwaniem jest tworzenie stron DHTML, które będą mogły być oglądane przez jak największą liczbę użytkowników, przy uwzględnieniu pewnych praktycznych ograniczeń. Użyłam tu słowa „praktycznych”, gdyż stworzenie prawdziwych dokumentów DHTML nie jest możliwe w przeglądarkach, które nie implementują technologii skryptowych lub arkuszy stylów; natomiast w przeglądarkach, w których implementacje tych technologii są jedynie częściowe lub nienajlepsze, tworzenie dokumentów DHTML jest niepraktyczne. Innymi słowy, tworząc dokumenty DHTML, nigdy nie będziesz w stanie dotrzeć do wszystkich użytkowników World Wide Web.

Jest także dobra wiadomość, dzięki doskonałemu zrozumieniu różnic pomiędzy najpopularniejszymi przeglądarkami oraz pomysłowemu pisaniu skryptów, istnieje możliwość stworzenia stron DHTML działających częściowo lub niemal całkowicie, tak jak sobie tego życzysz, we wszystkich przeglądarkach.

Alternatywnym podejściem jest tworzenie różnych wersji strony WWW, przeznaczonych dla różnych przeglądarek. Uważam jednak, że rozwiązanie to nie jest ani praktyczne, ani eleganckie, gdyż prowadzi ono do kilkukrotnego pomnożenia pracy, jaką należy wykonać. Z tego względu w następnych podrozdziałach skoncentruję się na tworzeniu kodu, który będzie działał w wielu różnych przeglądarkach.

Określanie przeglądarki

Przy pisaniu kodu DHTML, który ma poprawnie działać w różnych przeglądarkach, najważniejszym zadaniem jest określenie typu przeglądarki, która wyświetla stronę. Po określeniu typu przeglądarki można wykonać funkcje lub instrukcje zapewniające poprawne działanie skryptu.

Na szczęście nie będziesz musiał sam tworzyć kodu odpowiedzialnego za określanie przeglądarki. Firma Netscape podjęła to trudne zadanie, stworzyła odpowiedni kod i opublikowała go na witrynie DevEdge, pod adresem http://devedge.netscape.com/tech/ dynhtml/index.html . Cały kod listingu można skopiować i bezpłatnie używać we własnych stronach WWW.

W tym rozdziale wykorzystam skróconą wersję skryptu, wykrywającą wyłącznie przeglądarki Netscape Navigator oraz Internet Explorer w wersjach 4 lub wyższych. Fragment skryptu przedstawiony w poniższym przykładzie analizuje odpowiednie obiekty i tworzy zmienne określające typ oraz wersję przeglądarki. W szczególności będą nas interesowały dwie zmienne — is_nav4up oraz is_ie4up — zawierające wartości logiczne true oraz false.

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofera')==-1) &&

(agt.indexOf('compatible')==-1) &&

(agt.indexOf('opera')==-1) &&

(agt.indexOf('webtv')==-1))

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

Aby sprawdzić, czy przeglądarką, w której strona została wyświetlona jest Netscape Navigator lub Internet Explorer w wersji 4 lub wyższej, należy użyć poniższego fragmentu kodu:

if (is_nav4up) { zrób coś ... }

if (is_ie4up) { zrób coś ... }

Jeszcze nie raz zobaczysz te zmienne przy tworzeniu skryptów. Jedynym zadaniem funkcji określającej typ i wersję przeglądarki jest określenie wartości odpowiednich zmiennych, które będziesz mógł wykorzystać w innych fragmentach skryptu. Funkcja ta nie wykonuje żadnych innych czynności.

Przedstawiony poniżej przykład prezentuje praktyczne wykorzystanie kodu określającego typ i wersję przeglądarki. Wewnątrz znacznika body strony WWW wywoływana jest funkcja doSniff. Funkcja ta tworzy zmienną sniff i zapisuje w niej łańcuch znaków, którego postać zależy od typu przeglądarki, następnie wartość tej zmiennej jest wyświetlana w okienku dialogowym.

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Browser Sniffing</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script language="javascript" type="text/javascript">

<!—Hide JavaScript

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofer')==-1) &&

(agt.indexOf('compatible') == -1) &&

(agt.indexOf('opera')==-1) &&

tt (agt.indexOf('webtv')==-1));

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

// Funkcja wyświetlająca wersję przeglądarki

function doSniff() {

var sniff

if (is_nav4up == true) {

sniff = "Netscape Navigator 4+" }

if (is_ie4up == true) {

sniff = "Microsoft Internet Explorer 4+" }

alert(sniff);

}

</script>

</head>

<body onload="doSniff()">

</body>

</html>

Na rysunku 21.3 przedstawiłam powyższą stronę wyświetloną w przeglądarce Internet Explorer 5.5.

0x01 graphic

Rysunek 21.3.

Określanie typu
i wersji przegląda
rki

0x01 graphic

Tworzenie odwołań DOM działających w wielu przeglądarkach

Kolejnym narzędziem, które warto mieć, jest sposób odwoływania się do odpowiedniego modelu obiektów dokumentu, w zależności od przeglądarki, w której strona została wyświetlona. Zamiast stosowania niezależnych odwołań do każdego z istniejących modeli obiektów dokumentu, można stworzyć procedurę kreującą poprawne odwołanie w zależności od wykorzystywanej przeglądarki. Właśnie to zadanie realizuje przedstawiony poniżej fragment kodu. Są w nim wykorzystywane dwie zmienne — objRef oraz styleRef — które w przypadku Netscape Navigatora zawierają wartości puste a w przy-padku Internet Explorera wartości .all oraz .style. Po określeniu typu przeglądarki, skrypt określa poprawne wartości obu tych zmiennych:

// Konwencje odwołań do obiektów i stylów s

// w Navigatorze and IE. Użyj zmiennej objRef

// przy odwoływaniu się do obiektów oraz obu zmiennych

// przy odwoływaniu się do stylów.

var objRef, styleRef;

if (is_nav4up == true) {

objRef = ""

styleRef = ""

}

if (is_ie4up == true) {

objRef = ".all"

styleRef = ".style"

}

Ten sposób działania został wykorzystany na stronie WWW, przedstawionej w następnym przykładzie. Po określeniu typu przeglądarki, umieściłam w niej kod tworzący odwołanie do odpowiedniego modelu obiektów. Następnie zdefiniowane zostały dwie funkcje, tworzące okienka informacyjne wyświetlające poprawne odwołania DOM dla Netscape Navigator i Internet Explorera. Wewnątrz znacznika body przedstawionej strony WWW umieszczone zostały dwa znaczniki div, określające położenie dwóch hiperpołączeń tekstowych. Hiperpołączenia te przechwytują zdarzenia onmouseover i wywołują funkcję alert. Zauważ, iż wartością atrybutu href obu tych hiperpołączeń jest javascript:void(0). To najprostsza metoda zmuszenia hiperpołączenia do wykonania funkcji bez podawania jakiejkolwiek strony docelowej.

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Document Object Model References</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script language="javascript" type="text/javascript">

<!—ukrywamy skrypt

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofer')==-1) &&

(agt.indexOf('compatible') == -1) &&

(agt.indexOf('opera')==-1) &&

(agt.indexOf('webtv')==-1));

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

// Konwencje odwołań do obiektów i stylów

// w Navigatorze and IE. Użyj zmiennej objRef

// przy odwoływaniu się do obiektów oraz obu zmiennych

// przy odwoływaniu się do stylów.

var objRef, styleRef;

if (is_nav4up == true) {

objRef = ""

styleRef = ""

}

if (is_ie4up == true) {

objRef = ".all"

styleRef = ".style"

}

function alertstyle() {

alert(eval("document" + objRef + ".div01" + styleRef + ".top"));

}

function alertobject() {

alert(eval("document" + objRef + ".div02.id"));

}

// koniec ukrywania skryptu -->

</script>

<style type="text/css">

#div01 { position: absolute; }

#div02 { position: absolute; }

</style>

</head>

<body>

<div id="div01" style="top: 50; left: 50;">

<a href="javascript:void(0)" onmouseover="alertstyle()">Odwołanie do sytlów</a>

</div>

<div id="div02" style="top: 100; left: 100;">

<a href="javascript:void(0)" onmouseover="alertobject()">Odwołanie do obiektów</a>

</div>

</body>

</html>

Wyniki wykonania tej strony zostały przedstawione na rysunku 21.4. Zwróć uwagę, iż wskaźnik myszy został umieszczony na łączu wyświetlającym styl.

0x01 graphic

Rysunek 21.4.

Użycie funkcji tworzącej odwołania do obiektów działające w różnych przeglądarkach

0x01 graphic

Nie chcę wprowadzać niepotrzebnego zamieszania, więc przejdę już do dwóch ćwiczeń. Zaprezentują one sposób wykrywania rodzaju przeglądarki, podmieniania obrazków, ukrywania i wyświetlania elementów stron WWW, tworzenie rozwijalnych menu oraz inne techniki tworzenia kodu DHTML działającego w różnych przeglądarkach.

Ogólnie rzecz biorąc, ćwiczenia te mają na celu zaprezentowanie sposobów wykonywania poniższych zadań:

Ćwiczenie 21.1: Tworzenie rozwijalnych menu

W pierwszym ćwiczeniu będziesz miał za zadanie stworzyć stronę zawierającą rozwijalne menu, wykorzystując do tego możliwości, jakie daje DHTML. Gdy użytkownik kliknie obrazek umieszczony obok opcji, menu się rozwinie, prezentując kolejne opcje. Gdy użytkownik kliknie opcję menu, odpowiadająca jej zawartość umieszczona w znacz­niku div zostanie wyświetlona w głównym obszarze okna przeglądarki. Zauważ, iż tworząc strukturę tej strony, nie użyjesz ani tabel (znaczników table), ani ramek (znaczników frame). Zamiast nich wykorzystasz bezwzględnie umiejscowione znaczniki div i będziesz określał, czy są one widzialne czy nie. W tym ćwiczeniu posłużysz się także stylami zdefiniowanymi w nagłówku dokumentu przy użyciu znacznika style.

W pierwszej kolejności stwórz szablon strony WWW, zawierający wszystkie podstawowe elementy jej struktury oraz komponenty, w których następnie umieścisz skrypty.

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Stary ceglany dom</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<!-- Tutaj umieścimy skrypty JavaScript -->

<!-- Tutaj umieścimy arkusze stylów (CSS) -->

</head>

<body>

<!-- Tutaj umieścimy kod HTML -->

</body>

</html>

Kolejnym etapem będzie dodanie kodu HTML odpowiedzialnego za określenie formatowania strony. W celu zachowania odpowiedniej struktury, elementom najwyższego poziomu menu nadałam nazwy toc100 oraz toc200. Nazwy wszystkich elementów podmenu zostały określone na podstawie głównego elementu menu, do którego należą. Dzięki temu, zorientowanie się w organizacji strony będzie znacznie prostsze. W tworzonej stronie posłużę się także skryptami wpisanymi, wykorzystam je do sprawdzenia, czy element menu jest aktualnie widoczny oraz do zmienienia obrazka strzałki po rozwinięciu menu.

Dodałam także zawartość strony, która będzie wyświetlana po kliknięciu odpowiedniej opcji menu. Na razie nie musisz się przejmować, że wszystkie te elementy zostaną wyświetlone. W dalszej części ćwiczenia, poświęconej stylom, przypiszesz właściwości visibility tych elementów wartość hidden.

0x01 graphic

<div id="title">

<img src="title.gif" height="100" width="500" />

</div>

<div id="toc0100">

<a href="javascript:void(0)" onclick="menuaction();

if (show == 1) { document.menuimg.src = ea.src; return true }

if (show == 0) { document.menuimg.src = ca.src; return true }">

<img id="menuimg" name="menuimg" src="expand.gif" width="10" height="10" border="0" /></a>

Historia

</div>

<div id="toc0101">

<a href="javascript:void(0)" onclick="contentID='0101'; showcontent(0101)">Wczesne lata</a>

</div>

<div id="toc0102">

<a href="javascript:void(0)" onclick="contentID='0102'; showcontent(0101)">Stan teraźniejszy</a>

</div>

<div id="toc0200">

<a href="javascript:void(0)" onclick="contentID='0200'; showcontent(0101)">Zdjęcia</a>

</div>

<div id="splash" align="center">

<img src="splash.jpg" height="206" width="300" />

</div>

<div id="content0101">

<p>Ten dom został zbudowany na początku XIX wieku. Początkowo stanowił on część farmy o powierzchni kilkuset akrów, składającej się z kilku domów oraz stodoły. Aktualnie dom oraz stodoła usytuowane są na działce o powierzchni 4 akrów.</p>

</div>

<div id="content0102">

<p>Wnętrze domu zostało nieco zmodyfikowane, na przykład, przebudowano kuchnię. Nie mniej jednak z zewnątrz dom się niemal nie zmienił. Stodoła nie została natomiast w żaden sposób zmodyfikowana.</p>

</div>

<div id="content0200">

<img src="house.jpg" height="93" width="150" />

<img src="barn.jpg" height="100" width="150" />

<img src="grounds.jpg" height="69" width="150" />

</div>

Kolejnym krokiem będzie dodanie do nagłówka dokumentu arkuszy stylów. Każdy element strony, poszczególne opcje menu, graficzny tytuł strony oraz wyświetlane na niej informacje, powinny zostać umiejscowione bezwzględnie. Położenie poszczególnych elementów strony będziesz musiał określić metodą prób i błędów, na szczęście nie powinno to zająć wiele czasu. Zwróć uwagę, iż zarówno wszystkie elementy podmenu, jak i treść strony są początkowo ukryte (atrybutowi visibility przypisana jest wartość hidden). Później przy użyciu skryptu menu zostanie rozwinięte, a jego elementy odpowiednio rozmieszczone, aby wzajemnie siebie nie przesłaniały (patrz rysunek 21.5).

0x01 graphic

<style type="text/css">

<!--

#title { position: absolute; top: 20; left: 50; }

#splash { position: absolute; top: 150; left: 200; visibility: visible; }

#toc0100 { position: absolute; top: 130; left: 20; visibility: visible; }

#toc0101 { position: absolute; top: 150; left: 50; visibility: hidden; }

#toc0102 { position: absolute; top: 170; left: 50; visibility: hidden; }

#toc0200 { position: absolute; top: 150; left: 20; visibility: visible; }

#content0101 { position: absolute; top: 150; left: 200; visibility: hidden; }

#content0102 { position: absolute; top: 150; left: 200; visibility: hidden; }

#content0200 { position: absolute; top: 150; left: 200; visibility: hidden; }

-->

</style>

Teraz można już zacząć pisać skrypt. W pierwszej kolejności powinieneś stworzyć zmienne globalne, które będą wykorzystywane w skrypcie.

0x01 graphic

Rysunek 21.5.

Rozwijalne menu przed dodaniem głównego skryptu

0x01 graphic

0x01 graphic

// Deklaracje zmiennych globalnych

// i stworzenie obiektów obrazków.

var ea = new Image(10,10); //ea = strzałka rozwiń

var ca = new Image(10,10); //ca for strzałka zwiń

ea.src = "expand.gif";

ca.src = "contract.gif";

var show = 1;

var contentID;

Kolejnym krokiem będzie dodanie kodu służącego do wykrywania typu i wersji przeglądarki.

0x01 graphic

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofer')==-1) &&

(agt.indexOf('compatible') == -1) &&

(agt.indexOf('opera')==-1) &&

(agt.indexOf('webtv')==-1));

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

Teraz dodaj kod służący do tworzenia poprawnych odwołań do obiektów.

0x01 graphic

// Konwencje odwołań do obiektów i stylów

// w Navigatorze and IE. Użyj zmiennej objRef

// przy odwoływaniu się do obiektów oraz obu zmiennych

// przy odwoływaniu się do stylów.

var objRef, styleRef;

if (is_nav4up == true) { //W przypadku Navigatora są puste

objRef = ""

styleRef = ""

}

if (is_ie4up == true) { //W przypadku IE - określamy wartości

objRef = ".all"

styleRef = ".style"

}

Teraz przejdziemy do funkcji zapewniających możliwości funkcjonalne strony. Pierwsza z nich będzie wyświetlać, ukrywać oraz zmieniać położenie elementów menu. Zauważ, iż tworząc tę funkcję, wykorzystałam metodę odwoływania się do elementów DOM bez rozróżniania typu przeglądarki.

0x01 graphic

// Funkcja do wyświetlania i ukrywania

// podmenu.

function menuaction() {

if (show == 1) {

eval("document" + objRef + ".toc0101" + styleRef + ".visibility = 'visible'");

eval("document" + objRef + ".toc0102" + styleRef + ".visibility = 'visible'");

eval("document" + objRef + ".toc0200" + styleRef + ".top = '190'");

show = 0;

return true;

}

if (show == 0) {

eval("document" + objRef + ".toc0101" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".toc0102" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".toc0200" + styleRef + ".top = '150'");

show = 1;

return true;

}

}

Kolejna funkcja służy do wyświetlania zawartości strony. Także w tym przypadku będziesz musiał określić, które elementy początkowo powinny zostać ukryte, aby zrobić miejsce konieczne do wyświetlenia wybranych informacji.

0x01 graphic

// Funkcja do ukrywania warstw z zawartością

// oraz wyświetlania wybranej warstwy.

function showcontent() {

if (contentID == "0101") {

eval("document" + objRef + ".splash" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0102" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0200" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0101" + styleRef + ".visibility = 'visible'");

}

if (contentID == "0102") {

eval("document" + objRef + ".splash" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0101" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0200" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0102" + styleRef + ".visibility = 'visible'");

}

if (contentID == "0200") {

eval("document" + objRef + ".splash" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0101" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0102" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0200" + styleRef + ".visibility = 'visible'");

}

}

// zakończ ukrywanie skryptu -->

</script>

A oto pełny kod strony:

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Stary ceglany dom</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script language="javascript" type="text/javascript">

<!—Ukrywamy JavaScript

// Deklaracje zmiennych globalnych

// i stworzenie obiektów obrazków.

var ea = new Image(10,10); //ea = strzałak rozwiń

var ca = new Image(10,10); //ca for strzałka zwiń

ea.src = "expand.gif";

ca.src = "contract.gif";

var show = 1;

var contentID;

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofer')==-1) &&

(agt.indexOf('compatible') == -1) &&

(agt.indexOf('opera')==-1) &&

(agt.indexOf('webtv')==-1));

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

// Konwencje odwołań do obiektów i stylów

// w Navigatorze and IE. Użyj zmiennej objRef

// przy odwoływaniu się do obiektów oraz obu zmiennych

// przy odwoływaniu się do stylów.

var objRef, styleRef;

if (is_nav4up == true) { //W przypadku Navigatora są puste

objRef = ""

styleRef = ""

}

if (is_ie4up == true) { //W przypadku IE - określamy wartości

objRef = ".all"

styleRef = ".style"

}

// Funkcja do wyświetlania i ukrywania

// podmenu.

function menuaction() {

if (show == 1) {

eval("document" + objRef + ".toc0101" + styleRef + ".visibility = 'visible'");

eval("document" + objRef + ".toc0102" + styleRef + ".visibility = 'visible'");

eval("document" + objRef + ".toc0200" + styleRef + ".top = '190'");

show = 0;

return true;

}

if (show == 0) {

eval("document" + objRef + ".toc0101" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".toc0102" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".toc0200" + styleRef + ".top = '150'");

show = 1;

return true;

}

}

// Funkcja do ukrywania warstw z zawartością

// oraz wyświetlania wybranej warstwy.

function showcontent() {

if (contentID == "0101") {

eval("document" + objRef + ".splash" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0102" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0200" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0101" + styleRef + ".visibility = 'visible'");

}

if (contentID == "0102") {

eval("document" + objRef + ".splash" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0101" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0200" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0102" + styleRef + ".visibility = 'visible'");

}

if (contentID == "0200") {

eval("document" + objRef + ".splash" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0101" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0102" + styleRef + ".visibility = 'hidden'");

eval("document" + objRef + ".content0200" + styleRef + ".visibility = 'visible'");

}

}

// zakończ ukrywanie skryptu -->

</script>

<style type="text/css">

<!--

#title { position: absolute; top: 20; left: 50; }

#splash { position: absolute; top: 150; left: 200; visibility: visible; }

#toc0100 { position: absolute; top: 130; left: 20; visibility: visible; }

#toc0101 { position: absolute; top: 150; left: 50; visibility: hidden; }

#toc0102 { position: absolute; top: 170; left: 50; visibility: hidden; }

#toc0200 { position: absolute; top: 150; left: 20; visibility: visible; }

#content0101 { position: absolute; top: 150; left: 200; visibility: hidden; }

#content0102 { position: absolute; top: 150; left: 200; visibility: hidden; }

#content0200 { position: absolute; top: 150; left: 200; visibility: hidden; }

-->

</style>

</head>

<body>

<div id="title">

<img src="title.gif" height="100" width="500" />

</div>

<div id="toc0100">

<a href="javascript:void(0)" onclick="menuaction();

if (show == 1) { document.menuimg.src = ea.src; return true }

if (show == 0) { document.menuimg.src = ca.src; return true }">

<img id="menuimg" name="menuimg" src="expand.gif" width="10" height="10" border="0" /></a>

Historia

</div>

<div id="toc0101">

<a href="javascript:void(0)" onclick="contentID='0101'; showcontent(0101)">Wczesne lata</a>

</div>

<div id="toc0102">

<a href="javascript:void(0)" onclick="contentID='0102'; showcontent(0101)">Stan teraźniejszy</a>

</div>

<div id="toc0200">

<a href="javascript:void(0)" onclick="contentID='0200'; showcontent(0101)">Zdjęcia</a>

</div>

<div id="splash" align="center">

<img src="splash.jpg" height="206" width="300" />

</div>

<div id="content0101">

<p>Ten dom został zbudowany na początku XIX wieku. Początkowo stanowił on część farmy o powierzchni kilkuset akrów, składającej się z kilku domów oraz stodoły. Aktualnie dom oraz stodoła usytuowane są na działce o powierzchni 4 akrów.</p>

</div>

<div id="content0102">

<p>Wnętrze domu zostało nieco zmodyfikowane, na przykład, przebudowano kuchnię. Nie mniej jednak z zewnątrz dom się niemal nie zmienił. Stodoła nie została natomiast w żaden sposób zmodyfikowana.</p>

</div>

<div id="content0200">

<img src="house.jpg" height="93" width="150" />

<img src="barn.jpg" height="100" width="150" />

<img src="grounds.jpg" height="69" width="150" />

</div>

</body>

</html>

Wynikowa strona WWW została przedstawiona na rysunku 21.6. Widać na nim rozwinięte menu, jednak nie zostały jeszcze wyświetlone żadne informacje.

Rysunek 21.7 przedstawia wygląd strony po wybraniu jednej z opcji menu. Jak widać, ukryta wcześniej zawartość strony została wyświetlona.

0x01 graphic

Rysunek 21.6.

Rozwijalne menu wyświetlone w przeglądarce Microsoft Internet Explorer 5

0x01 graphic

0x01 graphic

Rysunek 21.7.

Ukryta wcześniej zawartość strony wyświetlona dzięki możliwościom DHTML

0x01 graphic

Na rysunku 21.8 przedstawiłam tę samą stronę wyświetloną w przeglądarce Netscape Navigator. Fakt, że strona działa poprawnie dowodzi, że wykorzystane techniki DHTML działają poprawnie w obu przeglądarkach. Jak widać na rysunku rozwinęłam menu i wybrałam ostatnią dostępną opcję, aby wyświetlić zdjęcia domu.

Ćwiczenie 21.2: Zagrajmy w kółko i krzyżyk

Ostatnim przykładem, jaki podam w tym rozdziale, będzie strona WWW umożliwiająca grę w kółko i krzyżyk, w całości stworzona przy użyciu DHTML. Bez żadnych dodatków ani konserwantów! Sama gra, jak również strona, na której została umieszczona, wykorzystują kilka przydatnych technik DHTML, takich jak: określanie typu i wersji przeglądarki, określanie „poziomu” elementu przy wykorzystanie atrybutu z-index, chowanie i wyświetlanie elementów oraz tworzenie animacji. Strona, którą spróbujemy stworzyć, została przedstawiona na rysunku 21.9.

0x01 graphic

Rysunek 21.8.

Strona wyświetlona za pomocą przeglądarki Netscape Navigator 4.61 jest potwierdzeniem, że stworzony kod DHTML może być używany w obu przeglądarkach

0x01 graphic

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x01 graphic

Rysunek 21.9.

Gra w kółko i krzyżyk, stworzona jako strona DHTML działająca w różnych przeglądarkach

0x01 graphic

Choć nie jesteś w stanie tego zobaczyć, patrząc na rysunki wydrukowane na stronach tej książki, to jednak w rzeczywistości tytuł strony jest początkowo wyświetlany poza jej lewym, górnym wierzchołkiem, po czym „wsuwa” się na nią i dociera do miejsca docelowego, czyli bezpośrednio nad planszę.

Tworzenie elementów graficznych strony

Grafika bo bardzo ważny element wszystkich stron WWW. Tworzona strona zawiera wizualną (choć prostą) grę w kółko i krzyżyk, dlatego też zdecydowałam, że wyświetlane na niej elementy graficzne powinny być wesołe, proste i kolorowe.

Gdy wymyśliłam już ogólną ideę działania strony i stworzyłam „wstępny” skrypt, byłam w stanie określić szczegółowy sposób rozwiązania problemu, jaki powstał w związku z graficzną postacią gry. W pierwszej chwili miałam zamiar stworzyć planszę do gry jako jeden duży kwadrat, podzielony na dziewięć mniejszych pól. Po stworzeniu takiej planszy odkryłam jednak, że łatwiejszym rozwiązaniem będzie wykreowanie dziewięciu niezależnych obrazków, reprezentujących dziewięć pól planszy i umieszczenie każdego z nich w odrębnym znaczniku div. Używając kaskadowych arkuszy stylów, każdy z tych elementów można wyświetlić w ściśle określonym miejscu strony, dzięki czemu użytkownik nie będzie w stanie stwierdzić, że plansza do gry składa się z dziewięciu części.

0x01 graphic

Tworząc obrazki wykorzystywane na tej stronie, posługiwałam się programami Adobe Photoshop 5 oraz Adobe ImageReady. Zdaję sobie sprawę, iż możesz nie mieć dostępu do tych programów. Na szczęście istnieją także inne (tańsze) pakiety graficzne, z którym możesz skorzystać. Sposoby tworzenia i optymalizacji obrazków są takie same we wszystkich dostępnych programach.

Aby gra była atrakcyjna graficznie, wykorzystałam fakt, iż jej angielska nazwa („tic-tac-toe”) składa się z dziewięciu liter. Pozwoliło mi to stworzyć obrazki .gif o wymiarach 77×77 pikseli i umieścić na nich poszczególne litery nazwy. Zmieniłam także kolor liter dla każdego ze słów tworzących nazwę; i tak litery tworzące słowo „Tic” są czerwone, „Tac” — czarne a „Toe” — niebieskie.

Następnie, modyfikując widzialność obiektów graficznych, sprawiłam, że litery stały się nieco „wyblakłe”, przez co lepiej nadają się do wyświetlenia w tle strony. Nie chciałam, aby ich kolory były zbyt mocne, gdyż mogłyby wtedy utrudniać rozpoznawanie pionków wyświetlanych na planszy.

Gdy wszystko już wymyśliłam i narysowałam, stworzyłam dziewięć plików .GIF (przedstawionych na rysunku 21.10) o identycznych wymiarach i nadałam im nazwy odpowiadające położeniu, w jakim będą wyświetlane na planszy (na przykład, topleft.gif, centercenter.gif, itd.).

0x01 graphic

Rysunek 21.10.

Wszystkie obrazki wyświetlane jako tło planszy są „wyblakłe”, aby nie stanowiły dominującego elementu strony

0x01 graphic

Jeśli chodzi o pionki, to musiałam stworzyć tylko dwa obrazki, jeden dla „kółka” (0) oraz drugi dla „krzyżyka” (X). Należy podkreślić, iż także te grafiki mają wymiary 77x77 pikseli, a ich tło nie jest przezroczyste. Nie chciałam, aby litery wyświetlane w tle były widoczne po umieszczeniu pionka na wybranym polu planszy. Na rysunku 21.11 przedstawiłam obrazki „kółka” i „krzyżyka” wyświetlone w programie Photoshop.

0x01 graphic

Rysunek 21.11.

Obrazki przedstawiające pionki — „kółko” i „krzyżyk”

0x01 graphic

Ostatnim elementem graficznym, który musiałam stworzyć, był tytuł strony pokazany na rysunku 21.12. Tytuł jest animowany, pojawia się w lewym, górnym wierzchołku strony i przesuwa ku jej środkowi. Nie chciałam powtarzać angielskiej nazwy gry i uznałam, że ciekawym tytułem będzie „Let's Play”.

0x01 graphic

Rysunek 21.12.

Animowany nagłówek strony

0x01 graphic

Przy tworzeniu tych wszystkich obrazków posłużyłam się stylową i zabawną czcionką Beesknees ITC. Zdecydowałam, że inne teksty na stronie będą wyświetlane bardziej czytelną czcionką, jednak do stworzenia tła, tytułu i pionków czcionka Beesknees ITC wydała mi się doskonała.

Teraz, kiedy już stworzyliśmy wszystkie elementy graficzne, można zabrać się za pisanie kodu strony.

Tworzenie kodu HTML z odrobiną stylu

Zacznijmy od określenia używanej wersji języka HTML oraz stworzenia znaczników head i body tworzących szablon strony.

0x01 graphic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Kółko i krzyżyk</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<!—Tutaj umieścimy skrypty -->

</head>

<body>

<!-- Tutaj umieścimy kod HTML -->

</body>

</html>

Na razie zajmiemy się kodem HTML umieszczonym wewnątrz znacznika body. W pierwszej kolejności stwórz graficzny tytuł strony, który następnie będzie animowany. W tym celu wykreuj znacznik div i zdefiniuj w nim atrybut ID, dzięki czemu będziesz mógł manipulować tym elementem w skryptach. Określ bezwzględne położenie tego elementu na stronie. Początkowo element ten ma być wyświetlony poza stroną WWW, a zatem atrybuty left oraz top powinny mieć ujemne wartości. Przypisanie atrybutowi z-index wartości 5 zapewni, że tytuł zostanie wyświetlony ponad wszystkimi innymi warstwami CSS. Po otwierającym znaczniku div umieść znacznik img definiujący obrazek, po czym dodaj zamykający znacznik div.

0x01 graphic

<div id="titleimage" style="position: absolute;

left: -100;

top: -100;

z-index: 5">

<img src="titleTTT.gif" height="57" width="254" />

</div>

To nie było zbyt trudne. A jeśli rozumiesz znaczenie tego fragmentu kodu, to bez trudu stworzysz następne elementy naszej gry: planszę oraz pionki.

Plansza gry składa się z dziewięciu znaczników div, w każdym z nich został umieszczony odpowiedni obrazek. Dokładne wymiary wszystkich obrazków określiłam w programie Photoshop, dzięki czemu bez trudu będzie można odczytać ich koordynaty (czyli wartości atrybutów left oraz top). Co więcej, plansza ma stanowić najniższą warstwę strony, a zatem atrybutowi z-index wszystkich jej elementów należy przypisać wartość 0. Trzeba także zadbać o to, aby poszczególne elementy tworzące planszę były widoczne; w tym celu posłużysz się właściwością visibility. Chcesz także, by kliknięcie planszy spowodowało wygenerowanie zdarzenia. W tym celu, w każdym ze znaczników div zdefiniuj atrybut onclick, a w nim przypisz wartość zmiennej identyfikującej kliknięte pole planszy i wywołaj funkcję update(), która wyświetli na planszy odpowiedni pionek. Analizując poniższy kod HTML tworzący planszę do gry, zwróć uwagę, iż każdy element div posiada unikalne wartości atrybutów id, top oraz left. Gdy użytkownik kliknie jedno z pól planszy, zmiennej position przypisywana jest odpowiednia wartość. Wartość ta zostanie wykorzystania w funkcji update().

0x01 graphic

<!-- początek definicji planszy -->

<div id="topleft"

style="position: absolute;

top: 100;

left: 100;

z-index: 0;

visibility: visible"

onclick="position = 'topleft'; update();">

<img src="topleft.gif" height="77" width="77" />

</div>

<div id="topcenter"

style="position: absolute;

top: 100;

left: 177;

z-index: 0;

visibility: visible"

onclick="position = 'topcenter'; update();">

<img src="topcenter.gif" height="77" width="77" />

</div>

<div id="topright"

style="position: absolute;

top: 100;

left: 254;

z-index: 0"

onclick="position = 'topright'; update()">

<img src="topright.gif" height="77" width="77" />

</div>

<div id="centerleft"

style="position: absolute;

top: 177;

left: 100;

z-index: 0"

onclick="position = 'centerleft'; update()">

<img src="centerleft.gif" height="77" width="77" />

</div>

<div id="centercenter"

style="position: absolute;

top: 177;

left: 177;

z-index: 0"

onclick="position = 'centercenter'; update()">

<img src="centercenter.gif" height="77" width="77" />

</div>

<div id="centerright"

style="position: absolute;

top: 177;

left: 254;

z-index: 0"

onclick="position = 'centerright'; update()">

<img src="centerright.gif" height="77" width="77" />

</div>

<div id="bottomleft"

style="position: absolute;

top: 254;

left: 100;

z-index: 0"

onclick="position = 'bottomleft'; update()">

<img src="bottomleft.gif" height="77" width="77" />

</div>

<div id="bottomcenter"

style="position: absolute;

top: 254;

left: 177;

z-index: 0"

onclick="position = 'bottomcenter'; update()">

<img src="bottomcenter.gif" height="77" width="77" />

</div>

<div id="bottomright"

style="position: absolute;

top: 254;

left: 254;

z-index: 0"

onclick="position = 'bottomright'; update()">

<img src="bottomright.gif" height="77" width="77" />

</div>

<!-- koniec definicji planszy -->

Na rysunku 21.13 przedstawiłem wygląd tworzonej strony WWW, w jej aktualnej postaci.

0x01 graphic

Rysunek 21.13.

Tytuł strony (znajdujący się poza widoczną częścią strony) oraz plansza do gry po określeniu położenia

0x01 graphic

A zatem plansza do gry została już stworzona. Teraz powinieneś zająć się zdefiniowaniem pionów. Zgodnie z oryginalnym pomysłem zdecydowałam się stworzyć zarówno piony O, jak i X i umieścić je nad każdym polem planszy. Początkowo piony te będą niewidoczne. Gdy użytkownik kliknie jedno z pól planszy, skrypt określi, jakimi pionami gra dana osoba (X bądź O) i wyświetli odpowiedni obrazek.

0x01 graphic

<!-- początek ukrytych pionów O -->

<div id="toplefto"

style="position: absolute;

top: 100;

left: 100;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="topcentero"

style="position: absolute;

top: 100;

left: 177;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="toprighto"

style="position: absolute;

top: 100;

left: 254;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="centerlefto"

style="position: absolute;

top: 177;

left: 100;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="centercentero"

style="position: absolute;

top: 177;

left: 177;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="centerrighto"

style="position: absolute;

top: 177;

left: 254;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="bottomlefto"

style="position: absolute;

top: 254;

left: 100;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="bottomcentero"

style="position: absolute;

top: 254;

left: 177;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="bottomrighto"

style="position: absolute;

top: 254;

left: 254;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<!-- koniec ukrytych pionów O -->

<!-- początek ukrytych pionów X -->

<div id="topleftx"

style="position: absolute;

top: 100;

left: 100;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="topcenterx"

style="position: absolute;

top: 100;

left: 177;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="toprightx"

style="position: absolute;

top: 100;

left: 254;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="centerleftx"

style="position: absolute;

top: 177;

left: 100;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="centercenterx"

style="position: absolute;

top: 177;

left: 177;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="centerrightx"

style="position: absolute;

top: 177;

left: 254;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="bottomleftx"

style="position: absolute;

top: 254;

left: 100;

z-index: 2;

visibility: hidden">

<img src="X.gif" height="77" width="77" />

</div>

<div id="bottomcenterx"

style="position: absolute;

top: 254;

left: 177;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="bottomrightx"

style="position: absolute;

top: 254;

left: 254;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<!—koniec ukrytych pionów X -->

O rany! To był naprawdę długi fragment kodu. Teraz należałoby wyświetlić kilka informacji, aby użytkownicy wiedzieli, jak należy grać i czyścić planszę. Także instrukcje zostaną wyświetlone przy użyciu dobrze już znanego znacznika div. Stworzysz także formularz zawierający przycisk Wyczyść planszę.

0x01 graphic

<div id="instructions"

style="position: absolute;

top: 95;

left: 350">

<h3>Instrukcje:</h3>

<p>Aby grać, należy kliknąć pole, na którym nie ma ani O ani X. Pierwszy gracz gra pionami X, a drugi O. Celem gry jest umieszczenie na planszy trzech swoich pionów w linii prostej - poziomo, pionowo lub po przekątnej.</p>

<form name="clearboard">

<input type="submit" value="Wyczyść planszę" onclick="window.location.reload()" />

</form>

Aktualną postać strony przedstawiłem na rysunku 21.14.

0x01 graphic

Rysunek 21.14.

Strona po dodaniu instrukcji oraz przycisku czyszczącego planszę

0x01 graphic

Ponieważ chcemy mieć pełną kontrolę nad wyglądem strony, także ten element został umiejscowiony bezwzględnie. Znacznik formularza nie zawiera atrybutu action ani method, nie są one potrzebne, gdyż jedynym zadaniem formularza jest wyświetlenie przycisku submit, który umożliwi wywołanie funkcji window.location.reload(). Wykonanie tej funkcji spowoduje ponowne wyświetlenie strony w przeglądarce.

Skrypty obsługujące stronę

A zatem strona jest gotowa. Teraz można zająć się skryptem, który „ożywi” naszą stronę DHTML.

W pierwszej kolejności stwórz znacznik script i na samym jego początku zdefiniuj kilka zmiennych, które będą wykorzystywane w dalszej części skryptu. Zauważ, iż bezpośrednio za otwierającym znacznikiem script umieściłam początek komentarza HTML (<!--); jego celem jest ukrycie kodu w starszych przeglądarkach, które nie są w stanie wykonywać skryptów. Pamiętaj, aby zakończyć ten komentarz (znacznikiem -->) przed zamykającym znacznikiem script. Komentarze języka JavaScript rozpoczynają się od dwóch znaków ukośnika (//).

0x01 graphic

<script language="javascript" type="text/javascript">

<!—Ukrywamy kod JavaScript

// Deklaracje zmiennych

var player1 = "x";

var player2 = "o";

var currentplayer;

var position;

var yhop = 3;

var ygoal = 20;

var xhop = 3;

var xgoal = 20;

var delay = 1;

var xpos;

var ypos;

Teraz należy określić przeglądarkę, w której strona została wyświetlona. Chcemy, aby tworzona strona mogła być wyświetlana w różnych przeglądarkach (przynajmniej w tych najpopularniejszych) i dlatego określenie rodzaju i wersji przeglądarki jest konieczne.

Nie mam zamiaru ponownie wymyślać koła i dlatego posłużę się nieco zmodyfikowaną wersją kodu dostępnego na witrynie firmy Netscape, umożliwiającego określenie typu przeglądarki głównego oraz dodatkowego numeru jej wersji, systemu operacyjnego, dla którego jest przeznaczona oraz wielu innych informacji. Cały ten kod umieścimy w nagłówku strony wewnątrz znacznika script.

0x01 graphic

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofer')==-1) &&

(agt.indexOf('compatible') == -1) &&

(agt.indexOf('opera')==-1) &&

(agt.indexOf('webtv')==-1));

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

W celu sprawdzenia, czy używana przeglądarka to Netscape Navigator lub Internet Explorer w wersji 4 lub wyższej, możesz posłużyć się następującym fragmentem kodu:

if (is_nav4up) { zrób coś ... }

if (is_ie4up) { zrób coś ... }

Pierwsza funkcja jest wywoływana w momencie zakończenia pobierania strony i służy do inicjalizacji skryptu. Aby śledzić ruchy kolejnych graczy, przypisz zmiennej currentplayer wartość player1. W ten sposób pierwsza osoba, która kliknie planszę, zostanie rozpoznana jako player1 (pierwszy gracz).

W drugiej części funkcji sprawdzamy, czy przeglądarką użytą do wyświetlenia strony jest Netscape Navigator. W takim przypadku włączamy przechwytywanie zdarzeń generowanych przez mysz. To niezwykle ważne, gdyż Netscape Navigator nie rozpoznaje zdarzeń onClick generowanych przez znaczniki div, z których składa się nasza plansza. Na samym końcu funkcji wywołujemy funkcję slidetitle() odpowiedzialną za przeprowadzenie animacji tytułu strony.

0x01 graphic

// Inicjalizacja pierwszego gracza

// i rozpoczęcie przechwytywania zdarzeń w Netscape

// Funkcja wywoływana przez znacznik BODY po załadowaniu strony

function init() {

currentplayer = player1;

if (is_nav4up == true ) {

document.captureEvents(Event.CLICK | Event.MOUSEDOWN)

document.onclick=updatenav

document.onmousedown=updatenav

}

slidetitle();

}

Funkcja slidetitle() sprawdza rodzaj przeglądarki i w zależności od niego animuje tytuł strony. W zasadzie jedyna różnica polega na postaci odwołania do tytułowego obrazka, jakiego należy użyć w każdej z przeglądarek. W Netscapie odwołanie to ma postać document.titleimage, natomiast w programie Internet Explorer — document.all .titleimage. Wewnątrz funkcji instrukcje if sprawdzają, czy wartości atrybutów top oraz left obrazka nie odpowiadają wartościom zmiennych xgoal oraz ygoal zadeklarowanych na początku skryptu. Jeśli wartości atrybutów nie odpowiadają koordynatom końcowym, to dodajemy do nich wartości zmiennych xhop oraz yhop. Określają one o ile pikseli należy każdorazowo przesunąć obrazek tytułowy.

0x01 graphic

// Animacja grafiki tytułu

function slidetitle() {

if (is_nav4up == true ) {

if ((parseInt(document.titleimage.left) != xgoal) ||

(parseInt(document.titleimage.top) != ygoal)) {

document.titleimage.left = document.titleimage.left + xhop;

document.titleimage.top = document.titleimage.top + yhop;

timeoutID = setTimeout("slidetitle()", delay); }

}

if (is_ie4up == true ) {

if ((parseInt(document.all.titleimage.style.left) != xgoal) ||

(parseInt(document.all.titleimage.style.top) != ygoal)) {

document.all.titleimage.style.left = parseInt(document.all.titleimage.style.left) + xhop;

document.all.titleimage.style.top = parseInt(document.all.titleimage.style.top) + yhop;

timeoutID = setTimeout("slidetitle()", delay); }

}

}

Jednak Netscape Navigator nie obsługuje zdarzenia onclick i z tego względu konieczne będzie stworzenie odrębnej procedury odpowiedzialnej za aktualizację planszy po jej kliknięciu.

W pierwszej kolejności należy określić współrzędne miejsca, w którym użytkownik kliknął. W tym celu należy posłużyć się właściwościami e.pageX oraz e.pageY. Następnie, musisz określić który gracz wykonał ruch. Kod obsługujący ruchy obu graczy jest niemal identyczny, jedyna różnica polega na tym, iż w przypadku pierwszego gracza (player1) wyświetlane są piony X, a w przypadku drugiego gracza (player2) — piony O. Precyzyjne określenie punktu kliknięcia jest konieczne, gdyż pozwala ustalić wybrane pole planszy. Warto także zwrócić uwagę na konieczność sprawdzenia widzialności pionu przeciwnika, pozwala ono ustalić, czy dane pole planszy jest puste, czy też zostało już wykorzystane. Jeśli w polu jest już wyświetlony pion przeciwnika, to nie wykonujemy żadnych dodatkowych czynności.

0x01 graphic

// Aktualizacja gdy Navigator wykryje zdarzenie wygenerowane przez mysz.

// IE ignoruje tę funkcję na korzyść zdarzenia onClick.

function updatenav(e) {

xpos = e.pageX;

ypos = e.pageY;

if (currentplayer == player1) {

if (xpos >= 100 && xpos <= 176 && ypos >= 100 && ypos <= 176 && document.toplefto.visibility == "hide") {

document.topleftx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 177 && xpos <= 253 && ypos >= 100 && ypos <= 176 && document.topcentero.visibility == "hide") {

document.topcenterx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 254 && xpos <= 331 && ypos >= 100 && ypos <= 176 && document.toprighto.visibility == "hide") {

document.toprightx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 100 && xpos <= 176 && ypos >= 177 && ypos <= 253 && document.centerlefto.visibility == "hide") {

document.centerleftx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 177 && xpos <= 253 && ypos >= 177 && ypos <= 253 && document.centercentero.visibility == "hide") {

document.centercenterx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 254 && xpos <= 331 && ypos >= 177 && ypos <= 253 && document.centerrighto.visibility == "hide") {

document.centerrightx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 100 && xpos <= 176 && ypos >= 254 && ypos <= 331 && document.bottomlefto.visibility == "hide") {

document.bottomleftx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 177 && xpos <= 253 && ypos >= 254 && ypos <= 331 && document.bottomcentero.visibility == "hide") {

document.bottomcenterx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 254 && xpos <= 331 && ypos >= 254 && ypos <= 331 && document.bottomrighto.visibility == "hide") {

document.bottomrightx.visibility = "visible"; currentplayer = player2;}

}

else {

if (xpos >= 100 && xpos <= 176 && ypos >= 100 && ypos <= 176 && document.topleftx.visibility == "hide") {

document.toplefto.visibility = "show"; currentplayer = player1;}

if (xpos >= 177 && xpos <= 253 && ypos >= 100 && ypos <= 176 && document.topcenterx.visibility == "hide") {

document.topcentero.visibility = "show"; currentplayer = player1;}

if (xpos >= 254 && xpos <= 331 && ypos >= 100 && ypos <= 176 && document.toprightx.visibility == "hide") {

document.toprighto.visibility = "show"; currentplayer = player1;}

if (xpos >= 100 && xpos <= 176 && ypos >= 177 && ypos <= 253 && document.centerleftx.visibility == "hide") {

document.centerlefto.visibility = "visible"; currentplayer = player1;}

if (xpos >= 177 && xpos <= 253 && ypos >= 177 && ypos <= 253 && document.centercenterx.visibility == "hide") {

document.centercentero.visibility = "visible"; currentplayer = player1;}

if (xpos >= 254 && xpos <= 331 && ypos >= 177 && ypos <= 253 && document.centerrightx.visibility == "hide") {

document.centerrighto.visibility = "visible"; currentplayer = player1;}

if (xpos >= 100 && xpos <= 176 && ypos >= 254 && ypos <= 331 && document.bottomleftx.visibility == "hide") {

document.bottomlefto.visibility = "visible"; currentplayer = player1;}

if (xpos >= 177 && xpos <= 253 && ypos >= 254 && ypos <= 331 && document.bottomcenterx.visibility == "hide") {

document.bottomcentero.visibility = "visible"; currentplayer = player1;}

if (xpos >= 254 && xpos <= 331 && ypos >= 254 && ypos <= 331 && document.bottomrightx.visibility == "hide") {

document.bottomrighto.visibility = "visible"; currentplayer = player1;}

}

}

I w końcu dochodzimy do funkcji używanej w przeglądarce Internet Explorer do aktualizacji planszy gry. W pierwszej kolejności funkcja ta sprawdza, który gracz wykonuje ruch i określa typ pionu, a następnie modyfikuje zmienną currentplayer w taki sposób, iż po poprawnym wykonaniu ruchu przypadnie kolej na drugiego gracza.

Następnie funkcja ustawia wartości atrybutów position oraz visiblility wszystkich pionów. W tym przypadku nie trzeba sprawdzać koordynat punktu kliknięcia, gdyż funkcja jest wywoływana przez znacznik div określający kliknięte pole planszy.

0x01 graphic

// Aktualizacja w IE w wyniku zgłoszenia zdarzenia onClick.

// Navigator ignoruje to zdarzenie więc nie trzeba się nim

// przejmować.

function update() {

if (currentplayer == player1) {

playermarker = "x";

currentplayer = player2;

}

else {

playermarker = "o";

currentplayer = player1;

}

if (is_ie4up == true) {

if (position == "topleft") {

eval("document.all.topleft"+playermarker+ ".style.visibility = 'visible'");}

if (position == "topcenter") {

eval("document.all.topcenter"+playermarker+ ".style.visibility = 'visible'");}

if (position == "topright") {

eval("document.all.topright"+playermarker+ ".style.visibility = 'visible'");}

if (position == "centerleft") {

eval("document.all.centerleft"+playermarker+ ".style.visibility = 'visible'");}

if (position == "centercenter") {

eval("document.all.centercenter"+playermarker+ ".style.visibility = 'visible'");}

if (position == "centerright") {

eval("document.all.centerright"+playermarker+ ".style.visibility = 'visible'");}

if (position == "bottomleft") {

eval("document.all.bottomleft"+playermarker+ ".style.visibility = 'visible'");}

if (position == "bottomcenter") {

eval("document.all.bottomcenter"+playermarker+ ".style.visibility = 'visible'");}

if (position == "bottomright") {

eval("document.all.bottomright"+playermarker+ ".style.visibility = 'visible'");}

}

}

// koniec ukrywania kodu JavaScript -->

</script>

Ostatni element skryptu jest umieszczony bezpośrednio w kodzie HTML strony. Jest nim wywołanie metody init() w odpowiedzi na zgłoszenie zdarzenia onload. Odpowiedni kod umieszczany jest w znaczniku body:

<body onload="init()">

Gotowy produkt

To była naprawdę trudna praca. Jeśli jeszcze tego nie zauważyłeś, to powinieneś zdać sobie sprawę z faktu, iż napisanie takiej strony WWW wymaga opanowania wszystkich trzech technologii tworzących DHTML — HTML, CSS oraz tworzenia skryptów. Poniżej podałam pełny kod źródłowy utworzonej strony WWW:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd">

<html>

<head>

<title>Kółko i krzyżyk</title>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script language="javascript" type="text/javascript">

<!-- Ukrywamy kod JavaScript

// Deklaracje zmiennych

var player1 = "x";

var player2 = "o";

var currentplayer;

var position;

var yhop = 3;

var ygoal = 20;

var xhop = 3;

var xgoal = 20;

var delay = 1;

var xpos;

var ypos;

// Uproszczona wersja wykrywania przeglądarki

// wykrywająca Navigatora 4+ oraz IE 4+.

// Użyj zmiennych is_nav4up oraz is_ie4up

// w innych częściach skryptu

var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);

var is_minor = parseFloat(navigator.appVersion);

var is_nav = ((agt.indexOf('mozilla')!=-1) &&

(agt.indexOf('spoofer')==-1) &&

(agt.indexOf('compatible') == -1) &&

(agt.indexOf('opera')==-1) &&

(agt.indexOf('webtv')==-1));

var is_nav4up = (is_nav && (is_major >= 4));

var is_ie = (agt.indexOf("msie") != -1);

var is_ie4up = (is_ie && (is_major >= 4));

// Inicjalizacja pierwszego gracza

// i rozpoczęcie przechwytywania zdarzeń w Netscape

// Funkcja wywoływana przez znacznik BODY po załadowaniu strony

function init() {

currentplayer = player1;

if (is_nav4up == true ) {

document.captureEvents(Event.CLICK | Event.MOUSEDOWN)

document.onclick=updatenav

document.onmousedown=updatenav

}

slidetitle();

}

// Animacja grafiki tytułu

function slidetitle() {

if (is_nav4up == true ) {

if ((parseInt(document.titleimage.left) != xgoal) ||

(parseInt(document.titleimage.top) != ygoal)) {

document.titleimage.left = document.titleimage.left + xhop;

document.titleimage.top = document.titleimage.top + yhop;

timeoutID = setTimeout("slidetitle()", delay); }

}

if (is_ie4up == true ) {

if ((parseInt(document.all.titleimage.style.left) != xgoal) ||

(parseInt(document.all.titleimage.style.top) != ygoal)) {

document.all.titleimage.style.left = parseInt(document.all.titleimage.style.left) + xhop;

document.all.titleimage.style.top = parseInt(document.all.titleimage.style.top) + yhop;

timeoutID = setTimeout("slidetitle()", delay); }

}

}

// Aktualizacja gdy Navigator wykryje zdarzenie wygenerowane przez mysz.

// IE ignoruje tę funkcję na korzyść zdarzenia onClick.

function updatenav(e) {

xpos = e.pageX;

ypos = e.pageY;

if (currentplayer == player1) {

if (xpos >= 100 && xpos <= 176 && ypos >= 100 && ypos <= 176 && document.toplefto.visibility == "hide") {

document.topleftx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 177 && xpos <= 253 && ypos >= 100 && ypos <= 176 && document.topcentero.visibility == "hide") {

document.topcenterx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 254 && xpos <= 331 && ypos >= 100 && ypos <= 176 && document.toprighto.visibility == "hide") {

document.toprightx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 100 && xpos <= 176 && ypos >= 177 && ypos <= 253 && document.centerlefto.visibility == "hide") {

document.centerleftx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 177 && xpos <= 253 && ypos >= 177 && ypos <= 253 && document.centercentero.visibility == "hide") {

document.centercenterx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 254 && xpos <= 331 && ypos >= 177 && ypos <= 253 && document.centerrighto.visibility == "hide") {

document.centerrightx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 100 && xpos <= 176 && ypos >= 254 && ypos <= 331 && document.bottomlefto.visibility == "hide") {

document.bottomleftx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 177 && xpos <= 253 && ypos >= 254 && ypos <= 331 && document.bottomcentero.visibility == "hide") {

document.bottomcenterx.visibility = "visible"; currentplayer = player2;}

if (xpos >= 254 && xpos <= 331 && ypos >= 254 && ypos <= 331 && document.bottomrighto.visibility == "hide") {

document.bottomrightx.visibility = "visible"; currentplayer = player2;}

}

else {

if (xpos >= 100 && xpos <= 176 && ypos >= 100 && ypos <= 176 && document.topleftx.visibility == "hide") {

document.toplefto.visibility = "show"; currentplayer = player1;}

if (xpos >= 177 && xpos <= 253 && ypos >= 100 && ypos <= 176 && document.topcenterx.visibility == "hide") {

document.topcentero.visibility = "show"; currentplayer = player1;}

if (xpos >= 254 && xpos <= 331 && ypos >= 100 && ypos <= 176 && document.toprightx.visibility == "hide") {

document.toprighto.visibility = "show"; currentplayer = player1;}

if (xpos >= 100 && xpos <= 176 && ypos >= 177 && ypos <= 253 && document.centerleftx.visibility == "hide") {

document.centerlefto.visibility = "visible"; currentplayer = player1;}

if (xpos >= 177 && xpos <= 253 && ypos >= 177 && ypos <= 253 && document.centercenterx.visibility == "hide") {

document.centercentero.visibility = "visible"; currentplayer = player1;}

if (xpos >= 254 && xpos <= 331 && ypos >= 177 && ypos <= 253 && document.centerrightx.visibility == "hide") {

document.centerrighto.visibility = "visible"; currentplayer = player1;}

if (xpos >= 100 && xpos <= 176 && ypos >= 254 && ypos <= 331 && document.bottomleftx.visibility == "hide") {

document.bottomlefto.visibility = "visible"; currentplayer = player1;}

if (xpos >= 177 && xpos <= 253 && ypos >= 254 && ypos <= 331 && document.bottomcenterx.visibility == "hide") {

document.bottomcentero.visibility = "visible"; currentplayer = player1;}

if (xpos >= 254 && xpos <= 331 && ypos >= 254 && ypos <= 331 && document.bottomrightx.visibility == "hide") {

document.bottomrighto.visibility = "visible"; currentplayer = player1;}

}

}

// Aktualizacja w IE w wyniku zgłoszenia zdarzenia onClick.

// Navigator ignoruje to zdarzenie więc nie trzeba się nim

// przejmować.

function update() {

if (currentplayer == player1) {

playermarker = "x";

currentplayer = player2;

}

else {

playermarker = "o";

currentplayer = player1;

}

if (is_ie4up == true) {

if (position == "topleft") {

eval("document.all.topleft"+playermarker+ ".style.visibility = 'visible'");}

if (position == "topcenter") {

eval("document.all.topcenter"+playermarker+ ".style.visibility = 'visible'");}

if (position == "topright") {

eval("document.all.topright"+playermarker+ ".style.visibility = 'visible'");}

if (position == "centerleft") {

eval("document.all.centerleft"+playermarker+ ".style.visibility = 'visible'");}

if (position == "centercenter") {

eval("document.all.centercenter"+playermarker+ ".style.visibility = 'visible'");}

if (position == "centerright") {

eval("document.all.centerright"+playermarker+ ".style.visibility = 'visible'");}

if (position == "bottomleft") {

eval("document.all.bottomleft"+playermarker+ ".style.visibility = 'visible'");}

if (position == "bottomcenter") {

eval("document.all.bottomcenter"+playermarker+ ".style.visibility = 'visible'");}

if (position == "bottomright") {

eval("document.all.bottomright"+playermarker+ ".style.visibility = 'visible'");}

}

}

// koniec ukrywania kodu JavaScript -->

</script>

</head>

<body onload="init()">

<div id="titleimage"

style="position: absolute;

left: -100;

top: -100;

z-index: 5">

<img src="titleTTT.gif" height="57" width="254" />

</div>

<!-- początek definicji planszy -->

<div id="topleft"

style="position: absolute;

top: 100;

left: 100;

z-index: 0;

visibility: visible"

onclick="position = 'topleft'; update();">

<img src="topleft.gif" height="77" width="77" />

</div>

<div id="topcenter"

style="position: absolute;

top: 100;

left: 177;

z-index: 0;

visibility: visible"

onclick="position = 'topcenter'; update();">

<img src="topcenter.gif" height="77" width="77" />

</div>

<div id="topright"

style="position: absolute;

top: 100;

left: 254;

z-index: 0"

onclick="position = 'topright'; update()">

<img src="topright.gif" height="77" width="77" />

</div>

<div id="centerleft"

style="position: absolute;

top: 177;

left: 100;

z-index: 0"

onclick="position = 'centerleft'; update()">

<img src="centerleft.gif" height="77" width="77" />

</div>

<div id="centercenter"

style="position: absolute;

top: 177;

left: 177;

z-index: 0"

onclick="position = 'centercenter'; update()">

<img src="centercenter.gif" height="77" width="77" />

</div>

<div id="centerright"

style="position: absolute;

top: 177;

left: 254;

z-index: 0"

onclick="position = 'centerright'; update()">

<img src="centerright.gif" height="77" width="77" />

</div>

<div id="bottomleft"

style="position: absolute;

top: 254;

left: 100;

z-index: 0"

onclick="position = 'bottomleft'; update()">

<img src="bottomleft.gif" height="77" width="77" />

</div>

<div id="bottomcenter"

style="position: absolute;

top: 254;

left: 177;

z-index: 0"

onclick="position = 'bottomcenter'; update()">

<img src="bottomcenter.gif" height="77" width="77" />

</div>

<div id="bottomright"

style="position: absolute;

top: 254;

left: 254;

z-index: 0"

onclick="position = 'bottomright'; update()">

<img src="bottomright.gif" height="77" width="77" />

</div>

<!-- koniec definicji planszy -->

<!-- początek ukrytych pionów O -->

<div id="toplefto"

style="position: absolute;

top: 100;

left: 100;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="topcentero"

style="position: absolute;

top: 100;

left: 177;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="toprighto"

style="position: absolute;

top: 100;

left: 254;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="centerlefto"

style="position: absolute;

top: 177;

left: 100;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="centercentero"

style="position: absolute;

top: 177;

left: 177;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="centerrighto"

style="position: absolute;

top: 177;

left: 254;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="bottomlefto"

style="position: absolute;

top: 254;

left: 100;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="bottomcentero"

style="position: absolute;

top: 254;

left: 177;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<div id="bottomrighto"

style="position: absolute;

top: 254;

left: 254;

z-index: 3;

visibility: hidden">

<img src="o.gif" height="77" width="77" />

</div>

<!-- koniec ukrytych pionów O -->

<!-- początek ukrytych pionów X -->

<div id="topleftx"

style="position: absolute;

top: 100;

left: 100;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="topcenterx"

style="position: absolute;

top: 100;

left: 177;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="toprightx"

style="position: absolute;

top: 100;

left: 254;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="centerleftx"

style="position: absolute;

top: 177;

left: 100;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="centercenterx"

style="position: absolute;

top: 177;

left: 177;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="centerrightx"

style="position: absolute;

top: 177;

left: 254;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="bottomleftx"

style="position: absolute;

top: 254;

left: 100;

z-index: 2;

visibility: hidden">

<img src="X.gif" height="77" width="77" />

</div>

<div id="bottomcenterx"

style="position: absolute;

top: 254;

left: 177;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<div id="bottomrightx"

style="position: absolute;

top: 254;

left: 254;

z-index: 2;

visibility: hidden">

<img src="x.gif" height="77" width="77" />

</div>

<!-- koniec ukrytych pionów X -->

<div id="instructions"

style="position: absolute;

top: 95;

left: 350">

<h3>Instrukcje:</h3>

<p>Aby grać, należy kliknąć pole, na którym nie ma ani O ani X. Pierwszy gracz gra pionami X, a drugi O. Celem gry jest umieszczenie na planszy trzech swoich pionów w linii prostej - poziomo, pionowo lub po przekątnej.</p>

<form name="clearboard">

<input type="submit" value="Wyczyść planszę" onclick="window.location.reload()" />

</form>

</div>

</body>

</html>

Przedstawiony powyżej kod w końcu zapewnił wszystkie możliwości funkcjonalne strony. Przedstawiłam je na rysunkach 21.15 oraz 21.16. Zauważ, iż pomimo znacznych różnic kodu służącego do obsługi strony w przeglądarkach Netscape Navigator oraz Internet Explorer, w obu tych przeglądarkach strona wygląda i działa identycznie. Ale super!

Dalsze poznawanie DHTML

Gorąco zachęcam Cię do odwiedzenia witryn WWW firm Microsoft oraz Netscape poświęconych DHTML. Każda z nich oferuje ciekawe spojrzenie na te zagadnienia.

Witryna firmy Microsoft (http://msdn.microsoft.com/workshop/cframe.htm?/workshop/ author/default.asp) zawiera niezliczone ilości informacji dotyczących możliwości użycia DHTML dostępnych w przeglądarkach Internet Explorer 4 oraz 5.

Firma Netscape wydaje się przeważać w pojedynku na zapewnienie możliwości wykonywania kodu w różnych przeglądarkach i na swojej witrynie http://devedge.netscape.com udostępnia wiele artykułów i informacji technicznych.

0x01 graphic

Rysunek 21.15.

Końcowa wersja strony wyświetlona w przeglądarce Internet Explorer 5.5

0x01 graphic

0x01 graphic

Rysunek 21.16.

Końcowa wersja strony wyświetlona w przeglądarce Netscape Navigator 4.6

0x01 graphic

Poniżej podałam listę innych witryn zawierających ciekawe informacje dotyczące DHTML:

Podsumowanie

W tym rozdziale dowiedziałeś się, że Dynamiczny HTML tworzą trzy technologie: HTML, arkusze stylów oraz skrypty. Każda z nich jest niezwykle istotna i pełni unikalną rolę. HTML tworzy podstawę umożliwiającą tworzenie stron WWW. Arkusze stylów pozwalają na formatowanie elementów stron i umieszczanie ich w wybranych miejscach. Skrypty są natomiast elementem zapewniającym „dynamizm” DHTML.

Niestety, DHTML boryka się z wieloma problemami. Największym z nich są niespójności pomiędzy implementacjami technologii tworzących DHTML, użytymi w poszczególnych przeglądarkach. Sprawiają one, iż tworzenie stron DHTML działających poprawnie w różnych przeglądarkach staje się poważnym wyzwaniem.

W tym miejscu obszernie omówiłam DHTML oraz tworzące go technologie. Niemniej jednak rozdział ten, w żadnym wypadku, nie może posłużyć za wyczerpujący podręcznik, szczegółowo wyjaśniający wszelkie aspekty DHTML.

Warsztat

W tym rozdziale dowiedziałeś się, jak należy posługiwać się kilkoma różnymi technologiami, określanymi ogólnie jako DHTML. Technologie te umożliwiają precyzyjne określenie wyglądu i dają możliwość tworzenia stron reagujących na poczynania użytkowników. W dalszej części rozdziału znajdziesz pytania i odpowiedzi oraz quiz dotyczący kilku najistotniejszych zagadnień tu omawianych.

Pytania i odpowiedzi

P. Czy nauka DHTML jest warta zachodu?

O. To naprawdę trudne pytanie. Bardzo mnie kusi, aby odpowiedzieć „nie”, jednak może się zdarzyć, że będziesz musiał (bądź chciał) stworzyć rozwiązania, które można uzyskać jedynie przy wykorzystaniu DHTML. Jeśli zaliczasz się do tej kategorii twórców stron WWW, to faktycznie, nauka DHTML jest warta zachodu. Jeśli jednak spędzasz cały wolny czas na próbach stworzenia rewelacyjnej strony WWW, której w efekcie nigdy nie publikujesz, to może warto, abyś rozpoczął naukę od podstaw i dopiero później zabrał się za poznawanie DHTML.

P. Jest tyle rzeczy, których się trzeba nauczyć. Od czego należy zacząć?

O. Bezwzględnie od HTML. Musisz się stać prawdziwym ekspertem w tej dziedzinie.

Następnie będziesz miał dwa rozwiązania: nauczyć się wszystkiego lub wybrać tylko te zagadnienia, które będą Ci potrzebne.

Metoda polegająca na poznaniu wszystkiego sprowadza się do opanowania, w pierwszej kolejności, języka HTML, a następnie CSS oraz tworzenia skryptów. Przy czym naukę kolejnych technologii należy zaczynać, dopiero gdy poprzednie zostaną opanowane w odpowiednio wysokim stopniu. Gdy poznasz już wszystkie trzy technologie tworzące DHTML, powinieneś zrozumieć ich wzajemne zależności i spróbować swych sił w tworzeniu dokumentów DHTML.

Druga opcja, polegająca na nauce wybranych zagadnień, umożliwia szybsze rozpoczęcie tworzenia stron WWW przy wykorzystaniu DHTML. Sprowadza się ona do określenia i poznania techniki, której chcesz użyć, na przykład, wyświetlania i ukrywania wybranego elementu strony. Stosując to podejście, będziesz poznawał elementy wszystkich trzech technologii tworzących DHTML, jednak wyniki będą zauważalne niemal od razu.

P. Jakie są kierunki rozwoju DHTML?

O. W3C pracuje obecnie nad stworzeniem bardziej standaryzowanego modelu obiektów dokumentu, określanego jako DOM Level 2 (DOM poziomu 2). Aktualnie większość tych rozwiązań została już zaimplementowana w przeglądarce Internet Explorer 5, prawdopodobnie pojawią się one także w kolejnej (piątej) wersji Netscape Navigatora. Zapowiadana kolejna oficjalna wersja DOM będzie się znacznie różnić od aktualnie stosowanych rozwiązań.

P. A co ze znacznikami LAYER stosowanymi w Netscape Navigatorze oraz innymi rozwiązaniami DHTML używanymi wyłącznie w przeglądarkach konkretnego typu?

O. Według mnie, jeśli w ogóle chcesz się zajmować DHTML, to powinieneś skoncentrować się na tworzeniu stron działających w różnych przeglądarkach. Jedynie w ten sposób, tworząc (stosunkowo) uniwersalne strony WWW, będziesz mógł dotrzeć do największej grupy odbiorców (choć jednocześnie, rezygnując z zaawansowanych możliwości poszczególnych przeglądarek, możesz stracić drobną część potencjalnych użytkowników). Muszę przyznać, iż wykorzystanie unikalnych możliwości poszczególnych przeglądarek może być bardzo kuszące, a uzyskiwane dzięki nim efekty są bardzo atrakcyjne. Niemniej jednak, nic chyba nie jest bardziej frustrujące od spędzenia wielu tygodni na tworzeniu rewelacyjnej strony DHTML i odkryciu, że przeważająca część użytkowników nie może jej oglądnąć.

Quiz

  1. Jakie trzy technologie tworzą DHTML?

  2. Co to jest model obiektów dokumentu (DOM)?

  3. Czy do tworzenia stron DHMTL można używać języka VBScript lub innego języka skryptowego?

  4. Jaki jest najistotniejszy element stron DHTML, które działają na różnych przeglądarkach?

Odpowiedzi

  1. HTML, arkusze stylów oraz technologie skryptowe.

  2. „Język” używany przy odwoływaniu się do obiektów stron WWW, którymi można manipulować z poziomu skryptów. Pamiętaj, że zarówno w przeglądarce Internet Explorer, jak i Netscape Navigator w odmienny sposób implementują model obiektów dokumentu (DOM). Z tego względu odwołania do tego samego elementu strony w obu przeglądarkach będą wyglądały w inny sposób.

  3. Tak. Pamiętaj jednak, iż obsługa języka VBScript w przeglądarce Netscape Navigator wymaga użycia specjalnego plugina. Wykorzystanie innych języków skryptowych może być jeszcze trudniejsze. Zatem najlepszym rozwiązaniem jest użycie języka JavaScript.

  4. Bez wątpienia, elementem tym jest funkcja służąca do określania rodzaju i wersji przeglądarki. Funkcja ta musi być w stanie precyzyjnie i bezbłędnie rozpoznać wszystkie dostępne rodzaje przeglądarek. Tylko w ten sposób będziesz mógł modyfikować kod i zapewnić poprawne działanie strony w wybranych przeglądarkach.

Ćwiczenia

  1. Zmodyfikuj grę w kółko i krzyżyk w taki sposób, aby można było grać z komputerem.

  2. Skopiuj z WWW biblioteki funkcji DHTML, które można wykorzystywać w różnych przeglądarkach; następnie zmodyfikuj grę w kółko i krzyżyk, dodając nowe efekty lub zastępując początkowe rozwiązania nowymi funkcjami.

Informacje na ten temat można też znaleźć pod adresem: http://developer.netscape.com:80/evangelism/tools/practical-browser-sniffing/.

Zagrajmy.

648 Część 7. JavaScript i Dynamiczny HTML

Rozdział 21. Użycie Dynamicznego HTML-a 647

Tytuł strony „wysuwa się” z lewego, górnego wierzchołka strony

Pionki biorące udział w grze są początkowo ukryte, pojawiają się w momencie kliknięcia pustego pola planszy

Każde pole planszy jest odrębnym elementem

Przycisk czyści planszę i przygotowuje ją do kolejnej gry



Wyszukiwarka

Podobne podstrony:
R-06-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-B-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-00-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-25-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-F-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-29-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-E-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-G-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-01-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-14-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-09-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-11-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-08-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-24-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-17-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-02-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-H-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-18-07, Programowanie, ! HTML, HTML 4 - Vademecum
R-30-07, Programowanie, ! HTML, HTML 4 - Vademecum

więcej podobnych podstron