Wyświetlanie i ukrywanie zawartości.


1. Wstęp

Podczas tworzenia stron www często zachodzi potrzeba dynamicznego wyświetlania lub ukrywania jej elementów. Operację tą wykonuje się za pomocą właściwości CSS o nazwie diplay, ustawiając jej wartość na block lub none (wartość block jest wartością domyślną). Przykładowo, warstwy <div>jakiś tekst</div> oraz <div style="display:block">jakiś tekst</div> posiadają wartość display ustawioną na block i obie zostaną wyświetlone na ekranie, natomiast warstwa <div style="display:none">jakiś tekst</div> pozostanie ukryta. Sterowanie wyświetlaniem elementów odbywa się przy użyciu JavaScript, poprzez obsługę rejestrowanych dla nich zdarzeń. Zasada jest bardzo prosta, np. w przypadku onclick - po kliknięciu na określony element, wywoływana jest funkcja, która odwołując się do tegoż elementu lub grupy elementów zmienia ich właściwości CSS z display:none, na display:block lub odwrotnie. Przyjrzyjmy się Listingowi 1 i Listingowi 2.

Listing 1. Kod HTML wyświetlający i ukrywający elementy kontenera (tu: warstwy div).

 <!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<!-- pierwszy kontener -->
<div id="TrescSkrocona_1"><div><b>Tytul 1 wyswietlany, gdy tekst jest zwiniety</b></div>Tresc 1 wyswietlana, gdy tekst jest zwiniety</div>
<div id="TrescPelna_1" style="display:none;"><div><b>Tytul 1 wyswietlany, gdy tekst jest rozwiniety</b></div>Tresc 1 wyswietlana, gdy tekst jest rozwiniety</div>
<div id="PrzyciskPokaz_1" onclick="PokazUkryjTekst('Pokaz',1);" style="cursor:pointer;">Pokaż</div>
<div id="PrzyciskUkryj_1" onclick="PokazUkryjTekst('Ukryj',1);" style="display:none; cursor:pointer;">Ukryj</div>
<!-- drugi kontener -->
<div id="TrescSkrocona_2"><div><b>Tytul 2 wyswietlany, gdy tekst jest zwiniety</b></div>Tresc 2 wyswietlana, gdy tekst jest zwiniety</div>
<div id="TrescPelna_2" style="display:none;"><div><b>Tytul 2 wyswietlany, gdy tekst jest rozwiniety</b></div>Tresc 2 wyswietlana, gdy tekst jest rozwiniety</div>
<div id="PrzyciskPokaz_2" onclick="PokazUkryjTekst('Pokaz',2);" style="cursor:pointer;">Pokaż</div>
<div id="PrzyciskUkryj_2" onclick="PokazUkryjTekst('Ukryj',2);" style="display:none; cursor:pointer;">Ukryj</div>
<script src="pokaz_ukryj_tekst.js" type="text/javascript"></script>
</body>
</html>

Listing 2. Kod JavaScript wyświetlający i ukrywający elementy kontenera. Plik: pokaz_ukryj_tekst.js.

function PokazUkryjTekst(polecenie,id) {
    var PrzyciskPokaz = document.getElementById('PrzyciskPokaz_' + id);
    var PrzyciskUkryj = document.getElementById('PrzyciskUkryj_' + id);
    var TrescSkrocona = document.getElementById('TrescSkrocona_' + id);
    var TrescPelna = document.getElementById('TrescPelna_' + id);
	if (polecenie == 'Pokaz') {
		PrzyciskPokaz.style.display = 'none';
		PrzyciskUkryj.style.display = 'block';
		TrescSkrocona.style.display = 'none';
		TrescPelna.style.display = 'block';
	} 
	else if (polecenie == 'Ukryj') {
		PrzyciskPokaz.style.display = 'block';
		PrzyciskUkryj.style.display = 'none';
		TrescSkrocona.style.display = 'block';
		TrescPelna.style.display = 'none';
	}
}

Po kliknięciu 'Pokaż' lub 'Ukryj', rejestrowane jest zdarzenie onlick, które wywołuje funkcję PokazUkryjTekst() z dwoma argumentami: nazwą polecenia oraz postfiksem identyfikującym elementy w obrębie kontenera. Po połączeniu postfixu z pozostałą częścią identyfikatorów, funkcja pobiera odwołania do wskazywanych przez nie elementów i na podstawie nazwy polecenia wykonuje operację wyświetlania lub ukrywania tych elementów.

Przedstawiony kod ma kilka wad - wymaga, bezwzględnego przestrzegania numeracji postfiksów, każdorazowej obsługi zdarzenia onlick i przekazywania funkcji prawidłowych argumentów. W sytuacji tej, pomyłka w nazwie identyfikatora lub błędne wywoływanie funkcji spowoduje albo wyświetlenie/ukrycie innego elementu albo brak jakiejkolwiek reakcji ze strony skryptu.

Przykład. Wyświetlanie i ukrywanie elementów kontenera na podstawie Listingów 1, 2.

Tytul 1 wyswietlany, gdy tekst jest zwiniety
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur rhoncus urna semper elit condimentum tempus. Morbi magna dui, cursus eu sagittis molestie,
Pokaż
Tytul 2 wyswietlany, gdy tekst jest zwiniety
Quisque sed libero risus, et tristique velit. In quis turpis quis mauris ultrices fermentum. Praesent semper interdum risus, a semper tortor fringilla euismod.
Pokaż

2. Rozwiązanie alternatywne

Chcąc nieco udoskonalić kod, musimy zmienić podejście do samego wyświetlania i ukrywania elementów. Po pierwsze, zamiast grupować elementy posługując się postfiksem, można skorzystać z klasy opakowującej, tzw. wrappera. Odpada wtedy konieczność nazywania i numerowania identyfikatorów. Po drugie, należy pominąć rejestrowanie zdarzenia onclick na każdym elemencie i włączyć jego nasłuchiwanie tylko dla wybranych elementów wrappera. Po, trzecie należy przyjąć, że po kliknięciu wszystkie elementy potomne wrappera posiadające wartość display:block zmieniamy na display:none i odwrotnie.

Sprawę obsługi onlick załatwia za nas jQuery, oferując gotowe rozwiązanie w postaci funkcji nasłuchującej, której argumentem może być nazwa klasy, identyfikator bądź nazwa znacznika. Biblioteka umożliwia również pobranie do tablicy właściwości i wartości stylów CSS danego elementu HTML. Pozostaje nam obsługa wrappera (rodzica) i jego elementów potomnych. Efekty te przedstawia Listing 4.

Listing 3. Kod HTML wyświetlający i ukrywający elementy wrappera (tu: warstwy div).

 <!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<!-- pierwszy kontener -->
<div class="PU_R">
    <div><p><b>Tytul 1 wyswietlany, gdy tekst jest zwiniety</b></p>Tresc 1 wyswietlana, gdy tekst jest zwiniety</div>
    <div style="display:none;"><p><b>Tytul 1 wyswietlany, gdy tekst jest rozwiniety</b></p>Tresc 1 wyswietlana, gdy tekst jest rozwiniety</div>
    <div class="PU_P">Pokaz</div>
    <div class="PU_P" style="display:none;">Ukryj</div>
</div>
<!-- drugi kontener -->
<div class="PU_R">
    <div><p><b>Tytul 2 wyswietlany, gdy tekst jest zwiniety</b></p>Tresc 2 wyswietlana, gdy tekst jest zwiniety</div>
    <div style="display:none;"><p><b>Tytul 2 wyswietlany, gdy tekst jest rozwiniety</b></p>Tresc 2 wyswietlana, gdy tekst jest zwiniety</div>
    <div class="PU_P">Pokaz</div>
    <div class="PU_P" style="display:none;">Ukryj</div>
</div>
<script src="pokaz_ukryj_tekst.js" type="text/javascript"></script>
</body>
</html>

Listing 4. Kod JavaScript wyświetlający i ukrywający elementy wrappera z wykorzystaniem jQuery. Plik: pokaz_ukryj_tekst.js.

01.  var PUJQ = $(".PU_P").click(function () {
02.      var Elem = $(this).parent().children();
03.      if($(this).parent().hasClass('PU_R')) {
04.          for (i=0; i<Elem.length; i++) {
05.              if (Elem[i].tagName) {
06.                  var wart = $(Elem[i]).css('display');
07.                  if (wart == 'block') { Elem[i].style.display = 'none'; }
08.                  if (wart == 'none')  { Elem[i].style.display = 'block';  }
09.              }
10.          }
11.      }
12.  });

Omówmy nasz kod. Do zmiennej PUJQ (Listing 4. 01) - zostaje przypisana metoda .click() - a dokładnie wszystkie zarejestrowane kliknięcia elementów o nazwie klasy PU_P, po czym do zmiennej Elem za pomocą .parent().children() zostają przypisane dzieci rodzica aktualnie klikniętego elementu (Listing 4. 02). Jeżeli rodzic ten posiada nazwę klasy PU_R (Listing 4. 03), pętla for rozpoczyna iterację po jego elementach potomnych (Listing 4. 04-12), począwszy od pierwszego do ostatniego (Elem.length - liczba wszystkich elementów potomnych). Wewnątrz pętli for - instrukcja if sprawdza, czy dany element jest znacznikiem (this.Elem[i].tagName zwraca wtedy true), a nie węzłem tekstowym (this.Elem[i].tagName zwraca undefined, false) (Listing 4. 05), i jeżeli tak - do zmiennej wart przypisywana jest wartość jego właściwości display (Listing 4. 06). Jeżeli wynosi ona block zostaje zmieniona na none (Listing 4. 08) i odwrotnie (Listing 4. 09). Działanie kodu ilustruje poniższy przykład.

Przykład. Wyświetlanie i ukrywanie elementów wrappera na podstawie Listingów 3, 4.

Tytul 1 wyswietlany, gdy tekst jest zwiniety
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur rhoncus urna semper elit condimentum tempus. Morbi magna dui, cursus eu sagittis molestie,
Tytul 1 wyswietlany, gdy tekst jest rozwiniety
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur rhoncus urna semper elit condimentum tempus. Morbi magna dui, cursus eu sagittis molestie, commodo eu felis. Proin ac justo libero, in auctor sapien. In fermentum ante eu urna molestie a euismod lorem dictum. Quisque hendrerit pulvinar nisi, a feugiat nunc ultrices sed. Suspendisse in enim ligula, quis tempor felis. Mauris quis purus lobortis est aliquam ullamcorper. Duis lacinia aliquet est. Duis felis dui, dictum non interdum vitae, faucibus eget nunc. In commodo luctus nisi, et pulvinar neque aliquet nec. Aliquam consectetur dictum tristique.
Pokaż
Tytul 2 wyswietlany, gdy tekst jest zwiniety
Quisque sed libero risus, et tristique velit. In quis turpis quis mauris ultrices fermentum. Praesent semper interdum risus, a semper tortor fringilla euismod.
Tytul 2 wyswietlany, gdy tekst jest rozwiniety
Quisque sed libero risus, et tristique velit. In quis turpis quis mauris ultrices fermentum. Praesent semper interdum risus, a semper tortor fringilla euismod. Sed vehicula, lectus nec convallis laoreet, tellus libero ultricies diam, quis commodo nunc mi vitae ipsum. Aliquam dui elit, sollicitudin non congue at, cursus mattis mi. Cras tempor, turpis eget hendrerit sagittis, augue arcu scelerisque magna, eget iaculis massa sapien ut mauris. Sed dapibus elementum lorem nec convallis. Fusce sit amet velit urna. Aenean molestie tincidunt leo, iaculis laoreet tellus pulvinar in. Cras nibh tellus, ultricies in volutpat non, ullamcorper a dolor. Cras et est feugiat risus elementum blandit ac sed tellus. Phasellus vulputate magna sit amet turpis porttitor porta. Sed eget augue sed lectus iaculis condimentum nec eu nulla.
Pokaż

Oczywiście warstwy PU_P (z tekstem Pokaż, Ukryj) stylujemy wedle potrzeb.

Zobacz demo: Pokaż/Ukryj Tekst

2. Alternatywa dla alternatywy

Przedstawiony skrypt możemy modernizować dalej, np. zamiast konstrukcji .parent().children() użyć metody .siblings(), dzięki czemu jeszcze bardziej zredukujemy kod HTML. Analizę róznic pozostawiamy czytelnikowi.

Listing 5. Kod HTML wyświetlający i ukrywający elementy wrappera (tu: warstwy div).

 <!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<!-- pierwszy kontener -->
<div class="PU_R">
    <div><p><b>Tytul 1 wyswietlany, gdy tekst jest zwiniety</b></p>Tresc 1 wyswietlana, gdy tekst jest zwiniety</div>
    <div style="display:none;"><p><b>Tytul 1 wyswietlany, gdy tekst jest rozwiniety</b></p>Tresc 1 wyswietlana, gdy tekst jest rozwiniety</div>
    <div class="PU_P">Pokaz</div>
</div>
<!-- drugi kontener -->
<div class="PU_R">
    <div><p><b>Tytul 2 wyswietlany, gdy tekst jest zwiniety</b></p>Tresc 2 wyswietlana, gdy tekst jest zwiniety</div>
    <div style="display:none;"><p><b>Tytul 2 wyswietlany, gdy tekst jest rozwiniety</b></p>Tresc 2 wyswietlana, gdy tekst jest zwiniety</div>
    <div class="PU_P">Pokaz</div>
</div>
<script src="pokaz_ukryj_tekst2.js" type="text/javascript"></script>
</body>
</html>

Listing 6. Kod JavaScript wyświetlający i ukrywający elementy wrappera z wykorzystaniem jQuery. Plik: pokaz_ukryj_tekst2.js.

01.  var PUS = $(".PU_P").click(function () {
02.      var Elem = $(this).siblings();
03.      if($(this).parent().hasClass('PU_R')) {
04.          for (i=0; i<Elem.length; i++) {
05.              if (Elem[i].tagName) {
06.                  var wart = $(Elem[i]).css('display');
07.                  if (wart == 'block') { Elem[i].style.display = 'none'; }
08.                  if (wart == 'none')  { Elem[i].style.display = 'block';  }
09.              }
10.          }
11.      }
12.  });

Zobacz demo: Pokaż/Ukryj Tekst 2

Ireneusz Sekuła, JavaScript dla zielonych