이러쿵저러쿵


A 태그의 중첩된 클릭 이벤트 문제 해결하기! (그리고 JQuery on()과 off() 함수(메서드) 사용해보기)

 

제목만 읽어서는 무슨 말인가 하실 수도 있을 것 같습니다.^^

 

일반적으로 크롬을 기반으로 개발 후, IE와 사파리 그리고 파폭 순으로 테스트를 하는 개발자입니다.

[IE브라우저] a 태그의 중첩된 onclick 문제 해결하기

모든 브라우저가 동일한 표준을 사용하고, 표준 코드에 대해서 동일하게 동작한다면 얼마나 좋겠지만, 현실은 그렇지 않지요.. (윈도우8의 Edge 브라우저는 표준을 잘 따른다고 선전은 하고 있는데, 아직 어떤지는 잘 모르겠습니다. (일단 아직까지는 큰 이슈는 없는 것 같군요.)

 

일단 본론으로 들어가면

 

종종 a 태그에 href 대신 onclick (물론 a태그가 아닌 태그으 경우에도) 이벤트를 주어서 사용하는 경우가 있습니다. onclick을 쓸 수 밖에 없는 경우도 발생하지요.

 

<span class="obj01 clsTest">

<a href="javascript:;">

<span class="btnClick">선택</span>

</a>

</span>

 

간단한 HTML 코드인데요. span 태그 내에 a 태그가 있습니다.

 

이 a 태그에는 아무런 이벤트도 걸려있지 않은데요. 만약 이 a 태그에 클릭 이벤트를 동적으로 재정의 해주어야 한다고 가정합니다.

코드는 다음과 같습니다.

 

// 이 함수(메서드)가 호출되면 위의 span 태그 내의 a 태그 onclick 이벤트를 정의합니다.

changeSomethingFunc : function(number) {    

 

// a 태그가 클릭되면 호출될 함수를 정의합니다.

$(".obj01").find("a").click(function() {

// Do Something

// 여기서는 입력된 number 값에 따라서 다른 동작이 정의됩니다.

doSomething(number); // 무언가 하는 함수

 

// 성공적으로 수행되었는지는 모르겠지만, 알림창을 띄웁니다. ㅎㅎㅎ

alert("Event " + number + " is done successfully");

 

});

 

}

 

위의 함수가 호출 될 때마다 a 태그의 onclick 이벤트는 재정의 됩니다.

 

a 태그에서 클릭 이벤트가 발생하면 가장 마지막에 정의 된 함수가 실행될 것입니다. (아주 일반적으로 생각한다면 말이지요.)

 

changeSomethingFunc(1);

changeSomethingFunc(2);

changeSomethingFunc(3);

 

위와 같은 순서로 changeSomethingFunc() 함수가 모두 호출되고 난 다음에 누군가가 a 태그에서 click 이벤트를 발생시키면 아래와 같이 정의된 함수가 실행될 것입니다. (아마도요? ㅎㅎㅎ)

 

function() {

doSomething(3);

alert("Event 3 is done successfully");

}

 

물론 크롬 브라우저에는 우리가 예상한대로 동작합니다.

즉, 위와 같이 정의된 함수가 한 번 실행됩니다.

 

그런데!

인터넷익스플로러(IE) 계열의 브라우저에서는 다르게 동작합니다. (IE 11까지도 말입니다.)

어떻게 다르게 동작할런지 눈치 채셨나요?

 

changeSomethingFunc(1);

changeSomethingFunc(2);

changeSomethingFunc(3);

이렇게 3개의 함수가 호출 되고 나면 IE 계열의 브라우저는 a 태그의 onclick 이벤트를 배열(Array) 형태로 쌓아두고, 이를 순차적으로 호출 시킵니다.

 

즉 누군가가 이 때 a 태그의 onclick 이벤트를 발생시키면 무려 아래의 3개의 함수가 호출되어 실행됩니다.

 

function() {
    doSomething(1);
    alert("Event 1 is done successfully");
}


 

function() {
    doSomething(2);
    alert("Event 2 is done successfully");
}


 

function() {
    doSomething(3);
    alert("Event 3 is done successfully");
}

 

누가 a 태그의 click 이벤트가 누적되어 순차적으로 실행될 것이라고 예상할까요?

어찌보면 IE브라우저의 동작 형태가 잘못된 것만은 아니고, 곧이곧대로 실행된 것이라 생각될 수도 있지만, 또 다르게 생각하면 융통성 없게 실행하는 것 같기도 합니다.

 

크롬 브라우저는 새로 이벤트가 정의 되면 (당연한 것이겠지만) 기존의 이벤트를 삭제하고, 새 이벤트를 등록합니다.

하지만 IE 브라우저는 새로 이벤트가 정의 되면 기존의 이벤트를 유지하고, 새 이벤트를 등록합니다. (즉 눈에도 보이지 않는 이벤트가 존재하게 됩니다.)

 

그렇다면 모든 브라우저에서 우리가 원하는 대로 잘 동작하게 하려면 어떻게 하면 될까요?

 

간단히 함수를 정의하기 전에 해당 이벤트를 제거하는 함수를 호출해 주기만 하면 됩니다.

 

// 이 함수가 호출되면 위의 span 태그 내의 a 태그 onclick 이벤트를 정의합니다.

changeSomethingFunc : function(number) {    

 

// a 태그의 onclick 이벤트에 연결된 이벤트(함수)를 제거합니다. (JQuery)

$(".obj01").find("a").off("click");

 

// a 태그가 클릭되면 호출될 함수를 정의합니다.

$(".obj01").find("a").click(function() {

// Do Something

// 여기서는 입력된 number 값에 따라서 다른 동작이 정의됩니다.

doSomething(number); // 무언가 하는 함수

 

// 성공적으로 수행되었는지는 모르겠지만, 알림창을 띄웁니다. ㅎㅎㅎ

alert("Event " + number + " is done successfully");

 

});

 

}

 

off()는 인자로 오는 이벤트에 대한 동작을 제거하겠다는 의미입니다.

위의 빨간색으로 된 코드는 현재 실행 시점에 a 태그에 걸려있는 click 이벤트를 삭제(무효화)시키라는 코드입니다.

그리고 그 다음에 새로 click 이벤트를 정의합니다.

 

위와 같이 하면 chageSomethingFunc 함수가 호출될 때마다 a 태그의 click 이벤트를 명시적으로 초기화 시킨 다음 재정의 하므로 위에서 발생하던 IE에서의 예상치 못한 동작을 차단할 수 있습니다.

 

위의 함수는 실제 다음과 같이 정의 되어 있습니다. 실제는 on() 함수와 함께 쌍으로 쓰여집니다.

 

// 객체에 이벤트 함수를 정의하는 방법

$(object).on(EventName, Function);

 

// 객체에서 이벤트를 제거하는 방법

$(object).off(EventName);

 

위에서 계속 설명드렸던 코드를 on() off()로 다시 구현해 보면 다음과 같습니다.

 

 

changeSomethingFunc : function(number) {    

 

$(".obj01").find("a").off("click");

 

$(".obj01").find("a").on("click", function(number) {

doSomething(number);

 

alert("Event " + number + " is done successfully");  

}); 

}

 

on() 함수를 사용하여 함수를 정의해도 코드가 크게 달라지지는 않습니다.

 

가장 많이 사용되는 두 브라우저가 이벤트 (재)정의에 대해서 어떻게 처리하는지 확인하였고, 이를 해결하는 간단한 JQuery 코드를 작성해 보았습니다.^^

 

 

참고로 위의 on(), off() 함수는 JQuery 1.7 버전 이후 부터 지원합니다.

 

 

저작자 표시 비영리 변경 금지
신고

Comment +0

티스토리 툴바