Inserimento di un testo in cui il cursore utilizza Javascript / jquery


167

Ho una pagina con molte caselle di testo. Quando qualcuno fa clic su un collegamento, voglio che una o due parole vengano inserite nel punto in cui si trova il cursore o aggiunte alla casella di testo che ha lo stato attivo.

Ad esempio, se il cursore / focus si trova su una casella di testo che dice "apple" e fa clic su un collegamento che dice "[e-mail]", allora voglio che la casella di testo dica "apple bob@example.com".

Come posso fare questo? È anche possibile, dal momento che cosa succede se il focus è su un elemento radio / dropdown / non textbox? L'ultimo focalizzato sulla casella di testo può essere ricordato?


Suppongo sia possibile perché è la base degli editor WYSISYG, come farlo, non lo so.
Ian Elliott,


Grazie per aver posto questa domanda ... ora posso inserire "[versione]" nel cursore con la mia estensione di Chrome!
Hayakam,

Se stai cercando un modulo semplice con il supporto di annullamento, prova a inserire-text-textarea . Se hai bisogno del supporto IE8 +, prova il pacchetto insert-text-at-pointer .
fregante

Risposte:


241

Usa questo, da qui :

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
Funzionava alla grande, ma non gestisce la sostituzione del testo selezionato come fanno tutti gli editor di testo. Questo potrebbe non essere necessario per la domanda originale del poster, ma se ne hai bisogno, puoi semplicemente sostituire 'strPos' con 'txtArea.selectionEnd'. La mia risposta di seguito mostra questo, insieme alla rimozione del codice di rilevamento del browser, se non è necessario supportare versioni precedenti di IE.
Jeffrey Harmon,

C'è un modo per selezionare tutti gli elementi con areaId?
Hayakam,

1
È possibile ottenere l'eliminazione automatica del testo selezionato inserendo una funzione come questa. 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,

Come inserire testo nella posizione del mouse?
Thamarai T

Sei il migliore!
Ecko Santoso,

156

Forse una versione più breve, sarebbe più facile da capire?

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

Ho scritto questo in risposta a Come aggiungere un testo a una casella di testo dalla posizione corrente del puntatore con jquery?


11
È inoltre possibile ripristinare posizione del cursore dopo aver cambiato il valore con: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf,

1
ha funzionato per me, grazie. Cordiali saluti, la proprietà "selectionStart" non esiste tramite il selettore jquery $ ("#"). Devi consultare document.getElementById ()
Lego il

1
jsfiddle.net/NaHTw/802 è la tua soluzione con un piccolo extra aggiunto per sostituire l'area selezionata con ciò che è stato incollato
patrick

3
Bene, se stai andando così lontano rimuovendo jQuery, potresti anche rimuoverlo tutto . ; ^)
Ruffin,

8
Solo per aiutare, ecco la soluzione completa con il ripristino della posizione del punto di inserimento
AlfaTeK

41

La risposta approvata da George Claghorn ha funzionato alla grande inserendo semplicemente il testo nella posizione del cursore. Tuttavia, se l'utente ha selezionato del testo e si desidera che il testo venga sostituito (l'esperienza predefinita con la maggior parte del testo), è necessario apportare una piccola modifica quando si imposta la variabile 'back'.

Inoltre, se non è necessario supportare le versioni precedenti di IE, le versioni moderne supportano textarea.selectionStart, in modo da poter eliminare tutto il rilevamento del browser e il codice specifico di IE.

Ecco una versione semplificata che funziona almeno per Chrome e IE11 e gestisce la sostituzione del testo selezionato.

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

Questo è buono, ma non tiene maxlengthconto dell'elemento , quindi il valore risultante dopo l'inserimento potrebbe essere più lungo del massimo.
mbomb007,

22

Il codice sopra non ha funzionato per me in IE. Ecco del codice basato su questa risposta .

Ho eliminato il getElementByIdmetodo in modo da poter fare riferimento all'elemento in modo diverso.

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: aggiunto uno snippet in esecuzione, jQuery non viene utilizzato .


Element è un oggetto jquery o no? element.value e element.focus () non possono funzionare entrambi ...
Scott Stafford,

7
element.focus()è un metodo JavaScript legittimo su DOMElements: w3schools.com/jsref/met_html_focus.asp
oliverseal

1
L'idea migliore è abbandonare la compatibilità con IE.
ar2015,

2
Sì, ho scritto questa risposta 7 anni fa. A questo punto IE 11 è una buona versione minima supportata e il codice sopra funziona lì.
Collin Anderson,

6

usando la risposta di @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

Come inserire del testo nella posizione corrente del cursore di una casella di testo tramite JQuery e JavaScript

Processi

  1. Trova la posizione attuale del cursore
  2. Ottieni il testo da copiare
  3. Imposta il testo laggiù
  4. Aggiorna la posizione del cursore

Qui ho 2 caselle di testo e un pulsante. Devo fare clic su una determinata posizione in una casella di testo e quindi fare clic sul pulsante per incollare il testo dall'altra casella di testo nella posizione della casella di testo precedente.

Il problema principale qui è che ottenere l'attuale posizione del cursore in cui incolleremo il testo.

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

L'aggiunta di testo alla posizione corrente del cursore prevede due passaggi:

  1. Aggiunta del testo nella posizione corrente del cursore
  2. Aggiornamento della posizione corrente del cursore

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

Testato su Chrome 48, Firefox 45, IE 11 e 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

Penso che potresti usare il seguente JavaScript per tenere traccia della casella di testo focalizzata sull'ultimo:

<script>
var holdFocus;

function updateFocus(x)
{
    holdFocus = x;
}

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

Uso:

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

Una soluzione precedente (props to gclaghorn) usa textarea e calcola anche la posizione del cursore, quindi potrebbe essere migliore per quello che vuoi. D'altra parte, questo sarebbe più leggero, se è quello che stai cercando.


Buona idea. Ho usato jquery così ogni casella di testo che aveva una certa classe aveva questo evento applicato a loro piuttosto che dover inserire "onfocus = ..." nell'html di ogni casella di testo. Ma buon approccio :)
Fai clic su Aggiorna

1

La risposta accettata non ha funzionato per me su Internet Explorer 9. L'ho verificato e il rilevamento del browser non funzionava correttamente, ha rilevato ff (firefox) quando ero su Internet Explorer.

Ho appena fatto questa modifica:

if ($.browser.msie) 

Invece di:

if (br == "ie") { 

Il codice risultante è questo:

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

Contenuti modificabili, HTML o qualsiasi altra selezione di elementi DOM

Se si sta tentando di inserire un punto di inserimento in un punto <div contenteditable="true">, questo diventa molto più difficile, specialmente se ci sono bambini all'interno del contenitore modificabile.

Ho avuto davvero molta fortuna usando la libreria Rangy :

Ha un sacco di fantastiche funzionalità come:

  • Salva posizione o selezione
  • Quindi, ripristinare la posizione o la selezione
  • Ottieni la selezione HTML o testo normale
  • Tra molti altri

La demo online non funzionava l'ultima volta che ho controllato, tuttavia il repository ha demo funzionanti. Per iniziare, scarica semplicemente Repo da Git o NPM, quindi apri ./rangy/demos/index.html

Rende un gioco da ragazzi lavorare con la posizione del cursore e la selezione del testo!


0

La risposta a questa domanda è stata pubblicata molto tempo fa e mi sono imbattuto in esso tramite una ricerca di Google. HTML5 fornisce l' API HTMLInputElement che include il metodo setRangeText () , che sostituisce un intervallo di testo in un elemento <input>o <textarea>con una nuova stringa:

element.setRangeText('abc');

Quanto sopra sostituirebbe la selezione effettuata all'interno elementcon abc. Puoi anche specificare quale parte del valore di input sostituire:

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

Quanto sopra sostituirà il 4 ° al 6 ° carattere del valore di input con abc. Puoi anche specificare come impostare la selezione dopo che il testo è stato sostituito fornendo una delle seguenti stringhe come quarto parametro:

  • 'preserve'tenta di preservare la selezione. Questo è il valore predefinito.
  • 'select' seleziona il testo appena inserito.
  • 'start' sposta la selezione appena prima del testo inserito.
  • 'end' sposta la selezione subito dopo il testo inserito.

Compatibilità del browser

La pagina MDN per setRangeText non fornisce dati di compatibilità del browser, ma immagino che sarebbe la stessa di HTMLInputElement.setSelectionRange () , che è fondamentalmente tutti i browser moderni, IE 9 e versioni successive, Edge 12 e versioni successive.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.