thecreep: window.setTimeout() wartet nicht...

Hi,
ich schreibe grade einen Fader (wo bei das Fader-Framework eine gute Vorlage darstellt). Allerdings funktioniert mein window.setTimeout nicht wirklich, bzw. es wartet nicht.

Hier mal der Quellcode:

function Fader(id)  
{  
  this.div = document.getElementById(id);  
  this.id = id;  
  this.ai = 0;  
  this.fadeTime = 100;  
  this.timeOut = 3000;  
  this.repeat = false;  
  this.images = new Array("./IMAGES/Fahrer/borch.jpg","./IMAGES/Fahrer/micha.jpg");  
  this.createImages = function(){  
    this.div.innerHTML="";  
    for(i=0;i<this.images.length;i++)  
	  this.div.innerHTML+="<img style='opacity: "+(i==0?"1":"0")+";' src='"+this.images[i]+"'>";  
  }  
  this.addImage = function(img){  
    this.images[this.images.length]=img;  
  }  
  
//Es geht mir um den Folgenden Code-Fetzen:  
  this.Fade = function(step) {  
	step = step || 0;  
	step+=2;  
    var imgs=this.div.getElementsByTagName("IMG");  
	imgs[this.ai+1].style.opacity=step/100;  
	if(step<100)  
  	  window.setTimeout(this.Fade(step), this.fadeTime);  
  }  
}

In meiner HTML-Seite erstelle ich im onload ein neues Fader-Objekt:
var myfader = new Fader("fadediv");

Dann habe ich noch einen Button:
<input type=button value="create&fade" onclick="myfader.createImages();myfader.Fade();">

Momentan ist die fadeTime auf 3000 Millisekunden eingestellt, quasi ja 3 Sekunden wird in der Fade-Routine das aktuelle Img-Objekt immer um 2% sichtbarer.

Heißt quasi, dass der Transparenz-Übergang ca. 2,5 Minuten dauern müsste. Nun rast es aber durch und ist innerhalb eines Bruchteils einer Sekunde fertig.
Fehlermeldungen bekomme ich keine, also wo liegt mein Fehler?
Im Fader-Framework wirds genauso gemacht aber da funktioniert es ja.
Falls es wichtig ist, ich benutze Firefox 3.0.15

MfG
thecreep

  1. Hallo,

    bist du dir sicher, dass setTimeout nicht mit eine String versehen werden muss als erstem Parameter? Isoliertes Testen vielleicht?

    Gruß

    jobo

  2. window.setTimeout(this.Fade(step), this.fadeTime);

    Und hier ist auch schon der Fehler, denn das "this.Fade(step)" in dieser Anweisung führt die Funktion sofort aus. Um sie verzögert aufzurufen, müsste es entweder also String übergeben oder in eine Funktion gekapselt werden - mit der ersten Lösung besteht jedoch das Problem, dass "this" in diesem Kontext nicht verfügbar ist, so dass eine vorher definierte Funktion die bessere Wahl darstellt:

    var timeoutFn = function() { this.Fade(step); }  
    window.setTimeout(timeoutFn, this.fadeTime);
    

    Gruß, LX

    --
    RFC 1925, Satz 6a: Es ist immer möglich, einen weiteren Umweg einzufügen.
    RFC 1925, Satz 11a: Siehe Regel 6a
    1. Hallo,

      var timeoutFn = function() { this.Fade(step); }

      window.setTimeout(timeoutFn, this.fadeTime);

        
      nicht window.setTimeout("timeoutFn()",timeVar) ?  
        
      Also als String?  
        
      Gruß  
        
      jobo
      
      1. nicht window.setTimeout("timeoutFn()",timeVar) ?

        Also als String?

        Nein, besser bzw. hier nur schöner, ist die Funktionsreferenz.

        Struppi.

        1. Hallo,

          Nein, besser bzw. hier nur schöner, ist die Funktionsreferenz.

          Funktionsreferenz ist Funktionsname ohne "()" ?

          Gruß

          jobo

          1. Nein, besser bzw. hier nur schöner, ist die Funktionsreferenz.
            Funktionsreferenz ist Funktionsname ohne "()" ?

            Kann man so sagen, ja.

            Das ist aber auch eine:

            var f = function(txt) { alert(txt);};  
            f('Hallo');  
            
            

            Struppi.

            1. Hallo,

              Nein, besser bzw. hier nur schöner, ist die Funktionsreferenz.
              Funktionsreferenz ist Funktionsname ohne "()" ?

              Kann man so sagen, ja.

              Das ist aber auch eine:

              var f = function(txt) { alert(txt);};

              f('Hallo');

                
              Unter Funktionsreferenz versteht man scheinbar zwei Sachen. Beim Googlen kommt haufenweise eine Auflistung von Funktionen (zB. PHP), also ein Manual.  
                
              Oder:  
                
              "window.onerror = Funktionsreferenz – Führt die angegebene Funktion beim Auftreten eines Fehlers aus. Es muss eine Referenz auf die Funktion angegeben werden, also window.onerror = funktion und nicht window.onerror = funktion()."  
                
              "funktion" ist dann die Funktionsreferenz, "funktion()" der aufruf der funktion. Ums aber genau zu wissen: Was ist bei deinem Beispiel die Funktionsreferenz? Der aufruf f("Hallo")? Das müsst ja bei SetTimeout als String verpackt sein, sonst "funzt es nicht, oder?"  
                
              setTimeout("f('hallo')",timeVar);  
                
              Gruß  
                
              jobo
              
              1. "funktion" ist dann die Funktionsreferenz, "funktion()" der aufruf der funktion. Ums aber genau zu wissen: Was ist bei deinem Beispiel die Funktionsreferenz? Der aufruf f("Hallo")? Das müsst ja bei SetTimeout als String verpackt sein, sonst "funzt es nicht, oder?"

                f ist die Referenz auf die Funktion.

                Nein der Aufruf muss nicht als String verpackt werden.

                setTimeout("f('hallo')",timeVar);

                In dem Fall benutzt man besser ein closure:

                window.setTimeout( fucntion() { f('hallo')}, timeVar);

                Struppi.

                1. "Referenz" ist schlicht und einfach ein Bezeichner, ein Variablenname, der in diesem Fall eben auf eine Funktion hinweist.

                  Man kann Funktionen auch ohne Referenz definieren und ausführen (bspw. um Code zu kapseln):

                  (function() {  
                     ...  
                  })()
                  

                  Was window.setTimeout betrifft: wenn es einen String bekommt, wird dieser innerhalb des Timeouts evaluiert - also das Equivalent von eval ausgeführt (und eval ist so böse, wie es sich auf Englisch anhört!).

                  Darum ist es gegebenenfalls besser, innerhalb von window.setTimeout eine Funktion zu übergeben.

                  Gruß, LX

                  --
                  RFC 1925, Satz 6a: Es ist immer möglich, einen weiteren Umweg einzufügen.
                  RFC 1925, Satz 11a: Siehe Regel 6a
                  1. Hallo,

                    (function() {

                    ...
                    })()

                      
                    (...)() wird sofort ausgeführt?  
                      
                    Gruß  
                      
                    jobo
                    
                    1. Wenn zwischen den Klammern eine Funktion steht bzw. zurückgegeben wird, ja.

                      Gruß, LX

                      --
                      RFC 1925, Satz 6a: Es ist immer möglich, einen weiteren Umweg einzufügen.
                      RFC 1925, Satz 11a: Siehe Regel 6a
                      1. Hallo,

                        Wenn zwischen den Klammern eine Funktion steht bzw. zurückgegeben wird, ja.

                        äh, und was, wenn nicht? ()()? bringt das was?

                        Gruß

                        jobo

                        1. Wenn zwischen den Klammern eine Funktion steht bzw. zurückgegeben wird, ja.

                          äh, und was, wenn nicht? ()()? bringt das was?

                          Ja, du hast einen lokalen Kontext.

                          Struppi.

                        2. äh, und was, wenn nicht? ()()? bringt das was?

                          Ja, einen Fehler, da "undefined" nicht als Funktion ausgeführt werden kann.

                          Gruß, LX

                          --
                          RFC 1925, Satz 6a: Es ist immer möglich, einen weiteren Umweg einzufügen.
                          RFC 1925, Satz 11a: Siehe Regel 6a
                2. Hallo,

                  In dem Fall benutzt man besser ein closure:

                  window.setTimeout( fucntion() { f('hallo')}, timeVar);

                  "closure", weil es die Funktion "einschließt", oder besser "kapselt"?

                  Gruß

                  jobo

                  1. "closure", weil es die Funktion "einschließt", oder besser "kapselt"?

                    http://aktuell.de.selfhtml.org/artikel/javascript/organisation/#closures

                    Struppi.

  3. Im Fader-Framework wirds genauso gemacht aber da funktioniert es ja.

    Nein, mit Sicherheit nicht.

    Leider bist du hier nicht mehr auf meinen Einwurf eingegangen, da dieses Problem hier mit dem dort vermutlich zusammenhängt.

    Du musst dir im klaren sein, in welchen Kontext ein Code aufgerufen wird. In deinem Fall ist this nicht das this mit dem du rechnest. Da window.setTimeout() im Kontext von window aufgerufen wird, folglich ist this == window

    Dummerweise machst du aber noch einen zweiten Fehler. Du benutzt einen falschen 1. Parameter in setTimeout. Dieser muss entweder eine Zeichenkette sein, die dann als JS Code interpretiert wird oder eine Funktionsreferenz, so wie im Faderframework.

    Der einfachste Weg die Problematik des Kontext zu beseitigen ist eine lokale Kopie des Objekt und für die Funktionsreferenz, ein closure. Beides nutzt das Faderframework. Lies dir noch mal diese Seite durch.

    Struppi.