MediaWiki:Gadget-VFonLine.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-VFonLine.js
 * Aggiunge a Speciale:OsservatiSpeciali e Speciale:UltimeModifiche le funzionalità
 * dette 'Vandal Fighter on Line' (VFOL).
 * Riscrittura da zero di:
 * http://it.wikipedia.org/w/index.php?title=Wikipedia:Monobook.js/VFonLine.js&oldid=27133290
 * http://it.wikipedia.org/w/index.php?title=MediaWiki:Gadget-VFonLine.js&oldid=38709825
 *
 * @author https://it.wikipedia.org/wiki/Utente:Rotpunkt
 */
/* global mediaWiki, jQuery, OO */

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

	// Per retrocompatibilità con il vecchio gadget, whitelist e blacklist sono contenute in due cookie.
	// Le operazioni sui cookie sono isolate per poterle in futuro sostituire facilmente.

	/**
	 * Restituisce il contenuto del cookie 'wikiVFOL', che può valere 'abilitato' o 'disabilitato'.
	 *
	 * @return {string} Il contenuto del cookie 'wikiVFOL'
	 */	
	function getState() {
		return $.cookie( 'wikiVFOL' ) === 'abilitato' ? 'abilitato' : 'disabilitato';
	}

	/**
	 * Salva la stringa 'abilitato' o 'disabilitato' nel cookie 'wikiVFOL'.
	 *
	 * @param {string} state - la stringa da salvare.
	 */	
	function setState( state ) {
		$.cookie( 'wikiVFOL', state, { expires: 365, path: '/' } );
	}

	/**
	 * Restituisce il contenuto dei cookie per la whitelist e la blacklist.
	 *
	 * @param {string} id - L'identificativo per scegliere whitelist (vfol1) o blacklist(vfol2)
	 * @return {string} Il contenuto del cookie
	 */	
	function getList( id ) {
		var content = $.cookie( id === 'vfol1' ? 'wikiWhiteList' : 'wikiBlackList' );
		return content ? decodeURIComponent( content ) : '';
	}

	/**
	 * Salva la whitelist o la blacklist nei relativi cookie.
	 *
	 * @param {string} id - L'identificativo per scegliere whitelist (vfol1) o blacklist(vfol2)
	 * @param {string} content - Il contenuto del cookie
	 */	
	function setList( id, content ) {
		$.cookie( id === 'vfol1' ? 'wikiWhiteList' : 'wikiBlackList',
			encodeURIComponent( content ), { expires: 365, path: '/' } );
	}

	/**
	 * Crea la finestra di dialogo per modificare whitelist e blacklist.
	 *
	 * @return {Object} L'oggetto derivato da OO.ui.Dialog che rappresenta la finestra
	 */
	function buildConfigDialog() {
		var style = '.gvf-container-button { width: 100%; text-align: center; margin-top: 10px }';
		mw.util.addCSS( style );
		function ConfigDialog( config ) {
			ConfigDialog.parent.call( this, config );
		}
		OO.inheritClass( ConfigDialog, OO.ui.Dialog );
		ConfigDialog.static.name = 'configDialog';
		ConfigDialog.prototype.initialize = function () {
			var self = this;
			ConfigDialog.parent.prototype.initialize.call( this );
			var textInput = new OO.ui.MultilineTextInputWidget( {
				rows: 12
			} );
			var textInputLayout = new OO.ui.FieldLayout( textInput, {
				label: '',
				align: 'top' 
			} );
			var okButton = new OO.ui.ButtonWidget( {
				label: 'Salva',
			} ).on( 'click', function () {
				var text = textInput.getValue();
				text = text.replace( /^\s*/gm, '' );
				text = text.replace( /\s*$/gm, '' );
				setList( self.currId, text.replace( /\n/g, '@' ) );
				self.close();
			} );
			var cancelButton = new OO.ui.ButtonWidget( {
				label: 'Annulla'
			} ).on( 'click', function () {
				self.close();
			} );
			var buttons = new OO.ui.HorizontalLayout( {
				items: [ okButton, cancelButton ],
				classes: [ 'gvf-container-button' ]
			} );
			this.textInput = textInput;
			this.textInputLayout = textInputLayout;
			this.panelLayout = new OO.ui.PanelLayout( { padded: true, expanded: false } );
			this.panelLayout.$element.append( textInputLayout.$element, buttons.$element );
			this.$body.append( this.panelLayout.$element );
		};
		ConfigDialog.prototype.getBodyHeight = function () {
			return this.panelLayout.$element.outerHeight( true );
		};
		return new ConfigDialog( {
			size: 'small'
		} );
	}

	/**
	 * Aggiunge o rimuove i portlet link 'Modifica la whitelist' e 'Modifica la blacklist'.
	 *
	 * @param {boolean} visible - Se impostato a true aggiunge i portlet link, altrimenti li rimuove
	 */
	function togglePortletLinks( visible ) {
		var configDialog, windowManager;
		if ( visible ) {
			mw.util.addPortletLink( 'p-tb', '#', 'Modifica la whitelist', 'vfol1',
				'VFOL whitelist', '1', $( '#vfol' ).next( 'li' ).length ? $( '#vfol' ).next( 'li' ) : null );
			mw.util.addPortletLink( 'p-tb', '#', 'Modifica la blacklist', 'vfol2',
				'VFOL blacklist', '2', $( '#vfol1' ).next( 'li' ).length ? $( '#vfol1' ).next( 'li' ) : null );
			$( '#vfol1, #vfol2' ).click( function ( event ) {
				var id = $( this ).attr( 'id' );
				event.preventDefault();
				mw.loader.using( [ 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] )
					.done( function () {
						if ( !configDialog ) {
							configDialog = buildConfigDialog();
							windowManager = new OO.ui.WindowManager();
							$( 'body' ).append( windowManager.$element );
							windowManager.addWindows( [ configDialog ] );
						}
						configDialog.textInput.setValue( getList( id ).replace( /@/g, '\n' ) );
						configDialog.textInputLayout.setLabel( 'VFOL Configurazione ' + ( id === 'vfol1' ? 'whitelist' : 'blacklist' ) );
						configDialog.currId = id;
						windowManager.openWindow( configDialog );
					} )
					.fail( function () {
						console.error( 'Impossibile avviare l\'accessorio VFonLine.' );
					} );
			} );
		} else {
			$( '#vfol1, #vfol2' ).remove();
		}
	}

	/**
	 * Gestore del click sui link "wl" e "bl".
	 *
	 * @param {string} username - L'utente sul quale si è effettuato il click
	 * @param {string} action - La stringa su cui si è cliccato (+wl, -wl, +bl o -bl)
	 */
	function anchorHandler( username, action ) {
		var id = action.substring( 1, 3 ) === 'wl' ? 'vfol1' : 'vfol2';
		var users = getList( id ) === '' ? [] : getList( id ).split( '@' );
		var idx = $.inArray( username, users );
		if ( action.charAt( 0 ) === '+' &&  idx === -1 ) {
			users.unshift( username );
		} else if ( action.charAt( 0 ) === '-' && idx !== -1 ) {
			users.splice( idx, 1 );
		}
		if ( id === 'vfol1' ) {
			users.sort();
		}
		setList( id, users.join( '@' ) );
		window.location.reload();
	}

	/**
	 * Funzione di utilità per editWatchlist, modifica una entry
	 * in OsservatiSpeciali o UltimeModifiche.
	 *
	 * @param {string} $el - L'elemento jQuery da modificare
	 * @param {string[]} usersWl - Utenti nella whitelist
	 * @param {string[]} usersBl - Utenti nella blacklist
	 * @param {string} color - Colore da applicare alla riga, per le modifiche raggruppate
	 * @return {string} Il colore applicato alla riga, per le modifiche raggruppate
	 */
	function editEntry( $el, usersWl, usersBl, color ) {
		var $wl, $bl, inWl, inBl, username;
		$el.find( 'a.mw-userlink' ).each( function () {
			username = $( this ).text();
			inWl = $.inArray( username, usersWl ) !== -1;
			inBl = $.inArray( username, usersBl ) !== -1;
			// color
			if ( color === undefined ) {
				color = inWl ? '#ccffcc' :
						inBl ? '#ffcccc' :
						$el.hasClass( 'mw-changeslist-user-unregistered' ) ? '#ffffbb' : '';
			}
			$el.css( 'background-color', color );
			// anchors
			$wl = $( '<a>' ).attr( 'href', '#' ).text( inWl ? '-wl' : '+wl' );
			$bl = $( '<a>' ).attr( 'href', '#' ).text( inBl ? '-bl' : '+bl' );
			$.each( [ $wl, $bl ], function ( i, el ) {
				el.click( function () {
					username = $( this ).parent( 'span' ).prev( 'a.mw-userlink' ).text();
					anchorHandler( username, $( this ).text() );
					return false;
				} );
			} );
			$( '<span>' ).append( ' ( ', $wl, ' ', $bl, ' )' ).insertAfter( $( this ) );
		} );
		return color;
	}

	/**
	 * Modifica la pagine Speciale:OsservatiSpeciali o Speciale:UltimeModifiche.
	 */
	function editWatchlist() {
		var usersWl = getList( 'vfol1' ).split( '@' );
		var usersBl = getList( 'vfol2' ).split( '@' );
		$( 'h4' ).each( function () {
			// visualizzazione avanzata con modifiche raggruppate: gruppo di modifiche
			$( this ).next( 'div' ).find( 'table.mw-collapsible' ).each( function () {
				var edits = {};
				$( this ).find( 'tr:not( :first )' ).each( function () {
					var color = editEntry( $( this ), usersWl, usersBl );
					edits[ color ] = true;
				} );
				$( this ).find( 'tr:first' ).each( function () {
					editEntry( $( this ), usersWl, usersBl,
							  edits[ '#ffcccc' ] ? '#ffcccc' :
							  edits[ '#ffffbb' ] ? '#ffffbb' :
							  !edits[ '' ] ? '#ccffcc' : '' );
				} );
			} );
			// visualizzazione avanzata con modifiche raggruppate: modifiche singole
			$( this ).next( 'div' ).find( 'table:not( .mw-collapsible ) tr' ).each( function () {
				editEntry( $( this ), usersWl, usersBl );
			} );
			// visualizzazione standard senza modifiche raggruppate
			$( this ).next( 'ul.special' ).find( 'li' ).each( function () {
				editEntry( $( this ), usersWl, usersBl );
			} );
		} );
	}

	$( function () {
		// setup portlet link
		var state = getState();
		var portletLink = mw.util.addPortletLink( 'p-tb', '#', 'VFonLine ' + state, 'vfol' );
		$( portletLink ).click( function ( event ) {
			event.preventDefault();
			state = getState() === 'abilitato' ? 'disabilitato' : 'abilitato';
			setState( state );
			$( portletLink ).find( 'a' ).text( 'VFonLine ' + state );
			togglePortletLinks( state === 'abilitato' );
		} );
		togglePortletLinks( state === 'abilitato' );
		// modifica watchlist
		if ( $.inArray( mw.config.get( 'wgPageName' ), [ 'Speciale:OsservatiSpeciali', 'Speciale:UltimeModifiche' ] ) !== -1 &&
			 state === 'abilitato' ) {
			editWatchlist();
		}
	} );
}( mediaWiki, jQuery ) );