Bug Tracker

Modify

Ticket #12061 (closed bug: fixed)

Opened 22 months ago

Last modified 10 months ago

$(window).beforeunload() clobbers previous handler and return values

Reported by: dmethvin Owned by:
Priority: low Milestone: 1.9
Component: event Version: 1.7.2
Keywords: Cc:
Blocking: Blocked by:

Description

Moved from:  http://bugs.jqueryui.com/ticket/8439

No matter what $(window).beforeunload(fn) does, it cannot interact reliably with a mix of native inline functions. For other events, jQuery attaches a private native handler via addEventListener or attachEvent and manages jQuery handlers in its own data structures. Here we are all trying to share a single window.onbeforeunload property, and it can't work.

Scenarios:

   window.onbeforeunload = fn1;
   $(window).on("beforeunload", fn2);
   $(window).on("beforeunload", fn3);

Currently, we clobber fn1 and it is never called; only fn2 and fn3 would be called.

   window.onbeforeunload = fn1;
   $(window).on("beforeunload", fn2);
   $(window).on("beforeunload", fn3);
   window.onbeforeunload = null;

If the code that sets fn1 later tries to remove it by nulling out the handler, fn2 and fn3 don't run.

Having jQuery and the native code save any existing handler allows everyone to run, but prevents anyone from removing their handler; perhaps that is less of a problem in real-life scenarios.

There is also the return value problem. Unlike other event handlers that return false as a flag, the onbeforeunload event returns a string that is supposed to be displayed to the user, such as "Are you sure you want to leave this page? Your edits will be lost". In the case that there are multiple handlers what should be displayed to the user? Right now, we display the string from the *last* jQuery handler called.

Change History

comment:1 Changed 22 months ago by dmethvin

  • Priority changed from undecided to low
  • Status changed from new to open
  • Component changed from unfiled to event
  • Milestone changed from None to 1.9

comment:3 follow-up: ↓ 4 Changed 18 months ago by Oleg

  • Status changed from open to closed
  • Resolution set to fixed

Fix #12061. Avoid window.onbeforeunload to permit multiple handlers. Close gh-894.

Changeset: 9dd0b010174dbfa70142a995a875a316337e1913

comment:4 in reply to: ↑ 3 Changed 18 months ago by anonymous

Replying to Oleg:

Changeset: 9dd0b010174dbfa70142a995a875a316337e1913

This does not appear to be the correct changeset link.

comment:5 Changed 17 months ago by skarkkai

As of 1.9.2. release, existing onbeforeunload handler is still getting clobbered.

comment:6 Changed 17 months ago by dmethvin

skarkkai, the test case above works. If you have a test case that fails can you post it?

comment:7 Changed 17 months ago by dmethvin

Test case that also includes the native onbeforeunload, which also works.

 http://jsfiddle.net/fDccK/10/

comment:8 Changed 14 months ago by antonio@…

The string to be showed has to be the last valid string so if the last callback returns null the page doesn't close without confirmation.

 http://jsfiddle.net/fDccK/19/

comment:9 Changed 14 months ago by dmethvin

Don't return null, return *nothing* so its undefined.

comment:10 Changed 10 months ago by lucas@…

Hello

Recently I needed to make a queue that is updated via ajax.

It is updated recursively with a interval between each request.

Users complained that they were receiving an error message when accessed any link while the queue is updated.

So I needed to identify if the onError was called by a failure or because the user left navigation during the ajax request.

I fulfilled using the combination of $.ajaxError and $.bind('beforeunload', func) in the following code  http://jsfiddle.net/7A6Ne/

But I just tested in Chrome 27, IE 10 and Firefox, so I'm afraid because I do not know if implementation of beforeunload is ok in all major browsers.

Should be fine if $.ajaxError tell us if user left navigation.

comment:11 Changed 10 months ago by lucas@…

Sorry, I posted in the wrong ticket.

It is the correct http://bugs.jquery.com/ticket/13171

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.