Find value of current line of a <textarea> using javascript
Asked Answered
K

3

2

How can I find the value of the current line of a textarea?

I know I have to find the caret position, but then find everything before it up to the last \n and everything after it to the next \n.

How can I do this?

Komsomolsk answered 30/6, 2010 at 22:53 Comment(0)
S
6

A simple way would be to just loop:

var caretPos = 53, // however you get it
    start, end
;

for (start = caretPos; start >= 0 && myString[start] != "\n"; --start);
for (end = caretPos; end < myString.length && myString[end] != "\n"; ++end);

var line = myString.substring(start + 1, end - 1);
Shaper answered 30/6, 2010 at 22:58 Comment(0)
S
3

In line with nickf's answer, the following example (which uses jQuery) may be a bit faster because it uses (lastI|i)ndexOf:

function current_line(textarea) {
  var $ta = $(textarea),
      pos = $ta.getSelection().start, // fieldselection jQuery plugin
      taval = $ta.val(),
      start = taval.lastIndexOf('\n', pos - 1) + 1,
      end = taval.indexOf('\n', pos);

  if (end == -1) {
      end = taval.length;
  }

  return taval.substr(start, end - start);
}

Here it is on jFiddle.

Shantell answered 8/11, 2011 at 2:22 Comment(1)
Thanks for the indexOf approach!Downtime
H
0

How about a one-liner :)

// after getting a textarea into el

sLine = el.value.substring(el.value.lastIndexOf('\n', el.selectionStart -1) + 1, ((end = el.value.indexOf('\n', el.selectionStart) - 1) => end > -1 ? end : undefined)());

This works because substring gives everything after start when end is undefined.

Start works nicely because lastIndexOf returns -1 when selection is on the first line and \n is not found. Since we are already adding 1 for a found result that gets us to 0.

End is trickier. To get an undefined when \n is not found so that the rest of the string is returned, a self-executing (IIEF) arrow function works.

Ackk, edge cases! lastIndexOf fails because for some reason it treats a start of -1 as zero instead of just returning -1 so if the selection start is on the first line and it's a blank line lastIndexOf finds the new line character at zero then when we add 1, '\n'.substring(1,0) // ='\n' The above and previous answers to this question here give the first line as '\n' instead of the empty string. To handle that edge case slice works:

// after getting a textarea into el
sline = el.value.slice(el.value.lastIndexOf('\n', el.selectionStart - 1) + 1, ((end = el.value.indexOf('\n', el.selectionStart)) => end > -1 ? end : undefined)());

function getTextAreaCurrentLine(el) {
    let line = '';
    if (el instanceof HTMLTextAreaElement) {
        // unlike substring, slice gives empty string when (1,0)
        line = el.value.slice(el.value.lastIndexOf('\n', el.selectionStart - 1) + 1,  
        ((end = el.value.indexOf('\n', el.selectionStart)) => end > -1 ? end : undefined)());
    }
    document.getElementById('result').innerHTML = '"'+line+'"';
}
<textarea id="ta" type="text" spellcheck="false" rows="8" cols="40" autocomplete="off" >&#10;&#10;The first line was empty&#10;Three&#10;Quatro&#10;&#10;Fin.</textarea>
<button id="get-line" onclick="getTextAreaCurrentLine(document.getElementById('ta'))">Get line</button>
<br>
<pre id="result"></pre>
Huttan answered 11/1, 2022 at 0:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.