Anzahl der verbleibenden Zeichen anzeigen
Problem
Ihre Firma hat auf ihrer Website eine
Kontaktform. In dieser Form gibt es ein <textarea>
-Element , damit die Anwender Anfragen stellen
können. Aber Sie wissen ja – Zeit ist Geld und Sie wollen nicht,
dass Ihre Mitarbeiter Kurzgeschichten lesen müssen, daher wollen
Sie die Länge der Nachrichten beschränken. Dabei wollen Sie dem
Anwender auch zeigen, wie viele Zeichen er noch eingeben kann:
<textarea></textarea> <div class="remaining">Verbleibende Zeichen: <span class="count">300</span></div>
Lösung
Sprechen Sie alle .remaining
-Elemente an und suchen sie das
zugehörige <textarea>
-Element
und die maximale Zeichenzahl aus dem Kind-Element .count
heraus. Binden Sie an das <textarea>
eine update
-Funktion, um benachrichtigt zu werden, wenn
der Anwender Text eingibt:
// für jedes Element der Art "Verbleibende Zeichen: ###" $('.remaining').each(function(){ // Maximalzahl und Eingabefeld finden und sichern var $count = $('.count',this); var $input = $(this).prev(); // .text() gibt einen Text zurück. Multipliziert mit 1 wird es eine Zahl (für math) var maximumCount = $count.text()*1; // update-Funktion wird für die Events keyup, paste und input aufgerufen var update = function(){ var before = $count.text()*1; var now = maximumCount - $input.val().length; // Prüfen, ob der Anwender die Grenze schon überschritten hat if ( now < 0 ){ var str = $input.val(); $input.val( str.substr(0,maximumCount) ); now = 0; } // DOM nur bei Bedarf aktualisieren if ( before != now ){ $count.text( now ); } }; // Auf Änderungen lauschen (siehe Diskussion) $input.bind('input keyup paste', function(){setTimeout(update,0)} ); // update direkt aufrufen, falls Eingabefeld schon befüllt ist update(); }); // Ende von .each()
Diskussion
Der vorgestellte Code ist generisch genug, um
eine beliebige Zahl von »Verbleibende Zeichen«-Ausgaben und
<textarea>
-Elementen auf einer
Seite betreuen zu können. Das kann nützlich sein, wenn Sie ein CMS
oder eine Dateneingabemaske haben.
Um auch das Kopieren oder Einfügen von Daten in
das <textarea>
per Maus zu
berücksichtigen, müssen wir die Events input
und paste
berücksichtigen. Das Event mouseup
kann nicht verwendet werden, weil es nicht ausgelöst wird, wenn man
einen Eintrag aus dem Kontextmenü des Browsers wählt. Das Event
input
ist Teil von HTML5 (Working
Draft) und schon durch Firefox, Opera und Safari implementiert. Es
wird bei einer Benutzereingabe ausgelöst – unabhängig vom
verwendeten Eingabegeräte (Maus oder Tastatur). Safari hat zum
Zeitpunkt der Entstehung dieses Buches einen Bug, durch den das
input
-Event bei <textarea>
-Elementen nicht ausgelöst wird.
Sowohl Safari als auch der Internet Explorer kennen das Event
paste
für <textarea>
-Elemente und keyup
, um Tastenaktionen abzufangen. Bindet man
keyup
, input
und paste
, ist
das zwar redundant, aber in diesem Fall hilfreich. Die Funktion
update
ist so einfach, dass sie keine
Performance-Probleme hervorruft, und sie passt das DOM nur dann an,
wenn es notwendig ist. Es gibt also keinen Ärger durch Redundante
Aufrufe von update
.
Eine Alternative zu redundanten Events wäre das
Verwenden von setInterval
, solange das
<textarea>
-Element den Fokus
besitzt. Die gleiche Funktion update
könnte in regelmäßigen Zeitabständen aufgerufen werden. Kombiniert
mit dem Event keyup
würden Sie beim
Tippen eine direkte Reaktion erhalten und mit einem passenden
Aktualisierungs-Intervall – vielleicht so 300 Millisekunden – würde
auch nach einem Einfügen eine Reaktion erfolgen. Ist die
update
-Funktion komplexer oder teurer,
dann kann das der bessere Weg sein.
Bindet man Events an Form-Elemente, ist es
manchmal wichtig, einen Timeout zu nutzen, um einen Funktionsaufruf
ein bisschen zu verzögern. Im vorherigen Beispiel löst der Internet
Explorer das paste
-Event aus, bevor
der Text aus der Zwischenablage tatsächlich im <textarea>
-Element eingefügt wird. Dadurch
würde die Berechnung der verbleibenden Zeichen falsch sein, bis der
Anwender klickt oder eine Taste drückt. Durch setTimeout(update,0)
wird die Funktion
update
an das Ende des Call Stacks
verschoben und erst ausgelöst, nachdem der Browser den Text
hinzugefügt hat:
$input.bind('input keyup paste', function(){setTimeout(update,0)} );
Was geschieht, wenn JavaScript abgeschaltet ist? Sie sollten den Bereich »Verbleibende Zeichen« standardmäßig per CSS verbergen. Mit JavaScript fügen Sie dann einem Eltern-Element einen Klassennamen hinzu, der die CSS-Regel überschreibt. Es ist zudem wichtig, die Länge der Nachricht auf dem Server zusätzlich zu kontrollieren:
<style type="text/css" title="text/css"> .remaining { display:none; } .jsEnabled .remaining { display:block; } </style> ... // wenn das HTML-DOM bereit ist $(document).ready(function(){ $('form').addClass('jsEnabled'); });