Skip to content Skip to sidebar Skip to footer

Set Caret Back To It's Original Place After Formating Number

I have an input field which has a data manipulation and is a decimal field. Everything works fine except when I put in more than 3 numbers it will lose the current caret and set it

Solution 1:

The simplest thing to do is get rid of the valueUpdate setting so that the formatting happens after the user is done editing the number.

To have it work interactively, you need to add an input event handler that

  1. Finds how many digits are behind the cursor (this happens before reformatting)
  2. Does a setTimeout to allow the reformatting to happen
  3. Sets the cursor position after the same number of digits

Also note that your formatter gets weird for very long numbers. You might want to replace it with a call to toLocaleString with some additional substitutions.

functionthousenderSign(number) {
  number = '' + number;
  if (number.length > 3) {
    var mod = number.length % 3;
    var output = (mod > 0 ? (number.substring(0, mod)) : '');
    for (i = 0; i < Math.floor(number.length / 3); i++) {
      if ((mod == 0) && (i == 0)) {
        output += number.substring(mod + 3 * i, mod + 3 * i + 3);
      } else {
        output += "'" + number.substring(mod + 3 * i, mod + 3 * i + 3); // set the sign
      }
    }
    return (output);
  } elsereturn number;
}
ko.extenders.numeric = function(target, precision) {
  var result = ko.pureComputed({
    read: target,
    write: function(newValue) {
      var current = target();
      var roundingMultiplier = Math.pow(10, precision);
      var newValueAsNum = null;

      if (newValue !== undefined && newValue !== 0 && newValue !== null) {
        newValueAsNum = newValue.toString().replace("'", "");
        // provide only int fort he functionvar onlyInt = newValueAsNum.split(".");
        // Remove more then 2 digits after the dotif (onlyInt.length > 1 && onlyInt[1].length > 2) {
          onlyInt[1] = onlyInt[1].toString().substring(0, 2);
        }
      }

      var valueToWrite = (Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier) === 0 ? null : Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;

      // thousender signif (newValueAsNum !== null && newValueAsNum.length > 3) {
        valueToWrite = thousenderSign(onlyInt[0]) + "." + (onlyInt.length > 1 ? onlyInt[1] : '00');
      }
      if (valueToWrite !== current) {
        target(valueToWrite);
      } else {
        if (newValue !== current) {
          target.notifySubscribers(valueToWrite);
        }
      }
    }
  }).extend({
    notify: 'always'
  });
  result(target());
  return result;
};

functionExampleViewModel() {
  self = this;
  self.counterofferPremium = ko.observable().extend({
    numeric: 2
  });
  self.findPlace = function (data, event) {
    const pos = event.target.selectionEnd;
    var numbersBeforePos = event.target.value.substr(0, pos).replace(/\D/g, '').length;
    setTimeout(function() {
      const formattedValue = event.target.value;
      const numbersNow = event.target.value.replace(/\D/g, '').length;
      
      if (numbersNow >= numbersBeforePos) {
        // find the numbersBeforePos-th numberconst re = /\d/g;
        var newPos;
        while (numbersBeforePos--) {
          newPos = 1 + re.exec(formattedValue).index;
        }
        event.target.setSelectionRange(newPos, newPos);
      }
    }, 0);
  };
};

var viewModel = newExampleViewModel();
ko.applyBindings(viewModel);
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script><inputdata-bind="value: counterofferPremium, valueUpdate: 'afterkeydown', event: {input: findPlace}"type="text" />

Post a Comment for "Set Caret Back To It's Original Place After Formating Number"