Définir la position du curseur du clavier dans la zone de texte HTML

173

Est-ce que quelqu'un sait comment déplacer le curseur du clavier dans une zone de texte vers une position particulière?

Par exemple, si une zone de texte (par exemple un élément d'entrée, pas une zone de texte) contient 50 caractères et que je souhaite placer le curseur avant le caractère 20, comment procéder?

Ceci est différent de cette question: jQuery Définit la position du curseur dans la zone de texte , qui nécessite jQuery.

Jonhobbs
la source

Réponses:

205

Extrait de la position du curseur du clavier de Josh Stodola dans une zone de texte ou zone de texte avec Javascript

Une fonction générique qui vous permettra d'insérer le curseur à n'importe quelle position d'une zone de texte ou d'une zone de texte que vous souhaitez:

function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);

    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}

Le premier paramètre attendu est l'ID de l'élément sur lequel vous souhaitez insérer le curseur du clavier. Si l'élément est introuvable, rien ne se passera (évidemment). Le deuxième paramètre est l'indice de position caret. Zéro mettra le curseur du clavier au début. Si vous passez un nombre plus grand que le nombre de caractères dans la valeur des éléments, cela placera le curseur du clavier à la fin.

Testé sur IE6 et plus, Firefox 2, Opera 8, Netscape 9, SeaMonkey et Safari. Malheureusement, sur Safari, cela ne fonctionne pas en combinaison avec l'événement onfocus).

Un exemple d'utilisation de la fonction ci-dessus pour forcer le curseur du clavier à sauter à la fin de toutes les zones de texte de la page lorsqu'ils reçoivent le focus:

function addLoadEvent(func) {
    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        if(func) {
            var oldLoad = window.onload;

            window.onload = function() {
                if(oldLoad)
                        oldLoad();

                func();
            }
        }
    }
}

// The setCaretPosition function belongs right here!

function setTextAreasOnFocus() {
/***
 * This function will force the keyboard caret to be positioned
 * at the end of all textareas when they receive focus.
 */
    var textAreas = document.getElementsByTagName('textarea');

    for(var i = 0; i < textAreas.length; i++) {
        textAreas[i].onfocus = function() {
            setCaretPosition(this.id, this.value.length);
        }
    }

    textAreas = null;
}

addLoadEvent(setTextAreasOnFocus);
Ta01
la source
4
if(elem.selectionStart)s'arrête lorsque selectionStart vaut 0 comme l'a également souligné la réponse de jhnns.
mpartel
1
Cela ne fonctionne pas pour moi. Lorsque je clique sur la zone de texte actuelle, je m'attends à ce que la position du curseur soit au début. Découvrez mon violon jsfiddle.net/khx2w
elad.chen
La fonction setCaretPosition fonctionne très bien. Votre fonction addActionHandler, cependant, ne le fait pas. Mais même sans cela, je ne pourrais pas faire bouger le curseur sur le focus. Très probablement, c'est parce que le navigateur définit lui-même la position du curseur en fonction de la position du clic. Il ne semble pas y avoir de moyen de contourner ce que je peux dire, mais je pourrais me tromper complètement.
GJK
Fonctionne dans IE9, FF25, mais pas Chrome 30. Mieux que rien!
Umber Ferrule
J'ai elem.value = elem.value.replace(/^9/g,'+79')dans le code. Sur le curseur OperaMINI après +. cette fonction n'aide pas
eri
52

Le lien dans la réponse est cassé, celui-ci devrait fonctionner (tous les crédits vont à blog.vishalon.net ):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

Au cas où le code se perd à nouveau, voici les deux fonctions principales:

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}
éternel
la source
1
+1 pour les fonctions de base, même si certains ajustements doivent être effectués . Le nombre de lignes doit être soustrait de "pos", lors de l'utilisation de la méthode range.
Rob W
36

Étant donné que j'avais vraiment besoin de cette solution et que la solution de base typique ( concentrer l'entrée - puis définir la valeur égale à elle-même ) ne fonctionne pas entre les navigateurs , j'ai passé du temps à tout peaufiner et à modifier pour que cela fonctionne. En s'appuyant sur le code de @ kd7 , voici ce que j'ai trouvé.

Prendre plaisir! Fonctionne dans IE6 +, Firefox, Chrome, Safari, Opera

Technique de positionnement du curseur cross-browser (exemple: déplacement du curseur vers END)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

La viande et les pommes de terre est fondamentalement setCaretPosition de @ kd7 , le plus gros ajustement étant if (el.selectionStart || el.selectionStart === 0), dans Firefox, selectionStart commence à 0 , ce qui en booléen devient bien sûr False, donc ça cassait là.

Dans Chrome, le plus gros problème était que le donner .focus()ne suffisait pas (il continuait à sélectionner TOUT le texte!) Par conséquent, nous définissons la valeur de lui-même, à lui-même el.value = el.value;avant d'appeler notre fonction, et maintenant il a une prise et une position avec le entrée pour utiliser selectionStart .

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}
Mark Pieszak - Trilon.io
la source
@mcpDESIGNS J'essaye d'utiliser cette fonction quand un focus est fait sur une entrée de texte, mais je n'arrive nulle part, pourriez-vous s'il vous plaît aider à appliquer cette fonction en utilisant du javascript pur?
elad.chen
@ elad.chen Essayez-vous de les positionner à la fin de la zone de texte dès qu'ils se concentrent dessus?
Mark Pieszak - Trilon.io
@mcpDESIGNS Je souhaite placer le curseur au début du champ dès que l'élément est focalisé. Voir le violon: jsfiddle.net/KuLTU/3
elad.chen
@ elad.chen Désolé pour la folle réponse tardive! Il suffit de changer cet événement à la .onclickplace de l' .onfocusintérieur de votre fonction search_field_focus
Mark Pieszak - Trilon.io
2
el.value = el.value; [...] if(el !== null)- J'échangerais ces deux lignes. Si elest nul, el.value = el.valueéchouera, donc cette ligne doit être à l'intérieur du if.
BackSlash
21

J'ai ajusté un peu la réponse de kd7 car elem.selectionStart évaluera à false lorsque selectionStart est accessoirement 0.

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}
Johannes Ewald
la source
5

J'ai trouvé un moyen simple de résoudre ce problème, testé dans IE et Chrome:

function setCaret(elemId, caret)
 {
   var elem = document.getElementById(elemId);
   elem.setSelectionRange(caret, caret);
 }

Passez l'identifiant de la zone de texte et la position du curseur à cette fonction.

Iam_NSA
la source
3

Si vous avez besoin de concentrer une zone de texte et que votre seul problème est que tout le texte est mis en surbrillance alors que vous voulez que le curseur soit à la fin, alors dans ce cas spécifique, vous pouvez utiliser cette astuce pour définir la valeur de la zone de texte sur elle-même après la mise au point:

$("#myinputfield").focus().val($("#myinputfield").val());
manish_s
la source
2
<!DOCTYPE html>
<html>
<head>
<title>set caret position</title>
<script type="application/javascript">
//<![CDATA[
window.onload = function ()
{
 setCaret(document.getElementById('input1'), 13, 13)
}

function setCaret(el, st, end)
{
 if (el.setSelectionRange)
 {
  el.focus();
  el.setSelectionRange(st, end);
 }
 else
 {
  if (el.createTextRange)
  {
   range = el.createTextRange();
   range.collapse(true);
   range.moveEnd('character', end);
   range.moveStart('character', st);
   range.select();
  }
 }
}
//]]>
</script>
</head>
<body>

<textarea id="input1" name="input1" rows="10" cols="30">Happy kittens dancing</textarea>

<p>&nbsp;</p>

</body>
</html>
DIpak
la source
2
function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }
Keith Cromm
la source
Uncaught TypeError: Object [object HTMLInputElement] n'a pas de méthode 'startsWith'
bobpaul
1
@bobpaul: tIDdoit être l'identifiant de l'élément, pas l'objet d'élément lui-même. Si vous passez l'objet élément, vous pouvez simplement supprimer les 2 premières lignes de cette méthode, et cela fonctionnera.
awe
2

Je fixerais les conditions comme ci-dessous:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}
Alexandre Gavriliuk
la source