मैं उपयोगकर्ता को कई स्टाइल देने के लिए एक टेक्स्ट इनपुट दिखाकर एक संख्यात्मक इनपुट मास्क/मूल्य जोड़ी बना रहा हूं (यानी हजारों को अल्पविराम से विभाजित करना), और वास्तविक मूल्य को एक छिपे हुए नंबर इनपुट में फ़ॉर्म में भेजने के लिए संग्रहीत करना।

अभी मैं देख रहा हूं कि दृश्यमान इनपुट के मान को संपादित करने से चयन सूचकांक बहुत अंत तक अपडेट हो जाता है, जो कि जब आप इनपुट को मान के बीच में। मैं समझता हूं कि स्थिति खो गई है क्योंकि मूल्य पूरी तरह से फिर से लिखा जा रहा है, लेकिन मैं इसे वापस अपडेट करने के लिए मैन्युअल रूप से इसका ट्रैक कैसे रख सकता हूं, यह देखते हुए कि on.('input') ईवेंट हैंडलर "बाद" ट्रिगर करता है मान पहले ही बदल चुका है और keydown घटना संशोधन होने से पहले होती है?

$("#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>
0
J-Rosales 30 अक्टूबर 2019, 01:30

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;
});
1
Ching Chang 29 अक्टूबर 2019, 23:10