build: Enable jscs jsDoc rule 'requireNewlineAfterDescription' and make pass
[mediawiki.git] / resources / src / mediawiki / mediawiki.confirmCloseWindow.js
blob4d0c1352de13cf66c4d8823ff4590d92370ec06a
1 /* jshint devel: true */
2 ( function ( mw, $ ) {
3         /**
4          * @method confirmCloseWindow
5          * @member mw
6          *
7          * Prevent the closing of a window with a confirm message (the onbeforeunload event seems to
8          * work in most browsers.)
9          *
10          * This supersedes any previous onbeforeunload handler. If there was a handler before, it is
11          * restored when you execute the returned release() function.
12          *
13          *     var allowCloseWindow = mw.confirmCloseWindow();
14          *     // ... do stuff that can't be interrupted ...
15          *     allowCloseWindow.release();
16          *
17          * The second function returned is a trigger function to trigger the check and an alert
18          * window manually, e.g.:
19          *
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)
24          *     } else {
25          *         // do whatever you wanted to do
26          *     }
27          *
28          * @param {Object} [options]
29          * @param {string} [options.namespace] Namespace for the event registration
30          * @param {string} [options.message]
31          * @param {string} options.message.return The string message to show in the confirm dialog.
32          * @param {Function} [options.test]
33          * @param {boolean} [options.test.return=true] Whether to show the dialog to the user.
34          * @return {Object} An object of functions to work with this module
35          */
36         mw.confirmCloseWindow = function ( options ) {
37                 var savedUnloadHandler,
38                         mainEventName = 'beforeunload',
39                         showEventName = 'pageshow',
40                         message;
42                 options = $.extend( {
43                         message: mw.message( 'mwe-prevent-close' ).text(),
44                         test: function () { return true; }
45                 }, options );
47                 if ( options.namespace ) {
48                         mainEventName += '.' + options.namespace;
49                         showEventName += '.' + options.namespace;
50                 }
52                 if ( $.isFunction( options.message ) ) {
53                         message = options.message();
54                 } else {
55                         message = options.message;
56                 }
58                 $( window ).on( mainEventName, function () {
59                         if ( options.test() ) {
60                                 // remove the handler while the alert is showing - otherwise breaks caching in Firefox (3?).
61                                 // but if they continue working on this page, immediately re-register this handler
62                                 savedUnloadHandler = window.onbeforeunload;
63                                 window.onbeforeunload = null;
64                                 setTimeout( function () {
65                                         window.onbeforeunload = savedUnloadHandler;
66                                 }, 1 );
68                                 // show an alert with this message
69                                 return message;
70                         }
71                 } ).on( showEventName, function () {
72                         // Re-add onbeforeunload handler
73                         if ( !window.onbeforeunload && savedUnloadHandler ) {
74                                 window.onbeforeunload = savedUnloadHandler;
75                         }
76                 } );
78                 /**
79                  * Return the object with functions to release and manually trigger the confirm alert
80                  *
81                  * @ignore
82                  */
83                 return {
84                         /**
85                          * Remove all event listeners and don't show an alert anymore, if the user wants to leave
86                          * the page.
87                          *
88                          * @ignore
89                          */
90                         release: function () {
91                                 $( window ).off( mainEventName + ' ' + showEventName );
92                         },
93                         /**
94                          * Trigger the module's function manually: Check, if options.test() returns true and show
95                          * an alert to the user if he/she want to leave this page. Returns false, if options.test() returns
96                          * false or the user cancelled the alert window (~don't leave the page), true otherwise.
97                          *
98                          * @ignore
99                          * @return {boolean}
100                          */
101                         trigger: function () {
102                                 // use confirm to show the message to the user (if options.text() is true)
103                                 if ( options.test() && !confirm( message ) ) {
104                                         // the user want to keep the actual page
105                                         return false;
106                                 }
107                                 // otherwise return true
108                                 return true;
109                         }
110                 };
111         };
112 } )( mediaWiki, jQuery );