简体   繁体   中英

How to prevent the cursor from moving when modifying an input's value?

I'm creating a numeric input mask/value pair by showing the user a text input to give it several stylings (ie dividing thousands with a comma), and storing the real value to be sent to the form in a hidden number input.

Right now I'm noticing that editing the value of the visible input updates the selection index to the very end, which is unintuitive when you edit the input from ie the middle of the value . I understand that the position has been lost since the value is being completely rewritten, but how can I manually keep track of it to update it back, given that the on.('input') event handler triggers "after" the value has already changed and the keydown event happens before the modification takes place?

 $("#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>

You can use the selectionStart property of the input fields to determine where the caret was before you completely rewrite the input field.

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;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM