Merge "Add tests for WikiMap and WikiReference"
[lhc/web/wiklou.git] / resources / src / mediawiki / mediawiki.confirmCloseWindow.js
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;
41
42 options = $.extend( {
43 message: mw.message( 'mwe-prevent-close' ).text(),
44 test: function () { return true; }
45 }, options );
46
47 if ( options.namespace ) {
48 mainEventName += '.' + options.namespace;
49 showEventName += '.' + options.namespace;
50 }
51
52 if ( $.isFunction( options.message ) ) {
53 message = options.message();
54 } else {
55 message = options.message;
56 }
57
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 );
67
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 } );
77
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 );