Как получить (x, y) пиксельные координаты каретки в текстовых полях?

Я использую jQuery и пытаюсь найти способ перекрестного браузера, чтобы получить пиксельные координаты каретки в блоках <textarea> и input, чтобы я мог разместить абсолютно позиционированный div вокруг этого местоположения.

Есть ли какой-нибудь плагин jQuery? Или фрагмент JavaScript, чтобы сделать это?

Ответ 1

Я искал плагин для координат textarea для meteor-autocomplete, поэтому я оценил все 8 плагинов на GitHub. Победителем является textarea-caret-position из Компонент.

Функции

  • точность пикселей
  • никаких зависимостей
  • Совместимость браузера: Chrome, Safari, Firefox (несмотря на два bugs он имеет), IE9 +; может работать, но не тестироваться в Opera, IE8 или старше
  • поддерживает любое семейство и размер шрифта, а также текстовые преобразования
  • текстовая область может иметь произвольное заполнение или границы
  • не путать горизонтальные или вертикальные полосы прокрутки в текстовом поле
  • поддерживает жесткие возвраты, вкладки (кроме IE) и последовательные пробелы в тексте
  • правильное положение в строках длиннее столбцов в текстовой области
  • no позиция "призрака" в пустом пространстве в конце строки при обертке длинных слов

Здесь демо - http://jsfiddle.net/dandv/aFPA7/

enter image description here

Как это работает

Зеркало <div> создается за пределами экрана и создается точно так же, как <textarea>. Затем текст текстовой области до каретки копируется в div и a <span> вставляется сразу после нее. Затем текстовое содержимое диапазона устанавливается в остальную часть текста в текстовом поле, чтобы точно воспроизвести обертку в faux div.

Это единственный метод, который гарантированно обрабатывает все граничные случаи, связанные с переносом длинных строк. Он также используется GitHub для определения местоположения своего раскрывающегося списка @.

Ответ 2

Примечание. В этом ответе описывается, как получить координаты символа текстового курсора/каретки. Чтобы найти пиксельные координаты, вам нужно продолжить это.

Первое, что нужно помнить, это то, что курсор может находиться в трех состояниях

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

Модель IE использует объект document.selection, из этого мы можем получить TextRange, который дает нам доступ к выбору и, следовательно, позицию (-ы) курсора.

Модель FF/Opera использует удобные переменные [input].selectionStart и selectionEnd.

Обе модели представляют собой обычный активный курсор в качестве выбора нулевой ширины, а левая граница - позиция курсора.

Если поле ввода не имеет фокуса, вы можете обнаружить, что ни один из них не установлен. У меня был хороший успех со следующим кодом, чтобы вставить фрагмент текста в текущее местоположение курсора, также заменив текущий выбор, если он есть. В зависимости от конкретного браузера YMMV.

function insertAtCursor(myField, myValue) {

/* selecion model - ie */
if (document.selection) {
  myField.focus();
  sel = document.selection.createRange();
  sel.text = myValue;
}

/* field.selectionstart/end  firefox */ 
else if (myField.selectionStart || myField.selectionStart == '0' ) {

  var startPos = myField.selectionStart;
  var endPos = myField.selectionEnd;
  myField.value = myField.value.substring(0, startPos)
    + myValue
    + myField.value.substring(endPos, myField.value.length);

  myField.selectionStart = startPos + myValue.length;
  myField.selectionEnd = startPos + myValue.length;
  myField.focus();
} 

// cursor not active/present
else {
  myField.value += myValue;
}

Ошибка Примечание: ссылки не правильно помечены в верхнем параграфе.

Объект выделения: http://msdn.microsoft.com/en-us/library/ms535869(VS.85).aspx
Объект TextRange: http://msdn.microsoft.com/en-us/library/ms535872(VS.85).aspx

Ответ 3

Я не думаю, что это можно сделать в каждом браузере. Кто-то сделал это в IE6, но он не работает в FF или Opera (AFAIK). Возможно, вы можете заставить его работать во всех браузерах.

Здесь сообщение в блоге с 2005 года.