Comment puis-je obtenir les coordonnées de pixels (x, y) du curseur dans les zones de texte?

J'utilise jQuery et j'essaie de trouver un moyen croisé pour obtenir les coordonnées en pixels du curseur dans les boîtes <textarea>s et input de sorte que je puisse placer un div absolument positionné autour de cet emplacement.

Y a-t-il un plugin jQuery? Ou un extrait JavaScript pour faire exactement cela?

28
demandé sur Dan Dascalescu 2008-08-27 12:05:37

3 réponses

J'ai cherché un plugin textarea caret coordinates pour meteor-autocomplete , donc j'ai évalué tous les 8 plugins sur GitHub. Le gagnant est, de loin, textarea-caret-position à partir de Composant.

Caractéristiques

  • précision des pixels
  • aucune dépendance
  • compatibilité du navigateur: Chrome, Safari, Firefox (malgré deux bugs il a), IE9+; peut fonctionner mais pas testé dans Opera, IE8 ou plus vieux
  • prend en charge toute famille de polices et la taille, ainsi que le texte-transforme
  • la zone de texte peut avoir un remplissage ou des bordures arbitraires
  • pas confondu par des barres de défilement horizontales ou verticales dans la zone de texte
  • prend en charge les retours durs, les onglets (sauf sur IE) et les espaces consécutifs dans le texte
  • position correcte sur les lignes plus longues que les colonnes de la zone de texte
  • non position"fantôme" dans l'espace vide à la fin d'une ligne lors de l'emballage long mots

Voici une démo - http://jsfiddle.net/dandv/aFPA7/

entrez la description de l'image ici

Comment ça marche

Un miroir {[0] } est créé hors écran et stylisé exactement comme le <textarea>. Ensuite, le texte de la zone de texte jusqu'au curseur est copié dans le div et un <span> est inséré juste après. Ensuite, le contenu du texte de la durée est définie à la suite du texte dans le textarea, afin de reproduire fidèlement l'emballage dans le faux-div.

C'est la seule méthode garantie pour gérer tous les cas de bord relatifs à l'emballage de longues lignes. Il est également utilisé par GitHub pour déterminer la position de son @ liste déroulante utilisateur.

31
répondu Dan Dascalescu 2014-03-17 11:11:14

Note: Cette réponse décrit comment obtenir les coordonnées de caractères du curseur/curseur de texte. Pour trouver les coordonnées des pixels, vous devrez étendre cela plus loin.

La première chose à retenir est que le curseur peut être dans trois états

  • un curseur d'insertion régulier à une position spécifique
  • une sélection de texte qui a une certaine zone délimitée
  • non actif: textarea n'a pas de focus. N'a pas été utilisé.

Le modèle IE utilise le Objet document.selection , à partir de cela, nous pouvons obtenir un objet TextRange qui nous donne accès à la sélection et donc à la(aux) position (s) du curseur.

Le modèle FF / Opera utilise les variables pratiques [input].selectionStart et selectionEnd.

Les deux modèles représentent un curseur ative régulier sous la forme d'une sélection de largeur nulle, la limite gauche étant la position du curseur.

Si le champ de saisie n'a pas de focus, vous pouvez constater que ni l'un ni l'autre n'est défini. J'ai eu un bon succès avec le code suivant pour insérer un morceau de texte à l'emplacement actuel du curseur, en remplaçant également la sélection actuelle, le cas échéant. Selon le navigateur exact, YMMV.

function insertAtCursor(myField, myValue) {

/* selecion model - ie */
if (document.selection) {
  myField.focus();
  sel = document.selection.createRange();
  sel.text = myValue;
}

/* field.selectionstart/end  firefox */ 
else if (myField.selectionStart || myField.selectionStart == '0' ) {

  var startPos = myField.selectionStart;
  var endPos = myField.selectionEnd;
  myField.value = myField.value.substring(0, startPos)
    + myValue
    + myField.value.substring(endPos, myField.value.length);

  myField.selectionStart = startPos + myValue.length;
  myField.selectionEnd = startPos + myValue.length;
  myField.focus();
} 

// cursor not active/present
else {
  myField.value += myValue;
}

Note de Bug: les liens ne sont pas correctement balisés dans le para supérieur.

Objet de sélection: http://msdn.microsoft.com/en-us/library/ms535869 (VS.85).aspx
Objet TextRange: http://msdn.microsoft.com/en-us/library/ms535872 (VS.85).aspx

1
répondu Cheekysoft 2008-08-27 12:59:44

Je ne pense pas que cela puisse être fait dans tous les navigateurs. Quelqu'un l'a fait dans IE6, mais cela ne fonctionne pas dans FF ou Opera (AFAIK). Peut-être que vous pouvez le faire fonctionner dans tous les navigateurs.

Voici un billet de blog de 2005 .

0
répondu Marius 2014-03-17 02:26:32