IE8 에서 propertychange 이벤트의 발생 순서 주의

발생일: 2014.11.21

키워드: propertychange event, input event, IE8

문제:
얼마 전엔, 자동완성처럼 textarea 영역이 변경되는 걸 감지하고 있다가,
해당 영역의 스타일을 업데이트해주는 코드를 작성했었는데, 역시 IE 때문에 꽤 고생을 했다.

자동완성을 위해 input 이나 textarea 의 변경을 감지하는 것에는 여러 방식이 있다.
구현할 때 주로 문제가 되는 건, 한글을 입력 중이라 자소가 완성되지 않은 상태를 처리하는 것이다.

예를 들어, ‘아이폰’을 입력할 때,
‘아ㅇ’, ‘앙’, ‘아잎’, ‘아이ㅍ’처럼 자소를 입력 중인 상태에서도 결과가 올바르게 나오도록 해야한다.

최근 브라우저에서는 `input` 이벤트를 사용하면 거의 문제가 없다.

  $(’input’).on(‘input’, function () {
    var value = $(e.currentTarget).val();
    // value는 자소를 입력 중일 때에도, 자소를 포함해 정확한 값을 리턴한다.
  });

(참고로, input 이벤트는 keydown 이벤트 이후에 발생하기 때문에,
키 컨트롤이 필요하다면 keydown 이벤트를 추가로 정의해야 한다.)


하지만, IE8 이하 버전은 input 이벤트를 제공하지 않는다.
예전에는 textarea에 focus 될 때, 텍스트 영역을 감지하는 타이머를 돌렸다가 blur 가 되면 종료하는 식으로 구현했었다.

헌데, 요번에는 동료 A가 작성한 코드를 참고해서 작성했는데,
익스플로러의 propertychange 이벤트를 사용하고 있다.

아래 같은 코드이다.

  $(‘input’).on(‘propertychange’, function (e) {
    if (e.originalEvent.propertyName === ‘value’) {
      var value = $(e.currentTarget.).val();
      // ...
    }
  });


잘 동작하는 것처럼 보였다.
그런데, 특정 상황에서 value 에 자소가 포함되지 않는 경우가 있다.
왜일까…?


해결책:

일단 propertychange 이벤트는 input 이벤트의 동작 방식과 거의 동일하고,
대부분의 상황에 의도한 대로 동작한다.

이번에 문제가 됐던 건, 자소 입력 중에 엔터를 입력하는 경우였다.

문제가 됐던 시나리오는,
  1. 텍스트를 입력하면 해당하는 항목을 포함해 드롭다운 리스트가 나오고,
  2. 엔터를 입력하면 첫 번째 아이템이 선택되고 레이어가 닫히는
거였다.

모던 브라우저에서는 input 이벤트로, IE8에서는 위에서처럼 propertychange 로 할당해주고,
keydown 이벤트에서는 엔터의 기본 입력을 막아뒀다.

헌데, 간헐적으로 자소 입력 중에 엔터를 입력하면 레이어가 닫혔다 다시 열리는 문제가 발생했다.
꽤 고생스럽게 원인을 찾아냈는데, 원인은 propertychange 이벤트가 발생하는 순서에 있었다.


일반적으로 키 이벤트는 아래 순서로 발생한다.

    keydown
    keypress
    input (propertychange)
    keyup


헌데, IE8에서는 특정 상황에서 아래처럼 keydown 보다 propertychange 가 먼저 발생한 거다. -_-

    propertychange
    keydown
    propertychange


그래서 keydown 이벤트에서 엔터키의 입력이 중지되기 전에 자소가 완성되어 버렸고, (A)
그 다음 keydown 이벤트가 발생, (A)에 의해 다시 propertychange가 발생한 것이다.


음… 현상은 발견했지만, 정확한 원인은 모르겠다.

일단은, 값을 설정하는 부분은 딜레이하는 식으로 처리했다. -_-;;;;


  $(‘input’).on(‘propertychange’, function (e) {
    if (e.originalEvent.propertyName === ‘value’) {
      setTimeout(function () {
        var value = $(‘input').val();
      }, 0);
    }
  }); 



카테고리

분류 전체보기 (711)
About me. (6)
Daylogs (676)
영어공부 (0)
My works - 추억 (29)
비공개 (0)