Получить позицию курсора (в символах) внутри поля ввода текста

212

Как я могу получить позицию каретки из поля ввода?

Я нашел несколько кусочков через Google, но ничего не доказательство.

В принципе что-то вроде плагина jQuery было бы идеальным, поэтому я мог бы просто сделать

$("#myinput").caretPosition()
MarkB29
источник
2
Попробуйте найти «позицию курсора», которая даст вам гораздо больше хитов, а также некоторые темы на эту тему в SO.
Алек
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;
}
bezmax
источник
9
else if (oField.selectionStart || oField.selectionStart == '0')может бытьelse if (typeof oField.selectionStart==='number')
user2428118
В чем идея "oField.focus ()"? У меня работает без этой строчки. Будьте осторожны, если вы используете событие размытия на своем входе и выполняете эту функцию внутри обратного вызова.
Кирилл Резников
Вы тестируете это на IE? Это целое, если раздел выполняется только в IE. В IE есть только глобальный выбор, поэтому это document.selectionне field.selectionили что - то. Кроме того, в IE 7 было возможно (не знаю, возможно ли это в 8+) выбрать что-то, а затем нажать TAB, не теряя выбора. Таким образом, когда текст выделен, но поле не сфокусировано, document.selectionвозвращается нулевое выделение. Вот почему, в качестве обходного пути для этой ошибки, вы должны сосредоточиться на элементе, прежде чем читать document.selection.
Безмакс
всегда получаю 0 за хром и firefox
Каушик Спасибо
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);
MarkB29
источник
3
Разве не так input = $(this).get(0)же, как input = this?
Mic
4
@ Мик нет, не в плагине jQuery. В плагине thisподразумевается полный упакованный набор. Его код все еще неверен, хотя, так и должно быть this.get(0). Его код, вероятно, все еще работал, потому что переупаковка упакованного набора ничего не делает.
Chev
1
Это дает мне неверную информацию. Я смотрел на позиции курсора при вводе текста. Моя скрипка, демонстрирующая это: jsfiddle.net/fallenreaper/TSwyk
Fallenreaper
1
Firefox генерирует NS_ERROR_FAILURE для input.selectionStart, когда ввод имеет числовой тип, обернуть его в try {} catch {}?
niall.campbell
было бы неплохо для новых пчел, если вы добавите использование для функции
Мухаммед Омер Аслам
101

ОЧЕНЬ ПРОСТО

Обновленный ответ

Используйте selectionStartего, он совместим со всеми основными браузерами .

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

Обновление: это работает только тогда, когда тип не определен или type="text"на входе.

CommonSenseCode
источник
2
Если я меняю положение с помощью мыши, он не печатается в консоли. Есть ли способ это исправить?
Евгений Барский
3
@EugeneBarsky Просто добавьте новый прослушиватель событий для события click. Вы можете проверить .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>

Я даю тебе fiddle_demo

Раджеш Пол
источник
13
sliceэто относительно дорогая операция, и она ничего не добавляет к этому «решению» - el.selectionStartэквивалентна длине вашего среза; просто верни это. Более того, причина, по которой другие решения являются более сложными, заключается в том, что они работают с другими браузерами, которые не поддерживают selectionStart.
mpen
Я бросил работу, где мне пришлось работать с кодом с именами переменных, как это.
Майкл Шепер
@ Майкл Шепер - Вы имеете в виду «el» для элемента и «val» для значения? Это довольно часто ...
user2782001
6
@ user2782001: Я ошибся - моей главной заботой было название функции. f1примерно такой же значимый, как 'user2782001'. Michael
Майкл Шепер
16

Теперь для этого есть хороший плагин: The Caret Plugin

Затем вы можете получить позицию, используя $("#myTextBox").caret()или установить ее через$("#myTextBox").caret(position)

Йенс Миккельсен
источник
1
плагин каретки, кажется, предназначен для элементов textarea, а не для ввода
schmidlop
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);
}
pmrotule
источник
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()или что-то вроде Underscores, _debounce()если текут события:

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

Вот скрипка, если вы хотите попробовать это: https://jsfiddle.net/Dhaupin/91189tq7/

dhaupin
источник
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>

Омар Бахш
источник