4

I'm trying to make a character counter that mimics a phone for . I've got it counting characters, spaces, and line breaks, however my counters differ. With line breaks, it decrements by 1 in the count for message.length, but does for more than one in the maxlength. I'm thinking that more spaces are added in when indented, but not sure how to get the message.length set the same as maxlength.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app>
  <textarea ng-model="message" ng-trim="false" maxlength="160"></textarea>
  <span>{{160 - message.length}} left</span>
</body>

Also this answer doesn't actually work for this (it counts spaces and line breaks as 1): angularjs text area character counter

Community
  • 1
  • 1
  • the reason that answer doesn't work is because ng-trim is set to false. Set it to true and it doesn't count spaces – Sir Neuman Jun 16 '15 at 18:34
  • Oh, I apologize for not being clear- I do need it to count spaces and line breaks, but ng-trim counts them both as 1; however SMS counts line breaks as 2. I'm looking for a way to accurately count line breaks as 2 to match with the maxlength. – Anna Laura Davenport Jun 16 '15 at 18:38
  • possible duplicate of [Chrome counts characters wrong in textarea with maxlength attribute](http://stackoverflow.com/questions/10030921/chrome-counts-characters-wrong-in-textarea-with-maxlength-attribute) – Naftali Jul 13 '15 at 12:57

2 Answers2

5

So the only thing you need to count as two characters are actual line breaks (line breaks entered manually by the user, not “virtual” line breaks caused by the text being longer than the textarea width allows)?

Then I’d suggest this:

<span>{{160 - message.length - (message.length ? message.split("\n").length-1 : 0)}} left</span>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app>
  <textarea ng-model="message" ng-trim="false" maxlength="160"></textarea>
  <span>{{160 - message.length - (message.length ? message.split("\n").length-1 : 0)}} left</span>
</body>

message.split("\n").length counts the number of parts you get after you split the message at line breaks. A message without a line break gets you one “part”, a message with one line break gets you two parts, etc. – hence the -1. And splitting an empty string still gets you one result, therefor the check if the message has a length at all first.

By definition, a browser has to return line breaks in a textarea’s value as \n – those are counted as one character by message.length already, so we just subtract the number of \n characters again, thereby counting each \n as two characters in the result. (I suppose they are counted as two in an SMS text message length, because that might actually be using \r\n for line breaks.)

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
CBroe
  • 91,630
  • 14
  • 92
  • 150
0

You can replace newline characters by a string of length 2 before evaluating the length, as follows:

<span>{{160 - message.replace('\n', '--').length}} left</span>

see this fiddle (I have reduced the max length in the fiddle to 10 for easier testing):

http://jsfiddle.net/9DbYY/307/

Remigius Stalder
  • 1,921
  • 2
  • 26
  • 31