<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.2swagg.net/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-UserHighlighter.js</id>
	<title>MediaWiki:Gadget-UserHighlighter.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.2swagg.net/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-UserHighlighter.js"/>
	<link rel="alternate" type="text/html" href="https://wiki.2swagg.net/index.php?title=MediaWiki:Gadget-UserHighlighter.js&amp;action=history"/>
	<updated>2026-09-29T01:05:19Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://wiki.2swagg.net/index.php?title=MediaWiki:Gadget-UserHighlighter.js&amp;diff=1141&amp;oldid=prev</id>
		<title>JANNY: Created page with &quot;/* Markblocked and Highlight Usergroups */  ( function ( $, mw ) {  	var mwConfig = mw.config.get( [ 		&#039;wgAction&#039;, 		&#039;wgArticlePath&#039;, 		&#039;wgDBname&#039;, 		&#039;wgNamespaceIds&#039;, 		&#039;wgScript&#039;, 		&#039;wgServer&#039;, 		&#039;wgUserLanguage&#039; 	] );  	// Default fallback tooltip if none is defined 	var mbTooltip = window.mbTooltip || &#039;Blocked ($1) by $2: $3 ($4 ago)&#039;;  	// Get all aliases for User: and Message_Wall: 	// NOTE: Namespace 3 (User_talk) has been removed so talk pages are not affected....&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.2swagg.net/index.php?title=MediaWiki:Gadget-UserHighlighter.js&amp;diff=1141&amp;oldid=prev"/>
		<updated>2026-09-07T10:01:49Z</updated>

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