Utente:Ricordisamoa/PDC.js: differenze tra le versioni

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca
Contenuto cancellato Contenuto aggiunto
fix autoRfd per Template:E
fallback per maggiorContributore(), evento select di autocomplete, wgArticleId > 0
(2 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
//<nowiki>
//<nowiki>
/* jshint browser:true, devel:true, smarttabs:true */
/* jshint browser:true, devel:true, smarttabs:true */
/* global mediaWiki, jQuery */
/* global mediaWiki, jQuery, OO */
( function ( mw, $ ) {
( function ( mw, $ ) {
'use strict';
'use strict';
var namespaces = mw.config.get( 'wgFormattedNamespaces' );
var namespaces = mw.config.get( 'wgFormattedNamespaces' ),
window.PDC = {
PDC = {
api: new mw.Api(),
api: new mw.Api(),


Riga 26: Riga 26:
*/
*/
dialog: [
dialog: [
'oojs-ui',
'jquery.spinner',
'jquery.spinner',
'jquery.ui.autocomplete',
'jquery.ui.autocomplete'
'jquery.ui.dialog'
]
]


Riga 91: Riga 91:
'dialog-button-cancel': 'Annulla',
'dialog-button-cancel': 'Annulla',
'dialog-button-proceed': 'Procedi',
'dialog-button-proceed': 'Procedi',
'dialog-button-final': 'Richiedi la cancellazione',
'error-msg': '$1: $2',
'error-msg': '$1: $2',
'process-init': 'Benvenuto/a!<br>Sarai guidato/a nella richiesta di cancellazione per la pagina "<b>$1</b>".<br><br>Se invece desideri effettuare la procedura manualmente, consulta $2.',
'process-init': 'Benvenuto/a!<br>Sarai guidato/a nella richiesta di cancellazione per la pagina "<b>$1</b>".<br><br>Se invece desideri effettuare la procedura manualmente, consulta $2.',
Riga 178: Riga 179:
*/
*/
dialogo: function ( contenuto ) {
dialogo: function ( contenuto ) {
$( '#PDC-dialog' ).empty().append( contenuto );
this.dialog.description.setLabel( $( '<p>' ).append( contenuto ) );
},
},


Riga 189: Riga 190:
messaggio = this.msg( messaggio );
messaggio = this.msg( messaggio );
console.info( messaggio );
console.info( messaggio );
var $d = $( '#PDC-dialog' );
if ( this.dialog ) {
var $l = this.dialog.$element.find( '.PDC-spinner-label' );
if ( $d.length === 1 ) {
var $l = $d.find( '.PDC-spinner-label' );
if ( $l.length === 1 ) {
if ( $l.length === 1 ) {
$l.empty().append( messaggio );
$l.empty().append( messaggio );
Riga 237: Riga 237:
}
}
console.error( messaggio );
console.error( messaggio );
if ( $( '#PDC-dialog' ).length === 1 ) {
if ( this.dialog ) {
this.dialogo(
this.dialogo(
$( '<p>' )
$( '<p>' )
Riga 376: Riga 376:
return ( ( t[a] > t[b] ) ? -1 : ( ( t[a] < t[b] ) ? 1 : 0 ) );
return ( ( t[a] > t[b] ) ? -1 : ( ( t[a] < t[b] ) ? 1 : 0 ) );
} ),
} ),
r = x[0];
r = x[0] || null;
$.each( t, function ( k, v ) {
$.each( t, function ( k, v ) {
if ( k != x[0] && v == t[x[0]] ) {
if ( k != x[0] && v == t[x[0]] ) {
Riga 723: Riga 723:
},
},


/**
opzione: function ( nome ) {
* Configura jquery.ui.autocomplete per un TextInputWidget.
var params = Array.prototype.slice.call( arguments );
* @param {OO.ui.TextInputWidget} widget - Il widget per il quale configurare i suggerimenti
params[0] = 'option-' + nome;
*/
return $( '<label>' )
autocompletaArgomento: function ( widget ) {
.append(
widget
$( '<input>' )
.attr( {
.$input
.autocomplete( {
type: 'checkbox',
source: this.scegliArgomento.bind( this ),
id: 'PDC-option-' + nome
select: widget.onEdit.bind( widget )
} )
)
} );
.append( this.msg.apply( this, params ) );
},
},


Riga 762: Riga 761:
mw.loader.using( self.dependencies.dialog )
mw.loader.using( self.dependencies.dialog )
.done( function () {
.done( function () {
PDC.Dialog = function ( config ) {
var cancelButton = {
PDC.Dialog.super.call( this, config );
text: self.msg( 'dialog-button-cancel' ),
specialButton: 'cancel',
click: function () {
$( this ).dialog( 'destroy' ).remove();
}
};
};
OO.inheritClass( PDC.Dialog, OO.ui.ProcessDialog );
$( '<div>' )
.attr( 'id', 'PDC-dialog' )
PDC.Dialog.static.title = 'PDC.js';
PDC.Dialog.static.size = 'large';
.append(
PDC.Dialog.static.actions = [
self.msg( 'process-init', titolo, '<a href="' + mw.util.getUrl( self.config.help ) + '">' + self.config.help + '</a>' )
)
{
.dialog( {
action: 'proceed',
title: self.msg( 'dialog-title' ),
label: self.msg( 'dialog-button-proceed' ),
flags: [ 'primary', 'progressive' ]
modal: true,
width: 'auto',
close: function () {
$( this ).dialog( 'destroy' ).remove();
},
},
buttons: [
{
cancelButton,
action: 'cancel',
label: self.msg( 'dialog-button-cancel' ),
{
text: self.msg( 'dialog-button-proceed' ),
flags: 'safe'
}
specialButton: 'proceed',
];
click: function () {
PDC.Dialog.prototype.initialize = function () {
var dialog = $( this );
PDC.Dialog.super.prototype.initialize.apply( this, arguments );
self.progresso( 'process-loading-contributors' );
this.content = new OO.ui.PanelLayout( { padded: true } );
self.ottieniContributori( titolo )
this.fieldset = new OO.ui.FieldsetLayout( {
.done( function ( contributori ) {
label: self.msg( 'dialog-title' ), icon: 'alert'
var opzioni = [
} );
self.msg( 'process-confirm', titolo ),
this.description = new OO.ui.LabelWidget( {
$( '<textarea>' )
padded: true,
.addClass( 'mw-ui-input' )
.css( 'background', '#fff' )
label: $( '<p>' )
.attr( {
.append(
id: 'PDC-option-reason',
self.msg(
placeholder: self.msg( 'option-reason' )
'process-init',
} )
titolo,
'<a href="' + mw.util.getUrl( self.config.help ) + '">' + self.config.help + '</a>'
],
)
creatore = contributori[contributori.length - 1],
)
magg = self.maggiorContributore( contributori );
} );
if ( creatore.anon === undefined && creatore.user !== mw.config.get( 'wgUserName' ) ) {
this.fieldset.addItems( [ this.description ] );
opzioni.push( self.opzione( 'notify-creator', creatore.user ) );
this.content.$element.append( this.fieldset.$element );
this.$body.append( this.content.$element );
this.starting = true;
this.options = {};
};
PDC.Dialog.prototype.proceed = function () {
var dialog = this;
self.ottieniContributori( titolo )
.done( function ( contributori ) {
dialog.options.reason = new OO.ui.TextInputWidget( {
multiline: true,
autosize: true,
validate: /\S/
} );
dialog.fieldset.addItems( [
new OO.ui.FieldLayout(
dialog.options.reason,
{
label: self.msg( 'option-reason' ),
align: 'top'
}
)
] );
dialog.description.setLabel(
$( '<p>' )
.append(
self.msg( 'process-confirm', titolo )
)
);
dialog.creatore = contributori[contributori.length - 1];
dialog.maggiore = self.maggiorContributore( contributori );
if (
dialog.creatore.anon === undefined &&
dialog.creatore.user !== mw.config.get( 'wgUserName' )
) {
dialog.options.notifyCreator = new OO.ui.CheckboxInputWidget( {} );
dialog.fieldset.addItems( [
new OO.ui.FieldLayout(
dialog.options.notifyCreator,
{
align: 'inline',
label: self.msg( 'option-notify-creator', dialog.creatore.user )
}
}
)
if ( magg !== null && magg !== creatore.user && magg !== mw.config.get( 'wgUserName' ) ) {
] );
opzioni.push( self.opzione( 'notify-biggest', magg ) );
}
if (
dialog.maggiore !== null &&
dialog.maggiore !== dialog.creatore.user &&
dialog.maggiore !== mw.config.get( 'wgUserName' )
) {
dialog.options.notifyBiggest = new OO.ui.CheckboxInputWidget( {} );
dialog.fieldset.addItems( [
new OO.ui.FieldLayout(
dialog.options.notifyBiggest,
{
align: 'inline',
label: self.msg( 'option-notify-biggest', dialog.maggiore )
}
}
)
for ( var i = 1; i < opzioni.length; i = i + 2 ) {
opzioni.splice( i, 0, '<br>' );
] );
}
}
dialog.options.notifyTopic1 = new OO.ui.TextInputWidget();
opzioni.push( '<br>' );
self.autocompletaArgomento( dialog.options.notifyTopic1 );
opzioni.push(
dialog.fieldset.addItems( [
$( '<label>' )
new OO.ui.FieldLayout(
.attr( 'for', 'PDC-option-topic1' )
dialog.options.notifyTopic1,
.append( self.msg( 'option-notify-topics' ) )
);
{
opzioni.push(
align: 'left',
$( '<input>' )
label: self.msg( 'option-notify-topics' )
}
.attr( 'id', 'PDC-option-topic1' )
.autocomplete( {
)
] );
source: function ( request, response ) {
dialog.options.notifyTopic2 = new OO.ui.TextInputWidget();
self.scegliArgomento( request, response );
self.autocompletaArgomento( dialog.options.notifyTopic2 );
}
} )
dialog.fieldset.addItems( [
);
new OO.ui.FieldLayout(
opzioni.push(
dialog.options.notifyTopic2,
$( '<label>' )
{
.attr( 'for', 'PDC-option-topic2' )
align: 'left',
.append( '+' )
label: '+'
);
}
opzioni.push(
)
$( '<input>' )
] );
// namespace "Discussioni progetto"
.attr( 'id', 'PDC-option-topic2' )
dialog.pTalk = self.config.wikiprojectNamespace + 1;
.autocomplete( {
dialog.options.notifyWikiprojects = new OO.ui.CheckboxInputWidget( {
source: function ( request, response ) {
self.scegliArgomento( request, response );
disabled: self.namespaces[dialog.pTalk] === undefined
}
} );
} )
dialog.fieldset.addItems( [
);
new OO.ui.FieldLayout(
opzioni.push( '<br>' );
dialog.options.notifyWikiprojects,
{
opzioni.push( self.opzione( 'notify-wikiprojects' ) );
var form = $( '<form>' )
align: 'inline',
.append( opzioni )
label: self.msg( 'option-notify-wikiprojects' )
.submit( function ( event ) {
}
event.preventDefault();
)
} );
] );
// Forza il ridimensionamento della finestra
self.dialogo( form );
dialog.manager.updateWindowSize( dialog );
// ricrea i pulsanti per cambiare la funzione di "Procedi"
// Reimposta il pulsante 'procedi'
dialog.dialog( 'option', 'buttons', [
cancelButton,
dialog.actions
.get( { actions: 'proceed' } )[0]
{
.clearFlags()
text: self.msg( 'dialog-button-proceed' ),
.setFlags( [ 'primary', 'constructive' ] )
specialButton: 'proceed',
.setLabel( self.msg( 'dialog-button-final' ) );
click: function () {
} );
var $motivazione = $( '#PDC-option-reason' ),
};
motivazione = $motivazione.val().trim().replace( /\s*(\-\-)?\~{4}$/, '' );
PDC.Dialog.prototype.final = function () {
if ( motivazione.length === 0 ) {
var dialog = this,
$motivazione.get( 0 ).setCustomValidity( self.msg( 'option-reason-missing' ) );
$motivazione.parents( 'form' ).submit();
motivazione = dialog.options.reason.getValue().trim(),
argomenti = $.map( [ 'notifyTopic1', 'notifyTopic2' ], function ( opt ) {
} else {
return dialog.options[opt].getValue().trim();
$motivazione.get( 0 ).setCustomValidity( '' );
} )
var argomenti = $.map( [1, 2], function ( n ) {
.filter( function ( el, i, arr ) {
return $( '#PDC-option-topic' + n ).val().trim();
} )
// Elimina i duplicati
.filter( function ( el, i, arr ) {
return el !== '' && arr.indexOf( el ) === i;
} ),
return el !== '' && arr.indexOf( el ) === i;
} );
daNotificare = $.map( {
notifyCreator: dialog.creatore.user,
var daNotificare = $.map( {
creator: creatore.user,
notifyBiggest: dialog.maggiore
}, function ( user, opt ) {
biggest: magg
if (
}, function ( user, opt ) {
dialog.options[opt] !== undefined &&
if ( $( '#PDC-option-notify-' + opt ).prop( 'checked' ) === true ) {
dialog.options[opt].isSelected()
return self.namespaces[3] + ':' + user;
}
) {
return self.namespaces[3] + ':' + user;
} );
}
var pTalk = self.config.wikiprojectNamespace + 1;
} );
if ( $( '#PDC-option-notify-wikiprojects' ).prop( 'checked' ) === true && pTalk in self.namespaces ) {
if (
pTalk = self.namespaces[pTalk] + ':';
!dialog.options.notifyWikiprojects.isDisabled() &&
daNotificare = daNotificare.concat( $.map( argomenti, function ( arg ) {
dialog.options.notifyWikiprojects.isSelected()
return pTalk + arg;
} ) );
) {
daNotificare = daNotificare.concat(
}
self.creaProcedura( titolo, motivazione )
$.map( argomenti, function ( argomento ) {
return self.namespaces[dialog.pTalk] + ':' + argomento;
.done( function ( procedura, numero ) {
} )
self.avvisoVoce( titolo, numero, argomenti )
.done( function () {
);
}
self.progresso( 'notify-wait' );
self.notificaProcedura( titolo, daNotificare )
self.creaProcedura( titolo, motivazione )
.done( function () {
.done( function ( procedura, numero ) {
self.avvisoVoce( titolo, numero, argomenti )
window.location = mw.util.getUrl( procedura );
} )
.done( function () {
.fail( function () {
self.progresso( 'notify-wait' );
self.errore( 'notify-error' );
self.notificaProcedura( titolo, daNotificare )
} );
.done( function () {
window.location = mw.util.getUrl( procedura );
} )
.fail( function () {
} )
.fail( function () {
self.errore( 'nominate-error' );
self.errore( 'notify-error' );
} );
} );
} )
self.progresso( 'nominate-wait' );
.fail( function () {
} )
self.errore( 'nominate-error' );
.fail( function () {
} );
self.errore( 'new-nomination-error' );
self.progresso( 'nominate-wait' );
} );
} )
.fail( function () {
self.progresso( 'new-nomination-wait' );
self.errore( 'new-nomination-error' );
}
}
} );
self.progresso( 'new-nomination-wait' );
};
PDC.Dialog.prototype.getActionProcess = function ( action ) {
return PDC.Dialog.super.prototype.getActionProcess.call( this, action )
.next( function () {
var dialog = this;
if ( action === 'proceed' ) {
if ( dialog.starting === true ) {
dialog.starting = false;
dialog.proceed();
} else {
dialog.options.reason.isValid()
.done( function ( isValid ) {
if ( isValid ) {
dialog.final();
}
}
] );
} );
} );
}
} else {
return this.close();
}
}
}
}, this );
]
};
var windowManager = new OO.ui.WindowManager();
} );
$( 'body' ).append( windowManager.$element );
self.dialog = new PDC.Dialog();
windowManager.addWindows( [ self.dialog ] );
windowManager.openWindow( self.dialog );
} );
} );
},
},
Riga 1 092: Riga 1 162:
preInit: function () {
preInit: function () {
if (
if (
// pagina esistente
mw.config.get( 'wgArticleId' ) > 0 &&
// in modalità di visualizzazione
// in modalità di visualizzazione
mw.config.get( 'wgAction' ) === 'view' &&
mw.config.get( 'wgAction' ) === 'view' &&
Riga 1 401: Riga 1 473:
}
}
};
};
window.PDC.preInit();
PDC.preInit();
window.PDC = PDC;
}( mediaWiki, jQuery ) );
}( mediaWiki, jQuery ) );

Versione delle 21:27, 10 gen 2015

//<nowiki>
/* jshint browser:true, devel:true, smarttabs:true */
/* global mediaWiki, jQuery, OO */
( function ( mw, $ ) {
	'use strict';
	var namespaces = mw.config.get( 'wgFormattedNamespaces' ),
	PDC = {
		api: new mw.Api(),

		namespaces: namespaces,

		dependencies: {

			/**
			 * Moduli ResourceLoader da cui dipende lo script.
			 */
			general: [
				'mediawiki.jqueryMsg',
				'mediawiki.api.edit',
				'mediawiki.ui.button',
				'mediawiki.ui.input'
			],

			/**
			 * Moduli ResourceLoader da cui dipende la funzionalità della finestra di dialogo.
			 */
			dialog: [
				'oojs-ui',
				'jquery.spinner',
				'jquery.ui.autocomplete'
			]

		},

		/**
		 * Configurazione per Wikipedia in italiano.
		 */
		config: {
			baseSummary: '[[Utente:Ricordisamoa/PDC.js|PDC.js]]: $1',
			base: namespaces[4] + ':Pagine da cancellare',
			help: namespaces[4] + ':Regole per la cancellazione',
			baseTemplate: namespaces[10] + ':Cancellazione',
			actInNamespaces: [0],
			afdCatPrefix: 'Pagine in cancellazione - ',
			wikiprojectNamespace: 102,
			autoRfd: [
				['non enciclopedica, puoi ', 'proporne', ' la '],
			],
			minEdits: 50,
			minDaysOld: 30,
			minDeferrableDays: 7,
			newNominationTemplate: 'subst:Cancellazione/creavvisotesto',
			newNominationSummary: 'nuova richiesta di cancellazione',
			nominationNoticeTemplate: 'Cancellazione',
			nominationNoticeSummary: 'richiesta di cancellazione',
			notificationNewSectionTitle: 'Cancellazione [[$1]]',
			notificationNewSectionTemplate: 'Cancellazione',
			consensualeStartTemplate: 'subst:Consensuale',
			consensualeStartSummary: 'avvio della modalità consensuale',
			deferMinDays: 1,
			deferMaxDays: 7,
			deferDefaultDays: 7,
			deferStartTemplate: 'subst:Proroga',
			deferStartSummary: 'modalità consensuale prorogata per $1 {{PLURAL:$1|giorno|giorni}}',
			voteStartTemplate: 'subst:Votazione',
			voteStartSummary: 'avvio della votazione',
			voteSummary: 'voto',
			simpleDeletedTemplate: 'subst:User:L736E/FineCanc',
			simpleDeletedSummary: 'notifica dell\'avvenuta cancellazione in modalità semplificata',
			simpleDeletedReason: 'Come da procedura di [[WP:RPC|cancellazione semplificata]]: [[$1]]',
			consensualeDeletedTemplate: 'subst:User:L736E/FineCons|cancellata',
			consensualeDeletedSummary: 'notifica dell\'avvenuta cancellazione in modalità consensuale',
			consensualeDeletedReason: 'Come da procedura di [[WP:RPC|cancellazione consensuale]]: [[$1]]',
			deletedAfterPollRfdTemplate: 'subst:User:L736E/FineVoto|cancellata',
			keptTalkTemplate: 'Mantenuta',
			keptRfdTemplate: 'subst:User:L736E/FineVoto|mantenuta',
			keptAfterPollTalkTemplate: 'Noncancellata',
			keptSummary: 'pagina mantenuta',
			protectLevel: 'edit=sysop|move=sysop',
			protectReason: '[[WP:PDC|Procedura di cancellazione]] terminata o annullata'
		},

		/**
		 * Messaggi di interfaccia per la lingua italiana.
		 */
		i18n: {
			it: {
				'menu-link-label': 'Richiedi cancellazione',
				'menu-link-tooltip': 'Procedura guidata per richiedere la cancellazione di questa pagina',
				'dialog-title': 'Richiesta di cancellazione: procedura guidata',
				'dialog-button-cancel': 'Annulla',
				'dialog-button-proceed': 'Procedi',
				'dialog-button-final': 'Richiedi la cancellazione',
				'error-msg': '$1: $2',
				'process-init': 'Benvenuto/a!<br>Sarai guidato/a nella richiesta di cancellazione per la pagina "<b>$1</b>".<br><br>Se invece desideri effettuare la procedura manualmente, consulta $2.',
				'process-loading-contributors': 'Caricamento dei contributori della pagina in corso...',
				'process-confirm': 'Stai per proporre la cancellazione della pagina "$1".',
				'option-reason': 'Perché la pagina dovrebbe essere cancellata? (La firma è inserita automaticamente)',
				'option-reason-missing': 'Inserisci una motivazione',
				'option-notify-creator': 'Notifica il creatore della pagina ($1)',
				'option-notify-biggest': 'Notifica il maggior contributore (tra gli utenti registrati) della pagina ($1)',
				'option-notify-topics': 'Eventuale/i argomento/i relativo/i: ',
				'option-notify-wikiprojects': 'Invia notifiche ai progetti di riferimento',
				'new-nomination-wait': 'Creazione della pagina di procedura in corso...',
				'new-nomination-error': 'Errore durante la creazione della pagina di procedura',
				'nominate-wait': 'Aggiunta dell\'avviso nella pagina in corso...',
				'nominate-error': 'Errore durante l\'aggiunta dell\'avviso nella pagina',
				'notify-wait': 'Notifica della proposta di cancellazione in corso...',
				'notify-error': 'Errore durante la notifica della proposta di cancellazione',
				'notify-done': 'Notifica della proposta di cancellazione inviata con successo alla pagina "$1"',
				'toolbox-title': 'Strumenti PDC per "$1"',
				'toolbox-days-ago': '$1 {{PLURAL:$1|giorno|giorni}} fa',
				'toolbox-today': 'oggi',
				'toolbox-yesterday': 'ieri',
				'toolbox-user-unknown': 'un utente sconosciuto',
				'toolbox-open-generic': 'Procedura aperta',
				'toolbox-open': 'Procedura aperta $1 da $2',
				'toolbox-closed' : 'Procedura chiusa',
				'toolbox-purge': 'Aggiorna',
				'toolbox-defer': 'Proroga',
				'toolbox-already-deferred': 'Già prorogata',
				'toolbox-not-deferrable-yet': 'Non ancora prorogabile',
				'toolbox-defer-days': 'Giorni di proroga',
				'toolbox-defer-cancel': 'Non prorogare',
				'toolbox-defer-wait': 'Annullamento della procedura in corso...',
				'toolbox-defer-error': 'Errore durante la proroga della procedura',
				'toolbox-consensuale': 'Passa alla modalità consensuale',
				'toolbox-consensuale-cancel': 'Annulla',
				'toolbox-consensuale-reason': 'Perché non vuoi che la pagina sia cancellata?',
				'toolbox-consensuale-wait': 'Passaggio alla modalità consensuale in corso...',
				'toolbox-consensuale-error': 'Errore durante il passaggio alla modalità consensuale',
				'toolbox-cancel': 'Annulla la procedura',
				'toolbox-cancel-cancel': 'Non annullare la procedura',
				'toolbox-cancel-reason': 'Perché la procedura deve essere annullata?',
				'toolbox-cancel-wait': 'Annullamento della procedura in corso...',
				'toolbox-cancel-error': 'Errore durante l\'annullamento della procedura',
				'toolbox-sysops': 'Per gli amministratori',
				'toolbox-vote-start': 'Avvia votazione',
				'toolbox-vote-start-wait': 'Avvio della votazione in corso...',
				'toolbox-vote-start-error': 'Errore durante l\'avvio della votazione',
				'toolbox-close': 'Chiudi la procedura',
				'toolbox-close-delete': 'Cancellare la pagina?',
				'toolbox-close-delete-yes': 'Sì',
				'toolbox-close-delete-no': 'No',
				'toolbox-close-cancel': 'Annulla',
				'toolbox-close-option-protect': 'Proteggi questa procedura',
				'toolbox-close-kept-wait': 'Notifica dell\'avvenuto mantenimento della pagina in corso...',
				'toolbox-close-kept-error': 'Errore durante la notifica dell\'avvenuto mantenimento',
				'toolbox-close-delete-wait': 'Cancellazione della pagina in corso...',
				'toolbox-close-delete-error': 'Errore durante la cancellazione della pagina',
				'toolbox-close-notice-wait': 'Notifica dell\'avvenuta cancellazione della pagina in corso...',
				'toolbox-close-notice-error': 'Errore durante la notifica dell\'avvenuta cancellazione',
				'toolbox-close-protect-wait': 'Protezione della pagina di procedura in corso...',
				'toolbox-close-protect-error': 'Errore durante la protezione della procedura',
				'toolbox-purge-wait': 'Purge della pagina di procedura in corso...'
			}
		},

		msg: function ( nome ) {
			var params = Array.prototype.slice.call( arguments );
			params[0] = 'PDC-' + nome;
			return mw.message.apply( this, params ).text();
		},

		l10nMsg: function ( nome ) {
			var params = Array.prototype.slice.call( arguments );
			params[0] = 'PDC-opzione-' + nome;
			if ( mw.messages.exists( params[0] ) === false ) {
				mw.messages.set( params[0], this.config[nome] );
			}
			return mw.message.apply( this, params ).text();
		},

		sysop: ( mw.config.get( 'wgUserGroups' ).indexOf( 'sysop' ) !== -1 || mw.config.get( 'wgUserName' ) === 'Ricordisamoa' ),

		/**
		 * Visualizza un messaggio come contenuto della finestra di dialogo creata dallo script.
		 * @param {string|jQuery} contenuto - Il contenuto da visualizzare
		 */
		dialogo: function ( contenuto ) {
			this.dialog.description.setLabel( $( '<p>' ).append( contenuto ) );
		},

		/**
		 * Visualizza uno spinner con un messaggio nella finestra di dialogo.
		 * @param {string|jQuery} messaggio - Il messaggio da visualizzare
		 * @param {jQuery} [box] - L'elemento HTML con cui contenere il messaggio, in modalità toolbox
		 */
		progresso: function ( messaggio, box ) {
			messaggio = this.msg( messaggio );
			console.info( messaggio );
			if ( this.dialog ) {
				var $l = this.dialog.$element.find( '.PDC-spinner-label' );
				if ( $l.length === 1 ) {
					$l.empty().append( messaggio );
				} else {
					this.dialogo( [
						$( '<span>' )
						.addClass( 'PDC-spinner-label' )
						.append( messaggio ),
						'<br><br>',
						$.createSpinner( {
							size: 'large',
							type: 'block'
						} )
					] );
				}
			} else {
				var $tb = $( '#PDC-toolbox' );
				if ( $tb.length === 1 ) {
					if ( $tb.find( '.mw-spinner' ).size() === 0 ) {
						$.createSpinner( {
							size: 'large'
						} ).css( {
							float: 'right',
							margin: '2em'
						} ).prependTo( $tb );
					}
					box.empty().append( messaggio );
				}
			}
		},

		/**
		 * Visualizza un messaggio di errore nella finestra di dialogo.
		 * @param {string} messaggio - Il codice corrispondente al messaggio di errore da visualizzare
		 * @param {Object|string} [dati] - Eventuali dettagli sull'errore
		 * @param {jQuery} [box] - L'elemento HTML con cui contenere il messaggio, in modalità toolbox
		 */
		errore: function ( messaggio, dati, box ) {
			messaggio = this.msg( messaggio );
			if ( dati ) {
				if ( dati.error && dati.error.info ) {
					dati = dati.error.info;
				}
				messaggio = this.msg( 'error-msg', messaggio, dati );
			}
			console.error( messaggio );
			if ( this.dialog ) {
				this.dialogo(
					$( '<p>' )
					.addClass( 'error' )
					.append( messaggio )
				);
			} else {
				var $tb = $( '#PDC-toolbox' );
				if ( $tb.length === 1 ) {
					$tb.find( '.mw-spinner' ).remove();
					box.empty()
					.addClass( 'error' )
					.append( messaggio );
				}
			}
		},

		/**
		 * Restituisce il titolo della pagina relativa a una procedura di cancellazione.
		 * @param {string} procedura - La procedura di cancellazione
		 * @return {jQuery.Promise}
		 */
		titoloPagina: function ( procedura ) {
			var self = this;
			return self.api.get( {
				action: 'query',
				format: 'json',
				prop: 'revisions',
				titles: procedura,
				rvprop: 'content',
				rvlimit: 1
			} )
			.then( function ( data ) {
				var rev = data.query.pages[Object.keys( data.query.pages )[0]].revisions,
				m = ( rev[0]['*'] || '' ).match( /\{\{\s*[Cc]ancellazione\/proposta\s*\|\s*(1\s*\=\s*)?([^\{\|\}]+)\s*(\}\}|\|)/ );
				if ( m ) {
					return m[2];
				}
			} );
		},

		/**
		 * Verifica i requisiti di apertura delle procedure da parte di un utente.
		 * vedi [[Wikipedia:Requisiti di voto#Requisiti relativi alle votazioni sulle pagine]]
		 * @param {string} [utente] - Il nome dell'utente del quale verificare i contributi
		 * @return {jQuery.Promise}
		 */
		verificaRequisiti: function ( utente ) {
			if ( utente === undefined ) {
				utente = mw.config.get( 'wgUserName' );
			}
			if ( mw.config.get( 'wgDBname' ) === 'testwiki' ) {
				return $.Deferred().resolve( true );
			}
			var self = this;
			return self.api.get( {
				action: 'query',
				format: 'json',
				list: 'users|usercontribs',
				usprop: 'editcount',
				ususers: utente,
				ucuser: utente,
				ucprop: 'timestamp',
				ucdir: 'newer',
				uclimit: 1
			} )
			.then( function ( data ) {
				if ( !data.query || !data.query.users || data.query.users.length !== 1 ) {
					return false;
				}
				var user = data.query.users[0];
				if ( !user.name || user.name !== utente || !user.editcount || user.editcount < self.config.minEdits || !data.query.usercontribs ) {
					return false;
				}
				var uc = data.query.usercontribs;
				if ( uc.length !== 1 || !uc[0].user || !uc[0].timestamp || ( new Date() - new Date( uc[0].timestamp ) ) / 86400000 < self.config.minDaysOld ) {
					return false;
				}
				return true;
			} );
		},

		/**
		 * Ottiene un array con tutte le revisioni della pagina,
		 * come oggetti contenenti l'autore.
		 * @param {string} titolo - Il titolo della pagina
		 * @return {jQuery.Promise}
		 */
		ottieniContributori: function ( titolo ) {
			var self = this,
			params = {
				action: 'query',
				prop: 'revisions',
				titles: titolo,
				rvprop: 'user',
				rvlimit: 'max'
			},
			revs = [],
			getRevsRecursive = function ( continua ) {
				return self.api.get(
					$.extend( {}, params, continua || {} )
				)
				.then( function ( data ) {
					var pages = data.query.pages,
						keys = Object.keys( pages );
					if ( keys.length === 1 && pages[keys[0]].revisions ) {
						// Aggiunge tutte le revisioni con la proprietà "user"
						revs = revs.concat(
							$.grep( pages[keys[0]].revisions, function ( e ) {
								return e.user !== undefined;
							} )
						);
					}
					if ( data['query-continue'] && data['query-continue'].revisions ) {
						// Ci sono ancora revisioni, si continua
						return getRevsRecursive( data['query-continue'].revisions );
					} else {
						// Finito!
						return revs;
					}
				} );
			};
			return getRevsRecursive();
		},

		maggiorContributore: function ( contributori ) {
			var t = {};
			$.each( contributori, function ( i, rv ) {
				if ( rv.anon === undefined ) {
					if ( t[rv.user] ) {
						t[rv.user] = t[rv.user] + 1;
					} else {
						t[rv.user] = 1;
					}
				}
			} );
			var x = Object.keys( t ).sort( function ( a, b ) {
				return ( ( t[a] > t[b] ) ? -1 : ( ( t[a] < t[b] ) ? 1 : 0 ) );
			} ),
			r = x[0] || null;
			$.each( t, function ( k, v ) {
				if ( k != x[0] && v == t[x[0]] ) {
					r = null;
					return;
				}
			} );
			return r;
		},

		/**
		 * Aggiunge il template {{Cancellazione}} all'inizio di una pagina.
		 * @param {string} titolo - Il titolo della pagina proposta per la cancellazione
		 * @param {integer} numero - Il numero della procedura di cancellazione
		 * @param {Array.<string>} argomenti - Gli eventuali argomenti al quale la pagina è relativa
		 * @return {jQuery.Promise}
		 */
		avvisoVoce: function ( titolo, numero, argomenti ) {
			argomenti = $.map( ['', '2'], function ( suf, i ) {
				if ( argomenti.length > i ) {
					return '|arg' + suf + '=' + argomenti[i];
				}
			} )
			.join( '' );
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				summary: this.l10nMsg( 'baseSummary', this.config.nominationNoticeSummary ),
				prependtext: '<noinclude>{{' + this.config.nominationNoticeTemplate + argomenti + '}}</noinclude>\n',
				nocreate: 1
			} );
		},

		/**
		 * Rimuove il template {{Cancellazione}} da una pagina.
		 * @param {string} titolo - Il titolo della pagina dalla quale rimuovere l'avviso
		 * @return {jQuery.Promise}
		 */
		rimuoviAvvisoVoce: function ( titolo ) {
			this.progresso( 'remove-wait' );
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				summary: this.l10nMsg( 'baseSummary', this.config.removeSummary ),
				text: newText,
				nocreate: 1
			} );
		},

		/**
		 * Aggiunge il template {{Mantenuta}} nella discussione di una pagina.
		 * @param {string} titolo - Il titolo della pagina sopravvissuta a una richiesta di cancellazione
		 * @param {boolean} votazione - Se la procedura di cancellazione si è svolta con voto
		 * @param {number} numero - Il numero della procedura di cancellazione
		 * @param {number} favorevoli - Il numero di voti favorevoli alla cancellazione
		 * @param {number} contrari - Il numero di voti contrari alla cancellazione
		 * @return {jQuery.Promise}
		 */
		mantenuta: function ( titolo, votazione, numero, favorevoli, contrari ) {
			var d = new Date(),
			tmp = '{{' + this.config['kept' + ( votazione ? 'AfterPoll' : '' ) + 'TalkTemplate'] + '|' + mw.config.get( 'wgMonthNames' )[d.getMonth() + 1] + '|' + d.getDate() + '|' + d.getFullYear() + '|' + titolo + '|' + ( numero && numero !== null ? numero : '' );
			if ( votazione ) {
				tmp += '|' + favorevoli + '|' + contrari;
			}
			tmp += '}}';
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				section: 0,
				summary: this.l10nMsg( 'baseSummary', this.config['kept' + ( votazione ? 'AfterPoll' : '' ) + 'Summary'] ),
				appendtext: tmp,
				nocreate: 1
			} );
		},

		/**
		 * Aggiunge il template {{Cancellazione}} in una nuova sezione di una o più pagine di discussione.
		 * @param {string} titolo - Il titolo della pagina da proporre per la cancellazione
		 * @param {Array.<string>} discussioni - I titoli delle pagine di discussione degli utenti o dei progetti da avvisare
		 * @return {jQuery.Promise}
		 */
		notificaProcedura: function ( titolo, discussioni ) {
			var self = this,
			deferreds = [],
			sectionTitle = self.l10nMsg( 'notificationNewSectionTitle', titolo ),
			sectionContent = '{{' + self.config.notificationNewSectionTemplate + '|' + titolo + '}}--~~~~';
			$.each( discussioni, function ( i, discussione ) {
				deferreds.push(
					self.api.newSection( discussione, sectionTitle, sectionContent )
					.done( function () {
						console.info( self.msg( 'notify-done', discussione ) );
					} )
				);
			} );
			return $.when.apply( $, deferreds );
		},

		/**
		 * Crea la procedura di cancellazione.
		 * @param {string} titolo - Il titolo della pagina da proporre per la cancellazione
		 * @param {string} motivazione - La motivazione per la quale proporre la cancellazione della pagina
		 * @return {jQuery.Promise}
		 */
		creaProcedura: function ( titolo, motivazione ) {
			var numero = 1,
				procedura = this.config.base + '/' + titolo;
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: procedura,
				summary: this.l10nMsg( 'baseSummary', this.config.newNominationSummary ),
				text: '{{' + this.config.newNominationTemplate + '}}\n\n' + motivazione + ' --~~~~',
				createonly: 1
			} );
		},

		/**
		 * Annulla una procedura di cancellazione.
		 * @param {string} titolo - Il titolo della procedura da annullare
		 * @param {string} motivazione - La motivazione per la quale la procedura va annullata
		 * @return {jQuery.Promise}
		 */
		annullaProcedura: function ( titolo, motivazione ) {
		},

		/**
		 * Passa alla modalità consensuale.
		 * @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
		 * @param {string} motivazione - La motivazione per la quale l'utente intende opporsi alla cancellazione tacita della pagina
		 * @return {jQuery.Promise}
		 */
		consensuale: function ( titolo, motivazione ) {
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				summary: this.l10nMsg( 'baseSummary', this.config.consensualeStartSummary ),
				appendtext: '{{' + this.config.consensualeStartTemplate + '}}\n\n' + motivazione.trim() + ' --~~~~',
				nocreate: 1
			} );
		},

		/**
		 * Proroga una procedura di cancellazione
		 * @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
		 * @param {integer} giorni - Il numero di giorni per i quali prorogare la procedura
		 * @return {jQuery.Promise}
		 */
		prorogaProcedura: function ( titolo, giorni ) {
			var giorniArg;
			if ( giorni === this.config.deferDefaultDays ) {
				giorniArg = '';
			} else {
				giorniArg = '|' + giorni;
			}
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				summary: this.l10nMsg( 'baseSummary', this.l10nMsg( 'deferStartSummary', giorni ) ),
				appendtext: '\n\n{{' + this.config.deferStartTemplate + giorniArg + '}}',
				nocreate: 1
			} );
		},

		/**
		 * Per gli amministratori: passa alla modalità votazione.
		 * @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
		 * @return {jQuery.Promise}
		 */
		avviaVotazione: function ( titolo ) {
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				summary: this.l10nMsg( 'baseSummary', this.config.voteStartSummary ),
				appendtext: '\n\n{{' + this.config.voteStartTemplate + '}}',
				nocreate: 1
			} );
		},

		/**
		 * Vota a favore o contro la cancellazione di una pagina.
		 * @param {string} titolo - Il titolo della procedura di cancellazione (già esistente)
		 * @param {string} tipo - Il tipo di voto da esprimere ("Mantenere", "Cancellare", o "Astenuti")
		 * @param {string} motivazione - La motivazione (facoltativa) per il voto espresso
		 * @return {jQuery.Promise}
		 */
		vota: function ( titolo, tipo, motivazione ) {
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				section: sezione,
				summary: this.l10nMsg( 'baseSummary', this.config.voteSummary ),
				appendtext: '\n# ' + motivazione.trim() + ( motivazione.trim() !== '' ? ' ' : '' ) + '--~~~~',
				nocreate: 1
			} );
		},

		/**
		 * Controlla se una pagina contiene già un avviso di cancellazione.
		 * @param {string} titolo - Il titolo della pagina da controllare
		 * @return {jQuery.Promise}
		 */
		inCancellazione: function ( titolo ) {
			return this.api.get( {
				action: 'query',
				format: 'json',
				titles: titolo,
				prop: 'templates',
				tltemplates: this.config.baseTemplate
			} )
			.then( function ( data ) {
				if ( data.query && data.query.pages ) {
					var pages = data.query.pages;
					return (
						Object.keys( pages ).length === 1 &&
						( pages[Object.keys( pages )[0]].templates || [] ).length === 1
					);
				}
				return false;
			} );
		},

		/**
		 * Controlla se esiste già una procedura di cancellazione (in corso o terminata) riguardante una pagina.
		 * @param {string} titolo - Il titolo della pagina da controllare
		 * @return {jQuery.Promise}
		 */
		proceduraEsistente: function ( titolo ) {
		},

		/**
		 * Controlla lo stato di una procedura di cancellazione.
		 * @param {string} titolo - Il titolo della procedura da controllare
		 * @return {jQuery.Promise}
		 */
		statoProcedura: function ( titolo ) {
			return this.api.get( {
				action: 'query',
				format: 'json',
				titles: titolo,
				prop: 'categories|revisions',
				rvprop: 'timestamp|user',
				cllimit: 'max',
				rvdir: 'newer',
				rvlimit: 1
			} )
			.then( function ( data ) {
				if ( data.query && data.query.pages && Object.keys( data.query.pages ).length === 1 ) {
					var stato = {},
					page = data.query.pages[Object.keys( data.query.pages )[0]];
					$.each( page.categories || [], function () {
						if ( this.title === 'Categoria:Procedure di cancellazione in corso' ) {
							stato.terminata = false;
						} else if ( this.title === 'Categoria:Procedure di cancellazione protette' ) {
							stato.terminata = true;
						}
						var inizio = this.title.match( /^Categoria\:Cancellazioni del (\d\d? .+ \d{4})$/ ),
						consensuale = this.title.match( /^Categoria\:Cancellazioni consensuali del (\d\d? .+ \d{4})$/ ),
						prorogata = this.title.match( /^Categoria\:Cancellazioni consensuali prorogate del (\d\d? .+ \d{4})$/ ),
						votazione = this.title.match( /^Categoria\:Cancellazioni con votazione del (\d\d? .+ \d{4})$/ );
						if ( inizio ) {
							stato.inizio = inizio[1];
						}
						if ( consensuale ) {
							stato.consensuale = consensuale[1];
						}
						if ( prorogata ) {
							stato.prorogata = prorogata[1];
						}
						if ( votazione ) {
							stato.votazione = votazione[1];
						}
					} );
					if ( page.revisions && page.revisions.length === 1 ) {
						stato.creazione = page.revisions[0];
					}
					return stato;
				}
			} );
		},

		/**
		 * Per gli amministratori: protegge la procedura di cancellazione, una volta terminata.
		 * @param {string} titolo - Il titolo della procedura da proteggere
		 * @return {jQuery.Promise}
		 */
		proteggiPagina: function ( titolo ) {
			return this.api.postWithToken( 'protect', {
				action: 'protect',
				format: 'json',
				title: titolo,
				protections: this.config.protectLevel,
				reason: this.config.protectReason
			} );
		},

		/**
		 * Per gli amministratori: cancella una pagina.
		 * @param {string} titolo - Il titolo della pagina da cancellare
		 * @param {string} procedura - Il titolo della procedura di cancellazione
		 * @param {string} motivazione - La motivazione per la quale la pagina va cancellata
		 * @return {jQuery.Promise}
		 */
		cancellaPagina: function ( titolo, procedura, modalità ) {
			return this.api.postWithToken( 'edit', {
				action: 'delete',
				title: titolo,
				reason: this.l10nMsg( 'baseSummary', this.l10nMsg( modalità + 'DeletedReason', procedura ) )
			} );
		},

		/**
		 * Per gli amministratori: notifica l'avvenuta cancellazione di una pagina.
		 * @param {string} titolo - Il titolo della procedura di cancellazione (terminata)
		 * @param {string} modalità - La modalità della procedura di cancellazione
		 * @return {jQuery.Promise}
		 */
		avvisoCancellata: function ( titolo, modalità ) {
			return this.api.postWithToken( 'edit', {
				action: 'edit',
				format: 'json',
				title: titolo,
				appendtext: '\n\n{{' + this.l10nMsg( modalità + 'DeletedTemplate' ) + '}}',
				summary: this.l10nMsg( 'baseSummary', this.config[modalità + 'DeletedSummary'] ),
				nocreate: 1
			} );
		},

		/**
		 * Purga la cache del server relativa a una pagina, compresa la cache dei link (utile per le categorie).
		 * @param {string} titolo - Il titolo della pagina da purgare
		 * @return {jQuery.Promise}
		 */
		purgaPagina: function ( titolo ) {
			return this.api.get( {
				action: 'purge',
				forcelinkupdate: 1,
				titles: titolo
			} );
		},

		/**
		 * Configura jquery.ui.autocomplete per un TextInputWidget.
		 * @param {OO.ui.TextInputWidget} widget - Il widget per il quale configurare i suggerimenti
		 */
		autocompletaArgomento: function ( widget ) {
			widget
			.$input
			.autocomplete( {
				source: this.scegliArgomento.bind( this ),
				select: widget.onEdit.bind( widget )
			} );
		},

		scegliArgomento: function ( request, response ) {
			var self = this;
			self.api.get( {
				list: 'allcategories',
				acprefix: self.config.afdCatPrefix,
				acprop: '',
				acfrom: self.config.afdCatPrefix + request.term,
				aclimit: 10
			} )
			.done( function ( data ) {
				response( $.map( data.query.allcategories, function ( e ) {
					return e['*'].replace( self.config.afdCatPrefix, '' );
				} ) );
			} );
		},

		/**
		 * Avvia una finestra di dialogo per guidare l'utente durante l'avvio della procedura.
		 * @param {string} titolo - Il titolo della pagina della quale proporre la cancellazione
		 */
		proceduraGuidata: function ( titolo ) {
			var self = this;
			titolo = titolo.replace( /_/g, ' ' );
			mw.loader.using( self.dependencies.dialog )
			.done( function () {
				PDC.Dialog = function ( config ) {
					PDC.Dialog.super.call( this, config );
				};
				OO.inheritClass( PDC.Dialog, OO.ui.ProcessDialog );
				PDC.Dialog.static.title = 'PDC.js';
				PDC.Dialog.static.size = 'large';
				PDC.Dialog.static.actions = [
					{
						action: 'proceed',
						label: self.msg( 'dialog-button-proceed' ),
						flags: [ 'primary', 'progressive' ]
					},
					{
						action: 'cancel',
						label: self.msg( 'dialog-button-cancel' ),
						flags: 'safe'
					}
				];
				PDC.Dialog.prototype.initialize = function () {
					PDC.Dialog.super.prototype.initialize.apply( this, arguments );
					this.content = new OO.ui.PanelLayout( { padded: true } );
					this.fieldset = new OO.ui.FieldsetLayout( {
						label: self.msg( 'dialog-title' ), icon: 'alert'
					} );
					this.description = new OO.ui.LabelWidget( {
						padded: true,
						label: $( '<p>' )
							.append(
								self.msg(
									'process-init',
									titolo,
									'<a href="' + mw.util.getUrl( self.config.help ) + '">' + self.config.help + '</a>'
								)
							)
					} );
					this.fieldset.addItems( [ this.description ] );
					this.content.$element.append( this.fieldset.$element );
					this.$body.append( this.content.$element );
					this.starting = true;
					this.options = {};
				};
				PDC.Dialog.prototype.proceed = function () {
					var dialog = this;
					self.ottieniContributori( titolo )
					.done( function ( contributori ) {
						dialog.options.reason = new OO.ui.TextInputWidget( {
							multiline: true,
							autosize: true,
							validate: /\S/
						} );
						dialog.fieldset.addItems( [
							new OO.ui.FieldLayout(
								dialog.options.reason,
								{
									label: self.msg( 'option-reason' ),
									align: 'top'
								}
							)
						] );
						dialog.description.setLabel(
							$( '<p>' )
							.append(
								self.msg( 'process-confirm', titolo )
							)
						);
						dialog.creatore = contributori[contributori.length - 1];
						dialog.maggiore = self.maggiorContributore( contributori );
						if (
							dialog.creatore.anon === undefined &&
							dialog.creatore.user !== mw.config.get( 'wgUserName' )
						) {
							dialog.options.notifyCreator = new OO.ui.CheckboxInputWidget( {} );
							dialog.fieldset.addItems( [
								new OO.ui.FieldLayout(
									dialog.options.notifyCreator,
									{
										align: 'inline',
										label: self.msg( 'option-notify-creator', dialog.creatore.user )
									}
								)
							] );
						}
						if (
							dialog.maggiore !== null &&
							dialog.maggiore !== dialog.creatore.user &&
							dialog.maggiore !== mw.config.get( 'wgUserName' )
						) {
							dialog.options.notifyBiggest = new OO.ui.CheckboxInputWidget( {} );
							dialog.fieldset.addItems( [
								new OO.ui.FieldLayout(
									dialog.options.notifyBiggest,
									{
										align: 'inline',
										label: self.msg( 'option-notify-biggest', dialog.maggiore )
									}
								)
							] );
						}
						dialog.options.notifyTopic1 = new OO.ui.TextInputWidget();
						self.autocompletaArgomento( dialog.options.notifyTopic1 );
						dialog.fieldset.addItems( [
							new OO.ui.FieldLayout(
								dialog.options.notifyTopic1,
								{
									align: 'left',
									label: self.msg( 'option-notify-topics' )
								}
							)
						] );
						dialog.options.notifyTopic2 = new OO.ui.TextInputWidget();
						self.autocompletaArgomento( dialog.options.notifyTopic2 );
						dialog.fieldset.addItems( [
							new OO.ui.FieldLayout(
								dialog.options.notifyTopic2,
								{
									align: 'left',
									label: '+'
								}
							)
						] );
						// namespace "Discussioni progetto"
						dialog.pTalk = self.config.wikiprojectNamespace + 1;
						dialog.options.notifyWikiprojects = new OO.ui.CheckboxInputWidget( {
							disabled: self.namespaces[dialog.pTalk] === undefined
						} );
						dialog.fieldset.addItems( [
							new OO.ui.FieldLayout(
								dialog.options.notifyWikiprojects,
								{
									align: 'inline',
									label: self.msg( 'option-notify-wikiprojects' )
								}
							)
						] );
						// Forza il ridimensionamento della finestra
						dialog.manager.updateWindowSize( dialog );
						// Reimposta il pulsante 'procedi'
						dialog.actions
							.get( { actions: 'proceed' } )[0]
							.clearFlags()
							.setFlags( [ 'primary', 'constructive' ] )
							.setLabel( self.msg( 'dialog-button-final' ) );
					} );
				};
				PDC.Dialog.prototype.final = function () {
					var dialog = this,
					motivazione = dialog.options.reason.getValue().trim(),
					argomenti = $.map( [ 'notifyTopic1', 'notifyTopic2' ], function ( opt ) {
						return dialog.options[opt].getValue().trim();
					} )
					.filter( function ( el, i, arr ) {
						// Elimina i duplicati
						return el !== '' && arr.indexOf( el ) === i;
					} ),
					daNotificare = $.map( {
						notifyCreator: dialog.creatore.user,
						notifyBiggest: dialog.maggiore
					}, function ( user, opt ) {
						if (
							dialog.options[opt] !== undefined &&
							dialog.options[opt].isSelected()
						) {
							return self.namespaces[3] + ':' + user;
						}
					} );
					if (
						!dialog.options.notifyWikiprojects.isDisabled() &&
						dialog.options.notifyWikiprojects.isSelected()
					) {
						daNotificare = daNotificare.concat(
							$.map( argomenti, function ( argomento ) {
								return self.namespaces[dialog.pTalk] + ':' + argomento;
							} )
						);
					}
					self.creaProcedura( titolo, motivazione )
					.done( function ( procedura, numero ) {
						self.avvisoVoce( titolo, numero, argomenti )
						.done( function () {
							self.progresso( 'notify-wait' );
							self.notificaProcedura( titolo, daNotificare )
							.done( function () {
								window.location = mw.util.getUrl( procedura );
							} )
							.fail( function () {
								self.errore( 'notify-error' );
							} );
						} )
						.fail( function () {
							self.errore( 'nominate-error' );
						} );
						self.progresso( 'nominate-wait' );
					} )
					.fail( function () {
						self.errore( 'new-nomination-error' );
					} );
					self.progresso( 'new-nomination-wait' );
				};
				PDC.Dialog.prototype.getActionProcess = function ( action ) {
					return PDC.Dialog.super.prototype.getActionProcess.call( this, action )
						.next( function () {
							var dialog = this;
							if ( action === 'proceed' ) {
								if ( dialog.starting === true ) {
									dialog.starting = false;
									dialog.proceed();
								} else {
									dialog.options.reason.isValid()
									.done( function ( isValid ) {
										if ( isValid ) {
											dialog.final();
										}
									} );
								}
							} else {
								return this.close();
							}
						}, this );
				};
				var windowManager = new OO.ui.WindowManager();
				$( 'body' ).append( windowManager.$element );
				self.dialog = new PDC.Dialog();
				windowManager.addWindows( [ self.dialog ] );
				windowManager.openWindow( self.dialog );
			} );
		},

		switchButtons: function ( $obj, show ) {
			var m = show ? 'show' : 'hide';
			if ( show ) {
				$obj.next().remove();
			}
			return $obj[m]();
		},

		/**
		 * Trasforma alcune frasi appositamente configurate
		 * in link per richiedere la cancellazione della pagina.
		 */
		autoRfd: function () {
			var self = this;
			if ( self.config.autoRfd.length === 0 ) {
				return;
			}
			$( 'div' ).each( function () {
				$( this )
				.contents()
				.filter( function () {
					// solo testo semplice
					return this.nodeType === this.TEXT_NODE;
				} )
				.each( function () {
					var htmlDiv = this;
					$.each( self.config.autoRfd, function ( replIdx, replParts ) {
						// cerca la frase intera,
						var find = htmlDiv.textContent.indexOf( replParts.join( '' ) );
						if ( find !== -1 ) {
							// ...la isola
							var node = htmlDiv.splitText( find + replParts[0].length );
							// ...e la rende cliccabile
							$( node.splitText( replParts[1].length ).previousSibling )
							.wrap( '<a>' ).parent()
							.attr( {
								href: '#',
								title: self.msg( 'menu-link-tooltip' )
							} )
							.click( function ( event ) {
								event.preventDefault();
								self.proceduraGuidata( mw.config.get( 'wgPageName' ) );
							} );
						}
					} );
				} );
			} );
		},

		/**
		 * Genera il contenitore per pulsanti che richiedono permessi di amministratore.
		 * @param {Object} stato - Lo stato della procedura di cancellazione
		 * @return {jQuery}
		 */
		buildSysopButtons: function ( stato ) {
			var self = this,
			$sysopButtons = $( '<div>' )
			.attr( 'id', 'PDC-toolbox-sysop' )
			.append( [
				// Pulsante "avvia votazione" con effetto immediato
				$( '<button>' )
				.addClass( 'mw-ui-button mw-ui-constructive' )
				.attr( !stato.votazione && stato.consensuale ? {} : { disabled: 'disabled' } )
				.text( self.msg( 'toolbox-vote-start' ) )
				.click( function ( event ) {
					event.preventDefault();
					var $cont = $( this ).prev();
					$cont.next().remove();
					$cont.after( '<p>' + self.msg( 'toolbox-vote-start-wait' ) + '</p>' );
					self.avviaVotazione( mw.config.get( 'wgPageName' ) )
					.done( function () {
						window.location.reload();
					} )
					.fail( function () {
						$cont.next().remove();
						$cont.after( self.msg( 'toolbox-vote-start-error' ) );
					} );
				} ),
				'&nbsp;',
				// Pulsante "chiudi la procedura" con conferma richiesta
				$( '<button>' )
				.addClass( 'mw-ui-button mw-ui-progressive' )
				.text( self.msg( 'toolbox-close' ) )
				.click( function ( event ) {
					event.preventDefault();
					$( '<div>' )
					.append( [
						// Cancellare la pagina?
						self.msg( 'toolbox-close-delete' ),
						'<br>',
						// Sì
						$( '<button>' )
						.addClass( 'mw-ui-button mw-ui-destructive' )
						.text( self.msg( 'toolbox-close-delete-yes' ) )
						.click( function ( event ) {
							event.preventDefault();
							var $div = $( this ).parent(),
								modalità = stato.consensuale ? 'consensuale' : 'simple';
							self.progresso( 'toolbox-close-delete-wait', $div );
							self.cancellaPagina( stato.pagina, mw.config.get( 'wgPageName' ), modalità )
							.done( function () {
								self.progresso( 'toolbox-close-notice-wait', $div );
								self.avvisoCancellata( mw.config.get( 'wgPageName' ), modalità )
								.done( function () {
									self.progresso( 'toolbox-close-protect-wait', $div );
									self.proteggiPagina( mw.config.get( 'wgPageName' ) )
									.done( function () {
										self.progresso( 'toolbox-purge-wait', $div );
										self.purgaPagina( mw.config.get( 'wgPageName' ) )
										.done( function () {
											window.location.reload();
										} );
									} )
									.fail( function ( code, info ) {
										self.errore( 'toolbox-close-protect-error', info, $div );
									} );
								} )
								.fail( function ( code, info ) {
									self.errore( 'toolbox-close-notice-error', info, $div );
								} );
							} )
							.fail( function ( code, info ) {
								self.errore( 'toolbox-close-delete-error', info, $div );
							} );
						} ),
						'&nbsp;',
						// No
						$( '<button>' )
						.addClass( 'mw-ui-button mw-ui-constructive' )
						.text( self.msg( 'toolbox-close-delete-no' ) )
						.click( function ( event ) {
							event.preventDefault();
							var $div = $( this ).parent();
							self.mantenuta( stato.pagina, votazione, numero, favorevoli, contrari )
							.done( function () {
								self.progresso( 'toolbox-close-protect-wait', $div );
								self.proteggiPagina( mw.config.get( 'wgPageName' ) )
								.done( function () {
									self.progresso( 'toolbox-purge-wait', $div );
									self.purgaPagina( mw.config.get( 'wgPageName' ) )
									.done( function () {
										window.location.reload();
									} );
								} )
								.fail( function ( code, info ) {
									self.errore( 'toolbox-close-protect-error', info, $div );
								} );
							} )
							.fail( function ( code, info ) {
								self.errore( 'toolbox-close-kept-error', info, $div );
							} );
							self.progresso( 'toolbox-close-kept-wait', $div );
						} ),
						'&nbsp;',
						// Annulla
						$( '<button>' )
						.addClass( 'mw-ui-button' )
						.text( self.msg( 'toolbox-close-cancel' ) )
						.click( function ( event ) {
							event.preventDefault();
							self.switchButtons( $sysopButtons, true );
						} )
					] )
					.insertAfter( self.switchButtons( $sysopButtons ) );
				} )
			] );
			return $sysopButtons;
		},

		/**
		 * Se lo script è utile nella pagina, carica le dipendenze e lo avvia.
		 */
		preInit: function () {
			if (
				// pagina esistente
				mw.config.get( 'wgArticleId' ) > 0 &&
				// in modalità di visualizzazione
				mw.config.get( 'wgAction' ) === 'view' &&
				// solo utenti registrati
				mw.user.isAnon() === false &&
				// niente redirect
				mw.config.get( 'wgIsRedirect' ) === false &&
				// niente diff
				mw.util.getParamValue( 'diff' ) === null &&
				// solo ultime versioni
				mw.util.getParamValue( 'oldid' ) === null
			) {
				var self = this,
				sp = mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ).split( '/' ),
				modes = {
					// visualizzare la casella "Strumenti PDC"?
					toolbox: ( sp.length > 1 && sp[0] === self.config.base ),
					// aggiungere il link per la finestra di dialogo alla sezione "Strumenti" della barra laterale?
					portlet: (
						mw.config.get( 'wgIsArticle' ) === true &&
						self.config.actInNamespaces.indexOf( mw.config.get( 'wgNamespaceNumber' ) ) !== -1
					)
				},
				values = $.map( modes, function ( val ) {
					return val;
				} );
				if ( values.indexOf( true ) !== -1 ) {
					self.modes = modes;
					mw.loader.using( self.dependencies.general )
					.done( function () {
						self.init();
					} );
				}
			}
		},

		/**
		 * Avvia lo script senza caricare le dipendenze.
		 */
		init: function () {
			var self = this;
			// Prepara i messaggi nella lingua dell'utente, e in alternativa in inglese.
			self.i18n = $.extend( true, ( self.i18n.en || {} ), ( self.i18n[mw.config.get( 'wgUserLanguage' )] || {} ) );
			$.each( self.i18n, function ( k, v ) {
				mw.messages.set( 'PDC-' + k, v );
			} );
			if ( self.modes.portlet === true ) {
				self.inCancellazione( mw.config.get( 'wgPageName' ) )
				.done( function ( val ) {
					if ( val === false ) {
						self.verificaRequisiti()
						.done( function ( accettato ) {
							if ( accettato !== true ) {
								return;
							}
							$( mw.util.addPortletLink( 'p-tb', '#', self.msg( 'menu-link-label' ), 'PDC-init', self.msg( 'menu-link-tooltip' ) ) )
							.click( function ( event ) {
								event.preventDefault();
								self.proceduraGuidata( mw.config.get( 'wgPageName' ) );
							} );
							self.autoRfd();
						} );
					}
				} );
			}
			if ( self.modes.toolbox === true ) {
				self.verificaRequisiti()
				.done( function ( accettato ) {
					if ( accettato !== true ) {
						return;
					}
					self.titoloPagina( mw.config.get( 'wgPageName' ) )
					.done( function ( titoloPagina ) {
						if ( !titoloPagina ) {
							return;
						}
						self.statoProcedura( mw.config.get( 'wgPageName' ) )
						.done( function ( stato ) {
							stato.pagina = titoloPagina;
							var prorogabile = false,
							adesso = new Date(),
							creazione,
							apertaDaGiorni;
							if ( stato && stato.creazione && stato.creazione.timestamp ) {
								creazione = new Date( stato.creazione.timestamp );
								apertaDaGiorni = ( adesso - creazione ) / 86400000;
								if ( stato.terminata === false && !stato.prorogata && apertaDaGiorni >= self.config.minDeferrableDays ) {
									prorogabile = true;
								}
							}
							var $toolbox = $( '<div>' )
							.attr( 'id', 'PDC-toolbox' )
							.addClass( 'toccolours' )
							.css( 'font-size', '100%')
							.append(
								$( '<h3>' )
								.text( self.msg( 'toolbox-title', stato.pagina ) )
							),
							statusMsg = self.msg( 'toolbox-open-generic' );
							if ( stato.terminata ) {
								statusMsg = self.msg( 'toolbox-closed' );
							} else if ( apertaDaGiorni ) {
								var days,
									user;
								if ( parseInt( apertaDaGiorni ) > 1 ) {
									days = self.msg( 'toolbox-days-ago', parseInt( apertaDaGiorni ) );
								} else if ( adesso.getDate() === creazione.getDate() ) {
									days = self.msg( 'toolbox-today' );
								} else {
									days = self.msg( 'toolbox-yesterday' );
								}
								if ( stato.creazione && stato.creazione.user ) {
									user = stato.creazione.user;
									user = '<a href="' + mw.util.getUrl( self.namespaces[2] + ':' + user ) + '">' + user + '</a>';
								} else {
									user = self.msg( 'toolbox-user-unknown' );
								}
								statusMsg = self.msg( 'toolbox-open', days, user );
							}
							$( '<p>' )
							.append( statusMsg )
							.appendTo( $toolbox );

							/**
							 * Contenitore per pulsanti che non richiedono permessi particolari.
							 */
							var $publicButtons = $( '<div>' )
							.attr( 'id', 'PDC-toolbox-public' )
							.appendTo( $toolbox );

							// Pulsante "aggiorna" con effetto immediato (innocuo)
							$( '<button>' )
							.addClass( 'mw-ui-button' )
							.text( self.msg( 'toolbox-purge' ) )
							.click( function ( event ) {
								event.preventDefault();
								var $box = $( this ).parent();
								self.progresso( 'toolbox-purge-wait', $box );
								self.purgaPagina( mw.config.get( 'wgPageName' ) )
								.done( function () {
									window.location.reload();
								} );
							} )
							.appendTo( $publicButtons );
							$publicButtons.append( '&nbsp;' );
							if ( !stato.terminata ) {
								if ( stato.consensuale ) {
									var deferButtonMsg;
									if ( prorogabile ) {
										deferButtonMsg = 'toolbox-defer';
									} else if ( stato.prorogata ) {
										deferButtonMsg = 'toolbox-already-deferred';
									} else {
										deferButtonMsg = 'toolbox-not-deferrable-yet';
									}
									// Pulsante "proroga" con conferma richiesta
									$( '<button>' )
									.addClass( 'mw-ui-button mw-ui-progressive' )
									.text( self.msg( deferButtonMsg ) )
									.attr( prorogabile ? {} : { disabled: 'disabled' } )
									.click( function ( event ) {
										event.preventDefault();
										$( '<div>' )
										.append( [
											// Di quanti giorni?
											$( '<label>' )
											.attr( 'for', 'PDC-defer-days' )
											.text( self.msg( 'toolbox-defer-days' ) ),
											$( '<input>' )
											.addClass( 'mw-ui-input' )
											.attr( {
												type: 'number',
												id: 'PDC-defer-days',
												min: self.config.deferMinDays,
												max: self.config.deferMaxDays
											} )
											.val( self.config.deferDefaultDays ),
											// Conferma
											$( '<button>' )
											.addClass( 'mw-ui-button mw-ui-constructive' )
											.text( self.msg( 'toolbox-defer' ) )
											.click( function ( event ) {
												event.preventDefault();
												var $box = $( this ).parent();
												self.progresso( 'toolbox-defer-wait', $box );
												self.prorogaProcedura( mw.config.get( 'wgPageName' ), parseInt( $( this ).prev().val() ) )
												.done( function () {
													self.progresso( 'toolbox-purge-wait', $box );
													self.purgaPagina( mw.config.get( 'wgPageName' ) )
													.done( function () {
														window.location.reload();
													} );
												} )
												.fail( function ( code, info ) {
													self.errore( 'toolbox-defer-error', info, $box );
												} );
											} ),
											'&nbsp;',
											// Annulla
											$( '<button>' )
											.addClass( 'mw-ui-button' )
											.text( self.msg( 'toolbox-defer-cancel' ) )
											.click( function ( event ) {
												event.preventDefault();
												self.switchButtons( $publicButtons, true );
											} )
										] )
										.insertAfter( self.switchButtons( $publicButtons ) );
									} )
									.appendTo( $publicButtons );
								} else {
									// Pulsante "passa alla modalità consensuale" con conferma richiesta
									$( '<button>' )
									.addClass( 'mw-ui-button mw-ui-progressive' )
									.text( self.msg( 'toolbox-consensuale' ) )
									.click( function ( event ) {
										event.preventDefault();
										$( '<div>' )
										.append( [
											// Motivazione
											$( '<textarea>' )
											.addClass( 'mw-ui-input' )
											.css( 'background', '#fff' )
											.attr( 'placeholder', self.msg( 'toolbox-consensuale-reason' ) ),
											// Conferma
											$( '<button>' )
											.addClass( 'mw-ui-button mw-ui-constructive' )
											.text( self.msg( 'toolbox-consensuale' ) )
											.click( function ( event ) {
												event.preventDefault();
												var $box = $( this ).parent();
												self.consensuale( mw.config.get( 'wgPageName' ), $( this ).prev().val() )
												.done( function () {
													window.location.reload();
												} )
												.fail( function ( code, info ) {
													self.errore( 'toolbox-consensuale-error', info, $box );
												} );
												self.progresso( 'toolbox-consensuale-wait', $box );
											} ),
											'&nbsp;',
											// Annulla
											$( '<button>' )
											.addClass( 'mw-ui-button' )
											.text( self.msg( 'toolbox-consensuale-cancel' ) )
											.click( function ( event ) {
												event.preventDefault();
												self.switchButtons( $publicButtons, true );
											} )
										] )
										.insertAfter( self.switchButtons( $publicButtons ) );
									} )
									.appendTo( $publicButtons );
								}
								$publicButtons.append( '&nbsp;' );
								// Pulsante "annulla la procedura" con conferma richiesta
								$( '<button>' )
								.addClass( 'mw-ui-button mw-ui-progressive' )
								.text( self.msg( 'toolbox-cancel' ) )
								.click( function ( event ) {
									event.preventDefault();
									$( '<div>' )
									.append( [
										// Motivazione
										$( '<textarea>' )
										.addClass( 'mw-ui-input' )
										.css( 'background', '#fff' )
										.attr( 'placeholder', self.msg( 'toolbox-cancel-reason' ) ),
										// Conferma
										$( '<button>' )
										.addClass( 'mw-ui-button mw-ui-destructive' )
										.text( self.msg( 'toolbox-cancel' ) )
										.click( function ( event ) {
											event.preventDefault();
											self.annullaProcedura( mw.config.get( 'wgPageName' ), $( this ).prev().val() )
											.done( function () {
												window.location.reload();
											} );
											self.progresso( 'toolbox-cancel-wait', $( this ).parent() );
										} ),
										'&nbsp;',
										// Annulla
										$( '<button>' )
										.addClass( 'mw-ui-button' )
										.text( self.msg( 'toolbox-cancel-cancel' ) )
										.click( function ( event ) {
											event.preventDefault();
											self.switchButtons( $publicButtons, true );
										} )
									] )
									.insertAfter( self.switchButtons( $publicButtons ) );
								} )
								.appendTo( $publicButtons );
							}
							if ( self.sysop && stato.terminata === false ) {
								// Strumenti per amministratori
								$toolbox
								.append( [
									$( '<h4>' )
									.text( self.msg( 'toolbox-sysops' ) ),
									self.buildSysopButtons( stato )
								] );
							}
							$toolbox.prependTo( '#mw-content-text' );
						} );
					} );
				} );
			}
		}
	};
	PDC.preInit();
	window.PDC = PDC;
}( mediaWiki, jQuery ) );