reko: Schreibmaschine

Ich möchte eine "Schreibmaschinen"-ausgabe simulieren. Dabei sollen die Zeichen eines gegebenen Strings einzeln in verschiedenen Zeitintervallen ausgegeben werden. Mit window.setInterval() sehe ich keine Möglichkeit, das zu realisieren, da die Intervalle ja, wie schon gesagt, sich ständig ändern sollen. Ich habe nun folgendes Fragment hier, das zwar läuft, aber nicht wie ich will:

function delay(ms)
{ var t=new Date();
  var r=new Date();
  while (r-t<ms) r=new Date();
  return(r-t);}

function typewrite()
{ var text=document.getElementById("eingabe").innerText;
  var out=document.getElementById("ausgabe").innerText;
  var ti;
  var h;
  for (var i=0; i<text.length; i++) {
      ti=Math.floor(Math.random()*800); //max 800ms zwischen zwei Zeichen
      out=out+text.charAt(i);  //kopieren und hinzufügen
      document.getElementById("ausgabe").innerText=out; //ausgeben
      h=0;    //warten
      while (h==0) h=delay(ti);
      //alert(out);
      }
}

Es gibt also zwei Textfelder eines mit id="eingabe" und eines mit id="ausgabe". Die Funktion typewrite() wird mit einem Button gestartet. Die Funktion verhält sich nun so: Scheinbar werden alle Anweisungen richtig ausgeführt, aber der auszugebende Text erscheint nicht zeichenweise in "ausgabe", sondern erst nachdem alle "delay"-Schleifen abgelaufen sind und dann als gesamter Text. Das könnte ich auch kürzer haben! Wenn die Zeile alert(out) nicht auskommentiert ist, geht es aber seltsamerweise. Woran kann das liegen? Hat wer eine Ahnung oder gar eine Lösung für mein Problem?

  1. Moin, Du,

    Woran kann das liegen? Hat wer eine Ahnung oder gar eine Lösung für mein Problem?

    Das Problem ist imo, dass der JavaScript-Interpreter die Ausgabe puffert, bevor er sie tätigt. Ein-Ausgabe-Prozesse sind vergleichsweise aufwendig, deswegen wird das oft so gemacht, dass man erstmal alle Ausgaben zusammensammelt, und wenn nix mehr kommt, haut man alles auf einmal raus.
    Wenn Du ein alert reinbaust, gehts natürlich, das zwingt das Programm zu einer Unterbrechung, und sorgt dafür, dass es seine Ausgabe brav vor jedem alert macht.

    Zur Lösung Deines Problemes: Du kannst statt window.setInterval window.setTimeout benutzen, und dann jedesmal den Delaywert verändern.
    Ich hab mal vor Ewigkeiten so ein dingens wie du programmiert
    (http://www.h5network.de/ <- nicht zu genau hingucken, das Teil ist wirklich alt *fg*) im linken Frame (siehe Funktion slow_typer). Meine Delays sind zwar immer fest auf 100 ms , aber es dürfte kein Problem sein, die noch mit einer Zufallszahl wie in Deinem Fall zu versehen.

    Gruesse,
    Joerg

    1. Hi Joerg,

      Dankeschön!
      Hatte es zwar schon mal mit window.setTimeout() probiert, bekam aber Probleme damit, daß ein "weiter hinten" stehendes Zeichen plötzlich eher ausgegeben wurde als ein "weiter vorn" stehendes. Bin damals überhaupt nicht darauf gekommen, die einzelnen "Zeiten" einfach zu addieren. Ein beinahe funktionierendes Fragment hab ich jetzt fertig - vielleicht kannst Du es ja auch mal brauchen :)

      function typewrite()
      { var ti=0;
        var text=document.getElementById("eingabe").innerText;
        var arr = new Array();

      for (var i=0; i<text.length; i++) {
            ti=ti+Math.floor(Math.random()*600);
            arr.push(ti);
            arr.push(text.charAt(i));
            alert(text.charCodeAt(i));
            }

      for (i=0; i<text.length; i++)
            window.setTimeout('putText(' + '"' + arr[2*i+1] + '"' + ')',arr[2*i]);
      }

      function putText(ch)
      { var text=document.getElementById("ausgabe").innerText;
        text=text+ch;
        document.getElementById("ausgabe").innerText=text;
      }

      Es hapert lediglich am CR/LF, aber das krieg ich noch irgendwie hin. Danke für Deine Hilfe. Reko.

      1. Hatte es zwar schon mal mit window.setTimeout() probiert, bekam aber Probleme damit, daß ein "weiter hinten" stehendes Zeichen plötzlich eher ausgegeben wurde als ein "weiter vorn" stehendes. Bin damals überhaupt nicht darauf gekommen, die einzelnen "Zeiten" einfach zu addieren.

        das ist ja auch grober Unfug. Damit erzeugst Du ja zig- oder hunderte von Timern. Du mußt den Timer in der Schleife immer wieder löschen und neu setzen.

        Gruß, Andreas

        --
        SELFFORUM - hier werden Sie geholfen,
        auch in Fragen zu richtiges Deutsch
        1. hi,

          Damit erzeugst Du ja zig- oder hunderte von Timern. Du mußt den Timer in der Schleife immer wieder löschen und neu setzen.

          wieso sollte man einen mit setTimeout() gesetzten timer wieder löschen müssen? der ist doch sowieso abgelaufen, wenn er seine aktion ausgeführt hat ...

          verwechselst du das vielleicht mit timer_intervallen_ über window.setInterval() - die man ja tatsächlich wieder mit clearTimeout() deaktivieren sollte?

          gruß,
          wahsaga

          --
          "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
          1. verwechselst du das vielleicht mit timer_intervallen_ über window.setInterval() - die man ja tatsächlich wieder mit clearTimeout() deaktivieren sollte?

            nein. Er erzeugt in einer rasenden Geschwindigkeit z.B. 100 Timer für 100 Zeichen. Timer 1 führt seine Aktion z.B. in 1 Sekunde aus, timer 2 seine in 2 Sekunden, timer 3 in 3 Sekunden... Wenn jetzt alle Timer in z.B. 0.5 Sekunden erstellt wurden, laufen sie alle parallel, und sterben erst nach und nach ab. Er addiert ja die Zeiten, weil die Timer alle _fast_ zu gleichen Zeit erstellt wurden.

            Gruß, Andreas

            --
            SELFFORUM - hier werden Sie geholfen,
            auch in Fragen zu richtiges Deutsch
        2. Tja, das ist schon wahr, daß ich damit zig Timer erzeuge. Aber ich frage mal so: Ich möchte, sagen wir mal einen Text von 150 Zeichen ausgeben und erzeuge somit 150 Timer auf einen Schlag. Klar. Beeinträchtigt das die Arbeitsweise des Interpreters, Browsers oder der Maschine selbst so stark? Wie stark? Und! wie hoch ist hingegen der Aufwand für die Verwaltung, die einzelnen Timeouts (wie und warum eigentlich?) zu löschen?

          Der reko.

    2. Ups! Die alert-Anweisung gehört natürlich rausgeschmissen! Sie diente nur dazu, das mit dem CR/LF-Bug herauszufinden.

  2. Hi,

    von allem anderen mal abgesehen:

    var out=document.getElementById("ausgabe").innerText;

    innerText ist MS-proprietär, mithin JScript, nicht JavaScript. Soll das nicht nur auf dem IE (und Opera) funktionieren, mußt Du das noch berücksichtigen.

    Gruß, Cybaer

    --
    Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!