Praktyczne wprowadzenie do JavaScript #20

Przed Wami 20. odcinek Praktycznego wprowadzenia do JavaScript. Odcinek jubileuszowy. Cieszę się, że doszliśmy do tego etapu, a pozytywne komentarze tylko potwierdziły, że warto robić to, co robię. Dzisiaj troszkę powspominamy, ale i też nauczymy się wielu nowych rzeczy. Będzie to niejako podsumowanie naszej wiedzy, a także wprowadzenie terminów i objaśnień, które do tej pory istniały poza naszym widnokręgiem.

Wszystko zaczęło się tak: (jak to napisałem w pierwszej notce na tym blogu):

W Ferrante.pl: napisałem:

Obecnie, kiedy Internet ugina się pod stosami nikomu niepotrzebnej treści, trudno jest zacząć swoją przygodę w świecie aplikacji internetowych. Wartościowe materiały są niezwykle rozproszone, przeplatają się nieraz z nic nie wartym bełkotem. Zdarzają się też sumienne i profesjonalne artykuły, które jednak w bezpośredniej konfrontacji z początkującym stają się zupełnie niezrozumiałe i trudne w odbiorze poprzez nad wyraz fachowy język i terminologię.

Do dzisiaj utrzymuję to, co napisałem pół roku temu. Jeśli chodzi o przekazywanie wiedzy, sytuację ratują dziś nie specjalistycznie serwisy, jak to było dawniej, a blogi. Pasjonatów, ale przede wszystkim równolegle dobrych specjalistów w danych dziedzinach. Wystarczy spojrzeć na blogi Riddle’a, Ludwika, czy Jarosława Zabiełło, by przekonać się, że to właśnie w internetowych dziennikach tkwi dziś fenomen dydaktycznego Internetu.

Niedawno z Rothmanem dyskutowaliśmy o fenomenie Webhelpu, ale też i o spadku jego popularności. Doszedłem do wniosku, że upadek tego typu serwisów ma swoje przyczyny w braku odpowiedniej kadry redaktorskiej, ale i też z przekonania potencjalnych autorów, że lepszym pomysłem będzie dzielenie się swoją wiedzą pod własnym sztandarem, stąd cząstkowe aktualizacje w tego typu portalach. Dzisiaj to blog stał się naczelną formą dzielenia się wiedzą. Oczywiście kierują blogerami różne przesłanki, jedni chcą się promować, co w sumie nie jest niczym dziwnym, drudzy chcą zrobić coś dla siebie. W każdym bądź razie dzięki rozpowszechnionej modzie na blogi, widoczny jest trend, który mówi, że tak naprawdę bardziej zyskujemy prowadząc działalność dydaktyczną na swoim blogu, a nie publikując na serwisie, który jest często własnością jednego człowieka.

Oczywiście dużym minusem publikacji tematycznych na blogach jest rozproszenie treści, co w przypadku specjalistycznych wortali jest sytuacją marginalną. Na szczęście istnieją agregatory treści, jak choćby Technorati czy też 10przykazań. Muszę przyznać, że nie jestem zadowolony z formy powyższych serwisów, dlatego myślałem nad stworzeniem serwisu agregującego blogi techniczne, a w zasadzie posty, tłumaczące pewne sprawy w dostępny i czytelny sposób. Jak myślicie, ma to sens? Sądzę, że ułożenie czegoś podobnego w przemyślany sposób ma szansę powodzenia, bo, nie oszukujmy się, brakuje dzisiaj dobrego centrum poradnikowego, jeśli chodzi o webdev, nie wspominając już o software jako takim.

Do czego zmierzam. Wydaje mi się, że forma, jaką jest blog, przejęła dziś w dużej mierze dość spory segment branży, jakim jest nauczanie nowych technologii. Pozostałą lukę zaś wypełniają specjalistyczne fora i grupy dyskusyjne. Wszystkim tym, którzy chcieliby spróbować podzielić się wiedzą w przemyślany i jasny sposób, proponuję rozpocząć działalność blogową. Sam wchodziłem w tą społeczność z zamkniętymi oczami, stąpając po niepewnym gruncie, jednak już po kilku dniach zrozumiałem, że blog to świetna forma na przekazanie swojej wiedzy, myśli i spostrzeżeń, ale i też wspaniały sposób na poszerzenie znajomości i poznanie ciekawych ludzi. Nie lękajcie się, dzielcie się swoją wiedzą, bo warto!

Najtrudniejszy pierwszy krok

Przez długi okres poprzedzający istnienie tego bloga, zastanawiałem się, jak zacząć, by nie spieprzyć swojej roboty już na początku. Szczególnie zależało mi na używaniu prostych pojęć, które miały być zrozumiałe dla wszystkich, mających CSS i HTML w małym palcu. Nie ukrywajmy, często takie osoby mają duże pojęcie o składaniu stron i grafice, ale jeśli chodzi o programistyczne myślenie jest już nieco gorzej. Jak wiemy też, JavaScript nieodłącznie towarzyszy obydwóm technologiom, tak więc dużym wyzwaniem było pogodzenie programistycznych terminów z przystępnością i prostotą cechującą choćby arkusze stylów.

Obiekty

Na samym początku kursu napisałem, że JavaScript to język obiektowy, ale zaraz potem stwierdziłem, że nie będziemy sobie zawracać głowy tą cechą języka. Sądzę, że to był jeden z punktów wyjściowych do dalszej pracy. Dziś możemy wyjaśnić tę terminologię. Najlepiej dostrzeżemy pewne sprawy na podanym niżej przykładzie:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	window.onload = function()
	{
		var p = document.getElementById('paragraph');
		alert(p);
	}
</script>

</head>
<body>
<div>
<p id="paragraph" style="margin: 2px;">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque metus eros, rutrum at, hendrerit nec, posuere ac.</p>

</div>
</body>
</html>

Jak widać, przed sobą mamy dokument HTML z jednym paragrafem, któremu nadaliśmy identyfikator o nazwie paragraph (id=”paragraph”). Podczas załadowania okienka ze stroną, pobieramy do zmiennej (var p = document.getElementById(‚paragraph’);) p odnośnik do tego właśnie akapitu. Następnie przekazujemy funkcji alert() jako argument utworzoną zmienną.

Jak zapewne domyślasz się, w okienku powinno się coś wyświetlić. Nie będzie to jednak treść, bo przecież musielibyśmy wpisać choćby p.innerHTML. Przekazujemy samą zmienną, która ma swoje właściwości (np. style.margin) i funkcje (np. setAttribute). Alert pobiera więc nie jakąś wartość, będącą liczbą, bądź ciągiem znaków, a kod JavaScript, który tworzy zmienna p.

Jak widzimy, w okienku pokazuję się wyraz [Object], bądź coś podobnego, w zależności od przeglądarki. Tłumacząc słówko z angielskiego, dochodzimy do wniosku, że chodzi o Obiekt. Zmienna p nie jest więc zmienną jako taką, a w istocie… obiektem.

Funkcje, które można wykonać na obiekcie, nazywamy też metodami.
Biorąc pod uwagę funkcję document.getElementById(), metodą jest tu funkcja getElementById, a obiektem, do którego należy: document. Jednym słowem, nawet dokument HTML (document) jest traktowany jako obiekt.

Zapytacie pewnie, co różni zmienną od obiektu? Otóż w najprostszym tłumaczeniu, obiekty mają swoje właściwości i funkcje, jakie można na nich wykonać, a zmienne przechowują tylko daną wartość. Logicznie rzecz ujmując, nazewnictwo to nawet się nie wyklucza, bo przecież p to zmienna, tyle że będąca obiektem (obiekt ten przechowuje jakieś wartości, jak choćby innerHTML).

Jak wspomniałem, obiekt dysponuje właściwościami i funkcjami. W naszym przykładzie za obiekt możemy przyjąć zmienną p. Udowodnijmy teraz, że jest tak w 100%, prezentując właściwości i funkcje (metody) tego obiektu, co jest najdobitniejszym dowodem, potwierdzającym naszą tezę:

Właściwości

Metody/funkcje

Jak więc widać, po pobraniu do zmiennej p odnośnika do paragrafu o id=”paragraph” zrobiliśmy z niej pełnoprawny obiekt, który ma swoje funkcje i właściwości, do których odnosimy się po kropce.

Pytanie jest następujące. Skąd wiemy, jakich funkcji i właściwości możemy użyć? To bardzo rozsądne pytanie, bo jasne jest, że nie wziąłem ich z kapelusza.

DOM, czyli Document Object Model po raz kolejny

Kluczem do rozwikłania tej zagadki jest poniższa linijka kodu:

var p = document.getElementById('paragraph');

Jak widać, standardowo pobraliśmy do zmiennej p odnośnik do paragrafu <p id=”paragraph”>, czyli elementu drzewa HTML. Jak wiemy natomiast z 14. części Praktycznego wprowadzenia, na elementach drzewa HTML operują funkcje skupione w tzw. DOM czyli:

[…] grupie funkcji i właściwości bezpośrednio związanych z operacjami na tagach dokumentów HTML, udostępnionych w JavaScript. […]

I tak, aby przekazać odnośnik do zmiennej (a wkrótce nowoutworzonemu obiektowi), używamy jednej z funkcji DOMgetElementById. Tym samym, biorąc pod uwagę, że funkcje DOM pozwalają operować na dowolnych tagach, do zmiennej p przekazujemy odnośnik do tego tagu paragrafu, wraz z całym asortymentem DOM – czyli wieloma funkcjami i właściwościami tegoż znacznika. Zmienna p może teraz korzystać z funkcji DOMowych, a że jak sama nazwa wskazuje, DOM składa się z obiektów, tam więc odnośniki do DOM są także obiektami.

Skupmy się na tym, jak to wygląda w uproszczeniu:

Wiele elementów DOM już znamy, natomiast cały spis znajdziesz tutaj. Oczywiście prawie każdą z tych funkcji i właściwości zajmiemy się w kolejnych odcinkach.

Obiekty wbudowane w JavaScript

W JavaScript możemy, oprócz manipulacji drzewem tagów HTML, wykonywać różne funkcje związane z datą, pobieranymi przez przeglądarkę obrazkami i tak dalej. W dużej mierze pozwalają na to wbudowane w język obiekty, które możemy przypisywać do zmiennych, które wtedy stają się obiektem danego typu.

Zajmijmy się najpierw obiektem typu Image

Obiekt Image

Często przychodzi nam podmienić jakiś obrazek po najechaniu nań myszką. Z reguły jednak wychodzi to dość brzydko, bo przeglądarka musi takowy obrazek najpierw załadować. Najlepiej więc byłoby, gdybyśmy mogli wgrać go podczas wczytywania całej strony. W tym celu przyda się nam właśnie obiekt Image, który będzie prekursorem, jeśli chodzi o objaśnianie, jak używać obiektów wbudowanych.

Zacznijmy, jak zwykle, od przygotowania dokumentu HTML.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład z obrazkami</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">
	
	var img;
	var img2;

	function dodajZdarzenie(odnosnik, zdarzenie, funkcja)
	{
		if (odnosnik.addEventListener)
		{
			odnosnik.addEventListener(zdarzenie, funkcja, false);
		}
		else
		{
			odnosnik.attachEvent("on"+zdarzenie, funkcja);
		}
	}
	

</script>

</head>
<body>
<p>
	<img src="http://ferrante.pl/examples/js/images/ferr2.jpg" alt="" id="obrazek" />
</p>
</body>
</html>

Przed nami dość proste w założeniach zadanie. Otóż po najechaniu kursorem na obrazek o id=”obrazek”, skrypt powinien podmienić atrybut src obrazka na http://ferrante.pl/examples/js/images/ferr1.jpg. Po zwolnieniu kursora, src przyjmuje defaultową wartość: http://ferrante.pl/examples/js/images/ferr2.jpg.

Jak widać w dokumencie, zdefiniowaliśmy na początek dwie zmienne globalne, widoczne dla każdej funkcji w skrypcie.

Po spojrzeniu na założenia, stwierdzamy, że podczas ładowania dokumentu, musimy wgrać do pamięci dwa obrazki. Przechowywane będą one w powyższych zmiennych. Następnie trzeba dać znać obrazkowi <img> o id=”obrazek”, że najechanie nań spowoduje podmianę atrybutu src. To samo dziać będzie się wraz ze zwolnieniem kursora. Za to odpowiedzialne będą funkcje PokazObrazek i UkryjObrazek.

Jako że powyższe procesy powinny się wykonać po załadowaniu dokumentu, wykorzystamy funkcję, którą nazwiemy, jak zwykle, Laduj, i wykonamy ją w zdarzeniu onload. Do dzieła!

<script type="text/javascript">
	
	var img;
	var img2;

	function dodajZdarzenie(odnosnik, zdarzenie, funkcja)
	{
		if (odnosnik.addEventListener)
		{
			odnosnik.addEventListener(zdarzenie, funkcja, false);
		}
		else
		{
			odnosnik.attachEvent("on"+zdarzenie, funkcja);
		}
	}
	function PokazObrazek()
	{
		
	}
	function UkryjObrazek()
	{
		
	}
	function Laduj()
	{
		
		
	}

	dodajZdarzenie(window, "load", Laduj);

</script>

Pora uzupełnić naszą funkcję Laduj. Stwierdziliśmy, że do załadowania obrazków podczas ładowania strony użyjemy obiektu Image. Jak już dowiedzieliśmy się z pierwszej części, z reguły jakaś zmienna staje się obiektem po wykonaniu jakieś funkcji (tam było to document.getElementById). Otóż wbudowany obiekt tworzymy i przypisujemy do zmiennej w ten sposób:

zmienna = new Nazwa_Obiektu();

Wcześniej uznaliśmy, że obrazki przechowywać będą zmienne img i img2. Wywołania wyglądałyby więc tak:

img = new Nazwa_Obiektu();
img2 = new Nazwa_Obiektu();

Za ładowanie obrazków odpowiedzialny jest zaś wbudowany obiekt o nazwie Image, więc podstawiamy jego nazwę:

function Laduj()
{
	img = new Image();
	

	img2 = new Image();
		
}

Tym sposobem utworzyliśmy dwa, nowe obiekty typu Image. Sprawdzić to możemy używając okienka alert().

function Laduj()
{
	img = new Image();
	alert(img);
	

	img2 = new Image();
	alert(img2);
		
}

Wyświetli się, w zależności od przeglądarki, [Object] bądź [object HTMLImageElement].

Jak to bywa, obrazek musi mieć atrybut src, by być obrazkiem jako takim. Trzeba więc każdemu nadać odpowiedni adres obrazka.

function Laduj()
{
	img = new Image();
	img.src = 'http://ferrante.pl/examples/js/images/ferr1.jpg';

	img2 = new Image();
	img2.src = 'http://ferrante.pl/examples/js/images/ferr2.jpg';
		
}

W takiej postaci funkcja Laduj załaduje nam do dwóch zmiennych/obiektów dwa obrazki. Zresztą powinieneś to zauważyć, obserwując pasek postępu w przeglądarce, kiedy to po załadowaniu HTML, wczytywane będą dwa pliki.

Pora uzupełnić naszą funkcję o dodanie zdarzeń dla obrazka.

function Laduj()
{
	img = new Image();
	img.src = 'http://ferrante.pl/examples/js/images/ferr1.jpg';

	img2 = new Image();
	img2.src = 'http://ferrante.pl/examples/js/images/ferr2.jpg';
		
	var obrazek = document.getElementById('obrazek');

	dodajZdarzenie(obrazek, "mouseover", PokazObrazek);
	dodajZdarzenie(obrazek, "mouseout", UkryjObrazek);
}

To:

dodajZdarzenie(obrazek, "mouseover", PokazObrazek);
dodajZdarzenie(obrazek, "mouseout", UkryjObrazek);

Doda dwa zdarzenia:

Pozostaje teraz nam zaimplementować działanie powyższych dwóch funkcji, tak, by zmieniały src głównego obrazka w dokumencie HTML.

function PokazObrazek()
{
	var obrazek = document.getElementById('obrazek');
	obrazek.src = img.src;
}
function UkryjObrazek()
{
	var obrazek = document.getElementById('obrazek');
	obrazek.src = img2.src;
}

Obydwie funkcje są w zasadzie podobne, tyle że pierwsza, PokazObrazek podmienia src obrazka o id="obrazek" na http://ferrante.pl/examples/js/images/ferr1.jpga a druga, UkryjObrazek na http://ferrante.pl/examples/js/images/ferr1.jpg. Voila:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład z obrazkami</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">
	
	var img;
	var img2;

	function dodajZdarzenie(odnosnik, zdarzenie, funkcja)
	{
		if (odnosnik.addEventListener)
		{
			odnosnik.addEventListener(zdarzenie, funkcja, false);
		}
		else
		{
			odnosnik.attachEvent("on"+zdarzenie, funkcja);
		}
	}
	function PokazObrazek()
	{
		var obrazek = document.getElementById('obrazek');
		obrazek.src = img.src;
	}
	function UkryjObrazek()
	{
		var obrazek = document.getElementById('obrazek');
		obrazek.src = img2.src;
	}
	function Laduj()
	{
		img = new Image();
		img.src = 'http://ferrante.pl/examples/js/images/ferr1.jpg';

		img2 = new Image();
		img2.src = 'http://ferrante.pl/examples/js/images/ferr2.jpg';
		
		var obrazek = document.getElementById('obrazek');

		dodajZdarzenie(obrazek, "mouseover", PokazObrazek);
		dodajZdarzenie(obrazek, "mouseout", UkryjObrazek);
		
	}

	dodajZdarzenie(window, "load", Laduj);

</script>

</head>
<body>
<p>
	<img src="http://ferrante.pl/examples/js/images/ferr2.jpg" alt="" id="obrazek" />
</p>
</body>
</html>

Screencast z tego przykładu znajdziecie tutaj, natomiast przykład na żywo tutaj.

Obiekt String

Drugim z obiektów wbudowanych jest obiekt String, który reprezentuje jakiś ciąg znaków. Idąc tym tropem, zmienną, będącą obiektem typu String będzie:

var ciag_znakow = "To jest ciag znakow";

lub

var ciag_znakow = "2313";

Słowem, wszystkie znaki przypisane do zmiennej, otoczone apostrofami bądź cudzysłowami.

Jeśli więc mamy zmienną zawierającą jakieś, przykładowe zdanie, to jest ona też obiektem typu String. Jak powiedzieliśmy, obiekty mają swoje charakterystyczne funkcje i właściwości, które można na nich wykonać. Również obiekty typu String nie są w tym odosobnione w tym przypadku. Pokażemy szerzej jedną z nich na poniższym przykładzie.

Dobrym sposobem na prezentację możliwości operacji na ciągach znaków jest animacja, symulująca pisanie danego zdania na klawiaturze. Chodzi o coś takiego, aby co sekundę dopisywany był nowy znak, aż powstanie całe zdanie:

Jak widać, musimy pobrać zdanie (które będzie zapisane w zmiennej). Potem uruchomić funkcję, która będzie się wykonywała co jakiś czas - tutaj pomoże nam funkcja window.setInterval, poznana odcinek wcześniej. Ostatnim elementem układanki będzie implementacja samej funkcji, uruchamianej cyklicznie.

Przeanalizujmy, jak będzie wyglądało jej uruchamianie:

Zacznijmy od dokumentu HTML.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład ze zdaniem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	var count = 0;
	var zdanie = new String("Ala ma kota");

</script>

</head>
<body>
<p id="zdanie">
	
</p>
</body>
</html>

Jak widać, w powyższym kodzie dysponujemy paragrafem o identyfikatorze równym zdanie. To w tym akapicie pokazywać będziemy animację, więc stosowny identyfikator był potrzebny, by móc dostać się do paragrafu (getElementById()) i zmienić jego wartość (innerHTML).

Uzupełniona została, co warto zauważyć, sekcja <script></script>. Mamy tutaj dwie zmienne:

Pora teraz nazwać funkcję, która będzie uruchamiana cyklicznie przez window.setInterval. Niech to będzie swojsko brzmiąca nazwa, PokazZdanie.

<script type="text/javascript"&glt;

	var count = 0;
	var zdanie = new String("Ala ma kota");

	function PokazZdanie()
	{
		
	}
	
	window.setInterval("PokazZdanie()", 200);

</script>

Jak widzimy, sprawa jest na tym etapie dość prosta. Uruchamiamy co 200 milisekund funkcję PokazZdanie, która z kolei jest pusta, więc efekt jej działania jest mizerny.

Pora zabrać się ze jej uzupełnienie, korzystając z planu, jaki ułożyliśmy wcześniej. Do roboty!

function PokazZdanie()
{
	count = count + 1;
}

Pierwsza linijka odpowiada za dodanie do zmiennej count wartości jeden. Ten zapis powoduje, że do zmiennej count dodajemy sumę jej dotychczasowej wartości i jeden. Równie dobrze możemy napisać:

function PokazZdanie()
{
	count += 1;
}

Co oznacza..., że do zmiennej count dodajemy jedynkę!

Pora sprawdzić, czy zmienna ta jest większa od liczby znaków naszego obiektu typu String, czyli, mówiąc prościej, zdania Ala ma kota.

function PokazZdanie()
{
	count += 1;
	if (count > zdanie.length)
	{
		document.getElementById('zdanie').innerHTML = '';
		count = 0;
	}
}

Istotą jest tutaj instrukcja warunkowa, która porównuje dwie wartości:

if (count > zdanie.length)

Lewa wartość jest nam znana, to zmienna count, którą powiększamy na początku o jeden. Potem musimy sprawdzić, czy jej wartość jest równa sumie znaków naszego zdania, które reprezentuje zmienna zdanie. Jako że jest ona obiektem, posiada swoje własności i funkcję. I tutaj korzystamy z jednej z własności, jaką jest "długość" obiektu - length. Jest to nic innego jak suma znaków obiektu typu String.

Przykładowo:

var wyraz = new String("Wyraz");
alert(wyraz.length);

Pokaże nam 5, bo słowo Wyraz ma istotnie pięć znaków...

Następna część warunku jest prosta - pobieramy odnośnik do paragrafu i czyścimy go poprzez ustawienie pustej wartości ''. Potem przypisujemy zmiennej count wartość zero, co oznacza, że liczymy (i pokazujemy animację) od nowa.

function PokazZdanie()
{
	count += 1;
	if (count > zdanie.length)
	{
		document.getElementById('zdanie').innerHTML = '';
		count = 0;
	}
		
	document.getElementById('zdanie').innerHTML = zdanie.substring(0, count)+"_";
	
}

To już ostatnia część naszej zabawy z funkcją PokazZdanie. Dodaliśmy poniższy kod:

document.getElementById('zdanie').innerHTML = zdanie.substring(0, count)+"_";

Jak widać, z lewej strony pobieramy odnośnik do naszego paragrafu i jego właściwość określającą zawartość tego tagu - innerHTML, - natomiast z prawej, no właśnie, przyjrzyjmy się co tam się stało:

zdanie.substring(0, count)+"_";
obiekt_typu_string.substring(liczba początkowa, liczba końcowa);

Metoda charakterystyczna dla obiektów typu String, która wycina znaki obiektu począwszy od liczby początkowej aż do liczby końcowej, licząc od lewej i zaczynając od zera.

jak widać, mamy coś w stylu obiekt.funkcja(). I rzeczywiście, zdanie, jak już powiedzieliśmy, jest obiektem String. substring musi być natomiast metodą obiektu, którą na nim wywołujemy, bo tylko metody (funkcje) wywołujemy z nawiasami, nieprawdaż?

Do dobra interpretacja, bo substring to jedna z charakterystycznych metod obiektów typu String. Wycina ona łańcuch znaków od jakiegoś znaku do jakiegoś znaku. Np.:

var wyraz = new String("Ferrante.pl jest ok!");
alert(wyraz.substring(0, 4));

wyświetli Ferr, bo rozkazaliśmy wyciąć znaki od pierwszego do czwartego. Niech nie myli Cię zero, będące pierwszym argumentem tej funkcji. W JavaScript znaki łańcucha liczymy od zera!

Ostatnim elementem, wymagającym wyjaśnienia jest +"_";. Tutaj po prostu z prawej strony tego, co wycięliśmy, dodajemy podkreślnik - zwykły łancuch znakowy, który dodajemy poprzez znak dodawania i cudzysłowy. Przerabialiśmy już to.

Pora teraz przedstawić gotowy dokument HTMl, jaki przed chwilą powstał:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład ze zdaniem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	var count = 0;
	var zdanie = new String("Ala ma kota");

	function PokazZdanie()
	{
		count += 1;
		if (count > zdanie.length)
		{
			document.getElementById('zdanie').innerHTML = '';
			count = 0;
		}
		

		document.getElementById('zdanie').innerHTML = zdanie.substring(0, count)+"_";
		
	}
	
	window.setInterval("PokazZdanie()", 200);


</script>

</head>
<body>
<p id="zdanie">
	
</p>
</body>
</html>

Screencast z tego przykładu znajdziecie tutaj, natomiast przykład na żywo tutaj.

Warto też popatrzeć na parę ciekawostek, związanych z obiektem typu String. Otóż, jako że JavaScript stara się być bardzo obiektowy, nie musimy wywoływać obiektu typu String używając new String(). Wystarczy, że użyjemy czegoś podobnego, jakże prostej konstrukcji przypisania:

var wyraz = "Ala ma kota";

Jest to dokładnie to samo, co

var wyraz = new String("Ala ma kota");

JavaScript to wygodny język i tworzy obiekt typu String dla zmiennej wyraz automatycznie!

Co więcej, aby dojść do właściwości różnych ciągów znaków, choćby ich długości, nie musimy ich najpierw zapisywać pod zmienną! Możliwe jest bowiem użycie podobnej konstrukcji:

alert("Ala ma kota".length);

Oczywiście, aby to zadziałało, musimy otoczyć zdanie apostrofami bądź cudzysłowami - ja wybrałem cudzysłowy. Bez tego JS nie rozpozna, że ma do czynienia z ciągiem znaków, co wielokrotnie staram się podkreślić.

Inne obiekty wbudowane

Obiektów wbudowanych w JavaScript jest jeszcze kilka. Są one jednak mało przydatne w konkretnych przykładach, używane są jako półśrodki. Oczywiście poznamy je, wykonując inne ćwiczenia w przyszłości.

Optymalizacja skryptów

Bardzo ważnym elementem w pisaniu skryptów JavaScript jest ich optymalizacja. Jak wiemy, ładujemy je tak jak każdy inny element strony. Dobrze jest więc poświęcić trochę czasu na ich odchudzenie. Weźmy na tapetę ostatni nasz dokument, gdzie ćwiczyliśmy na obiekcie String:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład ze zdaniem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	var count = 0;
	var zdanie = new String("Ala ma kota");

	function PokazZdanie()
	{
		count += 1;
		if (count > zdanie.length)
		{
			document.getElementById('zdanie').innerHTML = '';
			count = 0;
		}
		

		document.getElementById('zdanie').innerHTML = zdanie.substring(0, count)+"_";
		
	}
	
	window.setInterval("PokazZdanie()", 200);


</script>

</head>
<body>
<p id="zdanie">
	
</p>
</body>
</html>

Przede wszystkim należy wystrzegać się, jak w każdym języku programowania, powtórzeń w kodzie. Powyżej widzimy, że kilka elementów można by rozegrać inaczej. Powtarzają się choćby pobrania odnośników do paragrafu o id="zdanie":

document.getElementById('zdanie')

Dzieje się to dwa razy w obrębie jednej funkcji, warto więc na początku zapisać odnośnik do jakieś zmiennej, i potem ją podstawiać jako obiekt. Na przykład tak:

function PokazZdanie()
{
	var odnosnik = document.getElementById('zdanie');
	count += 1;
	if (count > zdanie.length)
	{
		odnosnik.innerHTML = '';
		count = 0;
	}

	odnosnik.innerHTML = zdanie.substring(0, count)+"_";
		
	}

Od razu lepiej. Idąc dalej, JavaScript to język bardzo elastyczny i jak każdy inny, pozwala definiować swoje funkcje, co robimy od pierwszego odcinka. Ta możliwość może przydać się też do odchudzenia kodu.

Jak zapewne dostrzegłeś, używamy bardzo często funkcji document.getElementById(). Jest to kilkanaście bajtów, które można by zminimalizować do kilku. Otóż możliwe jest napisanie własnej funkcji, która będzie się nazywać króciutko, a która też będzie pobierała odnośnik do danego elementu o określonym id., tak, jak to robi getElementById. Najkrótszym znakiem, jaki mi przychodzi do głowy, jest znak dolara - $. Spróbujmy zdefiniować więc zalążek takiej funkcji:

function $()
{
}

Tak, tak - coś takiego jest możliwe. Ale jak widać, funkcja ta nic nie robi, a założyliśmy przecież, że będzie pobierała odnośnik do tagu o określonym id. Aby można było wielokrotnie jej użyć, dla dowolnego identyfikatora, musimy go przekazywać jako argument:

function $(id)
{
}

Wtedy będzie możliwe wywołanie tego typu:

a = $("jakis_id");
b = $("inny_id");
c = $("jeszcze_inny_id");

Gdybyśmy nie umożliwili wywołania funkcji z argumentem, musielibyśmy pisać w jej ciele identyfikatory, które chcemy użyć, np:

function $(id)
{
	id1 = 'jakis_id';
	id2 = 'inny_id';
	//itd;
}

Po co? Wtedy funkcja ta będzie się rozrastać bardzo, ale to bardzo. My stawiamy na elastyczność.

Mimo wszystko w tej postaci nadal nic z funkcją $ nie zrobimy. Nie zwraca ona odnośnika. W odcinku 9. poznaliśmy konstrukcję we funkcjach, które zwracają jakieś wartości - chodzi o return. Użyjemy go, do zwrócenia odnośnika, który pobierała będzie funkcja document.getElementById():

function $(id)
{
	return document.getElementById(id);
}

Voila! Teraz możemy przypisywać odnośniki w ten sposób:

var odnosnik = $("zdanie");

Czyż nie prościej?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl-PL">
<head>
<title>Przykład ze zdaniem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	var count = 0;
	var zdanie = new String("Ala ma kota");

	function $(id)
	{
		return document.getElementById(id);
	}

	function PokazZdanie()
	{
		var odnosnik = $("zdanie");
		count += 1;
		if (count > zdanie.length)
		{
			odnosnik.innerHTML = '';
			count = 0;
		}
		

		odnosnik.innerHTML = zdanie.substring(0, count)+"_";
		
	}
	
	window.setInterval("PokazZdanie()", 200);


</script>

</head>
<body>
<p id="zdanie">
	
</p>
</body>
</html>

Komentowanie kodu

Inną cechą, która charakteryzuje JavaScript i wiele innych języków programowania, jest możliwość komentowania kodu - czyli zapisywania swoich spostrzeżeń, objaśniania funkcji wewnątrz skryptów JavaScript, tak, by nie przeszkodzić w ich działaniu.

Jeśli chcemy dodać komentarz w jednej linijce, przydatne są dwa ukośniki:

// deklarujemy zmienną liczba
var liczba = 2;

Jeśli zaś chcemy, aby nasz komentarz mieścił się w kilku linijkach i nie przeszkadzał skryptowi, używamy /* TRESC KOMENTARZA */:

/* Ta zmienna będzie ważną częścią skryptu.

Powoduje ona bardzo magiczne procesy.

Strzeżcie się!*/

var zmienna = "Czarownica";

Zakomentować, oprócz naszych uwag, możemy także jakiś kod JavaScript, który przeglądarka pominie i nie wykona go:


// var liczba = 2;
/* if (liczba == 2)
{
}
*/

Ten kod będzie niewidoczny dla przeglądarki i nie wykona się!

Podsumowanie

Wierzę, że 20 odcinków wytężonej i mozolnej pracy - mojej, jak i Waszej - sprawiło, że dziś możecie powiedzieć - tak, JS jest stosunkowo łatwy. Jeśli nie, cóż, zawsze czeka nas kolejnych 20 spotkań w miłej atmosferze zdobywania wiedzy, czyż nie?

Komentarze

1

tum tum tum tum – glos gitary basowej brzmi w tle. muzyka zespolu zamowionego na jubieusz czterdziestu tysiecy znakow oraz dwudziestego kursu niejakiego Mistrza eF. charakteryzuje sie niesamowitym wyczuciem smaku, a equalizer programu odtwarzajacego muzyke posiada nadzwyczajne mozliwosci, na pochwale zasluguje equalizer. pub „dam ci wiele czyli u gosi k.” peka w szwach od kreatorow, architektow przestrzeni, bez ktorej dzis juz nie potrafimy zyc – internetu. doborowe towarzystwo skupione wokol Mistrza, zasysa kolejne kilobajty plikow chmielnych i nietylko. sluchaja jak ten opowiada anegdoty z jego zycia przesyconego barwami TrueColor. kazdy kto chce nadal istniec w tym swiecie, siedzi na jednym z wylozonych nie-byle-jaką teksturą fotelach. nawet ten slawny haker i programista, ktory od dluzszego czasu jest nieuchwytny dla zwyklych smiertelnikow, sam D J.Chr. tu przybyl. nie ma Ciebie wsrod nich? join and enjoy! just create an account below – it’s fast and it’s free!

Gal Ananim
2

to prawda .. strony specjalistyczne powoli upadaja a fora … szkoda gadac same newby ktore odsylaja do googli albo krytykuja bez sensu :) pare razy probowalem uzyskac pomoc na forach .. bezskutecznie :/

Pj
3

Mam mały problem (kod się znajduje w dobrym miejscu, uljsdesign istnieje):
var design = document.getElementById('uljsdesign');
function onLoad()
{
alert(design);
design.style.display = "none";
}
window.onload = onLoad;

w okienku pojawi się „null”, a firebug pokaże błąd z przypisaniem „none”:
design has no properties.

Po wklejeniu deklaracji zmiennej do ciala funkcji działa.
Trochę się zdenerwowałem, myślałem że to jakaś literówka w prostym ale nagmatwanym kodzie (naszukałem się).

To jest tylko fragment, mam kilka takich zmiennych (to się chyba nazywa egzemplarzem? (chociaz gdyby ta lista była klasą to to byłby egzemplarz)), których używam w kilku funkcjach, dotychczas mialem to w każdej funkcji, ale po przeczytaniu któregoś odcinka (chyba 11) chciałem to zmienić według przykładu.

trochę się rozpisałem ;)
można jakoś to ominąć aby używać tych samych zmiennych-obiektów w każdej funkcji

JS
4

Pamietaj, ze JS ma dostep do DOM po jego zaladowaniu, wiec imho powinienes zostawic zmienna design pusta i w onload jej przypisac odnosnik:


var design;
function onLoad()
{

design = document.getElementById('uljsdesign');

}
window.onload = onLoad;

Zauwaz, ze nie dajesz drugi raz var, bo bys utworzyl zmienna wewnatrz funkcji, a tak, bez vara, odwolujesz sie do globalnej, tej, ktora zdefiniowales poza funkcjami.

5

rzeczywiście, obecnie fora i specjalistyczne wortale sa b. kiepskiej jakości. o wiele łatwiej znaleźć coś w blogosferze. dzięki wielkie za tak miłe słowa na początku – to zawsze bardzo mobilizuje. Do tej listy mógłbyś też śmiało siebie dopisać i to zdecydowanie na pierwszym miejscu, gdyż nie znam lepszego źródła wiedzy tudzież kursu niż Twój blog.

Co do agregatora blogów technicznych – popieram i to zdecydowanie… 10p jakoś już przestałem lubić, nie wiem czemu…

6

Świetny wstęp do JS właśnie tego szukałem całe 20 odcinków przerobiłem chyba w 6 h jednym ciągiem, tylko szkoda że od dana nie ukazał sie żaden nowy. Ale dodam ten blog do ulubionych, ostatnimi czasy moim głównym źródłem wiedzy są blogi bo w przystępny i użyteczny sposób przedstawiają zagadnienia. Szkoda że nie zainteresowałeś się Mootools bo z pośród (jQuery , Spry Adobe, Mootols) właśnie ten Framework wydał mi sie najbardziej obiecujący.

Kerim
7

Chciałem zapytać, jak zautomatyzować skrypt przy image, tak, żeby działał dla kilku obrazków. Bo ja potrzebuję 4 podmiany grafiki do 4 guzików.

8

Przeczytałem tylko kilka pierwszych akapitów. Jest w nich pare bzdur. W JS wszystko jest obiektem nawet Null czy Number. Można podzielić je na typy proste i złożone (pewnie znalazła by się lepsza nazwa niż typ). Typy proste to takie gdzie zmienna jest na stałe związana z jej wartością, złożone to takie gdzie zmienna jest WSKAŹNIKIEM na obiekt. Dość dużo mi czasu zajęło zrozumienie o co w tym chodzi i dlaczego w prototypach atrybuty się zachowują z pozoru niedeterministycznie (a może i nie z pozoru; jeszcze nie dokończyłem testów). Wygląda na to że typami prostymi są String, Integer, Null, Date i inne dostarczane przez język. Cała reszta włącznie z DOM itp są wskaźnikami. Być może jest to opisane w książce Zakasa a ja przeoczyłem. Wiadomo jeszcze, że każdy prototyp jest singletonem w którym zmieniamy wartości zmiennych a nie zmienne. Dla typów prostych oznacza to że np nie da się wewnątrz prototypu liczyć jego instancje chyba że umieścimy licznik w jakimś obiekcie i przechowamy na niego wskażnik. Tzn kiedy tworzymy instancję kopiowane są zmienne. Oznacza to że Integer jest kopiowany całościowo (każda instancja ma wskaźnik na inny obiekt). Jeśli kopiowane są typy złożone to zachowanie jest takie jak każdy normalny człowiek przewiduje.
Tak poza tym nie wiem czy dobrym pomysłem jest pisanie o DOM i HTMLu przy opisie JS. To są dwa różne światy. To że przeglądarki je łączą, nie oznacza, że JS=przeglądarka. Wręcz przeciwnie. Teraz jest boom na JS w KDE gdzie środowisko jest kompletnie inne i z tego artykułu sprawdza się pewnie z 10% rzeczy. Po przeczytaniu takiego kursu ludzie mogą być pewni że JS służy do generowania HTMLa np. I znowu wrócimy do czasów mieszania kodu z prezentacją (przedtem w PHP teraz w JS).

Adrian Kalbarczyk
9

Mistrzu, to jest kurs dla ludzi, ktorzy raczej ida droga wiodaca od znaku CSS. Chyba nie sadzisz, ze wyloze tutaj cala obiektowke, szargajac pr0 slownictwem.

Poza tym, uscislij gdzie jest te ‚kilka bzdur’, bo przyjmujac konwencje taka, jak napisalem, raczej ich nie dostrzegam.

Pozdro

10

Kolego Adrianie, może sam napisz jakiś kurs, zobaczymy jakim będzie się cieszył zainteresowaniem a następnie dopiero krytykuj innych.
Takich ludzi jak ty jest pełno na forach i specjalistycznych wortalach, dlatego też tracą one popularność, bo kto wróci tam po rade by skorzystać z google ?
Osobiście podziwiam ludzi którzy znajdują czas by przekazywać swą wiedzę w prosty i zrozumiały sposób dla innych, w dodatku za free.
Dlatego też uważam twój komentarz zupełnie nie na miejscu, wróć może na swoje forum lub bloga i tam się wymądrzaj, skoro nie rozumiesz że ten kurs przeznaczony jest dla początkujących a ty wyjeżdzasz z pro nazewnictwem.
A dla DAMIANA wielkie DZIĘKI za trud i poświęcony czas na prowadzenie tego bloga, chętnie będe tutaj wracał w poszukiwaniu wiedzy z której na co dzień korzystam. Pozdrawiam serdecznie, i dalszych sukcesów życzę zarówno na tym blogu jak i w życiu osobistym. George, UK

george
11

Kolega Adrian książkę Zakasa cytuje żywcem czuję. Co to bloga, to podziwiam autora za syntetyczne podejście do tematu, co bardzo ułatwia zrozumienie sedna rzeczy dla ludzi mniej zetkniętych do tej pory z JS. Brawo!

Kurt
12

No i dotarłem do ostatniej lekcji z serii „praktyczne wprowadzenie…” – wnioski naprawdę super. Nieskromnie powiem, że omówione zagadnienia już znałem, ale jakbym miał uczyć się od zera JS to byłoby to miejsce gdzie pierw bym zajrzał – świetna robota ! Przydałoby się też coś o Ajaxie.
Linki do kilku lekcji pozwoliłem sobie wrzucić do siebie.
Teraz poczytam o jQuery bo już dawno miałem to zrobić (ale leń ze mnie jest straszny..)

Życzę powodzenia i gratuluje.

13

dziękuję za wszystko i kłaniam się nisko,
super, dzięki, trzymaj się

mirmie
14

Witam.
Co prawda nie przeczytałem wszystkiego, ale chciałbym podziękować za kurs – naprawdę znaleźć coś takiego w sieci jest ciężko(mówię tu o innych językach). JS sie dopiero ucze, korzystałem z innych kursów ale ten jest nieporównanie lepszy – sama ilość przykładów jest wystarczająca do zrozumienia :)
Dzięki w imieniu reszty, co im się pisać nie chce podziękowań :)

Pozdrawiam
Darek

15

Dziękuje za ten kurs, dużo się z niego nauczyłem, wczoraj zacząłem od pierwszej części a nim się oglądnąłem 20 ;)
Bardzo podoba mi się styl w jakim piszesz, zachęca do dalszej nauki :)

To zabieram się za jQuery ^^
Wielkie Dzięki

Pozdrawiam.

Raphy
16

Przy okazji 20 odcinka również chciałbym podziękować za kurs. To niesamowite, że ludziom chce się robić takie rzeczy i do tego jeszcze w tak rzetelny sposób.

Bardzo podoba mi się to jak często prezentujesz wszystkie zmiany w kodzie i opisujesz niemal każdą linijkę. Co prawda przez to czasami pomijałem niektóre fragmenty, ale uważam, że to znacznie lepsze podejście niż przemilczanie czegoś, bo to „oczywiste”. Naprawdę miło się czyta a i przykłady są zachęcające. Zastanawiam, się tylko czy nie da się zrobić tak by przy kopiowaniu kodu nie kopiowały się numery linii (przynajmniej w Mozilli), choć notepad++ daje sobie z tym radę.

Nie mniej jednak – świetna robota!

Pozdrawiam,
MK

Maciej
17

Przed rokiem „zrobiłem” kurs stacjonarny z technik programowania. Budując następnie serwis całkowicie pominąłem technikę JS bo wydawała mi się nadawać tylko do „bajerków”. Może i dobrze zrobiłem bo mam fundament a teraz mogę dołożyć funkcje dla tych, którzy używają JS.
Twoje „Praktyczne Wprowadzenie…” przekonało mnie, że warto i pokazało, ze to proste. Dziękuję!

piotr
18

Przerobiłem sobie ten kurs i jestem zawiedziony. Wiele z tych efektów można osiągnąć zwykłymi stylami CSS. Więc po co używać Javy do podmiany obrazków itp?

sceptyk
19

Akurat z Javą ma to niewiele wspólnego, pewnie tak jak Ty. JavaScript to zupełnie inny język kolego.
Ten kurs miał pokazać możliwości, a nie dawać gotowce jak zrobić to czy tamto. Uczył on też programowania ludzi, którzy nie mają o tym pojęcia.
Pokazał specyfikę języka i ich zastosowanie w naprawdę przystępny sposób. Programowanie polega na logicznym myśleniu i korzystaniu z dokumentacji.

robert
20

Szkoda, że nie ma już kolejnych części :-( Dziękuje za trud włożony w przygotowanie odcinków, które pozwoliły mi w przystępny sposób poznać podstawy, jak do tej pory omijanego przeze mnie z daleka, języka JavaScript.

q3d
21

Dotarłem z lekturą od początku do tego momentu i lecę dalej :) Martwię się co będzie jak dojdę do ostatniego odcinka i będę musiał czekać na kolejne :( W każdym bądź razie będę czekał, bo jest na co. Dzięki za poradnik.

dobrypodpis
22

Cześć.

Przeszedłem przez wszystkie 20 odcinków i również chciałem podziękować za trud i wkład włożony w przygotowanie tego materiału. Na prawdę świetnie się czyta i przyswaja :) Biorę się za kolejne wpisy :)

Pozdrawiam
Calfy.

Calfy
23

Witam, właśnie doszedłem do 20 kursu i muszę powiedzieć, że bardzo porządkuje wiedze. Od kilku miesięcy korzystam z JS i JQ, ale w sposób bardzo chaotyczny, po prostu szukałem funkcji, której potrzebuję. Teraz i po przeczytaniu „Javascript. Programowanie obiektowe.” wszystko zaczyna być jasne ;)

Mam jeszcze pytanie. Dużo osób korzysta z NoScript. Czy wtedy dobrą praktyką jest tworzenie strony w taki sposób, żeby bez JSa również wykonywała się poprawnie? Np. chcemy za pomocą JQ zmienić opacity czegoś przy loadzie windowa. Wtedy dałbym w CSS opacity na 0 i w JS bym go zanimował do 1. Ale przy NoScripcie nigdy się ten element nie wyświetli. Czy lepiej wtedy w CSSie nie dawać opacity, natomiast ustawić je w JS na początku na 0? Tak się ostatnio zastanawiałem, bo moja strona po włączeniu NoScripta działała bardzo połowicznie :D

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>