3 * Prevent the closing of a window with a confirm message (the onbeforeunload event seems to
4 * work in most browsers).
6 * Provided by the mediawiki.confirmCloseWindow module.
8 * This supersedes any previous onbeforeunload handler. If there was a handler before, it is
9 * restored when you execute the returned release() function.
12 * mw.loader.using( 'mediawiki.confirmCloseWindow' ).then(() => {
13 * var allowCloseWindow = mw.confirmCloseWindow();
14 * // ... do stuff that can't be interrupted ...
15 * allowCloseWindow.release();
17 * // The second function returned is a trigger function to trigger the check and an alert
18 * // window manually, e.g.:
20 * var allowCloseWindow = mw.confirmCloseWindow();
21 * // ... do stuff that can't be interrupted ...
22 * if ( allowCloseWindow.trigger() ) {
23 * // don't do anything (e.g. destroy the input field)
25 * // do whatever you wanted to do
28 * @method confirmCloseWindow
30 * @param {Object} [options]
31 * @param {string} [options.namespace] Optional jQuery event namespace, to allow loosely coupled
32 * external code to release your trigger. For example, the VisualEditor extension can use this
33 * remove the trigger registered by mediawiki.action.edit, without strong runtime coupling.
34 * @param {Function} [options.test]
35 * @param {boolean} [options.test.return=true] Whether to show the dialog to the user.
36 * @return {Object} An object of functions to work with this module
38 mw.confirmCloseWindow = function ( options ) {
39 let beforeunloadEvent = 'beforeunload';
40 const test = options && options.test || function () {
44 if ( options && options.namespace ) {
45 beforeunloadEvent += '.' + options.namespace;
51 * @return {string|undefined}
53 function onBeforeunload( e ) {
55 // Standard supported in Firefox, IE9+, Safari 11.1+
58 // Support: Chrome, Edge, Safari 9-11
60 // Leave the "extra text" string empty since Chrome/Firefox/Safari/Edge
61 // won't display it anyway, and because otherwise IE11 would actually
62 // still display it otherwise.
64 // Before 2015, the standard behaviour was that when a string is returned here,
65 // the browser will prompt a native and localised message like
66 // "Are you sure? Unsaved changes may be lost.", with the returned string after
69 // As of 2015, this is no longer supported in modern browsers. But, the only
70 // cross-browser compatible way to trigger the prompt at all, remains to return
71 // a string, any string. The HTML spec says e.preventDefault() is the new way to
72 // signal this, but Chrome/Edge don't support that yet, and we also support
73 // Safari 9-11 which didn't have it.
75 // <https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event>
80 $( window ).on( beforeunloadEvent, onBeforeunload );
84 * Remove the event listener and don't show an alert anymore, if the user wants to leave
89 release: function () {
90 $( window ).off( beforeunloadEvent, onBeforeunload );
93 * Trigger the module's function manually.
95 * Check, if options.test() returns true and show an alert to the user if he/she want
96 * to leave this page. Returns false, if options.test() returns false or the user
97 * cancelled the alert window (~don't leave the page), true otherwise.
102 trigger: function () {
103 const message = mw.msg( 'confirmleave-warning' );
104 // use confirm to show the message to the user (if options.text() is true)
105 // eslint-disable-next-line no-alert
106 if ( test() && !confirm( message ) ) {
107 // the user want to keep the actual page
110 // otherwise return true