Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

How to Limit the Number of Lines and Characters in a Textarea with Cross Browser Support?

3.71/5 (5 votes)
22 Apr 2010CPOL5 min read 105.1K   926  
An article on how to limit the number of lines and characters in a textarea with cross browser support.

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

cBTALimit1.gif

Firefox 3.6

cBTALimit1.gif

Definition of the textareas

XML
<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>
XML
<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.

XML
<div id="noscroll_TA_LineHeight" style="font-family:arial; 
	font-size:16px; visibility:hidden;">
<br /></div> 
XML
<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:

XML
<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:

XML
<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

XML
<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.

JavaScript
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.

JavaScript
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:

JavaScript
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; // or any other suitable value
document.getElementById(txtArea.getAttribute("name") + '_maxChars').value = maxChars;
document.getElementById(txtArea.getAttribute("name") + '_maxLines').value = maxLines;
countChars.value = txtArea.value.length; // actual number of chars

Here we check the limits.

JavaScript
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.

JavaScript
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.

JavaScript
  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.

JavaScript
if(exceedMsg != "" && (kc != 8 && kc != 46))
  alert(exceedMsg);

Finally the character counter is updated.

JavaScript
  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.

JavaScript
function getEvent(e) 
{ 
  if (!e) 
  { // IE 
    e=window.event; 
    txtArea=e.srcElement; 
    if (e.keyCode) { 
      var kc = e.keyCode; 
    } 
  } 
  else 
  { // Gecko 
    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.

JavaScript
  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.

JavaScript
<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);
// example events for noscroll_TA
  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;
// example events for scroll_TA
  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
    • Support of Firefox
  • 3rd February, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)