CKEditor plugins
The core of CKEditor can be extended with many plugins. Each plugin has a unique all-lowercase name that is used to reference the plugin in the CKEditor configuration.
Table of contents
- Available plugins
- Add an existing CKEditor plugin
- Remove an existing CKEditor plugin
- Add a custom CKEditor plugin
- CKEditor plugin that opens a Wicket dialog
Available plugins
The following CKEditor plugins ship with Bloomreach Experience Manager by default:
Plugin | Description | Used by default in Formatted Text Fields in | Used by default in Rich Text Fields in | Available since release | ||
---|---|---|---|---|---|---|
Content | Channels | Content | Channels | |||
a11yhelp | Accessibility Help | No | No | Yes | Yes | 10.0 |
about | About CKEditor | No | No | No | No | 10.0 |
autogrow | Auto Grow | No | Yes [2] | No | Yes [2] | 12.0 |
autolink | Auto Link | No | No | Yes | Yes | 13.1 |
balloonpanel | Balloon Panel | No | No | No | No | 12.0 |
balloontoolbar | Balloon Toolbar | No | No | No | No | 12.5 |
basicstyles | Basic Styles | Yes | Yes | Yes | Yes | 10.0 |
bidi | BiDi (Text Direction) | No | No | No | No | 10.0 |
blockquote | Blockquote | No | No | No | No | 10.0 |
button | UI Button | Yes | Yes | Yes | Yes | 10.0 |
clipboard | Clipboard | Yes | Yes | Yes | Yes | 10.0 |
codemirror | CodeMirror (Source) Syntax Highlighting | No | No | Yes | Yes | 10.0 |
codesnippet | Code Snippet | No | No | No | No | 10.0 |
colorbutton | Color Button | No | No | No | No | 10.0 |
colordialog | Color Dialog | No | No | No | No | 10.0 |
copyformatting | Copy Formatting | Yes | Yes | Yes | Yes | 12.0 |
contextmenu | Context Menu | Yes | Yes | Yes | Yes | 10.0 |
dialog | Dialog | Yes | Yes | Yes | Yes | 10.0 |
dialogadvtab | Advanced Tab for Dialogs | No | No | Yes | Yes | 10.0 |
dialogui | Dialog User Interface | Yes | Yes | Yes | Yes | 10.0 |
div | Div Container Manager | No | No | No | No | 10.0 |
divarea | Div Editing Area | Yes | Yes | Yes | Yes | 10.0 |
elementspath | Elements Path | No | No | Yes | Yes | 10.0 |
emoji | Emoji | No | No | No | No | 13.1 |
enterkey | Enter Key | Yes | Yes | Yes | Yes | 10.0 |
entities | Escape HTML Entities | Yes | Yes | Yes | Yes | 10.0 |
fakeobjects | Fake Objects | No | No | No | No | 10.0 |
filebrowser | File Browser | No | No | No | No | 10.0 |
find | Find / Replace | No | No | No | No | 10.0 |
floatingspace | Floating Space | Yes | Yes | Yes | Yes | 10.0 |
floatpanel | Floating Panel | Yes | Yes | Yes | Yes | 10.0 |
font | Font Size and Family | No | No | No | No | 10.0 |
format | Format | No | No | No | No | 10.0 |
forms [1] | Form Elements | No | No | No | No | 10.0 |
hippoautosave | Bloomreach Experience Manager auto save | Yes | Yes | Yes | Yes | 10.0 |
hippopicker | Bloomreach Experience Manager pickers for images and internal links | No | No | Yes | Yes | 10.0 |
horizontalrule | Horizontal Rule | No | No | No | No | 10.0 |
htmlwriter | HTML Output Writer | Yes | Yes | Yes | Yes | 10.0 |
iframe | IFrame Dialog | No | No | No | No | 10.0 |
iframedialog | Iframe Dialog Field | No | No | No | No | 13.4 |
image | Image | No | No | No | No | 10.0 |
image2 | Enhanced Image | No | No | No | No | 10.0 |
indent | Indent / Outdent | No | No | Yes | Yes | 10.0 |
indentblock | Indent Block | No | No | Yes | Yes | 10.0 |
indentlist | Indent List | No | No | Yes | Yes | 10.0 |
justify | Justify | No | No | Yes | Yes | 10.0 |
language | Language | No | No | No | No | 10.0 |
link | Link | No | No | Yes | Yes | 10.0 |
list | List | No | No | Yes | Yes | 10.0 |
listblock | List Block | Yes | Yes | Yes | Yes | 10.0 |
liststyle | List Style | No | No | Yes | Yes | 10.0 |
magicline | Magic Line | Yes | Yes | Yes | Yes | 10.0 |
mathjax | Mathematical Formulas | No | No | No | No | 10.0 |
maximize | Maximize | No | No [3] | Yes | No [3] | 10.0 |
mentions | Mentions | No | No | No | No | 13.1 |
menu | Menu | Yes | Yes | Yes | Yes | 10.0 |
menubutton | Menu Button | Yes | Yes | Yes | Yes | 10.0 |
notification | Notification | No | No | No | No | 10.2 |
pagebreak | Page Break | No | No | No | No | 10.0 |
panel | Panel | Yes | Yes | Yes | Yes | 10.0 |
panelbutton | Panel Button | Yes | Yes | Yes | Yes | 10.0 |
pastefromword | Paste from Word | No | No | Yes | Yes | 10.0 |
pastetext | Paste as Plain Text | No | No | Yes | Yes | 10.0 |
placeholder | Placeholder | No | No | No | No | 10.0 |
popup | Popup | No | No | Yes | Yes | 10.0 |
removeformat | Remove Format | Yes | Yes | Yes | Yes | 10.0 |
resize | Editor Resize | No | No [3] | Yes | No [3] | 10.0 |
richcombo | Rich Combo | Yes | Yes | Yes | Yes | 10.0 |
selectall | Select All | No | No | No | No | 10.0 |
sharedspace | Shared Space | No | Yes [2] | No | Yes [2] | 12.0 |
showblocks | Show Blocks | No | No | Yes | Yes | 10.0 |
showborders | Show Table Borders | No | No | Yes | Yes | 10.0 |
smiley | Insert Smiley | No | No | No | No | 10.0 |
sourcearea | Source Editing Area | No | No [3] | No | No [3] | 10.0 |
sourcedialog | Source Dialog | No | Yes [2] | No | Yes [2] | 12.0 |
specialchar | Special Characters | No | No | Yes | Yes | 10.0 |
stylescombo | Styles Combo | Yes | Yes | Yes | Yes | 10.0 |
tab | Tab Key Handling | Yes | Yes | Yes | Yes | 10.0 |
table | Table | No | No | Yes | Yes | 10.0 |
tableresize | Table Resize | No | No | Yes | Yes | 10.0 |
tableselection | Table Selection | No | No | Yes | Yes | 12.0 |
tabletools | Table Tools | No | No | Yes | Yes | 10.0 |
templates | Content Templates | No | No | No | No | 10.0 |
textselection | Keep TextSelection | No | No | Yes | Yes | 10.0 |
toolbar | Editor Toolbar | Yes | Yes | Yes | Yes | 10.0 |
undo | Undo | Yes | Yes | Yes | Yes | 10.0 |
widget | Widget | No | No | No | No | 10.0 |
wordcount | Word Count and Character Count | No | No | No | No | 10.0 |
wysiwygarea | IFrame Editing Area | No | No | No | No | 10.0 |
youtube | YouTube Plugin | No | No | Yes | Yes | 10.0 |
1 The 'forms' plugin requires the CKEditor instance to run in an iframe instead of a div, please see the example configuration on how to set this up correctly.
2 Explicitly enabled by the system
3 Explicitly disabled by the system
- The maximize plugin is replaced by the "full width toggle" in the right side-panel.
- The sourcearea plugin does not work with the inline version of CKEditor, so Channels uses the sourcedialog plugin instead.
- The resize plugin does not work with the inline version of CKEditor, so Channels uses the autogrow plugin instead.
Runtime debugging
The names of all available plugins can also be retrieved at runtime:
- Login to Bloomreach Experience Manager using Chrome or Firefox
- Edit a document type that contains an HTML field
- Open the Chrome dev tools or Firebug
- Execute the following JavaScript one-liner:
Object.keys(CKEDITOR.plugins.registered).sort()
Similarly, it is possible to retrieve the list of plugins used by a specific editor instance:
- Print the map of all CKEditor instances to find the name of the editor instance to inspect:
CKEDITOR.instances
- List all plugins in a specific instance, for example 'editor123':
Object.keys(CKEDITOR.instances.editor123.plugins).sort()
Add an existing CKEditor plugin
To add a CKEditor plugin that is already available in Bloomreach Experience Manager, use the CKEditor configuration property ' extraPlugins'. For example, to add the 'About' plugin:
ckeditor.config.overlayed.json:
{ extraPlugins: 'about' }
A plugin may add one or more buttons to toolbar groups that are not shown by default. In that case, also add these toolbar groups. For example, to show the 'About' button in rich text fields, also add the following configuration:
ckeditor.config.appended.json:
{ toolbarGroups: [ { name: 'about' } ] }
Remove an existing CKEditor plugin
To remove a CKEditor plugin that is included by default, use the CKEditor configuration property ' removePlugins'. For example, to remove the 'styles' combo box, add the following configuration:
ckeditor.config.overlayed.json:
{ removePlugins: 'stylescombo' }
Add a custom CKEditor plugin
Custom CKEditor plugins can be located in any .jar file that is packaged with the 'cms' application in your project. The easiest way to include them is to add them to the 'cms' artifact itself.
The source code of all custom CKEditor plugins must be placed under:
src/main/resources/ckeditor/plugins/
Each plugin has its own sub-directory. The name of the sub-directory is the name by which the plugin is referred to in the CKEditor configuration. Each plugin consist of main 'plugin.js' file that is loaded by CKEditor, and optionally more files and icons.
In production, the CMS uses an 'optimized' version of the CKEditor sources (i.e. minified, concatenated, one big sprint with all icons, etc.). These optimized sources are loaded from the directory src/main/resources/ckeditor/optimized. Custom plugins should therefore also generate a version of their source code that is put in the subdirectory 'optimized' and used together with the optimized CKEditor sources. Optimizing a few small custom plugins usually does not gain much performance, so the easiest way is to simply copy the sources with the Maven resources plugin (see the example below).
mvn clean verify -Dinclude.ckeditor.sources
This mechanism ensures that the CKEditor sources are only included when explicitly asked for, which saves about 6MB of unused sources in production war files.
Example: timestamp plugin
The CKEditor developer's guide describes an example CKEditor plugin called 'timestamp'. Perform the following steps to add this timestamp plugin to the archetype-created project:
- Download the source code and copy the tutorial-timestamp/timestamp in the directory cms/src/main/resources/ckeditor/plugins. The final file structure should be as follows:
cms/ src/ main/ resources/ ckeditor/ plugins/ timestamp/ icons/ timestamp.png plugin.js
- To use a copy of the sources as an optimized version, add the following to the build/plugins section in the file cms/pom.xml:
<build> <plugins> ... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>create-optimized-resources</id> <phase>generate-resources</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/classes/ckeditor/optimized</outputDirectory> <resources> <resource> <directory>${basedir}/src/main/resources/ckeditor</directory> </resource> </resources> </configuration> </execution> </executions> </plugin> ... </plugins> </build>
- Build the project and start it:
mvn clean verify mvn -Pcargo.run
-
Login to the CMS as 'admin' and edit the 'newsdocument' type in the document type editor (To The Documents > Configuration > myproject > newsdocument > Edit)
-
Select the 'Body' field and add the 'timestamp' plugin to the overlayed CKEditor configuration:
ckeditor.config.overlayed.json:
{ extraPlugins: 'timestamp' }
The 'timestamp' icon should now be visible in toolbar of the editor for the 'Body' field.
Follow the Simple CKEditor Plugin Tutorial to learn more about creating CKEditor plugins.
CKEditor plugin that opens a Wicket dialog
A custom CKEditor plugin can also open a Wicket dialog in Bloomreach Experience Manager. Such a plugin requires two things:
- a CKEditor plugin for the client-side logic and UI.
- a custom CKEditorNodePlugin Java class that creates a CKEditorPanel class with an additional CKEditorPanelExtension.
A good example of such a plugin is the 'hippopicker' plugin in the CMS. This plugin adds the 'image' and 'internal link' buttons that open the Bloomreach Experience Manager image picker and Bloomreach Experience Manager document picker, respectively (which are both Wicket dialogs). Each CKEditor field is rendered by the CKEditorPanel class. The server-side Wicket behavior for the hippopicker plugin is added by default to the CKEditorPanel by the CKEditorNodePlugin. To get your own server-side behavior in there too, create your own class that extends CKEditorNodePlugin. First add the following dependency to your cms pom.xml (or the pom.xml of another artifact that will be included in the cms war file):
<dependency> <groupId>org.onehippo.cms7</groupId> <artifactId>hippo-cms-richtext-ckeditor-frontend</artifactId> </dependency>
The custom plugin class should override the createEditPanel method and add an extra CKEditorPanelExtension to the returned CKEditorPanel. For example:
public class MyCKEditorNodePlugin extends CKEditorNodePlugin { @Override protected CKEditorPanel createEditPanel(String id, String editorConfigJson) { CKEditorPanel panel = super.createEditPanel(id, editorConfigJson); panel.addExtension(new MyCKEditorPanelExtension(...)); return panel; } }
The MyCKEditorPanelExtension can then add the necessary Wicket behaviors that open your picker, and add the Ajax URL to open this picker to the editorConfig JSON object that will be provided to the client-side code. The client-side can then POST the Ajax URL to open the server-side picker. Vice-versa, the server-side can render some JavaScript that invokes a CKEditor command when the picker is closed (see the existing code for details).
The last thing to do is to use your own plugin class instead of the default one:
/hippo:namespaces/hippostd/html/editor:templates/_default_/root - plugin.class = org.example.MyCKEditorNodePlugin
Visual Editor
A plugin that opens a Wicket dialog cannot be used in HTML fields in the Visual Editor. The plugin code should therefore only initialize itself when the editor is loaded in a Wicket context:
CKEDITOR.plugins.add('mywicketbasedplugin', { init: function (editor) { if (window.Wicket) { // initialize plugin } } }
Another option is to not use Wicket at all. For example, let your plugin use CKEditor UI widgets only and let it call a custom REST API by creating a repository JAX-RS service.