Obtenir la position du curseur (en caractères) dans un champ de saisie de texte


212

Comment obtenir la position du curseur dans un champ de saisie?

J'ai trouvé quelques morceaux via Google, mais rien de pare-balles.

Fondamentalement, quelque chose comme un plugin jQuery serait idéal, donc je pourrais simplement faire

$("#myinput").caretPosition()

2
Essayez de rechercher la «position du curseur», qui vous donnera beaucoup plus de visites, ainsi que quelques sujets à ce sujet sur SO.
Alec


2
@CMS Trouver la position dans un <input>est beaucoup plus simple que de le faire dans un <textarea>.
Andrew Mao

1
@AndrewMao: et bien plus difficile si le texte défile et que le curseur est passé de sizecaractères.
Dan Dascalescu

@alec: je suis d'accord que la recherche du curseur au lieu du curseur peut donner plus de résultats. Comme indiqué ailleurs, j'ai appris que caret est le terme le plus approprié. Un curseur représente un emplacement dans quoi que ce soit alors qu'un caret représente un emplacement spécifique dans le texte.
Suncat2000

Réponses:


247

Mise à jour plus simple:

Utilisez l' field.selectionStart exemple dans cette réponse .

Merci à @commonSenseCode de l'avoir signalé.


Ancienne réponse:

J'ai trouvé cette solution. Pas basé sur jquery mais il n'y a aucun problème à l'intégrer à jquery:

/*
** Returns the caret (cursor) position of the specified text field (oField).
** Return value range is 0-oField.value.length.
*/
function doGetCaretPosition (oField) {

  // Initialize
  var iCaretPos = 0;

  // IE Support
  if (document.selection) {

    // Set focus on the element
    oField.focus();

    // To get cursor position, get empty selection range
    var oSel = document.selection.createRange();

    // Move selection start to 0 position
    oSel.moveStart('character', -oField.value.length);

    // The caret position is selection length
    iCaretPos = oSel.text.length;
  }

  // Firefox support
  else if (oField.selectionStart || oField.selectionStart == '0')
    iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;

  // Return results
  return iCaretPos;
}

9
else if (oField.selectionStart || oField.selectionStart == '0')pourrait êtreelse if (typeof oField.selectionStart==='number')
user2428118

Quelle est l'idée de "oField.focus ()"? Cela fonctionne pour moi sans cette ligne. Soyez prudent si vous utilisez un événement flou sur votre entrée et exécutez cette fonction dans un rappel.
Kirill Reznikov,

Testez-vous cela sur IE? Tout cela si la section est exécutée uniquement sur IE. Dans IE, il n'y a qu'une sélection globale, c'est pourquoi c'est document.selection, pas field.selectionou quelque chose. En outre, il était possible dans IE 7 (je ne sais pas s'il est toujours possible dans 8+) de sélectionner quelque chose, puis de TAB hors du champ sans perdre la sélection. De cette façon, lorsque le texte est sélectionné mais que le champ n'est pas focalisé, document.selectionretourne une sélection nulle. C'est pourquoi, comme solution de contournement pour ce bogue, vous devez vous concentrer sur l'élément avant de lire le document.selection.
bezmax

toujours obtenir 0 pour chrome et firefox
Kaushik Thanki

117

Sympa, grand merci à Max.

J'ai encapsulé la fonctionnalité dans sa réponse dans jQuery si quelqu'un veut l'utiliser.

(function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if ('selectionStart' in input) {
            // Standard-compliant browsers
            return input.selectionStart;
        } else if (document.selection) {
            // IE
            input.focus();
            var sel = document.selection.createRange();
            var selLen = document.selection.createRange().text.length;
            sel.moveStart('character', -input.value.length);
            return sel.text.length - selLen;
        }
    }
})(jQuery);

3
N'est-ce pas input = $(this).get(0)la même chose que input = this?
Mic

4
@Mic non, pas dans un plugin jQuery. Dans un plugin se thisréfère à un ensemble complet enveloppé. Son code est toujours faux cependant, il devrait l'être this.get(0). Son code fonctionnait probablement encore car le ré-emballage d'un ensemble encapsulé ne fait rien.
Chev

1
Cela me donne de fausses informations. Je regardais les positions des curseurs lors de la lecture de texte. Mon violon démontrant ceci est: jsfiddle.net/fallenreaper/TSwyk
Fallenreaper

1
Firefox génère un NS_ERROR_FAILURE sur input.selectionStart lorsque l'entrée est de type numérique, enveloppez-la dans un essai {} catch {}?
niall.campbell

serait bien pour les nouvelles abeilles si vous ajoutez l'utilisation de la fonction
Muhammad Omer Aslam

101

TRÈS FACILE

Réponse mise à jour

Utilisation selectionStart, il est compatible avec tous les principaux navigateurs .

document.getElementById('foobar').addEventListener('keyup', e => {
  console.log('Caret at: ', e.target.selectionStart)
})
<input id="foobar" />

Mise à jour: cela ne fonctionne que si aucun type n'est défini ou type="text"sur l'entrée.


2
Si je change de position à l'aide de la souris, elle n'est pas imprimée dans la console. Y a-t-il un moyen de le réparer?
Eugene Barsky

3
@EugeneBarsky Il suffit d'ajouter un nouvel écouteur d'événement pour l'événement click. Vous pouvez vérifier la .selectionStartpropriété à tout moment ( document.getElementById('foobar').selectionStart), elle ne doit pas nécessairement se trouver dans un écouteur d'événements.
JJJ

3
génial, mais ne fonctionne pas dans Firefox ou Chrome lorsque le type d'entrée est nombre.
Adam R. Gray

26

Vous avez une solution très simple . Essayez le code suivant avec un résultat vérifié -

<html>
<head>
<script>
    function f1(el) {
    var val = el.value;
    alert(val.slice(0, el.selectionStart).length);
}
</script>
</head>
<body>
<input type=text id=t1 value=abcd>
    <button onclick="f1(document.getElementById('t1'))">check position</button>
</body>
</html>

Je te donne le fiddle_demo


13
sliceest une opération relativement coûteuse et n'ajoute rien à cette «solution» - el.selectionStartéquivaut à la longueur de votre tranche; il suffit de retourner cela. De plus, la raison pour laquelle les autres solutions sont plus compliquées est qu'elles traitent avec d'autres navigateurs qui ne prennent pas en charge selectionStart.
mpen

J'ai quitté des emplois où je devais travailler avec du code avec des noms de variables comme celui-ci.
Michael Scheper

@Michael Scheper - Vous voulez dire «el» pour l'élément et «val» pour la valeur? Ce sont assez courants ...
user2782001

6
@ user2782001: J'ai mal parlé - ma principale préoccupation était le nom de la fonction. f1est à peu près aussi significatif que «user2782001». 😉
Michael Scheper

16

Il existe maintenant un joli plugin pour cela: le plugin Caret

Ensuite, vous pouvez obtenir la position en utilisant $("#myTextBox").caret()ou la définir via$("#myTextBox").caret(position)


1
le plugin caret semble être pour les éléments textarea et non pour les entrées
schmidlop

4
Eh bien, je l'ai fait fonctionner pour <input type = "text" id = "myTextBox" /> et utiliser le code ci-dessus.
Jens Mikkelsen

14
   (function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if (document.selection) {
            // IE
           input.focus();
        }
        return 'selectionStart' in input ? input.selectionStart:'' || Math.abs(document.selection.createRange().moveStart('character', -input.value.length));
     }
   })(jQuery);

10

Il y a quelques bonnes réponses publiées ici, mais je pense que vous pouvez simplifier votre code et ignorer la vérification de la inputElement.selectionStartprise en charge: il n'est pas pris en charge uniquement sur IE8 et versions antérieures (voir la documentation ), ce qui représente moins de 1% de l' utilisation actuelle du navigateur .

var input = document.getElementById('myinput'); // or $('#myinput')[0]
var caretPos = input.selectionStart;

// and if you want to know if there is a selection or not inside your input:

if (input.selectionStart != input.selectionEnd)
{
    var selectionValue =
    input.value.substring(input.selectionStart, input.selectionEnd);
}

2

Vous avez peut-être besoin d'une plage sélectionnée en plus de la position du curseur. Voici une fonction simple, vous n'avez même pas besoin de jQuery:

function caretPosition(input) {
    var start = input[0].selectionStart,
        end = input[0].selectionEnd,
        diff = end - start;

    if (start >= 0 && start == end) {
        // do cursor position actions, example:
        console.log('Cursor Position: ' + start);
    } else if (start >= 0) {
        // do ranged select actions, example:
        console.log('Cursor Position: ' + start + ' to ' + end + ' (' + diff + ' selected chars)');
    }
}

Disons que vous voulez l'appeler sur une entrée chaque fois qu'elle change ou que la souris déplace la position du curseur (dans ce cas, nous utilisons jQuery .on()). Pour des raisons de performances, il peut être judicieux d'ajouter setTimeout()ou quelque chose comme Underscores _debounce()si les événements affluent:

$('input[type="text"]').on('keyup mouseup mouseleave', function() {
    caretPosition($(this));
});

Voici un violon si vous voulez l'essayer: https://jsfiddle.net/Dhaupin/91189tq7/


0

const inpT = document.getElementById("text-box");
const inpC = document.getElementById("text-box-content");
// swch gets  inputs .
var swch;
// swch  if corsur is active in inputs defaulte is false .
var isSelect = false;

var crnselect;
// on focus
function setSwitch(e) {
  swch = e;
  isSelect = true;
  console.log("set Switch: " + isSelect);
}
// on click ev
function setEmoji() {
  if (isSelect) {
    console.log("emoji added :)");
    swch.value += ":)";
    swch.setSelectionRange(2,2 );
    isSelect = true;
  }

}
// on not selected on input . 
function onout() {
  // الافنت  اون كي اب 
  crnselect = inpC.selectionStart;
  
  // return input select not active after 200 ms .
  var len = swch.value.length;
  setTimeout(() => {
   (len == swch.value.length)? isSelect = false:isSelect = true;
  }, 200);
}
<h1> Try it !</h1>
    
		<input type="text" onfocus = "setSwitch(this)" onfocusout = "onout()" id="text-box" size="20" value="title">
		<input type="text" onfocus = "setSwitch(this)"  onfocusout = "onout()"  id="text-box-content" size="20" value="content">
<button onclick="setEmoji()">emogi :) </button>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.