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?
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?
 
    
     
    
    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);
 
    
    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.
 
    
    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" >

The first line was empty
Three
Quatro

Fin.</textarea>
<button id="get-line" onclick="getTextAreaCurrentLine(document.getElementById('ta'))">Get line</button>
<br>
<pre id="result"></pre>