Встановіть положення каретки клавіатури в текстовому полі HTML


173

Хтось знає, як перемістити каре на клавіатурі в текстовому полі на певну позицію?

Наприклад, якщо текстове поле (наприклад, елемент введення, а не область тексту) містить 50 символів, і я хочу розташувати карету перед символом 20, як би я це зробив?

Це відрізняється від цього питання: jQuery Встановіть позицію курсора у текстовій області , яка потребує jQuery.

Відповіді:


205

Витягнуто з Налаштування клавіатури Джоша Стодоли на клавіатурі Положення в текстовому полі або TextArea з 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 це не працює в поєднанні з подією фокусу).

Приклад використання вищевказаної функції, щоб змусити каре з клавіатури переходити до кінця всіх текстових областей сторінки, коли вони отримують фокус:

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

4
if(elem.selectionStart)перерви, коли selectionStart дорівнює 0, як також вказували у відповіді jhnns.
mpartel

1
Це не працює для мене. Коли я натискаю фактичне текстове поле, я очікую, що позиція каретки буде на початку. Ознайомтеся з моєю скрипкою jsfiddle.net/khx2w
elad.chen

Функція setCaretPosition працює чудово. Однак функція addActionHandler не виконує. Але навіть без цього я не міг змусити курсор рухатися по фокусу. Швидше за все, це тому, що браузер сам встановлює положення курсора на основі положення клацання. Здається, не існує способу його вирішення з того, що я можу сказати, але я можу бути абсолютно неправильним.
GJK

Працює в IE9, FF25, але не в Chrome 30. Краще, ніж ніхто!
Умбер Ферруле

У мене elem.value = elem.value.replace(/^9/g,'+79')в коді. На курсорі OperaMINI після +. ця функція не допомагає
Ері

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", використовуючи метод діапазону.
Rob W

36

Оскільки я насправді справді потребував цього рішення, а типове рішення базової лінії ( сфокусуйте вхід - тоді встановіть значення, яке дорівнює собі ) не працює перехресним браузером , я витратив деякий час, переглядаючи та редагуючи все, щоб його працювати. Побудова на @ kd7 ось що я придумав.

Насолоджуйтесь! Працює в IE6 +, Firefox, Chrome, Safari, Opera

Техніка позиціонування карет між переглядачами (наприклад: переміщення курсору до END)

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

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

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

У хромі найбільша проблема полягала в тому, що просто давати її .focus()недостатньо (вона постійно вибирала ВСІ тексти!) Отже, ми встановлюємо собі значення, el.value = el.value;перш ніж викликати нашу функцію, і тепер вона має розуміння та позицію вхід для використання selectStart .

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

@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)- Я би змінив ці два рядки. Якщо elnull, el.value = el.valueне вдасться, тому ця лінія повинна бути всередині if.
BackSlash

21

Я трохи коригував відповідь kd7, тому що elem.selectionStart оцінить значення false, коли вибірStart випадково дорівнює 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);
 }

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


3

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

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

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: У об’єкта [об’єкта HTMLInputElement] немає методу 'beginWith'
bobpaul

1
@bobpaul: tIDповинен бути ідентифікатором елемента, а не самим елементом елемента. Якщо ви передаєте об'єкт елемента, ви можете просто видалити 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();
  }
 }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.