Отримайте позицію курсора (у символах) у полі введення тексту


211

Як я можу отримати положення каретки з поля введення?

Я знайшов декілька біт і фрагментів через Google, але нічого не підтверджено.

В основному щось на зразок плагіна jQuery було б ідеальним, тому я міг би просто зробити

$("#myinput").caretPosition()

2
Спробуйте пошукати "позицію курсору", яка дасть вам набагато більше звернень, а також деякі теми про це на SO.
Алек

1
можливий дублікат Як отримати позицію курсору в textarea? . Дивіться також: Плагін FieldSelection
CMS

2
@CMS Пошук позиції в a <input>є простішим способом, ніж робити це в a <textarea>.
Андрій Мао

1
@AndrewMao: і набагато складніше, якщо текст прокручується, а карета - минулі sizeсимволи.
Дан Даскалеску

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

Відповіді:


247

Простіше оновлення:

Використовуйте field.selectionStart приклад у цій відповіді .

Дякуємо @commonSenseCode, що вказав на це.


Стара відповідь:

Знайшов це рішення. Не заснований на jquery, але немає проблеми інтегрувати його в 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;
}

9
else if (oField.selectionStart || oField.selectionStart == '0')могло бутиelse if (typeof oField.selectionStart==='number')
користувач2428118

Яка ідея "oField.focus ()"? Це працює для мене без цієї лінії. Будьте обережні, якщо ви використовуєте подію розмиття на вході та виконайте цю функцію всередині зворотного дзвінка.
Кирило Резніков

Ви тестуєте це на IE? Ціле, якщо розділ виконується тільки на IE. У IE є лише глобальний вибір, тому це document.selection, ні, field.selectionчи щось таке. Крім того, можна було в IE 7 (не знаю, чи все ще можливо в 8+) щось вибрати, а потім TAB вийти з поля, не втрачаючи вибір. Таким чином, коли текст обраний, але поле не зосереджене, document.selectionповертається нульовий вибір. Ось чому, як вирішення цієї помилки, ви повинні зосередитись на елементі перед читанням document.selection.
bezmax

завжди отримує 0 за хром та
фаєрфокс

117

Гарний, велике спасибі Максу.

Я перетворив функціонал своєї відповіді на jQuery, якщо хтось хоче ним користуватися.

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

3
Це не input = $(this).get(0)те саме, що input = this?
Мік

4
@Mic ні, не в плагіні jQuery. У плагіні thisвідноситься до повного загорнутого набору. Його код все ще помиляється, він просто повинен бути this.get(0). Його код, ймовірно, все ще працював, тому що повторна упаковка загорнутого набору нічого не робить.
Шев

1
Це дає мені неправильну інформацію. Я дивився на позиції курсора під час введення тексту. Моя скрипка, що демонструє це: jsfiddle.net/fallenreaper/TSwyk
Fallenreaper

1
Firefox генерує NS_ERROR_FAILURE на input.selectionStart, коли вхід має тип номера, оберніть його у спробу {} catch {}?
niall.campbell

було б добре для нових бджіл, якщо ви додасте використання для функції
Мухаммед Омер Аслам

98

ДУЖЕ ЛЕГКО

Оновлена ​​відповідь

Використовуйте selectionStart, він сумісний з усіма основними браузерами .

document.getElementById('foobar').addEventListener('keyup', e => {
  console.log('Caret at: ', e.target.selectionStart)
})
<input id="foobar" />

Оновлення: Це працює лише тоді, коли не визначено тип або type="text"на вході.


2
Якщо я міняю позицію за допомогою миші, вона не надрукується на консолі. Чи є спосіб це виправити?
Євген Барський

3
@EugeneBarsky Просто додайте нового слухача подій для події клацання. Ви можете перевірити .selectionStartвластивість у будь-який час ( document.getElementById('foobar').selectionStart), він не повинен бути у слухача події.
JJJ

3
дивовижно, але не працює в Firefox чи Chrome, коли тип вводу є числом.
Адам Р. Грей

26

Отримало дуже просте рішення . Спробуйте наступний код із підтвердженим результатом -

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

Я даю тобі скрипку


13
slice- відносно дорога операція, і вона нічого не додає до цього «рішення» - el.selectionStartеквівалентна довжині вашого фрагмента; просто поверніть це. Крім того, причина інших рішень є складнішою в тому, що вони мають справу з іншими браузерами, які не підтримують selectionStart.
mpen

Я кинув завдання, де мені довелося працювати з кодом із назви змінних, як це.
Майкл Шепер

@Michael Scheper - Ви маєте на увазі 'el' для елемента та 'val' для значення? Вони досить поширені ...
user2782001

6
@ user2782001: Я пропустив помилку - головним моїм клопотом було ім'я функції. f1є приблизно таким же значущим, як "user2782001". 😉
Майкл

16

Зараз для цього є приємний плагін: Плагін Caret

Тоді ви можете отримати позицію за допомогою $("#myTextBox").caret()або встановити її через$("#myTextBox").caret(position)


1
Плагін
caret,

4
Добре, що я працював над <input type = "text" id = "myTextBox" /> і використовую вищевказаний код.
Єнс Міккельсен

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

10

Тут розміщено кілька хороших відповідей, але, я думаю, ви можете спростити свій код і пропустити перевірку на inputElement.selectionStartпідтримку: він підтримується не лише в IE8 і раніше (див. Документацію ), що становить менше 1% від поточного використання браузера .

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

2

Можливо, вам потрібен вибраний діапазон, крім позиції курсору. Ось проста функція, вам навіть не потрібен 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)');
    }
}

Скажімо, ви хочете викликати його на вході щоразу, коли він змінюється або миша переміщує положення курсору (у цьому випадку ми використовуємо jQuery .on()). З міркувань продуктивності може бути хорошою ідеєю додати setTimeout()або щось на зразок підкреслення, _debounce()якщо події переливаються:

$('input[type="text"]').on('keyup mouseup mouseleave', function() {
    caretPosition($(this));
});

Ось загадка, якщо ви хочете спробувати її: https://jsfiddle.net/Dhaupin/91189tq7/


0

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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.