I have an html textarea that will be updated periodically via javascript.
when I do this:
$("#textarea").val(new_val);
The cursor moves to the end of the text.
I would like to update the text without changing the cursor position. Also, if the user has a range of text selected, the highlight should be preserved.
To set the cursor at the end of a textarea: Use the setSelectionRange() method to set the current text selection position to the end of the textarea. Call the focus() method on the textarea element. The focus method will move the cursor to the end of the element's value.
<textarea> does not support the value attribute.
Alternatively, you can use jQuery's . html() method, which uses the browser's innerHTML property to replace textarea content with the new content completely. Another good solution is to use the . val() method to set the text value of the textarea element.
Here is a pair of functions that get and set the selection/caret position in a text area in all major browsers.
Note: if you don't need to support IE <= 8, just use the selectionStart
and selectionEnd
properties (MDN). All of the complicated code below is just there to support old versions of IE.
function getInputSelection(el) {
var start = 0, end = 0, normalizedValue, range,
textInputRange, len, endRange;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
}
function offsetToRangeCharacterMove(el, offset) {
return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
}
function setInputSelection(el, startOffset, endOffset) {
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
el.selectionStart = startOffset;
el.selectionEnd = endOffset;
} else {
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();
}
}
When you change the textarea's value, first save the selection, then restore it afterwards:
var t = document.getElementById("textarea");
var sel = getInputSelection(t);
t.value = some_new_value;
setInputSelection(t, sel.start, sel.end);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With