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!