##一.이벤트 객체 취득에 대하여##
FF 는 조금 고집스러워서 arguments[0] 만 지원하고 window.event 는 지원하지 않습니다. 이번엔 정말 IE 를 탓할 수 없습니다. event 를 window 의 속성으로 하는 것은 규격에 맞지 않지만, 모두가 이미 이 작은 문제를 묵인하고 있으며, FF 만이这么多年이 지나도 특이하게独行합니다. 따라서 크로스 브라우저 이벤트 객체 취득에는 다음과 같은 두 가지 방식이 있습니다:
-
매개변수 있는 방식:
getEvent : function(event){ return event ? event : window.event; //return event || window.event;//또는 더 간단한 방식 } -
매개변수 없는 방식:
function getEvent() { return arguments[0] ? arguments[0] : window.event; //return arguments[0] || window.event;//또는 더 간단한 방식 }
특별히 설명해야 할 방식이 하나 있습니다: HTML 의 DOM0 급 방식 + 매개변수 있는 이벤트 핸들러, 다음과 같습니다:
function handler(event){
//do something
}
<!-- HTML 의 DOM0 급 방식 -->
<button id="btn" onclick="handler(event);">버튼</button>
위의 방식은 전 브라우저 호환이지만, HTML 의 DOM0 급 방식에 의존하는 단점이 분명하므로 앞의 두 가지 같은 주류 방식이 되지 못했습니다. 반면 JS 의 DOM0 급 방식 + 매개변수 있는 이벤트 핸들러는 다음과 같습니다:
function handler(event){
//do something
}
btn.onclick = handler;//JS 의 DOM0 급 방식
//btn.onclick = function(event){/*do something*/}//또는 무명 함수, 효과는 위와 동일
이 방식은 전 브라우저 호환이 아닙니다, [IE8-] 는 지원하지 않으며, IE9+ 는 알 수 없고, FF, Chrome 은 지원합니다.ずっと HTML 의 DOM0 급 이벤트 처리와 JS 의 DOM0 급 이벤트 처리가 동등하다고 생각했지만, 많은 실험을 해본 후에야 둘 사이에 차이가 있다는 것을 알게 되었습니다
##二.이벤트 소스 취득에 대하여##
event.srcElement 는 [IE8-] 만의 방식이며, IE9+ 는 알 수 없고, 기타 브라우저는 모두 표준인 event.target 방식을 지원합니다
##三.이벤트 기본 동작 방지에 대하여##
event.preventDefault() 는 표준 메서드이지만, [IE8-] 는 지원하지 않으며, IE 자체의 방식은 event.returnValue = false; 입니다
##四.이벤트 전파 중지에 대하여##
event.stopPropagation() 는 표준 메서드이지만, IE 는 또 의견이 있어서 이렇게 합니다: event.cancelBubble = true;여기서 특히 주의해야 합니다, cancel 은 메서드가 아니라 속성이므로 표준과 많이 달라서 잘못 기억하기 쉽습니다
##五.이벤트 핸들러 추가 및 제거에 대하여##
- DOM0 급 방식
ele.onclick = handler;ele.onclick=null;가장 오래된 방식
장점: 전 브라우저 호환
단점: 동일 이벤트에 하나의 이벤트 핸들러만 바인드/언바인드 가능
- DOM2 급 방식
ele.add/removeEventListener(eventType, handler, catch);
와 IE 방식: ele.attach/detachEvent('on'+eventType, handler);
장점: 여러 이벤트 핸들러의 바인드/언바인드 지원
단점: 호환성 판단이 필요합니다. 주의할 점은: 표준 방식에서 마지막 매개변수는 이벤트 캡처 단계에서 바인드/언바인드할지 여부를 나타내며, IE 는 이벤트 캡처를 지원하지 않으므로 세 번째 매개변수도 없습니다
주의: IE 방식은 메서드 이름이 표준과 다를 뿐만 아니라, 매개변수 중 이벤트 타입에 on 을 추가해야 합니다, 그렇지 않으면 바인드는 무효이지만 에러는 발생하지 않습니다
##六.크로스 브라우저 이벤트 처리##
//크로스 브라우저 이벤트 핸들러 추가 방식
var EventUtil = {
addHandler : function(elem, type, handler){
if(elem.addEventListener){
elem.addEventListener(type, handler, false);
}
else if(elem.attachEvent){
elem.attachEvent("on" + type, handler);//여러 개의 동일 타입 handler 를 추가할 때, IE 방식의 규칙은 나중에 추가한 것이 먼저 트리거됨
}
else{
if(typeof elem["on" + type] === 'function'){
var oldHandler = elem["on" + type];
elem["on" + type] = function(){
oldHandler();
handler();
}
}
else{
elem["on" + type] = handler;//여러 이벤트 핸들러 추가 지원
}
}
},
getEvent : function(event){
return event ? event : window.event;
},
getTarget : function(event){
return event.target || event.srcElement;
},
preventDefault : function(event){
if(event.preventDefault){
event.preventDefault();
}
else{
event.returnValue = false;
}
},
removeHandler : function(elem, type, handler){
if(elem.removeEventListener){
elem.removeEventListener(type, handler, false);
}
else if(elem.detachEvent){
elem.detachEvent("on" + type, handler);
}
else{
elem["on" + type] = null;//단일 이벤트 핸들러 제거를 지원하지 않으며, 모두 제거만 가능
}
},
stopPropagation : function(event){
if(event.stopPropagation){
event.stopPropagation();
}
else{
event.cancelBubble = true;
}
},
getRelatedTarget : function(event){
if(event.relatedTarget){
return event.relatedTarget;
}
else if(event.toElement && event.type == "mouseout"){
return event.toElement;
}
else if(event.fromElement && event.type == "mouseover"){
return event.fromElement;
}
else{
return null;
}
},
/*IE8 은 왼쪽 버튼과 중간 버튼 클릭 시 모두 0; FF 는 중간 버튼 인식 불가; Chrome 은 정상*/
getButton : function(event){//0,1,2 반환 - 왼쪽, 중간, 오른쪽
if(document.implementation.hasFeature("MouseEvents", "2.0")){
return event.button;
}
else{
switch(event.button){
case 0:case 1:case 3:case 5:case 7:
return 0;
break;
case 2:case 6:
return 2;
break;
case 4:
return 1;
break;
default:
break;
}
}
},
/*keypress 이벤트만 검출 가능, 반환값은 표시될 문자 코드와 동일*/
/*IE 와 Chrome 은 표시 가능한 문자 키만 트리거, FF 는 기타 키도 트리거 가능, 반환값은 0*/
getCharCode : function(event){
if(typeof event.charCode == "number"){
return event.charCode;
}
else{
return event.keyCode;
}
}
};
위의 코드는《JavaScript 高級程序设计》중문판에서 정리한 것으로, 책의 getRelatedTarget 에 약간의 문제가 있습니다 (P373), 본문에서 이미 수정했습니다
책의 addHandler 는 DOM0 급 방식으로 여러 이벤트 핸들러를 추가하는 것을 지원하지 않으며, 수정 후에는 지원 가능하지만 단일 이벤트 핸들러 제거를 지원하지 않으므로 코드는 여전히 불완전합니다. DOM0 급 이벤트 핸들러의 추가/제거 작업을 지원하려면 수동으로 이벤트 핸들러 큐를 유지할 수 있지만, 이 방식을 구현하는 데 큰 의미가 없으므로 여기서는 전개하지 않습니다
###참고 자료###
아직 댓글이 없습니다