Enrico: Funktion verursacht Absturz -> Alternativen?

Hallo,

ich habe auf unserer (momentan noch lokal hinterlegten) Homepage eine Grafik einer nicht leuchtenden Glühbirne eingebaut, dies ist auch gleichzeitig der Zustand bei MouseOut, die bei MouseOver durch die Grafik einer leuchtenden Glühbirne ersetzt wird.

Ich habe heute schon probiert, das Ein- und Ausschalten nicht mehr vom Zustand der Maus abhängig zu machen, sondern zufallsgesteuert über eine Javascript-Funktion regeln zu lassen:

var Schalter = "aus";

function Beleuchtung_steuern ()
   {
      var Dauer = Math.round (Math.random () * 50);

if (Schalter == "aus")
      {
         Beleuchtung_einschalten ();
         Schalter = "ein";
      }
      else
      {
         Beleuchtung_ausschalten ();
         Schalter = "aus";
      }

var Verzoegerung = window.setInterval ("Beleuchtung_steuern ()", Dauer);
   }

function Beleuchtung_einschalten ()
   {
      document.getElementById("Gluehbirne").className = "Gluehbirne_an";
   }

function Beleuchtung_ausschalten ()
   {
      document.getElementById("Gluehbirne").className = "Gluehbirne_aus";
   }

Die html-Datei hat hier folgende relevante Angaben hierzu:

<div id="Gluehbirne" class="Gluehbirne_aus"></div>

Die css-Datei legt folgendermassen die Klassen fest:

div.Gluehbirne,
   div.Gluehbirne_aus,
   div.Gluehbirne_an
   {
      height:     233px;
      margin:     0px 0px 0px 150px;
      top:        0px;
      width:      337px;
   }

div.Gluehbirne_aus
   {
      background: url("../../Grafiken/Layout/Gluehbirne_aus.png") no-repeat;
   }

div.Gluehbirne_an
   {
      background: url("../../Grafiken/Layout/Gluehbirne_an.png") no-repeat;
   }

Leider musste ich feststellen, dass sich der Browser, wie befürchtet, aufhängt, weil ich diesen Effekt nur über eine sich immer wieder selbst aufrufende Funktion bewerkstelligen kann, außer ich hätte die Funktion falsch programmiert.

Auch bin ich mir nicht sicher, ob ich wirklich drei css-Definitionen benötige.

Da ich keine Ahnung von beispielsweise Flash, als mögliche Alternative habe, aber auch keine gif-Animation erstellen kann, da die transparenten Grafiken beim Umwandeln ihre Transparenz immer verlieren, weiß ich nicht, wie man dies noch umsetzen könnte.

Könnt ihr mir hier weiterhelfen?
Vielleicht habe ich ja "nur" Fehler im Javascript-Code.

Vielen Dank und Gruß
Enrico

  1. hallo Enrico,

    var Verzoegerung = window.setInterval ("Beleuchtung_steuern ()", Dauer);

    das Problem an deinem Code ist, dass immer wieder ein Interval startest, aber nie eines http://de.selfhtml.org/javascript/objekte/window.htm#clear_interval@title=stoppst.
    Du 'stapelst' die Intervalle... Intervals.. Intervälle, ach verdammt![1]
    .. bis der Browser in die Knie geht.

    Leider musste ich feststellen, dass sich der Browser, wie befürchtet, aufhängt, weil ich diesen Effekt nur über eine sich immer wieder selbst aufrufende Funktion bewerkstelligen kann, außer ich hätte die Funktion falsch programmiert.

    Sie muss sich nicht selbst aufrufen. Starte ein Interval, wenn das Dokument geladen ist. Dieses Interval ruft eine Funktion auf, die erst die CSS-Klasse des Divs überprüft und anhand dessen entscheidet, welche sie als nächstes bekommt. Die Variable für die Interval-Geschwindigkeit solltest du da auch ändern können, solange sie nicht lokal in der Funktion definiert wird.

    Da ich keine Ahnung von beispielsweise Flash, als mögliche Alternative habe [...]

    Flash ist einzig eine Alternative für einen Gehirntumor.

    [1] - einmal zu lang über den Plural nachgedacht, schon sehen alle Varianten blöd aus

    grüße,
    henman

    --
    "Sir! We are surrounded!" - "Excellent! We can attack in any direction!"
    sh:( fo:| ch:? rl:° br:> n4:? ie:% mo:) va:| de:] zu:) fl:{ ss:| ls:[ js:|
    1. Hallo henman,

      danke für Deine schnelle Antwort.

      Ich habe Deinen Tip (hoffentlich) umgesetzt und den Code folgendermassen umgebaut:

      var Schalter      = "aus";
         var Warteschleife = "";

      function Beleuchtung_steuern ()
         {
            Dauer = Math.round (Math.random () * 5000);

      if (Schalter == "aus")
            {
               Warteschleife = window.setInterval ("Beleuchtung_einschalten ()", Dauer);
               Schalter      = "ein";
            }
            else
            {
               Warteschleife = window.setInterval ("Beleuchtung_ausschalten ()", Dauer);
               Schalter      = "aus";
            }
         }

      function Beleuchtung_einschalten ()
         {
            document.getElementById("Gluehbirne").className = "Gluehbirne_an";
            window.clearInterval (Warteschleife);
            Beleuchtung_steuern ();
         }

      function Beleuchtung_ausschalten ()
         {
            document.getElementById("Gluehbirne").className = "Gluehbirne_aus";
            window.clearInterval (Warteschleife);
            Beleuchtung_steuern ();
         }

      Jetzt funktioniert auch alles ohne Abstürze.

      Ob das Skript allerdings zu merkbaren Verzögerungen während des "normalen" Homepage-Betriebes führen, kann ich noch nicht sagen, weil ich jetzt erst Schritt für Schritt den eigentlichen Code einbaue.

      Wie könnte man den Code denn sicherheitshalber noch optimieren?

      Gruß
      Enrico

      1. hallo [Verbesserungsvorschlag],

        Wie könnte man den Code denn sicherheitshalber noch optimieren?

        Die Variable Schalter kann ganz weg.
        In Beleuchtung_steuern() machst du eine if-Abfrage, die platziere ich mal um. Starte in dieser Funktion einfach ein Interval, dass in Dauer Abständen die Funktion.. lampe_schalten() aufruft.
        In lampe_schalten() überprüfst du nun, was #Gluehbirne für eine Klasse hat.
        Hat es die Klasse 'foo', wird die Klasse eben in 'bar' umgenannt usw., so wie du es schon hattest.

        Da Beleuchtung_steuern() nur einmal aufgerufen werden sollte, braucht lampe_schalten kein clearInterval mehr.

        Willst du die Intervallänge variieren, so definiere Dauer außerhalb von Funktionen, damit sie global verfügbar ist und ändere den Wert in lampe_schalten().

        Dein Code würde damit von ca. 30 Zeilen auf .. bestimmt mehr als die Hälfte runtergekürzt.

        Mach dir aber Kommentare, damit du es in zwei Monaten auch noch verstehst.

        grüße,
        henman

        --
        "Sir! We are surrounded!" - "Excellent! We can attack in any direction!"
        sh:( fo:| ch:? rl:° br:> n4:? ie:% mo:) va:| de:] zu:) fl:{ ss:| ls:[ js:|
        1. Hallo henman,

          hallo [Verbesserungsvorschlag],

          Sorry, ich habe nicht herausgefunden, wie ich hier die Überschrift hätte variieren können...

          Ok, jetzt sieht mein (merklich gekürzter) Code wie folgt aus:

          var Warteschleife = "";
             var Dauer         = Math.round (Math.random () * 15000);

          function Beleuchtung_steuern ()
             {
                Warteschleife = window.setInterval ("Lampe_schalten ()", Dauer);
             }

          function Lampe_schalten ()
             {
                Dauer = Math.round (Math.random () * 15000);

          if (document.getElementById("Gluehbirne").className == "Gluehbirne_an")
                {
                   document.getElementById("Gluehbirne").className = "Gluehbirne_aus";
                }
                else
                {
                   document.getElementById("Gluehbirne").className = "Gluehbirne_an";
                }
             }

          Allerdings kann ich nicht feststellen, dass die Dauer jetzt variiert.

          Habe ich Dich bei Deinem Vorschlag missverstanden oder ihn lediglich unproduktiv umgesetzt?

          Gruß
          Enrico

          1. Hi,

            Allerdings kann ich nicht feststellen, dass die Dauer jetzt variiert.

            Natürlich nicht, du setzt ja auch nur ein mal ein Intervall mit dem zu diesem Zeitpunkt aktuellen Wert von Dauer.
            Dass du Dauer anschließend veränderst, interessiert dieses Intervall absolut nicht.

            Wenn du die Dauer ständig verändern willst, dann bleibst du doch besser bei setTimeout - und setzt jedes Mal am Ende der Funktion einen neuen Timeout mit einer neuen Dauer.

            MfG ChrisB

            --
            RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
            1. Hallo ChrisB,

              perfekt, so klappt es mit äusserst schlankem Code:

              var Warteschleife = "";
                 var Dauer         = Math.round (Math.random () * 15000);

              function Beleuchtung_steuern ()
                 {
                    Warteschleife = window.setTimeout ("Lampe_schalten ()", Dauer);
                 }

              function Lampe_schalten ()
                 {
                    if (document.getElementById("Gluehbirne").className == "Gluehbirne_an")
                    {
                       document.getElementById("Gluehbirne").className = "Gluehbirne_aus";
                    }
                    else
                    {
                       document.getElementById("Gluehbirne").className = "Gluehbirne_an";
                    }

              window.clearTimeout ("Lampe_schalten ()");
                    Dauer = Math.round (Math.random () * 15000);
                    window.setTimeout ("Lampe_schalten ()", Dauer);
                 }

              Wobei ich mir, wenn ich die Ablauflogik so ansehe, die erste Funktion eigentlich jetzt auch noch sparen könnte, oder?

              Gruß
              Enrico

              1. Hi,

                Wobei ich mir, wenn ich die Ablauflogik so ansehe, die erste Funktion eigentlich jetzt auch noch sparen könnte, oder?

                Ja.
                Und das clearen des Timeouts auch (zumal du die Methode auch falsch verwendest),
                und die Verwendung der Variablen Dauer auch,
                und die Übergabe der aufzurufenden Funktion an setTimeout in Stringform auch.

                In Kurzfassung sollte sich das herunterbrechen lassen auf (ungetestet):

                var gluehbirne = document.getElementById("Gluehbirne"); // aus Performance-Gründen die Referenz nur einmalig vorher ermitteln  
                  
                function Lampe_schalten() {  
                  gluehbirne.className = (gluehbirne.className == "Gluehbirne_an") ? "Gluehbirne_aus" : "Gluehbirne_an";  
                  window.setTimeout(Lampe_schalten, Math.round(Math.random() * 15000));  
                }
                

                MfG ChrisB

                --
                RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
              2. [latex]Mae  govannen![/latex]

                if (document.getElementById("Gluehbirne").className == "Gluehbirne_an")

                document.getElementById("Gluehbirne").className = "Gluehbirne_aus";

                document.getElementById("Gluehbirne").className = "Gluehbirne_an";

                Die wiederholte Ermittlung des gleichen Elements kann man auch noch wegoptimieren.

                Schreib ober- oder unterhalb von

                var Dauer = ...

                noch die Zeile var gluehlampe = document.getElementById("Gluehbirne");

                und überall, wo jetzt document.getElementById("Gluehbirne"). steht schreibst du einfach gluehlampe.

                Und die if ... else ... Abfrage könnte man sogar mit dem ternären Operator (->darfst du ergooglen) als Einzeiler erledigen.

                gluehlampe.classname = (gluehlampe.classname == 'Gluehbirne_an') ? 'Gluehbirne_aus' : 'Gluehbirne_an';

                Cü,

                Kai

                P.S. Ich habe mir erlaubt, zumindest bei der Variablenbezeichnung den Obst-Anteil durch eine bessere Bezeichnung zu ersetzen.

                --
                Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
                in Richtung "Mess up the Web".(suit)
                SelfHTML-Forum-Stylesheet
                1. Hallo Kai & ChrisB,

                  sorry, ich konnte nicht eher schreiben, weil ich am Nachmittag unterwegs war und eben erst von einem Dartpokalspiel vom DVO aus zurückgekommen bin.

                  Vielen Dank für Eure Anregungen und Optimierungstips, die ich auch so übernommen habe.

                  Die html-Datei hat folgenden Aufbau:

                  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
                      <html>
                         <head>
                            ...
                            <script language="javascript" src="Dateien/js/Lampe_steuern.js" type="text/javascript"></script>
                         </head>
                         <body>
                            <div class="Seite_Hintergrund"></div>
                            <div class="Abschluss_Oben"></div>
                            <div class="Abschluss_Unten"></div>
                            <div class="Container_Anzeigebereich">
                               TEXT
                            </div>
                            <div id="Lampe" class="Lampe_aus"></div>
                            <script type="text/javascript">
                               Lampe_schalten ();
                            </script>
                         </body>
                      </html>

                  Die js-Datei hat nun folgenden Aufbau (gemäss eurer Tips):

                  var Lampe = document.getElementById ("Lampe");

                  function Lampe_schalten ()
                      {
                     --> Lampe.className = (Lampe.className == "Lampe_an") ? "Lampe_aus" : "Lampe_an"; <--
                         window.setTimeout (Lampe_schalten, Math.round (Math.random() * 15000));
                      }

                  Allerdings bekomme ich die Fehlermeldung "Lampe ist null" in der markierten Zeile.

                  Ich muss erst noch recherchieren, warum, wollte mich aber jetzt gleich zu (geschriebenem) Wort melden, nicht dass ihr denkt, dass ich mich nicht mehr melden würde.

                  Gruß
                  Enrico

                  1. Hi,

                    <script language="javascript" src="Dateien/js/Lampe_steuern.js" type="text/javascript"></script>

                    Hier wird das Script eingebunden und damit
                    var Lampe = document.getElementById ("Lampe");
                    ausgeführt.

                    <div id="Lampe" class="Lampe_aus"></div>

                    erst hier beginnt das Element mit der Id "Lampe" zu existieren.

                    cu,
                    Andreas

                    --
                    Warum nennt sich Andreas hier MudGuard?
                    O o ostern ...
                    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
                    1. Hallo Andreas,

                      klar, das kann ja nicht funktionieren...

                      Danke, Andreas, jetzt klappt es einwandfrei.

                      Gruß
                      Enrico

                2. Hallo,

                  P.S. Ich habe mir erlaubt, zumindest bei der Variablenbezeichnung den Obst-Anteil durch eine bessere Bezeichnung zu ersetzen.

                  warum? Lass die klassischen Glühlampen doch aufgrund ihrer Form "Birnen" heißen. Die schlanken, länglichen Bauformen heißen ja auch "Kerzen".

                  Ciao,
                   Martin

                  --
                  In Ägypten haben früher 150000 Leute 35 Jahre lang an einer Pyramide gearbeitet. Aber bei uns arbeiten doppelt so viele Leute doppelt so lange allein an der Baugenehmigung.
                    (Dieter Nuhr, deutscher Kabarettist)
                  Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            2. hallo ChrisB,

              Dass du Dauer anschließend veränderst, interessiert dieses Intervall absolut nicht.

              huch, sorry, da is mir nen Fehlerchen unterlaufen :P

              grüße,
              henman

              --
              "Sir! We are surrounded!" - "Excellent! We can attack in any direction!"
              sh:( fo:| ch:? rl:° br:> n4:? ie:% mo:) va:| de:] zu:) fl:{ ss:| ls:[ js:|
  2. Hi,

    function Beleuchtung_steuern ()
       {

    [...]

    var Verzoegerung = window.setInterval ("Beleuchtung_steuern ()", Dauer);
       }

    Dir ist nicht klar, was setInterval macht.
    Es startet alle n Millisekunden die Funktion.
    Bei Dir wird dann jedesmal ein weiteres setInterval gemacht.

    Du willst aber eigentlich am Ende von Beleuchtung_steuern() nur, daß nach Ablauf der Zeit _einmal_ die Funktion aufgerufen wird.
    Dazu gibt es setTimeout.

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    1. Hallo Andreas,

      auch Dir danke für Deine Antwort.

      setTimeout habe dann auch eingebaut

      Der Code funktioniert jetzt reibungslos, vielleicht kann man ihn noch optimieren und schlanker formulieren, so dass er vielleicht (noch) weniger in's Gewicht fällt.

      Gruß
      Enrico