중첩된 요소가 있고 두 요소 모두 클릭 이벤트를 캡처한다. 안쪽 요소에서 발생한 클릭 이벤트가 바깥쪽 요소로 전파되는 것을 막고 싶다.
전파되는 이벤트를 일반적인 방식으로 중단한다.
//이벤트 전파 중단
function cancelPropagation(event){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
안쪽 요소를 클릭할 때 실행되는 이벤트 핸들러에서 이 함수를 호출하고 이벤트 객체를 인수로 전달하면 된다.
cancelPropagation(event);
이벤트를 취소하고 싶지는 않지만 전파되는 것을 막고 싶다면 이벤트가 발생했을 때 이벤트 전파를 중단시켜야 한다.
크롬, 사파리, 파이어폭스는 stopPropagation
메서드를 지원하지만 IE8에서는 cancelBubble
속성을 true
로 설정해야 작동한다.
<!DOCTYPE html>
<html>
<head>
<title>이벤트 전파 방지</title>
<meta charset="utf-8">
<style>
#one
{
width: 100px; height: 100px; background-color: #0f0;
}
#two {
width: 50px; height: 50px; background-color: #f00;
}
#stop
{
display: block;
}
</style>
<script>
// 전파 취소 여부를 가리키는 전역변수
var stopPropagation = false;
// 재사용 가능한 이벤트 처리함수
function listenEvent(eventTarget, eventType, eventHandler) {
if (eventTarget.addEventListener) {
eventTarget.addEventListener(eventType, eventHandler,false);
} else if (eventTarget.attachEvent) {
eventType = "on" + eventType;
eventTarget.attachEvent(eventType, eventHandler);
} else {
eventTarget["on" + eventType] = eventHandler;
}
}
// 이벤트 전파 취소
function cancelPropagation (event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
// 이벤트 등록
listenEvent(window,"load",function() {
listenEvent(document.getElementById("one"),"click",clickBoxOne);
listenEvent(document.getElementById("two"),"click",clickBoxTwo);
listenEvent(document.getElementById("stop"),"click",stopProp);
});
function stopProp() {
stopPropagation = true;
}
function clickBoxOne(evt) {
alert("Hello from One");
}
function clickBoxTwo(evt) {
alert("Hi from Two");
if (stopPropagation) {
cancelPropagation(evt);
}
}
</script>
</head>
<body>
<div id="one">
<div id="two">
<p>Inner</p>
</div>
</div>
<button id="stop">Stop Propagation</button>
</body>
</html>
다음은 좀더 효율적인 클릭 이벤트 처리함수이며 예제에 있던 두 개의 함수를 하나로 합친 것이다.
function clickBox(evt) {
evt = evt || window.event;
alert("Hi from " + this.id);
if (stopPropagation) {
cancelPropagation(evt);
}
}
stopPropagation이 false
로 설정되면 두 요소 모두 이벤트를 받는다. 이벤트 처리함수는 접근한 요소의 아이디를 this
를 통해 알아내어 메시지를 작성한다.
하지만 IE8은 이 함수를 지원하지 않는다. attachEvent
는 DOM이 아니라 window
객체를 통해 이벤트를 처리하므로 요소 콘텍스트 this
를 사용할 수 없다. 이벤트를 받은 객체는 이벤트 객체의 srcElement
속성을 통해 접근할 수 있지만 이벤트를 처음 받은 요소로 설정될 뿐 전파된 요소로 업데이트 되지 않는다.
대신 DOM 레벨 0 이벤트 핸들링에서는 이러한 문제가 발생하지 않는다. 이때는 IE도 전파와는 무관하게 이벤트 처리 함수 안에서 요소 콘텍스트 this
에 접근할 수 있다. 두 개의 div
에 이벤트 핸들러를 직접 할당한다.
document.getElementById("one").onclick = clickBox;
document.getElementById("two").onclick = clickBox;