Michael Kaufmann: Objekte und Events

Hallo,

ich habe ein Problem mit dem Aufrufen von Objektmethoden über einen Eventhandler. Hier der vereinfachte Code:

<html>
    <head><title>Test</title></head>
    <script language="JavaScript">
    function feld_mm()
      {
      alert(this.feld_div);
      }

function feld(feld_div)
      {
      this.feld_div             = feld_div;
      this.feld_mm              = feld_mm;

this.feld_div.document.onmousedown = this.feld_mm; // hier kommt undefined als Ausgabe ! Warum ?
      this.feld_div.document.captureEvents(Event.MOUSEDOWN);
      }
    function init()
      {

feld1=new feld(window.document.elm1);
      feld2=new feld(window.document.elm2);

feld2.feld_mm();  // Hier kommt als Ausgabe ObjectLayer, also das richtige
      }

</script>
    <body onload="init()" bgcolor="#ffffff">
    <div id="elm1" style="position:absolute; top:10px; left:50px;"><img src="images/feld1.gif" border=0"></div>
    <div id="elm2" style="position:absolute; top:40px; left:50px;"><img src="images/feld2.gif" border=0"></div>
    </body>
</html>

Eigentlich sollte, wenn an auf das Feld klickt ein Fensterchen aufpopen, in dem steht: [ObjectLayer].
Anstatt dessen steht dort aber undefined. Es sieht so aus, als würde nicht die Methode feld1.feld_mm() aufgerufen werden, sondern die Funktion feld_mm().
Das Problem liegt wohl an der Zeile:

this.feld_div.document.onmousedown = this.feld_mm;

im Konstruktor des Objekts (function feld();)
Dummerweise habe ich keine Ahnung warum! Geht das vielleicht gar nicht ?
Ich benutze NN4.73 für Linux (dummerweise gibt es gerade bei den Events unterschiede zwischen den Linux und Windows Versionen)

danke und tschüss Michael

  1. Hallo Michael

    function feld_mm()
          {
          alert(this.feld_div);
          }

    »»

    function feld(feld_div)
          {
          this.feld_div             = feld_div;
          this.feld_mm              = feld_mm;

    »»

    this.feld_div.document.onmousedown = this.feld_mm; // hier kommt undefined als Ausgabe ! Warum ?
          this.feld_div.document.captureEvents(Event.MOUSEDOWN);
          }
        function init()
          {

    »»

    feld1=new feld(window.document.elm1);
          feld2=new feld(window.document.elm2);

    »»

    feld2.feld_mm();  // Hier kommt als Ausgabe ObjectLayer, also das richtige
          }

    Ich bin kein Profi, und ich weiss auch nicht, obs was bringt, aber du hast die Funktion feld_mm() im Konstruktor nicht als Methode des Objekts definiert. Du definierst da nur, dass das Objakt die Variablen feld_div und feld_mm besitzt, aber nicht, dass du mit der Methode feld_mm() auf feld_div zugreifen kannst.

    Meiner Meinung nach sollte der Konstruktor irgendwie so aussehen:

    // function feld(feld_div, feld_mm){
    //   this.feld_div = feld_div;
    //   this.feld_mm  = feld_mm;
    //   this.feld_mm() = feld_mm();  // !!!
    //   this.feld_div.document.onmousedown = this.feld_mm;
    //   this.feld_div.document.captureEvents(Event.MOUSEDOWN);
    // }

    Abgesehen davon, was ist "mm" überhaupt ??

    Ich weiss nicht, obs stimmt, oder ob ich nur Blödsinn labere, aber ich würd es sowieso anders probieren. Ich weiss nicht wie es anders geht, aber das was du mir hier vorgelegt hast, wäre mir eindeutig zu kompliziert ;-)

    Grüsse
    Bernhard

    1. Hallo Bernhard

      Ich bin kein Profi, und ich weiss auch nicht, obs was bringt, aber du hast die Funktion feld_mm() im Konstruktor nicht als Methode des Objekts definiert. Du definierst da nur, dass das Objakt die Variablen feld_div und feld_mm besitzt, aber nicht, dass du mit der Methode feld_mm() auf feld_div zugreifen kannst.

      Ich bin leider auch kein Profi :-) Ich will aber mal einer werden !

      Meiner Meinung nach sollte der Konstruktor irgendwie so aussehen:

      // function feld(feld_div, feld_mm){

      Meiner Meinung nach, muss ich die Funktion feld_mm nicht
      extra übergeben, da sie global ist und damit sowieso im
      Konstruktor bekannt ist.

      //   this.feld_div = feld_div;
      //   this.feld_mm  = feld_mm;
      //   this.feld_mm() = feld_mm();  // !!!

      das kann auf keinen Fall so sein, denn mit den () nach
      dem Funktionsnamen wäre die Funktion this.feld_mm()
      der Rückgabewert der Funktion feld_mm. Ausserdem wäre
      das ein(e) falsche(r) Syntax.

      //   this.feld_div.document.onmousedown = this.feld_mm;
      //   this.feld_div.document.captureEvents(Event.MOUSEDOWN);
      // }

      Abgesehen davon, was ist "mm" überhaupt ??

      mm sollte eigentlich mousemove heissen...irgendwie ist
      es dann aber doch mousedown geworden :-)

      Ich weiss nicht, obs stimmt, oder ob ich nur Blödsinn labere, aber ich würd es sowieso anders probieren. Ich weiss nicht wie es anders geht, aber das was du mir hier vorgelegt hast, wäre mir eindeutig zu kompliziert ;-)

      hmm, Blödsinn ?? naja, es funzt so nicht.
      Das ist so "kompliziert", da das wirkliche Script (ich
      wollte keine 300+ Zeilen Code hier reinstellen) ein
      Scroll Object darstellen soll, mit dem man "einfach"
      (auch mehrere) scrollbare Layer in eine Seite einbinden
      können soll. Für sowas bietet sich ein Objekt halt sehr
      gut an.

      tschüss Michael

      1. Hallo Michael!

        das kann auf keinen Fall so sein, denn mit den () nach
        dem Funktionsnamen wäre die Funktion this.feld_mm()
        der Rückgabewert der Funktion feld_mm. Ausserdem wäre
        das ein(e) falsche(r) Syntax.

        Stimmt, die Klammern gehören weg, aber Funktionen sind in Javascript genauso Objekte. Daher kann man auch funktionen auf funktionen "zuweisen" ! -gibt's echt, ehrlich! Nur gehören die Klammern weg, da jedoch deine Funktion dann genauso heissen würde wie deine Variable müsstest du dir einen anderen Namen für eine(n) der beiden einfallen lassen.

        Vgl:
        var fenster  = new Window();
        var feld     = new Array();
        var funktion = new Function();

        ... im Grunde das selbe Schema !

        Ich hab dir einen Auszug aus einem Skriptum von einer meiner Übungen auf der Uni zum Thema Javascript:

        Ja, wir lernen sowas wirklich auf der Uni ;-)
        Aber frag nicht wie ... ! - SELFHTML-Forum is the place to be!!

        <html>
        <head>
        <script language="JavaScript">

        function zeige_umfang (r) { // Deklaration einer Objektmethode (=Funktion)
          var umfang, pi=3.14;
          alert("Kreis "+this.name + " mit Umfang " + (pi*2*r));
                // this.name greift auf Komponente name der  
                // aktuellen Instanz von Objekt kreis zu.
        }

        function position (x,y) { // Deklaration von Objekt position
          this.posx = x;          // mit 2 Komponenten posx und posy
          this.posy = y;          // this zeigt auf aktuelle Objektinstanz.
        }

        function kreis (name,radius,pos) {   // Deklaration von Objekt kreis
          this.name = name;
          this.radius = radius;
          this.pos = pos;                    // Objekt als Objektkomponente
          this.zeige_umfang = zeige_umfang;  // Methodenzuweisung !!!!!!!
        }

        </script>
        </head>
        <body>
        <script language="JavaScript">  
        pos1 = new position(0.0,0.0);
        kreis1 = new kreis("Kreis1",1.23,pos1);
        kreis1.zeige_umfang (kreis1.radius);
        </script>
        </body>
        </html>

        Du musst es mir ja nicht glauben, aber über JavaScript hab ich mich schon längst aufgehört zu wundern ;-)

        Dieses Beispiel kannst du Strg-Kopieren und austesten. Es funktioniert einwandfrei :-)

        Grüsse
        Bernhard

        1. Hallo Bernhard,

          's hat leider immer noch nicht funktioniert!

          Stimmt, die Klammern gehören weg, aber Funktionen sind in Javascript genauso Objekte. Daher kann man auch funktionen auf funktionen "zuweisen" ! -gibt's echt, ehrlich! Nur gehören die Klammern weg, da jedoch deine Funktion dann genauso heissen würde wie deine Variable müsstest du dir einen anderen Namen für eine(n) der beiden einfallen lassen.

          Meiner Meinung nach hast du recht !
          Ich habe dein Script mal ein bisschen umgeschrieben, so dass es
          Eventhandler (Mausklick ins Browserfenster) benutzt um die Methode
          kreis1.zeige_umfang() aufzurufen. Dann tritt das selbe Problem ein wie
          bei mir :-(

          <html>
          <head>
          <script language="JavaScript">

          function zeige_umfang ()
          // hier habe ich etwas geändert, da ich nicht weiss, wie ich bei
          // Eventhandlern irgendwelche Werte übergibt. Da diese  Funktion
          // aber sowieso auf this.radius zugreifen kann muss man den Radius
          // ja nicht extra übergeben.
              { // Deklaration einer Objektmethode (=Funktion)
              var umfang, pi=3.14;
              alert("Kreis "+this.name + " mit Umfang " + (pi*2*this.radius));
              // this.name greift auf Komponente name der  
              // aktuellen Instanz von Objekt kreis zu.
              }
            
            function position (x,y)
              { // Deklaration von Objekt position
              this.posx = x;          // mit 2 Komponenten posx und posy
              this.posy = y;          // this zeigt auf aktuelle Objektinstanz.
              }
                          
            function kreis (name,radius,pos)
              {   // Deklaration von Objekt kreis
              this.name = name;
              this.radius = radius;
              this.pos = pos;                    // Objekt als Objektkomponente
              this.zeige_umfang = zeige_umfang;  // Methodenzuweisung !!!!!!!
              document.onmousedown = this.zeige_umfang; // Entweder hier, was besser wäre (man stelle sich 1000
              document.captureEvents(Event.MOUSEDOWN);  // Objekte vor, hier nur 2 Zeilen, unten wären es 2000)
              }
                                          
          </script>
          </head>
          <body>
          <script language="JavaScript">
            pos1 = new position(0.0,0.0);
            kreis1 = new kreis("Kreis1",1.23,pos1);
            kreis1.zeige_umfang(); // hier kommt wieder da selbe Ergebnis wie vorher.

          //  document.onmousedown = kreis1.zeige_umfang; // oder hier, egal beides
          //  document.captureEvents(Event.MOUSEDOWN); // funktioniert nicht

          </script>
          </body>
          </html>

          Du musst es mir ja nicht glauben, aber über JavaScript hab ich mich schon längst aufgehört zu wundern ;-)

          Naja, ich glaube dir schon, ich habe nur meine Glauben an NN
          verloren. Manchmal kommt es vor dass er wegen JavaScripts abstürtzt
          oder dass NN4.7 keine Scripts ausführen kann, die NN4.73 ohne Probleme
          ausführt (teilweise ist es sogar andersrum, z.B. mit dem - im Variablennamen)

          Dieses Beispiel kannst du Strg-Kopieren und austesten. Es funktioniert einwandfrei :-)

          Das stimmt, ich glaube aber auch nicht, dass darin mein Problem liegt.
          Es liegt vielmehr daran, dass der Eventhandler die falsche funktion
          aufruft. Ich habe auch schon Funktionen umbenannt, so dass die
          Objektmethode anders heisst als die Funktion. Aber all das hat nicht
          geholfen. Ich könnte es natürlich auch mit eval machen. Das wäre dann
          aber nicht mehr OOP, sondern ein Mix aus normal und OOP.

          tschüss Michael