jQuery设置文本区域中的光标位置。

451

如何使用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);

78
你知道$(this).get(0).setSelectionRangethis.setSelectionRange完全一样,只是更慢且更难读吗?在这里jQuery实际上没有做任何事情。 - bobince
2
补充@bobince的评论,该函数应该对每个选定的元素进行迭代并返回结果。正确的代码在我的答案中。 - HRJ
21
@bobince的说法并不完全正确。'this'不是DOM节点,而是jQuery对象。因此,$(this).get(0).setSelectionRange与this.get(0).setSelectionRange相同,但与this.setSelectionRange不同。 - Prestaul
$(this)[0] 比 $(this).get(0) 更快。 - EminezArtus
请查看此教程以获取完整解决方案。http://webdesignpluscode.blogspot.com/2017/05/how-to-set-and-get-cursor-position-in.html - Waqas Ali
16个回答

4

如果您使用箭头键,请在函数调用后立即返回false,因为否则Chrome会出现问题。

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

2
最佳实践不是使用 return false;,而是使用 event.preventDefault();。如果你使用 return false;,就意味着你同时使用了 event.stopPropagation(),这并不总是理想的。 - Alan H.

4
基于这篇问题,当文本域中有换行符时,答案无法完美适用于ie和opera。 这篇回答解释了如何在调用setSelectionRange之前调整selectionStart、selectionEnd。
我已经尝试了来自其他问题的adjustOffset,并结合@AVProgrammer提出的解决方案,它可以工作。
function adjustOffset(el, offset) {
    /* From https://dev59.com/X1_Va4cB1Zd3GeqPTnYZ#8928945 */
    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://dev59.com/GXRB5IYBdhLWcg3w1Khe#7180862 */
    if(this.lengh == 0) return this;
    return $(this).setSelection(position, position);
}

$.fn.setSelection = function(selectionStart, selectionEnd) {
    /* From https://dev59.com/GXRB5IYBdhLWcg3w1Khe#7180862 
       modified to fit https://dev59.com/X1_Va4cB1Zd3GeqPTnYZ#8928945 */
    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://dev59.com/GXRB5IYBdhLWcg3w1Khe#7180862 */
    this.setCursorPosition(this.val().length);
}

4

我在Bitbucket上找到了一段代码,经过小的修改后,现在能够根据给定的起始点和结束点进行选择/高亮。在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)

在Chrome 39、IE11和Safari 5.1.7中可以运行,在Firefox 34中无法运行:http://jsfiddle.net/0t94z82k/6/ - jbobbins

3

我必须让这个工作对于可编辑的元素和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


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


0

对于我来说,添加文本(制表符 -> \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);
    }
});

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