45

What I would like is to count the number of lines in a textarea, e.g:

line 1
line 2
line 3
line 4

should count up to 4 lines. Basically pressing enter once would transfer you to the next line

The following code isn't working:

var text = $("#myTextArea").val();   
var lines = text.split("\r");
var count = lines.length;
console.log(count);

It always gives '1' no matter how many lines.

Ali
  • 261,656
  • 265
  • 575
  • 769

16 Answers16

71

The problem with using "\n" or "\r" is it only counts the number of returns, if you have a line that is long it could wrap and then it wouldn't be counted as a new line. This is an alternative way to get the number of lines - so it may not be the best way.

Edit (thanks alex):

Script

$(document).ready(function(){
 var lht = parseInt($('textarea').css('lineHeight'),10);
 var lines = $('textarea').attr('scrollHeight') / lht;
 console.log(lines);
})

Update: There is a much more thorough answer here: https://stackoverflow.com/a/1761203/145346

Community
  • 1
  • 1
Mottie
  • 84,355
  • 30
  • 126
  • 241
  • 3
    you could lessen maintenance with `var lineheight = $('textarea#my-textarea').css('line-height'); – alex Jan 10 '10 at 08:53
  • 2
    That doesn't seem to return the correct line height, you have to set it. – Mottie Jan 10 '10 at 16:09
  • It will only return it in pixels, I believe. – alex Jan 11 '10 at 06:35
  • 8
    I think you need to replace `attr` with `prop`, at least `attr` didn't work for me, it returned undefined every time... – benomatis Mar 30 '14 at 21:30
  • 8
    @webeno it depends on the version of jQuery that you use. As of jQuery v1.6, you need to use `prop()` instead of `attr()` ([ref](http://api.jquery.com/prop/#prop2)) – Mottie Mar 31 '14 at 12:14
  • 8
    This example doesn't take padding in consideration. When adding padding, I get the correct number: `var padding = parseInt($('textarea').css('paddingTop'),10) + parseInt($('textarea').css('paddingBottom'),10) var lines = ($('textarea').prop('scrollHeight') - padding) / lineheight;` – dnlmzw Jan 02 '15 at 13:13
  • There is a much more thorough answer here: http://stackoverflow.com/a/1761203/145346 – Mottie Aug 29 '15 at 17:12
  • 1
    This will work if your text is bigger than the textarea. If you are trying to expand AND contract the textarea altogether with your text you should always reset the rows property of the textarea element before applying this solution. It lead me to the right path though. So, thanks. – luckasfrigo Oct 12 '17 at 17:52
40

If you are just wanting to test hard line returns, this will work cross platform:

var text = $("#myTextArea").val();   
var lines = text.split(/\r|\r\n|\n/);
var count = lines.length;
console.log(count); // Outputs 4
Doug Neiner
  • 65,509
  • 13
  • 109
  • 118
  • 1
    You can even a whack a `.trim()` after `.val()` if you don't want to count empty line returns at the end: `$("#myTextArea").val().trim();` – Jarrod Feb 16 '21 at 23:01
27

I have implemented the lines and lineCount methods as String prototypes:

String.prototype.lines = function() { return this.split(/\r*\n/); }
String.prototype.lineCount = function() { return this.lines().length; }

Apparently the split method will not count a carriage return and/or newline character at the end of the string (or the innerText property of a textarea) in IE9, but it will count it in Chrome 22, yielding different results.

So far I have accomodated for this by subtracting 1 from the line count when the browser is other than Internet Explorer:

String.prototype.lineCount = function() { return this.lines().length - navigator.userAgent.indexOf("MSIE") != -1); }

Hopefully someone has a better RegExp or another workaround.

hector-j-rivas
  • 771
  • 8
  • 21
  • After further testing, I discovered that any whitespace after the last newline character and before the closing tag also counts as an extra element in the split -in other than IE9 browsers. – hector-j-rivas Oct 27 '12 at 13:28
  • this post is a little old, but just for info, I think I found a workaround: the use of a `contenteditable` element instead of a textarea: [http://stackoverflow.com/a/22732344/2037924](http://stackoverflow.com/a/22732344/2037924)... – benomatis Mar 30 '14 at 21:48
  • It work when I press enter, but it doesn't work for long text appearing in few lines. – RaV Sep 01 '16 at 11:31
  • 1
    How are you adding the text? When are you trying to get the count? Make sure to trigger the count after adding the initial text... How long is the text? There's no particular limit, but 64K is theorized as the limit. Also, make sure the maxLength attribute is not defined on your text area. Finally, this is pure JavaScript working on any JavaScript string, it just so happens that the OP wanted to apply to the text area's value (a JavaScript string). – hector-j-rivas Sep 01 '16 at 15:03
  • This is nonsense. Long lines of text **without spaces** are being wrapped inside a textarea, and here's no `\n` to split. – Roko C. Buljan Dec 02 '21 at 14:30
  • @RokoC.Buljan, not sure how long lines without spaces would be considered human-readable "text"; you'd have to break them and use some word wrapping algorithm to get lines (a problem Mottie's answer alludes to). The answer was for the OP's question regarding breaking lines as defined by new line characters. – hector-j-rivas Dec 11 '21 at 19:45
9

user \n instead of \r

var text = $("#myTextArea").val();   
var lines = text.split("\n");
var count = lines.length;
console.log(count);
Marek Karbarz
  • 28,956
  • 6
  • 53
  • 73
4

However this is working if you need use it because it respond to your problem

let text = document.getElementById("myTextarea").value;   
let lines = text.split(/\r|\r\n|\n/);
let count = lines.length;
console.log(count);
Ir Calif
  • 460
  • 6
  • 7
3

What about splitting on "\n" instead?

It will also be a problem where one line wrapped to 2 lines in the textarea.

To do it accurately like this, you could use a fixed height font and measure pixels. This could be problematic though.

alex
  • 479,566
  • 201
  • 878
  • 984
3

This function counts the number of lines which have text in a textarea:

function countLine(element) {
  var text = $(element).val();
  var lines = text.split("\n");
  var count = 0;
  for (var i = 0; i < lines.length-1; i++) {
    if (lines[i].trim()!="" && lines[i].trim()!=null) {
      count += 1;
    }
  }
  return count;
}
AJPerez
  • 3,435
  • 10
  • 61
  • 91
Tran Duy
  • 31
  • 1
2

Counting the newlines is not a reliable way for finding the number of lines, since long text could simply break and still only count as a single line. What you want to do, is find out the scrollHeight of the textarea and divide it by the height of a single line.

This is answered in detail here: https://stackoverflow.com/a/1761203/9863305

Philipp Poropat
  • 131
  • 1
  • 6
1

I've used the original answer of Mottie but some functions were changed in the JQuery API. Here is the working function for the current API v3.1.0:

var lht = parseInt($('#textarea').css('lineHeight'),10);
    var lines = $('#textarea').prop('scrollHeight') / lht;
    console.log(lines);

All tumbs up for Mottie's answer!

Quispie
  • 948
  • 16
  • 30
1

This will aim to consider lines with both hard and soft returns:

    //determine what the fontsize will be
    let fontsize = 12;
    //get number of characters that can fit in a row
    let charsperrow = textarea.clientWidth / fontsize;
    //get any hard returns
    let hardreturns = textarea.textContent.split(/\r|\r\n|\n/);
    let rows = hardreturns.length;
    //loop through returns and calculate soft returns
    for(let i = 0,len = rows; i < len; i++){
        let line = hardreturns[i];
        let softreturns = Math.round(line.length / charsperrow);
        //if softreturns is greater than 0, minus by 1 (hard return already counted)
        softreturns = Math.round(softreturns > 0 ? (softreturns - 1) : 0);
        rows += softreturns;
    }
    console.log(Math.round(rows));
milesholt
  • 161
  • 1
  • 9
  • this doesn't take into account the position of the last white-space for word wrap as soft returns don't always happen always on chars per row, but it's quite good start ;) – qdev Nov 19 '20 at 05:57
0

The normal newline character is "\n". The convention on some systems is to also have "\r" beforehand, so on these systems "\r\n" is often found to mean a new line. In a browser, unless the user intentionally enters a "\r" by copying it from somewhere else, the newline will probably be expressed as just "\n". In either case splitting by "\n" will count the number of lines.

Danny Roberts
  • 3,442
  • 23
  • 28
0
<html>
<head>
<script>
function countLines(theArea){
var theLines = theArea.value.replace((new RegExp(".{"+theArea.cols+"}","g")),"\n").split("\n");
if(theLines[theLines.length-1]=="") theLines.length--;
theArea.form.lineCount.value = theLines.length;
}
</script>
</head>
<body>
<form>
<textarea name="myText" onKeyUp="countLines(this)" cols="10" rows="10">
</textarea>
<br>
Lines:
<input type=text name="lineCount" size="2" value="0">
</form>
</body>
</html>
humo
  • 23
  • 5
0

Your ans can be done in very simple way.

var text = $("#myTextArea").val();

               // will remove the blank lines from the text-area
                text = text.replace(/^\s*[\r\n]/gm, "");

               //It will split when new lines enter
                var lines = text.split(/\r|\r\n|\n/);

             var count = lines.length; //now you can count thses lines.
                console.log(count);

This code for exact lines filled in the textarea. and will work for sure.

Bachas
  • 233
  • 6
  • 16
0

Instead of textarea you could use a div with the attribute contenteditable="true". On a div with this attribute you can write anything, just like in a textarea, but any new line (except the first) is automatically wrapped inside a div. You can use jQuery or JS to count the div's and add +1, which is the first line.

It's a no brainer, i would use this instead of textarea with every occasion. It has several advantages. It auto resizes, you can easily count blank lines, you can customize every div or add spans with colors or font sizes or anything, you can use any line-height and any font-size, you can add rich text features and more, it's better for SEO and more. Here is a working example with jQuery:

    $("#Editor").on("keyup mouseup", function(){
        blankSpace = $(this).find("br").length; //count blank lines
        urlCounter = $(this).find("div").length + 1 - blankSpace;

        $(".lineCounter").text("Number of links: "+ urlCounter);
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Editor" contenteditable="true" style="color:aqua;width: 100%;height: 100%;background: blue;"></div>
<div class="lineCounter" style="position: absolute;bottom: 0;z-index: 999;left: 0;"></div>
EPurpl3
  • 682
  • 7
  • 25
0

Try calling this function every time you change its value.

 textArea.addEventListener('input', function() {
        setDynamicHeight();
 });

 function setDynamicHeight() {
    textArea.style.height = 0; // set the height to 0 in case of it has to be shrinked
    textArea.style.height = textArea.scrollHeight + 'px'; // set the dynamic height
}
0

Each line break is defined by '\n'. The goal is to count them. For this, we will have to iterate on this with a loop on each character. See the example below

  let count = 0
  const a = document.querySelector('textarea')
  for (let i = 0; i < a.value.length; i++) {
    if (a.value[i] == '\n') {
      count++
    }
  }
  console.log(count)

In this live demonstration we can see a concrete case with 3 sentences :

const textareaLineCount = () => {
  let count = 0
  const a = document.querySelector('textarea')
  for (let i = 0; i < a.value.length; i++) {
    if (a.value[i] == '\n') {
      count++
    }
  }
  return count
}

const displayTotalTextareaLine = (total) => {
  document.querySelector('p').innerText = total
}

document.querySelector('button').addEventListener('click', () => {
  const total = textareaLineCount()
  displayTotalTextareaLine(total)
})
<textarea>
  Lorem ipsum dolor sit amet.
  Lorem ipsum dolor sit amet.
  Lorem ipsum dolor sit amet.
</textarea>
<button>count</button>
<p></p>

⚠️ It's possible that the last phase is not a line break, so I advise you to add 1 to the total result

ddos-san
  • 11
  • 2
  • 1
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Dharman Aug 11 '21 at 17:35