본문 바로가기

Slack 채널 정리

js, 이벤트 실행 전후에 기능 삽입

구글링해서 찾은 코드 조각을 조합해서 만들어본거(로직은 아직 제대로 이해 못했는데 분석하면서 공부해보면 js 이벤트리스너 핸들링하는거 이해하는데 도움이 많이 될 듯 싶긴함).  이벤트 발생 시 이벤트 실행 전후에 기능을 삽입하는 용도. 샘플은 버튼 타입의 엘리먼트들의 클릭 이벤트 시에 .  그런데 이상하게 버튼 엘리먼트에 인라인으로 onclick 이벤트해놓은 녀석은 이게 안 먹네요. 쉬운게 없어요 ㅜㅠ

$.fn.bindLF = function(name, fnFirst, fnLast) {
    this.bind(name, fnFirst);

    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];
        var handler = handlers.pop();
        handlers.splice(0, 0, handler);
    });

    this.on(name, fnLast);
    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];

         var hsucess = null;
         $.each(handlers, function (i, h) {
             if (h.handler == fnLast) {
                 hsucess = h;
             }
         });
         var index = handlers.indexOf(hsucess);
         if (index > -1) {
             handlers.splice(index, 1);
             handlers.push(hsucess);
         }
    });
};

$("button").on('click', function() {     
    console.log("Step1");
});
$("button").on('click', function() {     
    console.log("Step2");
});

var mLast = function(){ 
    console.log("END");
};
var mFirst = function(){ 
    console.log("First");
};

$("button").bindLF('click', mFirst, mLast);

위 코드는 돌아다니는 코드 주워모아 로직 이해 못한 상태에서 조합해본거라 성능 부분은 고려치 못했습니다. 가령 제일 앞에 바인드할 때랑 제일 뒤에 바인드할 때 각각 루프를 돌면서 처리하게 되어 있는데 이게 꼭 이럴 필요가 있는지 잘 모르겠어요. 루프 한 번 돌면서 이 둘을 해치울 수 있을까요?

위 스크립트를 이용한 실용적(?)인 코드 하나 만들어봤습니다. onbeforeunload 는 페이지 unload 전 실행되는 함수로 현재 화면 에서 나갈 때(브라우저의 창닫기 버튼, 백 버튼, 그리고 href 등 클릭해서 다른 페이지 이동하는 등의 경우에 데이타가 사라질 수 있다는 경고창을 띄워주는 기능을 합니다. 올려놓은 소스는 브라우저 버튼 외에 페이지 내에서 button 클릭 시 화면 이동하는 경우에는  onbeforeunload 가 실행되지 않도록 구현해본 겁니다. 

function warning(){
   if (!warning.disabled) {
      return "";
   }
}
​
window.onbeforeunload = warning;
​
$.fn.bindLF = function(name, fnFirst, fnLast) {
    this.bind(name, fnFirst); 
Untitled
 
function warning(){
   if (!warning.disabled) {
      return "";
   }
}

window.onbeforeunload = warning;

$.fn.bindLF = function(name, fnFirst, fnLast) {
    this.bind(name, fnFirst);

    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];
        var handler = handlers.pop();
        handlers.splice(0, 0, handler);
    });
    this.on(name, fnLast);
    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];
         var hsucess = null;

         $.each(handlers, function (i, h) {
             if (h.handler == fnLast) {
                 hsucess = h;
    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];
        var handler = handlers.pop();
        handlers.splice(0, 0, handler);
    });

    this.on(name, fnLast);
    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];
         var hsucess = null;
         $.each(handlers, function (i, h) {
             if (h.handler == fnLast) {
                 hsucess = h;
             }
         });
         var index = handlers.indexOf(hsucess);
         if (index > -1) {
             handlers.splice(index, 1);
             handlers.push(hsucess);
         }
    });
};

var isWarningDisabled = function(_flag) {
    warning.disabled = _flag;
}
var initWarn = function() {
    isWarningDisabled(false); 
};
var mLast = function(){ 
    setTimeout(initWarn, 1000);
};
var mFirst = function(){ 
    isWarningDisabled(true); 
};

$("button").bindLF('click', mFirst, mLast);

코드 간단히 설명하자면 버튼 클릭 시에는 warning.disabled 라는 전역 변수를 이용하여 onbeforeunload 를 사용하지 않도록 설정합니다(당연히 이 설정해주지 않으면 버튼에 'window.location.href =...' 같은게 구현되어 있을 때 onbeforeunload 가 실행됩니다) 문제는 이 버튼에서 가령 confirm 기능을 이용해서 페이지 이동할지 말지를 선택하게 할 때 사용자가 이동 안함 버튼을 누르면 onbeforeunload 기능이 비활성화된 상태가 유지 되기 때문에 브라우저 창당기 버튼 등을 눌러도 onbeforeunload 가 작동하지 않는다는 겁니다. 그래서 mLast 함수(버튼 클릭 이벤트 마지막에 자동 이벤트 삽입하는 기능) 에서 비동기로 onbeforeunload 값을 무조건 초기화해주도록 해버렸습니다.