Aller au contenu

[JS]position graphique du curseur dans un textarea


serik

Messages recommandés

Salut,

je cherche à obtenir la position graphique du curseur dans un textarea. Je dis bien graphique, selectionStart et selectionEnd ne donnant que l'offset dans le texte, alors que je cherche les coordonnées x,y par rapport au conteneur parent.

Ceci afin d'insérer un div en overlay juste sous le texte sélectionné.

Merci par avance!

Edit : l'objet Range ne semble pas fonctionner sur le contenu d'un textarea

Lien vers le commentaire
Partager sur d’autres sites

Humm, je ne suis pas sûr que cela sois possible.

Si je regarde l'interface standard de Range (http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/ranges.html#Level-2-Range-Comparing) il n'y a rien d'utile.

Par contre sur MSDN et MDN il y a deux trois trucs prometteurs mais non standards :

https://developer.mozilla.org/en/DOM/range

range.getBoundingClientRect() Requires Gecko 2.0

http://msdn.microsoft.com/en-us/library/ms535872(VS.85).aspx

boundingLeft Retrieves the distance between the left edge of the rectangle that bounds the TextRange object and the left side of the object that contains the TextRange.

boundingTop Retrieves the distance between the top edge of the rectangle that bounds the TextRange object and the top side of the object that contains the TextRange.

Vu que Opera et webkit implémentent une partie des interfaces non standard IE/FFx (http://www.quirksmode.org/dom/range_intro.html) Il y a peut être un espoir de faire quelque chose d'à peu près compatible, mais cela me semble très compromis.

Lien vers le commentaire
Partager sur d’autres sites

Comme je l'ai mis dans mon edit, range ne semble pas pouvoir fonctionner sur un textarea :

"Note: the getSelection method does not return the selection if the selected content is within an input:password, input:text or textarea element. For these cases, use the selectionStart and selectionEnd properties"

http://help.dottoro.com/ljcvonpc.php

J'ai essayé d'utiliser document.createRange(); puis range.selectNodeContents([le textarea]);

Mais il n'y a pas de texte sélectionné (indices de 0 en start et end, toString() renvoit une chaîne vide, le textarea contient bien sûr du texte).

J'ai lu des pages où certains calculent la position suivant les caractères et les lignes... mais c'est compliqué et pas fiable à 100%.

Y'a une démo là http://ufku.com/drupal/bueditor/contributions/cursor-offset avec BUE editor, prouvant que c'est possible, mais aucune comment ils font à l'intérieur.

D'autres utilisent une police monospace...

La solution avec gecko 2.0 me conviendrait mais comment avoir le range sur le contenu d'un textarea?

Lien vers le commentaire
Partager sur d’autres sites

Après moultes recherches il n'est pas possible d'utiliser un range sur le contenu d'un textarea.

Explications :

<textarea>

Un petit texte

</textarea>

Ceci crée un textNode sous un node textarea. Hors, lorsque l'on modifie le contenu du textarea c'est son attribut value qui change et pas le texte du textNode imbriqué. On peut changer le textNode avec la value, mais ça ne produit pas l'effet escompté vu que c'est value qui est affiché et non le textNode (donc clientRect a des bounds de 0). Je ne pense pas que FF 4.0 y changera quoi que ce soit, j'ai testé sous FF4.0 bêta portable Windows/Wine.

J'ai alors essayé de mesuré la longueur du texte, avec la méthode suivante :

- mettre le texte dans un div

- ajouter le div au body avec width=auto, height=auto, position=absolute, visibility=hidden et regarder offsetWidth

- supprimer le div

On peut avoir la largeur du texte à condition qu'il ait les mêmes attributs du texte original, et là ça se complique parce que je ne sais pas quelle est la police par défaut (c'est pas serif, sans-serif, Arial, Times New Roman, Georgia, Verdana). Mais en attribuant une police ça passe. Resterait plus qu'à compter les lignes...

Que de choses bien compliquées!

Le plus aberrant, c'est que l'offset du curseur est accessible avec IE depuis des lustres!

En attendant une solution miracle je vais mettre l'autocomplétion sur le côté.

Lien vers le commentaire
Partager sur d’autres sites

 

Ceci crée un textNode sous un node textarea. Hors, lorsque l'on modifie le contenu du textarea c'est son attribut value qui change et pas le texte du textNode imbriqué. On peut changer le textNode avec la value, mais ça ne produit pas l'effet escompté vu que c'est value qui est affiché et non le textNode (donc clientRect a des bounds de 0). Je ne pense pas que FF 4.0 y changera quoi que ce soit, j'ai testé sous FF4.0 bêta portable Windows/Wine.

:craint:

Pfff, c'est complètement bidon comme justification : dans ce cas la pourquoi je peux utiliser un Range dans un input ? Si un Range dans un textarea ne correspond pas à sa value pourquoi c'est différent dans un input ?!

De plus un Range est sensé correspondre à la sélection utilisateur, pas à l'arbre DOM d'origine. Si je sélèctionne des éléments de la page, mon Range contient des nodes de mon arbre DOM, si je me met dans le contexte d'un élément de formulaire je sélectionne une portion de sa value cela me semble évident (et c'est comme ça que fonctionne l'UI, donc l'API devrait fonctionner de manière identique) !!!

Cette explication est très clairement une excuse confuse pour ne pas se sortir les doigts du cul et corriger son implémentation ! Ce n'est ni cohérent, ni compatible avec le principe premier de l'API.  :cartonrouge:

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

Perso j'ai mis ça en application dans un script GreaseMonkey pour PCI justement (à l'abandon pour l'instant...), l'objectif étant d'afficher une DIV de proposition de smileys par-dessus la textarea des commentaires de news, bien sûr à l'endroit du curseur, en prenant en compte les sauts à la ligne, la taille de police, la position de scroll etc... En gros c'est aussi de l'autocomplétion et je trouve que ça marche plutôt pas mal :D

Voir ce topic pour description et surtout regarder la source

Grosso modo la méthodologie corresponds à peu près à ce que tu avais commencé à faire, sauf que c'est une question de règlages au niveau des la gestion des espaces et du positionnement (scrolling compris) notemment. Je te laisse mater le code, tester éventuellement (ça devrait toujours fonctionner avec les commentaires normalement) et poser des question si tu en as :ouioui:

[edit] J'oublie de préciser que la solution n'a été testée QUE avec des navigateurs supportant les custom scripts c'est à dire des versions récentes de Firefox et Chrome.

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...