Установить положение курсора клавиатуры в текстовом поле HTML

173

Кто-нибудь знает, как переместить курсор клавиатуры в текстовое поле в определенную позицию?

Например, если текстовое поле (например, элемент ввода, а не текстовая область) содержит 50 символов, и я хочу расположить каретку перед символом 20, как мне это сделать?

В этом отличие от этого вопроса: jQuery устанавливает положение курсора в текстовой области , для чего требуется jQuery.

jonhobbs
источник

Ответы:

205

Извлечено из « Задания положения курсора клавиатуры» Джоша Стодолы в текстовом поле или текстовой области с использованием Javascript

Универсальная функция, которая позволит вам вставить каретку в любую позицию текстового поля или текстовой области, которую вы пожелаете:

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();
        }
    }
}

Первый ожидаемый параметр - это идентификатор элемента, в который вы хотите вставить курсор клавиатуры. Если элемент не может быть найден, ничего не произойдет (очевидно). Второй параметр - это индекс положения каретки. Ноль поместит каретку клавиатуры в начале. Если вы передадите число, большее, чем количество символов в значении элементов, то клавиатура будет вставлена ​​в конце.

Протестировано на IE6 и выше, Firefox 2, Opera 8, Netscape 9, SeaMonkey и Safari. К сожалению, в Safari он не работает в сочетании с событием onfocus).

Пример использования вышеупомянутой функции, чтобы заставить клавиатуру переходить в конец всех текстовых областей на странице, когда они получают фокус:

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);
TA01
источник
4
if(elem.selectionStart)прерывается, когда selectionStart равен 0, что также указано в ответе jhnns.
mpartel
1
Это не работает для меня. Когда я нажимаю на текстовое поле, которое у меня есть, я ожидаю, что позиция каретки будет в начале. Проверьте мою скрипку jsfiddle.net/khx2w
elad.chen
Функция setCaretPosition работает просто отлично. Ваша функция addActionHandler, однако, этого не делает. Но даже без этого я не мог заставить курсор двигаться в фокусе. Скорее всего, это потому, что браузер сам устанавливает позицию курсора в зависимости от позиции щелчка. Кажется, нет никакого способа обойти это из того, что я могу сказать, но я могу быть совершенно неправ.
GJK
Работает в IE9, FF25, но не в Chrome 30. Лучше, чем ничего!
Umber Ferrule
Я elem.value = elem.value.replace(/^9/g,'+79')в коде. На OperaMINI курсор после +. эта функция не помогает
eri
52

Ссылка в ответе битая, эта должна работать (все кредиты идут на blog.vishalon.net ):

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

В случае, если код снова теряется, вот две основные функции:

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();
 }
}
вечный
источник
1
+1 для базовых функций, хотя некоторые корректировки должны быть сделаны . Количество строк должно быть вычтено из «pos» при использовании метода range.
Роб W
36

Поскольку на самом деле мне действительно нужно это решение, а типичное базовое решение ( сфокусировать ввод - затем установить значение равным себе ) не работает в кросс-браузерном режиме , я потратил некоторое время на настройку и редактирование всего, чтобы оно работало. Основываясь на коде @ kd7 , вот что я придумала.

Наслаждайтесь! Работает в IE6 +, Firefox, Chrome, Safari, Opera

Кросс-браузерная техника позиционирования каретки (пример: перемещение курсора в КОНЕЦ)

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

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

Мясо и картофель - это в основном setCaretPosition @ kd7 , с самой большой настройкой if (el.selectionStart || el.selectionStart === 0)в firefox, selectionStart начинается с 0 , что в логическом значении, конечно, превращается в False, поэтому оно ломалось там.

В chrome самой большой проблемой было то, что просто дать его .focus()было недостаточно (он продолжал выделять ВЕСЬ текст!). Следовательно, мы устанавливаем значение для себя, для себя, el.value = el.value;прежде чем вызывать нашу функцию, и теперь у него есть понимание и позиция с ввод для использования 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;
            }
        }
    }
}
Марк Песак - Trilon.io
источник
@mcpDESIGNS Я пытаюсь использовать эту функцию, когда фокус делается на ввод текста, но я ничего не получаю. Не могли бы вы помочь с применением этой функции с использованием чистого JavaScript?
elad.chen
@ elad.chen Вы пытаетесь расположить их в конце текстового поля, как только они сосредоточатся на нем?
Марк Писак - Trilon.io
@mcpDESIGNS Я хочу поместить курсор в начало поля, как только элемент будет сфокусирован. Смотрите скрипку: jsfiddle.net/KuLTU/3
elad.chen
@ elad.chen Извините за сумасшедший поздний ответ! Просто измените это событие .onclickвместо того, .onfocusчтобы использовать функцию search_field_focus
Марк Писак - Trilon.io
2
el.value = el.value; [...] if(el !== null)- Я бы поменял эти две строки. Если elноль, el.value = el.valueпроизойдет сбой, поэтому строка должна быть внутри if.
BackSlash
21

Я немного скорректировал ответ kd7, потому что elem.selectionStart будет иметь значение false, когда selectionStart случайно равен 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);
        }
    }
}
Йоханнес Эвальд
источник
5

Я нашел простой способ исправить эту проблему, протестирован в IE и Chrome:

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

Передайте идентификатор текстового поля и позицию каретки в эту функцию.

Iam_NSA
источник
3

Если вам нужно сфокусировать какое-то текстовое поле, и ваша единственная проблема заключается в том, что весь текст выделяется, тогда как вы хотите, чтобы каретка была в конце, тогда в этом конкретном случае вы можете использовать этот трюк для установки значения текстового поля себе после фокуса:

$("#myinputfield").focus().val($("#myinputfield").val());
manish_s
источник
2
<!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>
Дипак
источник
2
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); }
Кит Кромм
источник
Uncaught TypeError: У объекта [object HTMLInputElement] нет метода 'setsWith'
bobpaul
1
@bobpaul: tIDдолжен быть id элемента, а не сам объект элемента. Если вы передаете объект элемента, вы можете просто удалить 2 первые строки в этом методе, и он будет работать.
благоговение
2

Я бы исправил условия как ниже:

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();
  }
 }
}
Александр Гаврилюк
источник