Extension:WikiEditor/Toolbar customization
The article explains the technical details of customizing the toolbar. It requires a basic level of understanding of JavaScript. Starting from MediaWiki 1.26, understanding and following the section Basic setup is crucial to your code working.
If you just need some quick code that you can copypaste into your user JS, which will just work out of the box, see the customizations library.
Basic setup
Before a script is able to manipulate the toolbar provided by WikiEditor, the following things must happen:
- Set the following in LocalSettings.php:
$wgAllowUserJs = true;
to allow users to setup their individual toolbar, or$wgUseSiteJs = true;
to setup the toolbar site-wide
- The module "ext.wikiEditor" needs to be loaded which is usually done by invoking the WikiEditor extension.
- Add the following code to your User:YourUserName/common.js (or your MediaWiki:Common.js for a site-wide change) to customize the toolbar:
var customizeToolbar = function () {
/* Your code goes here */
};
/* Check if view is in edit mode and that the required modules are available. Then, customize the toolbar … */
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
mw.loader.using( 'user.options' ).then( function () {
// This can be the string "0" if the user disabled the preference ([[phab:T54542#555387]])
if ( mw.user.options.get( 'usebetatoolbar' ) == 1 ) {
$.when(
mw.loader.using( 'ext.wikiEditor' ), $.ready
).then( customizeToolbar );
}
} );
}
… and replace the line /* Your code goes here */
by the code which defines each button added. Multiple snippets can be added by simply pasting them below each other, inside of the function customizeToolbar
.
Configuration structure
The toolbar widget is defined by a jQuery plugin from module jquery.wikiEditor. You can look at the configuration for the default toolbar on module jquery.wikiEditor.toolbar.config to see how you can modify the toolbar. Complete documentation is to be written shortly.
You can modify the toolbar even after it's been built (see example above) by calling the .wikiEditor()
function on the textarea. You will need to do this inside an $(document).ready(function() {});
call, as already mentioned.
action
- type: one of "encapsulate", "replace", "callback", "dialog"
- options: for "encapsulate" or "replace" types, carries options for jquery.textSelection module (pre, peri, post); regex, regexReplace
- execute: for "callback" type, a callable function which will be passed the WikiEditor context
- module: for "dialog" type, named reference to a WikiEditor add-in dialog module to open
Example:
'action': {
'type': 'encapsulate',
'options': {
'pre': "'''",
'periMsg': 'wikieditor-toolbar-tool-bold-example',
'post': "'''"
}
}
}
Another example from it.source, using callback:
action: {
type: 'callback',
execute: function(context){
indentSelection();
}
}
button
- type: "button"
- icon string required: short key name or URL to icon
- label string: non-localizable label string
- labelMsg string: key for localizable message string
- #action
toggle
Toggles are like buttons but with a binary state. The button can be pressed (active) or non-pressed. (Since 1.32)
- type: "toggle"
- icon string required: short key name or URL to icon
- label string: non-localizable label string
- labelMsg string: key for localizable message string
- #action
You need to track the state yourself, the toggle button will not do it for you. After a callback, update the state, find the buttonelement and call $button.data( 'setActive' )(boolean);
to make the button reflect the new state.
booklet
- type: "booklet"
- label string: non-localizable label string
- labelMsg string: key for localizable message string
- deferLoad boolean
- pages object: map of name keys to further objects:
- layout string required: 'table' or 'characters'
- label string: non-localizable label string
- labelMsg string: key for localizable message string
- headings string[]: array of objects? {textMsg: key} ⁇
- rows object[] optional?: array of objects? {'row key name': {message object?}}
- characters object[] optional?: array of strings of little character bits for insertion, or objects specifying actions:
- A string is interpreted as a character or string to insert at the cursor position.
- An array with 2 strings will use the first string as the label, and the second string as the string to be inserted.
- An object containing
action
andlabel
properties will perform the action (used to split text to insert before and after the selection).
Default sections
The default WikiEditor toolbar has the following sections:
- The main section which is always visible, with the groups format and insert.
- The advanced section, with the groups heading, format, size, insert and search.
- The characters section, with pages latin, latinextended, ipa, symbols, greek, cyrillic, arabic, hebrew, bangla, telugu, sinhala and gujarati
- The help section, with pages format, link, heading, list, file, reference and discussion.
Adding things
When using the code below, remember it depends on the module "ext.wikiEditor.toolbar" and needs to wait until the page is loaded. To avoid executing it before everything is properly initialized, you should copy it inside of the function customizeToolbar
defined above, or something equivalent.
The general format for adding things is as follows:
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
// Configuration object here
} );
Some specific examples are displayed in the sections below.
Add a toolbar section
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'sections': {
'emoticons': {
'type': 'toolbar', // Can also be 'booklet'
'label': 'Emoticons'
// or 'labelMsg': 'section-emoticons-label' for a localized label
}
}
} );
Add a group to an existing toolbar section
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'emoticons',
'groups': {
'faces': {
'label': 'Faces' // or use labelMsg for a localized label, see above
}
}
} );
Add a button to an existing toolbar group
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'emoticons',
'group': 'faces',
'tools': {
'smile': {
label: 'Smile!', // or use labelMsg for a localized label, see above
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gnome-face-smile.svg/22px-Gnome-face-smile.svg.png',
action: {
type: 'encapsulate',
options: {
pre: ":)" // text to be inserted
}
}
}
}
} );
Filter which namespaces should or should not generate added buttons
- Ex. - To have a button generated only when editing any Talk: namespace page, add the highlighted line below.
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'emoticons',
'group': 'faces',
'tools': {
'smile': {
label: 'Smile!', // or use labelMsg for a localized label, see above
filters: [ 'body.ns-talk' ],
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gnome-face-smile.svg/22px-Gnome-face-smile.svg.png',
action: {
type: 'encapsulate',
options: {
pre: ":)" // text to be inserted
}
}
}
}
} );
- Ex. - To have a button generated in all namespaces except the User: and Template: namespaces, add the highlighted line below.
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'emoticons',
'group': 'faces',
'tools': {
'smile': {
label: 'Smile!', // or use labelMsg for a localized label, see above
filters: [ 'body:not(.ns-2, .ns-10)' ],
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gnome-face-smile.svg/22px-Gnome-face-smile.svg.png',
action: {
type: 'encapsulate',
options: {
pre: ":)" // text to be inserted
}
}
}
}
} );
Add a drop-down picklist
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
section: 'main',
groups: {
list: {
tools: {
templates: {
label: 'Templates',
type: 'select',
list: {
'Ping-button': {
label: '{{Ping}}',
action: {
type: 'encapsulate',
options: {
pre: '{{Ping|',
post: '}}'
}
}
},
'Clear-button': {
label: 'Clear',
action: {
type: 'encapsulate',
options: {
pre: '{{Clear}}'
}
}
},
'Done-button': {
label: 'Done',
action: {
type: 'encapsulate',
options: {
pre: '{{Done}}'
}
}
}
}
}
}
}
}
} );
Add a booklet section
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'sections': {
'info': {
'type': 'booklet',
'label': 'Info'
}
}
} );
Add a page to an existing booklet section
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'info',
'pages': {
'colors': {
'layout': 'table',
'label': 'Colors',
'headings': [
{ text: 'Name' }, // or use textMsg for localization, see also above
{ text: 'Temperature' },
{ text: 'Swatch' }
],
'rows': [
{
'name': { text: 'Red' },
'temp': { text: 'Warm' },
'swatch': { html: '<div style="width:10px;height:10px;background-color:red;">' }
},
{
'name': { text: 'Blue' },
'temp': { text: 'Cold' },
'swatch': { html: '<div style="width:10px;height:10px;background-color:blue;">' }
},
{
'name': { text: 'Silver' },
'temp': { text: 'Neutral' },
'swatch': { html: '<div style="width:10px;height:10px;background-color:silver;">' }
}
]
}
}
} );
Add a special characters page
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'characters',
'pages': {
'emoticons': {
'layout': 'characters',
'label': 'Emoticons',
'characters': [ ':)', ':))', ':(', '<3', ';)' ]
}
}
} );
Note that this only works after the 'characters' section has been built.
Add a whole new group with snippets, that insert text before and after the cursor position or selected text
Instead of a string, we can use an object in the array of characters, with a label and action, to provide the text to insert before and after the cursor or selected text.
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'sections': {
'snippets': {
'type': 'booklet',
'label': 'Useful Snippets',
'pages': {
'section-xml': {
'label': 'XML Tags',
'layout': 'characters',
'characters': [
'<references/>',
{
'action': {
'type': 'encapsulate',
'options': {
'pre': '<ref>',
'peri': '',
'post': '</ref>'
}
},
'label': '<ref></ref>'
}
]
},
'section-links': {
'label': 'Wikilinks',
'layout': 'characters',
'characters': [
{
'action': {
'type': 'encapsulate',
'options': {
'pre': '[[Category:',
'peri': '',
'post': ']]'
}
},
'label': '[[Category:]]'
},
{
'action': {
'type': 'encapsulate',
'options': {
'pre': '[[File:',
'peri': '',
'post': ']]'
}
},
'label': '[[File:]]'
}
]
}
}
}
}
} );
Add characters to an existing special characters page
Additional characters can be injected during the building of the 'characters' section:
$(function() {
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-buildSection-characters', function (event, section) {
section.pages.symbols.characters.push('\u02be', '\u02bf');
});
});
There is also an API function, but it only works after the 'characters' section has been built:
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'characters',
'page': 'symbols',
'characters': [ '\u02be', '\u02bf' ]
});
Removing things
Use the removeFromToolbar
call to remove buttons from the toolbar. The following example removes the button for deprecated HTML element <big>
:
/* Remove button for <big> */
$( '#wpTextbox1' ).wikiEditor( 'removeFromToolbar', {
'section': 'advanced',
'group': 'size',
'tool': 'big'
});
Modifying things
We don't really have a nice API to modify things, unfortunately. The best we have is a hook to change the configuration of a section just before it's being built:
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-buildSection-sectionname', function( event, section ) {
// Do stuff with section
} );
Example: adding localized icons
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-buildSection-main', function( event, section ) {
// Add icons for bold (F) and italic (L) for Swedish (sv)
// Don't overwrite them if they're already defined, so this hack can safely be removed once the
// usability team incorporates these icons in the software
if ( !( 'sv' in section.groups.format.tools.bold.icon ) ) {
// There's already a bold F icon for German, use that one
section.groups.format.tools.bold.icon['sv'] = 'format-bold-F.png';
section.groups.format.tools.bold.offset['sv'] = [2, -214];
}
if ( !( 'sv' in section.groups.format.tools.italic.icon ) ) {
// Use an icon from Commons for L
section.groups.format.tools.italic.icon['sv'] = '//upload.wikimedia.org/wikipedia/commons/3/32/Toolbaricon_italic_L.png';
section.groups.format.tools.italic.offset['sv'] = [2, -214];
}
} );
Determining when toolbar load is done
To be notified when the initial toolbar load is done, put:
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-doneInitialSections', function () {
// Do something
} );
This is in WikiEditor wmf/1.21wmf8 and later. For example, GuidedTour repositions absolutely positioned guiders (a type of tooltip) at this point.
This should be used carefully, because your script can be loaded later than the moment the event fires.
See also
- w:en:User:V111P/js/addToolbarButtons – a script allowing you to easily add encapsulate and callback type buttons to either the WikiEditor or the classic toolbar.
- meta:User:Krinkle/Scripts/InsertWikiEditorButton – a script to add new buttons to the WikiEditor toolbar in a way similar to how the classic 2006 toolbar worked.
- w:de:User:Schnark/js/wikieditor – a script allowing you to add encapsulate and callback type buttons
- meta:User:Perhelion/WikiEditorEmoticons.js – a script example with this huge smilie button list