BBCode-Buttons und jCaret

BBCode-Buttons und jCaret
Von Lars Ebert am 13.10.10, 22:37
Kategorien: jQuery and Tipps

Bei vielen Foren gibt es über dem Textfeld, in dem man einen Beitrag verfasst, eine Buttonbar, mit der automatisch BBCodes in den Text eingefügt werden können. Ich habe lange gesucht, wie man so etwas am Besten machen kann. Und bis vor kurzem war das Beste, was ging, den Code an das Ende des Textfeldes zu hängen. Sehr unpraktisch! Ich wollte eigentlich, dass sich zum Beispiel der BBCode [b] direkt um den Text legt, der in dem Textfeld ausgewählt ist. Aber das schien unmöglich.

Doch das Wunderwerkzeug jQuery lieferte mir, wie immer, alle Werkzeuge an die Hand, die ich dafür brauchte. Ich stieß per Zufall auf das Plugin jCaret. Was macht dieses Plugin? Im Grunde kann man, einfach gesagt, die Auswahlposition in einem Textfeld auslesen. Naja, jCaret kann noch ein bisschen mehr, aber dies war für mich das Wichtigste.

Beginnen wir mit folgendem HTML-Code:


<button id="bold">F</button>
<textarea id="field"></textarea>

Um jetzt bei einem Klick auf den F-Button den in dem Textfeld markierten Text mit [b] und [/b] zu umschließen, muss ich als erstes ein Click-Event an den Button binden:


$("#bold").click(function() {

}

In dieser Funktion frage ich als erstes die Auswahl in dem Textfeld ab:


var range = $("#field").caret();

Als nächstes speichere ich in zwei Variablen meine gewünschten Tags:


var starttag = "[b]";
var endtag = "[/b]";

Nun umschließe ich den Text mit den Tags. Dazu benutze ich substr():


var text = $("#field").val();
$("#field").val(text.substr(0, range.start) + starttag + text.substr(range.start, range.end-range.start) + endtag + text.substr(range.end));

Die Eigenschaften range.start und range.end liefern mir die Nummer des Zeichens, bei dem die Auswahl startet beziehungsweise endet. So kann ich bequem den Text vor, in und nach der Auswahl ermitteln.

Doch wo soll jetzt der Textcursor des Users platziert werden? Für mich schien die Regelung am sinnvollsten, das wenn Text ausgewählt war, der Textcursor hinter den Endtag gesetzt wird. So kann der Nutzer sofort weiter schreiben. Wenn aber kein Text ausgewählt war, muss der BBCode noch mit Inhalt gefüllt werden. Der Textcursor sollte zwischen Start- und Endtag gesetzt werden.

Um festzustellen, ob Text markiert war, müssen nur range.start und range.end verglichen werden. Ist range.end größer als range.start, war etwas markiert, wenn nicht, was der Cursor bloß an einer Position im Text. So setzte ich jetzt, nach der Fallunterscheidung, den Textcursor an die richtige Stelle im Textfeld:


if(range.start < range.end)
{
	$("#field").caret(range.end + starttag.length + endtag.length, range.end + starttag.length + endtag.length);
}
else
{
	$("#field").caret(range.start + starttag.length, range.start + starttag.length);
}

So einfach kann man mit dem jCaret-Plugin Zeichen in ein Textfeld an die Cursorposition einfügen.

Wie findet ihr dieses Plugin? Standet ihr schon einmal vor einem ähnlichen Problem? Teilt uns eure Erfahrungen in den Kommentaren mit!