Uvod

Događaji su pojave, koje su najčešće rezultat nečega što korisnik uradi (klik mišem, klik na tastaturi, drag and drop….), mada mogu biti izazvane i od strane sistema, browsera… Registrovanje dogadjaja na nekom HTML elementu podrazumeva vezivanje osluškivača dogadjaja (eng. event listener) za HTML elemenat i definisanje posledice tog događaja. Event listener nakon izvršenog dogadjaja poziva na akciju obrađivače događaja (eng. event handler). Event handler je callback funkcija koja se aktivira kao posledica nekog dogadjaja.

Event objekat

Kada god se desi neki dogadjaj (eng. event), javascript smešta sve relevantne podatke vezane za dogadjaj u event objekat (npr. gde je bio mouse pointer, kojim dugmetom je kliknuto, koje element je kliknut…). Ovaj event objekat se uvek prosledjuje callback funkciji a podacima smeštenim u njemu možemo pristupiti preko svojstva event objekta. Spisak svih svojstava event objekata možete pogledati ovde.

Primer

Primer

See the Pen Primer korišćenja event objekta by Web programiranje (@chos) on CodePen.


Redosled izvršavanja pri propagaciji

bubbling

Ukoliko imamo HTML elemente koji su “ugnježdjeni” jedan unutar drugog a svi imaju zakačen neki event listener, dogadjaji se ne izvršavaju odjednom nego prema odredjenom redosledu. Redosled izvršavanja dogadjaja može biti:
a) Bubbling
Ovakav redosled podrazumeva aktiviranje dogadjaja od unutrašnjeg elementa ka spoljnom (od deteta ka roditelju, pogledaj sliku). Skoro svi dogadjaji su bubbling osim par izuzetaka kao npr. focus dogadjaj kod koga je default-ni redosled capturing.
b) Capturing
Ovakav redosled podrazumeva aktiviranje dogadjaja od spoljnog ka unutrašnjem (od roditelja ka detetu)

Razlika izmedju THIS i event.target

Potrebno je naglasiti da u slučaju postojanja više HTML elemenata sa registrovanim dogadjaima, i medjusobno su ugnježđeni vrednost event.target ne ukazuje uvek isto što i ključna reč “this”!
Svojstvo objekata “event.target” ukazuje na element koji je inicirao dogadjaj dok “this” ukazuje na element na kome se trenutno izvršava obradjivač dogadjaja (event.currentTarget).

See the Pen Razlika izmedju THIS i event.target by Web programiranje (@chos) on CodePen.

Zaustavljanje propagacije

Ukoliko se iz nekog razloga pojavi potreba da se spreči “širenje uticaja dogadjaja” (eng. stop propagation) od targetiranog elementa duž DOM-a koristi se metoda event.stopPropagation(). Ali ako želimo da uključimo u zabranu i targetirani element (tj. da sprečimo da reaguje na dogadjaj), onda koristimo metodu event.stopImmediatePropagation()

Primer

Registrovanje dogadjaja

JavaScript

Postoje više različitih metoda za registrovanje dogadjaja u JavaScript-u.

Inline event handler (preko HTML atributa)

Inline event handlers registruje dogadjaj kroz HTML atribut i pripada zastarelom načinu za registrovanje dogadjaja. HTML atribut se dobija tako što se uz naziv dogadjaja dodaje prefiks “on” tj. on{eventtype}.

Primer br.1

Primer br.2

Ovakav postupak i dalje može da “uradi posao” mada nije najbolja praksa jer ima više mana:

  • Ne odvaja JS od HTML-a
  • Sprečava dodavanje više “event handlers” (funkcija koje se izvršavaju nakon JS dogadjaja) po istom dogadjaju
  • Nije praktičano ukoliko treba da se primeni odredjeni dogadjaj na više istih vrsta HTML tag-ova, jer treba upisati kod u svaki tag.
  • Pri korišćenju inline event handler-a ključna reč THIS ukazuje na globalni objekat tj. widnow objekat (jer HTML atribut nije vlasnik funkcije nego samo function call-a).
  • U slučaju da je inline event handler ugradjen u tag <a href=””></a>, javljaju se problemi sa redosledom dogadjaja jer se takodje pokreće atribut href koji će otvoriti drugu stranicu.

Traditional event registration model

Ovaj model je bolji od inline event handler-a jer razdvaja JS od HTML koda i ključna reč THIS ukazuje na targetirani element ali i dalje ne može da se dodaje više od jedne funkcije na isti dogadjaj.

Jedini način da imamo više od jednog event handler-a na istom dogadjaju je pokazan na sledećem primeru:

“addEventListener” (W3C model)

Ovaj model je najprihvaćeniji način registrovanja dogadjaja i omogućava registrovanje više dogadjaja na jednom elementu. Metoda addEventListener podržava i bubbling i capturing redosled izvršavanja dogadjaja a to definiše kroz treći opcioni parametar. Ovaj parametar je boolean-ova vrednost koja definiše da li je redosled izvršenja capture ili ne. Stoga ako je ovaj parametar false znači da nije capturing već je bubbling, dok vrednost parametra true jasno definiše capturing. Defaultna vrednost je false, stoga ako se ne koristi ovaj treći opcioni parametar smatra se da je u pitanju bubbling redosled.

Primer br.1

Primer br.2

Da bi se izbeglo ponavljanje koda, preporuka je da se umesto anonimne funkcije koristi imenovana:

Dinamičko registrovanje osluškivača dogadjaja

Kada se koristeći JavaScript dinamički grade novi HTML elementi oni se ne “radjaju” sa prikačenim event listener-ima, stoga je potrebno dinamički dodati svakome novom elementu njegov event listener.

Primer

See the Pen Adding dinamic event handler by Web programiranje (@chos) on CodePen.

Još jedno legitimno rešenje za dodavanje event listener-a dinamički dodatim elementima je uz primenu event delagation što je objašnjeno u nastavku.

Event delegation

Definicija

U slučaju da postoji puno HTML elemenata na koje treba dodati “event listener” kao npr. u slučaju liste sa puno članova, može doći nepotrebne potrošnje resusrsa. Stoga je korisno primeniti “event delegation” tehniku koja se zasniva na tome da se definiše samo jedan “event listener” ali na parent elementu. Pored jednostavnosti ove tehnike i smenjenje potrošnje resursa, prednost je što su na ovaj način obuhvaćeni i budući dinamički kreirani elementi.

Princip na kojem radi ova tehnika se zasniva na osobini da ukoliko aktiviramo neki dogadjaj na elementu, zbog bubbling rasporeda aktiviranja dogadjaja, posle nekog vremena će taj dogadjaj biti “okinut” i na roditeljskom elementu. A da bi odredili koji je element bio okidač dogadjaja ova tehnika koristi “event.target” svojstvo.

NAPOMENA:
Obratiti pažnju da se ove tehnika oslanja na bubbling redosled izvršavanja dogadjaja, ali neki dogadjaji nemaju takav raspored (blur, focus, load, unload…) pa kod njih ne može da se primenjuje. Takodje treba izbegavati dogadjaj “mousemove” jer bi on okidao previše dogadjaja i trošio resurse.

Primena

Plain JS

Postupak počinje sa vezivanjem “event listener-a” za roditeljski element, nakon čega se po aktiviranom dogadjaju pretražuje da li je okidač bio naš tip elementa.

jQuery

Najjednostavnija primena delegacije dogadjaja je uz korišćenje jQuery metode on().

Ova metoda kao opcioni argument prihvata selektor koji definiše “child” elemente na kojima očekujemo da budu okidači dogadjaja.

Primer

Problem sa gomilanjem osluškivača dogodjaja

U radu sa dogadjajima može doći do “nehotičnog” nagomilavanja “event listener-a”. Ovaj problem se može najbolje objasniti kroz naredni primer:

See the Pen Event problem by Web programiranje (@chos) on CodePen.

Kada se u prethodnom primeru klikne na dugme nakon višekratnog čekiranja checkbox-a, pojavljuju se alert prozori jedan za drugim (isti broj puta koliko je čekiran checkbox). Problem se javlja zbog toga što se pri svakom čekiranju dodaje novi event listener na elemenat dugmeta.
Ovaj problem može da se reši na više načina, ali je u narednom primeru prikazan brzi “hack”:

See the Pen Event problem rešen by Web programiranje (@chos) on CodePen.

Brzo rešenje ovog problema sa kojim sprečavamo gomilanje “event listener-a” je dodavanje metode off(). Sa off() metodom ukidamo sve click listener-e, a zatim sa metodom on() dodajemo novi event listener.

Pogledajte slične članke...

Podelite:

Ostavite komentar