修改输入值时如何防止光标移动?

Posted

技术标签:

【中文标题】修改输入值时如何防止光标移动?【英文标题】:How to prevent the cursor from moving when modifying an input's value? 【发布时间】:2020-02-25 05:08:59 【问题描述】:

我正在创建一个数字输入掩码/值对,方法是向用户显示文本输入以赋予其多种样式(即用逗号分隔千位),并将要发送到表单的实际值存储在隐藏数字中输入。

现在我注意到编辑可见输入的值会将选择索引更新到最后,当您从 the middle of the value 编辑输入时,这是不直观的。我知道位置已经丢失,因为值被完全重写,但是我如何手动跟踪它以更新它,因为on.('input') 事件处理程序触发“之后”值已经改变并且@ 987654323@事件发生在修改发生之前?

$("#foo").on('change paste input mouseup', function() 
  const validation_decimals = 3 //allowed decimal places
  const $mask = $('#foo')
  const $value = $('#baz')
  let hasDot = $mask.val().includes('.')
  let nValue = $mask.val().replace(/[a-zA-Z]/g, "").replace(/[!¡@#$%^&\/+*()=¿?":;\[\]\-_~`\\'|<>]/g, "")

  // only one period allowed
  if (hasDot) 
    if ($mask.val().match(/\./g).length > 1) 
      let newVal = $mask.val()
      const lastDot = newVal.lastIndexOf('.')
      newVal = newVal.slice(0, lastDot) + newVal.slice(lastDot + 1)
      $mask.val(newVal)
    
  
  $value.val(parseFloat($mask.val().replace(/,/g, "")))

  // adding comma-based thousands grouping
  let [integers, decimals] = $value.val().toString().split('.')
  if (integers.length > 3) 
    for (let iReverse = -3; iReverse > -integers.length; iReverse -= 4) 
      integers = integers.slice(0, iReverse) + ',' + integers.slice(iReverse)
    
  

  let fValue = integers

  if (hasDot) 
    fValue += '.'
  

  if (decimals !== undefined) 
    fValue += decimals
  

  $('#foo').val(fValue)
)

// preventing more decimal places than allowed and user-inputted commas.
$("#foo").on('select click keydown', function(e) 
  let selStart = e.target.selectionStart;
  let selEnd = e.target.selectionEnd;
  const isComma = e.keyCode == 188
  const isNumber = (e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 96 && e.keyCode <= 105)
  const validation_decimals = 3
  if ($(this).val().includes('.')) 
    const value = $(this).val()
    const decimals = value.split('.')[value.split('.').length - 1]
    const decimalLengthReached = decimals.length == validation_decimals
    const selectionBeforePeriod = selStart < value.indexOf('.') || selEnd > selStart
    if (isNumber && decimalLengthReached && !selectionBeforePeriod) 
      e.preventDefault()
    
  
  if (isComma) 
    e.preventDefault()
  
)
.input-group 
  margin: 10px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='form-group'>
  <label for='foo'>User Field (type here)</label>
  <div class="input-group mb-3">
    <input type="text" class="form-control" id='foo' step='0.01' aria-label="Amount (to the nearest dollar)">
  </div>
  <label for='baz'><em>Hidden field</em></label>
  <div class="input-group mb-3">
    <input type="number" id='baz' aria-label="Amount (to the nearest dollar)" step='0.1'>
  </div>
</div>

【问题讨论】:

【参考方案1】:

在完全重写输入字段之前,您可以使用输入字段的selectionStart 属性来确定插入符号的位置。

document.querySelector("#my-input").addEventListener("change", function() 
  // Get the position of the caret before you rewrite the input field
  let caretPosition = document.querySelector("#my-input").selectionStart;

  // Rewrite the input field here

  // Put the caret back to where it was
  document.querySelector("#my-input").selectionStart = caretPosition;
);

【讨论】:

太棒了!我不知道该物业如此容易到达。并且只是为了扩展解决方案,您还可以通过 jquery 使用 $("#name").selectionStart = value 修改此值,而不是像人们(可能错误地)期望的那样使用 $("#name").selectionStart(value)$("#name").prop('selectionStart', value)

以上是关于修改输入值时如何防止光标移动?的主要内容,如果未能解决你的问题,请参考以下文章

ubuntu vi 键入上下变成AB

vi文本编辑器的使用

如何使输入占位符随光标动态移动?

如何在不输入的情况下检测 UITextField 光标移动?

vscode如何快速将光标从文件位置移动到终端

linux终端怎么移动光标 Linux命令行快捷键