브라우저 창 닫기 이벤트를 캡처하는 방법은 무엇입니까?


149

브라우저 창 / 탭 닫기 이벤트를 캡처하고 싶습니다. jQuery로 다음을 시도했습니다.

jQuery(window).bind(
    "beforeunload", 
    function() { 
        return confirm("Do you really want to close?") 
    }
)

그러나 양식 제출에서도 작동하지만 이는 내가 원하는 것이 아닙니다. 사용자가 창을 닫을 때만 트리거되는 이벤트를 원합니다.

답변:


212

그만큼 beforeunload사용자가 어떤 이유로 페이지를 단풍 때마다 이벤트가 발생합니다.

예를 들어, 사용자가 양식을 제출하거나, 링크를 클릭하거나, 창 또는 탭을 닫거나, 주소 표시 줄, 검색 상자 또는 책갈피를 사용하여 새 페이지로 이동하면 시작됩니다.

다음 코드를 사용하여 양식 제출 및 하이퍼 링크 (다른 프레임 제외)를 제외 할 수 있습니다.

var inFormOrLink;
$('a').on('click', function() { inFormOrLink = true; });
$('form').on('submit', function() { inFormOrLink = true; });

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

1.7보다 오래된 jQuery 버전의 경우 다음을 시도하십시오.

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

live메소드는 submit이벤트 와 함께 작동하지 않으므로 새 양식을 추가하는 경우 핸들러도 해당 오브젝트에 바인드해야합니다.

다른 이벤트 핸들러가 제출 또는 탐색을 취소하면 나중에 실제로 창이 닫히면 확인 메시지가 표시되지 않습니다. submitclick이벤트 의 시간을 기록하고 beforeunload몇 초 후에 발생 하는지 확인 하여 문제를 해결할 수 있습니다.


8
응, 잘 했어! 최신 버전의 jquery는 $ ( 'form'). live ( 'submit, function () {})를 지원합니다.
Venkat D.

4
귀하의 솔루션은 좋지만 새로 고침시 이벤트를 어떻게 취소합니까? 브라우저를 닫은 경우에만 이벤트를 원합니다. 새로 고침 할 필요가 없습니다
Refael

브라우저가 beforeunload의 반환 값을 확인 대화 상자로 표시하는 것 같습니다. 이 답변이 더 정확하다고 생각합니다. link
tahagh

2
페이지의이 핸들 새로 고침 사용하지 Ctrl + r, F5, Ctrl + Shift + r브라우저의 URL을 변경?
Arti

1
@Jonny : 이제 막 .on().
SLaks

45

어쩌면 beforeunload폼의 submit이벤트 핸들러 내 에서 이벤트 핸들러를 바인딩 해제 할 수 있습니다 .

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});

3
양식 태그 정의에서 이것을 지정하여 jQuery를 사용하지 않는 것이 쉽지 않습니까? :`<form onsubmit = "window.onbeforeunload = null;">
awe

4
@awe 그러나 당신 onsubmit=...은 각 형태로 그것을 포함해야합니다 . (나는 특정 웹
응용 프로그램

16

크로스 브라우저 솔루션 (Chrome 21, IE9, FF15에서 테스트)의 경우 약간 수정 된 Slaks 코드 버전 인 다음 코드를 사용하는 것이 좋습니다.

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

Firefox 4부터 "정말로 닫으시겠습니까?"라는 메시지가 표시됩니다. 가 표시되지 않습니다. FF는 일반 메시지 만 표시합니다. https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload 에서 참고 사항 참조


3
이것은 브라우저에서 일관되게 작동합니다. 간단한 참고 사항; livebind문을 모두 업데이트 on하여 최신 수준의 jQuery와 잘 작동합니다. 감사!
Sablefoste


4

여러 가지 이유로 Anchor 태그를 사용하는 Telerik (예 : RadComboBox) 및 DevExpress와 같은 타사 컨트롤과 잘 작동하는 솔루션의 경우 다음 코드를 사용하는 것이 좋습니다. 앵커 태그 타겟팅 :

var inFormOrLink;
$('a[href]:not([target]), a[href][target=_self]').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
});

1
이 답변은 정확하지만 브라우저를 새로 고칠 때이 이벤트와 관련하여 문제가 발생한 사용자의 경우 if를 다음 코드로 변경하십시오. if (inFormOrLink! == undefined &&! inFormOrLink)
LeonPierre

4

내 대답은 간단한 벤치 마크를 제공하는 것입니다.

어떻게

@SLaks answer를 참조하십시오 .

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

브라우저가 페이지를 종료하는 데 얼마나 걸립니까?

사용자가 페이지를 닫을 때마다 ( x버튼 또는 CTRL+ W) 브라우저는 주어진 beforeunload코드를 실행 하지만 무한정 실행 되지는 않습니다. 유일한 예외는 확인 상자 (return 'Do you really want to close? , 사용자의 응답을 기다릴 ) .

크롬 : 2 초
Firefox : ∞ (또는 더블 클릭 또는 강제 종료)
Edge : ∞ (또는 더블 클릭)
Explorer 11 : 0 초.
사파리 : TODO

우리가 이것을 테스트하기 위해 사용한 것 :

  • 요청 로그가있는 Node.js Express 서버
  • 다음 짧은 HTML 파일

브라우저가 페이지를 (동기식으로) 종료하기 전에 가능한 많은 요청을 보내는 것입니다.

<html>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
    function request() {
        return $.ajax({
            type: "GET",
            url: "http://localhost:3030/" + Date.now(),
            async: true
        }).responseText;
    }
    window.onbeforeunload = () => {
        while (true) {
            request();
        }
        return null;
    }
    </script>
</body>
</html>

크롬 출력 :

GET /1480451321041 404 0.389 ms - 32  
GET /1480451321052 404 0.219 ms - 32  
...  
GET /hello/1480451322998 404 0.328 ms - 32

1957ms  2 seconds // we assume it's 2 seconds since requests can take few milliseconds to be sent.

3

Slaks 답변을 사용했지만 onbeforeunload returnValue가 문자열로 구문 분석 된 다음 브라우저의 확인 상자에 표시되므로 그대로 작동하지 않았습니다. 따라서 "true"와 같이 true 값이 표시되었습니다.

그냥 반품을 사용했습니다. 여기 내 코드가 있습니다

var preventUnloadPrompt;
var messageBeforeUnload = "my message here - Are you sure you want to leave this page?";
//var redirectAfterPrompt = "http://www.google.co.in";
$('a').live('click', function() { preventUnloadPrompt = true; });
$('form').live('submit', function() { preventUnloadPrompt = true; });
$(window).bind("beforeunload", function(e) { 
    var rval;
    if(preventUnloadPrompt) {
        return;
    } else {
        //location.replace(redirectAfterPrompt);
        return messageBeforeUnload;
    }
    return rval;
})

1

아마도 OnSubmit을 처리하고 나중에 OnBeforeUnload 핸들러에서 확인할 플래그를 설정할 수 있습니다.


1
jQuery(window).bind(
                    "beforeunload",
                      function (e) {
                          var activeElementTagName = e.target.activeElement.tagName;
                          if (activeElementTagName != "A" && activeElementTagName != "INPUT") {
                              return "Do you really want to close?";
                          }
                      })

1

불행히도 새로 고침, 새 페이지 리디렉션 또는 브라우저 닫기 여부에 관계없이 이벤트가 트리거됩니다. 대안은 이벤트를 트리거하는 id를 포착하는 것이며 폼인 경우 함수를 트리거하지 않으며 폼의 id가 아닌 경우 페이지를 닫을 때 수행하려는 작업을 수행하십시오. 그것이 직접 가능하고 지루한 지 확실하지 않습니다.

고객이 탭을 닫기 전에 몇 가지 작은 작업을 수행 할 수 있습니다. 자바 스크립트는 브라우저 닫기 탭 / 브라우저 닫기를 감지 하지만 작업 목록이 크고 탭이 끝나기 전에 닫히면 무기력합니다. 당신은 그것을 시도 할 수 있지만 내 경험으로는 그것에 의존하지 않습니다.

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  /* Do you small action code here */
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/beforeunload?redirectlocale=en-US&redirectslug=DOM/Mozilla_event_reference/beforeunload


0

양식 제출이 다른 페이지로 이동하는 경우 (따라서 트리거 됨 beforeunload) 양식 제출을 ajax 호출로 변경하려고 시도 할 수 있습니다. 이렇게하면 양식을 제출할 때 페이지를 떠나지 않으며 beforeunload원하는대로 바인딩 코드를 사용할 수 있습니다 .


0

내 문제 : 'onbeforeunload'이벤트는 홀수의 제출 (클릭)이있는 경우에만 트리거됩니다. 내 솔루션이 작동하도록 SO에 비슷한 스레드의 솔루션 조합이있었습니다. 잘 내 코드가 말할 것입니다.

<!--The definition of event and initializing the trigger flag--->


$(document).ready(function() {
updatefgallowPrompt(true);
window.onbeforeunload = WarnUser;   
}

function WarnUser() {
var allowPrompt = getfgallowPrompt();
    if(allowPrompt) {
    saveIndexedDataAlert();
    return null;
    } else {
        updatefgallowPrompt(true);
        event.stopPropagation
    }
}

<!--The method responsible for deciding weather the unload event is triggered from submit or not--->
function saveIndexedDataAlert() {
    var allowPrompt = getfgallowPrompt();
    var lenIndexedDocs = parseInt($('#sortable3 > li').size()) + parseInt($('#sortable3 > ul').size());

    if(allowPrompt && $.trim(lenIndexedDocs) > 0) {
        event.returnValue = "Your message";
    } else {
        event.returnValue = "   ";
        updatefgallowPrompt(true);
    }
}

<!---Function responsible to reset the trigger flag---->
$(document).click(function(event) {  
$('a').live('click', function() { updatefgallowPrompt(false); });
 });

<!--getter and setter for the flag---->
function updatefgallowPrompt (allowPrompt){ //exit msg dfds
    $('body').data('allowPrompt', allowPrompt); 
}   

function getfgallowPrompt(){        
    return $('body').data('allowPrompt');   
}

0

jQuery 1.7부터 .live () 메소드는 더 이상 사용되지 않습니다. .on ()을 사용하여 이벤트 핸들러를 첨부하십시오. 이전 버전의 jQuery 사용자는 .live ()보다 .delegate ()를 사용해야합니다.

$(window).bind("beforeunload", function() {
    return true || confirm("Do you really want to close?"); 
}); 

완료 또는 링크

$(window).unbind();

0

이것도 시도

window.onbeforeunload = function ()
{       
    if (pasteEditorChange) {
        var btn = confirm('Do You Want to Save the Changess?');
           if(btn === true ){
               SavetoEdit();//your function call
           }
           else{
                windowClose();//your function call
           }
    }  else { 
        windowClose();//your function call
    }
};

-1

그냥 확인하십시오 ...

function wopen_close(){
  var w = window.open($url, '_blank', 'width=600, height=400, scrollbars=no, status=no, resizable=no, screenx=0, screeny=0');
  w.onunload = function(){
    if (window.closed) {
       alert("window closed");
    }else{ 
       alert("just refreshed");
    }
  }
}

작동하지 않습니다. 언로드 이벤트가 발생하는 순간 (btw, 문서에서 발생) window.closed === false;
Sergey P. 일명 azure

-1
var validNavigation = false;
            jQuery(document).ready(function () {

                wireUpEvents();
            });

            function endSession() {
                // Browser or broswer tab is closed
                // Do sth here ...
                alert("bye");
            }

            function wireUpEvents() {
                /*
                * For a list of events that triggers onbeforeunload on IE
                * check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
                */
                window.onbeforeunload = function () {
                    debugger
                    if (!validNavigation) {
                        endSession();
                    }
                }

                // Attach the event keypress to exclude the F5 refresh
                $(document).bind('keypress', function (e) {
                    debugger
                    if (e.keyCode == 116) {
                        validNavigation = true;
                    }
                });

                // Attach the event click for all links in the page
                $("a").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event submit for all forms in the page
                $("form").bind("submit", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event click for all inputs in the page
                $("input[type=submit]").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

            }`enter code here`

-7

다음은 나를 위해 일했습니다.

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });

jquery 함수입니다.
maxisam

7
event.clientY브라우저의 닫기 버튼이나 탭 닫기 버튼을 클릭하면 부정적이다. 그러나 키보드 단축키 (F5, Ctrl-R)를 사용하여 페이지를 다시로드하거나 키보드 단축키 (예 : Alt-F4)를 사용하여 브라우저를 닫을 때이 값은 양수입니다. 따라서 브라우저 닫기 이벤트를 페이지 다시로드 이벤트와 구별하기 위해 이벤트 위치를 신뢰할 수 없습니다.
Julien Kronegg 2014
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.