Keep cursor after same char after changing input field value

550 views Asked by At

I have an input field where the user can type numbers. I have javascript code that reformats the numbers to a currency format. I would like to keep the cursor position after the same char.

Example where user types 9 at the cursor position:

Input value: 12.3[cursor]45.678,50

New input value: 123.9[cursor]45.678,50

or

Input value: 123[cursor].456,50

New input value: 1.239.[cursor]456,50

How can I do this? Currently the cursor will snap to the end of the input field.

Inputfield:

<input type="text" class="invoiceFields invoiceDescriptionFields form-control InputStyleForms {% if description_error in form_errors %} is-invalid {% endif %}"
       id="inputDescription-{{id}}" placeholder="Beskrivelse." name="invoiceline-{{id}}-description"
       style="margin-bottom: 8px;" value="{{line.description.value|default_if_none:''}}"
       maxlength="50">

Jquuery currency formatter:

$(document).on('keyup', '.invoiceFields', function () {
    $(this).val(displayInCurrencyFormat($(this).val()));
});

const displayInCurrencyFormat = (value) => {
            value = convertToDanishFloat(value);
            value = value.toString().replace(/(?!\,)\D/g, "").replace(/(?<=\,,*)\,/g, "").replace(/(?<=\,\d\d).*/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ".");
            if(value.indexOf(",") >= 0){
                // do nothing
            } else {
                value += ",00";
            }
            return value += " kr."
        }
1

There are 1 answers

0
Heiko Theißen On

The following code maintains the selectionStart property of the input field so that if the cursor is after the N-th digit before formatting, it is placed after the N-th digit after formatting as well.

This is only meant as a starting point to this complex problem. The parse function assumes a number format with . as grouping character and , as decimal point. And for simplicity, the cursor is left alone if the user pressed anything other than a digit, Delete or Backspace.

function isdigit(c) {
  return c.match(/[0-9]/);
}

function parse(s) {
  return Number(s.replaceAll(".", "")
    .replaceAll(",", "."));
}

function format(input) {
  if (isdigit(event.key) || event.key === "Backspace" || event.key === "Delete") {
    var cursor = input.selectionStart;
    var str = input.value.substring(0, cursor);
    var num = String(parse(str));
    cursor += num.length - str.length;
    input.value = Intl.NumberFormat("da").format(parse(input.value));
    for (var i = 0; i < input.value.length; i++) {
      if (cursor === 0) {
        input.selectionStart = input.selectionEnd = i;
        break;
      }
      if (isdigit(input.value[i])) cursor--;
    }
  }
}
<input onkeyup="format(this)" value="10.002" />