5

I need some function That will count rows ( i know that on stackoverflow there are more than hundreds of these questions) but in my case i need to count them even when there is no end of line (mean "/n") because typical function is

textarea.value.substr(0, textarea.selectionStart).split("\n").length;.

It means that if user overflows max length of the row but he doesn't use "enter" and the text is on "new line". Well, i dont know how to describe it better, so there is a example on fiddle https://jsfiddle.net/fNPvf/12872/ try to write long sentence with no spaces, enters etc.. and you will see where the problem is

what i really don't want is css rule nowrap, overflow-x etc..

j08691
  • 204,283
  • 31
  • 260
  • 272
Kuba Šimonovský
  • 2,013
  • 2
  • 17
  • 35

2 Answers2

14

Here you go.

/** @type {HTMLTextAreaElement} */
var _buffer;

/**
* Returns the number of lines in a textarea, including wrapped lines.
*
* __NOTE__:
* [textarea] should have an integer line height to avoid rounding errors.
*/
function countLines(textarea) {
    if (_buffer == null) {
        _buffer = document.createElement('textarea');
        _buffer.style.border = 'none';
        _buffer.style.height = '0';
        _buffer.style.overflow = 'hidden';
        _buffer.style.padding = '0';
        _buffer.style.position = 'absolute';
        _buffer.style.left = '0';
        _buffer.style.top = '0';
        _buffer.style.zIndex = '-1';
        document.body.appendChild(_buffer);
    }

    var cs = window.getComputedStyle(textarea);
    var pl = parseInt(cs.paddingLeft);
    var pr = parseInt(cs.paddingRight);
    var lh = parseInt(cs.lineHeight);

    // [cs.lineHeight] may return 'normal', which means line height = font size.
    if (isNaN(lh)) lh = parseInt(cs.fontSize);

    // Copy content width.
    _buffer.style.width = (textarea.clientWidth - pl - pr) + 'px';

    // Copy text properties.
    _buffer.style.font = cs.font;
    _buffer.style.letterSpacing = cs.letterSpacing;
    _buffer.style.whiteSpace = cs.whiteSpace;
    _buffer.style.wordBreak = cs.wordBreak;
    _buffer.style.wordSpacing = cs.wordSpacing;
    _buffer.style.wordWrap = cs.wordWrap;

    // Copy value.
    _buffer.value = textarea.value;

    var result = Math.floor(_buffer.scrollHeight / lh);
    if (result == 0) result = 1;
    return result;
}

Demo here

Kin
  • 1,522
  • 1
  • 13
  • 11
  • 1
    well, this looks really promising. Unfortunately, this is 2 years old topic. I am no longer working on this project :D. Anyway, thanks for the time you spend here, and I hope, that upvote will make you satisfied. Maybe for someone in future, this answer will be usefull – Kuba Šimonovský Jul 24 '17 at 13:52
  • 2
    I'm using the Dart version of this function to create a custom text area (similar to paper-textarea) that can auto grow/shrink based on its value. To enable that feature, I did a lot of search on how to count the number of lines in a text area but couldn't find a good answer. Then, I came up with this function and shared it here so others can use. – Kin Jul 25 '17 at 08:25
  • Oh my! I spent nearly 4 hours tweaking with canvas and DOM elements to create text element, count width and divide by the width of the textArea width. Something like this answer. But for some reason my solutions didn't work for all characters! I didn't try playing with the height and line height! This works perfectly well even with emojis and big UTF-8 characters and all that stuff! – 15 Volts Dec 19 '22 at 19:27
0

If I'm understanding the problem correctly, you need to count two things.

  1. The number of hard line breaks "\n".
  2. The number of lines that wrap past X characters.

Here's some pseudo code:

var lineLengthLimit = 40;
var lineCounter = 0;

foreach(lines as line){
    lineCounter+=Math.floor(line.length/lineLengthLimit);
}

lineCounter += lines.length;

Another option might be what this guy suggested: https://stackoverflow.com/a/3697249/1207539 but it seems a bit sketchy.

Community
  • 1
  • 1
Matt
  • 5,315
  • 1
  • 30
  • 57