====== Laboratorium, JiTW, JavaScript ====== JavaScript jest językiem skryptowym, w odróżnieniu od PHP wykonywanym po stronie klienta i stanowi podstawę interaktywnych stron WWW. Składnia JS przypomina tę znaną z języka C czy Java. JS wprowadza elementy obiektowości, a do jego podstawowych mechanizmów należą: * DOM - drzewo obiektów odwzorowujących wszystkie elementy strony oraz ich właściwości, * zdarzenia - mechanizm pozwalający m.in. na uzyskanie efektu interakcji z użytkownikiem, polegający na definiowaniu procedur uruchamianych po wystąpieniu w danym obiekcie określonego zdarzenia (np. najechanie kursorem myszy), * timery - pozwalają na zaplanowanie wykonania funkcji po upływie określonego czasu; stanowią podstawę animacji w JS oraz modelowania dynamiki interfejsu użytkownika. JavaScript posiada również bogatą bibliotekę funkcji wbudowanych, służących m.in. do obsługi zegara czy operacji matematycznych. Problem wymiany danych przez aplikację działająca w przeglądarce użytkownika z serwerem rozwiązywany jest przez metodologię AJAX, polegającą na wykonywaniu z poziomu JavaScript zapytań HTTP bez widocznego dla użytkownika przeładowania strony. AJAX będzie stanowił jeden z tematów kolejnych zajęć. ===== Ćwiczenia ===== ==== Ćwiczenie 1: Eksploracja obiektów DOM ==== Obiektowy Model Dokumentu (DOM - //Document Object Model//) jest strukturą drzewiastą przechowującą obiekty reprezentujące wszystkie elementy strony. Korzeniem części drzewa odpowiedzialnej za sam dokument HTML jest obiekt globalny ''document''. Na początek, proszę przygotować plik HTML o następującej treści: Lab JS

Proszę otworzyć panel Narzędzi Deweloperskich przeglądarki i włączyć konsolę. Konsola pozwala na wpisywanie dowolnych wyrażeń i poleceń JavaScript i wykonywanie ich w czasie rzeczywistym. Proszę wpisać: document W odpowiedzi, przeglądarka zwróci referencję do obiektu klasy **Document**. Można go klknąć i zobaczyć co kryje w środku. {{:pl:tiim:firebug-document.png}} Parametry te zmieniać można przy pomocy samego kodu JS, np.: document.title = "Ala ma kota" JavaScript posiada funkcje pozwalające na dotarcie do konkretnych obiektów w drzewie DOM: * //getElementById// - obiekt o określonym identyfikatorze, * //getElementsByName// - kolekcja obiektów o określonej wartości parametru ''name'', * //getElementsByClassName// - kolekcja obiektów danej klasy, * //getElementsByTagName// - kolekcja obiektów danego typu. Proszę sprawdzić działanie następujących poleceń: document.getElementById('akapit'); document.getElementsByName('formularz'); document.getElementsByName('formularz')[0]; document.getElementsByTagName('input'); document.getElementsByTagName('input')[0]; document.getElementsByTagName('input')[0].type; Proszę zwrócić uwagę jakie opcje pojawiają się w menu kontekstowym linku do określonego obiektu, m.in. //Badaj w karcie HTML// i //Badaj w karcie DOM//. LOL Proszę, przy pomocy jednego polecenia JS, wstawić napis z przycisku do paska tytułu przeglądarki. Każdy element HTML, który "w środku" posiada jakąś wartość, posiada też atrybut //innerHTML//, przechowujący kod HTML tej wartości. Proszę spróbować: document.getElementById('akapit').innerHTML; ==== Ćwiczenie 2: manipulowanie CSS przy pomocy JS ==== Każdy obiekt w DOM posiada składową ''style'', przechowującą jego wszystkie parametry CSS. Proszę wydać polecenie: document.getElementById('akapit').style; Firebug pozwala na badanie obiektów klasy **CSSStyleDeclaration** w zakładce CSS oraz w zakładce DOM. Ponieważ akapit nie posiada przypisanego stylu, w zakładce CSS nie pojawi się nic -- proszę więc otworzyć zakładkę DOM i przejrzeć wszystkie (puste) właściwości tego obiektu. Czy ich nazwy coś Państwu przypominają? LOL Proszę zmodyfikować styl akapitu poprzez ustawianie odpowiednich wartości określonych właściwości obiektu (w zakładce Konsola). ^ Top Tip ^ | Kolory w CSS można wyrazić przy pomocy ciągów znaków o następującej postaci: \\ 1. nazwa koloru (wg. [[http://www.w3schools.com/css/css_colornames.asp|specyfikacji]]), \\ 2. jak w "starym" HTML (np. ''#10DE34'') albo w postaci skróconej (''#0E8'' = ''#00EE88''), \\ 3. jako składowe RGB: przy pomocy wartości 8-bitowych (np. ''rgb(132,52,58)'') lub jako wartości procentowe (np. ''rgb(0%,20%,38%)''). | ==== Ćwiczenie 3: tworzenie nowego obiektu DOM ==== JS pozwala też na ingerencję w strukturę DOM, tzn. dodawanie i usuwanie obiektów. Do tworzenia nowych elementów strony służy metoda ''createElement'' obiektu DOM. Proszę wykonać polecenie: document.createElement('div'); Polecenie to jednakże nie dodaje elementu do dokumentu, a jedynie tworzy nowy obiekt w pamięci i zwraca do niego referencję. Ponieważ DOM ma strukturę drzewiastą, taki nowo utworzony element należy dodać jako dziecko jednego z już istniejących elementów. (Dobrym pomysłem będzie tworzenie nowych elementów jako dzieci obiektu ''document.body'' :-) ) Proszę ponowić polecenie, ale zapamiętując w zmiennej (np. ''mojElement'') referencję do nowo utworzonego obiektu: var mojElement = document.createElement('div'); LOL Teraz proszę dodać jakiś tekst do wartości atrybutu //innerHTML// tego obiektu, a następnie dodać go do drzewa DOM: document.body.appendChild(mojElement); ==== Ćwiczenie 4: operacje matematyczne w JS ==== JavaScript posiada bogatą [[http://www.w3schools.com/jsref/jsref_obj_math.asp|bibliotekę funkcji matematycznych]]. Proszę sprawdzić działanie następujących poleceń: Math.floor(2.54); Math.ceil(2.54); Math.round(2.54); Math.floor(-2.54); Math.ceil(-2.54); Math.round(-2.54); Math.min(4, 6, 2, 10); Math.random(); JS udostępnia też kilka użytecznych stałych, m.in.: Math.E; Math.PI; LOL Proszę przygotować polecenie, które generuje losowe liczby **całkowite** z zakresu 0-255. ==== Ćwiczenie 5: Tworzenie funkcji ==== Funkcje JS umieszcza się w pliku HTML najczęściej w sekcji ''head'': * bezpośrednio lub * w osobnym dołączonym pliku JS. Aby umieścić kod JS bezpośrednio, należy dodać następujący kod: ^ Top Tip ^ | W powyższym kodzie "przy okazji" proszę zwrócić uwagę na dwie rzeczy. Po pierwsze, skorzystaliśmy z obiektu ''console'', udostępnianego przez wtyczkę Firebug, aby pisać bezpośrednio na konsolę. Jest to bardzo użyteczne narzędzie przy debugowaniu tworzonych aplikacji webowych. Po drugie, konkatenacji stringów w JS dokonuje się przy pomocy operatora ''+''. | Alternatywnie, zawartość elementu ''script'' można umieścić w osobnym pliku, np. ''skrypty.js'' i zmodyfikować ten kod w następujący sposób: Takie wywołania często stosuje się do dołączania "hostowanych" wersji popularnych bibliotek JS, takich jak jQuery, Prototype czy Google Maps API. LOL Proszę napisać funkcję, która po wywołaniu dodaje do dokumentu (a dokładnie obiektu ''body'') nowy element typu akapit (''p''), zawierający jakiś określony, stały tekst i losowy kolor tła. ==== Ćwiczenie 6: zdarzenia ==== Interaktywność stron WWW (m.in. takich jak GMail) wykorzystujących JS oparta jest w dużej mierze na tzw. [[http://www.w3schools.com/jsref/dom_obj_event.asp|zdarzeniach]] (ang. //events//). Każdy obiekt posiada zbiór zdarzeń, na które może zareagować. Do najczęściej wykorzystywanych zdarzeń należą: * onclick, * onmouseover, * onmouseout, * onload, * onchange. Procedurę obsługi zdarzenia można przypisać do obiektu bezpośrednio w kodzie HTML, na przykład::
Kenny
^ Top Tip ^ | Przy okazji proszę zwrócić uwagę na wywołanie funkcji //alert//. JavaScript posiada też dwie podobne do niej funkcje - //prompt// oraz //confirm//. | LOL Zmodyfikuj kod strony tak, aby po kliknięciu przycisku wywoływała się funkcja napisana w poprzednim ćwiczeniu. ==== Ćwiczenie 7: dynamiczne przypisywanie zdarzeń ==== Procedura obsługi określnego zdarzenia do danego obiektu może też zostać przypisana dynamicznie w kodzie JS, np.: document.getElementsByTagName('p')[0].onclick = function(e) { console.log(e); } Powyższy fragment kodu przypisuje do pierwszego elementu typu ''p'' na stronie funkcję obsługi zdarzenia. Do takiej funkcji zawsze przekazywany jest parametr -- referencja do obiektu przechowującego parametry zdarzenia (w przykładzie nazywa się ''e''). W funkcji znajduje się polecenie wypisania referencji tego obiektu w konsoli Firebuga. Proszę przejrzeć własności tego obiektu w zakładce DOM Firebuga. Atrybut //target// przechowuje referencję do obiektu, który został kliknięty. Można więc dotrzeć do wszystkich atrybutów tego obiektu. LOL Proszę zmodyfikować kod z poprzedniego zadania tak, aby przypisać do zdarzenia ''onclick'' tworzonych akapitów wywołanie funkcji. Funkcja ta powinna wyświetlać okienko typu //alert//, zawierające wartość atrybutu CSS ''background-color'' klikniętego obiektu. LOL Proszę zmodyfikować funkcjonalność nowo tworzonych akapitów tak, aby po najechaniu na nie myszką ich kolor zmieniał się na inny, losowy. ==== Ćwiczenie 8: zmienne globalne ==== JS pozwala na definiowanie zmiennych globalnych. Zmienne te są widoczne z poziomu każdej funkcji; zasięg widoczności zmiennej ustalany jest podobnie jak w języku C, tzn. zmienna zadeklarowana poza funkcją jest widoczna w obrębie całego kodu, np.: ... Jak widać, zmienną taką można również zainicjalizować wartością. Zmienne globalne są użyteczne do zapamiętywania stanu różnych wartości, takich jak różne liczniki czy timery (o tym w kolejnych zadaniach). W rzeczywistości, zmienne globalne są składowymi obiektu ''window'': var myValue; function setValue() { myValue = "test"; } function getValue() { alert(window.myValue); } LOL Proszę wykonać powyższy kod i zwrócić uwagę, jak "dostajemy się" do zmiennej ''myValue'' w jednej i w drugiej funkcji. ==== Ćwiczenie 9: licznik czasu ==== Javascript dostarcza także mechanizmy kontroli czasu. Możemy np. określić wykonanie jakiegoś kodu po określonym czasie. Do tego celu służą zdarzenia czasowe, w obiekcie window: * setTimeout() * clearTimeout() Ich użycie jest następujące: var id = setTimeout("polecenie javascript",liczba_milisekund); Metodą ''setTimeout'' uruchamiamy proces odliczania czasu. Metoda ta zwraca identyfikator konkretnego procesu odliczania, zatem używając jej możemy uruchomić więcej niż jeden proces odliczający czas. Ustalając dla każdego procesu indywidualny identyfikator, możemy każdy z tych procesów przerwać stosując metodę ''clearTimeout()'', argumentem której powinien być wspomniany identyfikator danego procesu. Wypróbuj działanie następującego kodu: var moj_stoper = setTimeout("console.log('krok')",3000); oraz var moj_stoper = setTimeout("console.log('krok')",3000); clearTimeout(moj_stoper); Wykorzystując rekurencję, możemy stworzyć licznik czasu przebywania na stronie: Lab JS liczniki czasu

Licznik czasu: 0

^ TOP TIP ^ |Zauważ, w jaki sposób pierwszy raz wywołana została funkcja ''odliczaj()''! Wykorzystane zostało zdarzenie zachodzące w momencie wczytania (pobrania) strony internetowej do przeglądarki.| LOL Dodaj do powyższego skryptu funkcjonalność wypisującą słownie słowo "sekunda" uwzględniając koniugację np. 1 sekunda, 2 sekundy, ..., 5 sekund, itp. ===== Zadania dla zainteresowanych ===== ==== Zadanie 1: batak z pomiarem refleksu ==== Kierowcy Formuły 1 ćwiczą swój refleks i koordynację na specjalnej maszynie - Batak. Ćwiczenie to polega na naciskaniu podświetlających się przycisków w jak najkrótszym czasie. Stwórz komputerowy symulator urządzenia Batak. Pojedynczy czas reakcji (w sekundach) można obliczyć w następujący sposób: var czasStart = new Date(); ... var czasStop = new Date(); var czasReakcji = (czasStop.getTime()-czasStart.getTime())/1000 Szkielet strony HTML do napisania programu znajduje się poniżej: Lab JS batak

==== Zadanie 2: drag & drop ==== Dany jest plik HTML: Drag and Drop!
Celem tego zadania jest zrealizowanie funkcjonalności //drag & drop//, czyli umożliwienie użytkownikowi przeciągania czerwonego kwadratu w dowolne miejsce okna przeglądarki. Funckjonalność ta powinna być zrealizowana w oparciu o zdarzenia ''onmousemove'' (ruch myszą), ''onmousedown'' (wciśnięcie przycisku myszy) oraz ''onmouseup'' (puszczenie przycisku myszy), przypisane do kwadratu (patrz ćwiczenia 6 i 7). Najważniejszą rzeczą do zrobienia jest przesuwanie kwadratu do określonego miejsca. Przejrzyj atrybuty obiektu o id ''kwadrat'' w zakładce //Inspektor DOM//. Spróbuj, korzystając z konsoli, opracować metody przesuwania kwadratu o odpowiednią odległość w wybraną stronę przy pomocy JavaScript. **Uwaga:** funkcja w zdarzeniu ''onmousemove'' nie powinna //zawsze// przesuwać kwadratu. Przesuwanie powinno być realizowane tylko jeżeli użytkownik kliknął na kwadrat i trzyma wciśnięty przycisk myszy. Przyda się do tego zmienna globalna (patrz ćwiczenie 8), przechowująca informację o tym czy obiekt jest obecnie przeciągany czy nie.