/**
* Gadget-toolbar.js
* Permette di aggiungere ulteriori pulsanti alla toolbar di modifica
* e di selezionarli tramite una finestra di opzioni.
*
* @author ]
*/
/*jshint evil: true */
/*global mediaWiki, jQuery, gadgetToolbarButtons */
/* <nowiki> */
( function ( mw, $ ) {
'use strict';
var sign = ' --~~~~',
configVersion = 1,
optionname = 'userjs-gadget-toolbar',
iconOptions = '//upload.wikimedia.org/wikipedia/commons/1/1e/Button_ns-basics.png',
hotkeys,
userConfig,
groups = {
formattazione: { label: 'Formattazione' },
avvisivoci: { label: 'Avvisi voci' },
messaggiutente: { label: 'Messaggi utente' },
altro: { label: 'Altro' }
};
// ===========================
// Funzioni di utilità
// ===========================
function padleft0( num ) {
return ( num < 10 ? '0' : '' ) + num;
}
function makeTimestamp( date ) {
return date.getUTCFullYear() + '-' + padleft0( date.getUTCMonth() + 1 ) + '-' + padleft0( date.getUTCDate() ) +
'T' + padleft0( date.getUTCHours() ) + ':' + padleft0( date.getUTCMinutes() ) + ':00Z';
}
function endsWith( str, suffix ) {
return str.length >= suffix.length && str.indexOf( suffix, str.length - suffix.length ) !== -1;
}
function readUserConfig() {
var config, ret = { buttons: , version: configVersion };
if ( mw.user.options.exists( optionname ) ) {
config = JSON.parse( mw.user.options.get( optionname ) );
if ( config.version === configVersion ) {
ret = config;
}
}
return ret;
}
function writeUserConfig( config ) {
new mw.Api().postWithToken(
'csrf',
{
action: 'options',
optionname: optionname,
optionvalue: config,
}
)
.done( function ( data ) {
var msg;
if ( data && data.options === 'success' ) {
mw.notify( 'La configurazione dei pulsanti è stata aggiornata.' );
} else {
msg = data && data.error ? ': ' + data.error.code + ' ' + data.error.info : '';
mw.notify( 'Errore nell\'aggiornare la configurazione dei pulsanti ' + msg );
}
} );
}
function readUserButtons( readHandler ) {
var title = 'User:' + mw.config.get( 'wgUserName' ) + '/toolbarbuttons.js';
$.ajax( {
url: mw.config.get( 'wgScript' ),
data: {
title: title,
action: 'raw'
},
dataType: 'text'
} )
.done( function ( data ) {
var buttons = ;
try {
// non si può usare JSON perché i pulsanti contengono anche funzioni
eval( data );
if ( window.gadgetToolbarUserButtons !== undefined &&
$.isPlainObject( window.gadgetToolbarUserButtons ) ) {
buttons = window.gadgetToolbarUserButtons;
}
} catch ( e ) {
mw.notify( 'La pagina di configurazione ' + title + ' contiene errori.' );
} finally {
readHandler( buttons );
}
} )
.fail( function ( jqXHR, textStatus, errorThrown ) {
readHandler( );
} );
}
function buildDescr( button ) {
var ret = '';
if ( button.text ) {
ret = $( '<div>' ).text( 'Inserisce il testo ' +
( button.text.pre || '' ) + ' ' +
( button.text.post || '' ) + ' nella pagina.' ).html();
} else if ( button.template ) {
var $a = $( '<a>' )
.attr( 'href', 'https://wikifreehand.com/it/Template:' + button.template.name )
.attr( 'target', '_blank' )
.attr( 'tabindex', '-1' )
.css( 'color', '#2e45ad' )
.text( button.template.name );
ret = ;
}
return ret;
}
/**
* Aggiunge l'autocompletamento con gli ultimi contributi, non più vecchi di un'ora.
*/
function addAutocompleteContribs( inputEl ) {
var dateEnd = new Date();
dateEnd.setHours( dateEnd.getHours() - 1 );
new mw.Api().get( {
action: 'query',
list: 'usercontribs',
ucuser: mw.config.get( 'wgUserName' ),
uclimit: '10',
ucend: makeTimestamp( dateEnd ),
ucdir: 'older',
ucprop: 'title',
} )
.done( function ( data ) {
var contribs = ;
$.each( data.query.usercontribs, function( i, usercontrib ) {
if ( $.inArray( usercontrib.title, contribs ) === -1 ) {
contribs.push( usercontrib.title );
}
});
inputEl.autocomplete( { source: contribs } );
} );
}
/**
* Aggiunge l'autocompletamento per i nomi utente.
*/
function addAutocompleteUsers( inputEl ) {
inputEl.autocomplete( {
source: function( request, response ) {
new mw.Api().get( {
action: 'query',
list: 'allusers',
aulimit: '10',
auprefix: request.term,
} )
.done( function ( data ) {
var users = ;
$.each( data.query.allusers, function( i, user ) {
users.push( user.name );
});
response( users );
} );
}
} );
}
// =======================
// Finestra opzioni
// =======================
function buildRow( id, button ) {
var $tr = $( '<tr>' );
$( '<td>' ).html( '<img src="' + button.icon + '"/> ' + id ).appendTo( $tr );
$( '<td>' ).append( button.descr || buildDescr( button ) ).appendTo( $tr );
$( '<td>' ).append( $( '<input>' ).data( 'id', id )
.attr( 'type', 'checkbox' ).attr( 'checked', $.inArray( id, userConfig.buttons ) > -1 ) ).appendTo( $tr );
return $tr;
}
function buildTable() {
var $table, $thead, $tr;
$table = $( '<table>' )
.attr( 'border', '0' )
.attr( 'cellpadding', '0' )
.attr( 'cellspacing', '0' )
.attr( 'width', '100%' );
$thead = $( '<thead>' ).appendTo( $table );
$tr = $( '<tr>' ).appendTo( $thead );
$( '<th>' ).text( 'Pulsante' ).appendTo( $tr );
$( '<th>' ).text( 'Descrizione' ).appendTo( $tr );
$( '<th>' ).text( '' ).appendTo( $tr );
$( '<tbody>' ).appendTo( $table );
return $table;
}
/**
* Visualizza la finestra delle opzioni per selezionare i pulsanti.
*/
function showConfigDialog() {
var $div, $ul;
if ( $( '#gtb-dialog-options' ).hasClass( 'ui-dialog-content' ) ) {
$( '#gtb-dialog-options' ).dialog( 'open' );
return;
}
$div = $( '<div>' ).attr( 'id', 'tabs' );
$ul = $( '<ul>' ).appendTo( $div );
$.each( groups, function ( key, group ) {
var $a = $( '<a>' ).attr( 'href', '#tabs-' + key ).text( group.label );
$( '<li/>' ).append( $a ).appendTo( $ul );
group.table = buildTable();
} );
$.each( gadgetToolbarButtons, function ( id, button ) {
groups.table.find( 'tbody' ).append( buildRow( id, button ) );
} );
$.each( groups, function ( key, group ) {
$( '<div>' ).addClass( 'gtb-tablecontainer' ).attr( 'id', 'tabs-' + key )
.append( group.table )
.appendTo( $ul );
} );
$( '#gtb-dialog-options' ).html( $div ).tabs();
// visualizza il dialog
$( '#gtb-dialog-options' ).dialog( {
title: '<img src="' + iconOptions + '"/> Configurazione pulsanti toolbar',
width: 700,
resizable: false,
modal: true,
open: function( event, ui ) {
$( '#gtb-dialog-options' ).tabs( 'option', 'active', 0 );
},
buttons: {
'Salva': function () {
var newConfig, newConfigJSON;
// genera la nuova configurazione
newConfig = $( '#gtb-dialog-options' ).find( 'tr:has( td )' ).map( function () {
var $input = $( this ).find( 'input' ).eq( 0 );
return $input.prop( 'checked' ) ? : null;
} ).get();
newConfig = { buttons: newConfig, version: configVersion };
newConfigJSON = JSON.stringify( newConfig );
// se necessario scrive la configurazione
if ( newConfigJSON === JSON.stringify( userConfig ) ) {
mw.notify( 'I pulsanti non sono stati modificati.' );
} else {
writeUserConfig( newConfigJSON );
userConfig = newConfig;
addButtons();
}
$( this ).dialog( 'close' );
},
'Annulla': function () {
$( this ).dialog( 'close' );
}
}
} );
}
// =====================================
// Finestra parametri per template
// =====================================
function buildInputEl( id, val ) {
var inputEl;
switch ( val.type ) {
case 'textbox':
inputEl = $( '<input/>' ).attr( 'id', id ).attr( 'type', 'text' ).attr( 'size', 50 );
if ( val.autocomplete ) {
mw.loader.using( 'jquery.ui' )
.done( function () {
switch ( val.autocomplete ) {
case 'contribs':
addAutocompleteContribs( inputEl );
break;
case 'users':
addAutocompleteUsers( inputEl );
break;
// supporto per eventuali altri tipi di autocompletamento
default:
break;
}
} )
.fail( function () {
console.error( 'Impossibile avviare l\'accessorio "toolbar".' );
} );
}
break;
case 'combobox':
inputEl = $( '<select>' ).attr( 'id', id ).css( 'width', '200px' );
$.each( val.value, function ( i, option ) {
$( '<option>' ).html( option ).appendTo( inputEl );
} );
break;
case 'checkbox':
inputEl = $( '<input/>' ).attr( 'id', id ).attr( 'type', 'checkbox' ).attr( 'checked', val.value );
break;
default:
break;
}
return inputEl;
}
/**
* Visualizza la finestra di dialogo per richiedere i parametri dei template.
*/
function showTemplateDialog( button ) {
var $dialog, $fieldset, template = button.template;
// crea l'html del dialog
$dialog = $( '#gtb-dialog-template' ).html( buildDescr( button ) );
$fieldset = $( '<fieldset>' ).css( 'border-color', 'gray' ).appendTo( $dialog );
$( '<legend>' ).text( 'Parametri' ).appendTo( $fieldset );
$.each( template.params, function ( id, val ) {
var inputEl = buildInputEl( id, val );
$( '<label>' ).attr( 'for', id ).text( val.label + ':' ).appendTo( $fieldset );
$fieldset.append( '<br/>', inputEl, '<br/>' );
} );
// visualizza il dialog
$dialog.dialog( {
title: '<img src="' + button.icon + '"/> ' + button.label,
width: 500,
resizable: false,
modal: false,
buttons: {
'Inserisci': function () {
var params = {};
$dialog.find( 'input:text,select' ).each( function () {
params = $.trim( $( this ).val() );
} );
$dialog.find( 'input:checkbox' ).each( function () {
params = $( this ).prop( 'checked' );
} );
dumpTemplate( template, params );
setSummary( button );
$( this ).dialog( 'close' );
},
'Annulla': function () {
$( this ).dialog( 'close' );
}
}
} );
}
// =====================================
// Inserimento e gestione pulsanti
// =====================================
/**
* Inserisce il template nell'area di testo.
*/
function dumpTemplate( template, params ) {
var text, templateParams;
if ( template.format ) {
templateParams = template.format( params || {} );
}
text = ( template.noinclude ? '<noinclude>' : '' ) +
'{{' + ( template.subst ? 'subst:' : '' ) +
template.name + ( templateParams || '' ) + '}}' +
( template.sign ? sign : '' ) +
( template.noinclude ? '</noinclude>' : '' ) +
( template.extratext ? template.extratext : '' );
if ( template.position === 'top' ) {
$( '#wpTextbox1' ).textSelection( 'setSelection', { start: 0, end: 0 } );
$( '#wpTextbox1' ).textSelection( 'encapsulateSelection', { post: text + '\n' } );
} else if ( template.position === 'bottom' ) {
$( '#wpTextbox1' ).select().val( $( '#wpTextbox1' ).val() + '\n' + text );
} else {
$( '#wpTextbox1' ).textSelection( 'encapsulateSelection', { pre: text } );
}
}
/**
* Valorizza il campo oggetto della modifica.
*/
function setSummary( button ) {
var text, replace = false;
if ( button.summary !== undefined ) {
text = button.summary;
} else if ( button.template ) {
if ( $( '#wpMinoredit' ).length ) {
text = '+' + button.template.name;
} else if ( button.group === 'messaggiutente' ) {
text = 'Avviso';
replace = true;
}
}
if ( text ) {
$( '#wpSummary' ).val( function ( i, prevText ) {
return replace ? text : prevText + ( prevText.length > 0 ? ' ' : '' ) + text;
} );
}
}
/**
* Gestore del click sui pulsanti della toolbar (avanzata e classica).
*/
function clickHandler( button ) {
var dialog = false;
if ( button.text ) {
$( '#wpTextbox1' ).textSelection( 'encapsulateSelection', button.text );
} else if ( button.execute ) {
button.execute();
} else if ( button.template ) {
if ( button.template.params ) {
dialog = true;
showTemplateDialog( button );
// setSummary avviene alla conferma del dialog
} else {
dumpTemplate( button.template );
}
}
if ( !dialog ) {
setSummary( button );
}
}
/**
* Ritorna true se il namespace è corretto per il pulsante.
*/
function rightNs( button ) {
var ret = true;
if ( button.ns !== undefined ) {
if ( typeof button.ns === 'function' ) {
ret = button.ns();
} else if ( $.isArray( button.ns ) ) {
ret = $.inArray( mw.config.get( 'wgNamespaceNumber' ), button.ns ) !== -1;
}
}
return ret;
}
/**
* Inizializza il pulsante per l'utilizzo nella toolbar.
*/
function initButton( id, button ) {
button.label = button.tooltip = id;
if ( button.hotkey ) {
button.hotkey = button.hotkey.toUpperCase();
button.tooltip += ' ';
hotkeys = button;
}
}
/**
* Aggiunge i pulsanti alla toolbar avanzata (wikiEditor).
*/
function addButtonsAdvancedToolbar() {
$.each( groups, function ( key, buttons ) {
groups.tools = {};
} );
$.each( userConfig.buttons, function( i, id ) {
var button = gadgetToolbarButtons;
if ( button && rightNs( button ) ) {
initButton( id, button );
groups.tools = {
label: button.tooltip,
type: 'button',
icon: button.icon,
action: {
type: 'callback',
execute: function ( context ) {
clickHandler( button );
}
}
};
}
} );
var tb = {
sections: {
altro: {
type: 'toolbar',
label: 'Altri pulsanti',
groups: {
opzioni: {
label: 'Opzioni',
tools: {
opzioni: {
type: 'button',
label: 'Opzioni',
icon: iconOptions,
action: {
type: 'callback',
execute: function ( context ) {
showConfigDialog();
}
}
}
}
}
}
}
}
};
$.each( groups, function ( key, group ) {
tb.sections.altro.groups = { label: group.label, tools: group.tools };
} );
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', tb );
}
/**
* Aggiunge i pulsanti alla toolbar "classica".
*/
function addButtonsClassicToolbar() {
$.each( userConfig.buttons, function( i, id ) {
var button = gadgetToolbarButtons;
if ( button && rightNs( button ) ) {
initButton( id, button );
$( '<img/>' )
.attr( 'src', button.icon )
.attr( 'title', button.tooltip )
.css( 'cursor', 'pointer' )
.addClass( 'gtb-button' )
.click( function () {
clickHandler( button );
} )
.appendTo( '#toolbar' );
}
} );
}
function addButtons( userButtons ) {
hotkeys = {};
// unisce userButtons a gadgetToolbarButtons
if ( userButtons ) {
$.extend( gadgetToolbarButtons, userButtons );
}
// aggiunge i pulsanti alla toolbar
if ( mw.user.options.get( 'usebetatoolbar' ) ) {
mw.loader.using( , function () {
// rimozione pulsanti precedenti
if ( !userButtons ) {
$( '#wpTextbox1' ).wikiEditor( 'removeFromToolbar', { 'section': 'altro' } );
}
addButtonsAdvancedToolbar();
// secondo tentativo per ]
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-doneInitialSections', function () {
if ( !$( '#wikiEditor-ui-toolbar .tab-altro' ).length ) {
addButtonsAdvancedToolbar();
}
} );
} );
} else if ( mw.user.options.get( 'gadget-ClassicToolbar' ) ) {
mw.loader.using( 'ext.gadget.ClassicToolbar', function () {
if ( userButtons ) {
mw.toolbar.addButton( {
imageFile: iconOptions,
speedTip: 'Opzioni',
onClick: showConfigDialog
} );
} else {
// rimozione pulsanti precedenti
$( '.gtb-button' ).remove();
}
addButtonsClassicToolbar();
});
}
}
/**
* Installa il gestore per gli hotkeys
*/
function installHotkeyHandler() {
$( '#wpTextbox1' ).keypress( function ( event ) {
var button, help = '';
if ( event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ) {
if ( event.which === 72 || event.which === 104 ) {
event.preventDefault();
$.each( hotkeys, function ( hotkey, button ) {
help += button.label + ' = Alt+' + hotkey + '\n';
} );
alert( 'Hotkey attivi:\n' + help );
} else {
button = hotkeys;
if ( button ) {
event.preventDefault();
clickHandler( button );
}
}
}
} );
}
/**
* Verifica se la pagina userà codeEditor
*/
function needCodeEditor() {
var title = mw.config.get( 'wgTitle' ), ns = mw.config.get( 'wgNamespaceNumber' );
return endsWith( title, '.js' ) || ( ns == 828 && !endsWith( title, '/man' ) );
}
$( function () {
if ( !needCodeEditor() ) {
mw.loader.using( , function () {
// lettura configurazione
userConfig = readUserConfig();
// setup dialog
$( '<div>' ).attr( 'id', 'gtb-dialog-options' ).appendTo( 'body' );
$( '<div>' ).attr( 'id', 'gtb-dialog-template' ).appendTo( 'body' );
// installa handler hotkeys
installHotkeyHandler();
// aggiunge i pulsanti
readUserButtons( function( userButtons ) {
addButtons( userButtons );
} );
} );
}
} );
}( mediaWiki, jQuery ) );
/* </nowiki> */