Javascript, problem z dodajanjem event listenerjev
 
Vini 28. jan 2008 16:01:05 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#1

Kot vse kaze, sem prejsnjo sredo slabo poslusal predavanje v Kiberpipi :)



Problem je sledec. Uporabljam nek javascript objekt, ki ob klicu neke metode doda event listener (ali attacha event, v primeru IE) nekemu elementu v DOM, v mojem primeru je to element BODY. Zelim, da se ob eventu klice metoda tega istega objekta.



To sem zelel narediti nekako takole:


document.body.addEventListener('click', this.hide, false);

Vse lepo in prav, metoda hide se ob kliku na BODY sicer izvede, vendar ne metoda na zeljeni instanci objekta, torej tisti, v kateri sem ta event listener dodal, ampak se ocitno kreira neka nova instanca, ali pa se metoda izvede nad instanco funkcije, ki doloca objekt, ali pa se kaj tretjega?



Vprasanje bi bilo, kako bi dosegel, da se ob eventu izvede metoda nad to isto instanco objekta?


všeč(0) ni všeč(0) spam(0)
 
Vini 28. jan 2008 16:01:32 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#2

Hmm, ocitno je nekaj tretjega :)



this je znotraj tiste metode tipa HTMLBodyElement, ceprav je to metoda nekega tretjega objekta. Stvar ima mogoce celo smisel, ce addEventListener doda BODY objektu metodo, ki se oglasa na doloceni event. Potem se seveda vse skupaj dogaja na instanci BODY elementa.



No, vprasanje tudi v tem primeru ostaja enako :)


všeč(0) ni všeč(0) spam(0)
 
fatg 28. jan 2008 19:01:46 Pridružen od:
28. jan 2008
94 objav
73 2 0
#3

Kontekst onclick eventa je dokument, ker se na njem zgodi event. V javascriptu je pač tako. :)



Lahko uporabiš closure, kjer ohraniš referenco:


document.body.addEventListener('click', function (obj){ return (function() { obj.hide() })}(this), false);

Če to razčleniš, dobiš tole:


document.body.addEventListener('click',
function (obj) {
return (
function() {
obj.hide()
})
}(this),
false);

V besedah: na event click ti pripneš anonimno funkcijo s parametrom obj, ki jo že takoj izvedeš in ji podaš this, ona pa vrne novo anonimno funkcijo, ki ohrani parameter obj iz konteksta, kjer je bila klicana. Closures ftw!



Še drug primer in obširnejša razlaga: http://www.jibbering.com/faq/faq_notes/closures.html#clSto



lp, fat


všeč(0) ni všeč(0) spam(0)
 
Vini 28. jan 2008 20:01:44 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#4

Hvala, fatg, za tole razlago. V sredo me je predavanje malo razrajcalo, pa sem sel malo raziskovat se tele javascript objekte. Saj vem, da je bilo prav o tem govora tudi tam, ampak sem nekako pozabil. Vmes sem sicer nasel neko podobno resitev, ki tudi deluje:


var obj = this;
document.body.addEventListener('click', function () { obj.hide() }, false);

Se ti zdi to slabse? Isto? Ena nova referenca na objekt obstaja v obeh primerih, kajne?


všeč(0) ni všeč(0) spam(0)
 
fatg 28. jan 2008 21:01:14 Pridružen od:
28. jan 2008
94 objav
73 2 0
#5

če se ne motim, si s tem ustvaril "globalno" referenco, imenovano obj. Zadevo si nastavil v vrhnjem kontekstu (torej v objektu window). Ko se zgodi event, ti klic na funkcijo kliče v bistvu window.obj.hide(). Če vprašaš mene, je ta rešitev problematična, ker piše direktno v window. Če pa že itak imaš neko referenco na obstoječi objekt, potem pa le uporabi to.


všeč(0) ni všeč(0) spam(0)
 
Vini 28. jan 2008 21:01:23 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#6

Ne ne, referenco sem ustvaril znotraj metode objekta. Ce prav razumem, so spremenljivke, ki so definirane z var znotraj funkcije, tej funkciji lokalne, ja?


všeč(0) ni všeč(0) spam(0)
 
fatg 28. jan 2008 21:01:27 Pridružen od:
28. jan 2008
94 objav
73 2 0
#7

aja, znotraj si! potem si zgleda naredil closure in tista notranja funkcija drži referenco na obj. Na nek način enako, kot moja rešitev, samo za eno stopnjo manj komplicirano. Ne vem pa, če je ta način požegnan od profijev. Zgleda že v redu :).



lp


všeč(0) ni všeč(0) spam(0)
 
Vini 28. jan 2008 21:01:32 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#8

Resitev sem nasel tukaj, na Mozilli verjetno je kaksen profi, torej so verjetno zadevo tudi pozegnali :)



Je pa res, da ne govorijo prav tocno o tem problemu, ki sem ga imel jaz. Tudi meni se zdi tvoja resitev bolj profi, sem jo uporabil :)


všeč(0) ni všeč(0) spam(0)
 
Vini 28. jan 2008 21:01:40 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#9

Ha, fatg, en problem. Se ti kaj sanja, kako bi pa ta event listener removal? Metodi removeEventListener moram ravno tako podati referenco na neko funkcijo, kar pa tukaj tezko naredim, ce sem uporabil anonimno funkcijo, ni res?


všeč(0) ni všeč(0) spam(0)
 
Vini 28. jan 2008 22:01:37 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#10

Nasel resitev, se mi zdi kar elegantna in deluje:


function nekobjekt() {
}

nekobjekt.prototype.metoda1() {
this.clickfunc = function (obj) { return function () { obj.metoda2() } }(this);
document.body.addEventListener('click', this.clickfunc, false);
}

nekobjekt.prototype.metoda2() {
document.body.removeEventListener('click', this.clickfunc, false);
}

Imam prav?


všeč(0) ni všeč(0) spam(0)
 
 

🔒 Za odgovor na to temo se moraš prijaviti.

Prijavi se