From d607e6a70bb0250aad5a899aa14b663eb3404766 Mon Sep 17 00:00:00 2001 From: Mark Holmquist Date: Fri, 1 Aug 2014 11:05:09 -0700 Subject: [PATCH] Implement mediawiki.confirmCloseWindow module Copied from UploadWizard, removed there in I9411a6d33. Change-Id: I5d35b6fddd73cf56371eeda299ee0779cb40397a --- resources/Resources.php | 8 ++- .../mediawiki.action.edit.editWarning.js | 61 +++++++----------- .../mediawiki/mediawiki.confirmCloseWindow.js | 64 +++++++++++++++++++ 3 files changed, 93 insertions(+), 40 deletions(-) create mode 100644 resources/src/mediawiki/mediawiki.confirmCloseWindow.js diff --git a/resources/Resources.php b/resources/Resources.php index c634d9d8b0..a82260c09f 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -818,6 +818,11 @@ return array( 'mediawiki.content.json' => array( 'styles' => 'resources/src/mediawiki/mediawiki.content.json.css', ), + 'mediawiki.confirmCloseWindow' => array( + 'scripts' => array( + 'resources/src/mediawiki/mediawiki.confirmCloseWindow.js', + ), + ), 'mediawiki.debug' => array( 'scripts' => array( 'resources/src/mediawiki/mediawiki.debug.js', @@ -1079,7 +1084,8 @@ return array( 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js', 'dependencies' => array( 'jquery.textSelection', - 'mediawiki.jqueryMsg' + 'mediawiki.jqueryMsg', + 'mediawiki.confirmCloseWindow', ), 'messages' => array( 'editwarning-warning', diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js b/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js index b5654400f7..6b33012854 100644 --- a/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js +++ b/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js @@ -5,54 +5,37 @@ 'use strict'; $( function () { - var savedWindowOnBeforeUnload, - $wpTextbox1 = $( '#wpTextbox1' ), - $wpSummary = $( '#wpSummary' ); + var allowCloseWindow, + $textBox = $( '#wpTextbox1' ), + $summary = $( '#wpSummary' ), + $both = $textBox.add( $summary ); + // Check if EditWarning is enabled and if we need it - if ( $wpTextbox1.length === 0 ) { + if ( !mw.user.options.get( 'useeditwarning' ) ) { return true; } - // Get the original values of some form elements - $wpTextbox1.add( $wpSummary ).each( function () { - $( this ).data( 'origtext', $( this ).val() ); + + // Save the original value of the text fields + $both.each( function ( index, element ) { + var $element = $( element ); + $element.data( 'origtext', $element.textSelection( 'getContents' ) ); } ); - $( window ) - .on( 'beforeunload.editwarning', function () { - var retval; - // Check if the current values of some form elements are the same as - // the original values - if ( - mw.config.get( 'wgAction' ) === 'submit' || - $wpTextbox1.data( 'origtext' ) !== $wpTextbox1.textSelection( 'getContents' ) || - $wpSummary.data( 'origtext' ) !== $wpSummary.textSelection( 'getContents' ) - ) { - // Return our message - retval = mw.msg( 'editwarning-warning' ); - } + allowCloseWindow = mw.confirmCloseWindow( { + test: function () { + // We use .textSelection, because editors might not have updated the form yet. + return mw.config.get( 'wgAction' ) === 'submit' || + $textBox.data( 'origtext' ) !== $textBox.textSelection( 'getContents' ) || + $summary.data( 'origtext' ) !== $summary.textSelection( 'getContents' ); + }, - // Unset the onbeforeunload handler so we don't break page caching in Firefox - savedWindowOnBeforeUnload = window.onbeforeunload; - window.onbeforeunload = null; - if ( retval !== undefined ) { - // ...but if the user chooses not to leave the page, we need to rebind it - setTimeout( function () { - window.onbeforeunload = savedWindowOnBeforeUnload; - }, 1 ); - return retval; - } - } ) - .on( 'pageshow.editwarning', function () { - // Re-add onbeforeunload handler - if ( !window.onbeforeunload ) { - window.onbeforeunload = savedWindowOnBeforeUnload; - } - } ); + message: mw.msg( 'editwarning-warning' ), + namespace: 'editwarning' + } ); // Add form submission handler $( '#editform' ).submit( function () { - // Unbind our handlers - $( window ).off( '.editwarning' ); + allowCloseWindow(); } ); } ); diff --git a/resources/src/mediawiki/mediawiki.confirmCloseWindow.js b/resources/src/mediawiki/mediawiki.confirmCloseWindow.js new file mode 100644 index 0000000000..177367da93 --- /dev/null +++ b/resources/src/mediawiki/mediawiki.confirmCloseWindow.js @@ -0,0 +1,64 @@ +( function ( mw, $ ) { + /** + * @method confirmCloseWindow + * @member mw + * + * Prevent the closing of a window with a confirm message (the onbeforeunload event seems to + * work in most browsers.) + * + * This supersedes any previous onbeforeunload handler. If there was a handler before, it is + * restored when you execute the returned function. + * + * var allowCloseWindow = mw.confirmCloseWindow(); + * // ... do stuff that can't be interrupted ... + * allowCloseWindow(); + * + * @param {Object} [options] + * @param {string} [options.namespace] Namespace for the event registration + * @param {string} [options.message] + * @param {string} options.message.return The string message to show in the confirm dialog. + * @param {Function} [options.test] + * @param {boolean} [options.test.return=true] Whether to show the dialog to the user. + * @return {Function} Execute this when you want to allow the user to close the window + */ + mw.confirmCloseWindow = function ( options ) { + var savedUnloadHandler, + mainEventName = 'beforeunload', + showEventName = 'pageshow'; + + options = $.extend( { + message: mw.message( 'mwe-prevent-close' ).text(), + test: function () { return true; } + }, options ); + + if ( options.namespace ) { + mainEventName += '.' + options.namespace; + showEventName += '.' + options.namespace; + } + + $( window ).on( mainEventName, function () { + if ( options.test() ) { + // remove the handler while the alert is showing - otherwise breaks caching in Firefox (3?). + // but if they continue working on this page, immediately re-register this handler + savedUnloadHandler = window.onbeforeunload; + window.onbeforeunload = null; + setTimeout( function () { + window.onbeforeunload = savedUnloadHandler; + }, 1 ); + + // show an alert with this message + return options.message; + } + } ).on( showEventName, function () { + // Re-add onbeforeunload handler + if ( !window.onbeforeunload && savedUnloadHandler ) { + window.onbeforeunload = savedUnloadHandler; + } + } ); + + // return the function they can use to stop this + return function () { + $( window ).off( mainEventName + ' ' + showEventName ); + }; + }; +} )( mediaWiki, jQuery ); -- 2.20.1