JAVAIARY

일본어 입력기(IME) + AutoNumeric.js 숫자 입력 중복 문제 본문

lectureNote/JAVASCRIPT

일본어 입력기(IME) + AutoNumeric.js 숫자 입력 중복 문제

shiherlis 2023. 9. 12. 16:46

< input type=number />에서는 maxlength를 지원하지 않고, min/max만 사용할 수 있다.
그런데 그렇게 사용할 경우, 입력과 동시에 유효성 체크가 되지 않는다. 
범위를 넘어가는 숫자가 입력되어도 제출이 되지 않을 뿐 입력 자체는 가능하며 입력한 숫자들이 화면상에 보여지게 된다.
ex. (0~99)

그래서 기존에 type=text 로 두고 AutoNumeric.js를 사용해서 숫자 텍스트 필드의 포맷팅을 시켜주었다.
AutoNumeric 문서: https://www.decorplanit.com/plugin/

 

autoNumeric

autoNumeric 1.9.41 is a jQuery plugin that automatically formats currency and numbers as you type on form inputs. It supports most International numeric formats and currency signs including those used in Europe, North and South America, Asia and India lakh

www.decorplanit.com

그런데 일본어 입력기를 사용하면서부터 문제가 생겼다.

한글은 자음과 모음을 합하면 글자가 되지만, 일본어는 자음과 모음이 나누어지지 않은 문자이다.
따라서 타이핑을 할 때에는 로마자로 음을 만든 다음 그 음을 일본어(가나 혹은 한자)로 치환한다.

k + a => ka => か 

이 과정을 컴포지션이라고 한다.
입력이 시작(compositionstart)되면 원하는 문자열을 선택할 수 있는 창이 뜨고,
컴포지션이 완료(compositionend)되면 확정된 문자열이 삽입된다. 
문자 뿐만 아니라 숫자 입력시에도 반각으로 사용할 것인지 전각으로 사용할 것인지 확정을 해 주어야 한다. 

문자/숫자의 composition

이 부분에서 AutoNumeric과 IME에서 중복 삽입이 발생한다. 
AutoNumeric에서는 입력즉시 포맷팅을 시도하고, IME에서는 compositionend 시에 

그래서 생각해 낸 방법이

  1. 숫자 입력시에만 IME 구성(compostion) 제한
  2. 숫자 입력시에만 IME 모드를 바꾼다
  3. IME 모드가 JPN일 때만 숫자입력시 js로 처리
  4. oninput 마다 강제 클릭 (클릭 시 컴포지션 중지됨)

1~3 번은 OS에서 실행되는 IME 입력기를 브라우저에서 제어할 수 없기 때문에 탈락
4번은 물리적 입력을 브라우저에서 제어할 수 없어서 탈락

그래서 다른 방법을 찾아보는데 composition 관련 이벤트가 있었다.

https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event

 

Element: compositionstart event - Web APIs | MDN

The compositionstart event is fired when a text composition system such as an input method editor starts a new composition session.

developer.mozilla.org

 

  • compositionstart
  • compositionupdate
  • compositionend

IME composition을 사용할 때 발동하며 세 단계로 나누어져 있다.
쉽게말해 입력시작, 입력 중, 입력완료.

composition 자체를 하지 못하도록 막을 수는 없으니....
autoNumeric의 포맷팅을 잠시 중지시키도록 했다.

<input id='id' type='text' maxlength='5'/>
//composition start
$('#id')[0].addEventListener('compositionstart', (e) => {					
            $('#id').autoNumeric('destroy');
});

//composition end
$('#id')[0].addEventListener('compositionend', (e) => {						
            $('#id').val().replace(/\D/g, '');		      
            $('#id').autoNumeric('init',{
            	vMin: 'min', vMax: 'max', aSep: ',', mRound: 'D', nBracket:null
                });                                                   
});

이렇게 하면 maxLength 만큼만 들어가게 할 수 있었다. 
다른 이슈가 있는 게 아니라면 이정도로 마무리 지을 수 있었다.

그런데 jquery의 validate.js도 쓰면서 문제가 생겼다. 
validate 에서 maxlength가 있을 때 최대길이를 체크하고 메세지를 반환해 준다.

그런데 어떤 스크립트와 충돌이 난 것인지는 모르겠지만 지정해 준 maxlength의 -2 만큼만 입력이 가능했다. 

$('#id').val($('#id').val().slice(0,"+ maxLength +"));

그래서 replace 후, 후처리로 maxlength를 넘어가는 문자열을 잘라주기로 했다.

그렇게 완성된 compositionend 이벤트 부분

//composition end
$('#id')[0].addEventListener('compositionend', (e) => {						
            $('#id').val().replace(/\D/g, '');		
            $('#id').val($('#id').val().slice(0,"+ maxLength +"));
            $('#id').autoNumeric('init',{
            	vMin: 'min', vMax: 'max', aSep: ',', mRound: 'D', nBracket:null
                });                                                   
});

사실 이렇게 한다고 해서 한/영을 입력할 때와 완벽히 똑같은 작동을 하지는 않는다.
숫자 제외한 입력이 불가해야 하는데, 문자도 함께 삽입된 후 최대 길이만큼 자른 뒤 문자만 replace된다던가...
더 좋은 방법이 있으면 좋겠는데 IME 컨트롤이 되지 않아서 마땅한 대안은 떠오르지 않았다 😣

'lectureNote > JAVASCRIPT' 카테고리의 다른 글

js 변수  (0) 2022.10.06
창 만들기  (0) 2022.10.06