在 html 文本框中设置键盘插入符号位置

问题描述 投票:0回答:11

有人知道如何将文本框中的键盘插入符号移动到特定位置吗?

例如,如果一个文本框(例如输入元素,而不是文本区域)中有 50 个字符,我想将插入符放在第 20 个字符之前,我该怎么做?

这与这个问题有所区别:jQuery Set Cursor Position in Text Area,这需要 jQuery。

javascript textbox input
11个回答
241
投票

摘自 Josh Stodola 的Setting keyboard caret Position in a Textbox or TextArea with Javascript

允许您在文本框或文本区域的任何位置插入插入符号的通用函数:

function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);

    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}

第一个预期参数是您希望插入键盘插入符号的元素的 ID。如果找不到该元素,则什么也不会发生(显然)。第二个参数是插入符位置索引。零会将键盘插入符放在开头。如果您传递的数字大于元素值中的字符数,它会将键盘插入符放在末尾。

在 IE6 及更高版本、Firefox 2、Opera 8、Netscape 9、SeaMonkey 和 Safari 上进行了测试。不幸的是,在 Safari 上它不能与 onfocus 事件结合使用。

使用上述函数强制键盘插入符在获得焦点时跳转到页面上所有文本区域末尾的示例:

function addLoadEvent(func) {
    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        if(func) {
            var oldLoad = window.onload;

            window.onload = function() {
                if(oldLoad)
                        oldLoad();

                func();
            }
        }
    }
}

// The setCaretPosition function belongs right here!

function setTextAreasOnFocus() {
/***
 * This function will force the keyboard caret to be positioned
 * at the end of all textareas when they receive focus.
 */
    var textAreas = document.getElementsByTagName('textarea');

    for(var i = 0; i < textAreas.length; i++) {
        textAreas[i].onfocus = function() {
            setCaretPosition(this.id, this.value.length);
        }
    }

    textAreas = null;
}

addLoadEvent(setTextAreasOnFocus);

54
投票

答案中的链接已损坏,这个应该有效(所有学分都转到blog.vishalon.net):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

以防代码再次丢失,这里有两个主要功能:

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}

40
投票

因为我实际上真的需要这个解决方案,而典型的基线解决方案(关注输入 - 然后将值设置为等于自身不能跨浏览器工作,我花了一些时间调整和编辑所有内容以获得它在职的。基于@kd7 的代码,这就是我想出的。

享受吧!适用于 IE6+、Firefox、Chrome、Safari、Opera

跨浏览器插入符号定位技术(示例:将光标移动到 END)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

肉和土豆基本上是@kd7的setCaretPosition,最大的调整是

if (el.selectionStart || el.selectionStart === 0)
,在firefox中,selectionStart从0开始,在布尔值中当然会变成False,所以它在那里中断.

在 chrome 中,最大的问题是仅仅给它

.focus()
是不够的(它一直选择所有文本!)因此,我们在调用我们的函数之前将它自己的值设置为它自己
el.value = el.value;
,现在它掌握并定位输入以使用selectionStart.

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}

23
投票

我找到了一个简单的方法来解决这个问题,在 IE 和 Chrome 中测试过:

function setCaret(elemId, caret)
 {
   var elem = document.getElementById(elemId);
   elem.setSelectionRange(caret, caret);
 }

将文本框 ID 和插入符号位置传递给此函数。


21
投票

我稍微调整了 kd7 的答案,因为当 selectionStart 偶然为 0 时,elem.selectionStart 的计算结果为 false。

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}

3
投票

如果您需要聚焦某些文本框,而您唯一的问题是整个文本都被突出显示,而您希望插入符位于末尾,那么在这种特定情况下,您可以使用这个技巧在聚焦后将文本框值设置为自身:

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

2
投票
function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }

2
投票

我会修复以下条件:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}

2
投票

HTMLInputElement.setSelectionRange(selectionStart, selectionEnd);

// References
var e = document.getElementById( "helloworldinput" );

// Move caret to beginning on focus
e.addEventListener( "focus", function( event )
{
    // References
    var e = event.target;

    // Action
    e.setSelectionRange( 0, 0 );            // Doesn’t work for focus event
    
    window.setTimeout( function()
    {
        e.setSelectionRange( 0, 0 );        // Works
        //e.setSelectionRange( 1, 1 );      // Move caret to second position
        //e.setSelectionRange( 1, 2 );      // Select second character

    }, 0 );

}, false );

浏览器兼容性(仅适用于类型:文本、搜索、网址、电话和密码): https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange#Specifications


1
投票
<!DOCTYPE html>
<html>
<head>
<title>set caret position</title>
<script type="application/javascript">
//<![CDATA[
window.onload = function ()
{
 setCaret(document.getElementById('input1'), 13, 13)
}

function setCaret(el, st, end)
{
 if (el.setSelectionRange)
 {
  el.focus();
  el.setSelectionRange(st, end);
 }
 else
 {
  if (el.createTextRange)
  {
   range = el.createTextRange();
   range.collapse(true);
   range.moveEnd('character', end);
   range.moveStart('character', st);
   range.select();
  }
 }
}
//]]>
</script>
</head>
<body>

<textarea id="input1" name="input1" rows="10" cols="30">Happy kittens dancing</textarea>

<p>&nbsp;</p>

</body>
</html>

0
投票

这是已接受答案的变体

  • 允许通过传递任何有效的 CSS 选择器来指定目标元素OR 通过提供元素本身
  • TypeScript 编写
  • 基于班级
  • SRP 通过将解决方案拆分为多个较小的函数来实现
  • 抛出自定义错误
// CaretPositioner.ts

class ElementNotFoundError extends Error {}
class InvalidArgumentValueError extends Error {}

type HTMLInputOrTextAreaElement = HTMLInputElement | HTMLTextAreaElement

class CaretPositioner {
  public static setCaretPosition (
    element: HTMLInputOrTextAreaElement,
    caretPosition: number,
  ): void

  public static setCaretPosition (
    selector: string,
    caretPosition: number,
  ): void

  public static setCaretPosition (
    elementOrSelector: HTMLInputOrTextAreaElement | string,
    caretPosition: number,
  ): void {
    const element: HTMLInputOrTextAreaElement =
      CaretPositioner.determineElement(elementOrSelector)

    CaretPositioner._setCaretPosition(element, caretPosition)
  }

  private static determineElement (
    elementOrSelector: HTMLInputOrTextAreaElement | string,
  ): HTMLInputOrTextAreaElement {
    if (
      (elementOrSelector instanceof HTMLInputElement) ||
      (elementOrSelector instanceof HTMLTextAreaElement)
    ) {
      return elementOrSelector
    } else if (CaretPositioner.isValidCssSelector(elementOrSelector)) {
      return CaretPositioner.getInputElementBySelector(elementOrSelector)
    } else {
      throw new InvalidArgumentValueError()
    }
  }

  private static isValidCssSelector (subject: unknown): boolean {
    return typeof subject === 'string' &&
      subject.length > 0
  }

  private static getInputElementBySelector (
    selector: string,
  ): HTMLInputOrTextAreaElement {
    const element = document.querySelector(selector)

    if (
      !(element instanceof HTMLInputElement) &&
      !(element instanceof HTMLTextAreaElement)
    ) {
      throw new ElementNotFoundError('element')
    }

    return element
  }

  private static _setCaretPosition (
    element: HTMLInputOrTextAreaElement,
    caretPosition: number,
  ): void {
    element.focus()
    element.setSelectionRange(caretPosition, caretPosition)
  }
}

我想将这篇文章添加为对上述答案的评论,但我没有足够的声望点。

© www.soinside.com 2019 - 2024. All rights reserved.