A 태그의 중첩된 클릭 이벤트 문제 해결하기! (그리고 JQuery on()과 off() 함수(메서드) 사용해보기)
제목만 읽어서는 무슨 말인가 하실 수도 있을 것 같습니다.^^
일반적으로 크롬을 기반으로 개발 후, IE와 사파리 그리고 파폭 순으로 테스트를 하는 개발자입니다.
[IE브라우저] a 태그의 중첩된 onclick 문제 해결하기
모든 브라우저가 동일한 표준을 사용하고, 표준 코드에 대해서 동일하게 동작한다면 얼마나 좋겠지만, 현실은 그렇지 않지요.. (윈도우8의 Edge 브라우저는 표준을 잘 따른다고 선전은 하고 있는데, 아직 어떤지는 잘 모르겠습니다. (일단 아직까지는 큰 이슈는 없는 것 같군요.)
일단 본론으로 들어가면
종종 a 태그에 href 대신 onclick (물론 a태그가 아닌 태그으 경우에도) 이벤트를 주어서 사용하는 경우가 있습니다. onclick을 쓸 수 밖에 없는 경우도 발생하지요.
<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 버전 이후 부터 지원합니다.
'개발&컴퓨터 > JQuery & JS' 카테고리의 다른 글
a 태그에서 href 를 제거하고 싶다면! (href가 있는 경우와 없는 경우의 차이점) (2) | 2017.04.17 |
---|---|
Javascript에서의 not defined 변수 처리 (vs undefined) (0) | 2015.11.04 |
[Javascript] 영문 문자열 대소문자 변환 (영문 알파벳) (0) | 2015.06.11 |
[JQuery] Object의 특정 클래스(Class) 포함 여부를 확인하는 다양한 방법. (6) | 2015.06.05 |
Javascript - 숫자에 세자리마다 콤마 붙이기 (4) | 2015.05.08 |