I'm looking for a pure javascript answer as that reflects my projects scope. jQuery answers will not be marked correct, but are welcomed for future question seekers. Side note: I am also not interested in third party libraries.
I'm trying to get the first position (0) of the current line (current is based of selectionStart
the chance the user selects more than 1 line) in a multiline textarea
, but translate that to caret index.
What have I tried? Nothing pretty:
for ( i = 0; i < this.selectionStart; i++ ) {
if (this.value.substr(i,1).match(/\r?\n|\r/)) {
lineStartIndx = i + 1
}
}
This is proving to be costly when iterating textareas with huge amounts of lines. My personal usage of this will not be executed every keydown, however, I just used it as an example. Are there any better methods, built in or otherwise to emulate this outcome?
My full example:
var input = document.getElementById("ta");
var output = document.getElementById("output");
let pattern = /\r?\n|\r/;
var lineNum, lineStartIndx;
input.addEventListener("keydown", function(e) {
taHandler(this);
})
input.addEventListener("click", function(e) {
taHandler(this);
})
function taHandler(elem) {
lineNum = getLineNumForSelection(elem);
let caretPos = elem.selectionStart;
lineStartIndx = 0;
for ( i = 0; i < caretPos; i++ ) {
if (elem.value.substr(i,1).match(pattern)) {
lineStartIndx = i + 1
}
}
output.innerHTML = "Selection Start: " + caretPos + " Selection End: " + elem.selectionEnd +
" <br> Line Number: " + lineNum.start +
"<br>Line Start Position: " + lineStartIndx;
}
function getLineNumForSelection(sel) {
return {
'start' : sel.value.substr(0, sel.selectionStart).split(pattern).length,
'end' : sel.value.substr(0,sel.selectionEnd).split(pattern).length
};
}
<textarea id="ta" rows="5" cols="50">
Line one
Line two
Line three
Line four
</textarea>
<hr>
<div id="output"></div>