Вставка текста там, где курсор использует Javascript / jquery

167

У меня есть страница с множеством текстовых полей. Когда кто-то нажимает на ссылку, я хочу, чтобы слово или два были вставлены туда, где находится курсор, или добавлены к текстовому полю с фокусом.

Например, если курсор / фокус находится на текстовом поле с надписью «яблоко», и он щелкает ссылку с надписью «[электронная почта]», то я хочу, чтобы текстовое поле показывало «яблоко bob@example.com».

Как я могу это сделать? Возможно ли это вообще, так как что, если фокус находится на элементе radio / dropdown / non textbox? Можно ли запомнить последнее сосредоточенное на текстовом поле?

Нажмите Upvote
источник
Я предполагаю, что это возможно, потому что это основа редакторов WYSISYG, как это сделать, я не знаю.
Ян Эллиотт
Спасибо, что задали этот вопрос ... теперь я могу вставить "[версию]" в курсор с моим расширением Chrome!
haykam
Если вы ищете простой модуль с поддержкой отмены, попробуйте insert-text-textarea . Если вам нужна поддержка IE8 +, попробуйте пакет insert-text-at-cursor .
Фреганте

Ответы:

241

Используйте это отсюда :

function insertAtCaret(areaId, text) {
  var txtarea = document.getElementById(areaId);
  if (!txtarea) {
    return;
  }

  var scrollPos = txtarea.scrollTop;
  var strPos = 0;
  var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
    "ff" : (document.selection ? "ie" : false));
  if (br == "ie") {
    txtarea.focus();
    var range = document.selection.createRange();
    range.moveStart('character', -txtarea.value.length);
    strPos = range.text.length;
  } else if (br == "ff") {
    strPos = txtarea.selectionStart;
  }

  var front = (txtarea.value).substring(0, strPos);
  var back = (txtarea.value).substring(strPos, txtarea.value.length);
  txtarea.value = front + text + back;
  strPos = strPos + text.length;
  if (br == "ie") {
    txtarea.focus();
    var ieRange = document.selection.createRange();
    ieRange.moveStart('character', -txtarea.value.length);
    ieRange.moveStart('character', strPos);
    ieRange.moveEnd('character', 0);
    ieRange.select();
  } else if (br == "ff") {
    txtarea.selectionStart = strPos;
    txtarea.selectionEnd = strPos;
    txtarea.focus();
  }

  txtarea.scrollTop = scrollPos;
}
<textarea id="textareaid"></textarea>
<a href="#" onclick="insertAtCaret('textareaid', 'text to insert');return false;">Click Here to Insert</a>

George Claghorn
источник
7
Это отлично работает, но не обрабатывает замену выделенного текста, как все текстовые редакторы. Это может не понадобиться для исходного вопроса автора, но если вам это нужно, вы можете просто заменить 'strPos' на 'txtArea.selectionEnd'. Мой ответ ниже показывает это, наряду с удалением кода обнаружения браузера, если вам не требуется поддержка более старых версий IE.
Джеффри Хармон
Есть ли способ выбрать все элементы с помощью areaId?
Хайкам
1
Вы можете добиться автоматического удаления выделенного текста, вставив функцию, подобную этой. function deleteTxt() { var ele = document.getElementById('yourTextarea'); var text = ele.value; text = text.slice(0, ele.selectionStart) + text.slice(ele.selectionEnd); ele.value = text; return text; }
NSTuttle
Как вставить текст в положение мыши?
Thamarai T
Ты лучший!
Эко Сантосо
156

Может быть, более короткая версия, было бы легче понять?

    jQuery("#btn").on('click', function() {
        var $txt = jQuery("#txt");
        var caretPos = $txt[0].selectionStart;
        var textAreaTxt = $txt.val();
        var txtToAdd = "stuff";
        $txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<textarea id="txt" rows="15" cols="70">There is some text here.</textarea>
<input type="button" id="btn" value="OK" />

Я написал это в ответ на Как добавить текст в текстовое поле с текущей позиции указателя с помощью jquery?

quik_silv
источник
11
Вы также можете восстановить каретку позиции после изменения значения с: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf
1
работал на меня, спасибо. Кстати, свойство selectionStart не существует с помощью селектора jquery $ ("#"). Вам нужно пройти document.getElementById ()
Lego
1
jsfiddle.net/NaHTw/802 - это ваше решение с небольшим дополнительным добавлением для замены выделенной области тем, что вставлено
Патрик
3
Ну, если вы собираетесь зайти так далеко, удалив jQuery, вы можете удалить все это . ; ^)
Ерш
8
Просто чтобы помочь, вот полное решение с восстановлением позиции каретки и заменой выделенной области вставленным содержимым: jsfiddle.net/NaHTw/1028
AlfaTeK
41

Одобренный ответ Джорджа Клагхорна отлично подошел для простой вставки текста в позиции курсора. Если пользователь выбрал текст, и вы хотите, чтобы этот текст был заменен (по умолчанию используется большинство текста), вам нужно внести небольшое изменение при установке переменной 'back'.

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

Вот упрощенная версия, которая работает как минимум для Chrome и IE11 и обрабатывает замену выделенного текста.

function insertAtCaret(areaId, text) {
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var caretPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0, caretPos);
    var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length);
    txtarea.value = front + text + back;
    caretPos = caretPos + text.length;
    txtarea.selectionStart = caretPos;
    txtarea.selectionEnd = caretPos;
    txtarea.focus();
    txtarea.scrollTop = scrollPos;
}
Джеффри Хармон
источник
Это хорошо, но не учитывает элемент maxlength, поэтому результирующее значение после вставки может быть длиннее максимального.
mbomb007
22

Код выше не работал для меня в IE. Вот код, основанный на этом ответе .

Я вынул, getElementByIdчтобы я мог ссылаться на элемент по-другому.

function insertAtCaret(element, text) {
  if (document.selection) {
    element.focus();
    var sel = document.selection.createRange();
    sel.text = text;
    element.focus();
  } else if (element.selectionStart || element.selectionStart === 0) {
    var startPos = element.selectionStart;
    var endPos = element.selectionEnd;
    var scrollTop = element.scrollTop;
    element.value = element.value.substring(0, startPos) +
      text + element.value.substring(endPos, element.value.length);
    element.focus();
    element.selectionStart = startPos + text.length;
    element.selectionEnd = startPos + text.length;
    element.scrollTop = scrollTop;
  } else {
    element.value += text;
    element.focus();
  }
}
input{width:100px}
label{display:block;margin:10px 0}
<label for="in2copy">Copy text from: <input id="in2copy" type="text" value="x"></label>
<label for="in2ins">Element to insert: <input id="in2ins" type="text" value="1,2,3" autofocus></label>
<button onclick="insertAtCaret(document.getElementById('in2ins'),document.getElementById('in2copy').value)">Insert</button>

РЕДАКТИРОВАТЬ: Добавлен работающий фрагмент, jQuery не используется .

Коллин Андерсон
источник
Является ли элемент объектом jquery или нет? element.value и element.focus () не могут работать одновременно ...
Скотт Стаффорд
7
element.focus()является законным методом JavaScript для DOMElements: w3schools.com/jsref/met_html_focus.asp
oliverseal,
1
Лучшая идея - отказаться от совместимости с IE.
ar2015
2
Да, я написал этот ответ 7 лет назад. На данный момент IE 11 является хорошей минимально поддерживаемой версией, и код выше работает там.
Коллин Андерсон
6

используя ответ @quick_sliv:

function insertAtCaret(el, text) {
    var caretPos = el.selectionStart;
    var textAreaTxt = el.value;
    el.value = textAreaTxt.substring(0, caretPos) + text + textAreaTxt.substring(caretPos);
};
math2001
источник
4

Как вставить текст в текущую позицию курсора TextBox через JQuery и JavaScript

Обработать

  1. Найти текущую позицию курсора
  2. Получить текст для копирования
  3. Установить текст там
  4. Обновить позицию курсора

Здесь у меня есть 2 текстовых поля и кнопка. Я должен нажать на определенную позицию в текстовом поле, а затем нажать на кнопку, чтобы вставить текст из другого текстового поля в положение предыдущего текстового поля.

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

//Textbox on which to be pasted
<input type="text" id="txtOnWhichToBePasted" />

//Textbox from where to be pasted
<input type="text" id="txtFromWhichToBePasted" />


//Button on which click the text to be pasted
<input type="button" id="btnInsert" value="Insert"/>


<script type="text/javascript">

$(document).ready(function () {
    $('#btnInsert').bind('click', function () {
            var TextToBePasted = $('#txtFromWhichToBePasted').value;
            var ControlOnWhichToBePasted = $('#txtOnWhichToBePasted');

            //Paste the Text
            PasteTag(ControlOnWhichToBePasted, TextToBePasted);
        });
    });

//Function Pasting The Text
function PasteTag(ControlOnWhichToBePasted,TextToBePasted) {
    //Get the position where to be paste

    var CaretPos = 0;
    // IE Support
    if (document.selection) {

        ControlOnWhichToBePasted.focus();
        var Sel = document.selection.createRange();

        Sel.moveStart('character', -ctrl.value.length);

        CaretPos = Sel.text.length;
    }
    // Firefox support
    else if (ControlOnWhichToBePasted.selectionStart || ControlOnWhichToBePasted.selectionStart == '0')
        CaretPos = ControlOnWhichToBePasted.selectionStart;

    //paste the text
    var WholeString = ControlOnWhichToBePasted.value;
    var txt1 = WholeString.substring(0, CaretPos);
    var txt2 = WholeString.substring(CaretPos, WholeString.length);
    WholeString = txt1 + TextToBePasted + txt2;
    var CaretPos = txt1.length + TextToBePasted.length;
    ControlOnWhichToBePasted.value = WholeString;

    //update The cursor position 
    setCaretPosition(ControlOnWhichToBePasted, CaretPos);
}

function setCaretPosition(ControlOnWhichToBePasted, pos) {

    if (ControlOnWhichToBePasted.setSelectionRange) {
        ControlOnWhichToBePasted.focus();
        ControlOnWhichToBePasted.setSelectionRange(pos, pos);
    }
    else if (ControlOnWhichToBePasted.createTextRange) {
        var range = ControlOnWhichToBePasted.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    }
}

</script>
Сунил К Бехера -MindFire Sol-
источник
3

Добавление текста в текущую позицию курсора состоит из двух шагов:

  1. Добавление текста в текущей позиции курсора
  2. Обновление текущей позиции курсора

Демо: https://codepen.io/anon/pen/qZXmgN

Протестировано в Chrome 48, Firefox 45, IE 11 и Edge 25

JS:

function addTextAtCaret(textAreaId, text) {
    var textArea = document.getElementById(textAreaId);
    var cursorPosition = textArea.selectionStart;
    addTextAtCursorPosition(textArea, cursorPosition, text);
    updateCursorPosition(cursorPosition, text, textArea);
}
function addTextAtCursorPosition(textArea, cursorPosition, text) {
    var front = (textArea.value).substring(0, cursorPosition);
    var back = (textArea.value).substring(cursorPosition, textArea.value.length);
    textArea.value = front + text + back;
}
function updateCursorPosition(cursorPosition, text, textArea) {
    cursorPosition = cursorPosition + text.length;
    textArea.selectionStart = cursorPosition;
    textArea.selectionEnd = cursorPosition;
    textArea.focus();    
}

HTML:

<div>
    <button type="button" onclick="addTextAtCaret('textArea','Apple')">Insert Apple!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Mango')">Insert Mango!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Orange')">Insert Orange!</button>
</div>
<textarea id="textArea" rows="20" cols="50"></textarea>
Разан Пол
источник
2

Я думаю, что вы могли бы использовать следующий JavaScript для отслеживания последнего текстового поля:

<script>
var holdFocus;

function updateFocus(x)
{
    holdFocus = x;
}

function appendTextToLastFocus(text)
{
    holdFocus.value += text;
}
</script>

Использование:

<input type="textbox" onfocus="updateFocus(this)" />
<a href="#" onclick="appendTextToLastFocus('textToAppend')" />

Предыдущее решение (props to gclaghorn) использует textarea и рассчитывает положение курсора, так что это может быть лучше для того, что вы хотите. С другой стороны, этот будет более легким, если это то, что вы ищете.

DreadPirateShawn
источник
Отличная идея. Я использовал jquery, чтобы к каждому текстовому полю, в котором был определенный класс, применялось это событие, вместо того, чтобы помещать «onfocus = ...» в HTML каждого текстового поля. Но хороший подход :)
Нажмите Upvote
1

Принятый ответ не работал для меня в Internet Explorer 9. Я проверил его, и обнаружение браузера не работает должным образом, он обнаружил ff (firefox), когда я был в Internet Explorer.

Я только что сделал это изменение:

if ($.browser.msie) 

Вместо того:

if (br == "ie") { 

В результате получается следующий код:

function insertAtCaret(areaId,text) {
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var strPos = 0;
    var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? 
        "ff" : (document.selection ? "ie" : false ) );

    if ($.browser.msie) { 
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        strPos = range.text.length;
    }
    else if (br == "ff") strPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0,strPos);  
    var back = (txtarea.value).substring(strPos,txtarea.value.length); 
    txtarea.value=front+text+back;
    strPos = strPos + text.length;
    if (br == "ie") { 
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        range.moveStart ('character', strPos);
        range.moveEnd ('character', 0);
        range.select();
    }
    else if (br == "ff") {
        txtarea.selectionStart = strPos;
        txtarea.selectionEnd = strPos;
        txtarea.focus();
    }
    txtarea.scrollTop = scrollPos;
}
Alvaro
источник
0

Вы можете только сфокусировать нужное текстовое поле и вставить туда текст. нет никакого способа узнать, где фокус AFAIK (возможно, взаимодействующий по всем узлам DOM?).

проверьте этот стекопоток - у него есть решение: как узнать, какой элемент DOM находится в фокусе?

dusoft
источник
0

Редактирование содержимого, выбор HTML или любого другого элемента DOM

Если вы пытаетесь вставить курсор в a <div contenteditable="true">, это становится намного сложнее, особенно если в редактируемом контейнере есть дочерние элементы.

Мне очень повезло с использованием библиотеки Rangy :

Он имеет массу замечательных функций, таких как:

  • Сохранить позицию или выбор
  • Затем, позже, восстановить позицию или выбор
  • Получить выделенный HTML или обычный текст
  • Среди многих других

Онлайн-демонстрация не работала, когда я проверял последний раз, однако в репозитории есть рабочие демонстрации. Для начала просто загрузите репо из Git или NPM, а затем откройте ./rangy/demos/index.html

Это делает работу с Paret Pos и ​​выбор текста на одном дыхании!

factorypolaris
источник
0

Ответ на этот вопрос был опубликован так давно, и я наткнулся на него с помощью поиска Google. HTML5 предоставляет API HTMLInputElement , который включает в setRangeText () метод, который заменяет диапазон текста в <input>или <textarea>элемент с новой строки:

element.setRangeText('abc');

Вышеуказанное заменит выбор, сделанный внутри, elementна abc. Вы также можете указать, какую часть входного значения заменить:

element.setRangeText('abc', 3, 5);

Вышеуказанное заменило бы 4-6-й символы входного значения на abc. Вы также можете указать, как должен быть установлен выбор после замены текста, указав одну из следующих строк в качестве 4-го параметра:

  • 'preserve'попытки сохранить выбор. Это по умолчанию.
  • 'select' выбирает вновь вставленный текст.
  • 'start' перемещает выделение непосредственно перед вставленным текстом.
  • 'end' перемещает выделение сразу после вставленного текста.

Совместимость браузера

Страница MDN для setRangeText не предоставляет данные о совместимости браузера, но я думаю, что это будет то же самое, что и HTMLInputElement.setSelectionRange () , который в основном является всеми современными браузерами, IE 9 и выше, Edge 12 и выше.

А. Генеди
источник