MediaWiki:Gadget-DeluxeHistory.js

Un livre de Wikilivres.
Aller à : navigation, rechercher
/* [[Catégorie:MediaWiki:Fonction Monobook en JavaScript|DeluxeHistory.js]] */
/**
 * 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
 * Dépendances :
 *  — les habituelles implicites 'mediawiki' & 'jquery' ;
 *  — 'mediawiki.util' (fonctions mw.util.*) ;
 *  — 'user' (assure le chargement du common.js avant ce script, pour la configuration) ;
 *  — 'user.options' (pour tester si le gadget est coché dans les préférences) ;
 * {{Catégorisation JS|DeluxeHistory}}
 */

/*global document, localStorage, mw, $ */
/*jslint vars: true, plusplus: true */

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

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

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

		var supportLocalStorage;

		function initLocalStorage() {
			try {
				localStorage.setItem('modernizr', 'modernizr');
				localStorage.removeItem('modernizr');
				supportLocalStorage = true;
			} catch (e) {
				supportLocalStorage = false;
			}

			// nettoyage d'une ancienne clé (ajouté le 2017-11-13)
			if (supportLocalStorage) {
				localStorage.removeItem('HistoryDeluxe_lastUpdate');
			}
		}

		function storageGet(key) {
			if (supportLocalStorage) {
				var lastUpdate = localStorage.getItem('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 localStorage.getItem('HistoryDeluxe_' + key);
					}
				}
			}
			return null;
		}

		function storageSet(key, value) {
			if (supportLocalStorage) {
				localStorage.setItem('HistoryDeluxe_' + key, value);
				localStorage.setItem('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 = {
				'format'  : 'json',
				'action'  : 'query',
				'list'    : 'allusers',
				'aulimit' : APILimit,
				'augroup' : group,
			};
			if (userContinue) {
				$.extend(params, userContinue);
			}

			$.get(mw.util.wikiScript('api'), params, 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;
					} else if (group === 'patroller') {
						patrollerMembers = 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 (patrollerMembers.indexOf(UserName)   -1) { return 'UserIs-Patroller'; }
				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.util.addCSS('.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 && patrollerMembers && !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' );
				}

				initLocalStorage();
				classesCallback = callback;

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

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

				patrollerMembers = getUserList('patroller');
				if (!sysopMembers) {
					updateUserList('patroller', 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);
		}

	});
});