OOjs UI/Toolbars

From MediaWiki.org
Jump to: navigation, search

Toolbars[edit]

Toolbars are complex interface components that permit users to easily access a variety of tools (e.g., formatting commands) and actions, which are additional commands that are part of the toolbar, but not configured as tools.

Developers create and customize the individual tools, and then register them with a ToolFactory, which creates the tools on demand. Each tool has a symbolic name (used when registering the tool), a title (e.g., ‘Insert picture’), and an icon.

Individual tools are organized in toolgroups, which are displayed as menus of tools, lists of tools, or as a single bar of tools. You can customize the arrangement and order of the toolgroups when you set up the toolbar. Tools can display in any order, but each can only appear once in the toolbar.

The following is an example of a basic toolbar. We will be looking more closely at each of the components making up this example later in this documentation. To see this demo live, please see the code-generated documentation.

Example of a basic toolbar

Tools[edit]

Tools are created by extending the abstract Tool class or one of its subclasses, PopupTool or ToolGroupTool. Each tool must be configured with a static name, title, and icon property:

  • name: The symbolic name is used internally to register the tool with a ToolFactory. Tools must be registered with a tool factory before they can be used in a toolbar.
  • title: The title text is used in different ways depending on the type of group the tool is placed inside (ToolBarGroup, ToolMenuGroup, or ToolListGroup). For ‘bar’ toolgroups, where only an icon is displayed to identify the tool, the title text is used as a tooltip that is displayed when a user moves the mouse over the tool. For ‘list’ toolgroups, the title text is used to identify the tool in the dropdown menus used in the user interface. If a keyboard shortcut has been defined for the tool, the shortcut will automatically be displayed. For tools in ‘bar’ toolgroups, the keyboard shortcut is displayed in a tooltip; for tools in ‘menu’ and 'list' toolgroups, the shortcut appears to the right of each item in the dropdown menu.
  • icon: The icon is also used in different ways depending on the type of toolgroup that the tool is inside. For ‘bar’ toolgroups, the icon is displayed in the toolbar to identify the tool. For ‘list’ toolgroups, the icon is displayed beside the title text in the dropdown menu. For ‘menu’ toolgroups, the icon is ignored.

In addition to the static properties, tools must also implement the following two methods:

  • onSelect(), used to specify the action the tool will carry out when it is selected
  • onUpdateState(), used to synchronize the state of the tool with the state of its larger context. For example, this method could be used to select the ‘bold’ tool in the toolbar when the text cursor is moved inside an area of bolded text.
// Example: Creating a standard tool. 

// Create a tool factory (done once for each toolbar). All tools must be registered with a tool factory, which creates new tool objects upon request. 
var toolFactory = new OO.ui.ToolFactory();

// Define the tool’s static properties and the action it performs
function PictureTool() {
    PictureTool.super.apply( this, arguments );
};
OO.inheritClass( PictureTool, OO.ui.Tool );
// Each tool must have a 'name' (used as an internal identifier, see later) and at least one 'icon' and 'title' (displayed icon and text).
PictureTool.static.name = 'picture';
PictureTool.static.icon = 'picture';
PictureTool.static.title = 'Insert picture';
// Define the action that is performed when this tool is selected (clicked).
PictureTool.prototype.onSelect = function () {
    .. . whatever the tool does here ...
    this.setActive( false );
};
// Define the onUpdateState(). We are not using this feature here.
PictureTool.prototype.onUpdateState = function () {};

// Register the new tool with the tool factory.
toolFactory.register( PictureTool );

Tools can also be configured with a static 'group' property, which can later be used when adding the tool to a bar, menu, or list toolgroup (see ToolGroups for an example of how this is done):

// Define a static 'group' property if you'd like to include tools based on the name defined here.
function PictureTool() {
    PictureTool.super.apply( this, arguments );
};
OO.inheritClass( PictureTool, OO.ui.Tool );
PictureTool.static.name = 'picture';
PictureTool.static.icon = 'picture';
PictureTool.static.title = 'Insert picture';
PictureTool.static.group = 'myGroup';

For a complete list of supported methods and configuration options, please see the code-level documentation for the Tool class.

PopupTool[edit]

Popup tools open a popup window when they are selected from the toolbar. Unlike standard tools, popup tools do not require that developers specify an onSelect() or onUpdateState() method, as these methods have been implemented already.

An example of a PopupTool
// Example of a popup tool. When selected, a popup tool displays
// a popup window. 
function HelpTool( toolGroup, config ) {
    OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
        padded: true,
        label: 'Help',
        head: true
    } }, config ) );
    this.popup.$body.append( '<p>I am helpful!</p>' );
};
OO.inheritClass( HelpTool, OO.ui.PopupTool );
HelpTool.static.name = 'help';
HelpTool.static.icon = 'help';
HelpTool.static.title = 'Help';
toolFactory.register( HelpTool );

For a complete list of supported methods and configuration options, please see the code-level documentation for the PopupTool class.

ToolGroupTool[edit]

A ToolGroupTool is a special sort of tool that can contain other tools and toolgroups. The ToolGroupTool was specifically designed to be used inside a ‘bar’ toolgroup to provide access to additional tools from the bar item.

Example of a ToolGroupTool used in a BarToolGroup.
// Example: ToolGroupTool with two nested tools, 'setting1' and 'setting2', defined elsewhere.

function SettingsTool() {
    SettingsTool.super.apply( this, arguments );
};
OO.inheritClass( SettingsTool, OO.ui.ToolGroupTool );
SettingsTool.static.name = 'settings';
SettingsTool.static.title = 'Change settings';
SettingsTool.static.groupConfig = {
        icon: 'settings',
        label: 'ToolGroupTool',
        include: [  'setting1', 'setting2'  ]
    };

toolFactory.register( SettingsTool );

For a complete list of supported methods and configuration options, please see the code-level documentation for the ToolGroupTool class.

ToolGroups[edit]

Tools are organized into toolgroups, which are created by a ToolGroupFactory and then added to the toolbar when the toolbar is set up. Individual tools can be added to any type of toolgroup (bar, list, or menu). The type of toolgroup determines how the included tools are arranged in the toolbar:

  • bar: Tools are displayed by icon in a single row.
  • list: Tools are displayed with a label and icon in a dropdown menu. The tool's title is used as the label text. The list can be configured to be collapsed and expanded with the allowCollapse config.
  • menu: Tools are displayed by label in a dropdown menu. The tool's title is used as the label text. ‘menu’ tool groups are generally used for sets of mutually exclusive tools, such as a group of text formatting commands (paragraph, heading, etc).

Tools can be added to a toolgroup in one of several ways: by symbolic name, by group name, or with the ' * ' (asterisk) catch-all:

Add tools by name:

// Add tools by their symbolic name. 
{
   type: 'list',
   include: [ 'picture', 'help' ]
}

// or use an object:
{
   type: 'list',
   include: [ { name: 'picture' }, { name: 'help' } ]
}

Add tools by group. A tool's group name is specified with the tool's static 'group' property (see Tools for an example).

// Add tools by group name
{
   type: 'list',
   include: [ { group: 'myGroup' } ]
}

Add tools with the catch-all:

// Add tools with the 'catch all' character, an asterisk. 
// The asterisk specifies that all tools that are not yet in a toolgroup be included. 

{
  type: 'list',
  include: { '*' }
}

Developers can further curate the arrangement of the tools using the toolgroup’s promote and demote configuration options, which will arrange the tools at the top of the tool list (or front of the toolbar) or end, respectively. These settings are particularly useful when tools have been added to the toolbar en masse (e.g., with the asterisk catch-all or when a group of tools is added to a toolgroup) to manage their priority.

BarToolGroup[edit]

Tools in a BarToolGroup are displayed by icon in a single row. The title of the tool is displayed when users move the mouse over the tool.

An example of a BarToolGroup.
// Example of a BarToolGroup 
{
    // Tools are displayed by icon in a single row
    type: 'bar',
    include: [ 'picture', 'help', 'settings', 'stuff']
}

For a complete list of supported methods and configuration options, please see the code-level documentation for the BarToolGroup class.

ListToolGroup[edit]

Tools in a ListToolGroup are displayed by icon and label in a dropdown menu. The tool's title is used as the label text. List groups can be configured to be expanded and collapsed. Collapsed lists will have a ‘More’ option that users can select to see the full list of tools. If a collapsed toolgroup is expanded, a ‘Fewer’ option permits users to collapse the list again.

An example of a ListToolGroup.
// Example of a ListToolGroup. Tools are displayed by icon and label in a dropdown menu. 
// The dropdown menu can be configured with a label as well, in this example, 'ListToolGroup'
{
    type: 'list',
    indicator: 'down',
    label: 'ListToolGroup',
    include: [ 'picture', 'help', 'settings', 'stuff' ]
}

In addition to a label, ListToolGroups can also be configured with a header and title:

Example: ListToolGroup configured with a label, header, and title.
// Example: ListToolGroup with label, header, and title.
{
    type: 'list',
    indicator: 'down',
    header: 'This is the header',
    title: 'This is the title',
    label: 'ListToolGroup (this is the label)',
    include: [ 'picture', 'help', 'settings', 'stuff' ],

}

Use the allowCollapse config to designate tools as collapsible (‘help’ and ‘stuff’, in the following example). By default, the list opens in its collapsed state, and users must click the 'More' option to see the collapsed tools:

Example of a ListToolGroup with collapsible tools.
// Example of a ListToolGroup with collapsible tools. By default, the menu will open in its collapsed state. 
{
    type: 'list',
    indicator: 'down',
    label: 'ListToolGroup - Collapsed',
    include: [ 'picture', 'help', 'settings', 'stuff' ],
    allowCollapse: [ 'help',  'stuff' ]
}

To display a collapsible list in its expanded state when the list is opened, set the expanded config to ‘true’:

Example of a collapsible ListToolGroup that has been expanded.
// To expand a collapsible list, set the 'expanded' config to 'true'.
{
    type: 'list',
    indicator: 'down',
    label: 'ListToolGroup - Expanded',
    include: [ 'picture', 'help', 'settings', 'stuff' ],
    allowCollapse: [ 'help',  'stuff' ],
    expanded: true
}

Alternatively, you may wish to specify the names of tools that should never be collapsed. This is done with the forceExpand config. In the following example, only the ‘help’ tool has been designated as expanded; all other tools are collapsed by default.

Example of forceExpand config.
// Specify the tools that must be expanded; all other tools are collapsed by default.
{
    type: 'list',
    indicator: 'down',
    label: 'ListToolGroup - forceExpand',
    include: [ 'picture', 'help', 'settings', 'stuff' ],
    forceExpand: [ 'help' ]
}

For a complete list of supported methods and configuration options, please see the code-level documentation for the ListToolGroup class.

MenuToolGroup[edit]

Tools in MenuToolGroups are displayed by label in a dropdown menu. The tool's title is used as the label text, and the menu label is updated to reflect which tool or tools are currently selected. Note that all tools must define an onUpdateState() method if a MenuToolGroup is used.

Example: MenuToolGroup
// Example: MenuToolGroup

function SettingsTool() {
    SettingsTool.super.apply( this, arguments );
    this.reallyActive = false;
}
OO.inheritClass( SettingsTool, OO.ui.Tool );
SettingsTool.static.name = 'settings';
SettingsTool.static.icon = 'settings';
SettingsTool.static.title = 'Change settings';
SettingsTool.prototype.onSelect = function () {
    // Toggle the active state on each click
    this.reallyActive = !this.reallyActive;
    this.setActive( this.reallyActive );
    // Update the menu label
    this.toolbar.emit( 'updateState' );
};
SettingsTool.prototype.onUpdateState = function () {};
toolFactory.register( SettingsTool );

// Another tool.
function StuffTool() {
    StuffTool.super.apply( this, arguments );
    this.reallyActive = false;
}
OO.inheritClass( StuffTool, OO.ui.Tool );
StuffTool.static.name = 'stuff';
StuffTool.static.icon = 'ellipsis';
StuffTool.static.title = 'Change the world';
StuffTool.prototype.onSelect = function () {
    // Toggle the active state on each click
    this.reallyActive = !this.reallyActive;
    this.setActive( this.reallyActive );
    // Update the menu label
    this.toolbar.emit( 'updateState' );
};
StuffTool.prototype.onUpdateState = function () {};
toolFactory.register( StuffTool );

// Add the MenuToolGroup to the toolbar. 
toolbar.setup( [
    {
        type: 'menu',
        indicator: 'down',
        include: [ 'settings', 'stuff' ]
    }
] );

Configuring the toolbar[edit]

In addition to containing toolgroups, the toolbar can be configured with actions, CSS, accelerator keys, and/or an optional shadow.

Note that ‘actions’ in the context of the toolbar are different from ActionWidgets. For toolbars, ‘actions’ refers to an empty container that is right-aligned and can contain whatever you’d like.

Adding tool groups[edit]

Toolgroups are added to the toolbar with the toolbar's setup method:

A toolbar consisting of two tool groups.
// Add tool groups to the toolbar.  
toolbar.setup( [
    {
        type: 'bar',
        include: [ 'picture', 'help' ]
    },
    {
        type: 'list',
        indicator: 'down',
        label: 'More',
        include: [ 'settings', 'stuff' ]
    }
] );


Adding actions[edit]

Toolbars have an optional 'actions' area, which contains commands that are available to users but are not configured as tools. In the following example, the toolbar has been configured to use actions, in this case two additional buttons, ‘Action’ and ‘Disabled’. For the purpose of brevity, only the action-specific code is included in the example (the rest is just the same as the basic toolbar).

Example of a toolbar with actions
// Example: A toolbar with additional actions. 

// Create the toolbar and set the 'action' config to 'true'.
var toolFactory = new OO.ui.ToolFactory();
var toolGroupFactory = new OO.ui.ToolGroupFactory();
var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory, { actions: true } );

// Create and append the action buttons

actionButton = new OO.ui.ButtonWidget( { label: 'Action' } );
actionButtonDisabled = new OO.ui.ButtonWidget( { label: 'Disabled', disabled: true } );
  toolbar.$actions
    .append( actionButton.$element, actionButtonDisabled.$element );

Adding shadows[edit]

Toolbars can also be configured with an optional shadow. Note that the shadow is only displayed for the Apex theme. The shadow is never displayed when using the WikimediaUI theme:

Example: Toolbar with a shadow.
Example: Toolbar with no shadow
// Example: Adding a shadow to the toolbar

// Create the toolbar
var toolFactory = new OO.ui.ToolFactory();
var toolGroupFactory = new OO.ui.ToolGroupFactory();
var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory, { shadow: true } );

Using CSS to style tool labels[edit]

Tool labels can be styled with built-in CSS classes that are named after each tool: oo-ui-tool-name-<symbolic name of tool> (e.g., oo-ui-tool-name-picture). The following example uses CSS classes to customize the appearance of the 'picture' and the 'help' tool labels.

Example: Using CSS to style tool labels
<!-- Example: Styling tool labels with CSS -->
 <head>
    <title>Using CSS </title>

    <style>
        .oo-ui-listToolGroup .oo-ui-tool-name-picture .oo-ui-tool-title {
            font-size: 200%;
            font-weight: normal;
        }
        .oo-ui-listToolGroup .oo-ui-tool-name-help .oo-ui-tool-title {
           font-size: 150%;
           font-weight: normal;
        }
    </style>

</head>
<script>

// In this example, the 'picture' and 'help' tools are styled
{
    type: 'list',
    indicator: 'down',
    label: 'Using CSS',
    include: [ 'picture', 'help', 'settings', 'stuff' ]
}

</script>

Using accelerator keys[edit]

The OOjs UI library does not contain an accelerator system, but the Toolbar class does contain a hook for one. To use an accelerator system, subclass the toolbar and override the getToolAccelerator( ) method, which is meant to return a label that describes the accelerator keys for the tool passed (by symbolic name) to the method.

Accelerator labels (e.g., 'Ctrl + M') are displayed in different ways depending on the type of toolgroup used:

  • For bar toolgroups, the accelerator label appears in the tooltip displayed when users move the mouse over the tool.
  • For menu and list toolgroups, the accelerator label is right-aligned and rendered in gray text, which still complies to WCAG level AA.

Building the toolbar[edit]

The toolbar must be appended to the document before it can be built. Once it is appended, the toolbar can be initialized:

// Append the toolbar
$( 'body' ).append( toolbar.$element );
// Here is where the toolbar is actually built. This must be done after inserting it into the
// document.
toolbar.initialize();

// Emit an 'updateState' event after initializing the toolbar.
toolbar.emit( 'updateState' );

For a complete list of supported methods and configuration options, please see the code-level documentation for Toolbars.