Nihtan, der 2.: Will fehlerloses Tutorial verfassen (autom. vergr. Textarea)

hi,
wie ihr vielleicht von meinem letzten Thread wisst, schreibe ich an einer Textarea, die sich automatisch vergrößert.
Da ich im Netz keine bzw. nur gar nicht bis ungenau funktionierende Tutorials gefunden habe und nach einigem Nachjustieren mein Script auch sehr genau geworden ist, dachte ich mir, ich schreib ein Tutorial.
Da ich aber kein vielleicht nicht ganz sauber funktionierendes Script veröffentlichen will, bitte ich euch das Ganze als Experten nochmals durchzusehen; ich hab es zwar auch mehrmals durchgelesen, doch ich habe JS erst diesen Winter gelernt und bin deswegen noch kein Superprofi darin.

Hier mal der JS-Code...:

function addZeile() {  
  var Inhalt = eingabe.value; // In eingabe ist die Textarea gespeichert  
  
  var geteilt = Inhalt.split('\n'); //Jetzt nehme ich mal jeden Absatz  
  var Abstand = 0;  
  var altPos = 0;  
  for(var Zaehler = 0; Zaehler < geteilt.length; Zaehler++) { // Jeder Absatz wird einzeln verarbeitet  
  
    // Da ja, wenn ein Wort zu lang ist, es in die nächste Zeile gerückt wird und der Rest der Zeile leer bleibt, muss der dann leerbleibende Platz auch berechnet werden:  
    var Position = geteilt[Zaehler].indexOf(' ');  
    while(true) {  
      if(parseInt(Position / 60) != parseInt(altPos / 60))  
        Abstand += Math.abs(altPos%60 - 60);  
      altPos = Position;  
      Position++;  
      Position = geteilt[Zaehler].slice(Position).indexOf(' ')+Position; // Es wird nach den nächsten ' ' gesucht und das Ergebnis gleich absolut gemacht.  
      if(Position == altPos) // Wenn es vor dem absolut Machen -1 war, dann wird die Schleife gebrochen.  
        break;  
    }  
    Abstand += Math.abs((geteilt[Zaehler].length-1) % 60 - 60) + geteilt[Zaehler].length-1; // Der Restabstand nach dem Absatz wird berechnet.  
  }  
  
  Abstand = Abstand / 60 * 17 + 28; // durch Zeilenlänge, mal Zeilenhöhe, plus Spatze  
  if(Abstand > 560) // Wenn das Feld zu groß wird, um es zu überblicken (kann man später auch noch mit der innerHeight errechnen)...  
    Abstand = 560; // ... dann bleibt es so.  
  eingabe.style.height = Abstand+'px'; // Da ja die rows-Eigenschaft uneditierbar ist, muss es als Höhe gesetzt werden.  
}

... und hier der HTML-Code:
<textarea name="eingabe" style="width:500px;font-size:14px;" onkeydown="setTimeout('addZeile()',10)">Nihtan, der 2. oder vielleicht auch der 3. (es könnte aber auch der 4. sein) - auf jeden fall Nihtan</textarea>

Danke für jede Antwort.
lg Nihtan

  1. Also bei mir klappts nicht!

  2. hi,

    Danke für jede Antwort.

    Fehler: eingabe is not defined
    Zeile: 3

    var Inhalt = eingabe.value; // In eingabe ist die Textarea gespeichert

    http://dj-tut.de/z_test/selfhtml/scal_form/ -- Bei Wunsch kann ich das gaze sofort Offline nehmen[1]

    mfg
    [1] es sei denn, ich bin auf der Tastatur eingeschlafen ;)

    --
    echo '<pre>'; var_dump($Malcolm_Beck`s); echo '</pre>';
    array(2) {
      ["SELFCODE"]=>
      string(74) "ie:( fl:) br:> va:? ls:? fo:) rl:| n4:# ss:{ de:? js:} ch:? sh:( mo:? zu:("
      ["Meaningful"]=>
      string(?) "Der Sinn des Lebens ist deinem Leben einen Sinn zu geben"
    }
  3. Hi

    Meiner Ansicht nacht gibts da noch einiges zu verbessern:

    1.) onkeydown="setTimeout('addZeile()',10)"
    Ich bevorzuge HTML und JavaScript zu trennen, also kein onkeydown, sondern mit JavaScript dem Element den Event-Handler zuzuweisen.
    Der keydownevent ist hier ungünstig: besser keypress, da dieser nur bei keys ausgelöst wird, die auch ein geschriebenes Zeichen zur Folge haben.
    Wenn du setTimeout einen String mit einer Funktion übergibts, rufst du ein implizites eval() auf. Besser eine anonyme Funktion:
    setTimeout(function(){addZeile();},10)
    Wieso braucht es eigentlich ein setTimeout?

    2.) Es ist üblich, Variabeln klein zu schreiben und am besten halt auf Englisch. Ausserdem sollte vorzugsweise nur ein var pro scope stehen:

      
    var maxHeight = maxHeight || 560,  
    	text = eingabe.value,  
    	lines = text.split('\n'),  
    	space = 0,  
    	altPos = 0,  
    	lineLength = 0,  
    	counter,  
    	position;  
    
    

    Ausserdem habe ich den Wert 560 (für maximale Höhe) als Parameter definiert, da er vom Layout abhängig ist und somit angegeben werden muss.

    3.) Verwende nicht 'name', um auf das Element zuzugreifen. Besser 'id' o.ä.
    Ausserdem würde ich das Element als parameter der Funktion übergeben:

      
    addZeile(document.getElementById('eingabe'));  
    
    

    4.) while (true)
    ersetzen mit
    do {} while (position !== altPos);

    5.) Wie kommt der Wert 60 zustande? Sind das die Anzahl Zeichen pro Zeile? Der dürfte je nach Schriftgrösse und Schriftart ändern. Kann man den nicht dynamisch berechnen?

    6.) eingabe.style.height = abstand+'px'; nur ausführen, wenn sich der Wert tatsächlich ändert.

    7.) http://www.jslint.com/

    Gruss,
    Mathias

    1. Hi,

      Der keydownevent ist hier ungünstig: besser keypress, da dieser nur bei keys ausgelöst wird, die auch ein geschriebenes Zeichen zur Folge haben.

      Löst letzterer bei bspw. [ctrl]+[v] auch aus?

      (Es gibt zwar auch Events, die bei Befüllung eines Feldes per C&P feuern, aber ich weiss nicht, ob das inzwischen "alle" Browser unterstützen.)

      MfG ChrisB

      --
      Light travels faster than sound - that's why most people appear bright until you hear them speak.
    2. Wenn du setTimeout einen String mit einer Funktion übergibts, rufst du ein implizites eval() auf. Besser eine anonyme Funktion:
      setTimeout(function(){addZeile();},10)

      Solange in der anonymen Funktion auch nur eine andere ohne Parameter aufgerufen wird, kann man sie sich den Wrapper sparen und gleich die aufzurufende Funktion übergeben:

      setTimeout(addZeile, 10);

      Mathias