How do you set the cursor position in a text field using jQuery? I've got a text field with content, and I want the users cursor to be positioned at a certain offset when they focus on the field. The code should look kind of like this:
$('#input').focus(function() {
$(this).setCursorPosition(4);
});
What would the implementation of that setCursorPosition function look like? If you had a text field with the content abcdefg, this call would result in the cursor being positioned as follows: abcd**|**efg.
Java has a similar function, setCaretPosition. Does a similar method exist for javascript?
Update: I modified CMS's code to work with jQuery as follows:
new function($) {
$.fn.setCursorPosition = function(pos) {
if ($(this).get(0).setSelectionRange) {
$(this).get(0).setSelectionRange(pos, pos);
} else if ($(this).get(0).createTextRange) {
var range = $(this).get(0).createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
}(jQuery);
Source: Tips4all
I have two functions:
ReplyDeletefunction 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);
}
The you can use setCaretToPos like this:
setCaretToPos(document.getElementById("YOURINPUT"), 4);
I wanted to do this too, but I wasn't happy with the non-jQuery solution...
ReplyDelete$.fn.selectRange = function(start, end) {
return this.each(function() {
if (this.setSelectionRange) {
this.focus();
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();
}
});
};
With this, you can do
$('#elem').selectRange(3,5);
JsFiddle Example
The solutions here are right except for the jQuery extension code.
ReplyDeleteThe extension function should iterate over each selected element and return this to support chaining. Here is the a correct version:
$.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;
};
I found a solution that works for me:
ReplyDelete$.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);
}
Now you can move the focus to end of any element by calling:
$(element).focusEnd();
I'm using this: http://plugins.jquery.com/project/jCaret
ReplyDeleteIn IE to move cursor on some position this code is enough:
ReplyDeletevar range = elt.createTextRange();
range.move('character', pos);
range.select();
This worked for me on Safari 5 on Mac OSX, jQuery 1.4:
ReplyDelete$("Selector")[elementIx].selectionStart = desiredStartPos;
$("Selector")[elementIx].selectionEnd = desiredEndPos;
Just remember to return false right after the function call if you're using the arrow keys since Chrome fricks the frack up otherwise.
ReplyDelete{
document.getElementById('moveto3').setSelectionRange(3,3);
return false;
}
I found this in github:
ReplyDeletehttps://github.com/DrPheltRight/jquery-caret
You can directly change the prototype if setSelectionRange does not exist.
ReplyDelete(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
Based on this question, the answer will not work perfectly for ie and opera when there is new line in the textarea.
ReplyDeleteThe answer explain how to adjust the selectionStart, selectionEnd before calling setSelectionRange.
I have try the adjustOffset from the other question with the solution proposed by @AVProgrammer and it work.
function adjustOffset(el, offset) {
/* From http://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 http://stackoverflow.com/a/7180862/611741 */
if(this.lengh == 0) return this;
return $(this).setSelection(position, position);
}
$.fn.setSelection = function(selectionStart, selectionEnd) {
/* From http://stackoverflow.com/a/7180862/611741
modified to fit http://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 http://stackoverflow.com/a/7180862/611741 */
this.setCursorPosition(this.val().length);
}
Small modification to the code I found in bitbucket
ReplyDeleteCode is now able to select/highlight with start/end points if given 2 positions.
Tested and works fine in FF/Chrome/IE9/Opera.
$('#field').caret(1, 9);
The code is listed below, only a few lines changed:
(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)