Praktyczne wprowadzenie do JavaScript #2

W poprzedniej części kursu powstał prosty dokument HTML z minimalną funkcjonalnością JavaScript, jaką jest rozwinięcie rozszerzonej treści newsa. Stopień zaawansowania skryptu, powiedzmy to sobie szczerze, jest dość mizerny: kiedy odkryjemy drugą część wiadomości, nie możemy już jej ukryć. Chciałoby się też zrobić coś z linkiem więcej. Przyznacie zapewne, że zmiana jego wartości na zwiń/schowaj czy cokolwiek innego, co przychodzi Wam do głowy, byłaby całkiem sensowna. Szczytem marzeń byłoby z kolei dodanie jakichś stylów dla naszego akapitu, by wyróżnić go od pierwszego. To wszystko w tym i kolejnych odcinkach. Najpierw zajmiemy się problemem numer jeden.

Przypomnijmy sobie treść dokumentu HTML, jaki powstał ostatecznie w 1. części:

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

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	function PokazAkapit()
	{
		var akapit = document.getElementById('more');
		akapit.style.display = "block";
	}

</script>

</head>
<body>
<div>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque metus eros, rutrum at, hendrerit nec, posuere ac.<a href="#" onclick="PokazAkapit();" >więcej</a></p>

<p id="more" style="display: none;">Vivamus pretium fringilla metus. Praesent a enim eu metus scelerisque tincidunt. In auctor lorem et leo.</p>
</div>
</body>
</html>
document.getElementById(id);
Zapewne zastanawia Was, co oznacza w nazwie powyższej funkcji słowo document oraz kropka. By zrozumieć istotę problemu, przeczytajmy to, jak swoiste drzewo genealogiczne (w następnych częściach dowiesz się, że fachowa nazwa ma wiele wspólnego z drzewem genealogicznym). document jest tutaj, dajmy na to, rodzicem. Kropka oznacza natomiast, że getElementById() jest własnością rodzica. Po kropce może być również jakaś zmienna, dla której document jest rodzicem i ma do niej dostęp.

Zgłębiając się w problem dalej, można wywnioskować z łatwością, że słowo document oznacza zawartość całego dokumentu HTML. document ma więc różne funkcje, takie jak choćby poznana getElementById, pozwalające operować na jego dzieciach. Dziećmi, jak również można dostrzec, są wszystkie tagi HTML w naszym dokumencie. W kolejnych odcinkach spotkamy się więc z różnymi, podobnymi zapisami:

document.body.style.margin
Oznacza to, że odwołaliśmy się do dziecka dokumentu HTML, jakim jest tag <body>, a następnie, obserwując wartości po kropkach, dobraliśmy się do właściwości style tego tagu, jakim jest margines margin.

Wiemy już, na czym stoimy. Dzięki document.getElementById(‚more’) pobraliśmy odnośnik do akapitu o id=”more”. Przechowujemy go w zmiennej o nazwie akapit. Dzięki temu mamy między innymi dostęp do wszystkich właściwości stylów dla <p id=”more”></p>. Pora dodać możliwość zwinięcia akapitu, czyli, na chłopski rozum, należy ustawić z powrotem display: none;, kiedy rozwiniemy paragraf.

Zapewne wielu Was, zastanawiając się, jak działają programy, skrypty i inne, doszło do wniosku, że skrypty reagują na nasze poczynania w zależności, co robimy. Jeśli skorzystamy na przykład z funkcji wykop w znanym serwisie wykop.pl, strona wie, ze chcemy wykopać dany link i robi, co trzeba. Na piśmie można opisać to działanie w następujący sposób: jeśli user kliknie link, policz jego głos. Celowo podkreśliłem słowo „jeśli”, ponieważ na nim, tyle że w języku angielskim, opiera się wiele operacji w JavaScript. Często więc będziemy używać niepozornego słowa if, chcąc dać znak skryptowi, że jeśli coś się stanie, ten ma zareagować. Radzę się z if’em zaprzyjaźnić już na wstępie.

Wróćmy jednak do istoty problemu Naszym celem jest ponowne ukrycie paragrafu, prawda? Paragraf ten, po kliknięciu, ma styl display: block;. Trzeba więc rozpoznać, kiedy display jest równy „block” i wykonać jego zmianę na „none”.


<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	function PokazAkapit()
	{
	       var akapit = document.getElementById('more');
        
                akapit.style.display = "block";

                if (akapit.style.display == "block")
                {
                    akapit.style.display = "none";
                }
         }


</script>

Powyższym sposobem, do naszej funkcji PokazAkapit, znajdującej się w sekcji <script></script>, dodaliśmy następującą instrukcję warunkową:


                if (akapit.style.display == "block")
                {
                    akapit.style.display = "none";
                }

Zauważ, że cały czas opieramy się na zmiennej akapit, która jest naszym odnośnikiem do akapitu o id="more". Kod, jaki dodaliśmy, można przetłumaczyć tak:

Jeśli właściwość stylów display jest równa wartości "block", zmień ją na "none" po kliknięciu więcej.

if (jakiś warunek) { wykonaj jakieś zadanie }
Konstrukcja ta, nazywana instrukcją warunkową, oznacza, że jeśli jakiś warunek będzie prawdziwy, wykona się kod w klamrach.

if (1 == 1) { alert ('Jeden równa się jeden!'); }
Jeśli jeden równa się jeden, wywołaj funkcję alert(); o argumencie Jeden równa się jeden.

1 == 1 to warunek. Jeśli jest on prawdziwy, wykonuje się wszystko to, co jest zawarte w klamrach. Łatwo można wywnioskować, że jeśli chcemy porównać jakieś wartości, wstawiamy między nie == - dwa znaki równa się. Porównywane wartości mogą być zmiennymi, literami, bądź cyframi. Jeśli porównujemy litery, pamiętajmy, aby były one otoczone cudzysłowami lub apostrofami!

Wypróbujmy teraz nasz skrypt, klikając w link więcej. Ups?! Nasz skrypt nie działa!. Bez obaw, tak właśnie powinno być. Przeanalizujmy bowiem działanie funkcji PokazAkapit, której dodaliśmy przed chwilą nowe elementy. Wszystko w JavaScript wykonuje się w kolejności zapisania kodu, więc czytamy go od góry do dołu. I tak, najpierw pobieramy odnośnik do naszego paragrafu z roszerzoną treścią: var akapit = document.getElementById('more');. Następnie zmieniamy sposób wyświetlania paragrafu - akapit.style.display = "block";. Potem, przy pomocy instrukcji warunkowej, sprawdzamy, czy display akapitu ustawiony jest na block. Jest, ponieważ przed chwilą ustawiliśmy tą wartość. W takim razie wykona się kod w klamrach, bo warunek jest prawdziwy. A w klamrach mamy, by display akapitu ustawić znów na none, czyli, co łatwo można stwierdzić, akapit zostanie ponownie schowany! Dostaliśmy więc odpowiedź, dlaczego klikając w więcej, nic się nie działo.

Rozwiązanie tego problemu, jest, po głębszym przemyśleniu, bardzo logiczne. Musimy po kliknięciu w link więcej rozważyć dwie sytuacje:

Kiedy akapit ma display równy block, po kliknięciu w więcej zmienić go trzeba na none. Kiedy natomiast akapit ma display równy none, po kliknięciu zmienić go należy na block.

Inaczej rzecz biorąc, Jeśli akapit jest schowany, pokażmy go. Jeśli akapit jest widoczny, ukryjmy go!. Tłumacząc to na JavaScript, uzyskujemy następujący kod:


         function PokazAkapit()
	{
		var akapit = document.getElementById('more');
		
		var view = akapit.style.display;

		if (view == "block")
		{

			akapit.style.display = "none";
		}
		
		if (view == "none")
		{
			akapit.style.display = "block";
		}
			
	}

W funkcji zaszły istotne zmiany. Pojawiła się nowa zmienna o nazwie view.

Pamiętaj, że nazwy zmiennych są dowolne. Równie dobrze mogliśmy użyć nazwy babcia_jadzia, czy robertmateja0. W tym wypadku jest to view, ponieważ przechowuje ona wartość display akapitu, więc nazwa wydaje się być adekwatna.

Przechowuje ona display akapitu. Jak widać, podstawiamy ją do warunków. Wychodzi na to samo, ponieważ zmienna view ma wartość style.display akapitu, czyli to, o co nam chodziło. Porównujemy stronami interesujące nas wartości, przy użyciu ==. Jeśli któryś z warunków jest prawdziwy, zmieniamy style.display akapitu.

Nasz dokument zyskał kolejną funkcjonalność i wygląda już coraz lepiej:

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

<!-- Nasz kod Javascript: -->

<script type="text/javascript">

	 function PokazAkapit()
	{
		var akapit = document.getElementById('more');
		
		var view = akapit.style.display;

		if (view == "block")
		{

			akapit.style.display = "none";
		}
		
		if (view == "none")
		{
			akapit.style.display = "block";
		}
			
	}

</script>

</head>
<body>
<div>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque metus eros, rutrum at, hendrerit nec, posuere ac.<a href="#" onclick="PokazAkapit();" >więcej</a></p>

<p id="more" style="display: none;">Vivamus pretium fringilla metus. Praesent a enim eu metus scelerisque tincidunt. In auctor lorem et leo.</p>
</div>
</body>
</html>

Pozostaje zatroszczyć się o zmianę wartości <a>więcej</a> na coś w ten deseń: <a>schowaj/zwiń</a> i na odwrót. O tym i o wielu innych funkcjach, już w następnych odcinkach.

Jeśli masz pytania, sugestie - wyraź je w komentarzach, a na pewno otrzymasz odpowiedź!

Komentarze

1

juz widzę, że jest sexy :) na razie tylko przeczytałem, działać będe jutro, ale i tak już czekam na kolejną część :)

2

[…] jeśli na none, “schowaj”. Tą teoretyczną sytuację mamy już w kodzie z poprzedniego odcinka, […]

3

hmm… zauważyłem coś dziwnego… mamy sobie kod:
<p id="more" style="display: none;">Vivamus pretium</p>
jeśli display:none; dałbym w zewnętrznym arkuszu stylów jako
#more {
display: none;
}
to nie zadziała… się własnie 10 minut nad tym głowiem, dlaczego akurat mi jak zawsze skrypt opisany przez Ciebie nie działa…

4

Wybacz, zapomnialem tam dodać dwóch zdań. Bez nich rzeczywiście mogłem Cię wprowadzić w błąd, zatem proszę o rozgrzeszenie :>.

5

[…] tag HTML udostępnia swoje wszelkie właściwości. Szerzej omawialiśmy to, w żółtej ramce z prawej strony, w drugiej części kursu. Przypominając sobie te wiadomości, wiemy, że z […]

6

[…] Zresztą, to już wiemy z drugiego odcinka. […]

7

Mam pytanie, dlaczego kod nie zadziała:
if (view == „block”) { view = „none”; }
tylko musi być :
if (view == „block”) { akapit.style.display = „none”; }
Pytam się tak z ciekawości
POZDRAWIAM
bardzo przyjemny kurs ;)

slawcio
8

W artykule jest napisane, ze view przechowuje wartość display, a nie jest bezposrednim odnosnikiem do tej wartosci.

Pozdrawiam

ferrante
9

Witam,

A można jakoś przechwycić błąd jest dany kontener nie został jeszcze załadowany? a ktoś kliknie? Nie chodzi mi o cos stylu

if (document.getElementById('more')) {...

Tylko raczej coś globalnego, że gdziekolwiek ktoś kliknie zawsze będzie wywoływana jakaś funkcja która powiedzmy zwróci alerta jeśli jakiś div/span etc o podanym id nie istnieje?

Pozdrawiam i czekam na jakąś odpowiedz na maila/albo tutaj w komentarzach

mmmmK
10

Pytanie (zapewne) z gatunku banalnych, ale jestem nowy w temacie. Dlaczego skrypt nie działa po zamienieniu wszystkich ‚view’ na ‚akapit.style.display’ i wywaleniu linijki ‚var view’?

Mat
11

Bo do zmiennej view zapamietujesz wartosc style.display w danym momencie i ona caly czas tam bedzie. style.display natomiast odnosi „na zywo” do wartosci display i jesli przypiszemy jej jakas wartosc, to nastepne uzycie style.display bedzie odnosilo do przypisanej ostatnio wartosci. Zmienna view potrzebna jest Ci po to, aby warunki if zadzialaly.

12

Dzięki za szybką odpowiedź. Wykonujesz tu fanatastyczną pracę. Zdecydowanie najbardziej przystepny kurs JavaScript, jaki znalazłem w sieci. Wiem, że Cię tu bardzo wychwalaja, ale pochwał nigdy za wiele. :) Pozdrawiena i powodzenia w dalszym rozwijaniu bloga.

Mat
13

jeśli display:none; dałbym w zewnętrznym arkuszu stylów jako
#more {
display: none;
}
to nie zadziała… się własnie 10 minut nad tym głowiem, dlaczego akurat mi jak zawsze skrypt opisany przez Ciebie nie działa…

Pewnie autor już opisał dalej jak to zrobić przez arkusz CSS, ale napiszę – mianowicie należy skorzystać z własności visibility czyli w CSS (arkuszu) piszemy sobie :

#nazwa_diva {
visibility:hidden;
}

a w kodzie jeśli chcemy go pokazać :

document.getElementById(„nazwa_diva”).style.visibility = „visible”;

Ale jak wspominałem na pewno dalej autor zajął się tym zagadnieniem, pozdrawiam

14

A ja mam pytanie, jeżeli chcemy na stronie mieć kilka obszarów „zwijanych/rozwijanych” to dla każdego trzeba pisać osobna funkcje???

Bri
15

Można napisać to krócej:

if (view == ‚none’) {
akapit.style.display = ‚block’;
} else {
akapit.style.display = ‚none’;
}

Poju
16

jeszcze latwiej, bo bez zmiennej ‚view’
if(akapit.style.display == ‚block’)
{
akapit.style.display = ‚none’;
}
else
{
akapit.style.display = ‚block’;
}

zbycho
17

Mam pytanie do tej części kodu:
if (view == „block”) {
akapit.style.display = „none”;
}
if (view == „none”) {
akapit.style.display = „block”;
}

Czy jeżeli po wykryciu że display akapitu jest block i ustawieniu go na none w pierwszym warunku od razu w drugim warunku nie powinien sie ustawić znów na block(wykrył none i ustawił block)? Czy działa tu inna metoda, której może nie zrozumiałem?

avatar
18

najkrócej:
akapit.style.display == ‘block’ ? akapit.style.display = ‘none’ : akapit.style.display = ‘block’;

matey
19

do avatara:
zmienna „view” nie jest równoważna z „akapit.style.display”, przechowuje jedynie wartość „akapit.style.display” czyli „block” lub „none” (właściwość js). Dopiero po ponownym wywołaniu funkcji wartość „view” się zmieni, więc ta część kodu jest OK.

matey
20

@matey:
a nie czasem tak:
akapit.style.display = (akapit.style.display==’block’) ? ‚none’ : ‚block’;
??

otacon
21

Chyba powinno być if () {instrukcja} else if () {instrukcja}. Obecny układ z 2 if’ami sie neguje … pierszy if zamienia display na none, a kolejny nona na blocka.

Lukasz
22

Mnie się udało za pomocą:
function Pokaz(id_paragrafu)
{
var akapit = document.getElementById(id_paragrafu);
if(akapit.style.display!= „none”) akapit.style.display=”none”;
else{
if(akapit.style.display!=”block”) akapit.style.display=”block”;
}

}

Dodaj komentarz

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