Kawałek Kodu

Baczność! Informuję Czytelników, że dzisiejszy wpis to nie będą przelewki. Nie będziemy podziwiać ładnych efektów siedząc przed komputerem, ale będzie to prawdziwa strzelanina na polu walki. Kto odważny niech wystąpi z szeregu. W dół czytaj!

Poligon.

Aby zacząć musimy zacząć od... początku. Żeby odpalić zdarzenia delegowane musimy mieć jakieś pole do działań. Będzie to fragment HTML (DOM) i podpięta do jakiegoś elementu obsługa wybranego zdarzenia. Wykorzystajmy najprostszy i chyba najczęściej spotykany przykład, czyli obsługa grupy linków.

<ul>
 <li><a href="#glowna">Główna</a></li>
 <li><a href="#o-firmie">O firmie</a></li>
 <li><a href="#uslugi">Usługi</a></li>
 <li><a href="#kontakt">Kontakt</a></li>
</ul>

Będziemy chcieli dla kliknięcia każdego z czterech linków wykonać jakąś akcję. Nie ma sensu podpinania obsługi zdarzenia kliknięcia do każdego z elementów A. Delegowanie zdarzeń pozwala na podpięcie obsługi do wybranego kontenera zawierającego w sobie elementy, które chcemy obsłużyć. Klikając w element A zdarzenie "bąbelkuje" czyli jest odbierane po kolei przez każdego jego przodka.

Jeśli klikniemy w A, to o tym fakcie zostaną po kolei poinformowane:

  • oczywiście A,
  • LI,
  • UL,
  • BODY
  • document

Element A jest jak żołnierz wstrzymujący oddech w bagnistym jeziorze. Kiedy wypuści kilka bąbelków (np. z buzi), czyli wywoła zdarzenie, to te będą unosić się do góry pokonując kolejne metry głębin jeziora (czyli LI, UL, BODY), aż dotrą do powierzchni (czyli do elementu document).

W naszym przypadku najrozsądniejsza będzie obsługa zdarzenia w elemencie UL:

document.querySelector('ul').addEventListener('click', function(e){
});

Chcąc dowiedzieć się jaki konkretnie element wywołał całe zamieszanie, sprawdzamy właściwość target zmiennej e (e jest w tym przypadku instancją MouseEvent/Event):

document.querySelector('ul').addEventListener('click', function(e){
 if(e.target.tagName === 'A'){
   alert(e.target.href);
 }
});

Oczywiście target możemy sprawdzać nie tylko pod kątem tego jakim jest tagiem, ale jaką ma klasę, atrybut, właściwość, itd. W naszym przypadku wystarczy prosty warunek, ale należy pamiętać, że mając element o danym tagu zagłębiony w takim samym tagu, to kliknięcie na którykolwiek z nich, spełni tak prosty warunek. W takim przypadku należałoby go rozbudować.

W tej chwili wiemy jak wyłapać wystrzelone bąbelki na wybranym poziomie i dowiedzieć się jakiej wielkości jest bańka. A jak zmusić żołnierza, aby "wystrzelił" kilka bąbelków (nadal np. z buzi).

Strzelnica.

Musimy skorzystać z metody dispatchEvent, której przekażemy jako argument utworzony obiekt Event.

// tworzymy zdarzenie
var e = document.createEvent("Event");
// to będzie klikanie
e.initEvent("click");
/* odpalamy je na wybranym
   elemencie
*/
document.querySelector('a[href="#kontakt"]').dispatchEvent(e);

Powyższy kod zadziała jeśli handler obsługi zdarzenia byłby podpięty bezpośrednio do elementu A. Aby zadziałał w takiej formie, trzeba jako drugi element metody initEvent przekazać wartość true. Ten argument mówi czy zdarzenie ma się bąbelkować czy nie. Nadal więc wywołujemy zdarzenie na elemencie A, ale tym razem zostanie ono rozpropagowane w górę. Zmieniamy więc na:

e.initEvent("click", true);

I tym razem wyglada to tak:

Pomimo "delegowanej" obsługi procedury zdarzeń, ich odpalanie nadal wykonujemy na konkretnym elemencie, a nie na kontenerze, do którego jest podpięta obsługa (co byłoby bez sensu). Musimy jednak sprawić, aby kontener obsługujący zdarzenie odebrał je. Co powyżej poczyniliśmy. Spocznij!

 

Przydatne linki:
Tworzenie zdarzeń.
Inicjowanie zdarzeń.
Wywoływanie zdarzeń na elemencie.