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>
© 2022 - 2024 — McMap. All rights reserved.