JavaScript

Textfeld mit BBCodes ausstatten (JavaScript Tutorial)

Tutorial erstellt von Ingo, letzte Änderung am 16.06.2008

Wer in einem Forum wie zum Beispiel hier bei der-webdesigner.net einen Beitrag schreibt, nutzt dafür ein Formular, in dessen Mitte ein großes Textfeld steht. Das ist soweit nichts Besonderes, es handelt sich üblicherweise um ein <textarea>-Element, das auch ganz ohne JavaScript funktioniert. Aber meist halten diese Textfelder noch Buttons für Schriftformatierung, Smilies oder die logische Auszeichnung von Codeblöcken oder Zitaten bereit. Sehr nützlich - man stelle sich zum Beispiel ein Board ohne Smilies vor ;o).

In diesem Tutorial also sollen um ein <textarea>-Element herum ein paar nützliche Funktionen eingebaut werden, und zwar möglichst so, dass das Formular insgesamt auch ohne JavaScript brauchbar bleibt - wir wollen die Nutzerfreundlichkeit erhöhen, ohne dadurch Teile der Nutzerschaft auszuschließen. Das Ergebnis könnte dann (ähnlich wie hier im Forum) so aussehen:



Weil dieses Tutorial selbst mit BBCs formatiert ist, mussten im Text, besonders auch im Quellcode alle BBCs mit Leerzeichen versehen werden, damit diese nicht fälschlich vom "Tutorialsystem" in HTML gewandelt werden. Bitte beim Ausprobieren des Codes diese Leerzeichen [_b] entfernen.

Zum Konzept

Bei der Programmierung solcher Erweiterungen ergeben sich zwei Probleme:
  1. Man möchte nicht, dass die Nutzer beliebigen HTML-Code einfügen können.
  2. Die statt HTML verwendeten BBCodes müssen irgendwie in den Textfeld-Inhalt eingefügt werden. Hierfür gibt es einen IE-Weg und einen Gecko-Weg...


BBC (Bulletin Board Code) - kein HTML


Man stelle sich vor, was passiert, wenn jemand in bester Laune seinen Beitrag in ein unschuldiges <span style="font-size:5000px;">...</span> einfasst oder aber mit
einer gezielten JavaScript-Anweisung einfach den <body> verschwinden läßt. Stattdessen bekommt der Nutzer eine Auswahl an BBCodes an die Hand. HTML-Tags werden dagegen spätestens bei der serverseitigen Auswertung mit PHP unschädlich gemacht.

Die in diesem Tutorial verwendeten BBCodes umfassen (je ohne Leerzeichen)
Code:

[ b][ /b], [ i][ /i], [ u][ /u],
[ quote][ /quote],[ code][ /code],
[ list][ /list], [ list=1][ /list], [ list=a][ /list], [ *],
[ img][ /img]  gedacht als [ img]url[  /img],
[ url][ /url]  gedacht als [ url=Adresse]Beschreibung[ /url],
[ size=8/10/12][ /size],
[ color=rgb(n,n,n)][ /color],
Dazu die Smilies : lol:, : cool:, : thumb:, : mrgreen:, : eek:


BBCodes einfügen - 2 Wege

Nun ist es ein Leichtes, einfach einen BBCode an den Inhalt eines Textfeldes anzuhängen. Die value-Eigenschaft einer <textarea> beinhaltet deren kompletten Text. Und auf "value" kann man lesend, aber auch schreibend zugreifen. Oft möchte man aber etwas mitten im Text einfügen, also eine Textportion markieren und dann in BBC-Tags einschließen oder einfach einen Smiley an der Cursorposition einfügen. Nur: wo fängt die Auswahl an, wo hört sie auf?
Für den Zugriff auf die Textauswahl eines <textarea>-Elements gibt es zwei verschiedene Konzepte:
  • In Gecko-Browsern (Firefox u.a.) nutzen wir einfach die Eigenschaften meinTextfeld.selectionStart und meinTextfeld.selectionEnd. Sie liefern zu einer Auswahl die Zeichenposition des ersten und letzen ausgewählten Zeichens. - Um nach dem Einfügen die Cursorposition anzupassen, weist man dann selectionStart/End entsprechende Werte zu.
  • In IE-Browsern erzeugen wir mittels document.createRange() ein TextRange-Objekt. Dessen text-Eigenschaft beinhaltet den ausgewählten Text, Änderungen daran wirken direkt auf das Textfeld. - Zur Korrektur der Cursorposition stehen die Methoden meinTextRange.move(), .moveStart() und .moveEnd() zur Verfügung.




Das Skript im Detail

Im HTML stehen in den Button-Tags, Auswahllisten etc. Eventhandler wie

Code:
<button type="button" onclick="insertText('[ b]','[ /b]')" title="[ b][ /b]"><b>b</b></button>

<select size="1" onchange="insertProperty('size',this.value); ...


Im Kern besteht das Script dann aus folgenden vier Funktionen insertIE(), insertGecko(), insertText() und insertProperty().
Weil es zwei Konzepte für den Textfeld-Zugriff gibt, gibt es mit insertIE() und insertGecko() auch zwei Funktionen, die das eigentliche Einfügen erledigen. Die Funktion insertText() entscheidet vorab, welches Konzept gefragt ist und ruft dementsprechend insertIE() bzw. insertGecko().
Die Funktion insertProperty() ist hier eine praktische "Vorschaltfunktion": sie formt aus 2 Angaben einen BBCode und ruft dann insertText(). Zum Beispiel fügt insertProperty('size',2) letztlich den BBCode [ size=2][ /size] ein.



insertProperty()


Code:
function insertProperty(prop,val)
{
  insertText('[' + prop + '=' + val + ']', '[\/' + prop + ']');
}

Wie erwähnt, resultiert aus dem Aufruf insertProperty('size',2) der Aufruf insertText('[ size=2]', '[\/size]'). - Man beachte: JavaScript verlangt innerhalb von Strings die Maskierung des Slash / mit \.

insertText()

Code:
// IE/Gecko-Weiche zum Einfügen von Text ins Textfeld
function insertText(vor, nach)
{
  var textfeld = document.getElementById(idTextfeld);
  textfeld.focus();                                         // falls Cursor außerhalb war

  if(typeof document.selection != 'undefined')              // für IE, auch Opera
  {
    insertIE(textfeld, vor, nach);
  }
  else if (typeof textfeld.selectionStart != 'undefined')   // Geckos (FF)
  {
    insertGecko(textfeld, vor, nach);
  }
}

Abfragen wie if(typeof document.selection != 'undefined') erkundigen sich danach, ob ein bestimmtes Objekt existiert. Der typeof-Operator gibt dabei einen String als Antwort. Falls document.selection definiert ist, handelt es sich um einen IE-Browser und man nutzt den IE-Weg zum eigentlichen Einfügen. Ist hingegen für die <textarea> die Eigenschaft selectionStart definiert, nutzt man eben diesen Mechanismus. Beiden insert-Funktionen übergibt man das <textarea>-Element und die vor bzw. nach der Auswahl einzufügenden Strings.

insertIE()

Code:
  // Im "textfeld" Portionen "vor" und "nach" einfügen (IE)
function insertIE(textfeld, vor, nach)
{
  if(!rangeIE) rangeIE = document.selection.createRange();

  // nichts weiter tun, falls wir nicht im Textfeld sind
  if(rangeIE.parentElement().id != idTextfeld) { rangeIE = null; return; }

  var alterText = rangeIE.text;

  // Auswahl um BBC ergänzen
  rangeIE.text = vor + alterText + nach;

  // Cursor neu setzen (wie SelfHTML)
  if (alterText.length == 0)
    rangeIE.move('character', -nach.length);
  else
    rangeIE.moveStart('character', rangeIE.text.length);

  rangeIE.select();
  rangeIE = null;
}

Der schwierigere "Patient" ist hier der IE. Wie angedeutet, beschaffen wir uns zunächst die aktuelle Textauswahl in Form eines TextRange-Objekts, und zwar mit document.selection.createRange(). Im IE ist die Auswahl eine Eigenschaft des gesamten Dokuments (es heißt ja document.selection). Bevor wir diese Auswahl verändern, müssen wir sicherstellen, dass sie sich auch im Textfeld befindet, daher die Abfrage des rangeIE.parentElement(), also des Elementes, in dem die Auswahl liegt. Wenn dessen ID nicht die ID unseres Textfeldes ist, verlassen wir die Funktion ohne weitere Aktion.

Mit rangeIE.text haben wir direkten Zugriff auf die Auswahl, Änderungen wirken sofort. Wir müssen im Anschluss nur noch den Cursor an eine passende Stelle verschieben: Wenn nichts markiert war (nur der Cursor im Text), verschieben wir die Grenzen der Auswahl in die Mitte zwischen "vor" und "nach". Andernfalls setzen wir den Cursor hinter "nach". Die Funktion "move()" zieht den Range auf Länge 0 zusammen und verschiebt ihn gemäß dem zweiten Argument.
rangeIE.select() bewirkt, dass bei mehrfachem Einfügen (erst Smiley, dann Farbe ..) das Textfeld den Fokus behält und die Auswahl erhalten bleibt.- Zur ersten und letzen Zeile vergleiche unten "Farbwähler".

insertGecko()

Code:
// Im "textfeld" Portionen "vor" und "nach" einfügen (Geckos)
function insertGecko(textfeld, vor, nach)
{
  von = textfeld.selectionStart;            // liefert Zeichenposition
  bis = textfeld.selectionEnd;              //

  // Text zerlegen
  anfang = textfeld.value.slice(0,   von);
  mitte  = textfeld.value.slice(von, bis);
  ende   = textfeld.value.slice(bis);        // der Rest des Strings

  // BBC einfügen und ins Textfeld schreiben
  textfeld.value = anfang + vor + mitte + nach + ende;

  // Cursor neu setzen
  if(bis - von == 0)
  {
    textfeld.selectionStart = von + vor.length;
    textfeld.selectionEnd   = textfeld.selectionStart;
  }
  else
  {
    textfeld.selectionEnd   = bis + vor.length + nach.length;
    textfeld.selectionStart = textfeld.selectionEnd;
  }
};

Die Strategie bei Gecko-Browsern sieht etwas anders aus: Man beschafft sich die Zeichenpositionen von Auswahlanfang und -ende, zerlegt mit Hilfe von slice() den Inhalt (value) des Textfeldes, schiebt "vor" und "nach" ein und weist den verlängerten String wieder dem textfeld.value zu. - Die Cursorposition wird ähnlich wie beim IE angepasst, hier aber einfach dadurch, dass man selectionStart und selectionEnd neue Werte zuweist. - Ein zusätzliches Erneuern des Fokus' am Ende ist hier nicht nötig.

Zwischenstopp

Damit steht das Textfeld mit allen Buttons, inklusive der Smilies. Spätestens jetzt ist es Zeit, den Quelltext (unten eine komplettes Version) selbst noch einmal in Augenschein zu nehmen, HTML und JavaScript. - Etwas fehlt allerdings noch ...

Der Farbwähler - ein hübscher Zusatz

Natürlich könnte man für die Auswahl der Schriftfarbe auch einfach wie bei der Schriftgröße eine <select>-Box einbauen. Und ob ein Nutzer nun wirklich nur dann glücklich wird, wenn er nicht weniger als 125 Farben zur Wahl hat - nun ja. Aber einfach weil es in Reichweite ist und ein interessantes Problem mit sich bringt, sei er hier eingebaut - der Farbwähler.
Der Farbwähler (engl. color picker) besteht aus einer Tabelle, deren Zellen je eine bestimmte Hintergrundfarbe haben.

pickBgColor()

Bei Klick auf eine Zelle, die zu diesem Zweck mit dem Eventhandler onclick="pickBgColor(this)" ausgestattet ist, wird deren Hintergrundfarbe ausgelesen und mit insertProperty() als color-Tag ins Textfeld geschrieben:  

Code:
function pickBgColor(elem)
{
  insertProperty('color', elem.style.backgroundColor);
}

generateColorTable()

Erzeugt wird die Tabelle bei Klick auf den Farbwähler-Button, der im 'toggle'-Betrieb arbeitet: Wenn es die Tabelle schon gibt, löschen wir sie und verlassen die Funktion:

Code:
function generateColorTable(idContainer)
{
  if(document.getElementById(idColorpicker))
  {
    document.getElementById(idContainer).innerHTML = ''; return;
  }

Wir bauen die Tabelle nun zunächst in Form eines Strings strTabelle zusammen. Dazu durchlaufen wir eine 3-stufige for-Schleife für Rot, Grün und Blau. Zwischendurch fügen wir <tr>- und <td>-Tags ein, so dass die Tabelle aus 5 Zeile zu je 25 Feldern besteht:

Code:
  var strTabelle = '<table id="'+idColorpicker+'" cellspacing="0">'+"\n";

  // Eine 3-fache for-Schleife durch den RGB-Farbraum:
  for(var r=0; r<257; r+=64)
  {
    strTabelle += "<tr>\n";

    for(var g=0; g<257; g+=64)
      for(var b=0; b<257; b+=64)
        strTabelle += '<td style="background:rgb('+r+','+g+','+b+')" '
                    + 'onclick="pickBgColor(this)" '
                    + 'onmousedown="getSelectionIE()"><\/td>'+"\n";
      
      strTabelle += "<\/tr>\n";
   }

   strTabelle += "<\/table>\n";

Die Tabellenzellen bekommen als Eventhandler natürlich noch onclick="pickBgColor(this)" mit auf den Weg. - Zum Schluss hängen wir die Tabelle als "innerHTML" in das dafür vorgesehene, anfangs leere Container-Div:

Code:
  document.getElementById(idContainer).innerHTML += strTabelle;  
}


getSelectionIE() -  "onmousedown" gibt's Gedächtnishilfe

Fast fertig. Fast. Wenn man Text auswählt und dann in die Tabelle klickt, hat der IE offenbar die Auswahl im Textfeld bereits gelöscht. Ein onclick besteht aus onmousedown und onmouseup, erst dann ist das onclick-Ereignis komplett. Bei onmousedown gibt's die Auswahl (meist) noch; also liegt es nahe, sich diese noch vorhandene Auswahl in einer Variablen rangeIE zu merken. Dies geschieht mittels der Funktion getSelectionIE():

Code:
  // Im IE die Textauswahl merken (onMouseDown im Farbwähler)
  function getSelectionIE()
  {
    if (document.selection)        // nur im IE
    {
      document.getElementById(idTextfeld).focus();
      rangeIE = document.selection.createRange();    // Auswahl merken
    }
  }

Deswegen dann auch der Vorspann in insertIE():

Code:
if(!rangeIE) rangeIE = document.selection.createRange();

Wenn der rangeIE schon vorher beim Klick auf die Tabelle gesetzt wurde, nutzen wir die darin gespeicherte Auswahl; ansonsten holt man sich an Ort und Stelle eine "frische" Auswahl. Vor jedem Verlassen der Funktion insertIE() muss dann rangeIE = null gesetzt werden, damit die ja inzwischen veraltete Auswahl beim nächsten Mal nicht wieder benutzt wird. - Das "rangeIE = null" löscht übrigens nicht die Auswahl im Textfeld; rangeIE stellt nur eine Referenz auf diesen Bereich dar.

Fertig.

So, jetzt aber. Das Textfeld ist so natürlich nur ein Vorschlag, man kann Buttons dazusetzen oder auch den Farbwähler 'rauswerfen und dafür eine <select>-Liste wie für die Schriftgröße einbauen. Das macht den Code einfacher ;o) Die Smiley-Riege könnte auch noch aufgestockt werden, aber naja, für unsere Zwecke hier hat's gereicht. - Ohne JavaScript ist der Nutzer übrigens nicht verloren: Zwar funktionieren die BBC-Buttons nicht (die Submit-Buttons schon), aber wenn man alle BBC-Buttons so wie im Beispiel unten mit title-Tags ausstattet, ist der Nutzer dennoch informiert, welcher BBCode wofür da ist.

Und weiter? - Bastis PHP-Tutorial zum Thema

Wer nun wissen will, wie man die BBCodes serverseitig, also etwa mit PHP, wieder in HTML übersetzt, für den ist Bastis Tutorial zum Thema BBC mit Regulären Ausdrücken  umwandeln genau richtig. Reguläre Ausdrücke bieten die nötige Flexibilität, um eine große Anzahl von BBCodes mit wenig Aufwand zu erkennen und durch HTML-Code zu ersetzen. - Lesenswert! Auch und gerade, wenn ihr über Reguläre Ausdrücke noch wenig wisst.

Auf bald, Ingo :)


Ach ja, der komplette Code, hier HTML, CSS und JavaScript, alles in einer Datei, ausgenommen natürlich die Bilder (Smilies und der Button-Hintergrund):
Code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
  <title>BBC-Textfeld</title>
  <meta http-equiv="content-type" content="text/html;charset=ISO-8859-1" />
  <meta http-equiv="Content-Style-Type" content="text/css" />

  <style type="text/css">
  /* <![CDATA[ */
  #cpcontainer { height:56px; padding:5px; }

  #colorpicker       { border:2px ridge #dddddd; margin:auto; }
  #colorpicker td  { width:10px; height:10px; cursor:pointer; }
  #colorpicker td:hover  { width:8px; border:1px solid white; }
  
  #beitrag
  { width:650px;
    overflow:visible;
    padding:5px;
    background:#f8f8f8;
    position:relative;
  }
  #beitrag button
  { padding:1px 4px;
    background:url(button_grau.jpg) 0px center;
    border:1px solid #aaaaaa;
    cursor:pointer;
  }
  #beitrag select        { margin:0px 3px; }
  #beitrag textarea      { display:block; margin:5px auto; width:100%; }
  #beitrag div.center    { text-align:center; }
  #beitrag img           { border:none; }
  #beitrag #buttonleiste { white-space:nowrap; }
  #beitrag #smilies      { position:absolute; right:5px; }

  /* Speziell für den IE < 7 */
  * html #beitrag #schriftbutton { width:10em; }
  * html #beitrag button     { margin:0px 1px; }
  * html #beitrag select  { margin-bottom:0px; }

  /* ]]> */
  </style>

  <script type="text/javascript">
  /* <![CDATA[ */

  var idTextfeld    = 'nachricht';       // ID der <textarea>
  var idColorpicker = 'colorpicker';     // ID der Tabelle

  var rangeIE = null;

  function insertProperty(prop,val)
  {
    insertText('[' + prop + '=' + val + ']', '[\/' + prop + ']');
  }

  // IE/Gecko-Weiche zum Einfügen von Text ins Textfeld
  function insertText(vor, nach)
  {
     var textfeld = document.getElementById(idTextfeld);
     textfeld.focus();                                         // falls Cursor außerhalb war

     if(typeof document.selection != 'undefined')              // für IE, auch Opera
     {
       insertIE(textfeld, vor, nach);
     }
     else if (typeof textfeld.selectionStart != 'undefined')   // Geckos (FF)
     {
       insertGecko(textfeld, vor, nach);
     }
  }

  // Im "textfeld" Portionen "vor" und "nach" einfügen (IE)
  function insertIE(textfeld, vor, nach)
  {
     if(!rangeIE) rangeIE = document.selection.createRange();

     // nichts weiter tun, falls wir nicht im Textfeld sind
     if(rangeIE.parentElement().id != idTextfeld) { rangeIE = null; return; }

     var alterText = rangeIE.text;

     // Auswahl um BBC ergänzen
     rangeIE.text = vor + alterText + nach;

     // Cursor neu setzen (wie SelfHTML)
     if (alterText.length == 0)
       rangeIE.move('character', -nach.length);
     else
       rangeIE.moveStart('character', rangeIE.text.length);
    
     rangeIE.select();
     rangeIE = null;
  }

  // Im "textfeld" Portionen "vor" und "nach" einfügen (Geckos)
  function insertGecko(textfeld, vor, nach)
  {
     von = textfeld.selectionStart;
     bis = textfeld.selectionEnd;

     // Text zerlegen
     anfang = textfeld.value.slice(0,   von);
     mitte  = textfeld.value.slice(von, bis);
     ende   = textfeld.value.slice(bis);        // der Rest des Strings

     // BBC einfügen und ins Textfeld schreiben
     textfeld.value = anfang + vor + mitte + nach + ende;

     // Cursor neu setzen
     if(bis - von == 0)
     {
       textfeld.selectionStart = von + vor.length;
       textfeld.selectionEnd   = textfeld.selectionStart;
     }
     else
     {
       textfeld.selectionEnd   = bis + vor.length + nach.length;
       textfeld.selectionStart = textfeld.selectionEnd;
     }
  };

  // Im IE die Textauswahl merken (onMouseDown im Farbwähler)
  function getSelectionIE()
  {
    if (document.selection)
    {
      document.getElementById(idTextfeld).focus();
      rangeIE = document.selection.createRange();
    }
  }

  /* ========= Ab hier: Farbwähler =================================== */

  // Farbtabelle erzeugen und in Container-Div schreiben bzw. Tabelle löschen
  function generateColorTable(idContainer)
  {
    if(document.getElementById(idColorpicker))
    {
      document.getElementById(idContainer).innerHTML = ''; return;
    }

    var strTabelle = '<table id="'+idColorpicker+'" cellspacing="0">'+"\n";

    // Eine 3-fache for-Schleife durch den RGB-Farbraum:
    for(var r=0; r<257; r+=64)
    {
      strTabelle += "<tr>\n";

      for(var g=0; g<257; g+=64)
        for(var b=0; b<257; b+=64)
           strTabelle += '<td style="background:rgb('+r+','+g+','+b+')" '
                         + 'onclick="pickBgColor(this)" '
                         + 'onmousedown="getSelectionIE()"><\/td>'+"\n";

      strTabelle += "<\/tr>\n";
    }

    strTabelle += "<\/table>\n";

    document.getElementById(idContainer).innerHTML += strTabelle;    // "+=", ggf. "="
  }

  // Hintergrundfarbe des <td>-Elements auslesen und als [color=..] einfügen
  function pickBgColor(elem)
  {
    insertProperty('color', elem.style.backgroundColor);
  }
  
  /* ]]> */
  </script>
</head>
<body>

<form action="beitrag.php" method="post" accept-charset="utf-8" name="beitrag" id="beitrag">

  <div id="smilies">
    <img src="images/icon_lol.gif" onclick="insertText(' :lol: ','')" alt=":lol:" title=":lol:" />
    <img src="images/icon_cool.gif" onclick="insertText(' :cool: ','')" alt=":cool:" title=":cool:" />
    <img src="images/thumbup.gif" onclick="insertText(' :thumb: ','')" alt=":thumb:" title=":thumb:" />
    <img src="images/icon_mrgreen.gif" onclick="insertText(' :mrgreen: ','')" alt=":mrgreen:" title=":mrgreen:" />
    <img src="images/icon_eek.gif" onclick="insertText(' :eek: ','')" alt=":eek:" title=":eek:" />
  </div>

  <div id="cpcontainer"></div>

  <div id="buttonleiste">
    <button type="button" onclick="insertText('[ b]','[ /b]')" title="[ b][ /b]"><b>b</b></button>
    <button type="button" onclick="insertText('[ i]','[ /i]')" title="[ i][ /i]"><i>i</i></button>
    <button type="button" onclick="insertText('[ u]','[ /u]')" title="[ u][ /u]"><u>u</u></button>
    <button type="button" onclick="insertText('[ quote]','[ /quote]')" title="[ quote][ /quote]">quote</button>
    <button type="button" onclick="insertText('[ code]','[ /code]')" title="[ code][ /code]">code</button>
    <button type="button" onclick="insertText('[ list]','[ /list]')" title="[ list][ /list]">list</button>
    <button type="button" onclick="insertText('[ list=]','[ /list]')" title="[ list=1 oder a][ /list]">list=</button>
    <button type="button" onclick="insertText('[ *]','')" title="[ *] Listeneintrag">[ *]</button>
    <button type="button" onclick="insertText('[ img]','[ /img]')" title="[ img]URL[ /img]">img</button>
    <button type="button" onclick="insertText('[ url]','[ /url]')" title="[ url=Adresse]Beschreibung[ /url]">url</button>

    <!-- <select size="1" onchange="insertProperty('color',this.value); this.selectedIndex=0;">
      <option value="rgb(0,0,0)">schwarz&nbsp;&nbsp;</option>
      <option value="rgb(255,0,0)">rot</option>
      <option value="rgb(0,255,0)">grün</option>
      <option value="rgb(0,0,255)">blau</option>
    </select> -->

    <select size="1" onchange="insertProperty('size',this.value); this.selectedIndex=0;">
      <option value="10" title="[ size=10][ /size]">normal</option>
      <option value="8" title="[ size=8][ /size]">small</option>
      <option value="12" title="[ size=12][ /size]">big</option>
    </select>

    <button type="button" onclick="generateColorTable('cpcontainer')" id="schriftbutton">
      Farbwähler ein/aus
    </button>
  </div>  <!-- #buttonleiste -->

  <textarea cols="70" rows="14" name="nachricht" id="nachricht"></textarea>

  <div class="center">
    <input type="submit" name="speichern" id="speichern" value="Speichern" />
    <input type="submit" name="vorschau" id="vorschau" value="Vorschau" />
    <input type="submit" name="absenden" id="absenden" value="Absenden" />
  </div>

</form>
<span style="color:red">Bitte im Quelltext (HTML) die Leerzeichen aus den BBCs entfernen! Sie stehen meist direkt hinter der [-Klammer.</span>
</body>
</html>



>> Allgemeine Fragen oder Probleme mit dem Tutorial? Hier gehts zum Forum!

Impressum / Datenschutzerklärung          © der-Webdesigner.net 2002 - 2008           top ▲