민서네집

focus 이벤트가 어디서 오는지 구분하기(Keyboard or Mouse) 본문

WEB (HTML, CSS)

focus 이벤트가 어디서 오는지 구분하기(Keyboard or Mouse)

브라이언7 2014. 9. 19. 11:04

Differentiate between focus event triggered by keyboard/mouse


focus 이벤트가 Mouse의 Click에서부터 오는지 아니면 Keyboard에서 탭 키를 눌러서 발생한 것인지 구분할 필요가 생겼다.


왜냐하면 홈페이지를 만들때 메인 메뉴를 클릭했을 때 하위 메뉴가 펼쳐진 상태면 닫히고, 닫힌 상태면 펼쳐야 한다.


그런데 키보드에서 탭 키로 이동할 때도 똑같은 일을 해야 하고, 이런 경우 focus 이벤트 핸들러 함수에 이런 코드를 넣는다.


그런데 문제는 마우스로 클릭했을 때 focus 이벤트와 click 이벤트가 동시에 발생한다는 점이다.


Chrome 브라우저와 Safari 브라우저에서만 마우스로 클릭했을 때 focus 이벤트가 발생하지 않고, click 이벤트만 발생한다.


IE9와 FireFox 브라우저에는 마우스로 클릭했을 때 focus 이벤트가 먼저 발생하고 그 다음에 click 이벤트가 발생했다.

(물론 한번 focus가 옮겨진 상태에서 다시 클릭하면 focus 이벤트가 발생하지 않고 click 이벤트만 발생한다.)


그런데 서브 메뉴를 열고 닫기 위해 (Toggle 하기 위해) 동일한 코드를 focus 이벤트와 mouse 이벤트 핸들러에 넣어야 하니, IE9 와 FireFox 브라우저에서는 메뉴를 마우스로 클릭할 때 서브 메뉴가 열렸다 다시 닫혀서 펼쳐지지 않는다.


그래서 focus 이벤트가 발생했을 때 키보드의 탭 키로 이동한 경우만 하위 메뉴를 열거나 닫는 코드를 실행하고, 그 이외의 경우는 bypass 해야만 했다.


stackoverflow.com 을 찾아보니 'click' 이벤트나 'keypress' 이벤트에서 특정 변수를 셋팅하고, focus 이벤트 핸들러 함수에서 setTimeout()으로 100ms 후에 그 변수값을 검사하는 방식을 사용했다.


[참고] 

http://stackoverflow.com/questions/5653332/differentiate-between-focus-event-triggered-by-keyboard-mouse


var isClick;
$(document).bind('click', function() { isClick = true; })
           .bind('keypress', function() { isClick = false; })
           ;

var focusHandler = function () {
    if (isClick) {
        // clicky!
    } else {
        // tabby!
    }
}

$('input').focus(function() {
    // we set a small timeout to let the click / keypress event to trigger
    // and update our boolean
    setTimeout(focusHandler,100);
});

이렇게 해도 될 것 같다.


focus: function(event, ui){
  if(/^key/.test(event.originalEvent.originalEvent.type)){
    //code for keydown
  }else{
    //code for mouseenter and any other event
  }
}

위 방법은 문제가 좀 있다.


focus이벤트의 event 내부값을 검사할 때 FireFox 에서 마우스에서 focus 이벤트가 발생한 경우와 키보드에서 focus 이벤트가 발생한 경우가 event 내부값(event.originalEvent.explicitOriginalTarget)이 달라지는 것을 확인했지만, 이벤트 내부 구조는 브라우저마다 다르고, 또 그나마 값이 달라지는 경우도 FireFox 브라우저 밖에는 발견하지 못했다.


[참고] FireFox에서 Mouse로 Click 했을 때는 focus 이벤트의 event.originalEvent.explicitOriginalTarget 값이 다음과 같다. ( #text "{문자열}" )


jQuery에서 focus 이벤트의 발생 원인을 알 수 있는 메서드를 제공해 주면 좋겠지만...


Can we differentiate mouse and keyboard source in the focus event?

[참고] http://bugs.jqueryui.com/ticket/8307


Use event.originalEvent (you may need to walk multiple times).


이런 답변만 있고, 이 이슈는 closed 로 바뀌어 버렸다.


Mouse vs. Keyboard - Determining Click Initiator Using A jQuery Custom Event


http://www.bennadel.com/blog/2369-mouse-vs-keyboard-determining-click-initiator-using-a-jquery-custom-event.htm


☜ 링크를 엔터로 눌러서 실행시킨 경우와 마우스로 링크를 누른 경우를 분별할 수 있는 자바스크립트 코드이다.


Detecting keyboard focus



jQuery 1.11.1 버전과도 에러 없이 잘 실행된다.


나는 이 라이브러리를 이용했는데, 키보드 탭 키로 이동해서 focus 이벤트가 발생한 경우는,


keyboard-focus 클래스가 동적으로 생기고,


마우스로 Click 해서 focus 이벤트가 발생한 경우는, mouse-focus 클래스가 동적으로 생긴다.


(FireFox 개발자 도구에서 테스트 해 볼 수 있다.)


Chrome 브라우저와 Windows 용 Safari 브라우저에서는 Click 시 Focus 이벤트가 발생하지 않아서 개발자 도구에서 보면 mouse-focus 클래스가 생성되지 않는다.

Windows 용 Safari 브라우저에서는 이상하게도 키보드의 탭 키로 HTML을 이동할 수 없었다.


Comments