yoohoo! hot sauce please
10:27, 7 September 2026 (UTC)
MediaWiki:Gadget-UserHighlighter.js
From 2swagg wiki
Jump to navigationJump to search
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.
/* Markblocked and Highlight Usergroups */
( function ( $, mw ) {
var mwConfig = mw.config.get( [
'wgAction',
'wgArticlePath',
'wgDBname',
'wgNamespaceIds',
'wgScript',
'wgServer',
'wgUserLanguage'
] );
// Default fallback tooltip if none is defined
var mbTooltip = window.mbTooltip || 'Blocked ($1) by $2: $3 ($4 ago)';
// Get all aliases for User: and Message_Wall:
// NOTE: Namespace 3 (User_talk) has been removed so talk pages are not affected.
var userNS = [];
for ( var ns in mwConfig.wgNamespaceIds ) {
if ( mwConfig.wgNamespaceIds[ ns ] === 2 || mwConfig.wgNamespaceIds[ ns ] === 1200 ) {
userNS.push( mw.util.escapeRegExp(ns.replace( /_/g, ' ' )) + ':' );
}
}
//RegExp for links
var articleRX = new RegExp(
'^(?:' + mwConfig.wgServer + ')?' +
mwConfig.wgArticlePath.replace( '$1', '' ) + '([^?#]+)'
);
var scriptRX = new RegExp(
'^(?:' + mwConfig.wgServer + ')?' +
mwConfig.wgScript + '\\?title=([^#&]+)'
);
var userTitleRX, waitingCSS;
//--------Init functions
function init( specialContribs ) {
userTitleRX = new RegExp( '^'
+ '(' + userNS.join( '|' )
+ '|' + specialContribs + '\\/|Special:Contributions\\/'
+ ')'
+ '([^\\/#]+)$', 'i' );
// Added "a." prefix and "!important" to ensure it overrides standard wiki link colors
mw.util.addCSS(
'.mediawiki .user-blocked-partial {' + ( window.mbPartialStyle || 'opacity: 1' ) + '}\n'
+ '.mediawiki .user-blocked-temp {' + ( window.mbTempStyle || 'opacity: 0.7; text-decoration: line-through !important' ) + '}\n'
+ '.mediawiki .user-blocked-indef {' + ( window.mbIndefStyle || 'opacity: 0.4; font-style: italic; text-decoration: line-through !important' ) + '}\n'
+ '.mediawiki .user-blocked-tipbox {' + ( window.mbTipBoxStyle || 'font-size:85%; background:#FFFFF0; border:1px solid #FEA; padding:0 0.3em; color:#AAA' ) + '}\n'
);
waitingCSS = mw.util.addCSS( 'a.userlink {opacity:' + ( window.mbLoadingOpacity || 0.85 ) + '}' );
waitingCSS.disabled = true;
if ( window.mbNoAutoStart ) {
$( function () {
var portletLink = mw.util.addPortletLink( 'p-tb, .mytools', '#', 'Mark blocked users', 'ca-showblocks' );
$( portletLink ).click( function( event ) {
event.preventDefault();
markBlocked();
} );
} );
} else {
markBlocked();
mw.hook( 'wikipage.content' ).add( markBlocked );
}
window.ajaxCallAgain = window.ajaxCallAgain || [];
window.ajaxCallAgain.push( markBlocked );
}
function initSpecialContribsString() {
var promise = $.Deferred();
var storageKey = 'MarkBlocked-specialcontribs_' + mwConfig.wgDBname;
var specialContribs;
try { specialContribs = localStorage.getItem( storageKey ); } catch ( ignore ) {}
if ( specialContribs ) return promise.resolve( specialContribs );
$.getJSON( mw.util.wikiScript( 'api' ) , {
action: 'parse', format: 'json', prop: 'text',
text: '<span class="contribs">[[Special:Contributions]]</span>',
disablepp: '', maxage: 30 * 86400, smaxage: 30 * 86400
} ).done( function ( data ) {
var $parsed = $( data.parse.text['*'] );
var specialContribs = $parsed.find( '.contribs > a' ).attr( 'title' );
promise.resolve( specialContribs );
try { localStorage.setItem( storageKey, specialContribs ); } catch ( ignore ) {}
}).fail(function() {
promise.resolve( 'Special:Contributions' ); // Fallback on failure
});
return promise;
}
//--------Main function
function markBlocked( container ) {
var contentLinks = ( container || mw.util.$content || $('#mw-content-text')).find( 'a' )
.not( '.editsection > a, .mw-editsection > a' )
.add( '#ca-nstab-user a, li[data-id="profile"] > a' );
var userLinks = {};
var url, rlUrl, ma, pgTitle, user;
contentLinks.each( function( i, lnk ) {
url = $( lnk ).attr( 'href' );
rlUrl = $( lnk ).data( 'uncrawlableUrl' );
if ( rlUrl ) url = atob( rlUrl );
if ( !url || url.charAt( 0 ) !== '/' ) return;
if ( $( lnk ).hasClass( 'userlink' ) ) return;
if ( ma = articleRX.exec( url ) ) {
pgTitle = ma[ 1 ];
} else if ( ma = scriptRX.exec( url ) ) {
pgTitle = ma[ 1 ];
} else {
return;
}
pgTitle = decodeURIComponent( pgTitle ).replace( /_/g, ' ' );
user = userTitleRX.exec( pgTitle );
if ( !user ) return;
user = user[ 2 ];
$( lnk ).addClass( 'userlink' );
if ( !userLinks[ user ] ) userLinks[ user ] = [];
userLinks[ user ].push (lnk );
} );
var users = [];
for ( var u in userLinks ) users.push( u );
if ( users.length === 0 ) return;
var serverTime, apiRequests = 0;
waitingCSS.disabled = false;
while ( users.length > 0 ) {
apiRequests++;
var chunk = users.splice( 0, 50 ).join( '|' );
$.post(
mw.util.wikiScript( 'api' ) + '?format=json&action=query',
{
list: 'blocks|users',
bklimit: 100,
bkusers: chunk,
bkprop: 'user|by|timestamp|expiry|reason|flags',
ususers: chunk,
usprop: 'groups'
},
markLinks
);
}
//callback: receive data and mark links
function markLinks( resp, status, xhr ) {
serverTime = new Date( xhr.getResponseHeader('Date') );
var list, blk, clss, blTime, tip, links, lnk, blPartial;
if ( !resp || !resp.query ) return;
// 1. Process user groups
if ( resp.query.users ) {
var groupHierarchy = ['bureaucrat', 'staff', 'bot', 'sysop', 'Helper', 'moderator'];
for ( var j = 0; j < resp.query.users.length; j++ ) {
var usr = resp.query.users[ j ];
if ( !usr.groups ) continue;
var appliedClass = '';
for ( var g = 0; g < groupHierarchy.length; g++ ) {
if ( usr.groups.indexOf( groupHierarchy[ g ] ) > -1 ) {
appliedClass = 'user-group-' + groupHierarchy[ g ];
break;
}
}
if ( appliedClass ) {
links = userLinks[ usr.name ];
if ( links ) {
for ( var k = 0; k < links.length; k++ ) {
$( links[ k ] ).addClass( appliedClass );
}
}
}
}
}
// 2. Process blocks
if ( resp.query.blocks ) {
list = resp.query.blocks;
for ( var i = 0; i < list.length; i++ ) {
blk = list[ i ];
blPartial = '';
if ( /^in/.test( blk.expiry ) ) {
clss = 'user-blocked-indef';
blTime = blk.expiry;
} else {
clss = 'user-blocked-temp';
blTime = inHours ( parseTS( blk.expiry ) - parseTS( blk.timestamp ) );
}
if ('partial' in blk) {
clss = 'user-blocked-partial';
blPartial = ' partial';
}
tip = mbTooltip
.replace( '$1', blTime )
.replace( '$2', blk.by )
.replace( '$3', blk.reason )
.replace( '$4', inHours ( serverTime - parseTS( blk.timestamp ) ) );
links = userLinks[ blk.user ];
if ( links ) {
for ( var k = 0; k < links.length; k++ ) {
lnk = $( links[ k ] ).addClass( clss );
if ( window.mbTipBox ) {
$( '<span class=user-blocked-tipbox>#</span>' ).attr( 'title', tip ).insertBefore( lnk );
} else {
lnk.attr( 'title', (lnk.attr( 'title' ) || '') + '; ' + tip );
}
}
}
}
}
if ( --apiRequests === 0 ) {
waitingCSS.disabled = true;
$( '#ca-showblocks' ).remove();
}
}
}
//--------AUX functions
function parseTS( ts ) {
var m = ts.replace( /\D/g, '' ).match( /(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ );
return new Date ( Date.UTC( m[ 1 ], m[ 2 ] - 1, m[ 3 ], m[ 4 ], m[ 5 ], m[ 6 ] ) );
}
function inHours( ms ) {
var mm = Math.floor( ms / 60000 );
if ( !mm ) return Math.floor( ms / 1000 ) + 's';
var hh = Math.floor( mm / 60 );
mm = mm % 60;
var dd = Math.floor( hh / 24 );
hh = hh % 24;
if ( dd ) return dd + ( dd < 10 ? '.' + zz( hh ) : '' ) + 'd';
return hh + ':' + zz( mm );
}
function zz( v ) {
if ( v <= 9 ) v = '0' + v;
return v;
}
//start on some pages
switch ( mwConfig.wgAction ) {
case 'edit':
case 'submit':
case 'delete':
break;
default:
$.when(
initSpecialContribsString(),
mw.loader.using( 'mediawiki.util' )
).done( init );
}
}( jQuery, mediaWiki ) );