jQuery.Maxlength
jQuery.Maxlength copied to clipboard
Fix length calculation for Mac new lines /r/n
The count is incorrect when entering new lines in a textarea on a Mac. Each new line should count as 2 characters, but jQuery's .length counts /r/n as 1 character.
Hey, thanks for that PR!
I've tried putting a CRLF (\r\n
) inside a textarea on Mac (Mavericks 10.9.4), and both the browser (latest Chrome) and the plugin understood it as a single newline character, which is what I was expecting of them. Same behavior when simply hitting Enter.
I'm thus not sure what the fix you're proposing is for. Does the CR+LF combination usually lead to two newlines on Mac (I don't own one)? Should hitting Enter once create two newlines?
CR+LF lead to 1 new line, but browsers count it as 2 characters. To reproduce, go to your jsfiddle http://jsfiddle.net/pioul/ysC7L/ and type "line" and Enter into the maxlength=50 text area . This should be 5 characters if its just a LF, so you'd expect to be able to enter 10 rows + 1 empty row. On a Mac however the textarea stops taking input on the 9th row, after "li" but your plugin still says "8 characters left"
Here is a video of the issue on the iPad simulator so you can see the that I'm trying to enter characters on the last line when the text still says "8 characters left" but cannot - http://screencast.com/t/xYozYWvL
I'd expect the text to say "0 characters left" when the user has reached the limit.
My apologies for the late reply, I've been extremely busy during the last few months.
Also, thanks for bringing this issue to my attention. Interestingly, I wasn't aware of this discrepancy before, even though it now seems ubiquitous. It might have to do with the fact that the maxlength
attribute is a "recent" addition to textareas, contrarily to regular inputs.
I've run your manual test (type "line", press Enter, repeat until you reach the max) on a small range of browsers I had at hand:
- Chrome (Windows and OS X) counts a line break as 2 distinct characters
- Firefox (Windows and OS X) counts a line break as 1 single character
- IE (Windows) counts a line break as 1 single character
- Safari (OS X) counts a line break as 2 distinct characters
You'll notice I said these browsers were counting line breaks as 1 or 2 characters, without explicitly naming CR+LF
as the pair of characters used to represent line breaks; that's because I couldn't make sure they're in practice encoding line breaks as CR+LF
.
In fact, the W3C HTML 5 spec says that line breaks should be represented as single LF
characters inside a form element's API value, which is the one retrieved using JS.
For historical reasons, the element's value is normalised in three different ways for three different purposes. The raw value is the value as it was originally set. It is not normalized. The API value is the value used in the value IDL attribute. It is normalized so that line breaks use "LF" (U+000A) characters. Finally, there is the form submission value. It is normalized so that line breaks use U+000D CARRIAGE RETURN "CRLF" (U+000A) character pairs [...]
However, it also says that such line breaks should be represented as CR+LF
pairs in the value used for submission. The W3C HTML 4.01 spec also touches on this.
So, I'm not sure what behavior should be implied from these rules – and browser vendors don't seem sure either. If the spec was to be followed thoroughly, all browsers would behave along the following lines:
- Line breaks in textareas are normalized to a single
LF
character - When a form is submitted, those same line breaks should be normalized to a
CR+LF
pair
However, even when following these two rules scrupulously, one question remains regarding a textarea's maxlength
: Should a line break in a textarea's value count as one or two characters?
The HTML 5 spec once again comes to the rescue, stating that the maxlength
attribute's constraint should be evaluated based on "the code-unit length of the element's value". Since a line break in the current value of the textarea should be encoded as a single LF
character, it should only count towards 1 character.
To sum it all up, here's the current state of affairs:
- Line breaks aren't represented by the same set of characters when the form is being filled and when it's submitted: they're respectively represented as single
LF
characters, and thenCR+LF
pairs. - The correct behavior for a browser is to count a line break as 1 character when limiting the form control's value to a maximum length (that's what Firefox and IE seem to be doing).
- Some browsers choose to count a line break as 2 characters for their
maxlength
calculations (Chrome and Safari). I'd like to speculate and say they're doing this to take into account the fact that line breaks will, in fact, be represented as 2 characters when the form will be submitted.
What we're really left with, is another question: What does really matter to us and our users? The current value of the textarea (where line breaks are LF
s), or its future value, the one that'll be submitted with the form (where line breaks are CR+LF
s)?
For us developers, I'd say it depends on how these values are treated, and what the system they're sent to expects in terms of constraint validation.
For users, I don't see any of them expecting line breaks to be counted as 2 characters.
Hence, I'd like every browser to count line breaks as a single character for constraint validation:
- That's what's best for users
- That's what the W3C recommends, and normalization is what's best for us developers
In the meantime, I'm not sure how to make jQuery.maxlength report accurate results when the browsers themselves are wrong: the plugin only monitors the number of characters entered, and leaves constraint validation to the browser, mostly for progressive enhancement purposes.
A solution such as the one you proposed in your PR fixes the issue with Chrome and Safari, which both count line breaks as two characters for constraint validation: entering 10 alphanumeric characters and 2 line breaks will count as 14 characters in the eyes of these browsers, so forcing the plugin to count 2 characters for each line break makes sense.
It doesn't, however, take into account browsers like Firefox and IE, which already got things right. 10 alphanumeric characters and 2 line breaks will be counted as 12 characters, and a regular textarea.value.length
will report the same, accurate length. Your fix would incorrectly make the counter display the number 14 in these browsers.
So, yeah, not sure what can be done. I've starred the Chromium issue, even though someone in there has a different interpretation of the spec than mine. I'd be interested in hearing yours.
If this issue is really important to your use-case, I'd consider using browser sniffing and applying your proposed fix on non-compliant browsers, with all the risks such a thing entails. If not, I'd just wait for this whole situation to be fixed by browsers. In the meantime, since I can't think of any bulletproof way of fixing this at the plugin's level, it'll be left as is. (Unless, of course, someone comes up with a worthwhile solution, which would be incredibly welcome!) I'll add a note about this in the plugin's docs, though.