Search code examples
javascriptjquery

How can I fix cursor typewriter Jump to end Issue during convert number in JavaScript?


Following the questions What's the solution and the right way to convert digits in JavaScript? and How to convert numbers in JavaScript, and problems with commands to remove non-numeric characters on a keyboard with Tel input, I want to express one of the other problems.

There are not any differences in which method for converting numbers. However, in all methods, I have a little problem with this.

My problem is the keyboard typewriter pointer jumps to the end if I select a number in the middle of numbers with the mouse or touch (on mobile) and change one or more numbers. Please see this image pasted in below for clarification. I also added a JSFiddle link.

Enter image description here

https://jsfiddle.net/paulvek/4js965fr/7/

const phoneNumberInput = document.getElementById('phoneNumberInput');
phoneNumberInput.addEventListener('input', (event) => {
  const phoneNumberValue = event.target.value;
  const englishPhoneNumberValue = toEnglishDigits(phoneNumberValue);
  const numericPhoneValue = englishPhoneNumberValue.replace(/[^\d۰-۹٠-٩]/g, ''); // Added line
  event.target.value = numericPhoneValue;
});

function toEnglishDigits(str) {
  const persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"];
  const arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"];
  const englishNumbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];

  return str.split("").map(c => englishNumbers[persianNumbers.indexOf(c)] ||
    englishNumbers[arabicNumbers.indexOf(c)] || c).join("")
}
<input type="tel" id="phoneNumberInput" />

If the user selects one of the middle digits with the English keyboard and changes it, it will change there and the blinking type indicator of the same type pointer will stay there.

But if he/she selects and changes one of the middle digits with the Persian or Arabic keyboard, the change is done correctly. But the problem is that the text cursor jumps to the end.

This problem occurs only when typing or pasting Farsi and Arabic. What could be the problem?

Only when he/she wants to choose two or three numbers from among the numbers and change them. By writing the first number, it jumps to the end, and then the second digit, which should have been written next to the first digit in the same place he/she had chosen, goes to the end, and this messes up everything. If you test, you will see that there isn't any such problem with English.


Solution

  • I resolved this problem by following on comments and suggested solutions.

    Now here is well-working code. It was tested and worked.

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Phone Number Input</title>
    </head>
    <body>
    
    <input type="tel" id="phoneNumberInput" />
    
    <script>
    const phoneNumberInput = document.getElementById('phoneNumberInput');
    let cursorStart = 0; // Variable to store the start position of the selection
    let cursorEnd = 0;   // Variable to store the end position of the selection
    
    phoneNumberInput.addEventListener('input', (event) => {
      const phoneNumberValue = event.target.value;
    
      // Get the current cursor position
      cursorStart = phoneNumberInput.selectionStart;
      cursorEnd = phoneNumberInput.selectionEnd;
    
      const englishPhoneNumberValue = toEnglishDigits(phoneNumberValue);
      const numericPhoneValue = englishPhoneNumberValue.replace(/[^\d۰-۹٠-٩]/g, '');
    
      // Update the value
      event.target.value = numericPhoneValue;
    
      // Set the cursor position back to the original position
      phoneNumberInput.setSelectionRange(cursorStart, cursorEnd);
    });
    
    function toEnglishDigits(str) {
      // Your toEnglishDigits function remains unchanged
      const persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"];
      const arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"];
      const englishNumbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
    
      return str.split("").map(c => englishNumbers[persianNumbers.indexOf(c)] ||
        englishNumbers[arabicNumbers.indexOf(c)] || c).join("");
    }
    </script>
    
    </body>
    </html>