User:Mr. Stradivarius/gadgets/ConfirmRollback.js

//

/* ConfirmRollback

*

* This script allows you to customise your rollback links. You can either

* allow them, hide them, or ask for confirmation when you click them.

* Furthermore, you can have different rollback settings for different pages,

* and different settings for mobile and desktop devices.

*

* To install, add the following to your Special:MyPage/skin.js:

importScript('User:Mr. Stradivarius/gadgets/ConfirmRollback.js') // Linkback: User:Mr. Stradivarius/gadgets/ConfirmRollback.js

* See User:Mr. Stradivarius/gadgets/ConfirmRollback for documentation.

*/

mw.loader.using( [ 'oojs-ui' ], function () {

"use strict";

// Get a rollback status of either "hide", "confirm" or "allow" for a given

// page type and device type.

function getRollbackStatus ( pageType, deviceType ) {

var defaultConfig = {

desktop: {

watchlist: 'confirm',

contributions: 'allow',

recentchanges: 'allow',

relatedchanges: 'allow',

history: 'allow',

diff: 'allow'

},

mobile: {

watchlist: 'confirm',

contributions: 'confirm',

recentchanges: 'confirm',

relatedchanges: 'confirm',

history: 'confirm',

diff: 'confirm'

}

};

var scriptConfig = window.ConfirmRollback || {};

var deviceDefaults = defaultConfig[ deviceType ];

function resolveRollbackStatus ( cfg ) {

// resolve the config object recursively. We need to be recursive

// because the config syntax is very flexible.

var ret;

if ( typeof( cfg ) === 'object' ) {

if ( cfg.mobile || cfg.desktop ) {

return resolveRollbackStatus( cfg[ deviceType ] );

} else {

ret = cfg[ pageType ];

}

} else if ( cfg === 'hide' || cfg === 'allow' || cfg === 'confirm' ) {

ret = cfg;

}

return ret || deviceDefaults[ pageType ] || 'confirm';

}

return resolveRollbackStatus( scriptConfig );

}

// Makes the message that says something like

// "Revert 5 edits by Mr. Stradivarius?"

function makeRollbackMessage( event ) {

var targetText = $( event.target ).text();

var count = targetText.match(/\d/) ? targetText.match(/\d+/)[0] : null;

var edits = count ? count + ' edits' : 'edit';

var user = mw.util.getParamValue( 'from', event.target.href );

return 'Roll back ' + edits + ' by ' + user + '?';

}

// Handles rollback clicks on mobile devices. This uses the default browser

// window.confirm dialog, as OO-js UI windows on mobile are tiny and

// unreadable.

function handleMobileClicks( $rollbackLinks ) {

$rollbackLinks.click( function ( event ) {

var message = makeRollbackMessage( event );

if ( !confirm( message ) ) {

return event.preventDefault();

}

} );

}

// Handle rollback clicks on desktop. This uses OO-js UI, which looks

// pretty on desktops.

function handleDesktopClicks( $rollbackLinks ) {

// Initialize the dialog object.

var confirmationDialog = new OO.ui.MessageDialog();

var windowManager = new OO.ui.WindowManager();

$( 'body' ).append( windowManager.$element );

windowManager.addWindows( [ confirmationDialog ] );

$rollbackLinks.click( function ( event ) {

event.preventDefault();

var message = makeRollbackMessage( event );

windowManager.openWindow( confirmationDialog, {

title: 'Confirm rollback',

message: message,

actions: [

{ action: 'rollback', label: 'OK', flags: [ 'primary', 'destructive' ] },

{ label: 'Cancel' }

]

} ).then( function ( opening ) {

opening.then( function ( opened ) {

opening.then( function ( closing, data ) {

// The dialog is open. Check for the rollback action

// and if detected, follow the original rollback link

// URL.

if ( data && data.action === 'rollback' ) {

window.open( $( event.target ).attr( 'href' ), '_top' );

}

} );

} );

} );

} );

}

var pageType, deviceType, rollbackStatus, $rollbackLinks;

var mwConfig = mw.config.get( ['wgCanonicalSpecialPageName', 'wgAction'] );

// Find the page type, and exit if we are not viewing a page on which

// rollback links can appear.

if ( mwConfig.wgCanonicalSpecialPageName === 'Watchlist' ) {

pageType = 'watchlist';

} else if ( mwConfig.wgCanonicalSpecialPageName === 'Contributions' ) {

pageType = 'contributions';

} else if ( mwConfig.wgCanonicalSpecialPageName === 'Recentchanges' ) {

pageType = 'recentchanges';

} else if ( mwConfig.wgCanonicalSpecialPageName === 'Recentchangeslinked' ) {

pageType = 'relatedchanges';

} else if ( mwConfig.wgAction === 'history' ) {

pageType = 'history';

} else if ( $( location ).attr( 'href' ).indexOf( '&diff' ) !== -1 ) {

pageType = 'diff';

} else {

return;

}

deviceType = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent ) ? 'mobile' : 'desktop';

rollbackStatus = getRollbackStatus( pageType, deviceType );

$rollbackLinks = $( '.mw-rollback-link' );

if ( rollbackStatus === 'hide' ) {

$rollbackLinks.css( 'display', 'none' );

} else if ( rollbackStatus === 'allow' ) {

$rollbackLinks.css( 'display', 'inline' );

} else if ( rollbackStatus === 'confirm' ) {

// Display rollback links if they are hidden.

$rollbackLinks.css( 'display', 'inline' );

// Handle rollback clicks.

if ( deviceType === 'mobile' ) {

handleMobileClicks( $rollbackLinks );

} else {

handleDesktopClicks( $rollbackLinks );

}

}

} );

//