Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [JS] Nadpisywanie elementu
Forum PHP.pl > Forum > Po stronie przeglądarki
zurek
Witam

Mam taki kod:
[JAVASCRIPT] pobierz, plaintext
  1. for(i in this.board.fields) {
  2. var row = this.board.fields[i];
  3. //console.log(row);
  4.  
  5. for(var j=1; j<row.length; j++) {
  6. var fieldRow = row[j].getRow();
  7. var fieldNum = row[j].getNumber();
  8. var self = this;
  9.  
  10. row[j].canvasElement.click(function() {
  11. if(self.isMove) {
  12. self.move(fieldRow, fieldNum);
  13. self.isMove = false;
  14. }
  15. });
  16. }
  17. }
[JAVASCRIPT] pobierz, plaintext

Dokładniejsze wyjaśnienie co jest co zajęło by dużo czasu i wiele miejsca, więc na razie daję sam kod licząc na to, że obejdzie się bez tłumaczenia i będzie można z tego od razu wyciągnąć jakieś wnioski. Oczywiście, jeżeli zajedzie taka potrzeba, zaraz wszystko dokładnie wytłumaczę. W skrócie: Mam klasę Board(plansza), której zadaniem jest narysowanie ładnej planszy oraz parę operacji z nią związanych. Klasa ta posiada dwuwymiarową tablicę instancji klasy Field(pole). Teraz, każda instancja klasy Field posiada pole canvasElement. Kod, który przedstawiłem powyżej przechodzi po wszystkich polach tablicy pól i każdy element canvas wizualizujący pole łączy ze zdarzeniem click (korzystam z biblioteki wizualizacji Raphael). Problem polega na tym, że na samym końcu okazuje się, że którego pola bym nie kliknął, metoda move() zostaje wywołana zawsze dla tych samych argumentów - chodzi tutaj o zmienne fieldRow i fieldNum w 12. linijce. Są to wartości ostatniego pola w tablicy.

Wszystko działa w porządku do wywołania funkcji click. W ciele funkcji coś jest nie tak i tam staram się doszukać jakiegoś problemu.

Zapewne brzmi to bardzo nie składnie i chaotycznie, ale nie wiem jak w inny sposób mógłbym wytłumaczyć swój problem. Jestem mocno początkujący w JS, więc proszę o wyrozumiałość.
Z góry dzięki za każdą pomoc wink.gif
krh2
moim zdaniem powinienes wyciagnac zdarzenie z petli i polaczyc je z elementem DOM w canvaz (np klasa) i wywolaj w zdarzeniu funkcje. ja bym tak sprobowal. wink.gif
zurek
W canvas trudno jest chyba bezpośrednio odnosić się do konkretnych elementów DOM, w każdym razie ja nie mam pojęcia jak się do tego zabrać. Funkcję wywołuję przecież w zdarzeniu smile.gif
zegarek84
Więc w canvas czy w VML/SVG?? - wspomniałeś o bibliotece Raphael... wiem co jest jedno a co drugi choć nie korzystałem gdyż nie miałem potrzeby i co do canvas miałem pisać jedno, ale skoro całość działa a problem jest trywialny (cytując fragment pętli i wypowiedzi) to poniższy fragment pętli zamień z:
Cytat(zurek @ 13.09.2012, 23:12:25 ) *
[JAVASCRIPT] pobierz, plaintext
  1. // ...
  2. for(var j=1; j<row.length; j++) {
  3. var fieldRow = row[j].getRow();
  4. var fieldNum = row[j].getNumber();
  5. var self = this;
  6.  
  7. row[j].canvasElement.click(function() {
  8. if(self.isMove) {
  9. self.move(fieldRow, fieldNum);
  10. self.isMove = false;
  11. }
  12. });
  13. // ...
[JAVASCRIPT] pobierz, plaintext

...Problem polega na tym, że na samym końcu okazuje się, że którego pola bym nie kliknął, metoda move() zostaje wywołana zawsze dla tych samych argumentów - chodzi tutaj o zmienne fieldRow i fieldNum w 12. linijce.

na:
[JAVASCRIPT] pobierz, plaintext
  1. // ...
  2. for(var j=1; j<row.length; j++) {
  3. var fieldRow = row[j].getRow();
  4. var fieldNum = row[j].getNumber();
  5. var self = this;
  6.  
  7. row[j].canvasElement.click(
  8. (function(fieldRow, fieldNum){ return
  9. function() {
  10. if(self.isMove) {
  11. self.move(fieldRow, fieldNum);
  12. self.isMove = false;
  13. }
  14. }
  15. }(fieldRow, fieldNum)
  16. );
  17. // ...
[JAVASCRIPT] pobierz, plaintext

skoro jesteś początkujący z JS zachęcam do zapoznania się z tematem:
http://forum.php.pl/index.php?showtopic=204882&hl=
i z anonimowymi funkcjami typu (function(){})() oraz z dokładniejszym zasięgiem zmiennych - no przecież masz za każdym razem wartość z przebiegu pętli, czyli ostatnią wartość gdyż jest referencja do tej samej zmiennej...

ps. tylko kosmetyczna sprawa
self nie musisz przypisywać co każdy przebieg pętli, jest to ta sama wartość więc przypisz go przed pętlą (no oczywiście jakbyś chciał to można też this dać jako argument funkcji anonimowej, ale nie ma sensu, tylko tak wspominam jeśli kiedyś w kodzie obiekty by Ci się zmieniały pod daną zmienną a chciałbyś mieć w jakiejś funkcji stałą refrencję bez zmian), samą deklarację zmiennych "var fieldRow, fieldNum;" też mógłbyś dać przed pętlą - choć teraz przeglądarka dobrze to interpretuje, to wygląda jakby co każdy przebieg pętli te zmienne były deklarowane - a tak minimalistycznie to te 2 zmienne mógłbyś wyrzucić patrząc na konstrukcję funkcji anonimowej - mógłbyś napisać w stylu:
Kod
(function(fieldRow, fieldNum){ return
                function() {
            if(self.isMove) {
                self.move(fieldRow, fieldNum);
                self.isMove = false;
            }
        }
}(row[j].getRow(), row[j].getNumber())
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.