[javascript] Set keyboard caret position in html textbox

Does anybody know how to move the keyboard caret in a textbox to a particular position?

For example, if a text-box (e.g. input element, not text-area) has 50 characters in it and I want to position the caret before character 20, how would I go about it?

This is in differentiation from this question: jQuery Set Cursor Position in Text Area , which requires jQuery.

This question is related to javascript textbox input

The answer is


Excerpted from Josh Stodola's Setting keyboard caret Position in a Textbox or TextArea with Javascript

A generic function that will allow you to insert the caret at any position of a textbox or textarea that you wish:

function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);

    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}

The first expected parameter is the ID of the element you wish to insert the keyboard caret on. If the element is unable to be found, nothing will happen (obviously). The second parameter is the caret positon index. Zero will put the keyboard caret at the beginning. If you pass a number larger than the number of characters in the elements value, it will put the keyboard caret at the end.

Tested on IE6 and up, Firefox 2, Opera 8, Netscape 9, SeaMonkey, and Safari. Unfortunately on Safari it does not work in combination with the onfocus event).

An example of using the above function to force the keyboard caret to jump to the end of all textareas on the page when they receive focus:

function addLoadEvent(func) {
    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        if(func) {
            var oldLoad = window.onload;

            window.onload = function() {
                if(oldLoad)
                        oldLoad();

                func();
            }
        }
    }
}

// The setCaretPosition function belongs right here!

function setTextAreasOnFocus() {
/***
 * This function will force the keyboard caret to be positioned
 * at the end of all textareas when they receive focus.
 */
    var textAreas = document.getElementsByTagName('textarea');

    for(var i = 0; i < textAreas.length; i++) {
        textAreas[i].onfocus = function() {
            setCaretPosition(this.id, this.value.length);
        }
    }

    textAreas = null;
}

addLoadEvent(setTextAreasOnFocus);

HTMLInputElement.setSelectionRange( selectionStart, selectionEnd );

// References
var e = document.getElementById( "helloworldinput" );

// Move caret to beginning on focus
e.addEventListener( "focus", function( event )
{
    // References
    var e = event.target;

    // Action
    e.setSelectionRange( 0, 0 );            // Doesn’t work for focus event
    
    window.setTimeout( function()
    {
        e.setSelectionRange( 0, 0 );        // Works
        //e.setSelectionRange( 1, 1 );      // Move caret to second position
        //e.setSelectionRange( 1, 2 );      // Select second character

    }, 0 );

}, false );

Browser compatibility (only for types: text, search, url, tel and password): https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange#Specifications


I would fix the conditions like below:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}

The link in the answer is broken, this one should work (all credits go to blog.vishalon.net):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

In case the code gets lost again, here are the two main functions:

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}

If you need to focus some textbox and your only problem is that the entire text gets highlighted whereas you want the caret to be at the end, then in that specific case, you can use this trick of setting the textbox value to itself after focus:

$("#myinputfield").focus().val($("#myinputfield").val());

I've adjusted the answer of kd7 a little bit because elem.selectionStart will evaluate to false when the selectionStart is incidentally 0.

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}

I would fix the conditions like below:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}

<!DOCTYPE html>
<html>
<head>
<title>set caret position</title>
<script type="application/javascript">
//<![CDATA[
window.onload = function ()
{
 setCaret(document.getElementById('input1'), 13, 13)
}

function setCaret(el, st, end)
{
 if (el.setSelectionRange)
 {
  el.focus();
  el.setSelectionRange(st, end);
 }
 else
 {
  if (el.createTextRange)
  {
   range = el.createTextRange();
   range.collapse(true);
   range.moveEnd('character', end);
   range.moveStart('character', st);
   range.select();
  }
 }
}
//]]>
</script>
</head>
<body>

<textarea id="input1" name="input1" rows="10" cols="30">Happy kittens dancing</textarea>

<p>&nbsp;</p>

</body>
</html>

The link in the answer is broken, this one should work (all credits go to blog.vishalon.net):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

In case the code gets lost again, here are the two main functions:

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}

If you need to focus some textbox and your only problem is that the entire text gets highlighted whereas you want the caret to be at the end, then in that specific case, you can use this trick of setting the textbox value to itself after focus:

$("#myinputfield").focus().val($("#myinputfield").val());

I found an easy way to fix this issue, tested in IE and Chrome:

function setCaret(elemId, caret)
 {
   var elem = document.getElementById(elemId);
   elem.setSelectionRange(caret, caret);
 }

Pass text box id and caret position to this function.


function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }

HTMLInputElement.setSelectionRange( selectionStart, selectionEnd );

// References
var e = document.getElementById( "helloworldinput" );

// Move caret to beginning on focus
e.addEventListener( "focus", function( event )
{
    // References
    var e = event.target;

    // Action
    e.setSelectionRange( 0, 0 );            // Doesn’t work for focus event
    
    window.setTimeout( function()
    {
        e.setSelectionRange( 0, 0 );        // Works
        //e.setSelectionRange( 1, 1 );      // Move caret to second position
        //e.setSelectionRange( 1, 2 );      // Select second character

    }, 0 );

}, false );

Browser compatibility (only for types: text, search, url, tel and password): https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange#Specifications


I've adjusted the answer of kd7 a little bit because elem.selectionStart will evaluate to false when the selectionStart is incidentally 0.

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}

Since I actually really needed this solution, and the typical baseline solution (focus the input - then set the value equal to itself) doesn't work cross-browser, I spent some time tweaking and editing everything to get it working. Building upon @kd7's code here's what I've come up with.

Enjoy! Works in IE6+, Firefox, Chrome, Safari, Opera

Cross-browser caret positioning technique (example: moving the cursor to the END)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

The meat and potatoes is basically @kd7's setCaretPosition, with the biggest tweak being if (el.selectionStart || el.selectionStart === 0), in firefox the selectionStart is starting at 0, which in boolean of course is turning to False, so it was breaking there.

In chrome the biggest issue was that just giving it .focus() wasn't enough (it kept selecting ALL of the text!) Hence, we set the value of itself, to itself el.value = el.value; before calling our function, and now it has a grasp & position with the input to use selectionStart.

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}

function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }

Since I actually really needed this solution, and the typical baseline solution (focus the input - then set the value equal to itself) doesn't work cross-browser, I spent some time tweaking and editing everything to get it working. Building upon @kd7's code here's what I've come up with.

Enjoy! Works in IE6+, Firefox, Chrome, Safari, Opera

Cross-browser caret positioning technique (example: moving the cursor to the END)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

The meat and potatoes is basically @kd7's setCaretPosition, with the biggest tweak being if (el.selectionStart || el.selectionStart === 0), in firefox the selectionStart is starting at 0, which in boolean of course is turning to False, so it was breaking there.

In chrome the biggest issue was that just giving it .focus() wasn't enough (it kept selecting ALL of the text!) Hence, we set the value of itself, to itself el.value = el.value; before calling our function, and now it has a grasp & position with the input to use selectionStart.

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to textbox

Add two numbers and display result in textbox with Javascript How to check if a text field is empty or not in swift Setting cursor at the end of any text of a textbox Press enter in textbox to and execute button command javascript getting my textbox to display a variable How can I set focus on an element in an HTML form using JavaScript? jQuery textbox change event doesn't fire until textbox loses focus? PHP: get the value of TEXTBOX then pass it to a VARIABLE How to clear a textbox once a button is clicked in WPF? Get current cursor position in a textbox

Examples related to input

Angular 4 - get input value React - clearing an input value after form submit Min and max value of input in angular4 application Disable Button in Angular 2 Angular2 - Input Field To Accept Only Numbers How to validate white spaces/empty spaces? [Angular 2] Can't bind to 'ngModel' since it isn't a known property of 'input' Mask for an Input to allow phone numbers? File upload from <input type="file"> Why does the html input with type "number" allow the letter 'e' to be entered in the field?