2010-07-06 6 views
2

사용자가 요소 위에 마우스를 놓고 이벤트를 제거하면 처음부터 뭔가 할 수있는 코드가 있습니다.IE에서 이벤트 처리

W3C 이벤트 모델 브라우저에서는 훌륭하게 재생되지만 IE6-8에서는 오류가 계속 발생합니다. 다른 질문에서 코드를 얻었고 IE를 처리 할 것이라고 믿었습니다. 누구든지 내가 뭘 잘못하고 있는지 알아?

<script type="text/javascript"> 
    function setMouseEvent() { 
     //Tel: 01 8279 400 
     event = addEvent(document.getElementById('contactButton'), 'mouseover', changeText); 
    } 

    function changeText() { 
     alert("worked!"); 
     removeEvent(document.getElementById('contactButton'), 'mouseover', changeText); 
    } 

    function addEvent(obj, type, fn) { 
     if (typeof obj.addEventListener != undefined) { 
      obj.addEventListener(type, fn, false); 
     } 
     else if (typeof obj.attachEvent != undefined) { 
      obj.attachEvent("on" + type, fn); 
     } 
    } 

    function removeEvent(obj, type, fn) { 
     if (typeof obj.addEventListener != undefined) { 
      obj.removeEventListener(type, fn, false); 
     } 
     else if (typeof obj.attachEvent != undefined) { 
      obj.detachEvent("on" + type, obj[type + fn]); 
      obj[type + fn] = null; 
      obj["e" + type + fn] = null; 
     } 
    } 

    window.onload = setMouseEvent; 
</script> 

업데이트 : 난 그냥 문제없이 크롬, 오페라와 FF 최신 테스트하지만 언급 한 바와 같이 내가 마우스 이상 및 IE는 온로드 오류를 던지고 때 사파리는 아무것도하지 않습니다.

+1

윽. 'removeEvent'는 어디서 얻었습니까? John Resig의 구현 (http://ejohn.org/blog/flexible-javascript-events/)과 유사하지만'addEvent'와 대칭이 아닙니다. –

+0

어쩌면 나는 단순한 사람일지도 모르지만 이것이 내 페이지라면 간단한 호출 플래그를 가진 원샷 이벤트 처리기를 다루겠다. 첫 번째 호출 이후에 나는 뒤집을 것이다. 만약 내가 정말로 * 많은 이벤트를 논쟁하고 싶다면, 잘 테스트 된 프레임 워크가 추한 세부 사항을 다루도록 할 것입니다. – Pointy

+0

jQuery를 다시 잡는 것에 가까웠지만 이번에는 조금 파고 싶었습니다. 항상 배우고 싶다. –

답변

5
event = addEvent(

addEvent 아무것도 반환하지 않습니다 리턴 값이없는 undefined을 글로벌 변수 event에 할당합니다 (함수에 var event라고 말하지 않았으므로). 이로 인해 IE에서 전역 문자 event을 특수 객체로 사용하여 이벤트 세부 정보를 처리기로 전달하는 예외가 발생하므로 결과를 다른 항목에 할당 할 수 없습니다.

if (typeof obj.addEventListener != undefined) 

typeof는 항상 IE는 항상 비 IE 포크를 가지고 실패 있도록 undefined unvalue 동일한 테스트하지 않습니다 문자열을 반환합니다. 문자열이 의미하는 것은 if (typeof obj.addEventListener !== 'undefined')입니다. 당신이 typeaddEvent 기능이 서로 붙어 fn의 이름으로 속성을 작성하지 했으므로

obj.detachEvent("on" + type, obj[type + fn]); 

이 아무것도 검색되지 않습니다.

Crescent에 따르면 Resig의 removeEvent 함수를 사용하는 것과 같지 않은 다른 addEvent과 쌍을 이루는 것처럼 보입니다. 그의 removeEvent을 사용하는 경우에는 addEvent을 사용해야합니다.

그러나 어쨌든 나는이 기능을 사용하지 않을 것입니다. 꽤 위험합니다. 이 아픈 생각이 드는 코드가 "버블"모드의 addEvent 컨테스트에서 우승 한 것은 2005 년이라는 것을 알고 있습니다. 그렇더라도 우리는 더 잘 알았어야합니다. 문제는 이벤트 이름과 함수 코드 (type+fn)의 텍스트 직렬화에서 문자열을 생성하고 콜백을 저장하기위한 키로 사용한다는 것입니다. 이 키는 'mouseoverfunction changeText() {...code...}'과 같습니다.

그러나 기능 직렬화에 의존하는 것은 끔찍한 생각입니다. 형식이 ECMAScript에 의해 표준화되지 않았습니다 ("구현에 따라 달라지는 함수 표현이 반환됩니다."); many browser quirks;

var f1= function() {}; 
var f2= function() {}; 

f1f2이 같은 문자열 직렬화를해야합니다,하지만 그들은 같은 객체 아니에요 :이 아닌 이상, 두 개의 서로 다른 기능을 쉽게 브라우저 '현재의 직렬화의 방법에 대해 동일한 문자열을 반환 할 수 있습니다. IE에서 에 대해 addEvent을 수행 한 다음 f2에 대해 다른 하나를 수행 한 경우 두 번째 속성은 동일한 직렬화 된 문자열을 사용하고 첫 번째 속성을 덮어 씁니다.그런 다음 f1에 대해 removeEvent을 호출하면 f2에 대한 함수가 검색되고 detachEvent으로 시도하면 동일한 함수가 아니므로 실패합니다. 이 예제는 인위적으로 보일지 모르지만 요즘의 자바 스크립트가 점점 더 많이 요즘처럼 일반 클로저를 사용할 때 우연히하는 것은 실제로 매우 쉽습니다. 이러한 이유로 나는 모든 상황에서 Resig의 addEvent을 회피하여 을 추천 할 것입니다..

는 (jQuery를 사용자 :. jQuery를이 코드를 사용하는 함정에 빠지지 않는 모든 문제를 걱정하지 마십시오)

을이 해킹이 this 가치를 보존하기 위해이 당신의 changeText 함수가 다시 호출 될 때 IE에서 attachEventthis으로 설정되지 않습니다. 그러나 값을 사용하지 않으므로 더 단순한 버전 (예 : original addEvent)을 대체 할 수 있습니다.

적어도 addEvent는 잘 알려진하고 this를 사용하여 IE에서 테스트하는 경우에만 당신에 영향을주는 경우, 매우 될 가능성이 특정 경우에 잘못가는 대신에 즉시 표시하는 것이 의 단점 혼란스럽고 디버깅하기가 어렵습니다. 쉽게 떨어져 구식 DOM 레벨 0 이벤트 핸들러 얻을 수 있도록

가 다시, 현재, 같은 이벤트도 여러 리스너를 사용하지 않는, 같은 :

window.onload= function() { 
    var changed= false; 
    document.getElementById('contactButton').onmouseover= function() { 
     if (!changed) { 
      alert('changing text'); 
     } 
     changed= true; 
    }; 
}; 
+0

나는 이것이 Resig의'addEvent' 항목의 빠르기를 다루는 첫 번째 대답이라고 생각합니다. 이 답변에 대한 간단한 의견 교환이있었습니다 : http://stackoverflow.com/questions/1466875/ies-understanding-of-this/1471006#1471006 kangax가 기능 디 컴파일/직렬화에 의존하지 못하는 것에 대해 저를 계몽 시켰습니다. 함수 객체를 식별합니다. 잘 써라. + + + + + + + + –

+0

+1 초. – galambalazs

1

이동 Dean's addEvent를 들어, 당신이 유연한 솔루션을 원하는 경우 :

// written by Dean Edwards, 2005 
// with input from Tino Zijdel, Matthias Miller, Diego Perini 
// http://dean.edwards.name/weblog/2005/10/add-event/ 

function addEvent(element, type, handler) { 
    if (element.addEventListener) { 
     element.addEventListener(type, handler, false); 
    } else { 
     // assign each event handler a unique ID 
     if (!handler.$$guid) handler.$$guid = addEvent.guid++; 
     // create a hash table of event types for the element 
     if (!element.events) element.events = {}; 
     // create a hash table of event handlers for each element/event pair 
     var handlers = element.events[type]; 
     if (!handlers) { 
      handlers = element.events[type] = {}; 
      // store the existing event handler (if there is one) 
      if (element["on" + type]) { 
       handlers[0] = element["on" + type]; 
      } 
     } 
     // store the event handler in the hash table 
     handlers[handler.$$guid] = handler; 
     // assign a global event handler to do all the work 
     element["on" + type] = handleEvent; 
    } 
}; 
// a counter used to create unique IDs 
addEvent.guid = 1; 

function removeEvent(element, type, handler) { 
    if (element.removeEventListener) { 
     element.removeEventListener(type, handler, false); 
    } else { 
     // delete the event handler from the hash table 
     if (element.events && element.events[type]) { 
      delete element.events[type][handler.$$guid]; 
     } 
    } 
}; 

function handleEvent(event) { 
    var returnValue = true; 
    // grab the event object (IE uses a global event object) 
    event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); 
    // get a reference to the hash table of event handlers 
    var handlers = this.events[event.type]; 
    // execute each event handler 
    for (var i in handlers) { 
     this.$$handleEvent = handlers[i]; 
     if (this.$$handleEvent(event) === false) { 
      returnValue = false; 
     } 
    } 
    return returnValue; 
}; 

function fixEvent(event) { 
    // add W3C standard event methods 
    event.preventDefault = fixEvent.preventDefault; 
    event.stopPropagation = fixEvent.stopPropagation; 
    return event; 
}; 
fixEvent.preventDefault = function() { 
    this.returnValue = false; 
}; 
fixEvent.stopPropagation = function() { 
    this.cancelBubble = true; 
};