Ask the Jedi: Counting characters and lines with Spry

This post is more than 2 years old.

Barbara asks:

Ray, we are almost finished with a card site and we recently added the spry widget for text area to count the characters however, we need one more piece because we also need to account for carriage returns which is a database element. I looked through the JavaScript widget and it is obviously issing however was wondering if you knew of any way to account for it.

Ah, interesting question there. For folks who may not remember, Spry has a textarea widget that allows for some fun validation rules. I discussed this in an earlier blog entry (holy smokes - that blog entry was extactly one year ago today!) which you may want to read over, but the basic problem is that while Spry makes it easy to count the characters, there is no built in support for line numbering. I played with this a bit and came up with the following.

Let's first start with a simple character count demo.

<html> <head> <script src="/spryjs/SpryData.js" type="text/javascript"></script> <script src="/spryjs/SpryValidationTextarea.js" type="text/javascript"></script> <link href="/sprycss/SpryValidationTextarea.css" rel="stylesheet" type="text/css" /> </head>

<body>

<span id="sprytextarea1"> <textarea name="textarea1" id="textarea1" cols="45" rows="5"></textarea> </span> <p/> Chars Remaining: <span id="my_counter_span"></span><br />

</body> </html>

<script type="text/javascript"> var sprytextarea1 = new Spry.Widget.ValidationTextarea("sprytextarea1", {maxChars:100,counterType:"chars_remaining",counterId:"my_counter_span"}); </script>

I'm not going to explain the code here as the earlier entry explains this well I think, but basically you can see that I tell Spry to monitor a textarea with the ID of sprytextarea1. I've also created a simple span that Spry will use for a character counter (technically a characters remaining counter).

I began my modifications by adding an event listener to the textarea. I used Spry's built in support for this by adding addEventListener:

Spry.Utils.addEventListener("textarea1","keyup",lineCounter,false);

This says: Add a onKeyUp event to textarea1 and call the lineCounter function. Now let's take a look at it:

<script> var maxLines = 5; function lineCounter(e) { var text = Spry.$("textarea1").value; var lines = text.split(/\n/); var remaining = maxLines - lines.length; if(remaining < 0) { //make new str of lines 0-4 lines.pop(); var newStr = lines.join('\n'); Spry.$("textarea1").value = newStr; remaining = 0; } Spry.$("lines_remaining").innerHTML="You have "+remaining+ " line(s) remaining."; } </script>

I begin by getting the current text in the textarea. I split it on line numbers and figure out how many lines are remaining. The tricky part is what to do if there are too many. Spry will actually block (well, quickly delete) your text if you type too much, so I duplicated that behavior. I pop off that extra line of text, join them back together, and then update the textarea.

Lastly, I update a span with a message detailing how many lines remain. I added a new span just for this. The complete code is below.

<html> <head> <script src="/spryjs/SpryData.js" type="text/javascript"></script> <script src="/spryjs/SpryValidationTextarea.js" type="text/javascript"></script> <link href="/sprycss/SpryValidationTextarea.css" rel="stylesheet" type="text/css" /> <script> var maxLines = 5; function lineCounter(e) { var text = Spry.$("textarea1").value; var lines = text.split(/\n/); var remaining = maxLines - lines.length; if(remaining < 0) { //make new str of lines 0-4 lines.pop(); var newStr = lines.join('\n'); Spry.$("textarea1").value = newStr; remaining = 0; } Spry.$("lines_remaining").innerHTML="You have "+remaining+ " line(s) remaining."; } </script> </head>

<body>

<span id="sprytextarea1"> <textarea name="textarea1" id="textarea1" cols="45" rows="5"></textarea> </span> <p/> Chars Remaining: <span id="my_counter_span"></span><br /> Lines Remaining: <span id="lines_remaining">You have 5 lines remaining.</span>

</body> </html>

<script type="text/javascript"> var sprytextarea1 = new Spry.Widget.ValidationTextarea("sprytextarea1", {maxChars:100,counterType:"chars_remaining",counterId:"my_counter_span"}); Spry.Utils.addEventListener("textarea1","keyup",lineCounter,false); </script>

Enjoy!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Jason Brookins posted on 12/17/2008 at 8:09 PM

Man, I hope Spry comes back strong. I'm impressed with jQuery and all, but I do like Spry.

Comment 2 by Francois Levesque posted on 12/17/2008 at 9:23 PM

Hi Ray,

Interesting way to solve this problem! However, the question got me thinking, and I wonder if this is what the OP needed as well. When you count characters in a textarea, carriage returns are not accounted for in the length of the field. When submitting to the DB, though, these characters are part of the field and must be considered for the maxlength of the column.

ie: You have a column defined as varchar (500), and you validate via JS that your field does not go over 500 characters. By default, carriage returns will not be counted and will break the submit when it attempts to store in the database field.

Any ideas?

Comment 3 by Raymond Camden posted on 12/17/2008 at 9:33 PM

Actually the carriage returns _are_ counted. You see the counter go down when you hit enter. Both the char counter and the line counter.

Comment 4 by Francois Levesque posted on 12/17/2008 at 11:27 PM

Oops, my bad. I guess I never noticed that with Spry's textarea widget, but rather with other pre-built or home grown counting solutions.

I stand corrected!