Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting japanese fullwidth characters typed by user to halfwidth character in the same input field

There's an input field, when the user will type any fullwidth Japanese character (numbers only) it won't be displayed on that input field. It'll be converted to its respective halfwidth character and, then that halfwidth character will be visible inside that same input field. If user type , this will not be shown in the input field, it'll show the converted halfwidth 0. In my case the problem is if the user types , the function is running twice and showing 00, but it should be only 0. Can anybody please help me to sort it out?

<input type="text" id="inputField" oninput="convertToHalfWidth(this.value)">
<script>
    function convertToHalfWidth(input) {
        console.log(input);
        // Map of full-width to half-width numbers
        const fullToHalfMap = {
            '0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9'
        };

        // Replacing full-width numbers with their half-width counterparts
        const convertedInput = input.replace(/[0-9]/g, match => fullToHalfMap[match]);

        // Updating the input field with the converted value
        document.getElementById('inputField').value = convertedInput;
    }
</script> 
like image 412
anik ahmed Avatar asked Dec 29 '25 09:12

anik ahmed


1 Answers

As per spec:

The start of a composition is marked by dispatching a compositionstart event. During a composition session, whenever a text composition system updates its active text passage, a compositionupdate event is dispatched. After each compositionupdate event, a pair of beforeinput and input events are dispatched.

The problem is an input event with type insertCompositionText is fired whenever an a composition session is updated. Even for simple full width characters like numbers and space that doesn't require multiple symbols composed using an IME window, there will still be two input event fired by compositionupdate. (Reproduced on Chinese IME and Japanese full-width Katakana IME.)

Note that this problem won't be reproduced by pasting the full characters because there won't be any composition session started. Only an input event with type insertText will be started.

One solution is to use an additional compositionend event to handle composition input types. (Or a simple onkeyup is enough if you are okay with the delay between keydown and keyup.)

const inputField = document.getElementById('inputField');
const fullToHalfMap = {
    '0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9'
};

inputField.addEventListener('input', function (e) {
    // Might be enough to only check insertFromPaste inputType
    if (e.inputType !== 'insertCompositionText') {
        convertToHalfWidth(e);
    }
})

inputField.addEventListener('compositionend', convertToHalfWidth);

function convertToHalfWidth(e) {
    const input = e.target.value;
    // Replacing full-width numbers with their half-width counterparts
    const convertedInput = input.replace(/[0-9]/g, match => fullToHalfMap[match]);
    // Updating the input field with the converted value
    inputField.value = convertedInput;
}
<input type="text" id="inputField">
like image 78
SyndRain Avatar answered Jan 01 '26 01:01

SyndRain



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!