Praktyczne wprowadzenie do JavaScript #13

Poprzednie odcinki Praktycznego wprowadzenia naświetliły sprawę tworzenia i operowania na elementach formularzy w JavaScript. Dzisiaj kontynuacja tego ciekawego tematu – zajmiemy się bowiem elementami <select>, z którymi nie mieliśmy jeszcze do czynienia, a których działanie jest bardzo ciekawe.

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

Tym razem spróbujemy wyświetlić dany element blokowy w zależności od tego, co użytkownik wybrał w polu <select>. Załóżmy, że mamy rozwijaną listę z kilkoma opcjami do wyboru:

Jeśli wybierzemy którąś z nich, naszym oczom ukaże się, co łatwe do stwierdzenia, pierwszy, drugi bądź trzeci <div>. Stwórzmy więc na początek przykładowy dokument HTML, któremu będziemy dodawać stopniowo nowe funkcjonalnoś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 dynamicznym formularzem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">
	
</script>
</head>
<body>


	<form name="wybor" method="post">
		
		<select name="akapit">
			<option value="pierwszy">Pokaż pierwszy akapit</option>
			<option value="drugi">Pokaż drugi akapit</option>
			<option value="trzeci">Pokaż trzeci akapit</option>
		</select>
	</form>

	<div id="pierwszy" style="display: none;">Oto jest pierwszy akapit!</div>
	<div id="drugi" style="display: none;">A to drugi akapit!</div>
	<div id="trzeci" style="display: none;">To już trzeci akapit.</div>


</body>
</html>

Składa się on z dwóch istotnych sekcji:

Aby uzyskać, co planowaliśmy, należy przewidzieć sytuację, kiedy wybierzemy którąś z opcji <selecta>. Kiedy to nastąpi, pobierzemy wartość value wskazanej opcji, po czym wykorzystamy ją jako identyfikator <diva>, który chcemy odsłonić. Wspomniane wartości value będą miały tylko i wyłącznie następujące postaci:

Jak doskonale widać, takie same id mają divy, które chcemy pokazać. Jeśli w tym momencie przyszła Ci na myśl funkcja document.getElementById(), to nie jest to przypadek. Popatrzmy.

Użytkownik wybiera jakąś opcję. Następnie pobieramy jej wartość, którą przekazujemy funkcji document.getElementById(), jako argument. Wynik tej funkcji (czyli odnośnik do jednego z trzech elementów div) przekazujemy do jakieś zmiennej, jak już to robiliśmy wielokrotnie, po czym zmieniamy właściwości stylów display dla pobranego elementu. Oczywiście, aby pokazać go, display musi przyjąć wartość block. Postępując według tego planu, uzyskamy to, co nas interesuje.

Pierwsze, co musimy zrobić, to, jak już się rzekło, obdarzenie elementu <select> właściwością, która da znać o tym, że użytkownik wybrał jakąś opcję, co jest równoważne zmianie wartości pola <select>. Z naszej wiedzy wynika, że trzeba będzie wykorzystać tutaj jakieś zdarzenie. Tym razem jest to onchange, które uruchamia się wtedy, kiedy wartość danego elementu się zmienia. Jak można wywnioskować, onchange pomocny jest przede wszystkim w formularzach. Nadajmy więc tę właściwość elementowi <select> po załadowaniu całego dokumentu HTML. Użyjemy w tym celu starej, dobrej właściwości okienka przeglądarki, jaką jest window.onload oraz funkcji Laduj, która da znać <select>, że zmiana jego wartości ma zainicjować funkcję, która pokaże dany akapit/element blokowy.


<script type="text/javascript">
	window.onload = Laduj;
	
	function Laduj()
	{
		document.forms['wybor'].akapit.onchange = Zmien;
	}

	function Zmien()
	{
	}
</script>

Jak widać powyżej, kiedy wybierzemy którąś z opcji, uruchomi się funkcja Zmien. Wypróbujmy, czy to zadziała, uzupełniająć ją o:

alert('Wybrałeś pewną opcję!');

Zapiszmy nasz dokument i przejdźmy do testów. Rzeczywiście, po wybraniu jakiejkolwiek opcji, pojawi się okienko o treści Wybrałeś pewną opcję!. Wynika na to, że poprawnie podpięliśmy zdarzenie onchange do elementu <select>.

By zdobyć id akapitu, który powinien zostać odsłonięty, musimy najpierw pobrać wartość <option>, który został wybrany. Zastosujemy tutaj prostą sztuczkę: spróbujcie zapisać funkcję Zmien w poniższy sposób:

	function Zmien()
	{
		alert(this.value);
	}
*zmiennej – na razie nazwijmy podany zapis zmienną. Wkrótce, kiedy podsumujemy naszą wiedzę, dowiesz się, że poprawna jego nazwa jest nieco inna.

Wystarczy wybrać cokolwiek, by przekonać się, że funkcja po modyfikacjach pokazuje w okienku alert() wartość atrybutu value z opcji, którą wybraliśmy. Jak już wiemy, mieści się ona w tym przypadku w zmiennej* this.value. Rozbierzmy ów zapis na części pierwsze:

Mamy zatem do dyspozycji wartość value wybranej przez nas opcji, zatem pora przejść do działania, które pozwoli nam odkryć interesujący nas akapit.

<script type="text/javascript">
	window.onload = Laduj;

	function Laduj()
	{
		document.forms['wybor'].akapit.onchange = Zmien;
	}

	function Zmien()
	{
		var blok = document.getElementById(this.value);
		blok.style.display = "block";
	}
</script>

Zmieniła się funkcja Zmien. Jak zapewne zauważasz, nie ma tutaj żadnych nowych elementów – wykorzystaliśmy pełnie swojej wiedzy z poprzednich odcinków. Pobraliśmy odnośnik do akapitu i zmieniliśmy mu właściwość stylów display na block.

Wypróbujmy nasz przykład. Co się okazuję? Skrypt co prawda działa, ale kiedy wybierzemy drugi raz dowolną opcję, na ekranie ujrzymy wcześniej wybrany akapit oraz aktualny. Bezsensem byłoby zostawienie tego w takiej postaci, dlatego postarajmy się coś z tym zrobić.

Logika nakazuje aby – kiedy wybraliśmy już wcześniej jakiś paragraf – schować go i pokazać ten, na który wskazaliśmy. Musimy więc zapisać w skrypcie, który akapit jest aktualnie pokazywany, by ukryć go przy kolejnej zmianie na inny. Wszystko po to, by uniknąć sytuacji, kiedy odkryte będą jednocześnie dwa akapity.

Zapiszmy więc identyfikator wybranego <diva> do zmiennej o nazwie active_id. Zdeklarujmy ją jako zmienną, do której dostęp będą miały wszystkie funkcje. W ten sposób, po wywołaniu po raz kolejny funkcji Zmien, jej wartość nie skasuje się.

<script type="text/javascript">
	window.onload = Laduj;
	var active_id = "";

Pora teraz zająć się funkcją Zmien. Musi ona wykryć, czy zmienna active_id przechowuje jakąś wartość. Jeśli to będzie prawda, oznaczać to będzie, że użytkownik wybrał już przedtem którąś z opcji, przez co należy ukryć wskazany div. W przeciwnym razie skrypt po prostu pokaże wybrany akapit i przypisze do zmiennej active_id, niezależnie od tego, czy będzie ona pusta, nową wartość.

function Zmien()
	{
		if (active_id != "")
		{
			var blok2 = document.getElementById(active_id);
			blok2.style.display = "none";
		}
		var blok = document.getElementById(this.value);
		blok.style.display = "block";
		active_id = this.value;
	}

Przeanalizujmy to, co się zmieniło:


if (active_id != "")
		{
			var blok2 = document.getElementById(active_id);
			blok2.style.display = "none";
		}

Jeśli zmienna active_id będzie niepusta (czyli użytkownik wybrał wcześniej jakąś opcję, przez co ustawił wartość zmiennej na id wyświetlanego bloku), schowaj akapit o id, jakim jest wartość tej zmiennej.

active_id = this.value;

Zaktualizuj wartość zmiennej active_id, czyli ustaw aktualnie pokazywany div.

Okazuje się, że wszystko gra. Ostateczny dokument, jaki powstał, wygląda następująco:

<!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 dynamicznym formularzem</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<!-- Nasz kod Javascript: -->

<script type="text/javascript">
	window.onload = Laduj;
	var active_id = "";

	function Laduj()
	{
		document.forms['wybor'].akapit.onchange = Zmien;
	}

	function Zmien()
	{
		if (active_id != "")
		{
			var blok2 = document.getElementById(active_id);
			blok2.style.display = "none";
		}
		var blok = document.getElementById(this.value);
		blok.style.display = "block";
		active_id = this.value;
	}
</script>
</head>
<body>

	<form name="wybor" method="post">

		<select name="akapit">
			<option value="pierwszy">Pokaż pierwszy akapit</option>
			<option value="drugi">Pokaż drugi akapit</option>
			<option value="trzeci">Pokaż trzeci akapit</option>
		</select>
	</form>

	<div id="pierwszy" style="display: none;">Oto jest pierwszy akapit!</div>
	<div id="drugi" style="display: none;">A to drugi akapit!</div>
	<div id="trzeci" style="display: none;">To już trzeci akapit.</div>

</body>
</html>

Komentarze

1

ciarna magija dla mnie, ale przydatne te Twoje teksty, Fet… Ferr ;)

Fett
2

Dzięki, jak zwykle świetny tekst :) Nie wiem nawet, co powinienem tu napisać. Traktujesz temat tak fajnie, że nie ma w sumie czego komentować :D

3

Bellois: e tam, na wykopie jeszcze nie bylem ;-)

4

Bo trudno byłoby wrzucać na Wykop każdy kolejny odcinek. Bloga jako całości też nie było na Wykopie? Hmmm :))

5

Wpadlem tu z forum.php.pl i jak narazie fajnie. ide pobiegać po reszcie stronki :P

qwaq
6

Swietny skrypt i dziala super. Problem pojawia sie jedynie gdy w gre wchodza wiecej niz jeden select box!

aneta
7

Nikt nie powiedzial przeciez, ze powinien dzialac dla wielu selectow… Aczkolwiek na tym etapie Czytelnicy kursu powinni juz wiedziec, dlaczego tak sie dzieje…

Pomysle nad tym, by w przyszlych odcinkach zrobic dla odmiany cos uniwersalnego.

Pozdrawiam

8

Genialne! Coraz lepiej to rozumiem :PP

9

Ok… od razu mam pewne pytanko, wybacz jak popełnię babole w teorii to mnie popraw.
1. Pamiętam, że style CSS nie czyta JS (w osobnym pliku?). Robie tak: style block:none; wrzucam do nagłówka a w div zostawiam tylko id="pierwszy" etc.., to kod już nie działa
function Zmien() {alert('tekst');}
Dla czego tak się dzieje?
2. pytanie: czy CSS „nie zagada” prawidłowo w z JS (pomijając że w jednym pliku html jest cały kod) nawet jak w CSS nadaje właściwości tagom div style: display:none; ?
Chciałbym oczyścić kod HTML od stylów CSS tak jak Ty to pięknie robisz i separujesz JavaScript od HTML. ;-)
3. Czy w JS mogę zarządzać stylami CSS i ustawić style na none i display? pomijając właściwości CSS wpisywane w tagi HTML lub w nagłówku dokumentu?
4. Jak wyjazd nad morze i ambitny projekt 2w1 ? :) hej.
ps. kursik jest no nawet fajny!, bo żuje tak sobie, tak materiał po trochu i żre mi.. dydaktyka ciekawa ;) a zastanawiające jest to, że dopiero po solidnym przestudiowaniu „Ciebie” zaglądam powtórnie do książki (Po prostu JavaScript i Ajax) i dopiero jarzę ;).
Będzie jeszcze kontynuacja kursu JavaScript np. po wstępie to: dla średnio zaawansowanych lub jakiś Ajax czy cuś..? Zachłanny jestem.. ;) no wiem choć nie skończyłem jeszcze tego kursu, no ale masz dar to zagaduje.

obelyx
10

Wydaje mi się, że wskaźnik this.value nie może wskazywać na żadną wartość, moim zdaniem kod powinien wyglądać tak:

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, „Courier New”, Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}

.csharpcode .lnum { color: #606060; }

<script type=”text/javascript” language=”javascript”>
window.onload = function() {
Laduj();
}
var active_id = „”;

function Laduj() {
document.forms[‚wybor’].akapit.onchange = function() {
Zmien(this.value);
}
}
function Zmien(value) {
if (active_id != „”) {
var blok2 = document.getElementById(active_id);
blok2.style[‚display’] = „none”;
}

var blok = document.getElementById(value);
blok.style[‚display’] = „block”;
active_id = value;
}
</script>

11

Witam, gratuluje pomysłu i wykonania całego kursu.

Mam następujący problem dotyczący powyższego skryptu. Otóż, gdy wybiorę jako pierwszą opcje pierwszy akapit to nic sie nie pokazuje, dopiero gdy kliknę na drugą opcję to pojawia się druga opcja i potem już pierwsza działa. Co robić?

Pozdrawiam

12

@Pilaas – dodaj do puste pole w taki sposób:

domysle pole

parametr selected oznacza to pole jako domyslnie zaznaczone.

Co do kursu – fajne tylko nie rozumiem po co zabawa z funkcją Laduj i window.onload, moze i jestem poczatkujacy w js ale bez tego tez dziala :)

Pozdrawiam

Morthigan
13

ups nie wyswietlilo sie…
element ktory trzeba dodac to:
option z parametrem selected=”selected”

Morthigan
14

dokladnie cos takiego:

<option selected="selected"&gt dowolny tekst </option&gt

Morthigan
15

kolejna poprawka -.- :

<option selected="selected"> dowolny tekst </option>

Morthigan
16

‚; /*

"; /*
17

Czy ktoś próbował wyżej SQL Injection? XD

Dodaj komentarz

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