Context toolbar

A context toolbar can only contain either buttons that are defined for a normal toolbar, or buttons specifically registered for launching a ContextForm. The buttons comes as a list of strings, where each string is a registered name of a button.

Registering a context toolbar

A context toolbar is registered by calling the addContextToolbar API in the registry. The specification is as follows:

Name Description

predicate

This controls when the context toolbar will appear

position

This controls where the context toolbar will appear with regards to the current cursor

scope

This controls whether the predicate (condition) is a node-based predicate, or an editor-based predicate. See context toolbar priority section below, for more details.

items

A list of strings which represent either a registered toolbar button, or a registered context form launcher.

Positioning of context toolbars

There are three options for positioning context toolbars: selection, node, or line.

  • A selection position will place the context toolbar above or below the current selection, centered if possible.

  • A node position will place the context toolbar above or below the bounds of a node (e.g. a table or image).

  • A line position will place the context toolbar to the right (or left in Right-to-Left languages) of the current selection.

Example configuration

This example shows how the quickbars plugin adds the standard selection context toolbar and an example of a custom toolbar for image alignment. The context toolbar will show whenever any content is selected.

  • TinyMCE

  • HTML

  • JS

  • Edit on CodePen

<textarea id="context-toolbar">
  <p>Clicking on the example image below will show the newly configured context toolbar.</p>

  <p><img style="display: block; margin-left: auto; margin-right: auto;" title="Tiny Logo" src="https://www.tiny.cloud/docs/images/logos/android-chrome-256x256.png" alt="TinyMCE Logo" width="128" height="128"></p>

  <p>Select a word in this sentence, to see the other newly configured context toolbar.</p>

  <p>Clicking on text should not invoke the context toolbar</p>
</textarea>
tinymce.init({
  selector: 'textarea#context-toolbar',
  height: 350,
  setup: (editor) => {
    editor.ui.registry.addContextToolbar('imagealignment', {
      predicate: (node) => node.nodeName.toLowerCase() === 'img',
      items: 'alignleft aligncenter alignright',
      position: 'node',
      scope: 'node'
    });

    editor.ui.registry.addContextToolbar('textselection', {
      predicate: (node) => !editor.selection.isCollapsed(),
      items: 'bold italic | blockquote',
      position: 'selection',
      scope: 'node'
    });
  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});

Launching a context toolbar programmatically

There is an editor event called contexttoolbar-show that can be fired to show a context toolbar at the current selection. The event takes a parameter toolbarKey which specifies the name of the registered context form or context toolbar to show.

Troubleshooting context toolbar and context form conflicts

There are situations where custom context toolbars or custom context forms may conflict with:

  • Context toolbars or context forms provided by the editor,

  • Context toolbars or context forms provided by the Quick Toolbars (quickbars) plugin,

  • Other custom context toolbars or custom context forms.

Determining the display priority of context toolbars and context forms

There are three settings that determine the priority of context toolbars and context forms: scope, predicate, and position.

  • scope - Sets the context toolbar or form as either: specific to certain types of content (node), or a general (global) toolbar or form (editor).

  • predicate - The predicate is the condition(s) where the context toolbar or form should be shown. This setting is a function for determining if the context menu or form applies to the current selection or cursor position. This function should return a boolean value.

  • position - Sets where the context toolbar or form is rendered, relative to the current context (selection, node, or line).

Generally:

  • Context forms are prioritized over context toolbars.

  • Context forms with scope: 'node' are prioritized over scope: 'editor'.

  • Only one context form can be shown for a selection or cursor position, they cannot be concatenated to another context form or a context toolbar.

  • Context toolbars with position: 'selection' are prioritized over position: 'node', and position: 'line' is given the lowest priority.

  • The editor concatenates context toolbars when there is more than one context toolbar to display with:

    • A matching predicate,

    • The same scope and position values.

      Concatenated toolbars may contain duplicate toolbar items.

  • If no matching context toolbars or context forms are found for the selection or cursor position, then editor will recursively search for matches on the parent node of the current node, until it reaches the root node of the editor content.

Description of how context toolbars and context forms are prioritized

The following description can be used for troubleshooting the behavior of context toolbars and context forms.

The editor will determine which context toolbars or context form will be shown using following process:

  1. Find all context forms with both:

    • scope: 'node'

    • A predicate (condition) matching the current selection or cursor position.

      If there are any matching context forms, the first one found will be displayed in the editor and the process will end.

  2. Find all context forms with both:

    • scope: 'editor'

    • A predicate matching the current selection or cursor position.

      If there are any matching context forms, the first one found will be displayed in the editor and the process will end.

  3. Find all context toolbars with both:

    • Any scope

    • A predicate matching the current selection or cursor position.

      If there are any matching context toolbars, the editor will prioritize the context toolbars based on the position value.

    • All context toolbars with position: 'selection' or position: 'node' will be concatenated, the concatenated toolbar will be displayed, and the process will end.

    • Otherwise, all context toolbars with position: line will be concatenated, the concatenated toolbar will be displayed, and the process will end.

  4. Find all context forms with both:

    • Any scope

    • A predicate matching the parent node of the current node, selection, or cursor position.

      If there are any context forms found, the first one found will be displayed in the editor and the process will end.

  5. Find all context toolbars with both:

    • Any scope

    • A predicate matching the parent node of the current node, selection, or cursor position.

      If there are any matching context toolbars, the editor will prioritize the context toolbars based on the position value.

    • If there are context toolbars with position: 'selection', they will be concatenated, the concatenated toolbar will be displayed, and the process will end.

    • If there are context toolbars with position: 'node', they will be concatenated, the concatenated toolbar will be displayed, and the process will end.

    • Otherwise, all context toolbars with position: line will be concatenated, the concatenated toolbar will be displayed, and the process will end.

  6. Repeat step 4 and 5 for each successive parent node in the DOM for context toolbars and context forms with scope: node until either:

    • A matching context form or context toolbars are found and displayed,

    • The root node of the editor is reached.