MediaWiki:Gadget-CatWatch.js

Da Semi del Verbo, l'enciclopedia dell'influenza del Vangelo sulla cultura

Nota: dopo aver pubblicato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.

  • Firefox / Safari: tieni premuto il tasto delle maiuscole Shift e fai clic su Ricarica, oppure premi Ctrl-F5 o Ctrl-R (⌘-R su Mac)
  • Google Chrome: premi Ctrl-Shift-R (⌘-Shift-R su un Mac)
  • Internet Explorer / Edge: tieni premuto il tasto Ctrl e fai clic su Aggiorna, oppure premi Ctrl-F5
  • Opera: premi Ctrl-F5.
/**
 * Gadget-CatWatch.js
 * Quando si visita [[Speciale:OsservatiSpeciali]] questo gadget vi aggiunge anche ogni voce
 * a cui è stata inserita una delle categorie monitorate (non la rimozione).
 *
 * Il funzionamento si basa sull'utilizzo di [[mw:API:Categorymembers]]:
 * quando l'utente visita [[Speciale:OsservatiSpeciali]] lo script ottiene la lista delle pagine
 * che si trovano in quel momento nelle categorie monitorate. Ogni pagina, se la data di categorizzazione
 * è presente in OsservatiSpeciali, viene allora aggiunta a quelle già presenti in OsservatiSpeciali.
 * 
 * Riscrittura da zero di:
 * http://it.wikipedia.org/w/index.php?title=Wikipedia:Monobook.js/Catwatch.js&oldid=52893797
 * che a sua volta lo importava da:
 * http://en.wikipedia.org/w/index.php?title=User:Ais523/catwatch.js&oldid=216824057
 *
 * @author https://it.wikipedia.org/wiki/Utente:Rotpunkt
 */
/* global mediaWiki, jQuery */

( function ( mw, $ ) {
	'use strict';

	var i18n = {
		en : {
			errorGet: 'Error retrieving',
			msgConfig: 'Category watchlist not found. Do you want to create a new one?',
			monthNames: [ "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
			category: 'Category'
		},
		it : {
			errorGet: 'Errore nel leggere',
			msgConfig: 'Non hai ancora una lista di categorie da controllare. Vuoi crearne una?',
			monthNames: ["","gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],
			category: 'Categoria' 
		}
	};
	// Massimo numero di pagine monitorate per categoria (max configurabile 500)
	var maxPagesInCategory = 100;
	// Configurazione utente
	var userConfig = 'User:' + mw.config.get( 'wgUserName' ) + '/CategorieOsservate.js';
	// Modello di configurazione
	var configModel = 'MediaWiki:Gadget-CatWatch.js/CategorieOsservateTemplate.js';

	/**
	 * Restituisce il messaggio con un certo identificativo, in una delle lingue supportate.
	 *
	 * @param {string} key - L'identificativo del messaggio
	 * @return {string} Il messaggio nella lingua configurata
	 */
	function msg( key ) {
		var msgs = i18n[ mw.config.get( 'wgUserLanguage' ) ] || i18n.en;
		return msgs[ key ];
	}
	
	/**
	 * Ottiene la variabile CategorieOsservate nel CategorieOsservate.js dell'utente.
	 *
	 * @param {function} categoryHandler - La funzione da richiamare con il risultato
	 */
	function getUserConfig( categoryHandler ) {
		$.ajax( {
			url: mw.config.get( 'wgScript' ),
			data: {
				title: userConfig,
				action: 'raw',
				ctype: 'text/javascript'
			},
			dataType: 'script',
			cache: false
		} )
			.done( function ( data ) {
				if ( window.CategorieOsservate !== undefined ) {
					if ( window.CategorieOsservate.length > 0 ) {
						categoryHandler( window.CategorieOsservate );
					}
				} else if ( confirm( '[CatWatch] ' + msg( 'msgConfig' ) ) ) {
					document.location = mw.config.get( 'wgScript' ) +
										'?action=edit&title=' + userConfig +
										'&preload=' + configModel;
				}
			} )
			.fail( function ( jqXHR, textStatus, errorThrown ) {
				if ( mw.util.getParamValue( 'debug' ) ) {
					alert( '[CatWatch] ' + msg( 'errorGet' ) + ' ' +
						   userConfig + ': '  + errorThrown );
				}
			} );
	}

	/**
	 * Ottiene la lista di pagine in una categoria.
	 *
	 * @param {string} name - Nome della categoria
	 * @param {string} end - Data di fine
	 * @param {function} pageHandler - La funzione da richiamare con il risultato
	 */
	function getCategoryPages( name, end, pageHandler ) {
		new mw.Api().get( {
			action: 'query',
			list: 'categorymembers',
			cmtitle: 'Category:' + name,
			cmlimit: maxPagesInCategory,
			cmprop: 'title|timestamp',
			cmsort: 'timestamp',
			cmdir: 'desc',
			cmend: end,
			format: 'json'
		} ).done( function ( data ) {
			pageHandler( data.query.categorymembers );
		} );
	}

	/**
	 * Funzione di utilità per parseWatchlistDOM, crea un timestamp
	 * a partire da una data nel formato di OsservatiSpeciali, es. 1 gen 2012.
	 *
	 * @param {string} text - Data nel formato di OsservatiSpeciali
	 * @return {string} Il timestamp risultante
	 */
	function makeTimestamp( text ) {
		var months, month, date = text.split( ' ' );
		months = msg( 'monthNames' );
		month = months.indexOf( date[ 1 ] );
		return month !== -1 ? ( date[ 2 ] + '-' + padleft0( month ) + '-' + padleft0( parseInt( date[ 0 ], 10 ) ) + 'T00:00:00Z' ) : null;
	}

	/**
	 * Parsifica l'elenco di pagine di OsservatiSpeciali in un object con
	 * - chiavi: le date presenti nella pagina
	 * - valori: un object contenente l'ora e l'elemento jQuery per quella riga
	 *
	 * @return {object} Object che contiene le pagine in OS, suddivise per data e ora
	 */
	function parseWatchlistDOM() {
		var date, ret = {};
		// ogni giorno è un <h4> 
		$( 'h4' ).each( function () {
			date = $( this ).text();
			ret[ date ] = [];
			// la pagina di ogni giorno è un <li> in un <ul class='special'>
			$( this ).next( 'ul.special' ).find( 'li' ).each( function () {
				ret[date].push( {
					time: $( this ).find( 'span.mw-changeslist-date' ).text(),
					el: $( this )
				} );
			} );
			// retrocompatibilità con il vecchio CatWatch: con la vista raggruppata
			// visualizzava le pagine del CatWatch al fondo del giorno
			if ( ret[ date ].length === 0 ) {
				ret[ date ].push( {
					time: '23:59',
					el: $( this ).next( 'div' ).find( 'table:last-child()' )
				} );
			}
		} );
		ret.oldestDate = date ? makeTimestamp( date ) : null;

		return ret;
	}

	/**
	 * Formatta un numero con uno zero iniziale se minore di 10.
	 *
	 * @param {string} num - Il numero da formattare
	 * @return {string} La stringa risultante
	 */
	function padleft0( num ) {
		return ( num < 10 ? '0' : '' ) + num;
	}

	/**
	 * Funzione di utilità per watchlistAdd, parsifica un timestamp in date (1 gen 2001) e time (01:23).
	 *
	 * @param {string} timestamp - Timestamp da parsificare
	 * @return {object} Oggetto con date e time parsificati separatamente
	 */
	function parseTimestamp( timestamp ) {
		var date, hours, minutes, months;

		date = new Date( timestamp );
		hours = date.getHours();
		minutes = date.getMinutes();
		months = msg( 'monthNames' );
		return {
			date: date.getDate() + ' ' + months[ date.getMonth() + 1 ] + ' ' +
				  date.getFullYear(),
			time: padleft0( hours ) + ':' + padleft0( minutes )
		};
	}

	/**
	 * Funzione di utilità per watchlistAdd, crea un nuovo elemento di OsservatiSpeciali.
	 *
	 * @param {string} title - Nome della pagina
	 * @param {string} time - Ora di categorizzazione
	 * @param {string} category - Nome categoria
	 * @return {jQuery} L'elemento jQuery da aggiungere alla pagina
	 */
	function createWatchlistEl( title, time, category ) {
		var url, urlcat, $cron, $cat, $page, $last;

		url = mw.config.get( 'wgScript' ) + '?title=' + title;
		urlcat = mw.config.get( 'wgArticlePath' ).replace( '$1', 'Category:' + category );
		$cron = $( '<a>' ).attr( 'href', url + '&action=history' ).text( 'cron' );
		$cat = $( '<a>' ).attr( 'href', urlcat ).text( msg( 'category' ) + ':' + category );
		$page = $( '<a>' ).attr( 'href', mw.config.get( 'wgArticlePath' )
					.replace( '$1', encodeURIComponent( title ) ) + '?redirect=no' ).text( title );
		$last = $( '<a>' ).attr( 'href', url + '&diff=last' ).text( 'last' );
		return $( '<li>' ).css( 'font-weight', 'bold' )
				.append( '(diff | ', $cron, ') . . ', $cat, '; ', time,
						 '  . . (+ ', $page, ' (', $last, '))' );
	}

	/**
	 * Aggiunge una pagina ad OsservatiSpeciali, se quel giorno è visualizzato.
	 *
	 * @param {Object} watchlist - Gli OsservatiSpeciali come parsificati da parseWatchlistDOM
	 * @param {string} page - La pagina da aggiungere agli OS
	 * @param {string} category - La categoria in cui quella pagina è stata categorizzata
	 */
	function watchlistAdd( watchlist, page, category ) {
		var ts, el, daypages, prepended = false;

		ts = parseTimestamp( page.timestamp );
		daypages = watchlist[ ts.date ];
		if ( daypages ) {
			el = createWatchlistEl( page.title, ts.time, category );
			// per tutte le pagine di quel giorno cerca quella col time antecedente 
			$.each( daypages, function ( i, entry ) {
				if ( ts.time > entry.time ) {
					entry.el.before( el );
					daypages.splice( i, 0, { time: ts.time, el: el } );
					prepended = true;
					return false;
				}
			} );
			if ( !prepended ) {
				daypages[ daypages.length - 1 ].el.after( el );
				daypages.push( { time: ts.time, el: el } );
			}
		}
	}

	$( function () {
		// Se la pagina corrente è Speciale:OsservatiSpeciali
		if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Watchlist' ) {
			mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] )
				.done( function () {
					// ottiene la lista delle categorie da monitorare.
					getUserConfig( function ( categories ) {
						// Parsifica OsservatiSpeciali.
						var watchlist = parseWatchlistDOM();
						// Per ogni categoria da monitorare
						$.each( categories, function ( i, category ) {
							// ottiene la lista delle pagine in quella categoria.
							getCategoryPages( category, watchlist.oldestDate, function ( categorymembers ) {
								// Per ogni pagina nella categoria monitorata
								$.each( categorymembers, function ( i, page ) {
									// aggiunge la pagina a OsservatiSpeciali.
									watchlistAdd( watchlist, page, category );
								} );
							} );
						} );
					} );
				} )
				.fail( function () {
					console.error( 'Impossibile avviare l\'accessorio CatWatch.' );
				} );
		}
	} );
}( mediaWiki, jQuery ) );