From: jenkins-bot Date: Thu, 21 Mar 2019 12:00:23 +0000 (+0000) Subject: Merge "Implement non-JS RollbackAction with form" X-Git-Tag: 1.34.0-rc.0~2438 X-Git-Url: http://git.cyclocoop.org/%28?a=commitdiff_plain;h=4eea7de733b8af21c23b1cc81df1f14cc5ea7b8e;hp=0a840327110951c64eac4b50a192a9b1d80e468b;p=lhc%2Fweb%2Fwiklou.git Merge "Implement non-JS RollbackAction with form" --- diff --git a/includes/Linker.php b/includes/Linker.php index 711b9dc782..a02d57df01 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -1769,6 +1769,8 @@ class Linker { } if ( $context->getUser()->getBoolOption( 'showrollbackconfirmation' ) ) { + $stats = MediaWikiServices::getInstance()->getStatsdDataFactory(); + $stats->increment( 'rollbackconfirmation.event.load' ); $context->getOutput()->addModules( 'mediawiki.page.rollback.confirmation' ); } diff --git a/resources/src/jquery/jquery.confirmable.js b/resources/src/jquery/jquery.confirmable.js index 028b4b9184..08bb601acc 100644 --- a/resources/src/jquery/jquery.confirmable.js +++ b/resources/src/jquery/jquery.confirmable.js @@ -36,6 +36,7 @@ * the first parameter and 'yes' or 'no' as the second. * @param {Function} [options.handler] Callback to fire when the action is confirmed (user clicks * the 'Yes' button). + * @param {string} [options.delegate] Optional selector used for jQuery event delegation * @param {string} [options.i18n] Text to use for interface elements. * @param {string} [options.i18n.space] Word separator to place between the three text messages. * @param {string} [options.i18n.confirm] Text to use for the confirmation question. @@ -49,117 +50,127 @@ $.fn.confirmable = function ( options ) { options = $.extend( true, {}, $.fn.confirmable.defaultOptions, options || {} ); - return this.on( options.events, function ( e ) { - var $element, $text, $buttonYes, $buttonNo, $wrapper, $interface, $elementClone, - interfaceWidth, elementWidth, rtl, positionOffscreen, positionRestore, sideMargin; + if ( options.delegate === null ) { + return this.on( options.events, function ( e ) { + $.fn.confirmable.handler( e, options ); + } ); + } - $element = $( this ); + return this.on( options.events, options.delegate, function ( e ) { + $.fn.confirmable.handler( e, options ); + } ); + }; - if ( $element.data( 'jquery-confirmable-button' ) ) { - // We're running on a clone of this element that represents the 'Yes' or 'No' button. - // (This should never happen for the 'No' case unless calling code does bad things.) - return; - } + $.fn.confirmable.handler = function ( event, options ) { + var $element, $text, $buttonYes, $buttonNo, $wrapper, $interface, $elementClone, + interfaceWidth, elementWidth, rtl, positionOffscreen, positionRestore, sideMargin; - // Only prevent native event handling. Stopping other JavaScript event handlers - // is impossible because they might have already run (we have no control over the order). - e.preventDefault(); + $element = $( event.target ); - rtl = $element.css( 'direction' ) === 'rtl'; - if ( rtl ) { - positionOffscreen = { position: 'absolute', right: '-9999px' }; - positionRestore = { position: '', right: '' }; - sideMargin = 'marginRight'; - } else { - positionOffscreen = { position: 'absolute', left: '-9999px' }; - positionRestore = { position: '', left: '' }; - sideMargin = 'marginLeft'; - } + if ( $element.data( 'jquery-confirmable-button' ) ) { + // We're running on a clone of this element that represents the 'Yes' or 'No' button. + // (This should never happen for the 'No' case unless calling code does bad things.) + return; + } - if ( $element.hasClass( 'jquery-confirmable-element' ) ) { - $wrapper = $element.closest( '.jquery-confirmable-wrapper' ); - $interface = $wrapper.find( '.jquery-confirmable-interface' ); - $text = $interface.find( '.jquery-confirmable-text' ); - $buttonYes = $interface.find( '.jquery-confirmable-button-yes' ); - $buttonNo = $interface.find( '.jquery-confirmable-button-no' ); + // Only prevent native event handling. Stopping other JavaScript event handlers + // is impossible because they might have already run (we have no control over the order). + event.preventDefault(); + + rtl = $element.css( 'direction' ) === 'rtl'; + if ( rtl ) { + positionOffscreen = { position: 'absolute', right: '-9999px' }; + positionRestore = { position: '', right: '' }; + sideMargin = 'marginRight'; + } else { + positionOffscreen = { position: 'absolute', left: '-9999px' }; + positionRestore = { position: '', left: '' }; + sideMargin = 'marginLeft'; + } - interfaceWidth = $interface.data( 'jquery-confirmable-width' ); - elementWidth = $element.data( 'jquery-confirmable-width' ); + if ( $element.hasClass( 'jquery-confirmable-element' ) ) { + $wrapper = $element.closest( '.jquery-confirmable-wrapper' ); + $interface = $wrapper.find( '.jquery-confirmable-interface' ); + $text = $interface.find( '.jquery-confirmable-text' ); + $buttonYes = $interface.find( '.jquery-confirmable-button-yes' ); + $buttonNo = $interface.find( '.jquery-confirmable-button-no' ); + + interfaceWidth = $interface.data( 'jquery-confirmable-width' ); + elementWidth = $element.data( 'jquery-confirmable-width' ); + } else { + $elementClone = $element.clone( true ); + $element.addClass( 'jquery-confirmable-element' ); + + elementWidth = $element.width(); + $element.data( 'jquery-confirmable-width', elementWidth ); + + $wrapper = $( '' ) + .addClass( 'jquery-confirmable-wrapper' ); + $element.wrap( $wrapper ); + + // Build the mini-dialog + $text = $( '' ) + .addClass( 'jquery-confirmable-text' ) + .text( options.i18n.confirm ); + + // Clone original element along with event handlers to easily replicate its behavior. + // We could fiddle with .trigger() etc., but that is troublesome especially since + // Safari doesn't implement .click() on links and jQuery follows suit. + $buttonYes = $elementClone.clone( true ) + .addClass( 'jquery-confirmable-button jquery-confirmable-button-yes' ) + .data( 'jquery-confirmable-button', true ) + .text( options.i18n.yes ); + if ( options.handler ) { + $buttonYes.on( options.events, options.handler ); + } + if ( options.i18n.yesTitle ) { + $buttonYes.attr( 'title', options.i18n.yesTitle ); + } + $buttonYes = options.buttonCallback( $buttonYes, 'yes' ); + + // Clone it without any events and prevent default action to represent the 'No' button. + $buttonNo = $elementClone.clone( false ) + .addClass( 'jquery-confirmable-button jquery-confirmable-button-no' ) + .data( 'jquery-confirmable-button', true ) + .text( options.i18n.no ) + .on( options.events, function ( e ) { + $element.css( sideMargin, 0 ); + $interface.css( 'width', 0 ); + e.preventDefault(); + } ); + if ( options.i18n.noTitle ) { + $buttonNo.attr( 'title', options.i18n.noTitle ); } else { - $elementClone = $element.clone( true ); - $element.addClass( 'jquery-confirmable-element' ); - - elementWidth = $element.width(); - $element.data( 'jquery-confirmable-width', elementWidth ); - - $wrapper = $( '' ) - .addClass( 'jquery-confirmable-wrapper' ); - $element.wrap( $wrapper ); - - // Build the mini-dialog - $text = $( '' ) - .addClass( 'jquery-confirmable-text' ) - .text( options.i18n.confirm ); - - // Clone original element along with event handlers to easily replicate its behavior. - // We could fiddle with .trigger() etc., but that is troublesome especially since - // Safari doesn't implement .click() on links and jQuery follows suit. - $buttonYes = $elementClone.clone( true ) - .addClass( 'jquery-confirmable-button jquery-confirmable-button-yes' ) - .data( 'jquery-confirmable-button', true ) - .text( options.i18n.yes ); - if ( options.handler ) { - $buttonYes.on( options.events, options.handler ); - } - if ( options.i18n.yesTitle ) { - $buttonYes.attr( 'title', options.i18n.yesTitle ); - } - $buttonYes = options.buttonCallback( $buttonYes, 'yes' ); - - // Clone it without any events and prevent default action to represent the 'No' button. - $buttonNo = $elementClone.clone( false ) - .addClass( 'jquery-confirmable-button jquery-confirmable-button-no' ) - .data( 'jquery-confirmable-button', true ) - .text( options.i18n.no ) - .on( options.events, function ( e ) { - $element.css( sideMargin, 0 ); - $interface.css( 'width', 0 ); - e.preventDefault(); - } ); - if ( options.i18n.noTitle ) { - $buttonNo.attr( 'title', options.i18n.noTitle ); - } else { - $buttonNo.removeAttr( 'title' ); - } - $buttonNo = options.buttonCallback( $buttonNo, 'no' ); - - // Prevent memory leaks - $elementClone.remove(); - - $interface = $( '' ) - .addClass( 'jquery-confirmable-interface' ) - .append( $text, options.i18n.space, $buttonYes, options.i18n.space, $buttonNo ); - $interface = options.wrapperCallback( $interface ); - - // Render offscreen to measure real width - $interface.css( positionOffscreen ); - // Insert it in the correct place while we're at it - $element.after( $interface ); - interfaceWidth = $interface.width(); - $interface.data( 'jquery-confirmable-width', interfaceWidth ); - $interface.css( positionRestore ); - - // Hide to animate the transition later - $interface.css( 'width', 0 ); + $buttonNo.removeAttr( 'title' ); } + $buttonNo = options.buttonCallback( $buttonNo, 'no' ); + + // Prevent memory leaks + $elementClone.remove(); + + $interface = $( '' ) + .addClass( 'jquery-confirmable-interface' ) + .append( $text, options.i18n.space, $buttonYes, options.i18n.space, $buttonNo ); + $interface = options.wrapperCallback( $interface ); + + // Render offscreen to measure real width + $interface.css( positionOffscreen ); + // Insert it in the correct place while we're at it + $element.after( $interface ); + interfaceWidth = $interface.width(); + $interface.data( 'jquery-confirmable-width', interfaceWidth ); + $interface.css( positionRestore ); + + // Hide to animate the transition later + $interface.css( 'width', 0 ); + } - // Hide element, show interface. This triggers both transitions. - // In a timeout to trigger the 'width' transition. - setTimeout( function () { - $element.css( sideMargin, -elementWidth ); - $interface.css( 'width', interfaceWidth ); - }, 1 ); - } ); + // Hide element, show interface. This triggers both transitions. + // In a timeout to trigger the 'width' transition. + setTimeout( function () { + $element.css( sideMargin, -elementWidth ); + $interface.css( 'width', interfaceWidth ); + }, 1 ); }; /** @@ -171,6 +182,7 @@ wrapperCallback: identity, buttonCallback: identity, handler: null, + delegate: null, i18n: { space: ' ', confirm: 'Are you sure?',