Limit textarea symbols to visible part
Is there any way to limit textarea entered symbols to visible part only?
I don't want scrolling, I have specified number of rows column for it and I want that user could not enter so many characters that possible scrolling will appear.
Of course I could set overflow:hidden but symbols anyway will be entered. Limiting to the number of characters is not my case, because different character take different width: for example W and 1. I need this logic because data entered in textarea are used on some print report and there is no possibility for scrolling in paper.
I have found only 2 possible solutions:
Use some average number of characters. And limit by this number. This is very rough. Because for strings with average number of big characters greater than usual it will still hide some data.
Use rendering of entered characters to some separate div and calculate its width/height. Seem to me will be very slow and not sure this is the correct i开发者_开发百科mplementation.
You can use JavaScript to check the scrollHeight
and if bigger than the "original" height, truncate the text until it has no scroll anymore. Code for this would be:
function CheckScroll(oTextarea) {
if (oTextarea.scrollHeight > oTextarea.offsetHeight) {
while (oTextarea.scrollHeight > oTextarea.offsetHeight) {
oTextarea.value = oTextarea.value.substr(0, oTextarea.value.length - 1);
}
}
}
And to trigger it:
<textarea cols="15" rows="3" onkeyup="CheckScroll(this);" onchange="CheckScroll(this);" onpaste="CheckScroll(this);"></textarea>
Live test case: http://jsfiddle.net/yahavbr/bNqVf/1/
I came up with something similar to Shadow Wizard's effort which uses oninput
to detect all forms of input (like pasting, drag/drop), not just keyboard input. It requires switching off the scrollbars of the textarea with the following CSS:
textarea { overflow: hidden; }
You might want to set resize: none;
for browsers like Firefox 4 and Chrome. Also, Opera's wrapping doesn't break if there are no spaces, but it doesn't support word-wrap: word-break;
properly so I'm not sure how you'd work around this. The JavaScript involves remembering the content of the textarea each time it changes and, if the text exceeds the size of the element, the change is reverted to the previous value:
var prev = "",
tArea = document.getElementById("limit");
// Need to use onpropertychange event for IE8 and lower
if ("onpropertychange" in tArea && !("oninput" in tArea)) {
tArea.onpropertychange = function () {
// Only run code if value property changes
if (window.event.propertyName == "value")
this.oninput();
}
}
// oninput will fire for all types of input, not just keyboard
tArea.oninput = function () {
// Temporarily remove the onpropertychange event to prevent a stack overflow
var opc = this.onpropertychange;
this.onpropertychange = null;
// Revert value if the text exceeds the size of the box
if (this.scrollHeight > this.offsetHeight) {
this.value = prev;
}
prev = this.value;
if (opc)
this.onpropertychange = opc;
}
Working demo: http://jsfiddle.net/37Jnn/ - tested in Firefox 4, IE8, Chrome 9, Opera 10.
You could style it to use Courier, or some other non-proportional font. That way, you'd know exactly how many characters could fit, since all characters are the same size, which would make it easy to limit it using any one of several well-known techniques for limiting the number of characters in the string.
The downside is that it wouldn't look pretty (unless you happen to like how Courier looks), but it is a workable solution, and I can't think of anything else.
Just to summarize. I will exclude Courier font solution from discussion. Because in most cases it is not acceptable. Both solutions that use key up/property changes has drawback: visually text is entered and only then removed.
Making substr(0, oTextarea.value.length - 1) has problems when last symbol is \n in IE. In this case it will hang because \r symbol is left. So it should be used oTextarea.value.length - 2 in case of last \n.
For on property change should be used some multi browser solution. For example like this
The only possible way to make such checks user friendly (not allowing entering) is to create for each text area other hidden text area and make all checks on this text area in events before data are really shown in original text area (like key down). But in this case it will require handling of all selection ranges, pastes and reapplying them on hidden. And logic will be not trivial.
精彩评论