Prosty slider do przeglądania obrazków.


1. Wstęp

jQuery oprócz tego, że dynamicznie operuje na właściwościach elementów HTML, oferuje szereg ciekawych metod ich animacji, które z powodzeniem można wykorzystać do stworzenia własnej przeglądarki obrazków.

Najczęsciej wykorzystywanymi metodami są:

Jak je uruchomić i jak działają? Banalnie, wystarczy wywołać je w kodzie JavaScript i powiązać z dowolnym zdarzeniem obsługującym wybrany element, np. .click(), .dblclick(), .hover(), .mouseover(), .mouseout(), .mouseleave(). Spróbujmy...

Przykład. Animacja kwadratów za pomocą jQuery.

fadeIn
fadeOut
on click
slideUp
slideDown
on double click
hide
show
on mouseout

Listing 1. Kod HTML i JavaScript odpowiedzialny za animację kwadratów.

 <!DOCTYPE html>
<html>
<head>
 <style>
.div_01, .div_02, .div_03 { float:left; width:70px; height:70px; margin: 0 10px 0 0; padding:5px; font-size:12px; color:#fff; }
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div class="div_01" style="background-color:#ff7f00;">fadeIn<br />fadeOut<br />on click</div>
<div class="div_02" style="background-color:#d00000;">slideUp<br />slideDown<br />on double click</div>
<div class="div_03" style="background-color:darkgreen;">hide<br />show<br />on mouseout</div>
<script type="text/javascript">
$(document).ready(function() {
	$(".div_01").click(function() {
		$(".div_01").fadeOut();
		$(".div_01").fadeIn();
	});
	$(".div_02").dblclick(function() {
		$(".div_02").slideUp();
		$(".div_02").slideDown();
	});		
	$(".div_03").mouseout(function() {
		$(".div_03").hide(600);
		$(".div_03").show(600);
	});
});
</script>
</body>
</html>

Metody .dblclick() oraz .mouseout() działają analogicznie jak omówiona w poprzednim rozdziale metoda .click(). Rejestrują one zdarzenia na wskazanym elemencie i wykonują instrukcje zawarte w ciele metody. I tak, metoda .click() rejestruje kliknięcie elementu o nazwie klasy div_01, wywołując efekty .fadeOut(), .fadeIn(), metoda .dblclick() - podwójne kliknięcie elementu div_02 (efekty .slideUp(), .slideDown()), metoda .mouseout() - opuszczenie przez kursor myszy obszaru elementu div_03 (efekty .hide(), .show()). Efekty .hide(), .show() wywoływane są z opcją określającą czas trwania animacji (w naszym przypadku: 600 milisekund), pozostałe przyjmują jego wartość domyślną (400 milisekund). Oczywiście, zamiennie można posłużyć się metodami .fadeToggle(), .slideToggle(), .toggle().

Listing 2. Równoważny kod JavaScript odpowiedzialny za animację kwadratów.

<script type="text/javascript">
$(document).ready(function() {
	$(".div_01").click(function() {
		$(".div_01").fadeToggle();
		$(".div_01").fadeToggle();
	});
	$(".div_02").dblclick(function() {
		$(".div_02").slideToggle();
		$(".div_02").slideToggle();
	});		
	$(".div_03").mouseout(function() {
		$(".div_03").toggle(600);
		$(".div_03").toggle(600);
	});
});
</script>

2. Projektowanie Slidera za pomocą arkusza stylów CSS

Własna przeglądarka grafik wymaga zaprojektowania Slidera. Jego wygląd zależy od naszej wyobraźni, potrzeb i uwarunkowań. Slider musi posiadać klasę obudowującą (wrapper), odpowiedzialną za zmianę i dynamiczne stylowanie zawartości oraz przyciski nawigacji (Poprzedni, Następny), sterujące jego zawartością. Może też posiadać dodatkową funkcjonalność - klasę wyświetlającą zawartość pojedynczych elementów wrappera, np. powiększenia miniatur obrazków.

Ilustracja. Wygląd Slidera (grafika poglądowa).

Oba przyciski projektujemy za pomocą dowolnego programu graficznego, resztę stylujemy i wyświetlamy wykorzystując CSS i HTML. Prawidłowe zdefiniowanie właściwości CSS jest bardzo istotne, ponieważ arkusz stylów określa nie tylko wygląd Slidera, ale także liczbę miniatur wyświetlanych jednocześnie wewnątrz wrappera, wielkość przesunięcia miniatury w lewo/prawo, itd. Niektóre z wartości CSS należy wyliczyć.

Szerokość Slidera (klasa: slider) obliczamy sumując:
     szerokość wrappera (klasa: wrapper) (z jego prawym i lewym: marginesem, dopełnieniem, ramką)
  + szerokość lewego przycisku (klasa: prev) (z jego prawym i lewym: marginesem, dopełnieniem, ramką).
  + szerokość prawego przycisku (klasa: next) (z jego prawym i lewym: marginesem, dopełnieniem, ramką).
W naszym przypadku: (816px + 0px + 0px + 0px + 0px + 0px + 0px) + (32px + 18px + 0px + 0px + 0px + 0px + 0px) + (32px + 0px + 18px + 0px + 0px + 0px + 0px) = 916px

Szerokość wprappera (klasa: wrpapper) obliczamy mnożąc:
     szerokość pozycji listy (klasa: wrapper_list li) (z jej prawym i lewym: marginesem, dopełnieniem, ramką)
  * założona liczba miniatur wyświetlanych jednocześnie wewnątrz wrappera
W naszym przypadku: (200px + 0px + 0px + 2px + 2px + 0px + 0px) * 4 = 816px (przy założeniu, że chcemy wyświetlać jednocześnie 4 miniatury)

Uwaga: Na podstawie szerokości pozycji listy (klasa: wrapper_list li) (z jej prawym i lewym: marginesem, dopełnieniem, ramką) skrypt oblicza szerokość przesunięcia (zmienna: Offset).

Szerokość miniatur wyświetlanych wewnątrz wprappera (klasa: wrapper_list li img):
     według własnego uznania (nie może przekraczać szerokości pozycji listy)

Szerokość i wysokość obrazka wyświetlanego pod spodem wprappera (klasa: img_zoom img):
     nie podajemy - obrazek będzie wyświetlany w rozmiarze oryginalnym (szerokość obrazka nie powinna przekraczać szerokości Slidera)

Wszystkie marginesy, dopełnienia, ramki, tła, style kursora oraz pozostałe szerokości i wysokości definiujemy według własnego uznania. Właściwości CSS, takie jak: position, overflow, float, display, clear pozostawiamy bez zmian.

Przykład. Kod HTML i CSS wyświetlający Slider.

  <!DOCTYPE html>
<html>
<head>
 <style>
.slider { width:916px; overflow:hidden; clear:both; margin:0; padding:0; border-width:1px; border-style:solid; border-color:#d4d4d4; }
.wrapper { width:816px; height:80px; float:left; position:relative; overflow:hidden; margin:0 auto; padding:20px 0; }
.wrapper_list { position:absolute; overflow:hidden; margin:0; padding:0; list-style-type:none; }
.wrapper_list li { width:200px; display:none; float:left; margin:0; padding:0 2px; cursor:pointer; }
.wrapper_list li img { width:200px; }
.slider .prev  { width:32px; height:80px; float:left; padding:0; margin:20px 18px 0 0; cursor:pointer; display:block; background: url('prev.png') no-repeat top left; /*outerWidth:50px*/}
.slider .next { width:32px; height:80px; float:left; padding:0; margin:20px 0 0 18px; cursor:pointer; display:block; background: url('next.png') no-repeat top left; /*outerWidth:50px*/}
.img_zoom { clear:both; text-align:center; margin:0; cursor:pointer; }
.img_zoom img { margin:0 0 20px 0; }
</style>
</head>
<body> 
    <div class="slider">
        <a href="#" class="prev"></a>
        <div class="wrapper">
            <ul class="wrapper_list">
                <li><img src="obrazek1.jpg" /></li>
                <li><img src="obrazek2.jpg" /></li>
            </ul>
        </div>
        <a href="#" class="next"></a>
    </div>
</body>
</html>

Omówmy krótko stosowane właściwości CSS*:

  • width - szerokość elementu w pikselach
  • height - wysokość elementu w pikselach
  • overflow - kontrola przepełnienia elementu (overflow:hidden - ukrywa nadmiar)
  • clear - przyleganie elementu względem elementu pływającego (clear:both - przesuwa dany element poniżej elementu pływającego)
  • margin - marginesy elementu w pikselach (margin:82px 20px 0 0 - margines górny: 82 piksele, prawy: 20 pikseli, dolny: 0 pikseli, lewy: 0 pikseli)
  • padding - dopełnienia elementu w pikselach (padding:20px 0 - dopełnienie górne i dolne: 20 pikseli, dopełnienie prawe i lewe: 0 pikseli)
  • border - obramowanie elementu (border:1px solid #d4d4d4 (notacja skrócona) - szerokość obramowania 1 piksel, styl obramowania - stały, kolor obramowania: d4d4d4)
  • float - pływanie elementu (float:left - element umieszczony po lewej stronie, a opływany po prawej)
  • position - pozycjonowanie elementu (position:relative - pozycjonowanie relatywne, position:absolute - pozycjonowanie absolutne)
  • list-style-type - styl punktowania/numerowania elementów listy (list-style-type:none - brak punktowania/numerowania elementów)
  • display - sposób wyświetlania elementu (display:none - nie wyświetla elementu, display:block - wyświetla element jako blok (odstęp z góry i z dołu))
  • cursor - wygląd kursora (cursor:pointer - kursor w postaci wskaźnika)
  • background - tło elementu (background:url('next.png') no-repeat top left (notacja skrócona) - url obrazka tła, powtarzanie tła (nie powtarzaj), pozycja tła (do góry, do lewej)

Sam kod HTML jest na tyle prosty, że nie wymaga wyjaśnień.

*Należy pamiętać, że niektóre właściwości CSS dziedziczone są przez selektory potomne.

3. Programowanie Slidera za pomocą JavaScript i jQuery

Przystępując do programowania Slidera należy przeanalizować, czy korzystać z opcji konfigurowalnych, a jeżeli tak to z jakich, jakie obsługiwać zdarzenia i jaką wybrać metodę animacji. Z pewnością opcjami konfigurowalnymi mogą być: czas pojedynczej animacji oraz stopień przezroczystości wybranej miniatury, a obsługiwanym zdarzeniem - .onlick(). Co do metody animacji - najbardziej odpowiednia wydaje się .animate(), a dokładnie przesuwanie miniatur w lewo lub w prawo. Implementacja tej metody jest nieco trudniejsza od metod przedstawionych na początku artykułu, gdyż wymaga obliczenia aktualnej pozycji miniatury, szerokości listy z miniaturami oraz wielkości pojedynczego przesunięcia.

Opcje konfigurowalne możemy zapisać w formacie JSON. Ponieważ uczynimy je zmiennymi globalnymi i umiejscowimy na początku skryptu, będą one widziane wewnątrz wszystkich jego funkcji. Opcje jak i cały kod umieszczamy wewnątrz konstrukcji $(document).ready(function() {...}) lub $(function() {...}) (notacja skrócona). Konstrukcja ta za pomocą zdarzenia .ready() sprawdza gotowość DOM do obsługi dokumentu.

Listing 3. Kod JavaScript z opcjami konfigurowalnymi.

<script type="text/javascript">
$(function() {
    var settings = {                    	
        Speed:       200,   // szybkosc animacji ('slow', 'normal', 'fast', millisekundy) (Animation Speed)
        Opac_E:     60,   // przezroczystosc po kliknieciu - Internet Explorer (Opacity for IE)
        Opac_M:  0.6    // przezroczystosc po kliknieciu - Mozilla, Google Chrome (Opacity for Mozilla, Google Chrome)
    };
});
</script>

Obsługę Slidera rozpoczynamy od odszukania potrzebnych nam elementów według nazwy klasy. Możemy je zrealizować na kilka sposobów (każda wymaga uruchomienia silnika Sizzle).

Listing 4. Kod JavaScript wyszukujący elementy wegdług nazwy klasy i przypisujący je do zmiennej sliders.

<script type="text/javascript">
$(function() {
    // ... opcje konfigurowalne
    var sliders = $('div.slider');
    // lub 
    // var sliders = $('.slider');
    // lub (o ile slider jest potomkiem innej warstwy DIV)
    // var sliders = $('div').find('.slider');
});
</script>

W kolejnym etapie przygotowujemy zmienne. Zważywszy, że chcemy mieć możliwość obsługi dowolnej liczby Sliderów na stronie, najpierw korzystamy z metody .each() poprzedzając ją zmienną sliders, a następnie wskazujemy na aktualny Slider za pomocą wskaźnika this. Od tego momentu, wszystkie operacje będziemy wykonywać, odwołując się do aktualnego Slidera.

Listing 5. Kod JavaScript inicjujący zmienne i nadający im wartości.

01.  <script type="text/javascript">
02.  $(function() {
03.      // ... opcje konfigurowalne 
04.      var sliders = $('div.slider');
05.      sliders.each(function() {
06.          var _Slider                = $(this);
07.          var _Wrapper           = $('div.wrapper', _Slider);
08.          var _List                   = $('ul.wrapper_list', _Slider);
09.          var _Item                  = $('li', _List);
10.          var _ImgZoom          = $('div.img_zoom', _Slider);
11.          var AllItems              = _Item.length;
12.          var ItemWidth          = parseInt(_Item.eq(0).outerWidth());
13.          var ListWidth           = ItemWidth*AllItems;
14.          var WrapperWidth   = parseInt(_Wrapper.eq(0).width());
15.          var VisibleItems        = parseInt(WrapperWidth/ItemWidth);
16.          var Offset                 = ItemWidth + parseInt(_Item.eq(0).css('margin-left')) + parseInt(_Item.eq(0).css('margin-right'));
16.          // var Offset              = parseInt(_Item.eq(0).outerWidth(true))
17.          var PrevClickedItem = -1;
18.      });
19.  });
20.  </script>

Listing 5 krok po kroku:
(Listing 5. 02) - za pomocą zdarzenia .ready() sprawdzamy gotowość DOM do obsługi dokumentu
(Listing 5. 04) - wyszukujemy w dokumencie wszystkie warstwy o nazwie klasy slider i przypisujemy je do zmiennej sliders
(Listing 5. 05) - za pomocą metody .each() informujemy jQuery, że operacje dotyczyć będą wszystkich wyszukanych warstw przypisanych do zmiennej sliders
(Listing 5. 06) - korzystając z this wskazujemy na aktualny Slider i przypisujemy go do zmiennej _Slider
(Listing 5. 07) - wyszukujemy w aktualnym Sliderze warstwę o nazwie klasy wrapper i przypisujemy ją do zmiennej _Wrapper
(Listing 5. 08) - wyszukujemy w aktualnym Sliderze listę o nazwie klasy wrapper_list i przypisujemy ją do zmiennej _List
(Listing 5. 09) - wyszukujemy wszystkie elementy listy i przypisujemy je do zmiennej _Item
(Listing 5. 10) - wyszukujemy w aktualnym Sliderze warstwę o nazwie klasy img_zoom i przypisujemy ją do zmiennej _ImgZoom
(Listing 5. 11) - obliczamy liczbę wszystkich elementów listy i przypisujemy ją do zmiennej AllItems
(Listing 5. 12) - za pomocą .outerWidth() oraz .eq() pobieramy z CSS szerokość elementu listy o indeksie 0 (razem z ramkami, dopełnieniami, bez marginesów) i przypisujemy ją do zmiennej ItemWidth*
(Listing 5. 13) - obliczamy szerokość listy mnożąc szerokość jej elementu przez liczbę jej elementów i przypisujemy ją do zmiennej ListWidth
(Listing 5. 14) - za pomocą .width() oraz .eq() pobieramy z CSS szerokość wrappera o indeksie 0 (bez marginesów, dopełnień, ramek) i przypisujemy ją do zmiennej WrapperWidth*
(Listing 5. 15) - obliczamy liczbę jednocześnie wyświetlanych elementów listy dzieląc szerokość wrappera przez szerokość elementu listy i przypisujemy ją do zmiennej VisibleItems*
(Listing 5. 16) - obliczamy wielkość przesunięcia dla pojedynczego elementu - za pomocą .outerWidth(true) oraz .eq() pobieramy z CSS szerokość elementu listy o indeksie 0 (z marginesami, dopełnieniami, ramkami) i przypisujemy ją do zmiennej Offset* (zamiennie możemy do zmiennej ItemWidth dodać lewy i prawy margines elementu). W naszym przypadku: 200px + 2px + 2px = 204px
(Listing 5. 17) - przypisujemy do zmiennej PrevClickedItem indeks klikniętej miniatury (wartość początkowa -1, oznacza że nie został kliknięty żaden element listy (miniatura), gdyż taki indeks nie istnieje)

*Metoda parseInt() zwraca nam liczbę całkowitą.

Po przygotowaniu zmiennych, definiujemy szerokość listy, wyświetlamy jej elementy i piszemy funkcje obsługujące zdarzenie .click() dla przycisków (Poprzedni, Następny).

Listing 6. Kod JavaScript wyświetlający listę z miniaturami i obsługujący przyciski Poprzedni, Następny (przewijanie w lewo, w prawo).

01.  <script type="text/javascript">
02.  $(function() {
03.      // ... opcje konfigurowalne
04.      var sliders = $('div.slider');
05.      sliders.each(function() {
06.          // ... zmienne
07.          $(_List).css('width',ListWidth);
08.          $(_Item).show();
09.          if (ListWidth > WrapperWidth) {
10.              var maxOffsetLeft = Offset * AllItems - Offset * VisibleItems;
11.              var Next = $('a.next', _Slider).click(function() {
12.                  if (_List.position().left > -maxOffsetLeft) {
13.                      $(_List).not(':animated').animate({ 'left' : '-='+Offset },settings.Speed); 
14.                      return false;
15                   };
16.              });
17.              var Prev = $('a.prev', _Slider).click(function() {
18.                  if (_List.position().left<0) { 
19.                      $(_List).not(':animated').animate({ 'left' : '+='+Offset },settings.Speed); 
20.                      return false;
21                   };
22.              });
23.          }
24.          else {
25.              $('a.next, a.prev', _Slider).click(function() { return false; });
26.          };
27.      });
28.  });
29.  </script>

Listing 6 krok po kroku:
(Listing 6. 07) - za pomocą właściwości CSS o nazwie width definiujemy szerokość listy (z miniaturami) (dla aktualnego Slidera)
(Listing 6. 08) - wyświetlamy listę
(Listing 6. 09) - sprawdzamy, czy szerokość listy jest większa od szerokości wrappera (tylko wtedy ma sens przewijanie w lewo i w prawo)
(Listing 6. 10) - jeżeli warunek jest spełniony, obliczamy maksymalne przesunięcie listy w lewo (szerokość przesunięcia * liczba wszystkich elementów minus szerokość przesunięcia * liczba jednocześnie wyświetlanych elementów)
(Listing 6. 11) - przypisujemy do zmiennej Next każde zarejestrowane kliknięcie odnośnika aktualnego Slidera o nazwie klasy next i rozpoczynamy wykonywanie instrukcji zawartych w ciele metody .click()
(Listing 6. 12) - sprawdzamy, czy lewa pozycja listy jest większa niż maksymalne ujemne przesunięcie w lewo (wartości mierzone są w piskelach). Początkowo pozycja listy wynosi: 0 pikseli. Po pierwszym przesunięciu w lewo, zmienia się ona o wartość zmiennej Offset, czyli w naszym przypadku wynosi: -204 piksele, po drugim: -408 pikseli, itd. Listę przesuwamy w lewo do momentu, aż po jej prawej stronie pojawi się ostatni element listy (miniatura), czyli do osiągnięcia ujemnej wartości maksymalnego przesunięcia listy w lewo. Gdybyśmy przesuwali ją dalej, na końcu listy powstałoby puste miejsce (dlatego też maksymalne przesunięcie listy w lewo pomniejszamy o: szerokość przesunięcia * liczba jednocześnie wyświetlanych elementów).

Ilustracja. Koniec przesuwania listy w lewo dla 8 miniatur, przy 4 miniaturach wyświetlanych jednocześnie.

(Listing 6. 13) - jeżeli warunek jest spełniony i lista nie jest aktualnie animowana .not(':animated'), korzystając z metody .animate() przesuwamy listę w lewo o (ujemną) wartość zmiennej Offset z szybkością podaną w opcjach konfiguracyjnych
(Listing 6. 14) - po kliknięciu na przycisk Następny (dla DOM - odnośnik) zwracamy false, aby przeglądarka internetowa nie wyczyniała cudów i nie powracała na do górę strony
(Listing 6. 17) - przypisujemy do zmiennej Prev każde zarejestrowane kliknięcie odnośnika aktualnego Slidera o nazwie klasy prev i rozpoczynamy wykonywanie instrukcji zawartych w ciele metody .click()
(Listing 6. 18) - sprawdzamy, czy lewa pozycja listy jest mniejsza od 0 (oznacza to, że lista nie znajduje się w pozycji początkowej i można ją przesuwać w prawo)
(Listing 6. 19) - jeżeli warunek jest spełniony i lista nie jest aktualnie animowana .not(':animated'), korzystając z metody .animate() przesuwamy listę w lewo o (dodatnią) wartość zmiennej Offset z szybkością podaną w opcjach konfiguracyjnych. Przesunięcie listy w lewo o dodatnią wartość, powoduje w efekcie przesunięcie listy w prawo.
(Listing 6. 20) - po kliknięciu na przycisk Poprzedni (dla DOM - odnośnik) zwracamy false, aby przeglądarka internetowa nie wyczyniała cudów i nie powracała na do górę strony
(Listing 6. 24) - jeżeli szerokość listy jest większa lub równa szerokości wrappera, po kliknięciu na przyciski zwracamy false, czyli nie obsługujemy przewijania

Ostatnim etapem programowania Slidera jest wyświetlanie obrazka w oryginalnych rozmiarach po kliknięciu na element listy (miniaturę) oraz usuwanie wyświetlonego obrazka.

Listing 7. Kod JavaScript wyświetlający/usuwający obrazek po kliknięciu na element listy (miniaturę).

01.  <script type="text/javascript">
02.  $(function() {
03.      // ... opcje konfigurowalne
04.      var sliders = $('div.slider');
05.      sliders.each(function() {
06.          // ... zmienne
07.          // ... przewijanie w lewo, w prawo 
08.          var ItemClick = $(_Item).click(function() {
09.              var ClickedItem = _Item.index(this);
10.              CheckClick();
11.              if (PrevClickedItem != ClickedItem) {
12.                  _Item[ClickedItem].style.opacity = settings.Opac_M;
13.                  _Item[ClickedItem].style.filter = 'Alpha(Opacity='+settings.Opac_E+')';
14.                  var ImgSrc = $('img', _Item[ClickedItem]).attr('src');
15.                  $(_ImgZoom).append('<img src="'+ImgSrc+'" title="Click to close Image" />');
16.                  PrevClickedItem = ClickedItem;
17.              }
18.              else { PrevClickedItem = -1; }
19.          });
20.
21.          var ImageClick = $('div.img_zoom', _Slider).click(function() {
22.              CheckClick();
23.              PrevClickedItem = -1;
24.          });
25.
26.          var CheckClick = (function() {
27.              for (i=0; i<AllItems; i++) {
28.                  _Item[i].style.opacity = 1.0; // z wyjatkiem IE
29.                  _Item[i].style.filter = 'Alpha(Opacity=100)'; // IE
30.              };
31.              if(_ImgZoom.children().length > 0) { 
32.                  _ImgZoom.children().remove();
33.              };
34.          });
35.      });
36.  });
37.  </script>

Listing 7 krok po kroku:
(Listing 7. 08) - przypisujemy do zmiennej ItemClick każde zarejestrowane kliknięcie elementu listy aktualnego Slidera i rozpoczynamy wykonywanie instrukcji zawartych w ciele metody .click()
(Listing 7. 09) - przypisujemy do zmiennej ClickedItem indeks klikniętego elementu listy
(Listing 7. 10) - wywołujemy funkcję CheckClick() usuwającą przezroczystość wszystkich elementów listy (miniatur) i wyświetlany pod nimi obrazek
(Listing 7. 11) - sprawdzamy, czy indeks poprzednio klikniętego elementu listy (wartość początkowa: -1) jest równy indeksowi aktualnie klikniętego elementu (miniatury)
(Listing 7. 12-13) - jeżeli warunek jest spełniony, ustawiamy przezroczystość zgodnie z wartością podaną w opcjach konfiguracyjnych (osobno dla Internet Explorer i pozostałych przeglądarek)
(Listing 7. 14) - przypisujemy do zmiennej ImgSrc wartość atrybutu src klikniętego elementu listy, czyli url miniatury
(Listing 7. 15) - za pomocą .append() dodajemy do warstwy img_zoom przypisanej do zmiennej _ImgZoom element img z atrybutem src równym url-owi klikniętego elementu listy (miniatury)
(Listing 7. 16) - przypisujemy do zmiennej PrevClickedItem indeks klikniętego elementu listy
(Listing 7. 18) - jeżeli warunek nie jest spełniony, przypisujemy do zmiennej PrevClickedItem wartość: -1
(Listing 6. 21) - przypisujemy do zmiennej ImageClick każde zarejestrowane kliknięcie warstwy aktualnego Slidera o nazwie klasy img_zoom (czyli oryginalnego obrazka) i rozpoczynamy wykonywanie instrukcji zawartych w ciele metody .click()
(Listing 7. 22) - wywołujemy funkcję CheckClick() usuwającą przezroczystość wszystkich elementów listy (miniatur) i wyświetlany pod nimi obrazek
(Listing 7. 23) - przypisujemy do zmiennej PrevClickedItem wartość: -1
(Listing 7. 26) - przypisujemy do zmiennej CheckClick funkcję usuwającą przezroczystość wszystkich elementów listy (miniatur) i wyświetlany pod nimi obrazek
(Listing 7. 27-30) - iterujemy po wszystkich elementach listy, usuwając ich przezroczystość (osobno dla Internet Explorer i pozostałych przeglądarek)
(Listing 7. 31) - sprawdzamy, czy warstwa img_zoom przypisana do zmiennej _ImgZoom posiada potomków (dokładnie, czy ich liczba jest większa od 0)
(Listing 7. 32) - jeżeli warunek jest spełniony, usuwamy wszystkich potomków tej warstwy

Osobnego wyjaśnienia wymaga zmienna PrevClickedItem. Jak już wspomnieliśmy, przechowuje ona indeks klikniętej miniatury. Ponieważ indeksy liczone są od 0 w górę, wartość -1, oznacza nigdy nie występujący indeks. Sztuczka ta pozwala nam kontrolować zachowanie Slidera zarówno po kliknięciu na element listy (miniaturę) jak i oryginalny obrazek. W jaki sposób? Otóż po kliknięciu na element listy (Listingu 7. 08), wywoływana jest funkcja CheckClick() usuwającą przezroczystość jej wszystkich elementów oraz, o ile istnieją, elementy potomne warstwy img_zoom, czyli oryginalny obrazek. Następnie warunek if sprawdza, czy zmienna PrevClickedItem nie jest równa zmiennej ClickedItem, czyli indeksowi klikniętego elementu listy (Listing 7. 11). Jeżeli warunek jest spełniony, (czyli wartość PrevClickedItem wynosi -1), zostaje wyświetlony oryginalny obrazek, ustawiona przezroczystość a PrevClickedItem przypisany indeks klikniętego elementu. W tym momencie użytkownik może podjąć trzy akcje, które musi obsłużyć skrypt:

  1. Akcja 1 - powtórnie kliknąć na ten sam element listy (miniaturę) - skrypt usuwa przezroczystość wszystkich elementów i oryginalny obrazek
  2. Akcja 2 - kliknąć na oryginalny obrazek - skrypt usuwa przezroczystość wszystkich elementów i oryginalny obrazek
  3. Akcja 3 - kliknąć na inny element listy (miniaturę) - skrypt usuwa przezroczystość wszystkich elementów, oryginalny obrazek, ustawia przezroczystość nowego klikniętego elementu i wyświetla jego oryginalny obrazek

W przypadku Akcji 1 (Listing 7. 8-19), po kliknięciu - zmienna PrevClickedItem jest równa indeksowi klikniętego elementu listy, zatem po usunięciu przezroczystości i oryginalnego obrazka, nie jest spełniony warunek (Listing 7. 11), co powoduje, że nie jest wyświetlany oryginalny obrazek i ustawiana przezroczystość, a zmiennej PrevClickedItem zostaje przypisana wartość: -1 (i wszystko zaczyna się od nowa).

W przypadku Akcji 2, (Listing 7. 21-24) po kliknięciu usuwana jest przezroczystość i oryginalny obrazek, a zmiennej PrevClickedItem zostaje przypisana wartość: -1 (i wszystko zaczyna się od nowa).

W przypadku Akcji 3 (Listing 7. 8-19), po kliknięciu - zmienna PrevClickedItem nie jest równa indeksowi klikniętego elementu listy, zatem po usunięciu przezroczystości starego elementu i jego obrazka, spełniony jest warunek (Listing 7. 11), co powoduje, że ustawiana jest przezroczystość nowego klikniętego elementu i wyświetlany jest jego oryginalny obrazek, a zmiennej PrevClickedItem zostaje przypisana wartość klikniętego elementu.

Poniżej cały kod odpowiedzialny za obsługę Slidera

Listing 8. Skrypt JavaScript odpowiedzialny za obsługę Slidera.

<script type="text/javascript">
// Script: Simple Slider 1.0. Require jQuery.
// Author: Ireneusz Sekula, http://secom.pl, 2012-08-10
// Free to use and abuse under the MIT license.
$(function() {
// Opcje konfiguracyjne    
    var settings = {                 	
        Speed:   200,
        Opac_E:   60,
        Opac_M:  0.6
    };
// Obsluga Slidera
    var sliders = $('div.slider');
    sliders.each(function() {
// Zmienne
        var _Slider = $(this); // wskazanie na aktualny Slider
        var _Wrapper = $('div.wrapper', _Slider);
        var _List = $('ul.wrapper_list', _Slider);
        var _Item = $('li', _List);
        var _ImgZoom = $('div.img_zoom', _Slider);
        var AllItems = _Item.length;
        var ItemWidth = parseInt(_Item.eq(0).outerWidth());
        var ListWidth = ItemWidth*AllItems;
        var WrapperWidth = parseInt(_Wrapper.eq(0).width());
        var VisibleItems = parseInt(WrapperWidth/ItemWidth);
        var Offset = parseInt(_Item.eq(0).outerWidth(true));
        //var Offset = ItemWidth + parseInt(_Item.eq(0).css('margin-left')) + parseInt(_Item.eq(0).css('margin-right'));
        var PrevClickedItem = -1;
        $(_List).css('width',ListWidth);
        $(_Item).show();
// Obsluga przewijania w lewo, w prawo (klikniecia przycisków Poprzedni, Nastepny)
        if (ListWidth > WrapperWidth) {
            var maxOffsetLeft = Offset * AllItems - Offset * VisibleItems;
            // Przewijanie w lewo (przycisk Nastepny)
            var Next = $('a.next', _Slider).click(function() {
                if (_List.position().left > -maxOffsetLeft) { $(_List).not(':animated').animate({ 'left' : '-='+Offset },settings.Speed); };
                return false;
            });
            // Przewijanie w prawo (przycisk Poprzedni)
            var Prev = $('a.prev', _Slider).click(function() {
                if (_List.position().left<0) { $(_List).not(':animated').animate({ 'left' : '+='+Offset },settings.Speed); };
                return false;
            });
        }
        // Pomijanie przewijania w lewo, w prawo, jezeli na liscie wsywietlane sa jednoczesnie wszystkie jej elementy
        else {
            $('a.next, a.prev', _Slider).click(function() { return false; });
        };
// Obsluga klikniecia miniatury obrazka
        var ItemClick = $(_Item).click(function() {
            var ClickedItem = _Item.index(this);
            CheckClick();
            if (PrevClickedItem != ClickedItem) {
                // Ustawienie przezroczystosci miniatury i wyswietlenie oryginalnego obrazka wedlug wartosci atrybutu src miniatury
                _Item[ClickedItem].style.opacity = settings.Opac_M;
                _Item[ClickedItem].style.filter = 'Alpha(Opacity='+settings.Opac_E+')';
                var ImgSrc = $('img', _Item[ClickedItem]).attr('src');
                $(_ImgZoom).append('<img src="'+ImgSrc+'" title="Click to close Image" />');
                PrevClickedItem = ClickedItem;
            }
            else { PrevClickedItem = -1; }
        });
// Obsluga klikniecia oryginalnego obrazka
        var ImageClick = $('div.img_zoom', _Slider).click(function() {
            CheckClick();
            PrevClickedItem = -1;
            return false;
        });
// Sprawdzenie stanu Slidera po kliknieciu na miniature lub oryginalny obrazek
        var CheckClick = (function() {
		   // Usuniecie przezroczystosci dla wszystkich miniatur o0brazkow
		   for (i=0; i<AllItems; i++) {
               _Item[i].style.opacity = 1.0; // z wyjatkiem IE
               _Item[i].style.filter = 'Alpha(Opacity=100)'; // IE
           };
           // Usuniecie oryginalnego obrazka (dokladnie: wszystkich potomkow warstwy rodzica)
           if(_ImgZoom.children().length > 0) { _ImgZoom.children().remove(); };
           return true;
        });	   
    });
});
</script>

Zobacz demo: Prosty Slider

Ireneusz Sekuła, JavaScript dla zielonych