451 votes

jQuery Définir la position du curseur dans la zone de texte

Comment définir la position du curseur dans un champ de texte à l'aide de jQuery ? J'ai un champ de texte avec du contenu, et je veux que le curseur de l'utilisateur soit positionné à un certain décalage lorsqu'il se concentre sur le champ. Le code devrait ressembler à ceci :

$('#input').focus(function() {
  $(this).setCursorPosition(4);
});

À quoi ressemblerait l'implémentation de cette fonction setCursorPosition ? Si vous aviez un champ de texte avec le contenu abcdefg, cet appel entraînerait le positionnement du curseur comme suit : abcd**|**efg.

Java dispose d'une fonction similaire, setCaretPosition. Existe-t-il une méthode similaire en javascript ?

Mise à jour : J'ai modifié le code du CMS pour qu'il fonctionne avec jQuery comme suit :

new function($) {
  $.fn.setCursorPosition = function(pos) {
    if (this.setSelectionRange) {
      this.setSelectionRange(pos, pos);
    } else if (this.createTextRange) {
      var range = this.createTextRange();
      range.collapse(true);
      if(pos < 0) {
        pos = $(this).val().length + pos;
      }
      range.moveEnd('character', pos);
      range.moveStart('character', pos);
      range.select();
    }
  }
}(jQuery);

78 votes

$(this).get(0).setSelectionRange) ? Vous savez que c'est exactement la même chose que this.setSelectionRange JQuery ne fait littéralement rien pour vous, mais il est plus lent et plus difficile à lire.

2 votes

Pour ajouter au commentaire de @bobince, la fonction devrait itérer pour chacun des éléments sélectionnés et retourner ceci. Le code correct est dans ma réponse.

21 votes

@bobince n'est pas tout à fait correct non plus. this' n'est pas le nœud DOM, mais l'objet jQuery. Ainsi, $(this).get(0).setSelectionRange est identique à this.get(0).setSelectionRange, et non à this.setSelectionRange.

302voto

Mark Points 49079

Voici une solution jQuery :

$.fn.selectRange = function(start, end) {
    if(end === undefined) {
        end = start;
    }
    return this.each(function() {
        if('selectionStart' in this) {
            this.selectionStart = start;
            this.selectionEnd = end;
        } else if(this.setSelectionRange) {
            this.setSelectionRange(start, end);
        } else if(this.createTextRange) {
            var range = this.createTextRange();
            range.collapse(true);
            range.moveEnd('character', end);
            range.moveStart('character', start);
            range.select();
        }
    });
};

Avec cela, vous pouvez faire

$('#elem').selectRange(3,5); // select a range of text
$('#elem').selectRange(3); // set cursor position

2 votes

@Jesse : Je ne sais pas comment c'est arrivé, j'utilise habituellement 4. C'est corrigé.

0 votes

Je modifierais ceci, pour prendre un argument if (!end) { end = start; } return this.each(... Merci.

1 votes

@UberNeet : Mis à jour sur la base de votre suggestion.

264voto

CMS Points 315406

J'ai deux fonctions :

function setSelectionRange(input, selectionStart, selectionEnd) {
  if (input.setSelectionRange) {
    input.focus();
    input.setSelectionRange(selectionStart, selectionEnd);
  }
  else if (input.createTextRange) {
    var range = input.createTextRange();
    range.collapse(true);
    range.moveEnd('character', selectionEnd);
    range.moveStart('character', selectionStart);
    range.select();
  }
}

function setCaretToPos (input, pos) {
  setSelectionRange(input, pos, pos);
}

Vous pouvez alors utiliser setCaretToPos comme ceci :

setCaretToPos(document.getElementById("YOURINPUT"), 4);

Exemple concret avec à la fois un textarea et un input en montrant l'utilisation de jQuery :

function setSelectionRange(input, selectionStart, selectionEnd) {
  if (input.setSelectionRange) {
    input.focus();
    input.setSelectionRange(selectionStart, selectionEnd);
  } else if (input.createTextRange) {
    var range = input.createTextRange();
    range.collapse(true);
    range.moveEnd('character', selectionEnd);
    range.moveStart('character', selectionStart);
    range.select();
  }
}

function setCaretToPos(input, pos) {
  setSelectionRange(input, pos, pos);
}

$("#set-textarea").click(function() {
  setCaretToPos($("#the-textarea")[0], 10)
});
$("#set-input").click(function() {
  setCaretToPos($("#the-input")[0], 10);
});

<textarea id="the-textarea" cols="40" rows="4">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<br><input type="button" id="set-textarea" value="Set in textarea">
<br><input id="the-input" type="text" size="40" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit">
<br><input type="button" id="set-input" value="Set in input">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Depuis 2016, testé et fonctionnant sur Chrome, Firefox, IE11, même IE8 (voir ce dernier ici ; Stack Snippets ne prend pas en charge IE8).

3 votes

Pourquoi collapse(true) serait-il nécessaire puisque vous allez définir les décalages de fin et de début de sélection ?

0 votes

@mareoraft : Travaille sur textarea (et input ) pour moi sur Chrome, Firefox, IE8, et IE11.

0 votes

Je n'arrive pas à le faire fonctionner avec mon script. J'ai une zone de texte qui est vide au chargement de la page, puis remplie par javascript au fur et à mesure de l'utilisation de l'application. Je veux que le curseur soit remis à 0 avant chaque nouvelle écriture (un enregistrement de l'utilisation). est-ce que ce sont les données dynamiques qui me posent problème ? si oui, comment pourrais-je contourner cela ?

37voto

HRJ Points 4750

Les solutions ici sont correctes, sauf pour le code d'extension de jQuery.

La fonction d'extension doit itérer sur chaque élément sélectionné et renvoyer l'information suivante this pour prendre en charge le chaînage. Voici le site a version correcte :

$.fn.setCursorPosition = function(pos) {
  this.each(function(index, elem) {
    if (elem.setSelectionRange) {
      elem.setSelectionRange(pos, pos);
    } else if (elem.createTextRange) {
      var range = elem.createTextRange();
      range.collapse(true);
      range.moveEnd('character', pos);
      range.moveStart('character', pos);
      range.select();
    }
  });
  return this;
};

4 votes

La fonction each renvoie l'objet jquery. donc vous pouvez réellement faire : return this.each(function...) et supprimez la ligne "standalone".

24voto

AVProgrammer Points 626

J'ai trouvé une solution qui fonctionne pour moi :

$.fn.setCursorPosition = function(position){
    if(this.length == 0) return this;
    return $(this).setSelection(position, position);
}

$.fn.setSelection = function(selectionStart, selectionEnd) {
    if(this.length == 0) return this;
    var input = this[0];

    if (input.createTextRange) {
        var range = input.createTextRange();
        range.collapse(true);
        range.moveEnd('character', selectionEnd);
        range.moveStart('character', selectionStart);
        range.select();
    } else if (input.setSelectionRange) {
        input.focus();
        input.setSelectionRange(selectionStart, selectionEnd);
    }

    return this;
}

$.fn.focusEnd = function(){
    this.setCursorPosition(this.val().length);
            return this;
}

Maintenant vous pouvez déplacer le focus à la fin de n'importe quel élément en appelant :

$(element).focusEnd();

Ou vous spécifiez la position.

$(element).setCursorPosition(3); // This will focus on the third character.

4 votes

Pour les éléments textarea, une amélioration de focusEnd est d'ajouter this.scrollTop(this[0].scrollHeight); pour faire en sorte que la zone de texte défile de manière à rendre le point d'insertion visible.

0 votes

Selon Mozilla, j'éviterais tout simplement d'utiliser tout ce qui utilise createTextRange - developer.mozilla.org/fr/US/docs/Web/API/TextRange

13voto

BobFromBris Points 146

Cela a fonctionné pour moi sur Safari 5 sur Mac OSX, jQuery 1.4 :

$("Selector")[elementIx].selectionStart = desiredStartPos; 
$("Selector")[elementIx].selectionEnd = desiredEndPos;

0 votes

Pour moi cela ne fonctionnait pas bien avec un accès direct, mais ceci a fonctionné parfaitement. $(myID).prop('selectionStart', position) ; $(myID).prop('selectionEnd', position) ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X