Reputation: 631
I want to get the caret position inside text area (Internet Explorer only). I have this:
document.activeElement.focus();
var sel2 = document.selection.createRange();
sel2.moveStart('character', -document.activeElement.value.length);
var caretPos = sel2.text.length;
alert(caretPos);
If textarea is one line only I get correct result, but if there are many lines the result is wrong because new line takes extra char that is not visible...
How can I get the correct position value (without removing \r\n and similar dirty work)?
Upvotes: 2
Views: 7837
Reputation: 324547
I would argue that counting line breaks as two characters when calculating selection boundaries/cursor position is the correct approach. Fundamentally, those two characters \r\n
are there in the text. They are present in the textarea's value
property and they are in the value that is submitted to the server.
The only arguments I can see for counting line breaks as one character are:
TextRange
methods consider the line breaks as one characterI think neither is valid. Firstly, IE is already inconsistent with other browsers in counting line breaks as two characters rather than one. Secondly, IE's TextRange
character-based methods are a little insane anyway, causing problems wherever they're used.
I think it makes total sense to consider the selection/caret position as a position relative to the actual text in the textarea. This allows easy manipulation of the text.
Here are two main functions. The first is the only textarea selection/caret position getting function I've seen that works correctly with all line breaks. You can find this here:
How to get the start and end points of selection in text area?. Second, here's a complementary setSelection
function:
function offsetToRangeCharacterMove(el, offset) {
return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
}
function setSelection(el, startOffset, endOffset) {
var range = el.createTextRange();
var startCharMove = offsetToRangeCharacterMove(el, startOffset);
range.collapse(true);
if (startOffset == endOffset) {
range.move("character", startCharMove);
} else {
range.moveEnd("character", offsetToRangeCharacterMove(el, endOffset));
range.moveStart("character", startCharMove);
}
range.select();
}
Upvotes: 1