Introduction
Some weeks ago, I published an article about this question with a solution which works fine for Internet Explorer only.
When I was asked for a cross browser solution for Internet Explorer and Firefox (and maybe other browsers), I had to find a totally different way to get the desired result in both browsers: a client-side JavaScript to limit the content of a textarea to a certain number of characters as well as to a certain number of lines (not necessarily equal to the number of visible rows of the textarea).
In the meantime, I learned a little bit more about JavaScript and DOM within Firefox: so here is the result of my few experiences.
Textarea Limits
In both browsers, we can get the visible size of a textarea (attributes rows and columns), its line height and its scroll height. And we need two additional attributes: maxChars
(maximum number of characters) and maxRows
(maximum number of rows) to get its limits under full control.
Example
The example contains two textareas shown here under IE 8.0 and FF 3.6.
The first one does not allow any scrolling. The text may not exceed the visible size of the textarea (limited by the attributes cols and rows) or the given number of characters (maxChars = 120
). The second textarea shows 3 rows, but may scroll to a maximum of 4 rows, indicated and controlled by the additional attribute maxRows
.
Internet Explorer 8.0
Firefox 3.6
Definition of the textareas
<textarea name="noscroll_TA" id="noscroll_TA" cols="50" rows="3"
maxRows="3" maxChars="120" wrap="virtual"
style="font-family:arial; font-size:16px; overflow:auto;">
Text in the limited textarea may never exceed the defined maximum number of rows
and/or characters. </textarea>
<textarea name="scroll_TA" id="scroll_TA" cols="50" rows="3"
maxRows="4" maxChars="0" wrap="virtual"
style="font-family:arial; font-size:12px;" overflow:auto;">
In the second textarea the default chars limit (cols * maxRows) is used.
</textarea>
Attributes
We assign a name
and an id
to our textareas and we define their visible size (rows
and cols
). It is recommended to set the property wrap
to "virtual
" or "physical
" or "hard
", but it should not be set to "off
". We have to add two additional numeric attributes: maxRows
and maxChars
to the textarea definitions.
maxRows
is used to allow scrolling if it has a higher value than the attribute rows
.
maxChars
is used to set the maximum number of characters to a lower value than it would be by default.
The default value (cols * maxRows
) is taken if maxChars
is set to "0
" or to a higher value than the default value.
Style Properties
- font-family: We may use a proportional font (e.g. Arial) or a monospace font (e.g. Courier).
In the first case, we will rather reach the character limit, in the second case more probably the line limit will be reached first. - font-size: We need to know the font-size to get the line-height and to compute the height of the textarea.
- overflow:auto: Overflow is set to "auto" to display the textarea in Internet Explorer without a scrollbar.
The textareas may be empty or contain some default text, as is shown in the examples.
As an indispensable key prerequisite for our solution, for each textarea we need a hidden <div> containing a break (<br />), which is used to automatically compute and set the line height and height of the textarea. Its name has to correspond with the name of the textarea extended by "_LineHeight
", e.g. "noscroll_TA_LineHeight
" for the first textarea in our example.
And it has to have the same font-family and font-size as the corresponding textarea to get the proper value for the line height.You can put it anywhere within the <form>
tag, e.g. instead of a <br />
tag.
<div id="noscroll_TA_LineHeight" style="font-family:arial;
font-size:16px; visibility:hidden;">
<br /></div>
<div id="scroll_TA_LineHeight" style="font-family:arial;
font-size:12px; visibility:hidden;">
<br /></div>
If you omit this <div>
, you will have to set the height
and the lineHeight
of the textareas manually.
The limits of the textareas are displayed on the example page in three input fields (readonly) giving the actual and the maximum number of characters and the maximum number of lines in the corresponding textarea. To find the proper fields for each textarea programmatically, the names and ids of these fields have to have the name of their corresponding textarea as prefix.
Textarea noscroll_TA
contains:
<input name="noscroll_TA_Chars" id="noscroll_TA_Chars" type="text"
style="font-family:arial; font-size:14px; text-align:center;
border-width:0px; width:36px;" value="0" size="2" maxlength="4"
readonly="readonly">
of max. <input name="noscroll_TA_maxChars" id="noscroll_TA_maxChars"
type="text" style="font-family:arial; font-size:14px;
text-align:center; border-width:0px; width:40px;" value="0"
size="2" readonly="readonly"> characters in
max. <input name="noscroll_TA_maxLines" id="noscroll_TA_maxLines"
type="text" style="font-family:arial; font-size:14px;
text-align:center; border-width:0px; width:28px;" value="0"
size="1" maxlength="3" readonly="readonly"> lines
Textarea scroll_TA
contains:
<input name="scroll_TA_Chars" id="scroll_TA_Chars" type="text"
style="font-family:arial; font-size:14px; text-align:center;
border-width:0px; width:36px;" value="0" size="2" maxlength="4"
readonly="readonly">
of max. <input name="scroll_TA_maxChars" id="scroll_TA_maxChars" type="text"
style="font-family:arial; font-size:14px; text-align:center;
border-width:0px; width:40px;" value="0" size="2" readonly="readonly">
characters in
max. <input name="scroll_TA_maxLines" id="scroll_TA_maxLines" type="text"
style="font-family:arial; font-size:14px; text-align:center;
border-width:0px; width:28px;" value="0" size="1" maxlength="3"
readonly="readonly"> lines
The Code
<script type="text/javascript">
The main function checkLimits
is called with 3 parameters by the event body.onload
and by the function getEvent
. The parameters are 1st: name of the textarea, 2nd: name of the character counter field and 3rd: keycode of the calling event.
function checkLimits(txtArea,countChars,kc)
{
First we get the line height from the hidden <div>
and set lineHeight
and height
of the textarea to the corresponding values if the attributes lineHeight
and height
for the textarea do not already exist! To support different font-families and to take into account if scrolling is allowed for the textarea we need different formulas to compute these values.
div_LineHeight = txtArea.getAttribute("name") + "_LineHeight";
lh = document.getElementById(div_LineHeight).offsetHeight;
fs = parseInt(txtArea.style.fontSize.replace('px',''));
dh = Math.round((lh/fs)*100)/100;
if(!txtArea.style.lineHeight || !txtArea.style.height)
{
lh = document.getElementById(div_LineHeight).offsetHeight;
txtArea.style.lineHeight = lh +'px';
if(txtArea.rows == txtArea.getAttribute("maxRows"))
txtArea.style.height = Math.ceil((fs * txtArea.rows * dh)+((fs*200)/300));
else
txtArea.style.height = Math.ceil((fs * txtArea.rows * dh)+((fs*100)/300));
}
Now we can compute the limits of the textarea:
var exceedMsg = "";
maxLines = txtArea.getAttribute("maxRows");
maxHeight = Math.ceil((fs * maxLines * dh)+((fs*200)/300));
if(txtArea.getAttribute("maxChars") != 0 &&
txtArea.getAttribute("maxChars") < maxLines * txtArea.cols)
maxChars = txtArea.getAttribute("maxChars");
else
maxChars = maxLines * txtArea.cols;
document.getElementById(txtArea.getAttribute("name") + '_maxChars').value = maxChars;
document.getElementById(txtArea.getAttribute("name") + '_maxLines').value = maxLines;
countChars.value = txtArea.value.length;
Here we check the limits.
if(txtArea.value.length > maxChars || txtArea.scrollHeight > maxHeight)
{
If the characters limit is exceeded, we reduce the length of the text in the textarea character by character until chars limit is reached.
while (txtArea.value.length > maxChars && txtArea.scrollHeight <= maxHeight)
{
txtArea.value = txtArea.value.substr(0,txtArea.value.length-1);
exceedMsg = "chars limit exceeded";
}
If the lines limit is exceeded, we reduce the text in steps of three characters because we have to eliminate not only the last character of the text but also the two control characters of the line break.
while(txtArea.scrollHeight > maxHeight)
{
txtArea.value = txtArea.value.substr(0,txtArea.value.length-3);
exceedMsg = "lines limit exceeded";
}
}
If a limit has been exceeded, the user gets an alert except backspace (kc 8) or del (kc 46) is pressed.
if(exceedMsg != "" && (kc != 8 && kc != 46))
alert(exceedMsg);
Finally the character counter is updated.
countChars.value = txtArea.value.length;
}
To avoid an alert if backspace or del is pressed, we need to know the keyCode
. This is done by the function getEvent
for Internet Explorer and for Gecko.
function getEvent(e)
{
if (!e)
{
e=window.event;
txtArea=e.srcElement;
if (e.keyCode) {
var kc = e.keyCode;
}
}
else
{
txtArea=e.target;
if (e && e.which) {
var kc = e.which;
}
}
var charsCountfield = txtArea.getAttribute("name") + "_Chars";
countChars=document.getElementById(charsCountfield);
Now we can call checkLimits
.
checkLimits(txtArea,countChars,kc);
}
</script>
Within the <form>
tag of the <body>
we need to assign some events to our textareas to check the limits. First of all, we call checkLimits
for each textarea to initialize its limits. At least one of the shown events (preferably onkeyup
) we should use for each textarea to call the function getEvent
and from there to call the function checkLimits
.
<script type="text/javascript" >
<!--
document.body.onLoad=checkLimits(document.getElementById('noscroll_TA'),
document.getElementById('noscroll_TA_Chars'),null);
checkLimits(document.getElementById('scroll_TA'),
document.getElementById('scroll_TA_Chars'),null);
document.getElementById('noscroll_TA').onkeyup=getEvent;
document.getElementById('noscroll_TA').onfocus=getEvent;
document.getElementById('noscroll_TA').onblur=getEvent;
document.getElementById('noscroll_TA').onmousedown=getEvent;
document.getElementById('noscroll_TA').onmouseup=getEvent;
document.getElementById('noscroll_TA').onchange=getEvent;
document.getElementById('noscroll_TA').oncut=getEvent;
document.getElementById('noscroll_TA').onpaste=getEvent;
document.getElementById('scroll_TA').onkeyup=getEvent;
document.getElementById('scroll_TA').onfocus=getEvent;
document.getElementById('scroll_TA').onblur=getEvent;
document.getElementById('scroll_TA').onmousedown=getEvent;
document.getElementById('scroll_TA').onmouseup=getEvent;
document.getElementById('scroll_TA').onchange=getEvent;
document.getElementById('scroll_TA').oncut=getEvent;
document.getElementById('scroll_TA').onpaste=getEvent;
</script>
Compatibility
I have tested the script with Internet Explorer Version 7.0 and 8.0 as well as with Firefox V 3.5 and 3.6. Feedback about the compatibility of the script with other browsers / browser versions would be appreciated.
History
- 22nd April, 2010: Version 3
- Better support of different font-families and font-sizes.
- Different formulas to compute the height of scrollable and not scrollable textareas
- 31st March, 2010: Version 2
- 3rd February, 2010: Initial post