Chrome counts characters wrong in textarea with maxlength attribute

Go To StackoverFlow.com

39

Here is an example:

$(function() {
  $('#test').change(function() {
    $('#length').html($('#test').val().length)
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id=test maxlength=10></textarea>
length = <span id=length>0</span>

Fill textarea with lines (one character at one line) until browser allows. When you finish, leave textarea, and js code will calculate characters too.

So in my case I could enter only 7 characters (including whitespaces) before chrome stopped me. Although value of maxlength attribute is 10:

imgur

2012-04-05 14:52
by Roman Pominov
Similar: http://stackoverflow.com/q/12924591/26653 - styfle 2012-10-31 00:06
OR or might be this: http://stackoverflow.com/questions/11839413/textarea-character-counter-using-jquer - Tats_innit 2013-09-26 00:09


27

Your carriage returns are considered 2 characters each when it comes to maxlength.

1\r\n
1\r\n
1\r\n
1

But it seems that the javascript only could one of the \r\n (I am not sure which one) which only adds up to 7.

2012-04-05 14:56
by Neal
I've logged bugs on this issue in both Chrome and Firefox; it seems to be fixed in Chrome's latest version - Pointy 2012-04-05 14:57
@Pointy I am in the dev version of Chrome (19.0.1084.1) and I still have this issue - Neal 2012-04-05 14:59
Yep, i think so too. But why js doesn't count carriage returns as 2 characters? Is there way to make it do that - Roman Pominov 2012-04-05 15:00
@Pozadi I have no idea.. - Neal 2012-04-05 15:01
When the contents of a textarea are actually posted, embedded newlines must be transmitted as CR LF pairs. Thus, the correct thing to do is for the browser to report the length of the contents as if newlines cost 2 characters - Pointy 2012-04-05 15:02
@Neal oh well I was going by a comment on the OP. It seems like a pretty serious problem in that it renders the "maxlength" attribute basically useless - Pointy 2012-04-05 15:03
@Pointy -- http://stackoverflow.com/q/10031112/56173 - Neal 2012-04-05 15:03
Ah well I just typed in an answer here; I'll copy it there and community wiki it - Pointy 2012-04-05 15:07
Here's a fix as an angular expression: http://stackoverflow.com/a/30875979/125348 - spsaucier 2015-07-12 23:01


34

Here's how to get your javascript code to match the amount of characters the browser believes is in the textarea:

http://jsfiddle.net/FjXgA/53/

$(function () {
    $('#test').keyup(function () {
        var x = $('#test').val();

        var newLines = x.match(/(\r\n|\n|\r)/g);
        var addition = 0;
        if (newLines != null) {
            addition = newLines.length;
        }

        $('#length').html(x.length + addition);
    })
})

Basically you just count the total line breaks in the textbox and add 1 to the character count for each one.

2013-07-04 04:50
by Tim
Could also be written as: $('#length').html(x.replace(/(\r\n|\n|\r)/g, '--').length);noitseuq 2014-03-10 17:57
http://jsfiddle.net/FjXgA/53/

above link is useful. thank - Yogendra Joshi 2014-04-28 10:36

This works wrong in Firefox because it counts newline as 1 characte - Stalinko 2015-12-10 05:10
@Stalinko I just tested this in Firefox, Chrome, IE, Edge, and Opera. It appears to work the same in all of them. Newlines add 2 to the length. Is that what you saw or did you mean something else - nmit026 2017-01-23 20:22
@Tim, even though the script displays the length correctly its allowing to enter more characters if carriage return is already present. I was able to key in 12 characters after putting in 2 carriage returns - Nevin 2018-02-05 00:02


14

For reasons unknown, jQuery always converts all newlines in the value of a <textarea> to a single character. That is, if the browser gives it \r\n for a newline, jQuery makes sure it's just \n in the return value of .val().

Chrome and Firefox both count the length of <textarea> tags the same way for the purposes of "maxlength".

However, the HTTP spec insists that newlines be represented as \r\n. Thus, jQuery, webkit, and Firefox all get this wrong.

The upshot is that "maxlength" on <textarea> tags is pretty much useless if your server-side code really has a fixed maximum size for a field value.

edit — at this point (late 2014) it looks like Chrome (38) behaves correctly. Firefox (33) however still doesn't count each hard return as 2 characters.

2012-04-05 15:06
by Pointy
Pointy -- I just asked a question related to this OPNeal 2012-04-05 15:07
Right-o - I'll copy this there - Pointy 2012-04-05 15:07
It seems like you are saying .val() returns it wrong (1 character), but the browser correctly sees it as 2 characters, so the maxlength would take into account 2 characters for each newline. If that's the case, and your backend database has a fixed max, I don't see how maxlength is useless, because it correctly counts the amount of characters as they will be saved in the database - wired_in 2014-10-29 21:07
@wired_in hi again :) The problem is that the built-in maxlength check does not take into account the CR characters. That means that the built-in maxlength will allow the textarea to contain more actual characters in the client than are allowed. So, if you have a database field that's 500 characters long, and you say maxlength=500, a posted form may contain a value with more than 500 characters. The attribute is therefore useless - Pointy 2014-10-30 04:32
@Pointy That contradicts this question. The OP is saying that he has a textarea, with a maxlength of 10, but he is only able to type 7 characters (which includes 1 character for each newline) when he types in the textarea. This clearly shows that the maxlength is taking into account the 2 characters for each new line. My own testing confirms this.. - wired_in 2014-10-30 16:14
@wired_in what browser are you using? Internet Explorer has always behaved correctly (well, going back to IE6 at least). It didn't support maxlength on <textarea> but it correctly reported the length of the value (that is, it included the carriage return count) - Pointy 2014-10-30 16:16
@Pointy I'm using chrome, but the OP of this question clearly got the same results... This is easy to test. Look at the fiddle in the question. It's a javascript/jQuery issue, not a maxlength attribute problem - wired_in 2014-10-30 16:17
@Pointy, also look at the accepted answer to this question - wired_in 2014-10-30 16:20
Right. In the fiddle posted with the question, if you type "1", "2", "3", etc, following each one by a hard return, you can type up to "5". That should not be possible, because each line is 3 characters long: the digit, the CR, and the LF. But I'm on Firefox; the Chrome people must have actually fixed it, which makes me happy. (I got the most obnoxious pushback from the Firefox devs : - Pointy 2014-10-30 16:20
Let us continue this discussion in chat - wired_in 2014-10-30 16:21
upvote for the info about maxlength being useless on textarea fields - Barry Guvenkaya 2015-12-14 02:17


13

It seems like the right method, based on Pointy's answer above, is to count all new lines as two characters. That will standardize it across browsers and match what will get sent when it's posted.

So we could follow the spec and replace all occurrences of a Carriage Return not followed by a New Line, and all New Lines not followed by a Carriage Return, with a Carriage Return - Line Feed pair.

var len = $('#test').val().replace(/\r(?!\n)|\n(?!\r)/g, "\r\n").length;

Then use that variable to display the length of the textarea value, or limit it, and so on.

2014-01-31 18:57
by matt


3

It looks like that javascript is considering length of new line character also.

Try using:


var x = $('#test').val();

x = x.replace(/(\r\n|\n|\r)/g,"");    

$('#length').html(x.length);

I used it in your fiddle and it was working. Hope this helps.

2012-04-05 15:03
by anuragsn7


1

That is because an new line is actually 2 bytes, and therefore 2 long. JavaScript doesn't see it that way and therefore it will count only 1, making the total of 7 (3 new lines)

2012-04-05 14:56
by Rene Pot


1

Here's a more universal solution, which overrides the jQuery 'val' function. Will be making this issue into a blog post shortly and linking here.

var originalVal = $.fn.val;
$.fn.val = function (value) {
    if (typeof value == 'undefined') {
        // Getter

        if ($(this).is("textarea")) {
            return originalVal.call(this)
                .replace(/\r\n/g, '\n')     // reduce all \r\n to \n
                .replace(/\r/g, '\n')       // reduce all \r to \n (we shouldn't really need this line. this is for paranoia!)
                .replace(/\n/g, '\r\n');    // expand all \n to \r\n

            // this two-step approach allows us to not accidentally catch a perfect \r\n
            //   and turn it into a \r\r\n, which wouldn't help anything.
        }

        return originalVal.call(this);
    }
    else {
        // Setter
        return originalVal.call(this, value);
    }
};
2014-12-18 16:10
by Stachu
Awesome blog post bt - Kristopher 2017-03-22 18:08
Thanks, man. I appreciate the appreciation - Stachu 2017-03-22 18:14


0

var value = $('#textarea').val();
var numberOfLineBreaks = (value.match(/\n/g)||[]).length;
$('#textarea').attr("maxlength",500+numberOfLineBreaks);

works perfectly on google already in IE have to avoid the script! In IE the 'break-line' is counted only once, so avoid this solution in IE!

2015-05-09 00:54
by Fabio
This fails when pasting - NoName 2015-07-29 16:43


0

If you want to get remaining content length of text area then you can use match on the string containing the line breaks.

HTML:

<textarea id="content" rows="5" cols="15" maxlength="250"></textarea>

JS:

var getContentWidthWithNextLine = function(){
    return 250 - content.length + (content.match(/\n/g)||[]).length;
}
2015-05-23 09:50
by Rubi saini


0

Textareas are still not fully in sync among browsers. I noticed 2 major problems: Carriage returns and Character encodings

Carriage return

By default are manipulated as 2 characters \r\n (Windows style).

The problem is that Chrome and Firefox will count it as one character. You can also select it to observe there is an invisivle character selected as a space.

A workaround is found here:

var length = $.trim($(this).val()).split(" ").join("").split('\n').join('').length;

Jquery word counts when user type line break

Internet explorer on the other hand will count it as 2 characters.

Their representation is :

Binary: 00001101 00001010

Hex: 0D0A

, and are represented in UTF-8 as 2 characters and counted for maxlength as 2 characters.

The HTML entities can be

1) Created from javascript code:

<textarea id='txa'></textarea>

document.getElementById("txa").value = String.fromCharCode(13, 10);

2) Parsed from the content of the textarea:

Ansi code: &#13;&#10;

<textarea>Line one.&#13;&#10;Line two.</textarea>

3) Inserted from keyboard Enter key

4) Defined as the multiline content of the textbox

<textarea>Line one.
Line two.</textarea>

Character Encoding

Character encoding of an input field like textarea is independent than the character encoding of the page. This is important if you plan to count the bytes. So, if you have a meta header to define ANSI encoding of your page (with 1 byte per character), the content of your textbox is still UTF-8 with 2 bytes per character.

A workaround for the character encoding is provided here:

function htmlEncode(value){
  // Create a in-memory div, set its inner text (which jQuery automatically encodes)
  // Then grab the encoded contents back out. The div never exists on the page.
  return $('<div/>').text(value).html();
}

function htmlDecode(value){
  return $('<div/>').html(value).text();
}

HTML-encoding lost when attribute read from input field

2017-07-23 02:12
by profimedica
Ads