Praktyczne wprowadzenie do JavaScript #8

Za nami siedem odcinków wytężonej pracy nad wykonaniem wyświetlania rozszerzonej treści newsa przy pomocy JavaScript. Zapewne śni Ci się po nocach funkcja PokazAkapit, dlatego zajmijmy się dziś, dla odmiany, obsługą rozwijanego menu.

Mowa o takim menu, jakie możemy na przykład ujrzeć na stronach sportowych gazety.pl. Sprawa obija się właściwie o to, co do tej pory już robiliśmy. Wiedz jednak, że przy pomocy tego przykładu poznamy kolejne, pożyteczne funkcje języka. Zacznijmy więc.

Pierwsze, co zrobimy, to zaprojektowanie struktury 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>Strona z menu</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

</script>

</head>
<body>
	<div style="width: 60px;">
		<ul>
			<li id="main"><a href="#"><strong>Kategorie</strong></a>
				<ul id="menu">
					<li><a href="#">sport</a></li>
					<li><a href="#">zycie</a></li>
					<li><a href="#">gry</a></li>
				</ul>
			</li>
		</ul>
	</div>
</body>
</html>

Jak widać, mamy prostą listę otoczoną divem. Przy okazji nadaliśmy dwa identyfikatory: menu i main. Przyda się to nam, aby nasz skrypt mógł zrobić cokolwiek.

Zapewne domyślacie się już, że w zamierzeniach, po najechaniu na Kategorie, rozwinie się lista. Po zwolnieniu kursora myszy lista powinna się schować. Analogicznie do naszego przykładu z akapitem, schowanie oznaczać będzie ustawienie style.display = „none”;, a pokazanie style.display = „block”;.

Defaultowo musimy więc schować naszą listę z kategoriami, by w ogóle nasze menu miało sens działania. Mamy do wyboru dwie opcje: albo ukryć cały <ul id=”menu”> albo jego poszczególne elementy <li>. Wybierzemy drugi sposób, by przy okazji poznać kolejny element języka JavaScript, o którym przeczytasz trochę niżej. Na razie dodajmy potrzebne style.


<style type="text/css">
ul
{
	margin: 0;
	padding: 0;
}
li
{
	margin: 0;
	padding: 0;
	list-style-type: none;
}
#menu li
{
	display: none;
}
</style>

Tym sposobem nasz dokument przybrał taką postać:

<!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>Strona z menu</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />

<style type="text/css">
ul
{
	margin: 0;
	padding: 0;
}
li
{
	margin: 0;
	padding: 0;
	list-style-type: none;
}
#menu li
{
	display: none;
}
</style>

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

</script>

</head>
<body>
	<div style="width: 60px;">
		<ul>
			<li id="main"><a href="#"><strong>Kategorie</strong></a>
				<ul id="menu">
					<li><a href="#">sport</a></li>
					<li><a href="#">zycie</a></li>
					<li><a href="#">gry</a></li>
				</ul>
			</li>
		</ul>
	</div>
</body>
</html>

Wszystko działa jak należy – kategorie są ukryte.

Pozostaje dać znać <li id=”main”><a href=”#”><strong>Kategorie</strong></a>, że najechanie go myszką spowoduje ustawienie display <li> na block. Zwolnienie kursora ustawiało będzie tą właściwość na none. Praktycznie jesteśmy w domu, bo to samo robiliśmy parę odcinków wstecz z naszym kochanym akapitem.

Jako że nie mamy zamiaru bawić się w onmouseover=”” i onmouseout=”” wewnątrz dokumentu HTML, trzeba te właściwości ustawić tuż po załadowaniu okienka przeglądarki z naszą stroną. Jak wielu z Was pewnie pomyślało, przyda nam się w tym celu funkcja onload. Przyjmijmy też, że pokazywać menu będzie funkcja Pokaz, a ukrywać Ukryj. Wykorzystamy też trzecią funkcję o nazwie Laduj, która da znać dokumentowi, że najechanie na Kategorie spowoduje rozwinięcie menu i na odwrót. Skojarzymy ją z onload tak, jak w poprzednich odcinkach. Genialne w swej prostocie, czyż nie? Dodajmy więc pierwszy kod JS.


<script type="text/javascript">

	window.onload = Laduj;

	function Pokaz()
	{
		
	}

	function Ukryj()
	{
		
	}
	
	
	function Laduj()
	{
		
	}

</script>

Mamy więc ładny szkielet funkcji. Pora je zapełnić. Zacznijmy od Laduj.

Jak już uznaliśmy, funkcja ta sprawi, że po załadowaniu okienka, element<li id=”main”> będzie miał właściwość onmouseover i onmouseout, czyli, używając prostej terminologii, funkcja ta sprawi, że po najechaniu kursorem myszy na Kategorie menu się rozwinie, a po jego usunięciu z napisu, zwinie.


	function Laduj()
	{
		var li = document.getElementById('main');
		li.onmouseover = Pokaz;
		li.onmouseout = Ukryj;
	}

Przy pomocy document.getElementById, jak zwykle, pobraliśmy odnośnik do interesującego nas tagu <li> o id=”main”. Następnie daliśmy mu znać, że po najechaniu kursora nań ma wykonać się funkcja Pokaz, a po jego zwolnieniu funkcja Ukryj. Obie funkcje wywoływane będą bez argumentów, stąd też zapis bez jakichkolwiek nawiasów etc.

Jako że na początku napisaliśmy window.onload = Laduj;, po załadowaniu okienka wykona się od razu powyższa funkcja. Czyli mechanizm mamy już po części zainicjowany.

Nadal jednak nic się nie dzieje, ponieważ główne funkcje są puste. Zanim cokolwiek w nich napiszemy, przyjrzyjmy się bliżej temu, co te funkcje będą robić.

Jak wiadomo, ustawiliśmy za pomocą stylów CSS, aby każdy, pojedynczy element listy (<li>) był ukryty. Z tego więc wynika, że aby pokazać całe menu, musimy nadać każdemu, pojedynczemu <li> display równe block. Jak wiemy, do poszczególnych elementów dokumentu HTML dostawaliśmy się do tej pory przy użyciu document.getElementById. Stratą czasu byłoby jednak przypisywanie każdemu elementowi osobnego id. Tym bardziej, kiedy pozycje w menu mogą się zmieniać. Musimy więc dostać się do poszczególnych elementów dynamicznie, bez względu na identyfikatory.

Pora jednak na nowe elementy języka JavaScript.

Jak zapewne często rozmyślałeś, pewne rzeczy w programowaniu można wykonywać automatycznie parę razy. Na przykład odliczanie do trzech. W sumie można by to zapisać w ten sposób:


alert('1');
alert('2');
alert('3');
for() { }
Konstrukcja for przyjmuje 3 argumenty, które, wyjątkowo tutaj, oddzielamy średnikami. Warto dodać, że fachowo for nazywamy pętlą.

Logika przypomina jednak, że taki zapis odliczania byłby nierozsądny i na pewno istnieją lepsze rozwiązania. Doliczyliśmy co prawda do 3 przy pomocy okienek alert(), ale zapisaliśmy to wszystko sami, ręcznie. Nie ma tu miejsca na działanie komputera, który powinien wykonać te odliczanie sam i podstawiać konkretne liczby do funkcji alert. Pomocna w tym względzie jest konstrukcja for() { }, która dzięki wpisaniu odpowiednich argumentów (oczywiście pomiędzy nawiasami) sprawia, że kod w klamrach wykonuje się dopóki warunki w argumentach będą prawdziwe. Przyjrzyjmy się tej funkcji na konkretnym przykładzie:


	for (var i = 0; i < 3 ; i++)
	{
		alert(i);
	}

Taki oto kod wykonuje odliczanie od zera do 2, by wyświetlić kolejne liczby w okienku, przy pomocy alert(). Przeczytać słownie możemy to w ten sposób:

Poczynając od wartości zmiennej o nazwie i, równej zero, dopóki wartość tej zmiennej jest mniejsza od 3, wykonaj kod w klamrach, a potem powiększ zmienną i o jeden.

Przyjrzyjmy się teraz poszczególnym elementom tej konstrukcji:

Komentarze

1

najs i pozostaje tylko życzyć kolejnych odsłon i ciekawych (użytecznych) przykładów. :)

Lerno
2

Kolejna świetna część. Jako początkujący w JS czekam na kolejne odcinki :-)

btw. myślałeś, aby po skończeniu serii zebrać to wszystko i wydać np. w formie książki? zapotrzebowanie jest na pewno, ale dobrych publikacji książkowych dla początkujących niestety brakuje…

3

Bellois – jesli chodzi o PDF, to jak najbardziej. Postaram sie cos wydac, kiedy kurs dojdzie do tych 10 lub wiecej odcinkow i bedzie przedstawial podstawy.

Co do formy ksiazki jako takiej, coz, nie ma na polskim rynku czegos podobnego, wiec to byloby mile doswiadczenie. Natomiast jedna jedyna kwestia – brak wydawcy i takiego zainteresowania kursem, ktory by potwierdzil jego wartosc. Ergo, czekam na wieksza widownie :-), wiesz jak to jest.

4

window.onload = Laduj;
// (…)
function Laduj()
{ }
Czy przypadkiem, przy takim zapisie konsola nie wyrzuci błędu: „Laduj not defined”?

5

Nie wyrzuci.

6

Na wstępie gratuluję świetnego kursu i jednocześnie bardzo za niego dziękuję :)
Wreszcie każdy początkujący (jak ja) i nie mający zbyt dużo czasu (jak ja) może się pouczyć JavaScriptu.
A teraz mam pytanko do tego odcinka. Jak napisać funkcje, żeby dało się zrobić więcej elementów w menu (tzn takich jak Kategorie), po wskazaniu których pojawiają się pozycje (sport, zycie itp). Czy np Laduj powinna być wywoływana z parametrem, jakąś zmienną? Jeszcze trochę nie do końca wszystko łapię, więc będę wdzięczny za wskazówki. Pozdrawiam

Bartek
7

Bartek, dobrze rozumiem, chcesz miec kilka rozwijanych menu obok siebie tak?

8

Tak, właściwie wygląda to jak kilka rozwijanych menu. Tzn np 3 pozycje obok siebie, każda z rozwijaną listą opcji do wyboru.

Bartek
9

Biorac pod uwage powyzszy sposob, musialbys napisac po dwie funkcje Pokaz i Ukryj do kazdego menu i przyspisac je jako zdarzenie w Laduj. Ale to bardzo nieefektywne, wiec… zajme sie tym problemem w najblizszych odcinkach :-)

10

Niestety – u mnie nie działa :/ Przeleciałem cały kod w poszukiwaniu literówek i nic. Wklejałem też Twój kod częściami (html/css/js), a i tak nie chce działać :/
Co dziwne – przeklejenie CAŁEGO kodu powoduje, iż menu się wyświetla tak jak powinno. Mam w związku z tym taką teorię – czyżby fakt, iż tworzę html, css i js w osobnych plikach (z linkami w headzie do css/js) miał aż takie znaczenie? Wiesz może jak to obejść? Nie lubię wymieszania różnego kodu w jednym pliku dlatego stosuję taką, a nie inną konwencję.

m010ch
11

Dziwne, nawet z plikami w headzie powinno dzialac i dziala.

Może Twój edytor dziwinie formatuje apostrofy i cudzysłowa po wklejeniu? Sprawdź. Podaj również przeglądarkę jakiej używasz, to może miec znaczenie, choc nie sądze.

No i przydałby się kod, mój mail mam[ ]dosc.pl :-)

12

Dzięki za szybką odpowiedź.
Mam Firefoksa 2.0.0.3, a konsola błędów JS nic nie pokazuje :/
Za chwilę poślę Ci kod na maila – może znajdziesz przyczynę.

m010ch
13

Jak się okazało, przyczyną była deklaracja window.onload na samym początku pliku. Niestety nie wspomniałem o pewnym kruczku dotyczącym tej konstrukcji, tak więc Czterysta Czwarty słusznie zauważył, że mógł wystąpić błąd.

W każdym razie – jeśli umieszczamy kod JS w pliku HTML, window.onload może występować gdzie chcemy. Jeśli dołączamy go w postaci plików, musi wystąpić po funkcji, którą przypisaliśmy temu zdarzeniu.

Za problemy przepraszam :-)

14

mam pytanie jak zrobić aby w/w przykład działał w przeglądarkach bez obsługi JS, czy to przy włączonym dodatku ‚no-script`w Fxie, czy na przeglądarkach tekstowych {czasem bardzo przydatne jak Xy padają ;-)}. Teraz przeszkadza fakt że w href=”” jest tylko #

15

Da sie CSSem ;). # w linkach i tak trzeba podmienic na stosowny adres, do ktorego ma prowadzic, wiec nie ma problemu.

16

w linku można dać adres do strony gdzie będą wyszczególnione działy z tego menu.

Dominik Trzaskacz
17

Kolejny raz wchodzę na ten kurs i coraz to znajduje ciekawsze rzeczy! Fantazja, pomyśleć, że zrobienie manu dynamicznego w JS było do niedawna dla mnie udręką. Nigdzie nikt nie poruszał tego tematu, a na pewno w takiej wersji. Dziękuję za super manual. Z uwagą będę czytał kolejne tematy!

Serdecznie pozdrawiam

18

No i ja jestem pod wrażeniem (nie takim sobie..). Co dalej czytam i brnę z nauką tym więcej przypominam sobie tych „suchych” kursów JavaScript, gdzie przede wszystkim rządziły zasady regułek funkcji, wartości itp. Dochodziło do sytuacji pytania -a po co jest właściwie to for? pętla? żeby to chociaż zademonstrował w praktyce!? i na takich frustracjach kończyłem naukę takich teorii JS. Tutaj Ferrante pokazujesz mi jako pierwszy, jak praktycznie używać tych regułek, krok po kroczku. Dla mnie ten kurs JS, baa cała ta strona jest rozwiązaniem Pioniera w nauce i praktyce. Jeżeli kiedykolwiek wydasz swoją książkę np. w Helion to ją chętnie zakupię i wyślę Ci ją z pokorną prośbą o autograf ;)

obelyx
19

A jak zrobić tak, że gdy najadę na powiedzmy link o indexie 1 to pokazuje mi sie div o indexie 1 a nie wszystkie? Bo nie mogę sobie z tym poradzić :/

Qba_23
20

Dobra już wiem jak :D
Dla ciekawych:
function PokazDiv(id)
{
var div = document.getElementById(id);
div.style.display = "block";
}
function UkryjDiv(id)
{
var div = document.getElementById(id);
div.style.display = "none";
}

A potem mam:
while($wiersz2 = $link2 -> fetch())
{
echo ''.$wiersz2['tytul'].'';
echo ''.nl2br(stripslashes(skroc($wiersz2['tresc'], 100))).'';
++$a;
}

no i oczywiście na początku przed while trzeba ustawić $a, troche to kombinowane xD Ale na początek wystarczy, a jak mi coś przyjdzie lepszego do głowy, to wtedy zmienie :P Może ktoś napisze, jak można by to zrobić ładniej? xD Bo ja jakoś nie mogę nic wymyślić :P

Qba_23
21

chciałbym zwrócić uwagę na małe nieścisłości:

Poczynając od wartości zmiennej o nazwie i, równej zero, dopóki wartość tej zmiennej jest mniejsza od 3, powiększ ją o jeden i za każdym jej powiększeniem wykonaj kod w klamrach.

Powinno być: „Wykonaj kod w klamrach a następnie powiększ ją o jeden”. Gdyby pętla for działała w opisany sposób zwracałaby wartości: 1, 2, 3 a zwraca przecież: 0, 1, 2

Następnie uruchamiamy pętlę for, która odlicza do 0 do 2 (bo zmienna i, jak zapisaliśmy, nie może być większa od 3)

Powinno być: „…nie może być większa od 2”. „3” jest już wartością nieakceptowaną aby mógł wykonać sie kod…

Poza tym – wielke dzięki, ja też liczę na to, że poznam wreszcie JS w jakiś łatwo przystępny sposób, bo o posiadanym podręczniku tego nie mogę powiedzieć ;-)

Walking In The Darkness
22

Masz racje. W 1. pkcie mala poprawka, w 2. punkcie, nie wiem, jak to przeoczylem. Pozdrawiam

23

dlaczego podczas gdy wyciagne powtarzajace sie zmienne jak np. var ul = document.getElementById(‚menu’); i umieszcze je w kodzie globalnie to skrypt juz nie dziala?

pytanie
24

Umiesc je we funkcji Laduj(), bo jest ona uruchamiana po zaladowaniu strony – inaczej skrypt nie bedzie mial dostepu do tagów (drzewa DOM).

25

Taka tylko mala uwaga.
Przed przed-ostatnim listingiem napisales:
„Podstawmy więc odpowiednie wartości do ciała funkcji Pokaz, by otrzymać coś takiego:”
A powinno byc:
„Podstawmy więc odpowiednie wartości do ciała funkcji Ukryj, by otrzymać coś takiego:”
Zla nazwe funkcji wpisales po prostu ;)

26

Witam

Mi również twój kurs przypadł do gustu. Prościej się nie da tego wyjaśnić:)

Zbudowałem podobne menu na dl,dd,dt – wszystko działa tak jak opisałeś

Osadziłem to menu

w znacznikach bezpośrednio nad

i jak menu się rozwija to wszystko pod nim obniża się żeby zrobić miejsce zawartości
Jak spowodować aby znaczniki rozwijały się „nad” elementami strony umiieszczonymi pod nim i nie powodowały przesunięcia pozostałych elementów?
Z góry dzięki za pomoc i pozdrawiam

k-mad
27

@k-mad

Teraz, wziąwszy pod uwagę datę Twojego komentarza, to już musztarda po obiedzie, ale dopisz deklarację CSS:


#main {
position: relative;
}

#main ul {
position: absolute;
}

H68nkr
28

No więc znalazłem dwa błędy jednak. Zapomniałem o document.getElementById oraz o zamknięciu pętli for (nieparzysta ilość }) jednak skrypt dalej nie działa… szukam

Glorifind
29

no i znalazłem. Przyzwyczajenie z TurboPascala w forze robiłem for (warunek ,) zamiast ;

Glorifind
30

nie wiem jak u innych ale u mnie nie działa to poprawnie, mianowicie po opuszczeniu „obszaru” kategorie znika rozwijane menu a tym samym nie mozna kliknac w żaden link w menu

rafs
31

Rafs już dawno to pewnie rozwiązał ale miałem ten sam problem bo zamiast:

var ul = document.getElementById(‚menu’)
var elements = ul.getElementsByTagName(‚li’)

dawałem:

var ul = document.getElementById(‚menu’)
var elements = document.getElementsByTagName(‚li’)

czyli zamiast ul. dawałem document. :)

swat
32

Kurs świetny, ale moim zdaniem zły przykład z tym menu ,bo osobiście uważam , że do takich rzeczy lepiej wykorzystać tylko CSS.

Pozdrawiam

Rachel92
33

Hej, mam podobny problem jak m010ch
Jeśli kod js mam w pliku html, to działa, ale jeśli w oddzielnym pliku, to już nie. Przesunięcie window.onload za funkcję Laduj nie pomaga, w innych miejscach też próbowałam ją wstawiać i nic. Jak to można rozwiązać?

Maja
34

ok, literówka, sorry ;)

Dodaj komentarz

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