XodoX: Javascript-Problem / Elegante Lösung?

Hallo,

habe ein kleines "Ansatz"-Problem in meinem Script:

<script type="text/javascript">  
 function rand(min,max)  
 {  
 var wert =  min + Math.ceil(Math.random() * 1000) % (max-min) + 1;  
 return wert;  
 }  
  
var last_request=0;  
var aktiv = setInterval("loadData()",rand(10,20)*1000);  
setTimeout('loadData();',rand(5,35)*100);  
  
function asb_loadingEnd()  
{  
 document.getElementById("asb_loading").innerHTML='normal';  
}  
  
function loadData()  
{  
 document.getElementById("asb_loading").innerHTML='<img src=\"loading.gif\">';  
 setTimeout('asb_loadingEnd();',rand(5,35)*100);  
}  
</script>  
  
  
</head>  
  
<body>  
    <span id="asb_loading"/>normal</span>  
</body>

Dieses Script ersetzt den Text "normal" im span-element(id="asb_loading") alle paar Sekunden (Zufallsgeneriert) mit einer Grafik (loading.gif)

Bis hierher habe ich keine Probleme. Jetzt aber mein Anliegen:
Ich habe mehrere span-elemente, welche allesamt mit der loading.gif ersetzt werden sollen, allesamt nach einer zufallsgenerierten Sekundenanzahl, immer unterschiedlich.
Also beispielsweise wird nach 12 Sekunden der 1. Span-Eintrag für 2,5 Sekunden mit der loading.gif ersetzt, nach 18 Sekunden der 2. Span-Eintrag für 1,8 Sekunden, nach weiteren 15 Sekunden der nächste Span-Eintrag für 0,5 Sekunden und so weiter. Sollte sich auch alles überschneiden dürfen können!

Wie erreiche ich das am elegantesten? Ich hab da einfach ein Denkproblem, wie ich das in ein array, geschickte Funktionsverschachtelung oder ähnliches packen soll.

Wäre um einen Rat sehr dankbar!

  1. Hallo XodoX,

    <script type="text/javascript">

    function rand(min,max)
    {
    var wert =  min + Math.ceil(Math.random() * 1000) % (max-min) + 1;
    return wert;
    }

    Zunächst mal: Diese Implementierung ist nicht sehr elegant, sie funktioniert ja nur halbwegs, wenn (max-min) << 1000 ist.
    Wenn (max - min) kein Teiler von 1000 ist, treten ja nicht alle Reste gleich häufig auf. Bei kleinen Zahlen wirkt sich das nicht so aus, aber wenn man Beispielsweise (max - min) == 400 hat, so kommen die Reste 0 bis 199  ja 3 und die anderen 2 mal auf.

    Besser ist sowas:
    [code lang=javascript]
    function randInt(min, max) {
      return Math.ceil(min + Math.random() * (max - min));
    }

      
    
    > function asb\_loadingEnd()  
    > {  
    >  document.getElementById("asb\_loading").innerHTML='normal';  
    > }  
    >   
    > function loadData()  
    > {  
    >  document.getElementById("asb\_loading")  
    >  setTimeout('asb\_loadingEnd();',rand(5,35)\*100);  
    > }  
      
    
    > Wie erreiche ich das am elegantesten?  
    
    Zunächst mal musst Du das gewünschte Verhalten unabhängig vom konkreten Objekt formulieren:  
    ~~~javascript
      
    function setLoading(elem) {  
      elem.innerHTML = 'normal';  
      setTimeout(function() {setNormal(elem)}, randInt(1000, 30000));  
    }  
      
    function setNormal(elem) {  
      elem.innerHTML='<img src=\"loading.gif\">';  
      setTimeout(function(setLoading(elem)) {}, randInt(1000, 30000));  
    }  
    
    

    Dann musst Du das nur noch für jedes Element anstoßen:

      
    window.onload = function() {  
      var ids = new Array("foo", "bar", "baz");  
      for (var i = 0; i < ids.length; ++i) {  
        setNormal(document.getElementById(ids[i]));  
      }  
    };  
    
    

    Das ist alles ungetestet, kann also noch ein paar Flüchtigkeitsfehler enthalten.

    Grüße

    Daniel

    1. Hallo Daniel,

      funktioniert nicht, kommt Memory-Fehler.

      Aber der Ansatz ist gut, hab mal selbst was zusammengebastelt:

      <script type="text/javascript">  
        window.onload = function() {  
        var ids = new Array("te", "sa", "band");  
        for (var i = 0; i < ids.length; ++i) {  
        setInterval("setLoading(ids[i])",rand(1000,2000));  
        }  
      };  
        
        
       function rand(min,max)  
       {  
        return Math.ceil(min + Math.random() * (max - min));  
       }  
        
      function setLoadingEnd(elem)  
      {  
       document.getElementById(elem).innerHTML='normal';  
      }  
        
      function setLoading(elem)  
      {alert(elem);  
       document.getElementById(elem).innerHTML='<img src=\"loading.gif\">';  
       setTimeout('setLoadingEnd(elem);',rand(500,3500));  
      }  
        
      </script>
      

      Funktioniert aber noch nicht. Die Funktion setLoading wird zuerst aufgerufen, und dort ist das Argument elem plötzlich undefiniert. Warum das?

      In der For-Schleife noch mit einem Wert und dann beim Funktionsaufruf per setInterval muss was schiefgehen.

      setInterval("setLoading(ids[i])",rand(1000,2000));

      Wenn ich dort stat ids[i] z.B. einen Wert direkt (ohne Variablen-Nutzung) übergebe (z.B. "te") funktioniert alles tadellos.

      Ich kapier das echt nicht mehr....

      1. Hallo XodoX,

        funktioniert nicht, kommt Memory-Fehler.

        Was soll ein Memory-Fehler sein? Es ist aber tatsächlich ein Syntaxfehler drin. So tut es (getestet):

          
          setTimeout(function() {setNormal(elem)}, randInt(1000, 5000));  
        }  
          
        function setNormal(elem) {  
          elem.innerHTML='loading';  
          setTimeout(function() {setLoading(elem)}, randInt(1000, 5000));  
        }  
          
          
        window.onload = function() {  
          var ids = new Array("id1", "id2", "id3");  
          for (var i = 0; i < ids.length; ++i) {  
            setNormal(document.getElementById(ids[i]));  
          }  
        };  
          
        </script>  
        </head>  
        <body>  
        <p id="id1"></p>  
        <p id="id2"></p>  
        <p id="id3"></p>  
        </body>  
        </html>  
        
        

        Aber der Ansatz ist gut, hab mal selbst was zusammengebastelt:
        setInterval("setLoading(ids[i])",rand(1000,2000));

        setTimeout(function() {setLoading(elem)}, randInt(1000, 5000));
        Siehst Du den Unterschied?
        Du übergibst einen String ("setLoading(ids[i])"). Wenn der ausgeführt wird, sind die Variablen ids und i nicht mehr vorhanden.
        Ich übergebe eine (annonyme) Funktion. Da erkennt der Interpreter, dass ich da lokale Variablen verwende und löscht diese nicht.

        Der nächste Fehler ist, dass Du direkt eine Zählervariable einer Schleife verwendest. Diese ändert ja ihren Wert, bevor der Code ausgeführt wird.
        Da es in Javascript zudem keine wirklich lokalen variablen in Schleifen gibt, müsstest Du so etwas machen:

        window.onload = function() {
          var ids = new Array("te", "sa", "band");
          for (var i = 0; i < ids.length; ++i) {
            function() {
              var temp = i;
              setInterval(function() {setLoading(ids[temp])},rand(1000,2000));
            }();
          }
        };

        Grüße

        Daniel