Jense: Allgemeiner "DIV-Slide" funktioniert nicht ganz...

Hallo Experten,
ich bin mal wieder am verzweifeln...
Ich brauche DIV's die sanft ein- bzw. ausrollen (z.B. für's Menu). Funktioniert!
Da diese DIV's zum Teil dynamisch entstehen, sollte der Code derart gestaltet sein, dass die dynamisch erstellten DIV's alle unabhängig voneinander "sliden" können. Und genau da ist mein Problem:
Mit meiner Lösung funktioniert dass zwar eigentlich unabhängig, aber eben nur eigentlich. Denn wenn ein DIV zum "sliden" gebracht wird, während ein anderer gerade noch am "sliden" ist, dann wird das "sliden" beim letzteren (also dem der schon im slide war) einfach unterbrochen, d.h. er wird nicht zu Ende geöffnet oder geschlossen. Hier der Code (ist nur ein Ausschnitt, aber für die SEHER unter Euch sollte das Problem darin zu sehen sein - hoffe ich):

function fMakeDiv(pTop)
{
 var vCo = vCo800Null.appendChild(window[pWinBez].document.createElement("div"));
 with(vCo)
 {
        id="";
 className = "clCo";
 style.top = pTop+"px";
 }
 vCo.SlideFlag = 1;
 vCo.SlideMin = 50;
 vCo.SlideMax = 400;
 vCo.oSlide = new oSlide5(vCo);
}

function oSlide5(pObjekt)
{
 this.pObj = pObjekt;
 this.DoSlide = function fSlide()
 {
  this.pObj.SlideFlag = this.pObj.SlideFlag * (-1);
  fSlideAufZu(this.pObj);

function fSlideAufZu(pObj)
  {
   window.clearTimeout(pObj.Slide);

if(pObj.SlideFlag > 0)
   {
    pObj.SlideStep = Math.ceil(((pObj.SlideMax-                                pObj.SlideMin) - pObj.offsetHeight) * 0.1);
   }
   else
   {
    pObj.SlideStep = Math.ceil
                                ((pObj.offsetHeight-pObj.SlideMin) * 0.1);
   }

pObj.style.height = pObj.offsetHeight +
                        pObj.SlideFlag * pObj.SlideStep + 'px';

fSlideAufZuTimer = function()
   {
    fSlideAufZu(pObj);
   }

if(pObj.offsetHeight != Math.max(pObj.SlideFlag *
                        pObj.SlideMax,0))
   {
    pObj.Slide = window.setTimeout
                                ("fSlideAufZuTimer()", 50);
   }
   else
   {
    window.clearTimeout(pObj.Slide);
   }
  }
 }
}

Wenn man also hiermit verschiedene DIV's erzeugt und dann z.B. irgendwie mit
einElement.onclick = function() {vCoAlert.oSlide.DoSlide();};
aufruft, dann funktioniert alles wie gewünscht, solange man "slides" an unterschiedlichen DIV's nicht gleichzeitig ausführt - dann wie gesagt slidet nur noch der zuletzt betätigte DIV, der andere bleibt dann sofort stehen! Ich habe wirklich schon alles nur erdenkliche (subjektiv) ausprobiert, ohne Erfolg. Ich hoffe einer von Euch weiss Rat! Wenn jemand ein Script kennt, das die Anforderungen erfüllt (und durchgängig korrekt funktioniert) wäre ich natürlich auch dankbar. Trotzdem würde ich auch gerne verstehen warum das nicht funktioniert.

Gruss Jense

  1. Lieber Jense,

    mir scheint, dass das Script nicht konsequent objektorientiert aufgebaut ist, sodass sich irgendwelche "parallelen" Animationen wegen gemeinsam verwendeter Variablen/Namensräumen in die Quere kommen.

    Woher hast Du das Script?

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. mir scheint, dass das Script nicht konsequent objektorientiert aufgebaut ist, sodass sich irgendwelche "parallelen" Animationen wegen gemeinsam verwendeter Variablen/Namensräumen in die Quere kommen.

      Genau, irgendwo da liegt der Hase im Pfeffer. Ich versuche tatsächlich gerade die Scripte objektorientiert zu gestalten und muss zugeben, dass ich überall an meine Grenzen stosse. Deshalb hier noch mal eine allgemeinere Frage (Sorry wenn ich mich nicht korrekt ausdrücken sollte): Wenn man innerhalb einer (Konstruktor-)Funktion (hier: oSlide5) eine private Funktion definiert (hier: fSlideAufZu), dann sollte doch bei einer neuen Instanz von oSlide5 auch fSlideAufZu neu entstehen, also nur für das entsprechende Objekt arbeiten/funktionieren. Das war zumindest das Ziel des Scriptes, und wenn ich es nicht errreicht haben sollte so ist es doch allgemein möglich - oder? Mir scheint das vorliegende Problem aber gerade in der inneren Funktion fSlideAufZu zu liegen, und das versteh ich überhaupt nicht!?

      Woher hast Du das Script?

      Selber gebastelt - allerdings mit Vorlage, die ich dann angepasst habe. Die Vorlage stammt glaube ich sogar aus diesem Forum (evtl. von Dir Felix?), ich habe nur noch den link: http://www.sprachlernspiele.de/selftests/klapptabelle/klapp.html#
      Auf dieser Seite funktionieren die slides unabhängig voneinander, auch gleichzeitig. Nur warum es dort funktioniert und bei meinem Skript nicht, keine Ahnung. Ich möchte nochmal betonen: Das einzige Problem ist das zwei slides nicht gleichzeitig ablaufen können, weil offensichtlich die Funktion die sich immer wieder selbst aufruft (fSlideAufZu) nicht in jedem DIV seperat abläuft wie angedacht, sondern immer nur das zuletzt aktivierte DIV bearbeitet. Sonst gibt es aber keine Überschneidungen oder ähnliches.
      Noch eine allgemeine Frage: Kann man aus einem vordefinierten Objekt wie z.B. einem DIV eine Instanz erzeugen, die man dann mit speziellen Eigenschaften und Methoden belegt, so dass man dann quasi ein spezielles DIV-Objekt mit eigenen Eigenschaften/Methoden hat? Wenn ja, wie geht das?

      Gruss Jense

      1. Lieber Jense,

        Wenn man innerhalb einer (Konstruktor-)Funktion (hier: oSlide5) eine private Funktion definiert (hier: fSlideAufZu), dann sollte doch bei einer neuen Instanz von oSlide5 auch fSlideAufZu neu entstehen, also nur für das entsprechende Objekt arbeiten/funktionieren.

        Du irrst hier.

        Nach meinem Verständnis sind Funktionen in JavaScript immer global, sprich: Methoden des window-Objektes. Nur wenn Du das so notierst, ist eine Funktion "privat":

        meinObjekt.meineFunktion = function () { ... }

        Nach meinem Wissen sind "private" Funktionen in JavaScript Methoden eines existierenden Objekts, nur beim window-Objekt kann man anstatt z.B. window.alert() auch einfach nur alert() schreiben. Das macht die Funktion anscheinend "global", obwohl sie es in Wirklichkeit nicht ist, denn sie ist "nur" eine Methode des window-Objektes, das eben in JavaScript das höchste Objekt in der Objekthierarchie ist.

        In Deinem Konstruktor müsstest Du this.fSlideAufZu = function (param) { ... } notieren, damit Du eine an das Objekt gebundene Funktion (alias Methode) bekommst. Der Aufruf dieser Funktion ist aber dann auch an das Objekt gebunden! Du kannst dann nicht mehr einfach so notieren:

        window.setTimeout("fSlideAufZu(obj)", xyz)

        Du musst stattdessen das Objekt, dessen Methode Du willst, explizit aufrufen:

        window.setTimeout("meinObjekt.fSlideAufZu(obj)", xyz)

        Vielleicht hilft Dir ja dieser Thread weiter, in dem ich einen Lehrgang angefangen habe, der auch mit Animationen zu tun hat. Der dazugehörige Feature-Artikel ist leider noch in Arbeit, sodass ich Dich noch nicht darauf verweisen kann.

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. Hallo,

          Nach meinem Verständnis sind Funktionen in JavaScript immer global

          Das ist falsch, Funktionen können lokale Variablen sein und eine Funktionsdeklaration in einer anderen erzeugt nichts anderes als eine lokale Variable.

          function bla () {}
          ist immer identisch mit
          var bla = function () {...};
          erzeugt also im globalen Kontext eine globale Variable (= window-Methode), aber im Funktionskontext eine lokale Variable.

          Nach meinem Wissen sind "private" Funktionen in JavaScript Methoden eines existierenden Objekts, nur beim window-Objekt kann man anstatt z.B. window.alert() auch einfach nur alert() schreiben.

          Dass man alert() statt window.alert() schreiben kann, hängt einfach mit der sog. Scope Chain zusammen. Also die Reihenfolge, die zur Auflösung eines Bezeichners abgearbeitet wird. Wenn keine lokale Variable mit dem genannten Bezeichner gefunden wird, wird letztlich beim globalen Objekt nachgeschaut, das ist nunmal window.

          Du musst stattdessen das Objekt, dessen Methode Du willst, explizit aufrufen:

          window.setTimeout("meinObjekt.fSlideAufZu(obj)", xyz)

          Das geht davon aus, dass eine globale Variable namens meinObjekt existiert. Das will man eigentlich nicht.

          Mathias

          1. Hallo Mathias,

            Das ist falsch, Funktionen können lokale Variablen sein und eine Funktionsdeklaration in einer anderen erzeugt nichts anderes als eine lokale Variable.

            function bla () {}
            ist immer identisch mit
            var bla = function () {...};
            erzeugt also im globalen Kontext eine globale Variable (= window-Methode), aber im Funktionskontext eine lokale Variable.

            und konkret zu meinem Problem - warum funktioniert das dann nicht? So wie sich das Script verhält sieht es eben wirklich so aus als ob die innere Funktion fSlideAufZu global aktiv ist, denn sobald während eines slides eines DIVs ein slide eines anderen DIVs gestartet wird stopt der erstgenannte.

            Kannst Du den Fehler konkret erkennen, oder evtl. mal eine Lösung skizzieren?

            Gruss Jense

        2. Hi Felix,

          In Deinem Konstruktor müsstest Du this.fSlideAufZu = function (param) { ... } notieren, damit Du eine an das Objekt gebundene Funktion (alias Methode) bekommst. Der Aufruf dieser Funktion ist aber dann auch an das Objekt gebunden! Du kannst dann nicht mehr einfach so notieren:

          window.setTimeout("fSlideAufZu(obj)", xyz)

          Du musst stattdessen das Objekt, dessen Methode Du willst, explizit aufrufen:

          window.setTimeout("meinObjekt.fSlideAufZu(obj)", xyz)

          Ich habe das alles schon durchprobiert, also die innere Funktion fSlideAufZu z.B. nach aussen "gepackt". Kein Unterschied im Ergebnis - also wohl tatsächlich nicht irgendwie gekappselt. Auch die innere Funktion ebenfalls als Methode des Objektes zu definieren habe ich durchgespielt. Die Ergebnisse waren (für mich total verblüffend) immer gleich, d.h. es hat alles wunderbar funktioniert - nur nicht gleichzeitig! Ich habe es mit x-Varianten nicht einmal geschafft zwei slides zur gleichen Zeit ablaufen zu lassen!!! Aber sie sliden jedes für sich (also es gibt z.B. nicht den effekt, dass ich ein DIV sliden möchte, stattdessen aber (auch) ein anderes DIV slided)! Das verstehe ich einfach nicht, irgendwas läuft da unerwünscht global ab, wahrscheinlich die innere Funktion fSlideAufZu also werde ich diesen Ansatz (die innere Funktion auch direkt zu einer Methode des Objektes zu machen) nochmal aufgreifen und jetzt erstmal Deinen Artikel lesen. Danke Dir auf jedenfall erstmal für Deine Antworten.

          Gruss Jense

    2. Nochmal kurz in allgemeiner Form, das was ich brauche:
      Ich möchte einer beliebigen Anzahl von DIV's (aber nicht allen DIVs) eine Funktion zuordnen die nur im Rahmen des jeweiligen DIVs ausgeführt wird. Also möchte ich eine Methode für (manche) DIVs bestimmen. Die Funktion die dabei zur Methode wird (also hier den Slide) muss also irgendwie kopiert  werden und dem jeweiligen DIV als Methode angehängt werden. Wenn dann die Methode eines speziellen DIVs aufgerufen wird, so sollten sich die in der Methode stattfindenden Rückkopplungen immer nur auf das jeweilige DIV beziehen. Das sollte doch möglich sein - oder nicht? Wenn ja brauche ich jetzt nur noch einen (groben) Ansatz wie das zu bewerkstelligen ist, denn so wie ich es versuche klappt es wie gesagt nicht (gleichzeitig), irgendwo steckt der Wurm drin. Ich bau auf Euch!!!

      Gruss Jense

  2. Hallo,

    Denn wenn ein DIV zum "sliden" gebracht wird, während ein anderer gerade noch am "sliden" ist, dann wird das "sliden" beim letzteren (also dem der schon im slide war) einfach unterbrochen, d.h. er wird nicht zu Ende geöffnet oder geschlossen.

    Das ist ganz klar.

    Rekapitulieren wir mal, was du tust:

    function oSlide5(pObjekt)

    Die Konstruktor-Funktion

    this.DoSlide = function fSlide()

    Du fügst der Instanz eine Methode hinzu

    function fSlideAufZu(pObj)

    Du definierst eine nur in dieser Methode gültige Funktion, die in der lokalen Variable fSlideAufZu gespeichert wird. Sie bekommt das Elementobjekt übergeben.

    fSlideAufZuTimer = function()
       {
        fSlideAufZu(pObj);
       }

    Hier definierst du eine GLOBALE Funktion am window-Objekt und überschreibst gegenbenenfalls eine gleichnamige, vorher gesetzte Funktion.
    Rufst du den Konstruktor mehrmals auf, steht in fSlideAufZuTimer nur eine Funktion. Diese schließt die Variable pObj ein, und zwar mit dem Wert des letzten Aufrufs der Kontruktorfunktion.

    Wenn du diese globale Funktion nun immer wieder ausführst:

    pObj.Slide = window.setTimeout
                                    ("fSlideAufZuTimer()", 50);

    Dann wird immer das zuletzt gesetzte pObj behandelt, was solange gut geht, bis es nicht eine weitere Instanz gibt, die abwechselnd window.fSlideAufZuTimer wieder überschreibt.

    Das ganze kannst du viel einfacher machen. Du willst in einer Funktion, die du mit setTimeout aufrufst, eine Variable zur Verfügung haben.
    1. Du brauchst ihr dazu die Variable nicht übergeben, sie ist in ihr durch die Verschachtelung bereits verfügbar,
    2. Du brauchst die Funktion auch nicht global speichern, du kannst setTimeout auch direkt eine Funktionsreferenz übergeben. Die Funktion wird dann allerdings im Kontext von window ausgeführt, sodass "this" nicht auf das Instanzobjekt zeigt. Über Umwege kann man es aber auch darin verfügbar machen.

    function Konstruktor (elem) {  
      function step () {  
        // hier ist elem verfügbar  
        window.setTimeout(step, 50);  
      }  
      this.animate = function () {  
        step();  
      };  
    }
    

    Das Instanzobjekt verfügbar machen:

    function Konstruktor (elem) {  
      var instanz = this;  
      function step () {  
        // hier ist elem und instanz verfügbar, sodass du daran irgendwelche Flags speichern kannst, je nach Bedarf  
      }  
      ...  
    }
    

    Vergleiche diesen Artikel:
    http://aktuell.de.selfhtml.org/artikel/javascript/organisation/#methoden-eigener-objekte-und-kontext

    Mathias

  3. hier ist die Lösung im Ansatz:

    http://forum.de.selfhtml.org/archiv/2006/1/t122012/