Limit Characters in a Textarea with Prototype

by Terri Ann on January 17, 2008

This entry is part 9 of 10 in the series Prototype Tutorial

Lately I have fallen in love with prototype and in effort to challenge myself and my skills I continue to brainstorm ways to use Prototype as often as possible.

Until I started using the Really Easy Validation library I hadn’t done a lot with Prototype and forms. But after I did some custom work using that library I realized I also needed a text area with a character counter. That was easy enough, but I wanted to make it something that was nice and expandable, so I did.

We’ll start with the HTML code I already had for the two text areas whose character’s I want to count and limit.

HTML

  <div class="formrow">
    <label for="txtdesc">Description</label> <span>(<span id="counter-txtdesc"><b>#</b></span> characters)</span><br />
    <textarea name="txtdesc" id="txtdesc"></textarea>
  </div>

  <div class="formrow">
    <label for="comments">Comments</label><br />
    <textarea name="comments" id="comments"></textarea>
  </div>

I will change two lines in my .js file to initiate the character counting.

JavaScript

function init(){
    makeItCount('txtdesc', 300, false);
    makeItCount('comments',100);
}

I’ve defined that both text areas: txtdesc and comments are to have limits. The text area description will be limited to 300 characters and comments will be limited to 100 characters.

New 3rd, optional, parameter Added 4/16/08
The 3rd parameter allows you to override the limiting functionality. It defaults to true but can be overridden by passing false this will allow the text field to accept and not trim down the entry to the maximum amount, ti will continue to count up and inform you how over the limit you are so you can pick and choose what to trim down.

Is that more twitter like? I wouldn’t know since I don’t twitter(yet).


Since an element with the id 'counter-txtdesc' exists the script has a place to put the character count, in this case: 0/300.

No element with the id 'counter-comments' exists, so the script will create a div immediately below the text area with that id and puts 0/100 as the text within it.

When the count is below the maximum number of characters the relative counter- element also has the class of charcount-safe applied to it. When you meet or go over the character limit charcount-safe is removed and charcount-limit is applied. The script also trims down your content to the specified number of characters once you have gone over it.

If either text area doesn’t exist the script does not return an error, it just disregards the assignment to count that area.

Pretty easy. There’s additional customization I’d like to add to it but I need to research a few things before I do that!

Version 2

New update by request.

I’ve added a 3rd parameter (optional) to override the limiting functionality. Documentation above has been altered to allow for this change.

Download
1.0 KB – zip – Version 2.1

Demo & Download

You can view the demo to see this example live or download the script under the MIT License, same as the Prototype and Scriptaculous libraries.

Download
1.0 KB – zip – Version 2.1

Updates

Update 4/17/08
In response to a comment about an IE bug I looked into the problem…the problem was with the demo, not the script. I had used a meta tag <meta name="description" value="" /> and named the text area description. IE was picking up the <meta> tag instead of the <textarea> tag. Which I guess is just a friendly reminder that:

  • name is technically deprecated according to the w3c’s XHTML 1 documentation
  • Just be unique – Just name and id elements uniquely, only duplicate the name and id within the same element to eliminate confusion, k?

Old versions

I don’t support older versions, and I do limited support on the newest version. Please be sure to post your questions or comments

{ 1 trackback }

Prologue Theme Mod with 128 Chars Limit | Play Work Play Studio
January 28, 2008 at 10:29 pm

{ 22 comments… read them below or add one }

1 AN@S March 14, 2008 at 2:03 pm

Hi, Great article, I was looking for something like that for a while :).

I’m developing a web application for sending SMS messages, with this application you can send English messages (max characters per message is 160) but if you want to send a message with complicated characters (Chinese, Arabic, … etc), the max number of characters becomes 70 !!! I’m wondering how can the script be modified to do this? When you type a letter in Chinese for example the limit changes instantly to 70 ! The problem is that I don’t know Javascript I’m wondering whether hacking this script to do this is easy or not.

Thanks :)

2 Kinetic April 15, 2008 at 10:07 pm

I started looking around for way to limit the length of a text area and ran intot he same old bloated js routines and the site Im developping already uses prototype so when I saw your tutorial and demo I jumped for joy. nice use of prototype and character count lightweight and uber easy to implement

Bravissimo!

3 Phillip April 16, 2008 at 1:57 pm

How could I go about disabling the max allowed characters so that a user can paste in larger content and then pare it down? the way that twitter.com does it is very nice

thanks, Phillip

4 Kinetic April 16, 2008 at 5:18 pm

hmmm it seems this doesnt work in IE6 or IE7 anyone found a way around it so it works in Internet exploder?

5 Terri Ann April 17, 2008 at 12:56 am

@Kinetic

In the demo I had a <meta name="description" /> tag which IE was recognizing instead of the <textarea name="description" id="description"></textarea>

Oops! My bad! This has been fixed and I’ve added a note in the blog about it!

Thanks everyone for your comments, keep suggestions and bugs coming. :)

@Phillip

I’ve posted a version two that allows for an over-ride 3rd parameter that allows you to enter more than the maximum amount of characters

6 Phillip April 17, 2008 at 9:58 am

Nice version 2. I did some digging around in twitter’s code and found that they count characters this way:

HTML 140/140

Javascript: function postProcessUpdateKeypress(box, e) { var val = box.value; updateStatusTextCharCounter(val); } function updateStatusTextCharCounter(value) { $('status-field-char-counter').innerHTML = 140 - value.length; if (value.length > 130) { $('status-field-char-counter').setStyle({ color: 'red' }); } else if (value.length > 120) { $('status-field-char-counter').setStyle({ color: 'orange' }); } else { $('status-field-char-counter').setStyle({ color: 'black' }); } };

** Edited by admin 4-17-2008 @3:54pm to fix formatting

7 Kinetic April 17, 2008 at 10:47 am

Terri, nice fix glad it was only a conflict with the standard meta tag description and renaming the textarea to txtdesc (or anything else for that matter as long as you edit the js file to reflect your text area name/id and as long as it isnt being called up in the head by a meta tag or other tag) sure does the trick again very nice, very slick and nice to know you are on top of it 5 out 5 wOOt

8 Marc Falk June 17, 2008 at 9:25 pm

Hi Terri!

Thanks for a nice script. Is it possible to limit and

with this method? is yes, how?

Thanks in advance…

Marc

9 Marc Falk June 17, 2008 at 10:49 pm

Ah crap, hadn’t noticed that html tags was allowed here. They used to be forbidden with a big F! :P

Anyway , I wanted to know if you could limit other elements, like div, span and p with your script… and I’ve actually found a way to do it now with the prototype truncate string.

At the moment I’m just using:

Script: $('truncate').update($('truncate').innerHTML.truncate(10))

Content: </span

And it works.. but do you think it can be done in a smarter/faster way?

this guy does it in a very different way, but it doesn’t work here :/

Anyway, take care :) Marc

10 Paolo Gabrielli July 10, 2008 at 1:45 pm

Thanks for your code. Just a line to ask your help: if I (copy &) paste into the textarea the field is not updated. I searched around the net but I haven’t find anything. The only solution that I came with is to use new

Form.Element.Observer($(id), 0.5, function(){charCounter(id, maxsize, limited);})

instead of the 2 Event.observe. Every 500ms it check if the textarea is changed and even if you copy&paste it updates the counter. Many thanks, P.

11 Milos July 16, 2008 at 2:36 am

Hello! according to Phillips post I have updatet your script to output a message or to color the letters when a maximum limit of letters is reached.

function charCounter(id, maxlimit, limited){
    if (!$('counter-'+id)){
        $(id).insert({after: '<div id="counter-'+id+'"></div>'});
    }
    if($F(id).length >= maxlimit){
        if(limited){    $(id).value = $F(id).substring(0, maxlimit); }
        $('counter-'+id).addClassName('charcount-limit');
        $('counter-'+id).removeClassName('charcount-safe');
    } else {    
        $('counter-'+id).removeClassName('charcount-limit');
        $('counter-'+id).addClassName('charcount-safe');
    }
    $('counter-'+id).update( $F(id).length + ' von ' + maxlimit );
    // here is the updated Code START
    if ($F(id).length > 25) {
    // do here what ever you want if the limit is reached
    alert("Maximum letters are reached. ...");
    }
    // here is the updated Code END
}
12 Mark McKay July 16, 2008 at 9:18 pm

Great script.

If you place the containing the remaining characters in the Label your approach will be more accessible to screen readers as they only speak labels when in forms mode.

i.e.

Description (0/300 characters)

Mark

13 Knal November 29, 2008 at 1:00 pm

I have combined this functionality with the Really Easy validation and coma across a small problem: If i reset a form (), the counter does not reset since it isn’t triggered. Any ideas?

Thanks a load!

Knal.

14 Terri Ann November 30, 2008 at 11:07 pm

Best suggestion would be to add a trigger using the really easy validation, or call the makeItCount() or init() onreset.

Good luck – feel free to repost your findings!

15 Knal December 1, 2008 at 1:50 pm

I’ve aded the init();, but it only works if i click twice. My simplified code looks like this:

var valid = new Validation( ‘contactform’, { immediate : false, onFormValidate : HandleForm });

Validation.addAllThese([ ['msg', 'Bitte, Foobar', { minLength : 3, maxLength : 100, include : ['required'] }] ]);

$(‘resetform’).observe(‘click’, function (){ valid.reset(); init(); });

Hope you can help.

Thanks, Knal

16 Knal December 1, 2008 at 1:51 pm

Apparently my form in my comment was filtered out…

17 Terri Ann December 1, 2008 at 6:13 pm

When you submit your code use your preferred code edito to tab in the content you want to display as code and leave an empty line between your comments and code.

example:

blah blah blah blah

[tab] code code code [tab] code code code

Then I’ll take a look again!

18 Knal December 1, 2008 at 6:48 pm

Ok, thanks.

The simplified form looks like this:

<form id="contactform" action="contact.php" method="post">
    <label for="msg">Message</label>: <span>(<span id="counter-msg"><b>300</b></span> Chars)</span>     
    <textarea name="msg" id="msg" cols="40" rows="4"></textarea>
    <input type="submit" value="Submit" />
    <input type="reset" id="resetform" name="Reset" value="Reset" />
</form>

The javascript looks like this:

var valid = new Validation( 'contactform', { immediate : false, onFormValidate : HandleForm });
Validation.addAllThese([ ['msg', 'Bitte, Foobar', { minLength : 3, maxLength : 100, include : ['required'] }] ]);
$('resetform').observe('click', function (){ valid.reset(); init(); }); 

Thanks again for your help!

19 Franco Sabbatini January 20, 2009 at 7:06 am

Hi there! so i really loved your code :) because im a fun of prototype like you :).. i made a change to your code that i get everyone would love to have: The PROBLEM: when you changed the textarea value by javascript (lets say innerHTML=’hola amigo’) this code would not work due the lack of a CHANGE event. So when i tried CHANGE event didnt work either ’cause changing the value other way than clicking on it WILL NOT FIRE THE EVENT EITHER! the SOLUTION: just added a nice timer to it :) (a timed observer) so here is the code

[code] /*

Title : charcount.js Author : Terri Ann Swallow URL : http://www.ninedays.org/ Project : Ninedays Blog Copyright: (c) 2008 Sam Stephenson This script is is freely distributable under the terms of an MIT-style license.

Description : Functions in relation to limiting and displaying the number of characters allowed in a textarea Version: 2.1 Changes: Added overage override. Read blog for updates: http://blog.ninedays.org/2008/01/17/limit-characters-in-a-textarea-with-prototype/

Created : 1/17/2008 - January 17, 2008 Modified : 5/20/2008 - May 20, 2008

Functions: init() Function called when the window loads to initiate and apply character counting capabilities to select textareas charCounter(id, maxlimit, limited) Function that counts the number of characters, alters the display number and the calss applied to the display number contarCaracteres(id, maxsize, limited) Function called in the init() function, sets the listeners on teh textarea nd instantiates the feedback display number if it does not exist

Modified: 1/20/2009 Author of modification: Franco Sabbatini Changes: if innerHTML is inserted with javascript then KeyUp and KeyDown would not work. Added a timer

*/ Event.observe(window, 'load', init); function init(){ contarCaracteres('txtComentario',10); }

function charCounter(id, maxlimit, limited){
    if (!$('counter-'+id)){
        $(id).insert({after: '<div id="counter-'+id+'"></div>'});
    }
    if($F(id).length >= maxlimit){
        if(limited){    $(id).value = $F(id).substring(0, maxlimit); }
        $('counter-'+id).addClassName('charcount-limit');
        $('counter-'+id).removeClassName('charcount-safe');
    } else {    
        $('counter-'+id).removeClassName('charcount-limit');
        $('counter-'+id).addClassName('charcount-safe');
    }
    $('counter-'+id).update( $F(id).length + '/' + maxlimit );  

}

function contarCaracteres(id, maxsize, limited){
    if(limited == null) limited = true;
    if ($(id)){
        //new Form.Element.Observer($(id), 0.2, function(){charCounter(id, maxsize, limited);});
        Event.observe($(id), 'keyup', function(){charCounter(id, maxsize, limited);}, false);
        Event.observe($(id), 'keydown', function(){charCounter(id, maxsize, limited);}, false);
        charCounter(id,maxsize,limited);
    }
}

[/code]

20 Franco Sabbatini January 20, 2009 at 7:35 am

i forgot to mention: i added a // to the line i changed

21 gioco ai casinĂ² online April 20, 2009 at 8:14 am

I am using TinyMCE editor for textarea.how to limit the characters in that textarea.500 is limit for that textarea,how to limit characters for this textarea in client side.alert message after 500 characters or displaying dynamic count of characters above the text area.thanks

22 Jeremy Jackson April 25, 2009 at 1:27 pm

I reworked this code to better fit into a class that I was working on. Thanks for the example.

[code] /* Makes all textareas with a "limited" class limit the number of characters * that are allowed to be entered in it. It will update the number of chars * left in a given textarea with the [textarea.id]counter id set on it. The * number of characters it will restrict to is pulled from the title, so if * you want a 200 char limit, put something like "200 character limit" in the * title attribute (defaults to 100 if unable to parse one). */ makeTextareasLimitInput: function() { $$('textarea.limited').each(function(textarea) { var limitInput = function(event) { var element = Event.element(event), limit = parseInt(element.title) || 100; if (element.value.length >= limit) element.value = element.value.substring(0, limit); if (counter = (element.id) ? $(element.id + 'counter') : false) { var charsLeft = (limit - element.value.length); counter.update(charsLeft + ((charsLeft == 1) ? ' character ' : ' characters ') + 'left'); if (charsLeft) counter.removeClassName('max-reached'); else counter.addClassName('max-reached'); } } $w('keyup keydown blur').each(function(eventName) { textarea.observe(eventName, limitInput, false); }); }); }, [/code]

Leave a Comment

Previous post:

Next post: