[js] Wywolanie eventu z parametrem

0

Witam.
Mam taka sobie petelke, ktora przypisuje wartosc onclick, dla kazdego z 10 wierszy tabeli.

function Przypisz() {
var rows = document.getElementById('testTable').rows
for (var i = 0; i < 10; i++) {
rows[i].onclick = function() {
alert(i);
};
}
}

W przypisanej funkcji chce przekazac parametr z glownej funkcji. Niestety za kazdym razem obojetnie w ktory wiersz nie klikne w alercie przekazywana jest wartosc 10;

Dlaczego? W jaki sposob naprawic to tak aby alerty pokazywaly sie z poprawna wartoscia?

*alert i cala petla to juz postac po wielkim uproszczeniu kodu, by skupic sie na danym problemie.

0
function Przypisz() {
                var rows = document.getElementById('testTable').rows
                for (var i = 0; i < 10; i++) {
                        rows[i].onclick = function() {
                                var x=i;
                                alert(x);
                        };
                }
        }
0

Deti, a coz niby mialoby to jedno przypisanie zmienic?
Dalej wynik klikniecia na kazdy wiersz to 10;

0

Deti, a coz niby mialoby to jedno przypisanie zmienic?
Dalej wynik klikniecia na kazdy wiersz to 10;

Sorki, pomyliłem się. Dawno nie grzebałem w JS.

Trzeba zastosować Closure:

function Przypisz() {
                var rows = document.getElementById('testTable').rows
                for (var i = 0; i < 10; i++) {
                        rows[i].onclick = function(x) {
                                return function () {
                                  alert(x);
                                };
                        };
                }
        }
0

Deti - brakuje wywołania zewnętrznej funkcji :-)

function Przypisz() {
                var rows = document.getElementById('testTable').rows
                for (var i = 0; i < 10; i++) {
                        rows[i].onclick = (function(x) {
                                return function () {
                                  alert(x);
                                };
                        }(i));
                }
        }
0

Nav, dzieki, ten kod dziala.
Czy jeszcze ktos by mi mogl powiedziec dlaczego moj oryginalny kod zwraca 10? Bo tego akurat nie rozumiem.

Tworze var i w petli for... tak wiec i powinno miec lokalny zakres. I faktycznie po wyjsciu z metody 'i' juz nie istnieje... ale dlaczego istnieje ono przy wywolaniu funkcji inline? Zawsze myslalem, ze do funkcji inline takie zmienne sa kopiowane, a nie uzywane ich referencje?

Wiec jak to wkoncu jest? Bo juz nie wiem czy jesli nie uzywam petli to moge po prostu odwolywac sie bezposrednio do zmiennej z funkcji glownej, a dopiero przy petlach przypisywac parametryzowana funkcje zwracajaca funkcje?

0

to nie jest właściwie referencja. W swoim kodzie związałeś funkcję anonimową z kontekstem (wnętrzem funkcji Przypisz). Wtedy ten onclick wywołuje się, jakby dalej był w ciele Przypisz. Czyli po wyjściu z niej, i dalej istnieje.

Rozwiązaniem jest zmiana kontektstu (a właściwie jego rozszerzenie, ja tam w dalszym ciągu chyba jeszcze nie opanowałem w pełni tego, co się w javascripcie dzieje), jaką zaprezentowali Deti i nav.

0

No wlasnie, tez to tak rozumiem. Acz po wyjsciu z Przypisz i istnieje juz tylko dla tej anonimowej funkcji, acz z innych miejsc jest niedostepne.

Interesuje mnie to zwlaszcza w przypadku klas. Niestety nie zawsze moge w metodzie klasy uzywac referencji this, gdyz zdarza sie iz metoda wywolywana jest asynchronicznie (np pobieranie JSON'a przez jQuery), wowczas anonima funkcja ma zupelnie inny kontekst i this wskazuje na cos zupelnie innego. Rozwiazalem to poprzez przypisanie var ctrl = this - gdzie jak okazuje sie moge uzywac referencji na swoja klase.

function MojaKlasa(textBoxId, url) {
this.textboxId = textBoxId,
this.url = url;
this.data = null

var ctrl = this;
this.Update = function() {
	$.getJSON(url, function(data) {
		ctrl.data = data;
	}
}

}

Poki co dziala, dzieki powyzszym postom chyba w miare zrozumialem na jakiej zasadzie. Jesli jednak moja inwencja tworcza jest bledna i takie rzeczy powinno sie inaczej robic to bede wdzieczny za naprowadzenie mnie :)

0

Dokładnie tak się robi w takich sytuacjach ;-) Ewentualnie zostaje jeszcze "magiczna" funkcja bind obecna np w prototype.js, która zmienia kontekst wywołania funkcji (tworząc tak naprawdę dodatkową anonimową funkcję).

http://ejohn.org/apps/learn/ - fajna prezentacja na temat rzeczy wykorzystanych w funkcji bind. Polecam przycisk run, którym można odpalić kod. Na niektórych slajdach trzeba uzupełnić fragment kodu - do edycji wchodzi się przez dwuklik na kodzie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1