Как я могу сохранить ожидаемое положение курсора при автоматическом форматировании числа с помощью запятых?

#javascript

#javascript

Вопрос:

У меня есть ввод, в котором я хочу заменить значение числа в событии ввода. Использование Intl.NumberFormat().format(num); для достижения этой цели.

Все в порядке, и это отлично работает, пока вы не нажмете внутри уже отформатированного значения и не начнете добавлять больше чисел, курсор прыгает.

Я пытался решить это, установив курсор, но он по-прежнему ведет себя плохо.

Короче говоря, как я могу изменить этот фрагмент так, чтобы независимо от того, где вы редактируете значение, курсор оставался в ожидаемом положении?

 const input = document.getElementById("foo");
input.addEventListener("keyup", handleKeyUp);

function handleKeyUp(e) {
    const num = e.target.value.replace(/,/g, "");
  const formatted = new Intl.NumberFormat().format(num);
  
  var cursor = e.target.selectionStart;//   1;
  input.value = formatted;
  e.target.setSelectionRange(cursor, cursor);
}

// Try the following
// 1) 123456789
// 2) 123
// 3) place cursor between the 1 and 2 and add a number

// If I   cursor then #1 is resolved
// And #2 initially appears to be resolved unless I keep going with more numbers  
 <input id="foo" type="text">  

Ответ №1:

Не очень элегантное решение, но я переместил курсор в зависимости от того, была ли добавлена / удалена запятая из текстового поля (влево или вправо соответственно).

Смотрите фрагмент ниже:

 const input = document.getElementById("foo");
input.addEventListener("keyup", handleKeyUp);
let commas = 0;

function handleKeyUp(e) {
  const num = e.target.value.replace(/,/g, "");
  const formatted = new Intl.NumberFormat().format(num);
  // get total commas in number
  let totalCommas = (formatted.match(/,/g) || []).length;
  var cursor = e.target.selectionStart;
  
  if(commas > totalCommas) {
    //shift cursor to the left (a comma was removed)
    commas--;
    cursor--;
  } else if (commas < totalCommas){
    // shift cursor to the right (a comma was added)
    commas  ;
    cursor  ;
  }
  
  input.value = formatted;
  e.target.setSelectionRange(cursor, cursor);
}

// Try the following
// 1) 123456789
// 2) 123
// 3) place cursor between the 1 and 2 and add a number

// If I   cursor then #1 is resolved
// And #2 initially appears to be resolved unless I keep going with more numbers  
 <input id="foo" type="text">