Wstawianie tekstu, w którym kursor używa Javascript / jquery


167

Mam stronę z wieloma polami tekstowymi. Kiedy ktoś kliknie łącze, chcę wstawić słowo lub dwa w miejscu kursora lub dołączyć do pola tekstowego, na którym jest fokus.

Na przykład, jeśli kursor / fokus znajduje się na polu tekstowym z napisem „jabłko” i kliknie łącze „[e-mail]”, chcę, aby w polu tekstowym było napisane „jabłko bob@example.com”.

W jaki sposób mogę to zrobić? Czy jest to w ogóle możliwe, ponieważ co, jeśli fokus znajduje się na elemencie radio / dropdown / non textbox? Czy można zapamiętać ostatni skupiony na polu tekstowym?


Zakładam, że to możliwe, bo to podstawa redaktorów WYSISYG, jak to zrobić, nie wiem.
— Ian Elliott


Dziękuję za zadanie tego pytania… teraz mogę wstawić „[wersja]” pod kursorem za pomocą mojego rozszerzenia do Chrome!
— Haykam

Jeśli szukasz prostego modułu z obsługą cofania, wypróbuj wstaw-tekst- obszar -tekst . Jeśli potrzebujesz obsługi IE8 +, wypróbuj pakiet wstawiania tekstu w miejscu kursora .
— fregante

Odpowiedzi:


241

Użyj tego stąd :

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
To działało świetnie, ale nie obsługuje zastępowania zaznaczonego tekstu, jak robią to wszystkie edytory tekstu. Może to nie być potrzebne w przypadku oryginalnego pytania autora, ale jeśli tego potrzebujesz, możesz po prostu zamienić „strPos” na „txtArea.selectionEnd”. Moja odpowiedź poniżej pokazuje to, wraz z usunięciem kodu wykrywania przeglądarki, jeśli nie potrzebujesz obsługi starszych wersji IE.
— Jeffrey Harmon,

Czy istnieje sposób na wybranie wszystkich elementów areaId?
— Haykam

1
Możesz osiągnąć automatyczne usuwanie zaznaczonego tekstu, wstawiając taką funkcję. 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

Jak wstawić tekst w miejscu myszy?
— Thamarai T

Jesteś najlepszy!
— Ecko Santoso

156

Może krótsza wersja byłaby łatwiejsza do zrozumienia?

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

Napisałem to w odpowiedzi na Jak dodać tekst do pola tekstowego z aktualnej pozycji wskaźnika za pomocą jquery?


11
Można także przywrócić daszka pozycję po zmianie wartości z: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
— Bludwarf

1
pracował dla mnie, dzięki. FYI właściwość "selectionStart" nie istnieje za pośrednictwem selektora jquery $ ("#"). Musisz przejść przez document.getElementById ()
— Lego

1
jsfiddle.net/NaHTw/802 to Twoje rozwiązanie z niewielkim dodatkiem, aby zastąpić wybrany obszar tym, co zostało wklejone
— patrick,

3
Cóż, jeśli zamierzasz posunąć się tak daleko, usuwając jQuery, równie dobrze możesz usunąć to wszystko . ; ^)
— ruffin

8
Aby pomóc, oto kompletne rozwiązanie z przywracaniem pozycji karetki i zastępowaniem wybranego obszaru wklejoną zawartością: jsfiddle.net/NaHTw/1028
— AlfaTeK

41

Zatwierdzona odpowiedź od George'a Claghorna działała świetnie, gdy po prostu wstawiał tekst w miejscu kursora. Jeśli jednak użytkownik zaznaczył tekst i chcesz, aby ten tekst został zastąpiony (domyślne rozwiązanie z większością tekstu), musisz wprowadzić niewielką zmianę podczas ustawiania zmiennej „wstecz”.

Ponadto, jeśli nie potrzebujesz obsługi starszych wersji IE, nowoczesne wersje obsługują textarea.selectionStart, dzięki czemu możesz wyłączyć wszystkie funkcje wykrywania przeglądarki i kod specyficzny dla IE.

Oto uproszczona wersja, która działa przynajmniej w Chrome i IE11 i obsługuje zastępowanie zaznaczonego tekstu.

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

To dobrze, ale nie bierze maxlengthpod uwagę elementu , więc wynikowa wartość po wstawieniu może być dłuższa niż maksymalna.
— mbomb007

22

Powyższy kod nie działał dla mnie w IE. Oto kod oparty na tej odpowiedzi .

Wyciągnąłem element, getElementByIdwięc mogłem odwołać się do elementu w inny sposób.

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>

EDYCJA: Dodano działający fragment kodu, jQuery nie jest używany .


Czy element jest obiektem jquery, czy nie? element.value i element.focus () nie mogą działać jednocześnie ...
— Scott Stafford,

7
element.focus()to legalna metoda JavaScript na DOMElements: w3schools.com/jsref/met_html_focus.asp
— oliverseal

1
Najlepszym pomysłem jest rezygnacja z kompatybilności z IE.
— ar2015

2
Tak, napisałem tę odpowiedź 7 lat temu. W tym momencie IE 11 jest dobrą minimalną obsługiwaną wersją, a powyższy kod tam działa.
— Collin Anderson

6

używając @quick_sliv answer:

function insertAtCaret(el, text) {
    var caretPos = el.selectionStart;
    var textAreaTxt = el.value;
    el.value = textAreaTxt.substring(0, caretPos) + text + textAreaTxt.substring(caretPos);
};

4

Jak wstawić tekst do bieżącej pozycji kursora TextBox za pomocą JQuery i JavaScript

Proces

  1. Znajdź aktualną pozycję kursora
  2. Uzyskaj tekst do skopiowania
  3. Ustaw tam tekst
  4. Zaktualizuj pozycję kursora

Tutaj mam 2 pola tekstowe i przycisk. Muszę kliknąć określoną pozycję w polu tekstowym, a następnie kliknąć przycisk, aby wkleić tekst z drugiego pola tekstowego do pozycji poprzedniego pola tekstowego.

Głównym problemem jest to, że uzyskanie aktualnej pozycji kursora, w którym wkleimy tekst.

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

Dodanie tekstu do aktualnej pozycji kursora obejmuje dwa kroki:

  1. Dodanie tekstu w aktualnej pozycji kursora
  2. Aktualizacja aktualnej pozycji kursora

Demo: https://codepen.io/anon/pen/qZXmgN

Przetestowano w Chrome 48, Firefox 45, IE 11 i 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

Myślę, że możesz użyć następującego JavaScript do śledzenia ostatniego pola tekstowego:

<script>
var holdFocus;

function updateFocus(x)
{
    holdFocus = x;
}

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

Stosowanie:

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

Poprzednie rozwiązanie (rekwizyty do gclaghorn) używa textarea i oblicza również pozycję kursora, więc może być lepsze dla tego, co chcesz. Z drugiej strony ten byłby lżejszy, jeśli tego właśnie szukasz.


Dobry pomysł. Użyłem jquery, więc do każdego pola tekstowego, które miało określoną klasę, zastosowano to zdarzenie, zamiast umieszczać „onfocus = ...” w kodzie HTML każdego pola tekstowego. Ale dobre podejście :)
— Kliknij „Upvote”

1

Zaakceptowana odpowiedź nie działała dla mnie w Internet Explorerze 9. Sprawdziłem to i wykrywanie przeglądarki nie działało poprawnie, wykryło ff (firefox), kiedy byłem w Internet Explorerze.

Właśnie dokonałem tej zmiany:

if ($.browser.msie) 

Zamiast:

if (br == "ie") { 

Wynikowy kod jest taki:

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

Możliwość edycji treści, HTML lub dowolny inny element DOM

Jeśli próbujesz wstawić z daszkiem na a <div contenteditable="true">, staje się to znacznie trudniejsze, zwłaszcza jeśli w edytowalnym kontenerze znajdują się elementy podrzędne.

Miałem naprawdę wielkie szczęście korzystając z biblioteki Rangy :

Posiada mnóstwo wspaniałych funkcji, takich jak:

  • Zapisz pozycję lub wybór
  • Później przywróć pozycję lub zaznaczenie
  • Uzyskaj wybór HTML lub zwykły tekst
  • Wśród wielu innych

Demo online nie działało ostatnio, gdy sprawdzałem, jednak repozytorium ma działające wersje demonstracyjne. Aby rozpocząć, po prostu pobierz repozytorium z Git lub NPM, a następnie otwórz ./rangy/demos/index.html

To sprawia, że ​​praca z karetką i zaznaczaniem tekstu jest dziecinnie prosta!


0

Odpowiedź na to pytanie została opublikowana tak dawno temu i natknąłem się na nią przez wyszukiwarkę Google. HTML5 udostępnia interfejs API HTMLInputElement, który zawiera metodę setRangeText () , która zastępuje zakres tekstu w elemencie <input>lub <textarea>nowym ciągiem znaków:

element.setRangeText('abc');

Powyższy zastąpi wybór dokonany wewnątrz elementz abc. Możesz również określić, która część wartości wejściowej ma zostać zastąpiona:

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

Powyższe zamieniłoby od 4 do 6 znaki wartości wejściowej na abc. Możesz również określić, w jaki sposób należy ustawić zaznaczenie po zamianie tekstu, podając jeden z następujących ciągów jako czwarty parametr:

  • 'preserve'próbuje zachować wybór. To jest ustawienie domyślne.
  • 'select' wybiera nowo wstawiony tekst.
  • 'start' przenosi zaznaczenie tuż przed wstawionym tekstem.
  • 'end' przenosi zaznaczenie tuż za wstawionym tekstem.

Zgodność z przeglądarkami

Strona MDN dla setRangeText nie dostarcza danych dotyczących zgodności przeglądarek, ale myślę, że byłaby taka sama jak HTMLInputElement.setSelectionRange () , czyli w zasadzie wszystkie nowoczesne przeglądarki, IE 9 i nowsze , Edge 12 i nowsze .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.