JQuery définit la position du curseur dans la zone de texte

Comment définissez-vous 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 des utilisateurs soit placé à un certain décalage lorsqu'il se concentre sur le champ. Le code devrait ressembler à ceci:

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

À quoi ressemblerait la mise en œuvre 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 a une fonction similaire, setCaretPosition. Existe-t-il une méthode similaire pour javascript?

Mise à jour: j'ai modifié le code de CMS pour fonctionner 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); 

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); } 

Ensuite, vous pouvez utiliser setCaretToPos comme ceci:

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

Exemple en direct avec une zone de textarea et une input , 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> 

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 le faire

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

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

La fonction d'extension doit itérer sur chaque élément sélectionné et renvoyer this pour soutenir le chaînage. Voici une 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; }; 

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; 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 vers la fin de n'importe quel élément en appelant:

 $(element).focusEnd(); 

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

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

Configurez-vous avant d'avoir inséré le texte dans la zone de texte ainsi?

 $("#comments").focus(); $("#comments").val(comments); 

Dans IE pour déplacer le curseur sur une position, ce code suffit:

 var range = elt.createTextRange(); range.move('character', pos); range.select(); 

Petite modification du code que j'ai trouvé dans bitbucket

Code est maintenant en mesure de sélectionner / mettre en surbrillance avec les points de début / fin si vous avez 2 positions. Testé et fonctionne bien dans FF / Chrome / IE9 / Opera.

 $('#field').caret(1, 9); 

Le code est répertorié ci-dessous, seules quelques lignes ont changé:

 (function($) { $.fn.caret = function(pos) { var target = this[0]; if (arguments.length == 0) { //get if (target.selectionStart) { //DOM var pos = target.selectionStart; return pos > 0 ? pos : 0; } else if (target.createTextRange) { //IE target.focus(); var range = document.selection.createRange(); if (range == null) return '0'; var re = target.createTextRange(); var rc = re.duplicate(); re.moveToBookmark(range.getBookmark()); rc.setEndPoint('EndToStart', re); return rc.text.length; } else return 0; } //set var pos_start = pos; var pos_end = pos; if (arguments.length > 1) { pos_end = arguments[1]; } if (target.setSelectionRange) //DOM target.setSelectionRange(pos_start, pos_end); else if (target.createTextRange) { //IE var range = target.createTextRange(); range.collapse(true); range.moveEnd('character', pos_end); range.moveStart('character', pos_start); range.select(); } } })(jQuery) 

Cela fonctionne pour moi en chrome

 $('#input').focus(function() { setTimeout( function() { document.getElementById('input').selectionStart = 4; document.getElementById('input').selectionEnd = 4; }, 1); }); 

Apparemment, vous avez besoin d'un délai d'une microseconde ou plus, car généralement, un utilisateur se concentre sur le champ de texte en cliquant sur une position dans le champ de texte (ou en appuyant sur l'onglet) que vous souhaitez annuler, donc vous devez attendre que la position soit Configuré par l'utilisateur, cliquez, puis modifiez-le.

Je me rends compte qu'il s'agit d'un très vieux post, mais je pensais que je devais proposer peut-être une solution plus simple pour la mettre à jour en utilisant uniquement jQuery.

 function getTextCursorPosition(ele) { return ele.prop("selectionStart"); } function setTextCursorPosition(ele,pos) { ele.prop("selectionStart", pos + 1); ele.prop("selectionEnd", pos + 1); } function insertNewLine(text,cursorPos) { var firstSlice = text.slice(0,cursorPos); var secondSlice = text.slice(cursorPos); var new_text = [firstSlice,"\n",secondSlice].join(''); return new_text; } 

Utilisation pour utiliser ctrl-enter pour ajouter une nouvelle ligne (comme dans Facebook):

 $('textarea').on('keypress',function(e){ if (e.keyCode == 13 && !e.ctrlKey) { e.preventDefault(); //do something special here with just pressing Enter }else if (e.ctrlKey){ //If the ctrl key was pressed with the Enter key, //then enter a new line break into the text var cursorPos = getTextCursorPosition($(this)); $(this).val(insertNewLine($(this).val(), cursorPos)); setTextCursorPosition($(this), cursorPos); } }); 

Je suis ouvert à la critique. Je vous remercie.

MISE À JOUR: Cette solution ne permet pas aux fonctionnalités normales de copie et de pâte de fonctionner (ctrl-c, ctrl-v), donc je devrais l'éditer à l'avenir pour vous assurer que la pièce fonctionne à nouveau. Si vous avez une idée de comment faire, veuillez commenter ici, et je serai heureux de le tester. Merci.

N'oubliez pas de renvoyer le faux juste après l'appel de la fonction si vous utilisez les touches fléchées, car Chrome frugue le morceau autrement.

 { document.getElementById('moveto3').setSelectionRange(3,3); return false; } 

Sur la base de cette question , la réponse ne fonctionnera pas parfaitement, c'est-à-dire et l'opéra quand il y a une nouvelle ligne dans la zone de texte. La réponse explique comment ajuster la sélectionStart, selectionEnd avant d'appeler setSelectionRange.

J'ai essayé l'ajustement de l'autre question avec la solution proposée par @AVProgrammer et ça marche.

 function adjustOffset(el, offset) { /* From https://stackoverflow.com/a/8928945/611741 */ var val = el.value, newOffset = offset; if (val.indexOf("\r\n") > -1) { var matches = val.replace(/\r\n/g, "\n").slice(0, offset).match(/\n/g); newOffset += matches ? matches.length : 0; } return newOffset; } $.fn.setCursorPosition = function(position){ /* From https://stackoverflow.com/a/7180862/611741 */ if(this.lengh == 0) return this; return $(this).setSelection(position, position); } $.fn.setSelection = function(selectionStart, selectionEnd) { /* From https://stackoverflow.com/a/7180862/611741 modified to fit https://stackoverflow.com/a/8928945/611741 */ if(this.lengh == 0) return this; 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(); selectionStart = adjustOffset(input, selectionStart); selectionEnd = adjustOffset(input, selectionEnd); input.setSelectionRange(selectionStart, selectionEnd); } return this; } $.fn.focusEnd = function(){ /* From https://stackoverflow.com/a/7180862/611741 */ this.setCursorPosition(this.val().length); } 

Vous pouvez modifier directement le prototype si setSelectionRange n'existe pas.

 (function() { if (!HTMLInputElement.prototype.setSelectionRange) { HTMLInputElement.prototype.setSelectionRange = function(start, end) { if (this.createTextRange) { var range = this.createTextRange(); this.collapse(true); this.moveEnd('character', end); this.moveStart('character', start); this.select(); } } } })(); document.getElementById("input_tag").setSelectionRange(6, 7); 

JsFiddle link

Je devais obtenir ce travail pour des éléments contentes et jQuery et pensé que quelqu'un pourrait le vouloir prêt à l'emploi:

 $.fn.getCaret = function(n) { var d = $(this)[0]; var s, r; r = document.createRange(); r.selectNodeContents(d); s = window.getSelection(); console.log('position: '+s.anchorOffset+' of '+s.anchorNode.textContent.length); return s.anchorOffset; }; $.fn.setCaret = function(n) { var d = $(this)[0]; d.focus(); var r = document.createRange(); var s = window.getSelection(); r.setStart(d.childNodes[0], n); r.collapse(true); s.removeAllRanges(); s.addRange(r); console.log('position: '+s.anchorOffset+' of '+s.anchorNode.textContent.length); return this; }; 

Utilisation $(selector).getCaret() renvoie le décalage numérique et $(selector).setCaret(num) établit le décalage et met l'accent sur l'élément.

Aussi, un petit conseil, si vous exécutez $(selector).setCaret(num) de la console, il renverra le console.log mais vous ne visualiserez pas la mise au point puisqu'il est établi sur la fenêtre de la console.

Bests; D