Narzędzia użytkownika

Narzędzia witryny


pl:tiim:lab_tiim_js

Laboratorium, TIiM, 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ęć.

Uruchamianie aplikacji z borga lokalnie

Służy do tego polecenie ltsp-localapps, np.:

ltsp-localapps firefox
ltsp-localapps google-chrome --proxy-server=10.0.0.254:3128

Ważne jest ustawienie proxy na 10.0.0.254:3128 - polecenie dla Chrome posiada już odpowiedni switch.

Ć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.

Firebug jest niezwykle użytecznym narzędziem dla developerów. Proszę uruchomić Firefoksa poleceniem:

firefox &

Na serwerze borg zainstalowany jest Firefox (iceweasel) w wersji 3.0.6, natomiast na serwerze charon w wersji 2.0.0.19. Najnowszą wersją Firebuga współpracującą z przeglądarką w wersji 3.0.6 jest wersja 1.4.5, natomiast dla wersji Firefoxa 2.0.0.19 proszę użyć Firebuga w wersji 1.3.1. Proszę zainstalować odpowiednią wersję Firebuga i ponownie uruchomić przeglądarkę. W prawym dolnym rogu pojawi się ikonka, po kliknięciu której otwiera się na dole panel Firebuga.

Na początek, proszę przygotować plik HTML o następującej treści:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>Lab JS</title>
</head>
<body>
	<form name="formularz">
		<p id="akapit"><input type="button" value="Rysuj!"></p>
	</form>
</body>
</html>

Proszę otworzyć panel Firebuga 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, FireBug zwróci referencję do obiektu klasy Document. Po kliknięciu tego linku prawym klawiszem można wybrać opcję Zbadaj w karcie DOM.

W zakładce DOM można przeglądać i zmieniać właściwości obiektu oraz jego metody:

LOL Proszę, poprzez edycję odpowiedniej właściwości, zmienić tytuł strony pojawiający się w pasku tytułowym okna przeglądarki.

Parametry te zmieniać można również 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. 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ą 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:

<script type="text/javascript">
	function mojaFunkcja(tekst) {
		console.log('Wywołanie funkcji z parametrem: ' + tekst);
	}
</script>
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:

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

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. 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::

<div onclick="alert('OMG! They clicked Kenny!');">Kenny</div>
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.:

...
<head>
<script type="text/javascript">
var x = 5;
 
function display() {
  window.alert(x);
}
</head>
</script>
 
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'':
 
<code javascript>
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:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>Lab JS liczniki czasu</title>
 
<script type="text/javascript">
<!--
var czas = -1
function odliczaj(){
	czas++
	document.getElementById('czas').innerHTML = czas;
	setTimeout("odliczaj()",1000);
}
// -->
</script>
 
</head>
<body onload="odliczaj()">
	<p><span>Licznik czasu: </span><span id="czas">0</span></p>
</body>
</html>
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:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>Lab JS batak</title>
<style type="text/css">
div#d1, div#d2, div#d3, div#d4 {
	background-color: red;
	width: 50px;
	height: 50px;
	position: absolute;
}
div#d1 {
	top: 10px;
}
div#d2 {
	right: 10px;
}
div#d3 {
	bottom: 10px;
}
div#d4 {
	bottom: 10px;
	right: 10px;
}
div#srodek {
	text-align: center;
}
</style>
</head>
<body>
	<div id="d1" onclick="wcisnieto(1)"></div>
	<div id="d2" onclick="wcisnieto(2)"></div>
	<div id="d3" onclick="wcisnieto(3)"></div>
	<div id="d4" onclick="wcisnieto(4)"></div>
	<div id="srodek">
		<form action="#">
			<p><input type="button" value="start" onclick="start()" /></p>
		</form>
		<p id="komunikat"></p>
	</div>
</body>
</html>

Zadanie 2: drag & drop

Dany jest plik HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>Drag and Drop!</title>
	<style type="text/css" media="screen">
		body {
			background-color: #DDD;
		}
		#kwadrat {
			position: absolute;
			left: 100px;
			top: 100px;
			width: 100px;
			height: 100px;
			background-color: red;
			cursor: pointer;
		}
	</style>
	<script type="text/javascript" charset="utf-8">
		// tu będą skrypty...
	</script>
</head>
 
<body>
	<div id="kwadrat"></div>
</body>
</html>

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.

pl/tiim/lab_tiim_js.txt · ostatnio zmienione: 2021/01/08 14:09 (edycja zewnętrzna)