How can I get the caret position from within an input field?
I have found a few bits and pieces via Google, but nothing bullet proof.
Basically something like a jQuery plugin would be ideal, so I could simply do
$("#myinput").caretPosition()
How can I get the caret position from within an input field?
I have found a few bits and pieces via Google, but nothing bullet proof.
Basically something like a jQuery plugin would be ideal, so I could simply do
$("#myinput").caretPosition()
Easier update:
Use field.selectionStart
example in this answer.
Thanks to @commonSenseCode for pointing this out.
Old answer:
Found this solution. Not jquery based but there is no problem to integrate it to jquery:
/*
** Returns the caret (cursor) position of the specified text field (oField).
** Return value range is 0-oField.value.length.
*/
function doGetCaretPosition (oField) {
// Initialize
var iCaretPos = 0;
// IE Support
if (document.selection) {
// Set focus on the element
oField.focus();
// To get cursor position, get empty selection range
var oSel = document.selection.createRange();
// Move selection start to 0 position
oSel.moveStart('character', -oField.value.length);
// The caret position is selection length
iCaretPos = oSel.text.length;
}
// Firefox support
else if (oField.selectionStart || oField.selectionStart == '0')
iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;
// Return results
return iCaretPos;
}
else if (oField.selectionStart || oField.selectionStart == '0')
could be else if (typeof oField.selectionStart==='number')
–
Lifesize document.selection
, not field.selection
or something. Also, it was possible in IE 7 (don't know if it is still possible in 8+) to select something, and then TAB out of the field without loosing selection. This way, when the text is selected but the field is not focused, document.selection
returns zero selection. That's why, as a workaround for this bug, you have to focus on the element before reading the document.selection
. –
Rendezvous Use selectionStart
. It is compatible with all major browsers.
document.getElementById('foobar').addEventListener('keyup', e => {
console.log('Caret at: ', e.target.selectionStart)
})
<input id="foobar" />
This works only when no type is defined or type="text"
or type="textarea"
on the input.
.selectionStart
property at any time (document.getElementById('foobar').selectionStart
), it doesn't have to be inside an event listener. –
Rehearsal I've wrapped the functionality in bezmax's answer into jQuery if anyone wants to use it.
(function($) {
$.fn.getCursorPosition = function() {
var input = this.get(0);
if (!input) return; // No (input) element found
if ('selectionStart' in input) {
// Standard-compliant browsers
return input.selectionStart;
} else if (document.selection) {
// IE
input.focus();
var sel = document.selection.createRange();
var selLen = document.selection.createRange().text.length;
sel.moveStart('character', -input.value.length);
return sel.text.length - selLen;
}
}
})(jQuery);
input = $(this).get(0)
the same as input = this
? –
Gd this
refers to a full wrapped set. His code is still wrong though, it should just be this.get(0)
. His code probably still worked because re-wrapping a wrapped set does nothing. –
Yeah Got a very simple solution. Try the following code with verified result-
<html>
<head>
<script>
function f1(el) {
var val = el.value;
alert(val.slice(0, el.selectionStart).length);
}
</script>
</head>
<body>
<input type=text id=t1 value=abcd>
<button onclick="f1(document.getElementById('t1'))">check position</button>
</body>
</html>
I'm giving you the fiddle_demo
slice
is a relatively expensive operation and it adds nothing to this 'solution' -- el.selectionStart
is equivalent to the length of your slice; just return that. Moreover, the reason the other solutions are more complicated is because they deal with other browsers that don't support selectionStart
. –
Orly f1
is about as meaningful as 'user2782001'. 😉 –
Erin There is now a nice plugin for this: The Caret Plugin
Then you can get the position using $("#myTextBox").caret()
or set it via $("#myTextBox").caret(position)
There are a few good answers posted here, but I think you can simplify your code and skip the check for inputElement.selectionStart
support: it is not supported only on IE8 and earlier (see documentation) which represents less than 1% of the current browser usage.
var input = document.getElementById('myinput'); // or $('#myinput')[0]
var caretPos = input.selectionStart;
// and if you want to know if there is a selection or not inside your input:
if (input.selectionStart != input.selectionEnd)
{
var selectionValue =
input.value.substring(input.selectionStart, input.selectionEnd);
}
(function($) {
$.fn.getCursorPosition = function() {
var input = this.get(0);
if (!input) return; // No (input) element found
if (document.selection) {
// IE
input.focus();
}
return 'selectionStart' in input ? input.selectionStart:'' || Math.abs(document.selection.createRange().moveStart('character', -input.value.length));
}
})(jQuery);
Perhaps you need a selected range in addition to cursor position. Here is a simple function, you don't even need jQuery:
function caretPosition(input) {
var start = input[0].selectionStart,
end = input[0].selectionEnd,
diff = end - start;
if (start >= 0 && start == end) {
// do cursor position actions, example:
console.log('Cursor Position: ' + start);
} else if (start >= 0) {
// do ranged select actions, example:
console.log('Cursor Position: ' + start + ' to ' + end + ' (' + diff + ' selected chars)');
}
}
Let's say you wanna call it on an input whenever it changes or mouse moves cursor position (in this case we are using jQuery .on()
). For performance reasons, it may be a good idea to add setTimeout()
or something like Underscores _debounce()
if events are pouring in:
$('input[type="text"]').on('keyup mouseup mouseleave', function() {
caretPosition($(this));
});
Here is a fiddle if you wanna try it out: https://jsfiddle.net/Dhaupin/91189tq7/
const inpT = document.getElementById("text-box");
const inpC = document.getElementById("text-box-content");
// swch gets inputs .
var swch;
// swch if corsur is active in inputs defaulte is false .
var isSelect = false;
var crnselect;
// on focus
function setSwitch(e) {
swch = e;
isSelect = true;
console.log("set Switch: " + isSelect);
}
// on click ev
function setEmoji() {
if (isSelect) {
console.log("emoji added :)");
swch.value += ":)";
swch.setSelectionRange(2,2 );
isSelect = true;
}
}
// on not selected on input .
function onout() {
// الافنت اون كي اب
crnselect = inpC.selectionStart;
// return input select not active after 200 ms .
var len = swch.value.length;
setTimeout(() => {
(len == swch.value.length)? isSelect = false:isSelect = true;
}, 200);
}
<h1> Try it !</h1>
<input type="text" onfocus = "setSwitch(this)" onfocusout = "onout()" id="text-box" size="20" value="title">
<input type="text" onfocus = "setSwitch(this)" onfocusout = "onout()" id="text-box-content" size="20" value="content">
<button onclick="setEmoji()">emogi :) </button>
The solution is .selectionStart
:
var input = document.getElementById('yourINPUTid');
input.selectionEnd = input.selectionStart = yourDESIREDposition;
input.focus();
If .selectionEnd
is not assiged, some text (S-->E) will be selected.
.focus()
is required when the focus is lost; when you trigger your code (onClick).
I only tested this in Chrome.
If you want more complicated solutions, you have to read the other answers.
© 2022 - 2024 — McMap. All rights reserved.
<input>
is way simpler than doing it in a<textarea>
. – Idonahsize
characters. – Ting