4

Using javascript how can I get how many lines a textarea has? in this example I should get 4 (without reading the rows attr)

<textarea rows="4">Long text here foo bar lorem ipsum Long text here foo bar lorem ipsum Long text here foo bar</textarea>

Also, the text area can have a different style than the default one.

Any help? Thanks!

Mati Tucci
  • 2,826
  • 5
  • 28
  • 40
  • In short, you can't. Just run your snippet! It has more than 4 lines. It depends on how the browser renders your textarea. The 'rows' attribute just sets the height before scrollbars are Applied. – Poul Bak Oct 09 '18 at 03:12
  • @PoulBak in my browser it has 4 :(. But there must be a way to get this via js, no? – Mati Tucci Oct 09 '18 at 03:14
  • How about height / lineHeight? – karthikaruna Oct 09 '18 at 03:15
  • @Mati, try running the page in Edge, it has 4 lines visible, but the content is bigger (scrollbars). – Poul Bak Oct 09 '18 at 03:16
  • Are you trying to find the number of rows of text? This might be more than the number that are visible in the textarea (if there is a scrollbar). Or are you trying to find the number of visible rows? I note that it's possible to make a row partially visible, by shrinking the textarea carefully, so the number of visible rows may not be an integer. – John Oct 09 '18 at 03:19

1 Answers1

3

This is a very difficult problem because you can't call getBoundingClientRect() on a range within an <input> or <textarea> element (all browsers return 0s for the rect). See: How to get the bounding rect of selected text inside an <input>?

However, you can "clone" the node as a <div>, copy over the <textarea>'s computed style and text, and find the rects using the <div>. You can get the height of all of the text and divide it by the height of just one character in the selection (the line-height).

I had to do this for a project for work and this was the only reliable way to find geometry information about text inside <input> and <textarea> elements.

const clone = document.createElement('div');
const range = document.createRange();
const textarea = document.querySelector('textarea');

let rect = textarea.getBoundingClientRect();
let lineHeight;
let totalHeight;

// "Clone" the textarea and add it into the DOM
clone.style.cssText = window.getComputedStyle(textarea).cssText;
clone.style.left = rect.left + 'px';
clone.style.position = 'absolute';
clone.style.top = rect.top + 'px';
clone.textContent = textarea.value;
document.body.appendChild(clone);

// Determine the number of visible rows
range.setStart(clone.firstChild, 0);
range.setEnd(clone.firstChild, 1);
rect = range.getBoundingClientRect();
lineHeight = rect.height;

range.setEnd(clone.firstChild, clone.textContent.length);
rect = range.getBoundingClientRect();
totalHeight = rect.height;

console.log(totalHeight / lineHeight);

document.body.removeChild(clone);
<textarea rows="4">Long text here foo bar lorem ipsum Long text here foo bar lorem ipsum Long text here foo bar</textarea>
skyline3000
  • 7,639
  • 2
  • 24
  • 33
  • I should note that this will find the total number of rows even if they are not visible due to scrolling. If you need to know just the visible number of rows, that is also possible but you would use the height of the `textarea` element divided by the height of one character instead. – skyline3000 Oct 09 '18 at 03:47