Insérer un texte là où le curseur utilise Javascript / jquery

167

J'ai une page avec beaucoup de zones de texte. Quand quelqu'un clique sur un lien, je veux qu'un mot ou deux soient insérés là où se trouve le curseur, ou ajoutés à la zone de texte qui a le focus.

Par exemple, si le curseur / focus est sur une zone de texte disant «pomme» et qu'il clique sur un lien disant «[email]», alors je veux que la zone de texte dise «apple [email protected]».

Comment puis-je faire ceci? Est-ce même possible, puisque que se passe-t-il si le focus est sur un élément radio / dropdown / non textbox? Peut-on se souvenir du dernier axé sur la zone de texte?

Cliquez sur Upvote
la source
Je suppose que c'est possible parce que c'est la base des éditeurs de WYSISYG, comment le faire, je ne sais pas.
Ian Elliott
Merci d'avoir posé cette question ... maintenant je peux insérer "[version]" au niveau du curseur avec mon extension Chrome!
haykam
Si vous recherchez un module simple avec support d'annulation, essayez insert-text-textarea . Si vous avez besoin du support IE8 +, essayez le package insert-text-at-cursor .
fregante

Réponses:

241

Utilisez ceci, à partir d' ici :

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
la source
7
Cela a très bien fonctionné, mais cela ne gère pas le remplacement du texte sélectionné comme le font tous les éditeurs de texte. Cela peut ne pas être nécessaire pour la question originale de l'affiche, mais si vous en avez besoin, vous pouvez simplement remplacer «strPos» par «txtArea.selectionEnd». Ma réponse ci-dessous montre cela, ainsi que la suppression du code de détection du navigateur, si vous n'avez pas besoin de prendre en charge les anciennes versions d'IE.
Jeffrey Harmon
Existe-t-il un moyen de sélectionner tous les éléments avec areaId?
haykam
1
Vous pouvez obtenir la suppression automatique du texte sélectionné en insérant une fonction comme celle-ci. 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
Comment insérer du texte à la position de la souris?
Thamarai T
Tu es le meilleur!
Ecko Santoso
156

Peut-être qu'une version plus courte serait plus facile à comprendre?

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

J'ai écrit ceci en réponse à Comment ajouter un texte à une zone de texte à partir de la position actuelle du pointeur avec jquery?

quik_silv
la source
11
Vous pouvez également restaurer la position caret après avoir changé la valeur avec: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf
1
travaillé pour moi, merci. Pour info, la propriété "selectionStart" n'existe pas via le sélecteur jquery $ ("#"). Vous devez passer par document.getElementById ()
Lego
1
jsfiddle.net/NaHTw/802 est votre solution avec un petit supplément ajouté pour remplacer la zone sélectionnée par ce qui est collé
patrick
3
Eh bien, si vous allez aussi loin en supprimant jQuery, vous pouvez tout aussi bien le supprimer . ; ^)
ruffin
8
Pour vous aider, voici la solution complète avec restauration de la position du curseur et remplacement de la zone sélectionnée par du contenu collé: jsfiddle.net/NaHTw/1028
AlfaTeK
41

La réponse approuvée de George Claghorn a très bien fonctionné pour insérer simplement du texte à la position du curseur. Si l'utilisateur a cependant sélectionné du texte et que vous souhaitez que ce texte soit remplacé (l'expérience par défaut avec la plupart du texte), vous devez apporter une petite modification lors de la définition de la variable «retour».

De plus, si vous n'avez pas besoin de prendre en charge les anciennes versions d'IE, les versions modernes prennent en charge textarea.selectionStart, vous pouvez donc supprimer toute la détection du navigateur et le code spécifique à IE.

Voici une version simplifiée qui fonctionne au moins pour Chrome et IE11 et gère le remplacement du texte sélectionné.

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
la source
C'est bien, mais cela ne prend pas en compte les éléments maxlength, donc la valeur résultante après l'insertion pourrait être plus longue que le maximum.
mbomb007
22

Le code ci-dessus ne fonctionnait pas pour moi dans IE. Voici un code basé sur cette réponse .

J'ai sorti le getElementByIdpour pouvoir référencer l'élément d'une manière différente.

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: Ajout d'un extrait de code en cours d'exécution, jQuery n'est pas utilisé .

Collin Anderson
la source
L'élément est-il un objet jquery ou non? element.value et element.focus () ne peuvent pas fonctionner tous les deux ...
Scott Stafford
7
element.focus()est une méthode JavaScript légitime sur DOMElements: w3schools.com/jsref/met_html_focus.asp
oliverseal
1
La meilleure idée est de supprimer la compatibilité IE.
ar2015
2
Ouais, j'ai écrit cette réponse il y a 7 ans. À ce stade, IE 11 est une bonne version minimale prise en charge, et le code ci-dessus y fonctionne.
Collin Anderson
6

en utilisant la réponse @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
la source
4

Comment insérer du texte à la position actuelle du curseur d'une zone de texte via JQuery et JavaScript

Processus

  1. Trouver la position actuelle du curseur
  2. Obtenir le texte à copier
  3. Définissez le texte là-bas
  4. Mettre à jour la position du curseur

Ici, j'ai 2 TextBoxes et un Button. Je dois cliquer sur une certaine position dans une zone de texte, puis cliquer sur le bouton pour coller le texte de l'autre zone de texte à la position de la zone de texte précédente.

Le problème principal ici est d'obtenir la position actuelle du curseur où nous allons coller le texte.

//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-
la source
3

L'ajout de texte à la position actuelle du curseur comporte deux étapes:

  1. Ajout du texte à la position actuelle du curseur
  2. Mise à jour de la position actuelle du curseur

Démo: https://codepen.io/anon/pen/qZXmgN

Testé dans Chrome 48, Firefox 45, IE 11 et 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
la source
2

Je pense que vous pouvez utiliser le JavaScript suivant pour suivre la dernière zone de texte ciblée:

<script>
var holdFocus;

function updateFocus(x)
{
    holdFocus = x;
}

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

Usage:

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

Une solution précédente (props to gclaghorn) utilise textarea et calcule également la position du curseur, donc cela peut être mieux pour ce que vous voulez. D'un autre côté, celui-ci serait plus léger, si c'est ce que vous recherchez.

DreadPirateShawn
la source
Bonne idée. J'ai utilisé jquery donc chaque zone de texte qui avait une certaine classe avait cet événement appliqué à eux plutôt que d'avoir à mettre "onfocus = ..." dans le html de chaque zone de texte. Mais bonne approche :)
Cliquez sur Upvote le
1

La réponse acceptée n'a pas fonctionné pour moi sur Internet Explorer 9. Je l'ai vérifiée et la détection du navigateur ne fonctionnait pas correctement, elle a détecté ff (firefox) lorsque j'étais à Internet Explorer.

Je viens de faire ce changement:

if ($.browser.msie) 

Au lieu de:

if (br == "ie") { 

Le code résultant est celui-ci:

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
la source
1

Ce plugin jQuery vous offre un moyen prédéfini de manipulation de sélection / caret.

Chris S
la source
0

vous ne pouvez mettre au point que la zone de texte requise et y insérer le texte. il n'y a aucun moyen de savoir où se concentre AFAIK (peut-être interagissant sur tous les nœuds DOM?).

Vérifiez ce stackoverflow - il a une solution pour vous: Comment savoir quel élément DOM a le focus?

dusoft
la source
0

Contenu modifiable, HTML ou tout autre élément DOM Sélections

Si vous essayez d'insérer au point d'insertion sur a <div contenteditable="true">, cela devient beaucoup plus difficile, surtout s'il y a des enfants dans le conteneur modifiable.

J'ai eu beaucoup de chance en utilisant la bibliothèque Rangy :

Il a une tonne de fonctionnalités intéressantes telles que:

  • Enregistrer la position ou la sélection
  • Puis plus tard, restaurer la position ou la sélection
  • Obtenir la sélection HTML ou Plaintext
  • Parmi beaucoup d'autres

La démo en ligne ne fonctionnait pas la dernière fois que j'ai vérifiée, mais le dépôt a des démos fonctionnelles. Pour commencer, téléchargez simplement le Repo depuis Git ou NPM, puis ouvrez ./rangy/demos/index.html

Cela facilite le travail avec la position caret et la sélection de texte!

facteurypolaris
la source
0

La réponse à cette question a été publiée il y a si longtemps et je suis tombée dessus via une recherche Google. HTML5 fournit l' API HTMLInputElement qui inclut la méthode setRangeText () , qui remplace une plage de texte dans un élément <input>ou <textarea>par une nouvelle chaîne:

element.setRangeText('abc');

Ce qui précède remplacerait la sélection effectuée à l'intérieur elementpar abc. Vous pouvez également spécifier la partie de la valeur d'entrée à remplacer:

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

Ce qui précède remplacerait les 4e à 6e caractères de la valeur d'entrée par abc. Vous pouvez également spécifier comment la sélection doit être définie après le remplacement du texte en fournissant l'une des chaînes suivantes comme 4ème paramètre:

  • 'preserve'tente de conserver la sélection. C'est la valeur par défaut.
  • 'select' sélectionne le texte nouvellement inséré.
  • 'start' déplace la sélection juste avant le texte inséré.
  • 'end' déplace la sélection juste après le texte inséré.

Compatibilité du navigateur

La page MDN pour setRangeText ne fournit pas de données de compatibilité du navigateur, mais je suppose que ce serait la même chose que HTMLInputElement.setSelectionRange () , qui est essentiellement tous les navigateurs modernes, IE 9 et supérieur, Edge 12 et supérieur.

A. Genedy
la source