Verfasst von: hugahaga | 3 März 2009

JavaScript Experimente – I

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

Download eines Beispiels


Einen Kommentar hinterlassen

Ihre Antwort:

Kategorien