Quick insert
ElementQuickInsert opens a menu with a search field and the elements that can be inserted at a position. Type to filter, press Enter to insert the first match, or use the arrow keys to pick one.
import { ElementQuickInsert } from 'ckeditor5-elements';
import 'ckeditor5-elements/index.css';The menu is shown by the ElementMenu plugin, which ElementQuickInsert loads. It does not add a right-click menu; that needs ElementContextMenu.
Which elements are listed
Only the elements that the schema allows at exactly the position. Nothing is split to make room: inside a paragraph, only inline elements (such as a line break) are allowed, so headings are not listed there. Between blocks, the blocks are.
Generic schema items (such as $text) are never listed. The elements are listed in the order they were registered.
Keyboard
Alt+Enter (Option+Enter on macOS) opens the menu at the cursor. The keystroke is listed in the accessibility help (Alt+0):
Source
import { Essentials, Heading, Paragraph, SourceEditing } from 'ckeditor5';
import { ElementQuickInsert } from 'ckeditor5-elements';
import type { Demo } from './shared/demo';
export default {
config: {
plugins: [Essentials, SourceEditing, Paragraph, Heading, ElementQuickInsert],
toolbar: ['undo', 'redo', 'sourceEditing', '|', 'heading'],
// Elements without a label are listed by their model name.
elementQuickInsert: { labels: { softBreak: 'Line break' } }
},
data:
'<p>Put the cursor in the middle of this sentence and press Alt+Enter (Option+Enter on macOS). ' +
'Inside a paragraph, only inline elements are allowed, so the menu offers a line break.</p>'
} satisfies Demo;Before or after a block
To insert blocks, open the menu for the position before or after a block. The quickInsertBefore and quickInsertAfter commands do that for the block with the cursor, or for a given element. Use them as toolbar buttons or as context menu items:
Source
import { Essentials, Heading, Paragraph, Plugin, SourceEditing } from 'ckeditor5';
import { ElementContextMenu, ElementOrPositionButtonView, insertIcon, ElementQuickInsert } from 'ckeditor5-elements';
import { Note } from 'ckeditor5-elements-example';
import type { Demo } from './shared/demo';
/**
* Toolbar buttons for the `quickInsertBefore` and `quickInsertAfter` commands: they open the quick insert menu before
* or after the block with the cursor.
*/
class InsertButtons extends Plugin {
public static get requires(): readonly [typeof ElementQuickInsert] {
return [ElementQuickInsert] as const;
}
public init(): void {
const editor = this.editor;
for (const name of ['quickInsertBefore', 'quickInsertAfter'] as const) {
const command = editor.commands.get(name);
if (command) {
editor.ui.componentFactory.add(
name,
locale => new ElementOrPositionButtonView(locale, command, { withText: true })
);
}
}
}
}
export default {
config: {
plugins: [Essentials, SourceEditing, Paragraph, Heading, Note, ElementContextMenu, InsertButtons],
toolbar: ['undo', 'redo', 'sourceEditing', '|', 'heading', '|', 'quickInsertBefore', 'quickInsertAfter'],
// The same commands in the context menu.
elementContextMenu: (element, editor) => [
{
title: 'Insert',
icon: insertIcon,
items: [editor.commands.get('quickInsertBefore'), editor.commands.get('quickInsertAfter')]
}
],
elementQuickInsert: {
labels: { paragraph: 'Paragraph', heading1: 'Heading 1', heading2: 'Heading 2', note: 'Note' },
exclude: ['heading3']
}
},
data:
'<h2>Insert next to a block</h2>' +
'<p>Put the cursor here and click <b>Insert after</b>, or right-click and choose <b>Insert › Insert after</b>.</p>' +
'<aside class="note"><p>Inside a note, blocks can be inserted next to this paragraph too.</p></aside>'
} satisfies Demo;They are enabled only when something can be inserted at that position.
From code
The quickInsert command inserts an element by its name. It takes the target first, like all element commands: a position, an element (meaning the position before it), or nothing (the selection). The plugin opens the menu, with open().
// Inserts a heading at the position.
editor.execute('quickInsert', position, 'heading2');
// Opens the menu for the position before the element.
editor.plugins.get('ElementQuickInsert').open(element);After inserting, an object is selected; an element that holds text gets the cursor inside it; an element that holds blocks gets a paragraph with the cursor.
Source
import { Essentials, Heading, Paragraph, SourceEditing, type ClassicEditor } from 'ckeditor5';
import { ElementQuickInsert } from 'ckeditor5-elements';
import type { Demo } from './shared/demo';
/**
* Buttons outside the editor: one executes the `quickInsert` command, one opens the menu of the plugin.
*/
function addControls(editor: ClassicEditor, container: HTMLElement): void {
const root = editor.model.document.getRoot();
const controls = document.createElement('div');
const actions: [label: string, run: () => void][] = [
// With an element name: inserts it. The target comes first: here, the position at the end of the root.
[
'Insert a heading at the end',
() => {
if (root) {
editor.execute('quickInsert', editor.model.createPositionAt(root, 'end'), 'heading2');
}
}
],
// The menu, of the plugin. An element as the target means the position before it.
[
'Open the menu before the first block',
() => {
const first = root?.getChild(0);
if (first?.is('element')) {
editor.plugins.get(ElementQuickInsert).open(first);
}
}
]
];
controls.className = 'editor-demo__controls';
for (const [label, run] of actions) {
const button = document.createElement('button');
button.textContent = label;
button.addEventListener('click', run);
controls.append(button);
}
container.append(controls);
}
export default {
config: {
plugins: [Essentials, SourceEditing, Paragraph, Heading, ElementQuickInsert],
toolbar: ['undo', 'redo', 'sourceEditing', '|', 'heading'],
elementQuickInsert: { labels: { paragraph: 'Paragraph', heading1: 'Heading 1', heading2: 'Heading 2' } }
},
data: '<p>The first block.</p><p>The last block.</p>',
ready: addControls
} satisfies Demo;open(target?, domTarget?) shows the menu next to the DOM target, by default next to the element or the selection. editor.plugins.get('ElementQuickInsert') also has getItems(target?), and hasItems(target?).
Configuration
elementQuickInsert: {
// Labels by model name. Elements without a label are listed by their model name.
labels: { paragraph: 'Paragraph', heading1: 'Heading 1' },
// Elements that are never listed.
exclude: ['heading3'],
// The keystroke that opens the menu at the cursor. `false`: none.
keystroke: 'Alt+Enter'
}Limitations
- The menu closes when the document changes while it is open (e.g. by another user), so it never inserts at an outdated position.
- Elements are inserted empty, so elements that need attributes to be useful (e.g. an image needs its source) should be excluded.