使用jQuery设置鼠标焦点并将光标移动到输入的末尾

104

这个问题以前已经有过几种不同的提问方式,但我无法在我的场景中使任何答案都起作用。

我正在使用jQuery实现命令历史记录,当用户按上下箭头时。当按上箭头时,我会将输入值替换为先前的命令,并设置输入字段的焦点,但希望光标始终位于输入字符串的末尾。

我的代码如下:

$(document).keydown(function(e) {
  var key   = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
  var input = self.shell.find('input.current:last');

  switch(key) {
    case 38: // up
      lastQuery = self.queries[self.historyCounter-1];
      self.historyCounter--;
      input.val(lastQuery).focus();
// and it continues on from there

如何在聚焦后强制将光标放置在 'input' 的末尾?

20个回答

156

看起来,聚焦后清除值,然后重置可以解决问题。

input.focus();
var tmpStr = input.val();
input.val('');
input.val(tmpStr);

4
这是我找到的唯一跨浏览器可行的解决方案。向你致敬! - Meshaal
2
这在火狐和谷歌上运行良好,但在IE中不行。有人知道如何解决IE中的这个问题吗? - john Smith
1
注意,您也可以链接调用:var temp = input.focus().val(); input.val('').val(temp); - harpo
25
这可以更简单:input.focus().val(input.val());意思是让输入框获取焦点并将其值设置为当前的值,以达到清空输入框的目的。 - Fateh Khalsa
2
由于某种原因,似乎无法与contenteditable元素一起使用,可能是因为必须使用.html()而不是.val() - jg2703
显示剩余4条评论

56

它看起来有点奇怪、甚至有些傻,但对我有效:

input.val(lastQuery);
input.focus().val(input.val());

现在,我不确定我是否复制了您的设置。 我假设input是一个<input>元素。

通过重新设置值(为自身),我认为光标会被放置在输入的末尾。已在Firefox 3和MSIE7中进行了测试。


1
是的,input是一个<input>元素。我尝试过这个方法,在Firefox 3和Safari 4中没有成功。 - jerodsanto
有关这个问题有任何更新吗?对我有效。如果您找到了解决方案,请更新问题或添加答案。 - artlung
在FF15中,这将光标设置为输入字段的开头。除此之外都正常工作。你有解决方案来适配FF吗? - JochenJung
@JochenJung 我自2009年以来就没有再去看过这个问题 - 当时它能够在FF3和jQuery中工作。如果你能够使用当前版本的jQuery和FF15找到解决方案,请随意编辑这篇文章。 - artlung

54
希望这可以帮助你:
var fieldInput = $('#fieldName');
var fldLength= fieldInput.val().length;
fieldInput.focus();
fieldInput[0].setSelectionRange(fldLength, fldLength);

4
我觉得这个方法很好,比重新设置值更好,特别是在存在某种模型-视图绑定时。 - morten.c
2
这是正确的答案,可以精确地设置您想要设置的内容,而不需要任何折衷。 - Dan Barron
这个解决方案已经不再起作用了。它会出现"Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable"的错误。 - Ad Kahn

16
Chris Coyier编写了一个小型jQuery插件,可以完美地实现此功能:http://css-tricks.com/snippets/jquery/move-cursor-to-end-of-textarea-or-input/ 如果浏览器支持setSelectionRange,则使用该方法,否则使用可靠的替代方法。
jQuery.fn.putCursorAtEnd = function() {
  return this.each(function() {
    $(this).focus()
    // If this function exists...
    if (this.setSelectionRange) {
      // ... then use it (Doesn't work in IE)
      // Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh.
      var len = $(this).val().length * 2;
      this.setSelectionRange(len, len);
    } else {
      // ... otherwise replace the contents with itself
      // (Doesn't work in Google Chrome)
      $(this).val($(this).val());
    }
    // Scroll to the bottom, in case we're in a tall textarea
    // (Necessary for Firefox and Google Chrome)
    this.scrollTop = 999999;
  });
};

然后你只需要执行以下操作:
input.putCursorAtEnd();

太神奇了,这是我在2020年找到的唯一一个似乎可靠运行的解决方案。 - AdamJones

13

参考:@will824的评论。这个解决方案对我起作用,没有兼容性问题。其他解决方案在IE9中失败了。

var input = $("#inputID");
var tmp = input.val();
input.focus().val("").blur().focus().val(tmp);

测试并发现适用于:

Firefox 33
Chrome 34
Safari 5.1.7
IE 9

12

那么在一行里怎么办呢...

$('#txtSample').focus().val($('#txtSample').val());

这行代码对我有效。


8

2 artlung的回答: 在我的代码中只有第二行有效(IE7,IE8;Jquery v1.6):

var input = $('#some_elem');
input.focus().val(input.val());

补充:如果使用JQuery将input元素添加到DOM中,则IE浏览器不会设置焦点。我使用了一个小技巧:

input.blur().focus().val(input.val());

1
这对我有点用,但我必须做类似于以下的事情: var input = $(“#inputID”); tmp = input.val(); input.focus()。val(“”).blur()。focus()。val(tmp); - will824

6

对于不同的浏览器,情况会有所不同:

这个在 Firefox 中能够正常工作:

    var t =$("#INPUT");
    var l=$("#INPUT").val().length;
    $(t).focus();

    var r = $("#INPUT").get(0).createTextRange();
    r.moveStart("character", l); 
    r.moveEnd("character", l);      
    r.select();

更多详细信息可以在这些文章中找到:SitePointAspAlliance


6
我使用下面的代码,它工作得很好。
function to_end(el) {
            var len = el.value.length || 0;
            if (len) {
                if ('setSelectionRange' in el) el.setSelectionRange(len, len);
                else if ('createTextRange' in el) {// for IE
                    var range = el.createTextRange();
                    range.moveStart('character', len);
                    range.select();
                }
            }
        }

6

我知道这个答案来晚了,但是我看到人们还没有找到答案。为了防止向上箭头将光标放在开头,只需从处理事件的方法中return false即可。这样就停止了导致光标移动的事件链。以下是修改后的代码:

$(document).keydown(function(e) {
  var key   = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
  var input = self.shell.find('input.current:last');

  switch(key) {
    case 38: // up
      lastQuery = self.queries[self.historyCounter-1];
      self.historyCounter--;
      input.val(lastQuery).focus();
      // HERE IS THE FIX:
      return false; 
// and it continues on from there

1
你可以将第二行简化为 var key = e.charCode || e.keyCode || 0; - iCollect.it Ltd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接