2

I have a h:inputTextArea and i want to add on top of it a little label that says characters left, and it counts down from 400 to 0 when a new character is entered. I have no idea how can i add this feature at all to my h:inputTextArea. Do i need a bit of javascript for that(This feature should not refresh the page)?

Any recommendation?

What about the already existing validator, is it capable of doing such thing?

<h:inputTextarea id="offerDescription" value="#{newOfferSupportController.offerDescription}" validator="#{newOfferSupportController.validateDescription} "/>
javing
  • 12,307
  • 35
  • 138
  • 211
  • 1
    Yes, you'll need to use JavaScript (preferably with jQuery) for that. – ThiefMaster Apr 28 '11 at 15:18
  • Be careful - some available plugins (like the jqEasy one mentioned in an answer) do not properly account for the way browsers handle newlines explicitly typed into the textarea. – Pointy Apr 28 '11 at 15:27

4 Answers4

2

You could use JSF's ajax support to cause your countdown message to re-render whenever the user types something. The control that you re-render would simply count the size of the message and display that. A Javascript solution would be more efficient but this approach avoids some of the cross-browser silliness.

<h:inputTextarea id="tweet" style="width: 400px;" value="#{yourPageBean.tweet}">
    <f:ajax event="keydown" render="charactersRemaining"/>
    <f:ajax event="keyup" render="charactersRemaining"/>
</h:inputTextarea>
<h:outputText id="charactersRemaining" value="#{yourPageBean.charactersRemaining}"/> characters left
Lawrence McAlpin
  • 2,745
  • 20
  • 24
  • What if the delete key is pressed? will that be counted as +1 or -1 – javing May 02 '11 at 18:07
  • It doesn't matter what you press, when the charactersRemaining component is re-rendered, it calls yourPageBean.getCharactersRemaining(), which you could implement quite simply by counting the number of characters in the yourPageBean.tweet string and subtracting that from the total allowed (i.e., return 140 - yourPageBean.tweet.size();). – Lawrence McAlpin May 02 '11 at 18:38
  • will the `keydown` and `keyup` events be triggered in case of pasting text ? – amphibient Sep 17 '15 at 15:45
1

A complication of <textarea> countdown effects stems from the fact that, almost unbelievably, the length that browsers report for a <textarea> element value is not necessarily the actual length of the string that they'll send back to the server when the form is posted.

Here is a jsfiddle that demonstrates the issue. If you type some characters into the <textarea>, the script in the page will update a counter with the current length of the field's value. Type in a couple of characters, hitting "Enter" in between a couple times. Note the length reported. (Hitting "Enter" explicitly is important, as the problem involves explicit newlines.)

If you then click "Go", the server will respond with the HTTP request contents. Count the size of the value of "b" (the name of the <textarea> in the form). Note in particular that newlines are sent as two-character sequences. The browser, however, counts embedded newlines as a single character. Thus, each embedded explicit newline causes the reported length to be 1 less than the length that'll actually be submitted.

That discrepancy can be important, depending on what happens at your server when the parameter is extracted from the HTTP request body. I imagine some server-side environments might fold the CR-LF pairs into plain LF characters, thus getting the effective string length back in harmony with what was reported by the browser before form submittal. However, in my experience, that doesn't happen automaticaly, and in fact you might really not want that behavior anyway. Your server will be checking the length anyway before it saves, or at least the database server will if the ultimate destination is a text column with a maximum length, but it's bad form for the validation code on the page to report an OK situation only for that to be contradicted by a nasty error coming back from the server.

Many of the off-the-shelf JavaScript tools for providing a counter do not account for this behavior.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Also note that browsers differ on newline handling of textareas. Opera basically does value.replace(/\r\n|\r|\n/g, "\r\n") while Safari does value.replace(/\r\n|\r/g, "\n") while Firefox doesn't do any normalizing and just uses \n. These differences affect the count. – Shadow2531 Apr 28 '11 at 16:00
  • @Shadow2531 I have some recollection that what you say is true - trying Opera now ... – Pointy Apr 28 '11 at 16:02
  • @Pointy, pressed enter too quickly. Updated comment. – Shadow2531 Apr 28 '11 at 16:03
  • @Shadow2531 well when I try that fiddle in Opera, it behaves exactly the same way that Chrome and Firefox do. – Pointy Apr 28 '11 at 16:03
  • Anyway the point is that the browser *might* be lying, and that has to be accounted for either in the countdown code or at the server. – Pointy Apr 28 '11 at 16:04
  • Well, it may normalize the value of ` – Pointy Apr 28 '11 at 16:13
  • @Shadow2531 - whoa you're right; jQuery does do something fishy. I'll hit the source :-) – Pointy Apr 28 '11 at 16:17
  • I think i have a little work around idea, but i don't know if i can do that. What do you think about this?: My text area cannot have more than 2000 chars, so could i limit the text area to 100 chars per column and 20 rows? Would it be possible to create an script compatible with that, independently from the browser being used to view the page? – javing Apr 28 '11 at 19:54
  • Well jQuery makes it possible to be compatible because it makes the textarea length be uniformly wrong :-) Thus, if you get the length of the string returned from ".val()", and then add the number of newlines in the string, you'll get the actual size of the value as it will be sent to the server. – Pointy Apr 28 '11 at 20:16
0

Have a look at Count characters in textarea for some JavaScripts doing what you are looking for.

Community
  • 1
  • 1
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

There is a jQuery plugin that does this and is easy to use. And here is another plugin that does what you want quite easily.

Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
  • Neither of those account for the behavior I just reported as [bug 9007](http://bugs.jquery.com/ticket/9007) :-) – Pointy Apr 28 '11 at 16:52