【问题标题】:Get cursor position (in characters) within a text Input field获取文本输入字段中的光标位置(以字符为单位)
【发布时间】:2011-02-23 05:44:58
【问题描述】:

如何从输入字段中获取插入符号的位置?

我通过谷歌找到了一些零碎的东西,但没有什么防弹的。

基本上像 jQuery 插件这样的东西是理想的,所以我可以简单地做

$("#myinput").caretPosition()

【问题讨论】:

  • 尝试搜索“光标位置”,这会给你带来更多的点击率,以及关于 SO 的一些主题。
  • @CMS 在<input> 中查找位置比在<textarea> 中查找位置要简单得多。
  • @AndrewMao:如果滚动文本并且插入符号超过 size 个字符,则难度会更大。
  • @alec:我同意搜索光标而不是插入符号可能会产生更多结果。正如在别处指出的那样,我了解到 caret 是更合适的术语。 cursor 表示任何内容中的位置,而 caret 表示特定于文本中的位置。

标签: javascript jquery html


【解决方案1】:

更新更轻松:

使用field.selectionStartexample in this answer

感谢@commonSenseCode 指出这一点。


旧答案:

找到了这个解决方案。不是基于jquery的,但是集成到jquery没有问题:

/*
** Returns the caret (cursor) position of the specified text field (oField).
** Return value range is 0-oField.value.length.
*/
function doGetCaretPosition (oField) {

  // Initialize
  var iCaretPos = 0;

  // IE Support
  if (document.selection) {

    // Set focus on the element
    oField.focus();

    // To get cursor position, get empty selection range
    var oSel = document.selection.createRange();

    // Move selection start to 0 position
    oSel.moveStart('character', -oField.value.length);

    // The caret position is selection length
    iCaretPos = oSel.text.length;
  }

  // Firefox support
  else if (oField.selectionStart || oField.selectionStart == '0')
    iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;

  // Return results
  return iCaretPos;
}

【讨论】:

  • else if (oField.selectionStart || oField.selectionStart == '0') 可能是else if (typeof oField.selectionStart==='number')
  • “oField.focus()”的概念是什么?没有这条线它对我有用。如果您在输入上使用模糊事件并在回调中执行该函数,请小心。
  • 你是在 IE 上测试吗?整个 if 部分仅在 IE 上执行。在 IE 中只有一个全局选择,这就是为什么它是 document.selection,而不是 field.selection 之类的。此外,在 IE 7 中(不知道在 8+ 中是否仍然可能)可以选择某些内容,然后 TAB 退出该字段而不会丢失选择。 This way, when the text is selected but the field is not focused, document.selection returns zero selection.这就是为什么,作为此错误的解决方法,您必须在阅读 document.selection 之前专注于元素。
  • chrome 和 firefox 总是为 0
【解决方案2】:

使用selectionStart。是compatible with all major browsers

document.getElementById('foobar').addEventListener('keyup', e => {
  console.log('Caret at: ', e.target.selectionStart)
})
<input id="foobar" />

这仅适用于未定义类型或在输入上定义type="text"type="textarea"

【讨论】:

  • 如果我使用鼠标改变位置,它不会打印在控制台中。有办法解决吗?
  • @EugeneBarsky 只需为点击事件添加一个新的事件监听器。您可以随时检查.selectionStart 属性 (document.getElementById('foobar').selectionStart),它不必位于事件侦听器中。
  • 很棒,但在输入类型为数字时在 Firefox 或 Chrome 中不起作用。
  • @JJJ 属性 'selectionStart' 在类型 'HTMLElement' 上不存在。
  • @MojioMS 这确实作为 HTMLInputElement 的一部分存在,正如已经指出的那样,如果目标是文本类型或文本区域类型,它将起作用
【解决方案3】:

如果有人想使用它,我已经将 bezmax's answer 中的功能包装到 jQuery 中。

(function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if ('selectionStart' in input) {
            // Standard-compliant browsers
            return input.selectionStart;
        } else if (document.selection) {
            // IE
            input.focus();
            var sel = document.selection.createRange();
            var selLen = document.selection.createRange().text.length;
            sel.moveStart('character', -input.value.length);
            return sel.text.length - selLen;
        }
    }
})(jQuery);

【讨论】:

  • input = $(this).get(0)input = this不一样吗?
  • @Mic 不,不在 jQuery 插件中。在插件中this 指的是完整包装的集合。他的代码仍然是错误的,它应该只是this.get(0)。他的代码可能仍然有效,因为重新包装一个包装集没有任何作用。
  • 这给了我错误的信息。我在娱乐文本时正在查看光标位置。我的小提琴证明了这一点:jsfiddle.net/fallenreaper/TSwyk
  • 当输入是数字类型时,Firefox 在 input.selectionStart 上生成一个 NS_ERROR_FAILURE,将其包装在 try {} catch {} 中?
  • 如果你添加函数的用法对新蜜蜂来说会很好
【解决方案4】:

有一个非常简单的解决方案。 尝试以下代码验证结果-

<html>
<head>
<script>
    function f1(el) {
    var val = el.value;
    alert(val.slice(0, el.selectionStart).length);
}
</script>
</head>
<body>
<input type=text id=t1 value=abcd>
    <button onclick="f1(document.getElementById('t1'))">check position</button>
</body>
</html>

我给你fiddle_demo

【讨论】:

  • slice 是一个相对昂贵的操作,它没有给这个“解决方案”增加任何东西——el.selectionStart 相当于你的切片的长度;只是返回。此外,其他解决方案更复杂的原因是因为它们处理不支持selectionStart的其他浏览器。
  • 我已经辞去了工作,因为我不得不使用这样的变量名来处理代码。
  • @Michael Scheper - 你的意思是“el”代表元素,“val”代表价值?这些很常见......
  • @user2782001:我说错了——我主要关心的是函数名。 f1 与 'user2782001' 一样有意义。 ?
【解决方案5】:

现在有一个不错的插件:The Caret Plugin

然后你可以使用$("#myTextBox").caret()获取位置或通过$("#myTextBox").caret(position)设置位置

【讨论】:

  • 插入符号插件似乎适用于 textarea 元素而不是输入
  • 好吧,我让它为 工作并使用上面的代码。
【解决方案6】:
   (function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if (document.selection) {
            // IE
           input.focus();
        }
        return 'selectionStart' in input ? input.selectionStart:'' || Math.abs(document.selection.createRange().moveStart('character', -input.value.length));
     }
   })(jQuery);

【讨论】:

    【解决方案7】:

    这里发布了一些很好的答案,但我认为您可以简化代码并跳过对inputElement.selectionStart 支持的检查:它不仅在 IE8 和更早版本上受支持(请参阅documentation),它表示小于 1当前browser usage的百分比。

    var input = document.getElementById('myinput'); // or $('#myinput')[0]
    var caretPos = input.selectionStart;
    
    // and if you want to know if there is a selection or not inside your input:
    
    if (input.selectionStart != input.selectionEnd)
    {
        var selectionValue =
        input.value.substring(input.selectionStart, input.selectionEnd);
    }
    

    【讨论】:

      【解决方案8】:

      除了光标位置之外,您可能还需要一个选定范围。这是一个简单的函数,你甚至不需要 jQuery:

      function caretPosition(input) {
          var start = input[0].selectionStart,
              end = input[0].selectionEnd,
              diff = end - start;
      
          if (start >= 0 && start == end) {
              // do cursor position actions, example:
              console.log('Cursor Position: ' + start);
          } else if (start >= 0) {
              // do ranged select actions, example:
              console.log('Cursor Position: ' + start + ' to ' + end + ' (' + diff + ' selected chars)');
          }
      }
      

      假设您想在输入更改或鼠标移动光标位置时调用它(在本例中,我们使用 jQuery .on())。出于性能原因,如果事件涌入,添加setTimeout() 或类似下划线_debounce() 可能是个好主意:

      $('input[type="text"]').on('keyup mouseup mouseleave', function() {
          caretPosition($(this));
      });
      

      如果你想尝试一下,这里有一个小提琴:https://jsfiddle.net/Dhaupin/91189tq7/

      【讨论】:

        【解决方案9】:

        const inpT = document.getElementById("text-box");
        const inpC = document.getElementById("text-box-content");
        // swch gets  inputs .
        var swch;
        // swch  if corsur is active in inputs defaulte is false .
        var isSelect = false;
        
        var crnselect;
        // on focus
        function setSwitch(e) {
          swch = e;
          isSelect = true;
          console.log("set Switch: " + isSelect);
        }
        // on click ev
        function setEmoji() {
          if (isSelect) {
            console.log("emoji added :)");
            swch.value += ":)";
            swch.setSelectionRange(2,2 );
            isSelect = true;
          }
        
        }
        // on not selected on input . 
        function onout() {
          // الافنت  اون كي اب 
          crnselect = inpC.selectionStart;
          
          // return input select not active after 200 ms .
          var len = swch.value.length;
          setTimeout(() => {
           (len == swch.value.length)? isSelect = false:isSelect = true;
          }, 200);
        }
        <h1> Try it !</h1>
            
        		<input type="text" onfocus = "setSwitch(this)" onfocusout = "onout()" id="text-box" size="20" value="title">
        		<input type="text" onfocus = "setSwitch(this)"  onfocusout = "onout()"  id="text-box-content" size="20" value="content">
        <button onclick="setEmoji()">emogi :) </button>

        【讨论】:

          【解决方案10】:

          解决办法是.selectionStart:

          var input = document.getElementById('yourINPUTid');
          input.selectionEnd = input.selectionStart = yourDESIREDposition;
          input.focus();
          

          如果没有分配.selectionEnd,则会选择一些文本(S-->E)。

          失去焦点时需要.focus();当您触发代码时(onClick)。

          我只在 Chrome 中测试过。

          如果您想要更复杂的解决方案,则必须阅读其他答案。

          【讨论】:

            猜你喜欢
            • 2010-12-20
            • 2012-12-21
            • 1970-01-01
            • 2011-10-19
            • 1970-01-01
            相关资源
            最近更新 更多