MediaWiki:Gadget-DeluxeHistory.js

Note : après avoir publié vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

  • Firefox / Safari : maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou appuyez sur Ctrl + F5 ou Ctrl + R (⌘ + R sur un Mac).
  • Google Chrome : appuyez sur Ctrl + Maj + R (⌘ + Shift + R sur un Mac).
  • Internet Explorer / Edge : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl + F5.
  • Opera : appuyez sur Ctrl + F5.
/**
 * Nom : DeluxeHistory
 * Implémentation originale de Dake, basée sur du code Ajax de GôTô
 * Réécriture complète par Dr Brains et Od1n, avec améliorations de Ltrlg
 *
 * {{Catégorisation JS|DeluxeHistory}}
 */

/*global mw, $ */

// La dépendance 'user' assure le chargement du common.js utilisateur avant ce script, pour la configuration.

mw.loader.using(['user', 'user.options', 'mediawiki.api', 'mediawiki.storage'], function () {
	$(function ($) {
		'use strict';

		var $content = $('#mw-content-text');
		var botMembers, sysopMembers;

		/////////////////////////////////////// LOCALSTORAGE ///////////////////////////////////////

		function storageGet(key) {
			var lastUpdate = mw.storage.get('HistoryDeluxe_' + key + '_lastUpdate');
			if (lastUpdate) {
				// cacheAge ne peut théoriquement pas être négatif, mais si jamais cela arrive (problème d'horloge)
				// le test "cacheAge > 0" permet de ne pas se retrouver avec un cache indéfiniment valide
				var cacheAge = Date.now() - lastUpdate;
				if (cacheAge < 1000 * 3600 * 24 && cacheAge > 0) {
					return mw.storage.get('HistoryDeluxe_' + key);
				}
			}
			return null;
		}

		function storageSet(key, value) {
			mw.storage.set('HistoryDeluxe_' + key, value);
			mw.storage.set('HistoryDeluxe_' + key + '_lastUpdate', Date.now());
		}

		/////////////////////////////////////// RÉCUPÉRATION DE LA LISTE DES BOTS ET SYSOPS ///////////////////////////////////////

		function getUserList(group) {
			var storedValue = storageGet(group);
			return storedValue ? storedValue.split('|') : null;
		}

		function updateUserList(group, doneCallback, userList, userContinue) {
			if (!userList) { userList = []; }

			var paramUserGroups = mw.config.get('wgUserGroups');
			var APILimit = paramUserGroups.indexOf('sysop') > -1 || paramUserGroups.indexOf('bot') > -1
				? 5000 : 500;
			var params = {
				'action'  : 'query',
				'list'    : 'allusers',
				'aulimit' : APILimit,
				'augroup' : group,
			};
			if (userContinue) {
				$.extend(params, userContinue);
			}

			new mw.Api()
				.get(params)
				.done(function (data) {
					$.each(data.query.allusers, function () {
						userList.push(this.name);
					});
					if (data['continue']) {
						updateUserList(group, doneCallback, userList, data['continue']);
					} else {
						storageSet(group, userList.join('|'));
						if (group === 'bot') {
							botMembers = userList;
						} else if (group === 'sysop') {
							sysopMembers = userList;
						}
						doneCallback();
					}
				});
		}

		/////////////////////////////////////// FONCTION DE TRAITEMENT DES LIENS ///////////////////////////////////////

		function userGroupClassName($lis) {
			var nsSpecial = mw.config.get('wgFormattedNamespaces')[-1] + ':';
			var watcherName = mw.config.get('wgUserName');

			function isUserIP(userlink) {
				// Les liens des IP sont de la forme « Spécial:Contributions/<IP> »
				return userlink.title.indexOf(nsSpecial) === 0;
			}

			function getUserClass(userlink) {
				var UserName = userlink.textContent;
				if (UserName === watcherName) { return 'UserIs-Self'; }
				if (botMembers.indexOf(UserName) > -1) { return 'UserIs-Bot'; }
				if (sysopMembers.indexOf(UserName) > -1) { return 'UserIs-Sysop'; }
				if (isUserIP(userlink)) { return 'UserIs-IP'; }
				return 'UserIs-User';
			}

			// Renvoie 'UserIs-…' si un seul type, 'UserIs-Mixed' sinon (RC "améliorée").
			// Colore les liens vers les utilisateurs pour disposer de la différentiation même si historique mixte.
			function getMultipleClassName(userlinks) {
				var className = '';
				$.each(userlinks, function () {
					var localClassName = getUserClass(this);
					this.classList.add(localClassName);
					if (className === '') {
						className = localClassName;
					} else if (className !== localClassName) {
						className = 'UserIs-Mixed';
					}
				});
				return className;
			}

			$lis.each(function () {
				var userlinks = this.getElementsByClassName('mw-userlink');
				if (userlinks.length === 1) {
					this.classList.add(getUserClass(userlinks[0]));
				} else if (userlinks.length > 1) {  // groupe des RC "améliorées"
					this.classList.add(getMultipleClassName(userlinks));
				}
			});
		}

		/////////////////////////////////////// FONCTIONS DE PARCOURS DES ÉLÉMENTS ///////////////////////////////////////

		function scan_first_ul() {
			userGroupClassName($content.find('ul').eq(0).find('li'));
		}

		function scan_ul_special_li() {
			userGroupClassName($content.find('ul.special li'));
		}

		function scan_td() {
			userGroupClassName($content.find('td'));
		}

		/////////////////////////////////////// FONCTIONS DE SÉLECTION DES FILTRES ///////////////////////////////////////

		function process_History() {
			userGroupClassName($content.find('#pagehistory, .flow-board-history').find('li'));
		}

		function process_Watchlist() {
			if (mw.user.options.get('usenewrc')) {
				scan_td(); // Liste de suivi "améliorée"
			} else {
				scan_ul_special_li(); // Liste de suivi normale
			}
		}

		function process_Recentchanges() {
			if (mw.user.options.get('usenewrc')) {
				scan_td(); // RC "améliorées"
			} else {
				scan_ul_special_li(); // RC normales
			}
		}

		function process_Recentchangeslinked() {
			if (mw.user.options.get('usenewrc')) {
				scan_td(); // RC liées "améliorées"
			} else {
				scan_ul_special_li(); // RC liées normales
			}
		}

		function process_Newpages() {
			scan_first_ul();
			mw.loader.addStyleTag('.not-patrolled { text-decoration: underline; }');
		}

		function process_Log() {
			scan_first_ul();
		}

		function process_AbuseLog() {
			scan_first_ul();
		}

		function process_OtherPages() {
			scan_ul_special_li();
		}

		/////////////////////////////////////// LANCEMENTS ///////////////////////////////////////

		var classesApplied = false;
		var classesCallback;

		function applyClasses() {
			if (botMembers && sysopMembers && !classesApplied) {
				classesApplied = true;
				classesCallback();
			}
		}

		function processIfEnabled(pageType, callback) {
			var enabled = $.extend({
				'history': true,
				'watchlist': true,
				'recentchanges': true,
				'recentchangeslinked': true,
				'newpages': true,
				'log': true,
				'abuseLog': true,
				'other': true
			}, window.DeluxeHistory_Enabled);

			if (enabled[pageType]) {
				if (!mw.user.options.get('gadget-DeluxeHistory')) {
					mw.loader.load('/w/index.php?title=MediaWiki:Gadget-DeluxeHistory.css&action=raw&ctype=text/css', 'text/css');
				}

				classesCallback = callback;

				botMembers = getUserList('bot');
				if (!botMembers) {
					updateUserList('bot', applyClasses);
				}

				sysopMembers = getUserList('sysop');
				if (!sysopMembers) {
					updateUserList('sysop', applyClasses);
				}

				applyClasses();
			}
		}

		/////////////////////////////////////// INITIALISATION ///////////////////////////////////////

		var paramAction = mw.config.get('wgAction');
		var paramCanonicalSpecialPageName = mw.config.get('wgCanonicalSpecialPageName');

		if (paramAction === 'history') {
			processIfEnabled('history', process_History);

		} else if (paramCanonicalSpecialPageName === 'Watchlist') {
			processIfEnabled('watchlist', process_Watchlist);

		} else if (paramCanonicalSpecialPageName === 'Recentchanges') {
			processIfEnabled('recentchanges', process_Recentchanges);

		} else if (paramCanonicalSpecialPageName === 'Recentchangeslinked') {
			processIfEnabled('recentchangeslinked', process_Recentchangeslinked);

		} else if (paramCanonicalSpecialPageName === 'Newpages') {
			processIfEnabled('newpages', process_Newpages);

		} else if (paramCanonicalSpecialPageName === 'Log') {
			processIfEnabled('log', process_Log);

		} else if (paramCanonicalSpecialPageName === 'AbuseLog') {
			processIfEnabled('abuseLog', process_AbuseLog);

		} else if ($content.find('.special').length) {
			processIfEnabled('other', process_OtherPages);
		}

	});
});