MediaWiki:Gadget-CreditiTraduzione.js

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca

Questa pagina definisce alcuni parametri di aspetto e comportamento generale di tutte le pagine. Per personalizzarli vedi Aiuto:Stile utente.


Nota: dopo aver salvato è necessario pulire la cache del proprio browser per vedere i cambiamenti (per le pagine globali è comunque necessario attendere qualche minuto). Per Mozilla / Firefox / Safari: fare clic su Ricarica tenendo premuto il tasto delle maiuscole, oppure premere Ctrl-F5 o Ctrl-R (Command-R su Mac); per Chrome: premere Ctrl-Shift-R (Command-Shift-R su un Mac); per Konqueror: premere il pulsante Ricarica o il tasto F5; per Opera può essere necessario svuotare completamente la cache dal menù Strumenti → Preferenze; per Internet Explorer: mantenere premuto il tasto Ctrl mentre si preme il pulsante Aggiorna o premere Ctrl-F5.

/** 
 * Aggiunge il template {{Tradotto da}} in modo automatico nella pagina di discussione della pagina corrente.
 */
/* global mediaWiki, jQuery, OO */
( function ( mw, $ ) {
	'use strict';

	// la finestra di dialogo per l'inserimento delle informazioni sul template
	var inputDialog;
	var currTitle = mw.config.get('wgPageName');
	var currTitleObj = new mw.Title( currTitle );
	var gadgetName = "CreditiTraduzione.js";
	var docTitle = "Aiuto:Accessori/Crediti traduzione";
	
	function logError(msg) {
		console.error("[" + gadgetName + "] " + msg);
	}
	
	/*********************
	 * GESTIONE AUTOEDIT *
	 *********************/
	
	/**
	 * Restituisce un token che identifica la sessione utente, usato per convalidare il link per la modifica automatica.
	 * 
	 * @return {string} Una stringa alfanumerica.
	 */
	function getAutoSaveToken() {
		return mw.user.sessionId();
	}
	
	/**
	 * Aggiunge un banner temporaneo in cima alla pagina in attesa che questa venga salvata.
	 * 
	 * @param {string} s - Il messaggio da visualizzare
	 */
	function bannerMessage(s) {
		var headings = document.getElementsByTagName('h1');
		if (headings) {
			var div = document.createElement('div');
			div.innerHTML = '<div style="font-size:1.2em"><b>' + s + '</b></div>';
			headings[0].parentNode.insertBefore(div, headings[0]);
		}
	}
	
	/**
	 * Esegue la modifica automatica di una pagina.
	 * 
	 * @param {string} prepend - Il wikicodice da inserire prima di quello esistente
	 * @param {string} summary - L'oggetto di modifica; per default è vuoto
	 * @param {boolean} minor - 'true' se la modifica dev'essere marcata come minore, 'false' se dev'essere marcata come non minore; altrimenti viene lasciato il valore predefinito
	 */
	function autoEdit(prepend, summary, minor) {
		if (prepend) {
			// aggiungi il template nel codice
			var editBox = document.editform.wpTextbox1;
			editBox.value = prepend + editBox.value;
			
			// contrassegna la modifica come (non) minore
			if (minor === true || minor === false) {
				document.editform.wpMinoredit.checked = minor;
			}
			
			// aggiungi l'oggetto di modifica
			document.editform.wpSummary.value = summary;
			
			// salva la pagina
			setTimeout(function() {
				bannerMessage('Il pulsante per il salvataggio della pagina è stato cliccato automaticamente. Attendi che la pagina venga salvata.');
				document.title = '(' + document.title + ')';
				document.editform.wpSave.click();
			}, 500);
		}
	}
	
	/**
	 * La funzione seguente si occupa di far partire il processo di inserimento del template {{Tradotto da}}.
	 */
	$( function () {
		// controlla se 1) siamo in un namespace di discussione 2) siamo in modalità modifica 3) il token passato in input è valido
		if (mw.config.get('wgNamespaceNumber') % 2 === 1 &&
				mw.config.get('wgAction') === 'edit' &&
				mw.util.getParamValue('tdtoken') === getAutoSaveToken()) {
			// ricava i parametri HTTP GET
			var lang      = mw.util.getParamValue('tdlang'),
				title     = mw.util.getParamValue('tdtitle'),
				timestamp = mw.util.getParamValue('tdtimestamp'),
				oldid     = mw.util.getParamValue('tdoldid');
			
			if (lang && title && timestamp && oldid) {
				// genera il wikicodice del template ed esegui l'edit automatico
				var date = new Date(timestamp).toLocaleString('it-IT',  {dateStyle:'long'});
				var wikicode = '{{Tradotto da|' + lang + '|' + title + '|' + date + '|' + oldid + '}}\n',
					summary = "Aggiungo [[template:Tradotto da]] tramite [[MediaWiki:Gadget-" + gadgetName + "]] ([[" + docTitle + "|aiuto]])";
				autoEdit(wikicode, summary, null);
			}
		}
	} );
	
	
	/*****************************
	 * LOGICHE RECUPERO METADATI *
	 *****************************/

	/**
	 * Ricerca l'oldid e relativo timestamp di una voce di un'altra versione linguistica di Wikipedia
	 * in base al timestamp fornito (non necessariamente uguale a quello di output).
	 *
	 * @param {string} lang - La lingua del progetto in questione
	 * @param {string} title - Il titolo della pagina
	 * @param {string} timestamp - Il timestamp di riferimento (formato: "YYYY-MM-DDThh:mm:ssZ")
	 * @return {Object} Un oggetto thenable contenente un array costituito dall'oldid desiderato e dal relativo timestamp.
	 */
	function getOtherWikiRevIdAndTimestamp( lang, title, timestamp ) {
		return getOtherWikiRevIdAndTimestampAux( lang, title, timestamp, true );
	}
	
	/**
	 * Funzione ausiliaria per getOtherWikiRevIdAndTimestamp
	 * 
	 * @param {boolean} firstAttempt - Valore booleano ausiliario, per sapere in quale direzione della cronologia effettuare la ricerca
	 */
	function getOtherWikiRevIdAndTimestampAux( lang, title, timestamp, firstAttempt ) {
		// Come da [[mw:API:Cross-site_requests#CORS_usage]]
		var apiEndpoint = 'https://' + lang + '.wikipedia.org/w/api.php';
		var params = 'action=query&prop=revisions&rvlimit=1&rvprop=ids|timestamp&titles=' + title + '&rvstart=' + timestamp;
		var otherParams = firstAttempt ? '' : '&rvdir=newer';
		
		return fetch(apiEndpoint + '?' + params + otherParams + '&formatversion=2&format=json&origin=*')
			.then(function(response) { return response.json(); })
			.then(function(response) {
				if (typeof response.query.pages[0].revisions !== "undefined") {
					var revision = response.query.pages[0].revisions[0];
					return [revision.revid, revision.timestamp];
				}
				else if (firstAttempt) {
					// se nessuna revision è trovata, prova invertendo la direzione di ricerca (rvdir=newer)
					return getOtherWikiRevIdAndTimestampAux(lang, title, timestamp, false);
				}
			});
	}

	/**
	 * Ricava il titolo della voce di un'altra versione linguistica di Wikipedia.
	 * 
	 * @param {string} lang - Il codice della lingua
	 * @return {Object} Un oggetto thenable contenente una stringa che rappresenta il titolo della voce dell'altra versione linguistica,
	 *                  ma solo se è possibile ricavarla.
	 */
	function getTitleByLang( lang ) {
		return new mw.Api().get( {
			action: 'query',
			titles: currTitle,
			prop: 'langlinks',
			lllang: lang,
			format: 'json',
			formatversion: '2'
		} ).then( function ( response ) {
			// controlla se la voce è collegata ad un elemento Wikidata
			// e c'è almeno un sitelink ad un'altra versione linguistica
			if (typeof response.query.pages[0].langlinks !== "undefined") {
				return response.query.pages[0].langlinks[0].title;
			}
		} );
	}

	/**
	 * Ricava il timestamp relativo a un certo oldid.
	 * 
	 * @param {string} oldid - L'oldid di riferimento
	 * @return {Object} Un oggetto thenable contenente uil timestamp relativo all'oldid in input.
	 */
	function getTimestampByRevisionId( oldid ) {
		return new mw.Api().get( {
			action: 'query',
			prop: 'revisions',
			revids: oldid,
			rvprop: 'timestamp',
			format: 'json',
			formatversion: '2'
		} ).then( function ( response ) {
			return response.query.pages[0].revisions[0].timestamp;
		} );
	}
	
	/**
	 * Ricava l'identificativo della prima versione della pagina corrente.
	 * 
	 * @return {Object} Un oggetto thenable contenente l'oldid della prima versione della pagina corrente.
	 */
	function getFirstRevId() {
		return new mw.Api().get( {
			action: 'query',
			prop: 'revisions',
			titles: currTitle,
			rvlimit: '1',
			rvprop: 'ids',
			rvdir: 'newer',
			format: 'json',
			formatversion: '2'
		} ).then( function ( response ) {
			if (typeof response.query.pages[0].revisions !== "undefined") {
				return response.query.pages[0].revisions[0].revid;
			}
		} );
	}
	
	/**
	 * Ricava l'identificativo della versione attuale della pagina corrente.
	 * 
	 * @return {int} L'oldid della versione attuale della pagina corrente.
	 */
	function getCurrentRevId() {
		return mw.config.get('wgCurRevisionId');
	}

	/**
	 * Controlla se l'identificativo appartiene ad una versione.
	 * 
	 * @param {string} oldid - L'identificativo da controllare
	 * @return {Object} Un oggetto thenable contenente l'oldid in input, ma solo se questo è corretto.
	 */
	function checkRevId(oldid) {
		return new mw.Api().get( {
			action: 'query',
			revids: oldid,
			format: 'json',
			formatversion: '2'
		} ).then( function ( response ) {
			// controlla che l'oldid sia valido e che il titolo della voce corrisponda
			if (typeof response.query.pages === "undefined") {
				logError("L'oldid fornito non sembra corrispondere ad alcuna pagina.");
			}
			else {
				var retrievedTitle = response.query.pages[0].title.replaceAll(" ", "_");
				if (retrievedTitle !== currTitle) {
					logError("Il titolo della pagina relativo all'oldid fornito (" + retrievedTitle + ") non coincide con quello della pagina corrente (" + currTitle + ").");
				}
				else return oldid;
			}
		} );
	}
	
	
	/**********************
	 * GESTIONE MODAL BOX *
	 **********************/
	
	/**
	 * Gestore del click sul pulsante "Inserisci template".
	 */
	function inputHandler() {
		function setResultLabel(html) {
			inputDialog.resultLabel.setLabel($( html ));
		}
		
		var lang = $.trim( inputDialog.langInput.getValue() );
		if (!lang) {
			setResultLabel('<p>Specificare il codice della versione linguistica da cui proviene la traduzione.</p>');
			return;
		}
		
		var revisionId;
		if      (inputDialog.firstRevRadio.isSelected()) revisionId = getFirstRevId();
		else if (inputDialog.currRevRadio.isSelected())  revisionId = getCurrentRevId();
		else if (inputDialog.otherRevRadio.isSelected()) {
			revisionId = $.trim( inputDialog.otherRevInput.getValue() );
			if (!revisionId) {
				setResultLabel('<p>Specificare l\'oldid della versione della voce.</p>');
				return;
			}
			else revisionId = checkRevId(revisionId);
		}
		else {
			setResultLabel('<p>Selezionare una delle tre opzioni.</p>');
			return;
		}
		setResultLabel(' ');
		
		Promise.resolve(revisionId).then( function(revId) {
			if (!revId) {
				setResultLabel('<p>Impossibile trovare la versione specificata. Assicurati di trovarti nella pagina corretta e di indicare una versione valida.</p>');
			}
			else Promise.all([
				getTimestampByRevisionId(revId),
				getTitleByLang(lang)
			]).then( function(values) {
				var timestamp      = values[0],
					otherWikiTitle = values[1];
				if (typeof otherWikiTitle === "undefined") {
					setResultLabel('<p>Impossibile rintracciare la pagina di origine su ' + lang + '.wiki. Assicurati di aver collegato questa pagina su Wikidata!</p>');
				}
				else {
					getOtherWikiRevIdAndTimestamp(lang, otherWikiTitle, timestamp).then( function(response) {
						var otherWikiRevId = response[0],
							otherWikiTs    = response[1];
						var autoEditUrl = '//it.wikipedia.org/wiki/' + currTitleObj.getTalkPage().getPrefixedText() + '?action=edit&tdtoken=' + getAutoSaveToken() +
							'&tdlang=' + lang + '&tdtitle=' + otherWikiTitle + '&tdtimestamp=' + otherWikiTs + '&tdoldid=' + otherWikiRevId;
						window.open(autoEditUrl,"_self");
					});
				}
			});
		});
	}

	/**
	 * Crea la finestra di dialogo per l'inserimento dei dettagli del template.
	 * Basato su [[Special:Permalink/109422525]]
	 * 
	 * @return {Object} L'oggetto derivato da OO.ui.Dialog che rappresenta la finestra
	 */
	function buildInputDialog() {
		var style = '.grv-container { height: 80px }' + 
					'.grv-container-button { width: 100%; text-align: center }';
		mw.util.addCSS( style );
		function InputDialog( config ) {
			InputDialog.parent.call( this, config );
		}
		OO.inheritClass( InputDialog, OO.ui.Dialog );
		InputDialog.static.name = 'inputDialog';
		InputDialog.prototype.initialize = function () {
			InputDialog.parent.prototype.initialize.call( this );
			
			var langInput = new OO.ui.TextInputWidget();
			langInput.on( 'enter', inputHandler );
			var langInputLayout = new OO.ui.FieldLayout( langInput, {
				label: 'Codice lingua d\'origine:',
				align: 'top' 
			} );
			
			var radioInstrLabel = new OO.ui.LabelWidget( {
				label: $( '<br><p>In quale versione della <u>voce di it.wiki</u> è stata inserita la traduzione?</p>' )
			} );
			
			var firstRevRadio = new OO.ui.RadioOptionWidget( {
				data: 'first',
				label: 'Nella prima versione della voce'
			} );
			var currRevRadio = new OO.ui.RadioOptionWidget( {
				data: 'first',
				label: 'Nella versione attuale della voce'
			} );
			
			var otherRevInput = new OO.ui.TextInputWidget( { readOnly: true });
			otherRevInput.on( 'enter', inputHandler );
			var otherRevRadio = new OO.ui.RadioOptionWidget( {
				data: 'first',
				label: 'Altra versione (specificare oldid):'
			} );
			
			var radioSelect = new OO.ui.RadioSelectWidget( {
				items: [firstRevRadio, currRevRadio, otherRevRadio]
			} );
			radioSelect.on( 'choose', function(item) {
				otherRevInput.setReadOnly(item !== otherRevRadio);
			} );
			
			var resultLabel = new OO.ui.LabelWidget( {
				classes: [ 'grv-container' ],
				label: ' '
			} );
			
			var submitButton = new OO.ui.ButtonWidget( {
				label: 'Inserisci template {{Tradotto da}}',
			} ).on( 'click', inputHandler );
			var cancelButton = new OO.ui.ButtonWidget( {
				label: 'Annulla'
			} ).on( 'click', function () {
				inputDialog.close();
			} );
			var buttons = new OO.ui.HorizontalLayout( {
				items: [ submitButton, cancelButton ],
				classes: [ 'grv-container-button' ]
			} );
			
			this.langInput = langInput;
			this.currRevRadio = currRevRadio;
			this.firstRevRadio = firstRevRadio;
			this.otherRevRadio = otherRevRadio;
			this.otherRevInput = otherRevInput;
			this.resultLabel = resultLabel;
			this.panelLayout = new OO.ui.PanelLayout( { padded: true, expanded: false } );
			this.panelLayout.$element.append( langInputLayout.$element, radioInstrLabel.$element, radioSelect.$element,
				otherRevInput.$element, resultLabel.$element, buttons.$element );
			this.$body.append( this.panelLayout.$element );
		};
		InputDialog.prototype.getBodyHeight = function () {
			return this.panelLayout.$element.outerHeight( true );
		};
		return new InputDialog( {
			size: 'small'
		} );
	}

	$( function () {
		var windowManager;
		var portletLink = mw.util.addPortletLink( 'p-navigation', '#', 'Aggiungi crediti traduzione' );
		$( portletLink ).click( function ( event ) {
			event.preventDefault();
			mw.loader.using( [ 'mediawiki.api', 'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows' ] )
					.done( function () {
						if ( !inputDialog ) {
							inputDialog = buildInputDialog();
							windowManager = new OO.ui.WindowManager();
							$( 'body' ).append( windowManager.$element );
							windowManager.addWindows( [ inputDialog ] );
						}
						windowManager.openWindow( inputDialog );
					} )
					.fail( function () {
						console.error( 'Impossibile avviare l\'accessorio "CreditiTraduzione".' );
					} );
		} );
	} );
}( mediaWiki, jQuery ) );