Вставлення тексту, де курсор використовує Javascript / jquery


167

У мене є сторінка з великою кількістю текстових полів. Коли хтось клацає посилання, я хочу, щоб слово чи два було вставлено там, де знаходиться курсор, або додане до текстового поля, на якому є фокус.

Наприклад, якщо курсор / фокус знаходиться на текстовому полі з надписом "яблуко", і він натискає на посилання із повідомленням "[email]", то я хочу, щоб у текстовому полі було сказано "apple bob@example.com".

Як я можу це зробити? Це навіть можливо, адже що робити, якщо фокус робиться на елементі радіо / випадаючого / не текстового поля? Чи можна запам'ятати останню, зосереджену на текстовому полі?


Я припускаю, що це можливо, тому що це основа редакторів WYSISYG, як це зробити, я не знаю.
Ян Елліотт


Дякую за те, що ви задали це запитання ... тепер я можу вставити "[версію]" в курсор за допомогою мого розширення Chrome!
haykam

Якщо ви шукаєте простий модуль з підтримкою скасування, спробуйте вставити-текст-textarea . Якщо вам потрібна підтримка IE8 +, спробуйте пакет вставити текст-на-курсор .
fregante

Відповіді:


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>


7
Це спрацювало чудово, але воно не справляється із заміною вибраного тексту, як це роблять усі текстові редактори. Це може не знадобитися для оригінального питання афіші, але якщо він вам потрібен, ви можете просто замінити 'strPos' на 'txtArea.selectionEnd'. Моя відповідь нижче показує це разом із видаленням коду виявлення браузера, якщо вам не потрібно підтримувати старіші версії IE.
Джефрі Хармон

Чи є спосіб виділити всі елементи за допомогою areaId?
haykam

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

Як вставити текст у положення миші?
Тамарай 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?


11
Ви також можете відновити каретку позиції після зміни значення з: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf

1
працював на мене, дякую. FYI властивість "selectionStart" не існує через селектор jquery $ ("#"). Вам потрібно пройти document.getElementById ()
Лего

1
jsfiddle.net/NaHTw/802 - це ваше рішення з додатковим додаванням, щоб замінити вибрану область на те, що вставлено
Патрік

3
Ну, якщо ви збираєтеся йти так далеко, видаляючи jQuery, ви можете також видалити все це . ; ^)
ruffin

8
Просто на допомогу, ось повне рішення з відновленням позиції карети
AlfaTeK

41

Затверджена відповідь Джорджа Клагхорна відмінно підійшла для простого вставлення тексту в позицію курсору. Якщо користувач вибрав текст, і ви хочете, щоб цей текст був замінений (стандартний досвід із більшою частиною тексту), вам потрібно зробити невелику зміну, встановивши змінну 'назад'.

Крім того, якщо вам не потрібно підтримувати більш старі версії 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>

EDIT: Доданий запущений фрагмент, 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);
};

4

Як вставити текст у поточну позицію курсору TextBox через JQuery та JavaScript

Процес

  1. Знайдіть поточну позицію курсору
  2. Отримайте текст для копіювання
  3. Встановіть текст там
  4. Оновіть позицію курсору

Тут у мене є 2 TextBoxes і кнопка. Я повинен натиснути певну позицію в текстовому полі, а потім натиснути кнопку, щоб вставити текст з іншого текстового поля у положення попереднього текстового поля.

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

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

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')" />

Попереднє рішення (реквізит до gclaghorn) використовує textarea і також обчислює положення курсору, тож може бути краще для того, що ви хочете. З іншого боку, це було б легше, якби це те, що ти шукаєш.


Гарна ідея. Я використовував 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;
}



0

Зміст, який можна редагувати, HTML або будь-який інший вибір елементів DOM

Якщо ви намагаєтеся вставити каре на a <div contenteditable="true">, це стає набагато складніше, особливо якщо в контейнері, який можна редагувати, є діти.

Мені пощастило користуватися бібліотекою Rangy :

Він має багато чудових функцій, таких як:

  • Зберегти позицію або вибір
  • Потім пізніше відновіть позицію або вибір
  • Отримайте HTML вибору або простий текст
  • Серед багатьох інших

Демонстрація в Інтернеті не працювала востаннє, я перевірив, проте репо має робочі демонстрації. Для початку просто завантажте Repo з Git або NPM, а потім відкрийте ./rangy/demos/index.html

Це робить роботу з вибором карети та підбором тексту легким вітром!


0

Відповідь на це питання була опублікована так давно, і я натрапив на неї за допомогою пошуку в Google. HTML5 надає API HTMLInputElement, який включає метод setRangeText () , який замінює діапазон тексту в <input>або <textarea>елементі новим рядком:

element.setRangeText('abc');

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

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

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

  • 'preserve'спроби зберегти відбір. Це за замовчуванням.
  • 'select' вибирає щойно вставлений текст.
  • 'start' переміщує виділення безпосередньо до вставленого тексту.
  • 'end' переміщує виділення лише після вставленого тексту.

Сумісність браузера

Сторінка MDN для setRangeText не надає даних про сумісність браузера, але, мабуть, це буде те саме, що HTMLInputElement.setSelectionRange () , в основному це всі сучасні браузери, IE 9 і вище, Edge 12 і вище.

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