70-480 – Wywoływanie i obsługa zdarzenia

70-480

Obsługa typowych zdarzeń udostępnianych przez model DOM (OnBlur, OnFocus, OnClick); deklarowanie i obsługa zdarzeń propagowanych; obsługa zdarzenia przy użyciu funkcji anonimowej.



Wracając już do tematu artykułu – zdarzenia w przeglądarce występują na porządku dziennym i to w ogromnych ilościach. Język JavaScript pozwala nam deklarować obsługę takich zdarzeń w postaci funkcji. Zdarzenia związane są także z terminem ich propagowania (bąbelkowaniem).

Zdarzenia DOM

JavaScript pozwala przypisywać zdarzenia do elementów HTML. Obsługa tych zdarzeń deklarowana jest w funkcjach przypisanych do konkretnego zdarzenia, a funkcje te są wywoływane dopiero w momencie wystąpienia zdarzenia. Ilość zdarzeń jest ogromna, a mamy również możliwość tworzenia własnych zdarzeń (o czym niżej).

Pewnie nie raz spotkaliście się z:

  • onclick (kliknięcie),
  • onblur (utrata aktywności – przeciwieństwo onfocus),
  • onfocus (aktywność elementu – przeciwieństwo onblur),
  • onscroll (zdarzenie wywoływane w momencie zmiany pozycji w pionie).

Pokaźna ich lista znajduje się na stronie w3schools.

Deklarowanie i obsługa zdarzeń

Mamy kilka możliwości na deklarowanie i obsługę zdarzeń DOM:

  • inline
  • przypisując funkcję do pola obiektu HTML
  • rejestrując obsługę konkretnego zdarzenia za pomocą funkcji addEventListener (attachEvent – starsze wersje IE)

Deklaracja inline

Najprostsza i najbardziej prymitywna opcja obsługi zdarzenia, to tak zwana deklaracja inline. Nie jest ona zbyt często spotykana, a powinna być wręcz niepożądana ze względu na mieszanie logiki JavaScript z widokiem HTML.

Spójrzmy na przykład deklaracji zdarzenia, które wywoła okienko typu alert w momencie kliknięcia w osadzony na stronie przycisk.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/1/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Widzimy tutaj deklaracje zdarzenia onclick za pomocą atrybutu i wywołania funkcji alert na elemencie button. Nic prostszego, ale warto wspomnieć, że w taki sposób nie mamy dostępu do słowa kluczowego this danego elementu.

Przypisanie funkcji do pola obiektu HTML

Spójrzmy od razu na przykład, który realizuje dokładnie taką samą funkcjonalność jak poprzednia wersja z deklaracją inline.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/2/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Tym razem brakuje atrybutu onlick dla elementu button, ale pojawił się kawałek kodu JavaScript. Pobieramy w nim referencje do przycisku, a następnie do pola onlick przypisujemy funkcję, która wykonuje dokładnie taki sam kod jak poprzedni, czyli funkcję alert.

Tak jak już wspomniałem wcześniej, deklaracje inline nie pozwalają używać słowa kluczowego this. Zobaczmy jeszcze raz na ten sam przykład, ale z wykorzystaniem słowa kluczowego this.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/3/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Tym razem funkcja alert przyjmuje jako argument wywołanie this.firstChild.nodeValue, a to nic innego jak wartość tekstowa przycisku, dla którego deklarujemy zdarzenie onlick. Poprzez użycie referencji do obiektu (this) mamy dostęp do elementu, dla którego zadeklarowane zostało zdarzenie.

To co można zauważyć, to fakt, że takie przypisanie funkcji do pola obiektu pozwala nam na obsługę danego zdarzenia tylko w jeden sposób. Jeżeli chcielibyśmy dodać kilka funkcji, mających się wywołać na kliknięcie myszką na przycisk, to nie jesteśmy w stanie zrobić tego w prosty sposób lub wręcz w ogóle nie jesteśmy w stanie tego wykonać.

By odrejestrować zdarzenie wystarczy przypisać do tego samego pola wartość null.

Funkcja addEventListener

Ostatnim i polecanym sposobem rejestracji zdarzenia jest funkcja addEventListener. Przyjmuje ona trzy argumenty:

  • nazwa zdarzenia
  • funkcja obsługująca zdarzenie
  • flaga włączająca lub wyłączająca bąbelkowanie zdarzenia (patrz kolejny podrozdział)

I od razu przykład, by nie było “na sucho”:

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/4/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Po raz kolejny jest to ta sama funkcjonalność, ale tym razem z użyciem funkcji addEventListener oraz słowa kluczowego this. Jak widać – w kodzie JavaScript zadeklarowana zostałą również funkcja invokeAlert, która przekazywana jest niżej jako drugi parametr funkcji. Sama nazwa zdarzenia nie zawiera także przedrostka on.

Deklaracja dodatkowej (nazwanej) funkcji pozwala ją również później odrejestrować za pomocą funkcji removeEventListener.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/5/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Funkcja removeEventListener zostaje wywołana dla przycisku w ciele funkcji invokeEvent. Skutkuje to tym, że zdarzenie zostaje zarejestrowane, co umożliwia wywołanie zadeklarowanej funkcji po kliknięciu na przycisk, a następnie funkcja removeEventListener usuwa to zdarzenie z przycisku. Tym samym przycisk nie pokazuje nam już okienka typu alert.

Funkcja podawana jako drugi argument obu funkcji nie musi być oczywiście nazwana, ale w takim momencie nie mamy możliwości jej odrejestrowania.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/6/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Ostatnia już przykład, który pokazuje nam możliwość definicji wielu funkcji, które reagować będą na to samo zdarzenie.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/7/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Dla przycisku zadeklarowane zostaje dwukrotnie zdarzenie click z obsługą w postaci dwóch funkcji invokeAlert oraz doSomething. Pierwsza funkcja jest nam dobrze znana. Druga natomiast wykonana zostaje zaraz po pierwszej i dodaje kolejny przycisk nas stronie, zaraz za przyciskiem, dla którego zadeklarowane zostało zdarzenie click.

Dla starszych przeglądarek Internet Explorer (<= 10) istnieje funkcja attachEvent.

Event bubbling – propagacja zdarzenia

Ostatnim elementem, o którym warto nadmienić w tym temacie, to bąbelkowe wywoływanie zdarzeń. Polega ono na przekazywaniu zdarzenia do kolejnych elementów w górę całej hierarchii, aż do elementu document. Trzeci argument funkcji addEventListener powoduje włączenie przekazywania zdarzeń (wartość true) lub ich wyłączenie (wartość false). W momencie włączenia przekazywania zdarzeń w górę, wszystkie elementy znajdujące się wyżej w hierarchii danego elementu HTML otrzymują powiadomienie o konieczności obsługi takiego zdarzenia. Oczywiście taka obsługa ma miejsce, gdy dla tych elementów, które są wyżej zadeklarowane zostało dane zdarzenie.

Spójrzmy na przykład, który powinien rozwiać wszystkie wątpliwości:

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/9/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Klikając w najbardziej wewnętrzny element (element3) wykonuje się propagacja zdarzenia click aż do elementu skrajnego (element1). Następnie wywołana zostaje obsługa zdarzenia, poczynając od najbardziej skrajnego elementu. Więc wyświetli nam się w tym wypadku trzy razy okienko typu alert z wartościami, odpowiednio: element1element2element3.

Obsługę zdarzenia możemy przerwać, wykonując funkcję stopPropagation() na obiekcie event przekazanym do funkcji obsługującej dane zdarzenie.

[wp-js-fiddle url="https://jsfiddle.net/mrzepinski/qddothdt/11/" style="width:100%;height:400px;border:solid #4173A0 1px;"]

Widzimy tutaj deklarację kolejnej funkcji stop. Zostaje ona przypisana dla elementu element2. Po kliknięciu w najbardziej wewnętrzny element (element3) tym razem otrzymamy sekwencję alertów: element1element2. Nie wywoła się alert dla elementu element3 ze względu na to, że element wyżej w hierarchii zatrzymuje propagowanie zdarzenia click dalej.