447

如何使用 jQuery 在文本字段中设置光标位置?我有一个包含内容的文本字段,我希望用户光标在他们关注该字段时定位在某个偏移量处。代码应该看起来像这样:

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

该 setCursorPosition 函数的实现是什么样的?如果您有一个内容为 abcdefg 的文本字段,则此调用将导致光标定位如下:abcd**|**efg。

Java 有一个类似的函数,setCaretPosition。javascript是否存在类似的方法?

更新:我修改了 CMS 的代码以使用 jQuery,如下所示:

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

16 回答 16

302

这是一个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();
        }
    });
};

有了这个,你可以做

$('#elem').selectRange(3,5); // select a range of text
$('#elem').selectRange(3); // set cursor position
于 2009-05-08T18:17:32.917 回答
263

我有两个功能:

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

然后你可以像这样使用 setCaretToPos :

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

textarea带有 a和 an 的实时示例input,展示了 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>

截至 2016 年,已在 Chrome、Firefox、IE11 甚至 IE8 上进行了测试和工作(请参阅此处的最后一条;Stack Snippets 不支持 IE8)。

于 2009-01-31T16:56:36.723 回答
38

除了 jQuery 扩展代码之外,这里的解决方案都是正确的。

扩展函数应该遍历每个选定的元素并返回this支持链。这是正确 版本:

$.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;
};
于 2010-09-06T11:55:41.480 回答
25

我找到了一个适合我的解决方案:

$.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;
}

现在您可以通过调用将焦点移动到任何元素的末尾:

$(element).focusEnd();

或者你指定位置。

$(element).setCursorPosition(3); // This will focus on the third character.
于 2011-08-24T19:02:59.703 回答
14

这在 Mac OSX 上的 Safari 5 上对我有用,jQuery 1.4:

$("Selector")[elementIx].selectionStart = desiredStartPos; 
$("Selector")[elementIx].selectionEnd = desiredEndPos;
于 2010-08-26T15:51:17.987 回答
10

我确实意识到这是一篇非常古老的帖子,但我认为我应该提供一个更简单的解决方案来仅使用 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;
}

使用 ctrl-enter 添加新行的用法(如在 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);
    }
});

我愿意接受批评。谢谢你。

更新:此解决方案不允许正常的复制和粘贴功能工作(即 ctrl-c、ctrl-v),因此我将来必须对其进行编辑以确保该部分再次工作。如果您知道如何做到这一点,请在此处发表评论,我很乐意对其进行测试。谢谢。

于 2015-12-03T20:44:04.920 回答
8

在 IE 中将光标移动到某个位置,这段代码就足够了:

var range = elt.createTextRange();
range.move('character', pos);
range.select();
于 2009-05-14T13:12:48.197 回答
8

我正在使用这个: http: //plugins.jquery.com/project/jCaret

于 2010-01-18T20:20:29.740 回答
8

在将文本插入文本区域之前设置焦点?

$("#comments").focus();
$("#comments").val(comments);
于 2013-01-01T09:38:49.293 回答
7

这在 chrome 中对我有用

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

显然您需要一微秒或更长的延迟,因为通常用户通过单击您想要覆盖的文本字段中的某个位置(或通过点击选项卡)来关注文本字段,因此您必须等到该位置由用户单击设置,然后更改它。

于 2015-06-27T23:16:04.507 回答
4

如果您使用箭头键,请记住在函数调用后立即返回 false ,否则 Chrome 会搞砸。

{
    document.getElementById('moveto3').setSelectionRange(3,3);
    return false;
}
于 2011-03-08T01:41:34.770 回答
4

基于this question,当textarea中有新行时,对于ie和opera,答案将不完美。答案解释了如何在调用 setSelectionRange 之前调整 selectionStart、selectionEnd 。

我已经用@AVProgrammer提出的解决方案尝试了另一个问题的adjustOffset,它可以工作。

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);
}
于 2012-02-02T17:08:00.740 回答
4

对我在bitbucket中找到的代码进行小修改

如果给定 2 个位置,代码现在可以选择/突出显示起点/终点。经过测试,在 FF/Chrome/IE9/Opera 中运行良好。

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

代码如下,只改动了几行:

(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)
于 2012-04-11T05:52:27.013 回答
3

我必须让它为 contenteditable 元素和 jQuery 工作,并且有人可能希望它准备好使用:

$.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;
};

用法$(selector).getCaret()返回数字偏移量并$(selector).setCaret(num)建立偏移量并将焦点设置在元素上。

还有一个小技巧,如果您$(selector).setCaret(num)从控制台运行,它将返回 console.log,但您不会看到焦点,因为它是在控制台窗口中建立的。

最佳;D

于 2017-04-03T15:54:29.163 回答
1

如果 setSelectionRange 不存在,您可以直接更改原型。

(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链接

于 2011-10-17T07:44:50.177 回答
1

至于我这里最简单的方法是通过光标位置在 textarea 中添加文本(Tab -> \t)并将焦点保存在光标上:

$('#text').keyup(function () {
    var cursor = $('#text').prop('selectionStart');
    //if cursot is first in textarea
    if (cursor == 0) {
        //i will add tab in line
        $('#text').val('\t' + $('#text').val());
        //here we set the cursor position
        $('#text').prop('selectionEnd', 1);
    } else {
        var value = $('#text').val();
        //save the value before cursor current position
        var valToCur = value.substring(0, cursor);
        //save the value after cursor current position
        var valAfter = value.substring(cursor, value.length);
        //save the new value with added tab in text
        $('#text').val(valToCur + '\t' + valAfter);
        //set focus of cursot after insert text (1 = because I add only one symbol)
        $('#text').prop('selectionEnd', cursor + 1);
    }
});
于 2020-09-15T08:11:45.457 回答