User:Hoo man/smart rollback.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/*
* [[m:user:Hoo man]]; Version 3.2; 2022-10-15;
* Provides several useful functions for rollback (custom edit summary, mark as bot edits and mass revert)
* Requires rollback permissions (and 'markbotedits' for the bot option)
* Tested in IE and FF with vector and monobook, uses my (Hoo man) wiki tools (shared.js)
*
* DO NOT COPY AND PASTE, instead see https://meta.wikimedia.org/wiki/User:Hoo_man/Scripts/Smart_rollback
*/
/*global hoo, mw, smartRollbackConfig, disable_smart_rollback, confirm */
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:false, undef:true, unused:true, curly:true, browser:true, jquery:true, indent:4, maxerr:50, loopfunc:true, white:false */
mw.loader.using( [ 'mediawiki.util', 'jquery.ui', 'jquery.spinner', 'mediawiki.api' ], function() {
"use strict";
var config = {
// Default config
enableMarkbotedits : null,
watchPages : 'nochange',
oneClickBotLinks : false,
availableLangs : ['en', 'et', 'de', 'ja', 'ar']
},
lastSummary = false,
$dialog;
// Commit rollback
function commitRollback( params, elem, done ) {
var api = new mw.Api();
api.post( params )
// Remove the rollback link(s) (the one click bot links as well)
.done(
function() {
$( elem )
.parent()
.parent()
.find( '.mw-rollback-link' )
.hide();
}
)
// Always go on even if an error occurs
.always( done );
}
// Delete a list of pages
function rollbackRevisions( rollbacks ) {
var rollback = rollbacks.shift();
commitRollback(
rollback.params,
rollback.elem,
function() {
if ( rollbacks.length ) {
rollbackRevisions( rollbacks );
} else {
// Reload the page after the work is done
window.location.reload();
}
}
);
}
// Whether the user is in the given group
function isInGroup( group ) {
return ( $.inArray( group, mw.config.get( 'wgUserGroups' ) ) !== -1 );
}
// Whether the user is in the given global group
function isInGlobalGroup( group ) {
return ( mw.config.exists( 'wgGlobalGroups' ) && $.inArray( group, mw.config.get( 'wgGlobalGroups' ) ) !== -1 );
}
// This function shows an animation while changes are reverted
function showProcess( selector ) {
var $loadSpinner = $.createSpinner()
.addClass( 'smartRollback-spinner' );
$( selector )
.html( $loadSpinner );
}
// Adding the toolbar link and creating the one click bot rollback links (if enabled)
// Executed after i18n has been loaded
function main() {
var hasRollbackLink = false,
i;
// Is there at least one rollback link on the page?
var spans = mw.util.$content[0].getElementsByTagName( 'span' );
for ( i = 0; i < spans.length; i++ ) {
if ( spans[i].className === 'mw-rollback-link' ) {
hasRollbackLink = true;
break;
}
}
if ( !hasRollbackLink ) {
return;
}
// There is a rollback link so we add a visible link
hoo.addToolLink(
mw.message( 'hoo-smartRollback-toolbarText' ).escaped(),
openWindow,
'',
config.toolLinkMethod
);
// Edit summaries
if ( typeof smartRollbackConfig === 'undefined' || typeof smartRollbackConfig.editSummaries === 'undefined' ) {
// smartRollbackConfig.editSummaries isn't set, so we take the default out of the lang file
config.editSummaries = mw.messages.get( 'hoo-smartRollback-editSummaries' );
} else {
config.editSummaries = smartRollbackConfig.editSummaries;
}
if( config.oneClickBotLinks ) {
$( '.mw-rollback-link' ).each( function() {
var $rollbackLink = $( this );
$rollbackLink.parent().append(
$rollbackLink
.clone()
.addClass( 'mw-rollback-link-bot' )
)
.find( '.mw-rollback-link-bot a' )
.attr( 'href', $rollbackLink.find( 'a' ).attr( 'href' ) + '&bot=true' )
.text( $rollbackLink.find( 'a' ).text() + ' (B)' );
} );
}
}
function openWindow() {
var html, i;
html = '<div id="smartRollbackDialog"><form name="smartRollbackForm" id="smartRollbackForm">' +
mw.message( 'hoo-smartRollback-editSummary' ).escaped() + '<br /><select name="editSummarySelect" style="width: 97%;">' +
'<option value="useDefault">' + mw.message( 'hoo-smartRollback-useDefault' ).escaped() + '</option>';
for ( i in config.editSummaries ) {
if ( typeof config.editSummaries[i] === 'string' && i !== 'other' && i !== 'useDefault' ) {
// Filter out prototype functions and deprecated strings
html += '<option value="' + config.editSummaries[i] + '">' + config.editSummaries[i] + '</option>';
}
}
html += '<option value="otherSummary" id="smartRollbackUseCustomEditSummary">' + mw.message( 'hoo-smartRollback-other' ).escaped() + '</option>' +
'</select><br />' +
'<small>' + mw.message( 'hoo-smartRollback-editSummaryInfo' ).escaped() + '</small><br /><br />' +
mw.message( 'hoo-smartRollback-customEditSummary' ).escaped() + '<br /><input name="editSummaryOther" id="smartRollbackEditSummaryOther" type="text" style="width: 97%;"><br /><br />';
if ( config.enableMarkbotedits !== false && ( isInGroup( 'sysop' ) || isInGlobalGroup( 'Global_sysops' ) || isInGlobalGroup( 'Global_rollback' ) || isInGlobalGroup( 'steward' ) || config.enableMarkbotedits === true ) ) {
html += mw.message( 'hoo-smartRollback-markbotedits' ).escaped() + '<br /><label for="hoo-smartRollback-yes">' + mw.message( 'hoo-smartRollback-yes' ).escaped() + ':</label><input type="radio" name="bot" value="true" id="hoo-smartRollback-yes">' +
'<label for="hoo-smartRollback-no">' + mw.message( 'hoo-smartRollback-no' ).escaped() + ':</label><input type="radio" name="bot" value="false" id="hoo-smartRollback-no" checked>';
}
html += '</form></div>';
if ( !$dialog ) {
$dialog = $( html ).dialog( {
title: mw.message( 'hoo-smartRollback-windowTitle' ).escaped(),
minWidth: 515,
minHeight: 175,
buttons: [
{
text: mw.message( 'hoo-smartRollback-windowMassButton' ).escaped(),
click: function( event ) { performAction( 'automatic', event.target ); }
},
{
text: mw.message( 'hoo-smartRollback-windowButton' ).escaped(),
click: function() { performAction( 'perHand' ); }
},
{
text: mw.message( 'hoo-smartRollback-closeButtonText' ).escaped(),
click: function() { $( this ).dialog( 'close' ); }
}
]
} );
} else {
$dialog
.html( html )
.dialog( "open" );
}
$( '#smartRollbackEditSummaryOther' ).click( function() {
document.getElementById( 'smartRollbackUseCustomEditSummary' ).selected = 'true';
} );
if ( lastSummary && lastSummary !== 'useDefault' ) {
// Set the custom edit summary to the one previosly selected
document.getElementById( 'smartRollbackEditSummaryOther' ).value = lastSummary;
document.getElementById( 'smartRollbackUseCustomEditSummary' ).selected = 'true';
}
}
// Collect all rollback links on page and change them or submit them (depends on mode)
// button: the element that triggered this function
function performAction( mode, button ) {
var smartRollbackForm = document.getElementById( 'smartRollbackForm' ),
rollbacks = [],
revertSummary, i, y, params, parameters;
// New edit summary
var summary = smartRollbackForm.editSummarySelect.value;
if ( summary === 'otherSummary' ) {
summary = smartRollbackForm.editSummaryOther.value;
}
// Mark as bot edits?
var bot = 'false';
if ( smartRollbackForm.bot ) {
for ( i = 0; i < smartRollbackForm.bot.length; i++ ) {
if ( smartRollbackForm.bot[i].checked ) {
bot = smartRollbackForm.bot[i].value;
}
}
}
// Get all rollback links on page
var links = document.getElementsByTagName( 'a' );
for(i = 0; i<links.length; i++) {
if(links[i].parentNode.className === 'mw-rollback-link') {
rollbacks.push( links[i] );
}
}
/* jQuery alternative:
$( '.mw-rollback-link a' ).each( function() {
if ( !$(this).parent().hasClass( 'mw-rollback-link-bot' ) ) {
rollbacks.push( $(this)[0] );
}
} );
*/
if ( mode === 'automatic' ) {
// Confirm the mass revert, if we have more than 1 rollback link
if ( rollbacks.length > 1 && !confirm( mw.message( 'hoo-smartRollback-confirm' ).escaped() ) ) {
return false;
}
// Substitute the button that was pressed with a spinner
showProcess( button );
}
// Iterate over all links
for ( i = 0; i < rollbacks.length; i++ ) {
// The actual revert summary (replaces $1 with the name of the user which has been reverted)
revertSummary = summary.replace( /\$1/g, mw.util.getParamValue( 'from', rollbacks[i].href ) );
// Remove old bot settings and summary
rollbacks[i].href = rollbacks[i].href.replace( '&bot=true', '' ).replace( /&summary=[^&]*/, '' );
if ( mode !== 'automatic' ) {
if ( summary !== 'useDefault' ) {
rollbacks[i].href += '&summary=' + encodeURIComponent( revertSummary );
}
if ( bot !== 'false' ) {
rollbacks[i].href += '&bot=true';
}
} else {
// Auto rollback: Rewrite URI for the API
parameters = rollbacks[i].href.substring( rollbacks[i].href.indexOf( '?' ) +1 );
parameters = parameters.replace( '&from=', '&user=' );
parameters = parameters.split( '&' );
params = [];
for ( y = 0; y < parameters.length; y++ ) {
params[ parameters[y].split( '=' )[0] ] = decodeURIComponent( parameters[y].split( '=' )[1].replace( /\+/g, ' ' ) );
}
params.watchlist = config.watchPages;
if ( bot !== 'false' ) {
params.markbot = true;
}
if ( summary !== 'useDefault' ) {
params.summary = revertSummary;
}
rollbacks[i] = {
params: params,
elem: rollbacks[i]
};
}
}
if ( mode === 'automatic' ) {
rollbackRevisions( rollbacks );
}
// Save edit summary to make the user able to change it
lastSummary = summary;
$dialog.dialog( 'close' );
}
// Init code
function init() {
var lang;
if ( typeof disable_smart_rollback !== 'undefined' && disable_smart_rollback ) {
return false;
}
if(typeof hoo === 'undefined') {
return false;
}
if ( typeof smartRollbackConfig !== 'undefined' ) {
$.extend( true, config, smartRollbackConfig );
}
if ( typeof config.toolLinkMethod === 'undefined' ) {
config.toolLinkMethod = hoo.config.toolLinkMethod;
}
if ( config.lang ) {
lang = config.lang;
} else {
lang = hoo.config.lang;
}
// Localization
if ( lang !== 'en' && $.inArray( lang, config.availableLangs ) !== -1 ) {
// Load from meta
$.ajax( {
url: '//meta.wikimedia.org/w/index.php?title=User:Hoo_man/lang/' + lang + '/smart_rollback.js&action=raw&ctype=text/javascript',
dataType: 'script',
cache: true
} )
.done( main );
} else {
// English is already set
main();
}
}
// Load the shared functions script if needed
if ( typeof hoo === 'undefined' || typeof hoo.addToolLink === 'undefined' ) {
$.ajax( {
url: '//meta.wikimedia.org/w/index.php?title=User:Hoo_man/functions.js&action=raw&ctype=text/javascript',
dataType: 'script',
cache: true
} )
.done(
function() {
$( document ).ready( init );
}
);
} else {
$( document ).ready( init );
}
} );
// Default lang
mw.messages.set( {
'hoo-smartRollback-toolbarText' : 'Smart rollback',
'hoo-smartRollback-windowTitle' : 'Smart rollback',
'hoo-smartRollback-windowButton' : 'Update links',
'hoo-smartRollback-windowMassButton' : 'Revert everything',
'hoo-smartRollback-editSummary' : 'Edit summary:',
'hoo-smartRollback-editSummaryInfo' : '($1 will be replaced with the user name of the reverted user)',
'hoo-smartRollback-customEditSummary' : 'Custom edit summary:',
'hoo-smartRollback-markbotedits' : 'Mark edits as bot edits:',
'hoo-smartRollback-confirm' : 'Do you really want to automatically rollback all pages?',
'hoo-smartRollback-yes' : 'Yes',
'hoo-smartRollback-no' : 'No',
'hoo-smartRollback-closeButtonText' : 'Close',
'hoo-smartRollback-useDefault' : 'Use the default edit summary',
'hoo-smartRollback-other' : 'Other ->',
'hoo-smartRollback-editSummaries' : [
'revert (vandalism)',
'revert (test edit)',
'revert'
]
} );