MediaWiki:Gadget-GadgetsPreferences.js
Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.
Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;
Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5./**
* GadgetsPreferences
*
* Library to make a gadget easily configurable by its users:
* - Declaration of preferences from within the code;
* - Storage in the user preferences (no edits are made);
* - Easy to use interface and common to all gadgets.
*
* It is not made to be activated directly by the user, but rather loaded
* as a dependency by other gadgets and/or user scripts.
*
* {{Projet:JavaScript/Script|GadgetsPreferences}}
* <nowiki>
*/
/* globals mw, OO, $ */
mw.loader.using( [ 'mediawiki.util', 'mediawiki.api' ], function () {
'use strict';
// Site-related parameters
const EDITPAGE = 'MediaWiki:Préférences_des_Gadgets';
const PREFIX = 'gprefs';
// I18N messages
const messages = {
'fr': {
'gprefs-portlet-label': '(gadgets)',
'gprefs-portlet-tooltip': 'Accéder aux préférences des gadgets',
'gprefs-savebutton-label': 'Enregistrer',
'gprefs-notif-success': 'Les préférences des gadgets ont été sauvegardées. La page va être rechargée pour les appliquer.',
'gprefs-notif-error': '',
}
};
mw.messages.set( messages.fr );
var lang = mw.config.get( 'wgUserLanguage' );
if ( lang !== 'fr' && lang in messages ) {
mw.messages.set( messages[ lang ] );
}
/**
* Widget displaying a color picker.
*
* @constructor
* @inherit
*/
var ColorInputWidget = function ( config ) {
// Configuration initialization
config = Object.assign( {
type: 'color',
}, config);
// Parent constructor
ColorInputWidget.parent.call( this, config );
// Properties
this.type = 'color';
this.readOnly = false;
this.required = false;
this.validate = null;
// Initialization
this.$element
.addClass( 'oo-ui-textInputWidget oo-ui-textInputWidget-type-' + this.type )
.append( this.$icon, this.$indicator );
this.$input.attr( 'type', config.type );
};
/**
* Manage user-configurable preferences.
*
* @constructor
* @param {boolean} loadUI Set to true to display the configuration interface on the current page.
*/
var GadgetsPreferences = function ( loadUI ) {
// Properties
this.loadUI = loadUI || false;
this.api = new mw.Api( { timeout: 7000 } );
this.config = {};
this.tabs = {};
// Graphical properties
this.layout;
this.saveButton;
this.ui;
if ( this.loadUI ) {
OO.inheritClass( ColorInputWidget, OO.ui.InputWidget );
this.createUI();
}
};
/**
* Allows a gadget to register preferences that should be user-configurable.
*
* The 'prefs' object should look like this:
* {
* pref1: { label: 'Preference 1', type: 'string', default: 'This is the default value' },
* secondpref: { label: 'Second preference', type: 'boolean', default: true, help: 'This is an optional help message.' },
* lastone: { label: 'Last one', type: 'number', default: 42, min: 0, max: 101 }
* }
*
* Type should be one of those: string, number, boolean
*
* @param {string} gadgetID Internal identifier used to identify the gadget.
* @param {string} label Text displayed in the UI to identify the gadget.
* @param {Object} prefs Object listing all the preferences of the gadget.
* @return {Object} Object binding prefIDs to their configured values.
*/
GadgetsPreferences.prototype.register = function ( gadgetID, label, prefs ) {
var prefID, pref,
result = {};
this.config[ gadgetID ] = prefs;
if ( this.loadUI ) {
this.createTab( gadgetID, label );
}
for ( prefID in this.config[ gadgetID ] ) {
pref = this.config[ gadgetID ][ prefID ];
pref.value = mw.user.options.get( 'userjs-' + PREFIX + '-' + gadgetID + '-' + prefID );
switch( pref.type ) {
case 'boolean':
if ( pref.value === 'true' ) {
pref.value = true;
} else if ( pref.value === 'false' ) {
pref.value = false;
} else {
pref.value = null;
}
break;
case 'number':
pref.value = parseFloat( pref.value );
break;
}
if ( pref.value === null || pref.value === undefined || Number.isNaN( pref.value ) ) {
pref.value = pref.default;
}
result[ prefID ] = pref.value;
if ( this.loadUI ) {
this.createField( gadgetID, prefID );
}
}
return result;
};
/**
* Get the value of a preference, previously registred.
*
* This will either be the value configured by the user, or the default one
* if not.
*
* @param {string} gadgetID Internal identifier of the current gadget.
* @param {string} prefID Internal identifier of the preference to get.
* @return {Mixed} the value of the given preference.
*/
GadgetsPreferences.prototype.get = function ( gadgetID, prefID ) {
if ( this.config[ gadgetID ] === undefined || this.config[ gadgetID ][ prefID ] === undefined ) {
return undefined;
}
return this.config[ gadgetID ][ prefID ].value;
};
/**
* Set the value of a preference, previously registred, and save it.
*
* @param {string} gadgetID Internal identifier of the current gadget.
* @param {string} prefID Internal identifier of the preference to set.
* @param {Mixed} value New value for the given preference.
* @return {jQuery.Promise} the value of the given preference.
*/
GadgetsPreferences.prototype.set = function ( gadgetID, prefID, value ) {
if ( this.config[ gadgetID ] === undefined || this.config[ gadgetID ][ prefID ] === undefined ) {
return false;
}
this.config[ gadgetID ][ prefID ].value = value;
return this.api.saveOption( 'userjs-' + PREFIX + '-' + gadgetID + '-' + prefID, value );
};
/**
* Create an empty IndexLayout and a save button as the bases of the UI.
*
* @private
*/
GadgetsPreferences.prototype.createUI = function () {
this.layout = new OO.ui.IndexLayout( {
expanded: false,
framed: false
} );
this.saveButton = new OO.ui.ButtonWidget( {
label: mw.msg( 'gprefs-savebutton-label' ),
flags: [ 'primary', 'progressive' ]
} );
this.saveButton.on( 'click', this.saveAll.bind( this ) );
this.ui = new OO.ui.Widget( {
content: [
new OO.ui.PanelLayout( {
expanded: false,
framed: true,
content: [ this.layout ],
classes: [ 'gprefs-panel' ]
} ),
this.saveButton
]
} );
this.ui.$element.hide(); // Hide it until a first tab is added
$( '#mw-content-text' ).append( this.ui.$element );
};
/**
* Add a new empty tab to the UI.
*
* @private
*/
GadgetsPreferences.prototype.createTab = function ( gadgetID, label ) {
this.tabs[ gadgetID ] = new OO.ui.TabPanelLayout( gadgetID, { label: label } );
this.layout.addTabPanels( [ this.tabs[ gadgetID ] ] );
this.ui.$element.show();
};
/**
* Add a new input field to the tab of the corresponding gadget.
*
* The field varies depending of the type of the preference.
*
* @private
*/
GadgetsPreferences.prototype.createField = function ( gadgetID, prefID ) {
var field, layout,
pref = this.config[ gadgetID ][ prefID ];
switch( pref.type ) {
case 'boolean':
field = new OO.ui.CheckboxInputWidget( {
selected: pref.value
} );
break;
case 'number':
field = new OO.ui.NumberInputWidget( {
value: pref.value,
min: pref.min,
max: pref.max,
} );
break;
case 'color':
field = new ColorInputWidget( {
value: pref.value
} );
break;
case 'string':
default:
field = new OO.ui.TextInputWidget( {
value: pref.value
} );
break;
}
pref.__field = field;
layout = new OO.ui.FieldLayout( field, {
align: 'left',
label: pref.label,
help: pref.help
} );
this.tabs[ gadgetID ].$element.append( layout.$element );
};
/**
* Fetch all values of the preferences from the UI and save them.
*
* This method is called when the user clicks on the save button on the UI.
*
* @private
*/
GadgetsPreferences.prototype.saveAll = function () {
var gadgetID, prefID, pref, key,
options = {};
this.ui.setDisabled( true );
for ( gadgetID in this.config ) {
for ( prefID in this.config[ gadgetID ] ) {
pref = this.config[ gadgetID ][ prefID ];
key = 'userjs-' + PREFIX + '-' + gadgetID + '-' + prefID;
switch( pref.type ) {
case 'boolean':
pref.value = pref.__field.isSelected();
break;
case 'number':
pref.value = pref.__field.getNumericValue();
break;
case 'color':
case 'string':
default:
pref.value = pref.__field.getValue();
break;
}
options[ key ] = pref.value;
}
}
return this.api.saveOptions( options ).then( function() {
this.ui.setDisabled( false );
mw.notification.notify( mw.msg( 'gprefs-notif-success' ), { autoHide: true } );
setTimeout( function() {
document.location.href = mw.util.getUrl();
}, 1250 );
}.bind( this ), function() {
this.ui.setDisabled( false );
mw.notification.notify( mw.msg( 'gprefs-notif-error' ), { type: 'error', autoHide: true } );
}.bind( this ) );
};
/**
* Main function.
*
* It instanciate the GadgetsPreferences object as mw.gadgetsPreferences
* and fires the 'gadgets-preferences.ready' hook.
*/
if ( mw.config.get( 'wgPageName' ) === EDITPAGE && mw.config.get( 'wgAction' ) === 'view' ) {
mw.loader.using( [ 'oojs-ui', 'mediawiki.notification' ], function() {
$( function () {
mw.gadgetsPreferences = new GadgetsPreferences( true );
mw.hook( 'gadgets-preferences.ready' ).fire();
} );
} );
} else {
mw.gadgetsPreferences = new GadgetsPreferences( false );
mw.hook( 'gadgets-preferences.ready' ).fire();
}
$( function () {
mw.util.addPortletLink( 'p-personal', mw.util.getUrl( EDITPAGE ), mw.msg( 'gprefs-portlet-label' ), 'pt-gadgetpreferences', mw.msg( 'gprefs-portlet-tooltip' ), undefined, '#pt-betafeatures' );
} );
} );
/* </nowiki> */