ASP.NET/MVC3 Limit/Count Number of Characters in TextArea/Textbox

This article demonstrates how to create & use jQuery to limit or count the number of characters in a TextArea or Text Field.

limit textarea characters

Table of contents
 

Introduction

Lately, I was revising the article ASP.NET - Limit number of characters in TextBox control that I wrote nearly two years ago. I decided to take the opportunity to improve it and brush up my jQuery skills. In this article, I will share with everyone how to implement this using jQuery. You can use this jQuery plug-in limit_textarea to limit and count the number of characters in the TextArea or TextBox with multiline text mode on client-side only. The sample codes includes an example of how to use the plug-in with ASP.NET web forms, HTML and MVC 3 pages.

Implementation

In this version, the plug-in accepts three optional parameters, namely maxLength, displayText and displayTextPosition. The maxLength parameter allows us to specify the maximum number of characters in the TextArea. There is also an option to customize the ending display text through the displayText property. Last but not least, the displayTextPosition provides the flexibility to specify the location of the display text message. The valid values are topLeft, bottomLeft, topRight and bottomRight. By default, the maximum allowable number of characters is 500, the display text message is "characters left" and the text position is the top left.

There are three functions inside the plug-in, namely createLabel, trimEnter and validateLimit. Shown in Listing 1 is the createLabel function. It is responsible for creating the display message based on the displayText and displayTextPosition parameters. The display message is placed inside the HTML span tag and its ID is the combination of the TextArea object ID and the static text "_lbl". The display text position is calculated using the TextArea object position, width and height. The formula to derive the text position was from trial and error, you are welcome to enhance it.

Listing 1

this.createLabel = function (txtArea, options) {
 
             var txtAreaID = txtArea.attr("id");
             var labelID = txtAreaID + "_lbl";
 
             //textarea position
             var txtLeftPos = $("[id='" + txtAreaID + "']").position().left;
             var txtTopPos = $("[id='" + txtAreaID + "']").position().top;
 
             var displayLabel = $('<span id=' + labelID + '>' + options.displayText + '</span>')
             .css({ position: 'absolute', height: 15, padding: 2,
                 'font-size': '75%', display: 'inline-block'
             });
 
             //attach the label to text area
             txtArea.after(displayLabel);
 
             //position
             switch (options.displayTextPosition) {
                 case 'topRight':
                     displayLabel.css({ top: txtTopPos - 18, left: txtArea.width() - $("[id='" + labelID + "']").width() - 5 });
                     break;
                 case 'bottomLeft':
                     displayLabel.css({ top: txtTopPos + txtArea.height() + 5, left: txtLeftPos });
                     break;
                 case 'bottomRight':
                     displayLabel.css({ top: txtTopPos + txtArea.height() + 5,
 left: txtArea.width() - $("[id='" + labelID + "']").width() - 5 });
                     break;
                 default:
                     displayLabel.css({ top: txtTopPos - 18, left: txtLeftPos });
                     break;
             }
 
             //initialize
             limit_textarea.validateLimit(txtArea, options);
 
             return true;
         }

The trimEnter function in Listing 2 will replace the carriage returns or newlines in the TextArea with an empty string.

Listing 2

//remove paragraph break from the textarea
        this.trimEnter = function (dataStr) {
            return dataStr.replace(/(\r\n|\r|\n)/g, "");
        }

Similar to the previous version, the purpose of the validateLimit function is to ensure the text entered does not exceed the maximum number of allowable characters and to display the count. Unlike the previous version, this function will add the the carriage returns or newlines count into the maxLength. This way it will display the text in the TextArea correctly when the remaining characters equal to zero instead of truncating the text.

Listing 3

this.validateLimit = function (txtArea, options) {
            var txtValue = txtArea.val();
            var txtAreaID = txtArea.attr("id");
            var labelID = txtAreaID + "_lbl";
            //get the paragraph break count
            var lineBreakMatches = txtValue.match(/(\r\n|\r|\n)/g);
            var lineBreakCount = lineBreakMatches ? lineBreakMatches.length : 0;
            //remaining character left
            var remaningChar = options.maxLength - limit_textarea.trimEnter(txtValue).length;
            if ($("#" + labelID).length) {
                $("#" + labelID).html(remaningChar + options.displayText);
                if (Number(remaningChar) <= Number(0)) {
                    txtArea.val(txtValue.substring(0, options.maxLength + lineBreakCount));
                    $("#" + labelID).html("0" + options.displayText);
                    return false;
                }
                else
                { return true; }
            }
            return true;
        }
    }

The code in Listing 4 will trigger the function when the user copies or cuts and pastes using the mouse. It will wait for 250 milliseconds before calling the validateLimit function because the text in the TextArea will not be available immediately after the paste.

Listing 4

       $(this).bind('cut paste', null, function (e) {
            if (!e.keyCode) {
                var ctrl = $(this);
                setTimeout(function () {
                    limit_textarea.validateLimit(ctrl, options);
                }, 250);
            }
        });

The code in Listing 5 will trigger the function when user enters the text into the TextArea.

Listing 5

       $(this).keyup(function (e) {
            limit_textarea.validateLimit($(this), options);
        });

The code in Listing 6 is a work-around to trigger the function when the user deletes the text in the TextArea using the mouse. The problem with that is it will be triggered every time the user left-clicks the mouse in the TextArea. You can delete or comment out the code if you don't need it in your application.

Listing 6

       //make sure the count is up-to-date
        $(this).mousedown(function (e) {
            if (!e.keyCode) {
                //left mouse click
                if (e.which === 1) {
                    var ctrl = $(this);
                    setTimeout(function () {
                        limit_textarea.validateLimit(ctrl, options);
                    }, 250);
                }
            }
        });

Using the code

Include the jQuery library and the plug-in and as many TextArea controls and/or elements as you want into the web page. Please refer to listing 7 to see how to call the plug-in.

Listing 7

<script type="text/javascript">
    $(document).ready(function () {
        $("[id$='TextBox1']").limit_textarea({ maxLength: 100, displayText: ' Letters left.' });
        $("[id$='TextBox2']").limit_textarea({ maxLength: 200, displayTextPosition: 'bottomLeft' });
        $("[id$='TextBox3']").limit_textarea({ displayTextPosition: 'bottomRight' });
        $("[id$='TextArea1']").limit_textarea();
        $("[id$='TextArea2']").limit_textarea({ maxLength: 125 });
    });
</script>

Conclusion

I hope someone will find this information useful and make your programming job easier. If you find any bugs or disagree with the contents or want to help improve this article, please drop me a line and I'll work with you to correct it. I would suggest downloading the demo and explore it to grasp the full concept of it because I might miss some important information in this article. Please send me an email if you want to help improve this article.

browsers

Tested on IE 7.0/8.0/9.0, Google Chrome 24.0.1312.57, Firefox 18.0.2, Safari 5.1.7

History

- 05/20/2010 - v01.00.00
- 02/16/2013 - v02.00.00

Resources

http://stackoverflow.com/questions/686995/jquery-catch-paste-input
http://lawrence.ecorp.net/inet/samples/regexp-format.php
http://docs.jquery.com/Plugins/Authoring

Watch this script in action

Demo
Demo (MVC 3)

Downloads

Download
Download (MVC 3)