Jeena Paradies: onclick verhalten und foo has no properties

Hallo,

  
<body onload="addBehaviour();">  
  <table>  
   <tr id="g42">  
    <td>  
     <button>+</button>  
     <input class="tor" type="text" name="g[42][foo]" value="3" readonly="readonly" size="2" />  
     <button>-</button>  
    </td>  
    <td>foo</td>  
    <td>  
     <button>+</button>  
     <input class="tor" type="text" name="g[42][bar]" value="2" readonly="readonly" size="2" />  
     <button>-</button>  
    </td>  
    <td>bar</td>  
   </tr>  
  </table>  
</body>  

01 function addBehaviour() {  
02  
03    var table = document.getElementsByTagName('table')[0];  
04    var trs = table.getElementsByTagName('tr');  
05  
06    var i=0;  
07    for(i; i <= trs.length; i++) {  
08  
09        var tr = trs[i];  
10        var buttons = tr.getElementsByTagName('button');  
11        var id = tr.getAttribute('id').slice(1);  
12  
13        buttons[0].onclick = sendInfo.addGoal(id, 0);  
14    }  
15 }

In Zeile 10 des JS gibt der Firefox mir immer diese Fehlermeldung aus:

Error: tr has no properties
  Source File: http://localhost/Webs/xml/GamesClient.js
  Line: 10

Außerdem wird die funktion sendInfo.addGoal() in Zeile 13 schon beim onLoad ausgeführt und nicht erst beim klick auf den Button, warum passiert das?

Grüße
Jeena Paradies

--
Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
  1. 13        buttons[0].onclick = sendInfo.addGoal(id, 0);

    hier rufst du die Funktion addGoal() auf und weist dem Handler den Rückgabewert zu - ziemlich sinnlos vermutlich (es denn die Funktion liefert als Rückgabewert eine Funktionsreferenz).

    Du willst:

    buttons[0].onclick = function()
    {
    sendInfo.addGoal(id, 0);
    };

    wobei das id ein Problem ist, da es jeden Schleifendruchgang neu erzeugt wird und in JS lokale Variabeln nicht wirklich lokal sind (nur innerhalb der Funktion) ist in jedem Handler am Ende der letzte Wert der id.

    Du kannst dies umgehen, entweder wenn du die Funktionsreferenz mit new Function erzeugst oder wenn du dem objekt den Wert als Attribut mit gibst:

    buttons[0].parentId = id;
    buttons[0].onclick = function()
    {
    sendInfo.addGoal(this.parentId, 0);
    };

    Struppi.

    1. Hallo,

      hier rufst du die Funktion addGoal() auf und weist dem Handler den Rückgabewert zu - ziemlich sinnlos vermutlich (es denn die Funktion liefert als Rückgabewert eine Funktionsreferenz).

      Aahh hm. Ok, ich sehe schon das mit den event Handlern habe ich noch nicht wirklich kappiert.

      Du kannst dies umgehen, entweder wenn du die Funktionsreferenz mit new Function erzeugst oder wenn du dem objekt den Wert als Attribut mit gibst:
      buttons[0].parentId = id;
      buttons[0].onclick = function() { sendInfo.addGoal(this.parentId, 0); };

      das blöde ist, dass ich ziemlich viele Buttons habe, muss ich dann jedem ein buttons[x].parentID = id; mitgeben, oder kann man das irgendwie sinnvoller gestalten?

      Grüße
      Jeena Paradies

      --
      Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
      1. Du kannst dies umgehen, entweder wenn du die Funktionsreferenz mit new Function erzeugst oder wenn du dem objekt den Wert als Attribut mit gibst:
        buttons[0].parentId = id;
        buttons[0].onclick = function() { sendInfo.addGoal(this.parentId, 0); };
        das blöde ist, dass ich ziemlich viele Buttons habe, muss ich dann jedem ein buttons[x].parentID = id; mitgeben, oder kann man das irgendwie sinnvoller gestalten?

        Ja musst du, wo ist ds Problem?

        Das ist eine einzige zusätzliche Zeile in der Schleife.

        Struppi.

        1. Hallo,

          Das ist eine einzige zusätzliche Zeile in der Schleife.

          Nein das ist für jeden Button eine zusätzliche Zeile in der Schleife und ich habe ungefähr 15 solcher Buttons, eventuell werden es noch mehr. Die ID ist aber bei jedem immer die gleiche, deshalb kommt mir das sehr redundant vor. Jeder Button soll eine Andere Funktion aufrufen mit anderen Parametern, aber immer auch mit der gleichen ID, wobei ich jetzt auch überlege ob ich nicht aus dem ganzen ding ein einzelnes objekt machen sollte und da einfach nur einmal die ID übergeben sollte und ansonsten nur die Funktionen.

          Grüße
          Jeena Paradies

          --
          Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
          1. Das ist eine einzige zusätzliche Zeile in der Schleife.
            Nein das ist für jeden Button eine zusätzliche Zeile in der Schleife und ich habe ungefähr 15 solcher Buttons, eventuell werden es noch mehr. Die ID ist aber bei jedem immer die gleiche, deshalb kommt mir das sehr redundant vor. Jeder Button soll eine Andere Funktion aufrufen mit anderen Parametern, aber immer auch mit der gleichen ID, wobei ich jetzt auch überlege ob ich nicht aus dem ganzen ding ein einzelnes objekt machen sollte und da einfach nur einmal die ID übergeben sollte und ansonsten nur die Funktionen.

            Wenn ich deinen Code anschaue:

            07    for(i; i <= trs.length; i++) {
            08
            09        var tr = trs[i];
            10        var buttons = tr.getElementsByTagName('button');
            11        var id = tr.getAttribute('id').slice(1);
            12
            13        buttons[0].onclick = sendInfo.addGoal(id, 0);
            14    }

            Dann ist es für mich eine einzige Zeile, für alle Buttons.

            for(var i = 0; i < trs.length; i++)
            {
            var tr = trs[i];
            var buttons = tr.getElementsByTagName('button');
            buttons[0].parentId = tr.id;
            buttons[0].onclick = function() { sendInfo.addGoal(this.parentId, 0); };
            }

            Oder was fehlt da jetzt noch?

            Struppi.

            1. Hallo,

              07    for(i; i <= trs.length; i++) {
              08
              09        var tr = trs[i];
              10        var buttons = tr.getElementsByTagName('button');
              11        var id = tr.getAttribute('id').slice(1);
              12
              13        buttons[0].onclick = sendInfo.addGoal(id, 0);
              14    }
              Dann ist es für mich eine einzige Zeile, für alle Buttons.
              Oder was fehlt da jetzt noch?

              Ja das war ein Vereinfachtes Beispiel. Im Beispiel greife ich ja -- so weit ich das verstehe -- nur auf den ersten Button im tr zu. In einem tr gibt es aber -- über verschiedene td verteilt -- bis zu 15 Buttons, die ich dann einzeln mit:

              13        buttons[0].onclick = sendInfo.addGoal(id, 0);

              14        buttons[1].onclick = sendInfo.delGoal(id, 0);
                 15        buttons[2].onclick = sendInfo.addGoal(id, 1);
                 16        buttons[3].onclick = sendInfo.delGoal(id, 1);
                 17        [und so weiter bis buttons[14] oder so]

              Ich habe mir das aber jetzt anders überlegt und mit Daniels Hilfe aus dem #selfhtml Chat so etwas hinbekommen was jetzt auch funktioniert, und ich verstehe jetzt endlich was du damit meinst wenn du sagst das lokale Variabeln nicht ganz lokal sind oder so ;-)

              function addBehaviour() {  
                
                  var table = document.getElementsByTagName('table')[0];  
                  var trs = table.getElementsByTagName('tr');  
                
                  for(var i=0; i < trs.length; i++) {  
                
                      var tr = trs[i];  
                      var id = tr.getAttribute('id').slice(1);  
                      var buttons = tr.getElementsByTagName('button');  
                
                      var local = function()  {  
                        var sendInfo = new Action(id);  
                        buttons[0].onclick = function() { sendInfo.addGoal('heim'); };  
                        buttons[1].onclick = function() { sendInfo.delGoal('heim'); };  
                        buttons[2].onclick = function() { sendInfo.addGoal('gast'); };  
                        buttons[3].onclick = function() { sendInfo.delGoal('gast'); };  
                        // und so weiter  
                     };  
                     local();  
                  }  
              }
              

              Grüße
              Jeena Paradies

              --
              Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
              1. Ja das war ein Vereinfachtes Beispiel. Im Beispiel greife ich ja -- so weit ich das verstehe -- nur auf den ersten Button im tr zu. In einem tr gibt es aber -- über verschiedene td verteilt -- bis zu 15 Buttons, die ich dann einzeln mit:

                13        buttons[0].onclick = sendInfo.addGoal(id, 0);
                   14        buttons[1].onclick = sendInfo.delGoal(id, 0);
                   15        buttons[2].onclick = sendInfo.addGoal(id, 1);
                   16        buttons[3].onclick = sendInfo.delGoal(id, 1);
                   17        [und so weiter bis buttons[14] oder so]

                Nein, das ist immer noch falsch, du rufst hier eine Funktion auf und weist den Rückgabewert immer noch dem Eventhandler zu.

                Aber letztlich ist die Frage wozu du die ID überhaupt brauchst?

                Was soll eigentlich dieser slice() bei der ID?

                slice ist eine Funktion für ein Array und eigentlich sind Strings keine Arrays.
                auch getAttribute ist in so einem Falle nicht zu empfehlen, da der IE damit immer mal wieder Schwierigkeiten hat und du ohne Problem auch direkt die id erhälst.

                [code lang=javascript]function addBehaviour() {

                var table = document.getElementsByTagName('table')[0];
                    var trs = table.getElementsByTagName('tr');

                for(var i=0; i < trs.length; i++) {

                var tr = trs[i];
                        var id = tr.getAttribute('id').slice(1);
                        var buttons = tr.getElementsByTagName('button');

                var local = function()  {
                          var sendInfo = new Action(id);
                          buttons[0].onclick = function() { sendInfo.addGoal('heim'); };
                          buttons[1].onclick = function() { sendInfo.delGoal('heim'); };
                          buttons[2].onclick = function() { sendInfo.addGoal('gast'); };
                          buttons[3].onclick = function() { sendInfo.delGoal('gast'); };
                          // und so weiter
                       };
                       local();

                so ganz versteh ich nicht den Sinn, warum du hier eine anonyme Funktion erzeugst und dann unmittelbar aufrufst.

                Letztlich wäre es hier interessant, was sendInfo und Action ist, wozu du die id brauchst usw.

                Struppi.

                1. Hallo,

                  Nein, das ist immer noch falsch, du rufst hier eine Funktion auf und weist den Rückgabewert immer noch dem Eventhandler zu.

                  Jo habe ich dann auch nach dem Absenden gemerkt.

                  Aber letztlich ist die Frage wozu du die ID überhaupt brauchst?

                  Um es an PHP zu übergeben, damit das wiederum mit hilfe des Funktionsnamens, der spielID und des Teams, welches das Goal gemacht hat einen Eintrag in der Datenbank macht und bei Erfolg oder Misserfolg eine Meldung zurückgibt.

                  Was soll eigentlich dieser slice() bei der ID?

                  das einzelne tr welches die buttons enthält hat die id g12 zum beispiel wobei das 12 die spielID ist. Ich dachte dass ich das mit dem g so machen muss, da ids in XHTML nicht mit einer Zahl anfangen dürfen.

                  slice ist eine Funktion für ein Array und eigentlich sind Strings keine Arrays.

                  Ich habe das konkret so aus diesem SELFHTML Beispiel übernommen: http://de.selfhtml.org/javascript/objekte/string.htm#slice

                  auch getAttribute ist in so einem Falle nicht zu empfehlen, da der IE damit immer mal wieder Schwierigkeiten hat und du ohne Problem auch direkt die id erhälst.

                  Das ist nicht so schlimm, den Browser kann ich mir aussuchen über welchen das ding laufen wird, bisher wird Opera benutzt aber das ist egal welcher, es wird nur durch einen einzigen menschen bedient.

                  so ganz versteh ich nicht den Sinn, warum du hier eine anonyme Funktion erzeugst und dann unmittelbar aufrufst.

                  Damit die variable lokal bleibt und nicht überschrieben wird.

                  Letztlich wäre es hier interessant, was sendInfo und Action ist, wozu du die id brauchst usw.

                  Ja kann ich schon gut verstehen, deshalb habe ich das Script so weit ich es bisher habe mal hier hochgeladen: http://phpfi.com/93465

                  Dabei ist dort in Zeile 29 auch wieder so eine unschöne Sache die ich unbedingt vermeiden möchte, denn die funktionalität dieser anonymen Funktion bräuchte ich eigentlich öfter später auch für delGoal() und andere Funktionen, die noch folgen werden. Wenn ich es aber mit einem Konkreten Namen mache dann kann ich es irgendwie nicht so als callback Funktion übergeben, bzw. weiß ich nicht wie ich das machen soll.

                  Grüße
                  Jeena Paradies

                  --
                  Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
                  1. Was soll eigentlich dieser slice() bei der ID?
                    das einzelne tr welches die buttons enthält hat die id g12 zum beispiel wobei das 12 die spielID ist. Ich dachte dass ich das mit dem g so machen muss, da ids in XHTML nicht mit einer Zahl anfangen dürfen.

                    slice ist eine Funktion für ein Array und eigentlich sind Strings keine Arrays.
                    Ich habe das konkret so aus diesem SELFHTML Beispiel übernommen: http://de.selfhtml.org/javascript/objekte/string.htm#slice

                    Stimmt, ich habe bisher immer substring() verwendet, aber slice() sieht einfacher aus.

                    so ganz versteh ich nicht den Sinn, warum du hier eine anonyme Funktion erzeugst und dann unmittelbar aufrufst.
                    Damit die variable lokal bleibt und nicht überschrieben wird.

                    Letztlich wäre es hier interessant, was sendInfo und Action ist, wozu du die id brauchst usw.
                    Ja kann ich schon gut verstehen, deshalb habe ich das Script so weit ich es bisher habe mal hier hochgeladen: http://phpfi.com/93465

                    Dabei ist dort in Zeile 29 auch wieder so eine unschöne Sache die ich unbedingt vermeiden möchte, denn die funktionalität dieser anonymen Funktion bräuchte ich eigentlich öfter später auch für delGoal() und andere Funktionen, die noch folgen werden. Wenn ich es aber mit einem Konkreten Namen mache dann kann ich es irgendwie nicht so als callback Funktion übergeben, bzw. weiß ich nicht wie ich das machen soll.

                    Das gleiche Problem.

                    Ich würde dem Objekt Action als Eigenschaft die ID die du ja schon beim 26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    53
                    54
                    55
                    56
                    57
                    58
                    59
                    60
                    61
                    62
                    63
                    64
                    65
                    66
                    67
                    68
                    69
                    70
                    71
                    72
                    73
                    74
                    75
                    76
                    77
                    78
                    79
                    80
                    81
                    82
                    83
                    84
                    85
                    86
                    87
                    88
                    89
                    90
                    91

                    function GameClient(url, callback) {

                    var req = new XMLHttpRequest();

                    req.onreadystatechange = function() {
                            if (req.readyState == 4) {
                                if ( req.status < 400 ) {
                                    callback(1, req.responseText);
                                }
                                else {
                                    callback(-1, "Es gab ein Problem beim abrufen der Daten: " + req.status+ "/ " + req.statusText);
                                }
                            }
                        }

                    req.open("GET", 'http://localhost/Webs/xml/GamesServer.php?function='+url, true);
                        req.send(null);

                    return;
                    }

                    function Action(spielID) {

                    this.id = spielID;

                    this.addGoal = function (team) {

                    var getResponse = function(code, response) {
                                if(code == 1) {
                                    this.responseAction(response);
                                }
                                else this.responseAction.wrong(response);
                            }

                    var send = new GameClient('addGoal&spielID='+ this.spielID

                    • '&team='+team, getResponse);
                          }
                      ....

                    parent ist überflüssig, da in this.goal() this gleich dem Action objekt ist.

                    Ansonsten bist du natürlich sehr verstrickt in die "hohe Kunst der JS OOP" Programmierung. Und stehst damit auch zwischen vielen Fallstricken. Welche Funktion letztlich Action in addBehaviour() hat ist nicht ganz klar. Und ich vermute dass du auch noch die Referenz auf den Button brauchst um z.b. den Wert bei dem onclick event zu ermitteln .

                    Struppi.

                    1. Ich würde dem Objekt Action als Eigenschaft die ID die du ja schon beim 26
                      27
                      28
                      29
                      30
                      31
                      32
                      33
                      34
                      35
                      36
                      37
                      38
                      39
                      40
                      41
                      42
                      43
                      44
                      45
                      46
                      47
                      48
                      49
                      50
                      51
                      52
                      53
                      54
                      55
                      56
                      57
                      58
                      59
                      60
                      61
                      62
                      63
                      64
                      65
                      66
                      67
                      68
                      69
                      70
                      71
                      72
                      73
                      74
                      75
                      76
                      77
                      78
                      79
                      80
                      81
                      82
                      83
                      84
                      85
                      86
                      87
                      88
                      89
                      90
                      91

                      Hmm, paste & copy ohne genau hinzugucken was wirklich rauskommt.

                    2. Hallo,

                      Das gleiche Problem.

                      Jup.

                      function Action(spielID) {
                          this.id = spielID;
                          this.addGoal = function (team) {
                              var getResponse = function(code, response) {
                                  if(code == 1) {
                                      this.responseAction(response);
                                  }
                                  else this.responseAction.wrong(response);
                              }
                      var send = new GameClient('addGoal&spielID='+ this.spielID

                      • '&team='+team, getResponse);
                            }
                        ....
                        parent ist überflüssig, da in this.goal() this gleich dem Action objekt ist.

                      Aber ich bin doch wiederum innerhalb von dieser anonymen Funktion und da (dachte ich zumindest) ist this die addGoal() Mehtode?

                      Ansonsten bist du natürlich sehr verstrickt in die "hohe Kunst der JS OOP" Programmierung.

                      Ja ich weiß, da ich das aber lernen möchte muss ich da wohl durch. Bisher habe ich schon viel erfahren, nur leider habe ich online noch nichts gefunden wo ich über solche Sachen nachlesen kann und versuche mich druch probieren und fragen irgendwie fortzubewegen. Vielleicht hast du einen Lesetipp?

                      Und stehst damit auch zwischen vielen Fallstricken. Welche Funktion letztlich Action in addBehaviour() hat ist nicht ganz klar.

                      Naja eigentlich schon, es ist eine Funktionalität die bei onclick auf einen Button zur Verfügung gestellt wird. Wobei es halt ungefähr bis zu 300 mal 15 = 4500 Buttons auf einer Seite geben kann und die Seite den ganzen Tag offen gehalten wird und somit auch die Daten. Deshalb ist das ganze wohl am sinvollsten mit oop zu lösen, oder?

                      Und ich vermute dass du auch noch die Referenz auf den Button brauchst um z.b. den Wert bei dem onclick event zu ermitteln .

                      Nein das versuche ich ja damit zu umgehen, dass ich die spielID übergebe und eine konkrete funktion mit dem Button in verbindung bringe. Es gibt nämlich auch noch in einer reihe (tr) mehrere Buttons mit geichen werten die aber unterschiedliche funktionen ausführen. Ich mache mal hier einen screenshot rein, damit man sich das besser vorstellen kann:

                      Hier sieht man sechs Spiele und es kommen noch ein paar Buttons dazu. Jeder Button muss eine bestimmte Funkton auslösen, die die Information über XMLHttpRequest() an PHP weiterleitet, daten empfeängt und das Ergebnis visualisiert.

                      Grüße
                      Jeena Paradies

                      --
                      Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
                      1. ....
                        parent ist überflüssig, da in this.goal() this gleich dem Action objekt ist.
                        Aber ich bin doch wiederum innerhalb von dieser anonymen Funktion und da (dachte ich zumindest) ist this die addGoal() Mehtode?

                        Ich hab mir das ganez mal nachgebaut.
                        Du brauchst oparent, weil du innerhalb der closure Funktion eine callbackfunktion aufrufst.

                        So wäre es ausreichend:
                        this.addGoal = function (team) {
                                var parent = this;
                                var getResponse = function(code, response) {
                                    if(code == 1) {
                                        parent.responseAction(response);
                                    }
                                    else parent.responseAction.wrong(response);
                                }
                        var send = new GameClient('addGoal&spielID='+ this.id + '&team='+team, getResponse);
                        }

                        Aber das ist natürlich sehr tricky. Ein closure, das einem Objekt als Callbackfunktion übergeben wird, um innerhalb des Objektes Funktionen auszuführen. Das ist notwendig, da eine Funktionsreferenz ihr Objekt verliert.

                        angenommen es gäbe:

                        Action.prototype.callback = function() {...}

                        und du übergibst hier:
                        function GameClient(url, callback) {

                        ..
                            callback(1, 'test text');
                        }
                        this.callback
                        würde zwar die Funktion aufgerufen, aber in der Funktion wäre this = window.

                        Ansonsten bist du natürlich sehr verstrickt in die "hohe Kunst der JS OOP" Programmierung.
                        Ja ich weiß, da ich das aber lernen möchte muss ich da wohl durch. Bisher habe ich schon viel erfahren, nur leider habe ich online noch nichts gefunden wo ich über solche Sachen nachlesen kann und versuche mich druch probieren und fragen irgendwie fortzubewegen. Vielleicht hast du einen Lesetipp?

                        Es gibt ein paar Seiten, aber immer nur irgendwelche Tipps. also z.B. über closure oder die speziellen Vererbungstechniken von JS.

                        Ich kram mal....

                        http://jibbering.com/faq/faq_notes/closures.html
                        http://crockford.com/javascript/inheritance.html (und alles was dort an Seiten noch existiert)

                        Und stehst damit auch zwischen vielen Fallstricken. Welche Funktion letztlich Action in addBehaviour() hat ist nicht ganz klar.
                        Naja eigentlich schon, es ist eine Funktionalität die bei onclick auf einen Button zur Verfügung gestellt wird. Wobei es halt ungefähr bis zu 300 mal 15 = 4500 Buttons auf einer Seite geben kann und die Seite den ganzen Tag offen gehalten wird und somit auch die Daten. Deshalb ist das ganze wohl am sinvollsten mit oop zu lösen, oder?

                        Jein, der Button stößt eine Funktion an. Wozu gehört der Button, also zu welchem abstrakten Objekt in deiner Anwendung?
                        Ist es nur ein Button, der einer globalen Anwendung im Falle onclick Daten übergibt und etwas anstößt oder soll er noch etwas anderes machen?

                        Und ich vermute dass du auch noch die Referenz auf den Button brauchst um z.b. den Wert bei dem onclick event zu ermitteln .
                        Nein das versuche ich ja damit zu umgehen, dass ich die spielID übergebe und eine konkrete funktion mit dem Button in verbindung bringe. Es gibt nämlich auch noch in einer reihe (tr) mehrere Buttons mit geichen werten die aber unterschiedliche funktionen ausführen. Ich mache mal hier einen screenshot rein, damit man sich das besser vorstellen kann:

                        ...

                        Naja, dann ist z.b. eine Reihe ein Objekt mit fünf (bzw. x ) verschiedenen Buttons, die jeweils unterschiedliche Dinge in diesem Objekt anstossen, aber evtl. auch miteinander in Verbindung stehen.

                        Sieht auf jeden Fall interessant aus.

                        Struppi.

                        1. Hallo,

                          So wäre es ausreichend:
                                  var parent = this;

                          ok

                          Aber das ist natürlich sehr tricky.
                          angenommen es gäbe:
                          Action.prototype.callback = function() {...}
                          function GameClient(url, callback) { callback(1, 'test text'); }
                          this.callback
                          würde zwar die Funktion aufgerufen, aber in der Funktion wäre this = window.

                          Das muss ich dann verhindern indem ich aufpasse das so etwas nie zustande kommen kann.

                          http://jibbering.com/faq/faq_notes/closures.html
                          http://crockford.com/javascript/inheritance.html (und alles was dort an Seiten noch existiert)

                          Ah, das sieht doch schon mal viel besser aus als das was ich über die Suchmaschine gefunen habe, werde ich mir morgen mal genauer angucken.

                          Jein, der Button stößt eine Funktion an. Wozu gehört der Button, also zu welchem abstrakten Objekt in deiner Anwendung?

                          Er gehört zu den anderen Buttons im gleichen tr, die ein ganzes Spiel mit einer eindeutigen spielID representieren.

                          Ist es nur ein Button, der einer globalen Anwendung im Falle onclick Daten übergibt und etwas anstößt oder soll er noch etwas anderes machen?

                          Hm eigentlich muss er nichts weiter machen, wenn er bei onclick seine Daten übergeben hat, dann hat er seine arbeit getan und kann auf den nächsten klick warten, alles andere erledigen dann die funktionen und eventhandler, die gefeuert werden wenn der button angeklickt wurde.

                          Naja, dann ist z.b. eine Reihe ein Objekt mit fünf (bzw. x ) verschiedenen Buttons, die jeweils unterschiedliche Dinge in diesem Objekt anstossen, aber evtl. auch miteinander in Verbindung stehen.

                          Ja genau so habe ich mir das vorgestellt. Das ganze Programm wird dann aber von früh bis Abends durchlaufen, im Idealfall ohne dass man die Seite neu laden muss. Ich muss dann glaube ich penibel schauen, dass ich nicht mehr benötigte objekte auch aus dem Speicher lösche, denn ich glaube dass das schon eine ganz schöne Belastung für den Browser ist. Andererseits habe ich mit so etwas gar keine Erfahrung, es könnte auch sein, dass er spielend damit umgehen kann.

                          Sieht auf jeden Fall interessant aus.

                          Ja, ist es auch, ich lerne vor allem wirklich sehr viel über Programmierung allgemein und OOP in JavaScript im konkreten was ich auch bei anderen Sachen sehr gut gebrauchen kann.

                          Grüße
                          Jeena Paradies

                          --
                          Open- vs. Closed Source Software - Verdienstmöglichkeiten | Jlog | Gourmetica Mentiri
                          1. Jein, der Button stößt eine Funktion an. Wozu gehört der Button, also zu welchem abstrakten Objekt in deiner Anwendung?
                            Er gehört zu den anderen Buttons im gleichen tr, die ein ganzes Spiel mit einer eindeutigen spielID representieren.

                            Ist es nur ein Button, der einer globalen Anwendung im Falle onclick Daten übergibt und etwas anstößt oder soll er noch etwas anderes machen?
                            Hm eigentlich muss er nichts weiter machen, wenn er bei onclick seine Daten übergeben hat, dann hat er seine arbeit getan und kann auf den nächsten klick warten, alles andere erledigen dann die funktionen und eventhandler, die gefeuert werden wenn der button angeklickt wurde.

                            Das seh ich anders, du musst ja z.b. auch das Formular dann u.U. updaten.

                            Naja, dann ist z.b. eine Reihe ein Objekt mit fünf (bzw. x ) verschiedenen Buttons, die jeweils unterschiedliche Dinge in diesem Objekt anstossen, aber evtl. auch miteinander in Verbindung stehen.
                            Ja genau so habe ich mir das vorgestellt. Das ganze Programm wird dann aber von früh bis Abends durchlaufen, im Idealfall ohne dass man die Seite neu laden muss. Ich muss dann glaube ich penibel schauen, dass ich nicht mehr benötigte objekte auch aus dem Speicher lösche, denn ich glaube dass das schon eine ganz schöne Belastung für den Browser ist. Andererseits habe ich mit so etwas gar keine Erfahrung, es könnte auch sein, dass er spielend damit umgehen kann.

                            Vergiß den Gedanken, du programmierst nicht in C wo du dir um Speicher Gedanken machen müßtest und bei der Größenordnung, was du da machst, ist das kein Problem. Zumal du ja nicht immer ein neues Objekt erzeugen musst, du kannst diese auch dauerhaft im Speicher behalten, das ist keine Problem.

                            Du solltest, so wie ich dich verstehe, eher ein Objekt Global definieren. Mit den verschiedenen Unterobjekten und nicht quasi auf Aufruf ein neues Objekt erzeugen, das ist funktionale Programmierung.

                            Struppi.

  2. Hi,

    06    var i=0;
    07    for(i; i <= trs.length; i++)

    das ist zumindest eigenwillig. Ich ziehe sowas normalerweise zusammen:

    07    for (var i=0; i <= trs.length; i++)

    In Zeile 10 des JS gibt der Firefox mir immer diese Fehlermeldung aus:
      Error: tr has no properties
      Source File: http://localhost/Webs/xml/GamesClient.js
      Line: 10

    Da wird er wohl Recht haben. Denn durch den <= Operator deiner for-Schleife machst du hier eine Runde zuviel und greifst im letzten Schleifendurchlauf bei

    09        var tr = trs[i];

    ins Leere.

    Außerdem wird die funktion sendInfo.addGoal() in Zeile 13 schon beim onLoad ausgeführt und nicht erst beim klick auf den Button, warum passiert das?

    Siehe Struppis Hinweis.
    So long,

    Martin

    --
    Was ist eigentlich aus deinem schlimmen Durchfall geworden?
    Mein Arzt hat mir Valium verschrieben.
    Und das hilft?
    Naja, ich mach mir immer noch in die Hose. Aber inzwischen ist es mir egal.
  3. Hallo,

    06    var i=0;
    07    for(i; i <= trs.length; i++) {

    ^? Warum nicht nur kleiner als?

    08
    09        var tr = trs[i];

    Nehmen wir an, es gibt drei TR-Elemente trs[0], trs[1] und trs[2], dann ist trs.length==3 und Deine Schleife zählt bis i==3, versucht also auf trs[3] zuzugreifen. Das ergibt undefined.

    10        var buttons = tr.getElementsByTagName('button');

    ^undefined hat keine Eigenschaften.

    13        buttons[0].onclick = sendInfo.addGoal(id, 0);

    ^hier wird sendInfo.addGoal(id, 0)aufgerufen und der Rückgabewert dieser Methode wird buttons[0].onclick zugewiesen. Willst Du buttons[0].onclick eine Methode des Objektes sendInfo als Funktion zuweisen, wäre das

    buttons[0].onclick = sendInfo.addGoal;

    Mit Attributen wäre es:

    buttons[0].onclick = function() {sendInfo.addGoal(id, 0);};

    Voraussetzung ist allerdings, dass sendInfo und id zum Zeitpunkt des Klicks auf den Button einen Wert haben.

    viele Grüße

    Axel

    1. Hallo,

      Mit Attributen wäre es:

      buttons[0].onclick = function() {sendInfo.addGoal(id, 0);};

      Voraussetzung ist allerdings, dass sendInfo und id zum Zeitpunkt des Klicks auf den Button einen Wert haben.

      sendInfo muss tatsächlich noch als globale Variable zur Verfügung stehen, id aber nicht - das ist ja der Sinn der Closure. Man kopiert die lokale Variable id in den Scope der anonymen Funktion. Was mit der lokalen Variable dann passiert, ist egal. Sie ändert ja vor allem ihren Wert durch die for-Schleife. An der Variable id im Scope der erzeugten Funktion ändert das nichts, die existiert selbst dann noch, wenn die lokale Variable id längst passé ist, weil die Funktion addBehaviour beendet wurde.

      Mathias

      1. Hallo,

        Mit Attributen wäre es:

        buttons[0].onclick = function() {sendInfo.addGoal(id, 0);};

        Voraussetzung ist allerdings, dass sendInfo und id zum Zeitpunkt des Klicks auf den Button einen Wert haben.

        sendInfo muss tatsächlich noch als globale Variable zur Verfügung stehen, id aber nicht - das ist ja der Sinn der Closure. Man kopiert die lokale Variable id in den Scope der anonymen Funktion. Was mit der lokalen Variable dann passiert, ist egal. Sie ändert ja vor allem ihren Wert durch die for-Schleife. An der Variable id im Scope der erzeugten Funktion ändert das nichts, die existiert selbst dann noch, wenn die lokale Variable id längst passé ist, weil die Funktion addBehaviour beendet wurde.

        Ja, die Variable existiert noch, aber immer mit dem Wert, den sie _zuletzt_ innerhalb von addBehaviour gehabt hat. Das ist das Problem, welches Struppi auch ansprach.

        Beispiel:

        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
                "http://www.w3.org/TR/html4/strict.dtd">
        <html>
        <head>
        <title>Text des Titels</title>
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
        <script type="text/javascript">
        <!--
        var id = 100; //window.id

        function addBehaviour() {
            var table = document.getElementsByTagName('table')[0];
            var trs = table.getElementsByTagName('tr');
            for(var i=0; i < trs.length; i++) {
                var tr = trs[i];
                var buttons = tr.getElementsByTagName('button');
                var id = tr.getAttribute('id').slice(1); // id im scope addBehaviour
                buttons[0].onclick = function() {alert(id + " : " + window.id + " : " + this.parentNode.parentNode.id);}
            }
         }
        //-->
        </script>

        </head>
        <body onload="addBehaviour();">
          <table>
           <tr id="g42">
            <td>
             <button>Button in TR mit ID g42</button>
            </td>
           </tr>
           <tr id="g43">
            <td>
             <button>Button in TR mit ID g43</button>
            </td>
           </tr>
           <tr id="g44">
            <td>
             <button>Button in TR mit ID g44</button>
            </td>
           </tr>
          </table>
        </body>
        </html>

        viele Grüße

        Axel

        1. Hallo,

          Ja, die Variable existiert noch, aber immer mit dem Wert, den sie _zuletzt_ innerhalb von addBehaviour gehabt hat.

          Ah, stimmt. Das hätte ich nicht erwartet. Also wird bei der Closure tatsächlich eine Referenz auf die Variable im Scope der Ausführung der äußeren Funktion angelegt.

          Neben der Speicherung in Eigenschaften kann man natürlich weitere Funktionen und Closures verwenden:

            
          function addBehaviour() {  
           var id = "g";  
           var elem = document.getElementById(id);  
           function addClick (elem, id) { // Closure, aber elem und id werden als Parameter überschrieben  
            function clickHandler () {  
             alert(elem + " " + id);  
            }  
            elem.onclick = clickHandler;  
           }  
           addClick(elem, id);  
           elem = id = null;  
          }  
          window.onload = addBehaviour;  
          
          

          Die inneren Funktionen können natürlich auch anonym sein, hier nur aus Gründen der Übersicht nicht.

          Mathias