Saturday, September 15, 2007

MaxLength with MultiLine TextBox

We've all ran into the issue with using a TextArea control or a TextBox control with MultiLine set to True to allow the user to enter a long description or comments, etc. Specifically the problem is that the built in MaxLength attribute that we are so used to using for a standard TextBox does not work if you are using MultiLine=True.
 
There are a variety of ways to handle this. In some cases I've simply dropped in a line or two of JavaScript and added some onkeypress events to analyze the number of characters the user has typed in and when they reach the maximum to just stop them form entering anything else. That approach works fine, but it involves having to worry about making sure you copy the JavaScript to the right pages and worry about setting up your onkeypress event for each item you want to limit the length of, etc. When researching this I came across a better solution that is pretty simple, yet it's more generic and easier to reuse throughout your projects.
 
The idea is essentially just extending the functionality of the System.Web.UI.WebControls.TextBox control.

public
class TextArea : System.Web.UI.WebControls.TextBox
{
    
protected override void OnPreRender(EventArgs e)
    
{
         
if (MaxLength > 0 && TextMode == System.Web.UI.WebControls.TextBoxMode.MultiLine)
         
{
              
// add javascript handlers for paste and keypress
              
Attributes.Add("onkeypress", "doKeypress(this);");
              
Attributes.Add("onbeforepaste", "doBeforePaste(this);");
              
Attributes.Add("onpaste", "doPaste(this);");

              
// add attribute for access of maxlength property on client-side
              
Attributes.Add("maxLength", MaxLength.ToString());

              
// register client side include - only once per page
              
if(!Page.ClientScript.IsClientScriptIncludeRegistered("TextArea"))
              
{
                    
Page.ClientScript.RegisterClientScriptInclude("TextArea", ResolveClientUrl("~/Common/TextArea.js"));
               
}
          
}

         
base.OnPreRender(e);
     }
}
 
The main thing to recognize is how it's adding the onkeypress, onbeforepaste, and onpaste events to execute JavaScript functions on the client.
 
Another nice thing about this code is that you don't have to worry about putting your JavaScript code everywhere you want to use this functionality. You can simply keep it centralized in a .js file and place it in a folder with your other JavaScript files.
 
In our case we have the necessary JavaScript in TextArea.js, which is as follows:
 
// Keep user from entering more than maxLength characters
function doKeypress(control)
{
    
maxLength = control.attributes["maxLength"].value;
    
value = control.value;
    
if(maxLength && value.length > maxLength-1)
     {
         
event.returnValue = false;
          maxLength = parseInt(maxLength);
    
}
}
 
// Cancel default behavior
function doBeforePaste(control)
{
    
maxLength = control.attributes["maxLength"].value;
    
if(maxLength)
    
{
         
event.returnValue = false;
    
}
}
 
// Cancel default behavior and create a new paste routine
function doPaste(control)
{
    
maxLength = control.attributes["maxLength"].value;
    
value = control.value;
    
if(maxLength)
     {
         
event.returnValue = false;
         
maxLength = parseInt(maxLength);
         
var oTR = control.document.selection.createRange();
         
var iInsertLength = maxLength - value.length + oTR.text.length;
         
var sData = window.clipboardData.getData("Text").substr(0,iInsertLength);
         
oTR.text = sData;
    
}
}
 
Now to use it you can simply register the control on your page like so:
 
<%@ Register TagPrefix="WebControls" Namespace="Test.WebControls" Assembly="Test.WebControls" %>
 
Then you can use the control as follows:
 
<WebControls:TextArea ID="txtTest" TextMode="MultiLine" MaxLength="500" Rows="10" Columns="75" runat="server" />
 
The value you specify for the MaxLength attribute will determine the maximum number of characters the user will be able to enter.
 
Of course the user can disable JavaScript, so it's always a good idea to test for that accordingly or make sure to validate on the server side as well.

0 comments: