My task is to allow users to type arabic text in my input field, however they are unable to do so due to a function named isNumber()
in the code. Without the isNumber()
function, the users are able to type arabic text. I'm inspecting the code and I can't figure out why that function isn't allowing users to accepting arabic input.
I've reproduced this error in code sandbox
The next provided example code is the boiled down variant of the above linked sandbox code.
function validateLength(value, maxLength) {
if (value.length >= maxLength) {
return false;
}
return true;
}
function isNumber(evt, maxLength = 30/*1000000*/) {
// evt = evt || window.event;
const value = evt.target.value;
if (!/*this.*/validateLength(value, maxLength)) {
evt.preventDefault();
return false;
}
const charCode = evt.which ? evt.which : evt.keyCode;
if (
charCode > 31 &&
(charCode < 48 || charCode > 57) &&
charCode !== 46
) {
evt.preventDefault();
} else {
return true;
}
}
document
.querySelector('input')
.addEventListener('keypress', isNumber);
[type="text"] { display: block; width: 50%; }
<input type="text" value="01234٠١٢٣٤٥٦٧٨٩56789" />
CodePudding user response:
Your isNumber
function only permits typing in the text box if the key code is within the range of the Basic Latin number character codes. The key codes on an Arabic keyboard will correspond to the ASCII Arabic Codepage instead.
Note that a key code is a distinct concept from a Unicode character code, and that the key code approach is deprecated.
A key code is the decimal ASCII (RFC 20) or Windows 1252 code corresponding to the key. The operating system and/or browser may (will) map this value to a Unicode character, which will have a different identifying number.
You have two ways of fixing this:
- Continue using key codes and check for the ASCII Arabic codepage values if the user has configured their machine to work in Arabic (you need to do this check because other languages will use different codepages THAT MAP TO THE SAME NUMBERS), or
- Use a Unicode-first approach (see below).
Unicode-first approach:
In order to make this work for users who wish to use Arabic you will need to:
- Use
input
events orKeyboardEvent.key
, - Identify what Unicode codepoints correspond to the Arabic numbers (see below), and
- Permit entry of the Unicode codepoints corresponding to Arabic numbers. Checks can be performed using String#codePointAt or a regular expression with the
u
(Unicode) flag set.
Arabic codepoints are located in the 13th Unicode block (range U 0600
to U 06FF
). You can see the codepoints in this document.
0660 ٠ ARABIC-INDIC DIGIT ZERO
0661 ١ ARABIC-INDIC DIGIT ONE
0662 ٢ ARABIC-INDIC DIGIT TWO
0663 ٣ ARABIC-INDIC DIGIT THREE
0664 ٤ ARABIC-INDIC DIGIT FOUR
0665 ٥ ARABIC-INDIC DIGIT FIVE
0666 ٦ ARABIC-INDIC DIGIT SIX
0667 ٧ ARABIC-INDIC DIGIT SEVEN
0668 ٨ ARABIC-INDIC DIGIT EIGHT
0669 ٩ ARABIC-INDIC DIGIT NINE
CodePudding user response:
Another possible approach was to listen to any input
event (including pasted and deleted content) where a sanitizing method always assures a valid field value.
Such a task would remove any non digit characters from the current input value and also limit the latter to its maximum allowed length. It then would rewrite the sanitized value and reestablish a meaningful selection range of the input fields.
function assureValidNumberValue({ currentTarget }, maxlength = 20) {
const { value, selectionStart, selectionEnd } = currentTarget;
const sanitizedValue = value
.replace(/[^\p{N}]/gu, '')
.slice(0, maxlength);
const deltaLength = value.length - sanitizedValue.length;
currentTarget.value = sanitizedValue;
currentTarget.setSelectionRange(selectionEnd - deltaLength, selectionEnd - deltaLength);
}
document
.querySelector('input')
.addEventListener('input', assureValidNumberValue);
[type="text"] { display: block; width: 50%; }
<input type="text" value="01234٠١٢٣٤٥٦٧٨٩56789" />