Insertar un texto donde el cursor está usando Javascript / jquery

167

Tengo una página con muchos cuadros de texto. Cuando alguien hace clic en un enlace, quiero que se inserte una o dos palabras donde está el cursor, o que se agregue al cuadro de texto que tiene el foco.

Por ejemplo, si el cursor / foco está en un cuadro de texto que dice 'manzana' y hace clic en un enlace que dice '[correo electrónico]', entonces quiero que el cuadro de texto diga 'apple [email protected]'.

¿Cómo puedo hacer esto? ¿Es esto posible, ya que si el foco está en un elemento de radio / menú desplegable / no textbox? ¿Se puede recordar el último centrado en el cuadro de texto?

Haga clic en Upvote
fuente
Supongo que es posible porque es la base de los editores de WYSISYG, no sé cómo hacerlo.
Ian Elliott
Gracias por hacer esta pregunta ... ¡ahora puedo insertar "[versión]" en el cursor con mi extensión de Chrome!
haykam
Si está buscando un módulo simple con soporte para deshacer, intente insert-text-textarea . Si necesita soporte para IE8 +, pruebe el paquete insert-text-at-cursor .
fregante

Respuestas:

241

Use esto, desde aquí :

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
fuente
77
Esto funcionó muy bien, pero no maneja reemplazar el texto seleccionado como lo hacen todos los editores de texto. Esto puede no ser necesario para la pregunta original del póster, pero si lo necesita, simplemente puede reemplazar 'strPos' con 'txtArea.selectionEnd'. Mi respuesta a continuación muestra esto, junto con la eliminación del código de detección del navegador, si no necesita admitir versiones anteriores de IE.
Jeffrey Harmon
¿Hay alguna manera de seleccionar todos los elementos con areaId?
haykam
1
Puede lograr la eliminación automática del texto seleccionado insertando una función 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; }
NSTuttle
¿Cómo insertar texto en la posición del mouse?
Thamarai T
¡Eres la mejor!
Ecko Santoso
156

Tal vez una versión más corta, ¿sería más 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" />

Escribí esto en respuesta a ¿Cómo agregar un texto a un cuadro de texto desde la posición actual del puntero con jquery?

quik_silv
fuente
11
También puede restaurar la posición del símbolo después de cambiar el valor con: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf
1
funcionó para mí, gracias. Para su información, la propiedad "selectionStart" no existe a través de jquery selector $ ("#"). Debe pasar por document.getElementById ()
Lego
1
jsfiddle.net/NaHTw/802 es su solución con un poco extra agregado para reemplazar el área seleccionada con lo que está pegado
patrick
3
Bueno, si vas a llegar tan lejos eliminando jQuery, también podrías eliminarlo todo . ; ^)
ruffin
8
Solo para ayudar, aquí está la solución completa con la restauración de la posición de caret y el reemplazo del área seleccionada con contenido pegado: jsfiddle.net/NaHTw/1028
AlfaTeK
41

La respuesta aprobada de George Claghorn funcionó muy bien simplemente insertando texto en la posición del cursor. Sin embargo, si el usuario había seleccionado texto y desea que se reemplace ese texto (la experiencia predeterminada con la mayoría del texto), debe realizar un pequeño cambio al configurar la variable 'atrás'.

Además, si no necesita admitir versiones anteriores de IE, las versiones modernas admiten textarea.selectionStart, por lo que puede eliminar toda la detección del navegador y el código específico de IE.

Aquí hay una versión simplificada que funciona para Chrome e IE11 al menos, y se encarga de reemplazar el texto seleccionado.

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
fuente
Esto es bueno, pero no tiene maxlengthen cuenta los elementos , por lo que el valor resultante después de la inserción podría ser más largo que el máximo.
mbomb007
22

El código anterior no funcionó para mí en IE. Aquí hay un código basado en esta respuesta .

Saqué el getElementByIdpara poder hacer referencia al elemento de una manera 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>

EDITAR: se agregó un fragmento en ejecución, jQuery no se está utilizando .

Collin Anderson
fuente
¿Element es un objeto jquery o no? element.value y element.focus () no pueden funcionar ...
Scott Stafford
77
element.focus()es un método JavaScript legítimo en DOMElements: w3schools.com/jsref/met_html_focus.asp
oliverseal
1
La mejor idea es eliminar la compatibilidad con IE.
ar2015
2
Sí, escribí esta respuesta hace 7 años. En este punto, IE 11 es una buena versión mínima admitida, y el código anterior funciona allí.
Collin Anderson
6

usando la respuesta @quick_sliv:

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

Cómo insertar texto en la posición actual del cursor de un cuadro de texto a través de JQuery y JavaScript

Proceso

  1. Encuentra la posición actual del cursor
  2. Obtenga el texto para copiar
  3. Establecer el texto por allí
  4. Actualizar la posición del cursor

Aquí tengo 2 cuadros de texto y un botón. Tengo que hacer clic en una determinada posición en un cuadro de texto y luego hacer clic en el botón para pegar el texto del otro cuadro de texto en la posición del cuadro de texto anterior.

El problema principal aquí es obtener la posición actual del cursor donde pegaremos el 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-
fuente
3

Agregar texto a la posición actual del cursor implica dos pasos:

  1. Agregar el texto en la posición actual del cursor
  2. Actualización de la posición actual del cursor

Demostración: https://codepen.io/anon/pen/qZXmgN

Probado en Chrome 48, Firefox 45, IE 11 y 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
fuente
2

Creo que podría usar el siguiente JavaScript para rastrear el último cuadro de texto enfocado:

<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 solución anterior (accesorios para gclaghorn) usa textarea y calcula la posición del cursor también, por lo que puede ser mejor para lo que desea. Por otro lado, este sería más liviano, si eso es lo que estás buscando.

TemorPirataShawn
fuente
Buena idea. Usé jquery para que cada cuadro de texto que tenía una determinada clase se aplicara a este evento en lugar de tener que poner "onfocus = ..." en el html de cada cuadro de texto. Pero buen enfoque :)
Haga clic en Votación a favor
1

La respuesta aceptada no funcionó para mí en Internet Explorer 9. Lo revisé y la detección del navegador no funcionaba correctamente, detecté ff (firefox) cuando estaba en Internet Explorer.

Acabo de hacer este cambio:

if ($.browser.msie) 

En vez de:

if (br == "ie") { 

El código resultante es 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
fuente
0

solo puede enfocar el cuadro de texto requerido e insertar el texto allí. no hay forma de averiguar dónde está el foco AFAIK (¿tal vez interaccionando en todos los nodos DOM?).

compruebe este stackoverflow: tiene una solución para usted: ¿cómo puedo averiguar qué elemento DOM tiene el foco?

dusoft
fuente
0

Contenido editable, HTML o cualquier otra selección de elementos DOM

Si está tratando de insertarlo con cuidado en un <div contenteditable="true">, esto se vuelve mucho más difícil, especialmente si hay niños dentro del contenedor editable.

He tenido mucha suerte usando la biblioteca Rangy :

Tiene un montón de excelentes características como:

  • Guardar posición o selección
  • Luego, restaurar la posición o selección
  • Obtener selección HTML o texto sin formato
  • Entre muchos otros

La demostración en línea no funcionaba la última vez que revisé, sin embargo, el repositorio tiene demostraciones en funcionamiento. Para comenzar, simplemente descargue el Repo de Git o NPM, luego abra ./rangy/demos/index.html

¡Hace que trabajar con la posición del cursor y la selección de texto sea muy fácil!

factorypolaris
fuente
0

La respuesta de esta pregunta se publicó hace mucho tiempo y me topé con ella a través de una búsqueda en Google. HTML5 proporciona la API HTMLInputElement que incluye el método setRangeText () , que reemplaza un rango de texto en un elemento <input>o <textarea>con una nueva cadena:

element.setRangeText('abc');

Lo anterior reemplazaría la selección hecha adentro elementcon abc. También puede especificar qué parte del valor de entrada reemplazar:

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

Lo anterior reemplazaría los caracteres 4º a 6º del valor de entrada con abc. También puede especificar cómo se debe establecer la selección después de que se haya reemplazado el texto proporcionando una de las siguientes cadenas como el 4º parámetro:

  • 'preserve'intenta preservar la selección. Este es el valor predeterminado.
  • 'select' selecciona el texto recién insertado.
  • 'start' mueve la selección justo antes del texto insertado.
  • 'end' mueve la selección justo después del texto insertado.

Compatibilidad del navegador

La página MDN para setRangeText no proporciona datos de compatibilidad del navegador, pero supongo que sería lo mismo que HTMLInputElement.setSelectionRange () , que es básicamente todos los navegadores modernos, IE 9 y superior, Edge 12 y superior.

A. Genedy
fuente