Clickable elements
ElementClickable calls a function when an element is clicked or double-clicked, with the model element. The elements are matched by the name of the model element, or by a filter function. The definitions are the elementClickable editor option:
import { ElementClickable } from 'ckeditor5-elements';
// In the editor config:
plugins: [..., ElementClickable],
elementClickable: [
// By name. The default event is `click`.
{ element: 'imageBlock', callback: (element, editor) => console.log(element.getAttribute('src')) },
// By a filter: `(element: ModelElement) => boolean`. Here, on double click.
{ element: element => element.name.startsWith('heading'), event: 'dblclick', callback: edit }
];The callback gets the model element, the editor, and the DOM MouseEvent.
Source
import { Essentials, ImageBlock, ImageCaption, Link, LinkImage, Paragraph, SourceEditing } from 'ckeditor5';
import { ElementAttributes, ElementClickable, type ElementClickableDefinition } from 'ckeditor5-elements';
import { Note } from 'ckeditor5-elements-example';
import type { Demo } from './shared/demo';
// An image that needs no network.
const image =
'data:image/svg+xml;utf8,' +
encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="160" height="90"><rect width="160" height="90" fill="#4f46e5"/></svg>'
);
// The callback runs the command of `ElementAttributes` for the element that was clicked.
const showAttributes: ElementClickableDefinition['callback'] = (element, editor) => {
editor.commands.get('showElementAttributes')?.executeFor(element);
};
export default {
config: {
plugins: [
Essentials,
SourceEditing,
Paragraph,
Link,
ImageBlock,
ImageCaption,
LinkImage,
ElementAttributes,
Note,
ElementClickable
],
toolbar: ['undo', 'redo', 'sourceEditing', '|', 'link', 'note'],
elementClickable: [
// By a filter function: images, and anything with a link (a linked image). Called on click.
{
element: element => element.name === 'imageBlock' || element.hasAttribute('linkHref'),
callback: showAttributes
},
// By name, on double click.
{ element: 'note', event: 'dblclick', callback: showAttributes }
]
},
data:
'<p><strong>Click an image</strong>: a modal with its attributes. <strong>Double-click the note</strong> for the ' +
'attributes of the note.</p>' +
`<figure class="image"><img src="${image}" alt="A plain image"></figure>` +
`<figure class="image"><a href="https://ckeditor.com"><img src="${image}" alt="A linked image"></a></figure>` +
'<aside class="note"><p>Double-click this note.</p></aside>'
} satisfies Demo;The demo shows the attributes of the element in CKEditor's modal dialog. The callback runs the command of ElementAttributes for the element that was clicked:
const showAttributes = (element, editor) => {
editor.commands.get('showElementAttributes').executeFor(element);
};Which element is called
The click is matched against the element that was clicked and its ancestors, the innermost first. The first element that matches a definition for that event calls its callback, and nothing more is called:
- Clicking an image inside a note calls the definition of the image, not the note's one.
- When two definitions match the same element, the first one in the config wins.
- A click and a double click are separate: a definition for
dblclickis not called by a single click. (A double click is two clicks and a double click, so aclickdefinition for the same element is called twice too.)
The filter is a function of the model element, so it can look at its attributes: element => element.hasAttribute('linkHref') matches linked images.
What it is not
- The click still does what it does in the editor, e.g. selects an image or moves the cursor: the plugin reports it, and does not prevent it. It works in read-only mode too.
- Only model elements can be matched. A link in text is an attribute of the text (
linkHref), not an element, so a click on it gives the paragraph. A linked image is an element with alinkHrefattribute, so it can be matched.