Inserindo um texto em que o cursor está usando Javascript / jquery

167

Eu tenho uma página com muitas caixas de texto. Quando alguém clica em um link, quero que uma ou duas palavras sejam inseridas onde está o cursor ou anexadas à caixa de texto que tem o foco.

Por exemplo, se o cursor / foco estiver em uma caixa de texto dizendo 'apple' e ele clicar em um link dizendo '[email]', então eu quero que a caixa de texto diga 'apple [email protected]'.

Como posso fazer isso? Isso é possível, e se o foco estiver em um elemento de rádio / menu suspenso / sem caixa de texto? A última focada na caixa de texto pode ser lembrada?

Click Voto a favor
fonte
Suponho que seja possível porque é a base dos editores do WYSISYG, como fazê-lo, não sei.
31560 Ian
Obrigado por fazer esta pergunta ... agora posso inserir "[versão]" no cursor com minha extensão do Chrome!
haykam
Se você estiver procurando por um módulo simples com suporte a desfazer, tente inserir texto-texto-área . Se você precisar do suporte ao IE8 +, tente o pacote inserir texto no cursor .
28819 fregante

Respostas:

241

Use isso aqui :

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
fonte
7
Isso funcionou muito bem, mas não lida com a substituição do texto selecionado, como fazem todos os editores de texto. Isso pode não ser necessário para a pergunta original do pôster, mas se você precisar, pode simplesmente substituir 'strPos' por 'txtArea.selectionEnd'. Minha resposta abaixo mostra isso, juntamente com a remoção do código de detecção do navegador, se você não precisar suportar versões mais antigas do IE.
Jeffrey Harmon
Existe uma maneira de selecionar todos os elementos areaId?
21716 haykam
1
Você pode conseguir excluir automaticamente o texto selecionado inserindo uma função como esta. 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; }
precisa saber é o seguinte
Como inserir texto na posição do mouse?
Thamarai T
Você é o melhor!
Ecko Santoso
156

Talvez uma versão mais curta, seria mais fácil de entender?

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

Eu escrevi isso em resposta a Como adicionar um texto a uma caixa de texto a partir da posição atual do ponteiro com jquery?

quik_silv
fonte
11
Você também pode restaurar a posição do cursor após alterar o valor com: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf
1
trabalhou para mim, obrigado. Para sua informação, a propriedade "selectionStart" não existe através do seletor jquery $ ("#"). Você precisa passar por document.getElementById ()
Lego
1
jsfiddle.net/NaHTw/802 é a sua solução com um pouco mais de acréscimo para substituir a área selecionada pelo que é colado
patrick
3
Bem, se você for tão longe removendo o jQuery, poderá remover tudo . ; ^)
ruffin
8
Apenas para ajudar, aqui está a solução completa com a posição acento circunflexo restaurar além de substituir a área selecionada com conteúdo colado: jsfiddle.net/NaHTw/1028
ALFATEK
41

A resposta aprovada de George Claghorn funcionou muito bem para simplesmente inserir texto na posição do cursor. Se o usuário selecionou o texto e você deseja que o texto seja substituído (a experiência padrão com a maioria dos textos), faça uma pequena alteração ao definir a variável 'back'.

Além disso, se você não precisar oferecer suporte a versões mais antigas do IE, as versões modernas suportam textarea.selectionStart, para que você possa remover toda a detecção do navegador e o código específico do IE.

Aqui está uma versão simplificada que funciona pelo menos para Chrome e IE11 e lida com a substituição do texto selecionado.

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;
}
Jeffrey Harmon
fonte
Isso é bom, mas não leva maxlengthem conta o elemento , portanto o valor resultante após a inserção pode ser maior que o máximo.
Mbomb007
22

O código acima não funcionou para mim no IE. Aqui está um código com base nesta resposta .

Tirei o getElementByIdpara poder referenciar o elemento de uma maneira diferente.

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: Adicionado um snippet em execução, o jQuery não está sendo usado .

Collin Anderson
fonte
O elemento é um objeto jquery ou não? element.value e element.focus () pode não tanto trabalho ...
Scott Stafford
7
element.focus()é um método JavaScript legítimo em DOMElements: w3schools.com/jsref/met_html_focus.asp
oliverseal
1
A melhor idéia é abandonar a compatibilidade do IE.
Ar2015 04/0418
2
Sim, eu escrevi esta resposta há 7 anos. Neste ponto, o IE 11 é uma boa versão mínima suportada e o código acima funciona lá.
22618 Collin Anderson #
6

usando a resposta @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
fonte
4

Como inserir algum texto na posição atual do cursor de um TextBox por JQuery e JavaScript

Processo

  1. Encontre a posição atual do cursor
  2. Obter o texto a ser copiado
  3. Coloque o texto ali
  4. Atualizar a posição do cursor

Aqui eu tenho 2 TextBoxes e um botão. Eu tenho que clicar em uma determinada posição em uma caixa de texto e, em seguida, clique no botão para colar o texto da outra caixa de texto para a posição da caixa de texto anterior.

O principal problema aqui é que, obtendo a posição atual do cursor onde colaremos o texto.

//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>
Sunil K Behera -MindFire Sol-
fonte
3

A adição de texto à posição atual do cursor envolve duas etapas:

  1. Adicionando o texto na posição atual do cursor
  2. Atualizando a posição atual do cursor

Demonstração: https://codepen.io/anon/pen/qZXmgN

Testado no 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>
Razan Paul
fonte
2

Eu acho que você poderia usar o seguinte JavaScript para rastrear a última caixa de texto focada:

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

Uma solução anterior (props para gclaghorn) usa a área de texto e calcula a posição do cursor também, portanto, pode ser melhor para o que você deseja. Por outro lado, este seria mais leve, se é isso que você está procurando.

DreadPirateShawn
fonte
Boa ideia. Eu usei o jquery para que cada caixa de texto que tivesse uma determinada classe tivesse esse evento aplicado a eles, em vez de precisar colocar "onfocus = ..." no html de cada caixa de texto. But good approach :)
Click Voto a favor
1

A resposta aceita não funcionou para mim no Internet Explorer 9. Eu verifiquei e a detecção do navegador não estava funcionando corretamente, detectou ff (firefox) quando eu estava no Internet Explorer.

Acabei de fazer essa alteração:

if ($.browser.msie) 

Ao invés de:

if (br == "ie") { 

O código resultante é este:

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
fonte
1

Este plugin jQuery oferece uma maneira pré-fabricada de seleção / manipulação de sinal de intercalação.

Chris S
fonte
0

você pode focar apenas a caixa de texto necessária e inserir o texto nela. não há como descobrir onde o foco está no AFAIK (talvez interagindo em todos os nós do DOM?).

verifique este stackoverflow - ele tem uma solução para você: Como descobrir qual elemento DOM tem o foco?

dusoft
fonte
0

Conteúdo editável, HTML ou qualquer outro elemento DOM

Se você estiver tentando inserir um sinal de intercalação em a <div contenteditable="true">, isso se tornará muito mais difícil, especialmente se houver filhos no contêiner editável.

Eu tive muita sorte usando a biblioteca Rangy :

Ele tem vários recursos excelentes, como:

  • Salvar posição ou seleção
  • Depois, restaure a posição ou seleção
  • Obter seleção HTML ou Texto sem formatação
  • Entre muitos outros

A demonstração on-line não estava funcionando da última vez que verifiquei, no entanto, o repositório tem demos em funcionamento. Para começar, faça o download do repositório Git ou NPM e abra ./rangy/demos/index.html

Isso facilita o trabalho com pontos de intercalação e seleção de texto!

factorypolaris
fonte
0

A resposta desta pergunta foi postada há muito tempo e eu a encontrei através de uma pesquisa no Google. O HTML5 fornece a API HTMLInputElement que inclui o método setRangeText () , que substitui um intervalo de texto em um elemento <input>ou <textarea>por uma nova string:

element.setRangeText('abc');

O exemplo acima substituiria a seleção feita por dentro elementcom abc. Você também pode especificar qual parte do valor de entrada substituir:

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

O texto acima substituiria os caracteres de 4 a 6 do valor de entrada por abc. Você também pode especificar como a seleção deve ser definida após a substituição do texto, fornecendo uma das seguintes seqüências de caracteres como o quarto parâmetro:

  • 'preserve'tenta preservar a seleção. Esse é o padrão.
  • 'select' seleciona o texto recém-inserido.
  • 'start' move a seleção para pouco antes do texto inserido.
  • 'end' move a seleção para logo após o texto inserido.

Compatibilidade do navegador

A página MDN para setRangeText não fornece dados de compatibilidade do navegador, mas acho que seria o mesmo que HTMLInputElement.setSelectionRange () , que é basicamente todos os navegadores modernos, IE 9 e superior, Edge 12 e superior.

A. Genedy
fonte