Jump to content

Extension:WikiEditor/Toolbar customization: Difference between revisions

From mediawiki.org
Content deleted Content added
Turkmen (talk | contribs)
m Reverted edits by 107.242.113.6 (talk) to last version by Lofty abyss
m Reverted edits by 2001:FB1:2F:C56B:8C8D:17C9:C9C3:3C72 (talk) to last version by Kghbln
Tag: Rollback
 
(35 intermediate revisions by 19 users not shown)
Line 1: Line 1:
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.
This article explains the technical details of customizing the toolbar. It requires a basic level of understanding of JavaScript.


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 [[/Library|customizations library]].
If you just need some quick working code that you can copy into your user JS, see the [[/Library|customizations library]].


== Basic setup ==
== Basic setup ==

{{Note|Be sure that you have read the documentation on this page.|reminder}}
=== Scripts and gadgets ===
Before a script is able to manipulate the toolbar provided by WikiEditor, the following things must happen:

# Set the following in LocalSettings.php:
Before a script or gadget is able to manipulate the toolbar provided by WikiEditor, the following things must happen:
#*<code>[[$wgAllowUserJs]] = true;</code> to allow users to setup their individual toolbar, or

#*<code>[[$wgUseSiteJs]] = true;</code> to setup the toolbar site-wide
# Set the following in {{ll|Manual:LocalSettings.php|LocalSettings.php}}:
# The module "ext.wikiEditor" needs to be [[ResourceLoader/Default modules#mediaWiki.loader|loaded]] which is usually done by invoking the WikiEditor extension.
#*<code>{{ll|Manual:$wgAllowUserJs|$wgAllowUserJs}} = true;</code> to allow users to setup their individual toolbar, or
#*<code>{{ll|Manual:$wgUseSiteJs|$wgUseSiteJs}} = true;</code> to setup the toolbar site-wide
# The module "ext.wikiEditor" needs to be [[Special:MyLanguage/ResourceLoader/Default modules#mediaWiki.loader|loaded]] which is usually done by invoking the WikiEditor extension.
# Add the following code to your [[Special:MyPage/common.js|User:YourUserName/common.js]] (or your MediaWiki:Common.js for a site-wide change) to customize the toolbar:
# Add the following code to your [[Special:MyPage/common.js|User:YourUserName/common.js]] (or your MediaWiki:Common.js for a site-wide change) to customize the toolbar:


<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
// Check if we're editing a page.
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 ) {
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
// Add a hook handler.
mw.loader.using( 'user.options' ).then( function () {
mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
// This can be the string "0" if the user disabled the preference ([[phab:T54542#555387]])
// Configure a new toolbar entry on the given $textarea jQuery object.
if ( mw.user.options.get( 'usebetatoolbar' ) == 1 ) {
$textarea.wikiEditor( 'addToToolbar', {
$.when(
/* Your code goes here */
mw.loader.using( 'ext.wikiEditor' ), $.ready
} );
).then( customizeToolbar );
}
} );
} );
}
}
</syntaxhighlight>
</syntaxhighlight>


… and replace the line <syntaxhighlight lang="javascript" inline>/* Your code goes here */</syntaxhighlight> by the code which defines each button added. Multiple snippets can be added by simply pasting them below each other, inside of the function <code>customizeToolbar</code>.
… and replace the line <syntaxhighlight lang="javascript" inline>/* Your code goes here */</syntaxhighlight> by the code which defines each button added. Multiple snippets can be added by adding multiple separate <code>$textarea.wikiEditor( 'addToToolbar' )</code> calls.

=== Extensions ===

Extensions wishing to customize the toolbar should first [[ResourceLoader/Developing with ResourceLoader|set up a module]] (with a dependency on <code>ext.wikiEditor</code>) and then add the following (e.g. in <code>extensions/MyExt/modules/mymodule/init.js</code>):

<syntaxhighlight lang="javascript">
( function () {
mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
$textarea.wikiEditor( 'addToToolbar', {
/* Toolbar configuration goes here. */
} );
} );
}() );
</syntaxhighlight>


== Configuration structure ==
== Configuration structure ==


The toolbar widget is defined by a [[jQuery]] plugin from module [https://phabricator.wikimedia.org/diffusion/EWED/browse/master/modules/jquery.wikiEditor.js jquery.wikiEditor]. You can look at the configuration for the default toolbar on module [https://phabricator.wikimedia.org/diffusion/EWED/browse/master/modules/jquery.wikiEditor.toolbar.config.js jquery.wikiEditor.toolbar.config] to see how you can modify the toolbar. Complete documentation is to be written shortly.
The toolbar widget is defined by a [[Special:MyLanguage/jQuery|jQuery]] plugin from module [https://phabricator.wikimedia.org/diffusion/EWED/browse/master/modules/jquery.wikiEditor.js jquery.wikiEditor]. You can look at the configuration for the default toolbar on module [https://phabricator.wikimedia.org/diffusion/EWED/browse/master/modules/jquery.wikiEditor.toolbar.config.js jquery.wikiEditor.toolbar.config] to see how you can modify the toolbar.


You can modify the toolbar even after it's been built (see example above) by calling the <code>.wikiEditor()</code> function on the textarea. You will need to do this inside an <code>$(document).ready(function() {});</code> call, as already mentioned.
You can modify the toolbar even after it's been built (see example above) by calling the <code>.wikiEditor()</code> function on the textarea. You will need to do this inside an <code>$(document).ready(function() {});</code> call, as already mentioned.
Line 48: Line 60:


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
'action': {
action: {
'type': 'encapsulate',
type: 'encapsulate',
'options': {
options: {
'pre': "'''",
pre: "'''",
'periMsg': 'wikieditor-toolbar-tool-bold-example',
peri: mw.msg( 'wikieditor-toolbar-tool-bold-example' ),
'post': "'''"
post: "'''"
}
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>


Another example, using a callback function for the most flexibility in what should happen when the button is pressed:
Another example from [[s:it:MediaWiki:Gadget-indentaVersi.js|it.source]], using callback:


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
action: {
action: {
type: 'callback',
type: 'callback',
execute: function(context){
execute: function ( context ) {
// The context object contains things such as the toolbar and the textarea.
indentSelection();
console.log( context );
}
context.$textarea.css( 'background-color', 'pink' );
}
}
}
</syntaxhighlight>
</syntaxhighlight>

If you want to use <code>type: 'dialog'</code>, you must register a function that returns the dialog in advance using <code>wikiEditor( 'addModule', DialogFunc())</code>.


=== button ===
=== button ===


* ''type'': "button"
* ''type'': "button"
* ''icon'' string '''required''': short key name or URL to icon
* ''icon'' or ''oouiIcon'' string '''required''': short key name or URL to icon
* ''label'' string: non-localizable label string
* ''label'' string: label string (use ''[[Manual:Messages API#Using messages in JavaScript|mw.msg]]( key )'' for localization)
* ''labelMsg'' string: key for localizable message string
* ''[[#action]]''
* ''[[#action]]''


Line 81: Line 95:
Toggles are like buttons but with a binary state. The button can be pressed (active) or non-pressed. (Since 1.32)
Toggles are like buttons but with a binary state. The button can be pressed (active) or non-pressed. (Since 1.32)
* ''type'': "toggle"
* ''type'': "toggle"
* ''icon'' string '''required''': short key name or URL to icon
* ''icon'' or ''oouiIcon'' string '''required''': short key name or URL to icon
* ''label'' string: non-localizable label string
* ''label'' string: label string (use ''[[Manual:Messages API#Using messages in JavaScript|mw.msg]]( key )'' for localization)
* ''labelMsg'' string: key for localizable message string
* ''[[#action]]''
* ''[[#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 <code>$button.data( 'setActive' )(boolean);</code> to make the button reflect the new state.
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 <code>$button.data( 'setActive' )(boolean);</code> to make the button reflect the new state.

=== select ===
A dropdown menu with menuitems, each menuitem having its own action

* ''type'': "select"
* ''icon'' or ''oouiIcon'' string '''required''': short key name or URL to icon
* ''label'' string: label string (use ''[[Manual:Messages API#Using messages in JavaScript|mw.msg]]( key )'' for localization)
* ''list'' object with dropdown menu items, each with their own label and ''[[#action]]''

=== element ===
Insert a raw DOM element. When you use this, you are responsible for everything (labels, event handling, accessiblity, etc.) but have the freedom to do whatever you want (dropdowns, buttons with visible labels, etc.).

* ''type'': "element"
* ''element'': either a htmlString, HTMLElement, Text, Array, jQuery object, a function returning any of the aforementioned, or a OO.ui.HTMLSnippet to be inserted.

For example, a button added to the secondary end of the toolbar that displays an alert when clicked:

<syntaxhighlight lang="javascript">
$textarea.wikiEditor( 'addToToolbar', {
section: 'secondary',
group: 'default',
tools: {
dothing: {
type: 'element',
element: function ( context ) {
// Note that the `context` object contains various useful references.
console.log( context );
var button = new OO.ui.ButtonInputWidget( {
label: 'Do a thing',
icon: 'hieroglyph'
} );
button.connect( null, {
click: function ( e ) {
// Do whatever is required when the button is clicked.
console.log( e );
OO.ui.alert( 'A thing is done.' );
}
} );
return button.$element;
}
}
}
} );
</syntaxhighlight>


=== booklet ===
=== booklet ===


* ''type'': "booklet"
* ''type'': "booklet"
* ''label'' string: non-localizable label string
* ''label'' string: label string (use ''[[Manual:Messages API#Using messages in JavaScript|mw.msg]]( key )'' for localization)
* ''labelMsg'' string: key for localizable message string
* ''deferLoad'' boolean
* ''deferLoad'' boolean
* ''pages'' object: map of name keys to further objects:
* ''pages'' object: map of name keys to further objects:
** ''layout'' string '''required''': 'table' or 'characters'
** ''layout'' string '''required''': 'table' or 'characters'
** ''label'' string: non-localizable label string
** ''label'' string: label string (use ''[[Manual:Messages API#Using messages in JavaScript|mw.msg]]( key )'' for localization)
** ''labelMsg'' string: key for localizable message string
** ''headings'' string[]: array of objects? {text: mw.message( key ).parse() } ⁇
** ''headings'' string[]: array of objects? {textMsg: key} ⁇
** ''rows'' object[] ''optional?'': array of objects? {'row key name': {message object?}}
** ''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:
** ''characters'' object[] ''optional?'': array of strings of little character bits for insertion, or objects specifying actions:
Line 108: Line 163:
The default WikiEditor toolbar has the following sections:
The default WikiEditor toolbar has the following sections:
* The ''main'' section which is always visible, with the groups ''format'' and ''insert''.
* The ''main'' section which is always visible, with the groups ''format'' and ''insert''.
* The ''secondary'' is at the opposite end from the main section, and contains the ''default'' group that is empty by default.
* The ''advanced'' section, with the groups ''heading'', ''format'', ''size'', ''insert'' and ''search''.
* 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 ''characters'' section, with pages ''latin'', ''latinextended'', ''ipa'', ''symbols'', ''greek'', ''cyrillic'', ''arabic'', ''hebrew'', ''bangla'', ''telugu'', ''sinhala'' and ''gujarati''
Line 114: Line 170:
== Adding things ==
== Adding things ==


The general format for adding things is as follows:
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 <code>customizeToolbar</code> defined above, or something equivalent.


The general format for adding things is as follows:
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
// Configuration object here
// Configuration object here
} );
} );
} );
</syntaxhighlight>
</syntaxhighlight>

Some specific examples are displayed in the sections below.
Some specific examples are displayed in the sections below.


=== Add a toolbar section ===
=== Add a toolbar section ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'sections': {
sections: {
'emoticons': {
emoticons: {
'type': 'toolbar', // Can also be 'booklet'
type: 'toolbar', // Can also be 'booklet',
'label': 'Emoticons'
label: 'Emoticons'
// or 'labelMsg': 'section-emoticons-label' for a localized label
// or label: mw.msg( 'section-emoticons-label' ) for a localized label
}
}
}
}
Line 139: Line 197:
=== Add a group to an existing toolbar section ===
=== Add a group to an existing toolbar section ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'section': 'emoticons',
section: 'emoticons',
'groups': {
groups: {
'faces': {
faces: {
'label': 'Faces' // or use labelMsg for a localized label, see above
label: 'Faces' // or use mw.msg() for a localized label, see above
}
}
}
}
Line 151: Line 209:
=== Add a button to an existing toolbar group ===
=== Add a button to an existing toolbar group ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'section': 'emoticons',
section: 'emoticons',
'group': 'faces',
group: 'faces',
'tools': {
tools: {
'smile': {
smile: {
label: 'Smile!', // or use labelMsg for a localized label, see above
label: 'Smile!', // or use mw.message( key ).escaped() for a localized label, see above
type: 'button',
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gnome-face-smile.svg/22px-Gnome-face-smile.svg.png',
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gnome-face-smile.svg/22px-Gnome-face-smile.svg.png',
Line 173: Line 231:
:'''Ex'''. - To have a button generated <u>only</u> when editing any Talk: namespace page, add the highlighted line below.
:'''Ex'''. - To have a button generated <u>only</u> when editing any Talk: namespace page, add the highlighted line below.
<syntaxhighlight lang="JavaScript" highlight="7">
<syntaxhighlight lang="JavaScript" highlight="7">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'section': 'emoticons',
section: 'emoticons',
'group': 'faces',
group: 'faces',
'tools': {
tools: {
'smile': {
smile: {
label: 'Smile!', // or use labelMsg for a localized label, see above
label: 'Smile!', // or use mw.msg() for a localized label, see above
filters: [ 'body.ns-talk' ],
filters: [ 'body.ns-talk' ],
type: 'button',
type: 'button',
Line 194: Line 252:
:'''Ex'''. - To have a button generated in all namespaces <u>except</u> the User: and Template: namespaces, add the highlighted line below.
:'''Ex'''. - To have a button generated in all namespaces <u>except</u> the User: and Template: namespaces, add the highlighted line below.
<syntaxhighlight lang="JavaScript" highlight="7">
<syntaxhighlight lang="JavaScript" highlight="7">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'section': 'emoticons',
section: 'emoticons',
'group': 'faces',
group: 'faces',
'tools': {
tools: {
'smile': {
smile: {
label: 'Smile!', // or use labelMsg for a localized label, see above
label: 'Smile!', // or use mw.msg() for a localized label, see above
filters: [ 'body:not(.ns-2, .ns-10)' ],
filters: [ 'body:not(.ns-2, .ns-10)' ],
type: 'button',
type: 'button',
Line 216: Line 274:
=== Add a drop-down picklist ===
=== Add a drop-down picklist ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
section: 'main',
section: 'main',
groups: {
groups: {
Line 263: Line 321:
=== Add a booklet section ===
=== Add a booklet section ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'sections': {
sections: {
'info': {
info: {
'type': 'booklet',
type: 'booklet',
'label': 'Info'
label: 'Info'
}
}
}
}
Line 275: Line 333:
=== Add a page to an existing booklet section ===
=== Add a page to an existing booklet section ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'section': 'info',
section: 'info',
'pages': {
pages: {
'colors': {
colors: {
'layout': 'table',
layout: 'table',
'label': 'Colors',
label: 'Colors',
'headings': [
headings: [
{ text: 'Name' }, // or use textMsg for localization, see also above
{ text: 'Name' }, // or use mw.message( key ).parse() for localization, see also above
{ text: 'Temperature' },
{ text: 'Temperature' },
{ text: 'Swatch' }
{ text: 'Swatch' }
],
],
'rows': [
rows: [
{
{
'name': { text: 'Red' },
name: { text: 'Red' },
'temp': { text: 'Warm' },
temp: { text: 'Warm' },
'swatch': { html: '<div style="width:10px;height:10px;background-color:red;">' }
swatch: { html: '<div style="width:10px;height:10px;background-color:red;">' }
},
},
{
{
'name': { text: 'Blue' },
name: { text: 'Blue' },
'temp': { text: 'Cold' },
temp: { text: 'Cold' },
'swatch': { html: '<div style="width:10px;height:10px;background-color:blue;">' }
swatch: { html: '<div style="width:10px;height:10px;background-color:blue;">' }
},
},
{
{
'name': { text: 'Silver' },
name: { text: 'Silver' },
'temp': { text: 'Neutral' },
temp: { text: 'Neutral' },
'swatch': { html: '<div style="width:10px;height:10px;background-color:silver;">' }
swatch: { html: '<div style="width:10px;height:10px;background-color:silver;">' }
}
}
]
]
Line 310: Line 368:
=== Add a special characters page ===
=== Add a special characters page ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
$textarea.wikiEditor( 'addToToolbar', {
'section': 'characters',
section: 'characters',
'pages': {
pages: {
'emoticons': {
emoticons: {
'layout': 'characters',
layout: 'characters',
'label': 'Emoticons',
label: 'Emoticons',
'characters': [ ':)', ':))', ':(', '<3', ';)' ]
characters: [ ':)', ':))', ':(', '<3', ';)' ]
}
}
}
}
Line 441: Line 499:
}
}
} );
} );
</syntaxhighlight>

=== Example: modifying button action ===
The solution below replaces the insertion of obsolete <code><nowiki><big></nowiki></code> tag with Big template, but could be used for any customisation of button actions in WikiEditor.

<syntaxhighlight lang="javascript">
// Stop WikiEditor from inserting obsolete HTML tag / <nowiki>
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-buildSection-advanced', function( event, section ) {
// The exact paths are available in jquery.wikiEditor.toolbar.config.js file of the extension
section.groups.size.tools.big.action.options.pre = '{{big|';
section.groups.size.tools.big.action.options.post = '}}';
} );
// </nowiki>
</syntaxhighlight>
</syntaxhighlight>


Line 455: Line 526:


This should be used carefully, because your script can be loaded later than the moment the event fires.
This should be used carefully, because your script can be loaded later than the moment the event fires.

So it is better to use a hook (it will work also when you run this after the page is fully loaded).
<syntaxhighlight lang="JavaScript">
mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
// Do something
} );
</syntaxhighlight>


== See also ==
== See also ==
Line 461: Line 539:
* [[w:de:User:Schnark/js/wikieditor]] – a script allowing you to add encapsulate and callback type buttons
* [[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
* [[meta:User:Perhelion/WikiEditorEmoticons.js]] – a script example with this huge smilie button list
* [https://test.pro.wiki/wiki/Replace_the_default_WikiEditor_signature_button_with_a_custom_signature_button Replace the default signature button with a custom signature button]

Latest revision as of 12:52, 1 June 2024

This article explains the technical details of customizing the toolbar. It requires a basic level of understanding of JavaScript.

If you just need some quick working code that you can copy into your user JS, see the customizations library.

Basic setup

[edit]

Scripts and gadgets

[edit]

Before a script or gadget is able to manipulate the toolbar provided by WikiEditor, the following things must happen:

  1. Set the following in LocalSettings.php :
  2. The module "ext.wikiEditor" needs to be loaded which is usually done by invoking the WikiEditor extension.
  3. Add the following code to your User:YourUserName/common.js (or your MediaWiki:Common.js for a site-wide change) to customize the toolbar:
// Check if we're editing a page.
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
		$textarea.wikiEditor( 'addToToolbar', {
			/* Your code goes here */
		} );
	} );
}

… and replace the line /* Your code goes here */ by the code which defines each button added. Multiple snippets can be added by adding multiple separate $textarea.wikiEditor( 'addToToolbar' … ) calls.

Extensions

[edit]

Extensions wishing to customize the toolbar should first set up a module (with a dependency on ext.wikiEditor) and then add the following (e.g. in extensions/MyExt/modules/mymodule/init.js):

( function () {
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
		$textarea.wikiEditor( 'addToToolbar', {
			/* Toolbar configuration goes here. */
		} );
	} );
}() );

Configuration structure

[edit]

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.

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

[edit]
  • 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: "'''",
		peri: mw.msg( 'wikieditor-toolbar-tool-bold-example' ),
		post: "'''"
	}
}

Another example, using a callback function for the most flexibility in what should happen when the button is pressed:

action: {
	type: 'callback',
	execute: function ( context ) {
		// The context object contains things such as the toolbar and the textarea.
		console.log( context );
		context.$textarea.css( 'background-color', 'pink' );
	}
}

If you want to use type: 'dialog', you must register a function that returns the dialog in advance using wikiEditor( 'addModule', DialogFunc()).

button

[edit]
  • type: "button"
  • icon or oouiIcon string required: short key name or URL to icon
  • label string: label string (use mw.msg( key ) for localization)
  • #action

toggle

[edit]

Toggles are like buttons but with a binary state. The button can be pressed (active) or non-pressed. (Since 1.32)

  • type: "toggle"
  • icon or oouiIcon string required: short key name or URL to icon
  • label string: label string (use mw.msg( key ) for localization)
  • #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.

select

[edit]

A dropdown menu with menuitems, each menuitem having its own action

  • type: "select"
  • icon or oouiIcon string required: short key name or URL to icon
  • label string: label string (use mw.msg( key ) for localization)
  • list object with dropdown menu items, each with their own label and #action

element

[edit]

Insert a raw DOM element. When you use this, you are responsible for everything (labels, event handling, accessiblity, etc.) but have the freedom to do whatever you want (dropdowns, buttons with visible labels, etc.).

  • type: "element"
  • element: either a htmlString, HTMLElement, Text, Array, jQuery object, a function returning any of the aforementioned, or a OO.ui.HTMLSnippet to be inserted.

For example, a button added to the secondary end of the toolbar that displays an alert when clicked:

	$textarea.wikiEditor( 'addToToolbar', {
		section: 'secondary',
		group: 'default',
		tools: {
			dothing: {
				type: 'element',
				element: function ( context ) {
					// Note that the `context` object contains various useful references.
					console.log( context );
					var button = new OO.ui.ButtonInputWidget( {
						label: 'Do a thing',
						icon: 'hieroglyph'
					} );
					button.connect( null, {
						click: function ( e ) {
							// Do whatever is required when the button is clicked.
							console.log( e );
							OO.ui.alert( 'A thing is done.' );
						}
					} );
					return button.$element;
				}
			}
		}
	} );

booklet

[edit]
  • type: "booklet"
  • label string: label string (use mw.msg( key ) for localization)
  • deferLoad boolean
  • pages object: map of name keys to further objects:
    • layout string required: 'table' or 'characters'
    • label string: label string (use mw.msg( key ) for localization)
    • headings string[]: array of objects? {text: mw.message( key ).parse() } ⁇
    • 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 and label properties will perform the action (used to split text to insert before and after the selection).

Default sections

[edit]

The default WikiEditor toolbar has the following sections:

  • The main section which is always visible, with the groups format and insert.
  • The secondary is at the opposite end from the main section, and contains the default group that is empty by default.
  • 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

[edit]

The general format for adding things is as follows:

mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
	$textarea.wikiEditor( 'addToToolbar', {
		// Configuration object here
	} );
} );

Some specific examples are displayed in the sections below.

Add a toolbar section

[edit]
$textarea.wikiEditor( 'addToToolbar', {
	sections: {
		emoticons: {
			type: 'toolbar', // Can also be 'booklet',
			label: 'Emoticons'
			// or label: mw.msg( 'section-emoticons-label' ) for a localized label
		}
	}
} );

Add a group to an existing toolbar section

[edit]
$textarea.wikiEditor( 'addToToolbar', {
	section: 'emoticons',
	groups: {
		faces: {
			label: 'Faces' // or use mw.msg() for a localized label, see above
		}
	}
} );

Add a button to an existing toolbar group

[edit]
$textarea.wikiEditor( 'addToToolbar', {
	section: 'emoticons',
	group: 'faces',
	tools: {
		smile: {
			label: 'Smile!', // or use mw.message( key ).escaped() 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

[edit]
Ex. - To have a button generated only when editing any Talk: namespace page, add the highlighted line below.
$textarea.wikiEditor( 'addToToolbar', {
	section: 'emoticons',
	group: 'faces',
	tools: {
		smile: {
			label: 'Smile!', // or use mw.msg() 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.
$textarea.wikiEditor( 'addToToolbar', {
	section: 'emoticons',
	group: 'faces',
	tools: {
		smile: {
			label: 'Smile!', // or use mw.msg() 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

[edit]
$textarea.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

[edit]
$textarea.wikiEditor( 'addToToolbar', {
	sections: {
		info: {
			type: 'booklet',
			label: 'Info'
		}
	}
} );

Add a page to an existing booklet section

[edit]
$textarea.wikiEditor( 'addToToolbar', {
	section: 'info',
	pages: {
		colors: {
			layout: 'table',
			label: 'Colors',
			headings: [
				{ text: 'Name' }, // or use mw.message( key ).parse() 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

[edit]
$textarea.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

[edit]

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

[edit]

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

[edit]

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

[edit]

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

[edit]
$( '#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];
	}
} );

Example: modifying button action

[edit]

The solution below replaces the insertion of obsolete <big> tag with Big template, but could be used for any customisation of button actions in WikiEditor.

// Stop WikiEditor from inserting obsolete HTML tag / <nowiki>
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-buildSection-advanced', function( event, section ) {
	// The exact paths are available in jquery.wikiEditor.toolbar.config.js file of the extension
	section.groups.size.tools.big.action.options.pre = '{{big|';
	section.groups.size.tools.big.action.options.post = '}}';
} );
// </nowiki>

Determining when toolbar load is done

[edit]

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.

So it is better to use a hook (it will work also when you run this after the page is fully loaded).

mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
    // Do something
} );

See also

[edit]