Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple OnBeforeUnload

I am writing a JS which is used as a plugin. The JS has an onbeforeunload event.

I want suggestions so that my onbeforeunload event doesn't override the existing onbeforeunload event (if any). Can I append my onbeforeunload to the existing one?

Thanks.

like image 347
Jayesh Avatar asked Jan 25 '12 08:01

Jayesh


3 Answers

You only need to take care of this if you are not using event observing but attach your onbeforeunload handler directly (which you should not). If so, use something like this to avoid overwriting of existing handlers.

(function() {
    var existingHandler = window.onbeforeunload;
    window.onbeforeunload = function(event) {
        if (existingHandler) existingHandler(event);

        // your own handler code here
    }
})();

Unfortunately, you can't prevent other (later) scripts to overwrite your handler. But again, this can be solved by adding an event listener instead:

$(window).unload(function(event) {
    // your handler code here
});
like image 187
Julian D. Avatar answered Nov 06 '22 00:11

Julian D.


I felt this has not been answered completely, because no examples were shown using addEventListener (but The MAZZTer pointed out the addEventListener solution though). My solution is the same as Julian D. but without using jQuery, only native javascript.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Before Unload</title>
</head>
<body>
    <p>Test</p>

    <script>
      window.addEventListener('beforeunload', function (event) {
        console.log('handler 1')
        event.preventDefault()
        event.returnValue = ''
      });

      window.addEventListener('beforeunload', function (event) {
        console.log('handler 2')
      });
    </script>
</body>
</html>

In this example, both listeners will be executed. If any other beforeunload listeners were set, it would not override them. We would get the following output (order is not guaranteed):

handler 1
handler 2

And, importantly, if one or more of the event listener does event.preventDefault(); event.returnValue = '', a prompt asking the user if he really wants to reload will occur.

This can be useful if you are editing a form and at the same time you are downloading a file via ajax and do not want to lose data on any of these action. Each of these could have a listener to prevent page reload.

const editingForm = function (event) {
  console.log('I am preventing losing form data')
  event.preventDefault()
  event.returnValue = ''
}

const preventDownload = function (event) {
  console.log('I am preventing a download')
  event.preventDefault()
  event.returnValue = ''
}

// Add listener when the download starts
window.addEventListener('beforeunload', preventDownload);
// Add listener when the form is being edited
window.addEventListener('beforeunload', editingForm);

// Remove listener when the download ends
window.removeEventListener('beforeunload', preventDownload);
// Remove listener when the form editing ends
window.removeEventListener('beforeunload', editingForm);
like image 37
Lunfel Avatar answered Nov 06 '22 01:11

Lunfel


My idea:

var callbacks = [];
window.onbeforeunload = function() {
    while (callbacks.length) {
        var cb = callbacks.shift();
        typeof(cb)==="function" && cb();
    }
}

and

callbacks.push(function() {
    console.log("callback");
});
like image 40
ft525 Avatar answered Nov 06 '22 01:11

ft525