Erneut möchte ich ein Auszug JavaScript-Code teilen, mit dem ich ein wenig mehr Zeit verbracht habe und der auch für andere nützlich sein könnte.
Aufgabenstellung war es ein Textfeld in einem HTML-Formular (<textarea>) so zu beschränken, dass nur eine bestimmte Anzahl an Zeichen und Zeilen eingegeben werden können.
Mit dem normalen Attributen ist das nicht möglich und auch mit einem JavaScript-Wrapper hat man seine liebe Müh. Primär deshalb, weil der Internet Explorer mal wieder eine Extrawurst möchte (fairerweise sei angemerkt: Opera auch… )
Mein Ansatz sah vor, einfach die bereits eingegebenen Zeichen der Reihe nach zu durchlaufen und jeweils zu prüfen, ob schon die maximale Anzahl an Zeichen/Zeilen überhaupt oder die Anzahl Zeichen pro Zeile erreicht war. Gegebenenfalls wurde ein Hinweistext gezeigt oder es wurden Zeilenumbrüche eingefügt.
Problem: Ein Zeilenumbruch wird beim IE und Opera unter Windows intern als „%0D%0A“ kodiert. Das macht das Ganze etwas aufwendiger. Und man muss erst mal drauf kommen… :-/
Quellcode HTML:
<html> <head> <script language="JavaScript" type="text/javascript" src="js/textarea.js">/* nicht leer */</script> <script language="JavaScript" type="text/javascript" src="js/utils.js">/* nicht leer */</script> </head> <body onload="init()"> <textarea id="greetingText" rows="8" cols="63"></textarea> </body> </html>
Quellcode JavaScript:
isMSIE = /*@cc_on!@*/false;
function init(){
var textarea = new LimitedTextArea("greetingText", 5, 60);
textarea.addEventHandler();
}
function LimitedTextArea(id, maxLines, maxCharsPerLine){
this.textArea = document.getElementById(id);
this.maxLines = maxLines;
this.maxCharsPerLine = maxCharsPerLine;
this.maxChars = (maxCharsPerLine * maxLines) + (maxLines-1);
}
LimitedTextArea.prototype.limitInput = function(evt){
if(!evt){evt = window.event}
if(this.isSpecialKey(evt)){
return;
}
if(this.isOverMaxLines() || this.isOverMaxChars()){
this.showMessage("Bitte nicht mehr als "+this.maxCharsPerLine*this.maxLines+" Zeichen und \nnicht mehr als "+this.maxLines+" Zeilen verwenden");
}
if(isMSIE){this.cropForIE()}
else{this.crop();}
}
/**
* works fine in FF 3, Safari 3.1, Chrome/Iron...
* NOT WOKRING in IE <=7, Opera 9.52, because \n is internally encoded as %0D%0A
*/
LimitedTextArea.prototype.crop = function(){
var text = this.textArea.value+"";
var currentLine = 1;
var currentCharsInLine = 0;
var temp = "";
for(var i=0; i<text.length; i++) {
var ch = text.charAt(i);
if(ch == "\n"){
if(currentLine+1 > this.maxLines){
this.textArea.value = temp;
return;
}
temp += ch;
currentLine++;
currentCharsInLine = 0;
}
else{
if(currentCharsInLine+1 > this.maxCharsPerLine){
if(currentLine+1 > this.maxLines){
this.textArea.value = temp;
return;
}
temp += "\n";
temp += ch;
currentLine++;
currentCharsInLine = 1;
}
else{
temp += ch;
currentCharsInLine++;
}
}
}
this.textArea.value = temp;
}
LimitedTextArea.prototype.cropForIE = function(){
var text = this.textArea.value+"";
var currentLine = 1;
var currentCharsInLine = 0;
var temp = "";
for(var i=0; i<text.length; i++) {
var ch = text.charAt(i);
if(ch == "\r"){
if(text.charAt(i+1) == "\n"){
i++;
continue;
}
if(currentLine+1 > this.maxLines){
this.textArea.value = temp;
return;
}
temp += ch;
currentLine++;
currentCharsInLine = 0;
}
else{
if(currentCharsInLine+1 > this.maxCharsPerLine){
if(currentLine+1 > this.maxLines){
this.textArea.value = temp;
return;
}
temp += "\n";
temp += ch;
currentLine++;
currentCharsInLine = 1;
}
else{
temp += ch;
currentCharsInLine++;
}
}
}
this.textArea.value = temp;
document.getElementById("debug").innerText = currentCharsInLine+" "+this.getCharCount()+" "+this.maxChars;
}
/**
* sehr bloede funktion, aber es gibt leider keinen eleganten weg...
*/
LimitedTextArea.prototype.isSpecialKey = function(evt){
var test = evt.keyCode;
if(test == 8 || test == 13 || test == 16 || test == 17 || test == 18 ||
test == 20 || test == 27 || test == 33 || test == 34 || test == 35 ||
test == 36 || test == 37 || test == 38 || test == 39 || test == 40 ||
test == 45 || test == 46 ){
return true;
}
return false;
}
LimitedTextArea.prototype.isOverMaxLines = function(){
if(this.getLineCount() > this.maxLines){
return true;
}
return false;
}
LimitedTextArea.prototype.isOverMaxChars = function(){
if(isMSIE){
var tempCharCount = this.getCharCount()-4;
}
else{
var tempCharCount = this.getCharCount();
}
if(tempCharCount >= this.maxChars){
return true;
}
return false;
}
LimitedTextArea.prototype.getLineCount = function(){
var input = this.textArea.value;
var lineCount = 1; // keine "nullte" zeile!
for(var i=0; i<input.length; i++) {
if(input.charAt(i) == "\n"){
lineCount++;
}
}
return lineCount;
}
LimitedTextArea.prototype.getCharCount = function(){
return this.textArea.value.length;
}
LimitedTextArea.prototype.addEventHandler = function(){
var me = this;
if(me.textArea.addEventListener) {
me.textArea.addEventListener("keyup", function(event){me.limitInput(event);},false);
me.textArea.addEventListener("blur", function(event){me.limitInput(event);},false);
} else {
me.textArea.attachEvent("onkeyup", function(event){me.limitInput(event);});
}
}
LimitedTextArea.prototype.showMessage = function(message){
this.textArea.disabled = true;
alert(message);
Delegate.create(this, this.reenable());
}
LimitedTextArea.prototype.reenable = function(){
this.textArea.disabled = false;
this.textArea.focus();
}
Hinweis: Im eigenen Interesse sollte man die Anzahl an Zeichen /Zeile und Anzahl der Zeilen korrespondierend mit der Größe des Eingabebereichs wählen:
Es sollte gelten
maxCharsPerLine <= textarea cols
und
maxLines <= textarea rows