- From: Shropshire, Andrew A <shropshire@att.com>
- Date: Mon, 5 Jan 2009 07:29:49 -0500
- To: "Boris Zbarsky" <bzbarsky@MIT.EDU>
- Cc: <public-webapps@w3.org>
Thank you for your comments. I agree with your objection concerning loss of browsing history. One other objection I had was that it still would not be possible to recreate the typical desktop application behavior of asking the user if they wish to save changes/cancel when closing the application (providing a YES/NO/CANCEL dialog whereby YES saves the changes and exits, NO does not save the changes and exits, and CANCEL cancels the exit). I would like to submit a revised proposal that addresses these 2 objections, and a few additional objections that are best illustrated with 4 brief web page examples. EXAMPLE #1 ------------ In this example, tested with Internet Explorer 7, the page has the name 'test.htm'. One may test it by saving it to disk and opening it in a browser. This page will block all navigation by redirecting the browser to itself in the unload event handler. IE 7 however, allows the user to close the page. Effectively, the user has lost their browsing history. <html> <head> <script> function exitPageCheck() { window.location = 'test.htm'; } </script> </head> <body onunload='exitPageCheck()'> Test </body> </html> EXAMPLE #2 ------------ In this second example, I added an alert() before the redirect. The alert displays when the user closes the page. This shows that the unload event handler is fired when the user closes the page, but in spite of the redirect, the browser closes the page. <html> <head> <script> function exitPageCheck() { alert('blocking'); window.location = 'test.htm'; } </script> </head> <body onunload='exitPageCheck()'> Test </body> </html> EXAMPLE #3 ------------ In this example, the code displays a confirm dialog prior to the redirect rather than an alert. When the user closes the page, the tab is given an orange color, focus switches to a different tab, but tab/page does not close yet. If the user clicks on the orange tab, they will see the confirm dialog, however, hitting cancel does not stop the page from finally closing (at which point the tab will disappear). <html> <head> <script> function exitPageCheck() { var answer = confirm('There are unsaved changes, are you sure you wish to leave?'); if (answer) return; window.location = 'test.htm'; } </script> </head> <body onunload='exitPageCheck()'> Test </body> </html> EXAMPLE #4 ------------ In this last example, the code display 10,000 confirm dialogs in the unload event handler. When the user closes the page, IE changes the tab color to orange and gives focus to a different tab, however, if the user clicks on the orange tab (returning focus to the malicious page), IE becomes modal and the user cannot do anything with IE (such as giving focus to another tab) until going through 10000 confirm dialogs (effectively the browser is crashed). <html> <head> <script> function exitPageCheck() { for (var i = 0; i < 10000; ++i) var answer = confirm('There are unsaved changes, are you sure you wish to leave?'); if (answer) return; window.location = 'test.htm'; } </script> </head> <body onunload='exitPageCheck()'> Hello </body> </html> Revised proposal follows that addresses all these issues. This obsoletes & replaces the previous proposal. 1. Allow the unload event to be cancellable from script. This will allow web designers to recreate the modal flavor of desktop apps like MS Excel that prompt with "Yes/No Cancel" when there are unsaved changes. As to how the cancel is accomplished, this could be a method of the event object such as .cancel(), with another method such as .isCanceled() to address situations where that are multiple event listeners registered, and a previous one has already canceled the unload event. For example, suppose there are 2 unload event listeners. The 2nd event listener to be called would not want to display another confirm dialog to the user, if the first event handler had already done so and canceled the unload. 2. In the unload event, distinguish between closes and navigating away, by adding a property to the event object such as getUnloadType() which returns an enumerated type with one of these values: WINDOW_IS_CLOSING = 1 WINDOW_IS_NAVIGATING_TO_NEW_PAGE = 2 (Since javascript doesn't have an enumerated type that I am aware of, this could be an integer, or even two separate methods like .isClosing()and .isNavigatingAway() which return booleans). It may be helpful to know for WINDOW_IS_NAVIGATING_TO_NEW_PAGE events what the new URL is, however, this may violate security, and I can't think of a benefit to knowing that information at the moment, so it may be best to not provide that information. 3. Warn user with information style bar (similar to what IE already uses when it blocks a file download) if page cancels unload event (it will disappears after a few seconds without user interaction to avoid annoying the user with having to close it). The text in the bar might be (for page closures): "This page has blocked closure. Click here to override." Or "This page is blocked navigation to the new url. Click here to override." For navigating away. If the bar is clicked on, then a popup-like window (hereafter referred to as the OVERRIDE CONTROL will overlay the page and show navigation history in a list, allowing the user to override the script and forcefully navigate to a page in history. In addition the OVERRIDE CONTROL will have an edit box for typing in a new URL and a means to go to a bookmark. The implementation details could be made more specific or done differently, I just suggest an implementation design to illustrate. 4. The OVERRIDE CONTROL will be available to the user at any time (maybe as a button near the back/forward buttons, not just when an unload event is blocked by script. This will address the 10000 confirm dialog problem given as an example above. 5. If the OVERRIDE CONTROL is used, the page will not receive any further events or have the opportunity to run any more script. This is not such a problem for benevolent developers, who have to design for electric power failures anyways. 6. In a tabbed browser, do NOT allow a modal state to affect the other windows. In the 10000 confirm dialog problem mentioned above, the browser entered a modal state and did not allow the user to go to any of the other tabs. Andrew Shropshire -----Original Message----- From: Boris Zbarsky [mailto:bzbarsky@MIT.EDU] Sent: Friday, January 02, 2009 3:13 PM To: Shropshire, Andrew A Cc: public-webapps@w3.org Subject: Re: Proposal: Detecting when the user leaves a page due to hitting the back button or typing in a URL or going to a favorite Shropshire, Andrew A wrote: > 4) Should a web page designer cancel all navigations away from the > page just to be malicious, the user can still close the page (since > closing the page does not fire the onNavigateToNewPage event). That loses the user's navigation history in that window, so doesn't seem acceptable to me, as a user. In fact, preventing backwards navigation in history, to before the malicious site was entered, if nothing else, is also not acceptable. -Boris
Received on Monday, 5 January 2009 12:30:55 UTC