Customizing the RichText field using CKEditor
Magnolia in just 12 minutes
Why not learn more about what Magnolia can do while you have a coffee?
The RichText field is one of the most popular among Magnolia authors. It allows an author to influence the structure and appearance of the content and this flexibility is the reason many authors prefer the RichText field over others. Developers, however, often perceive the RichText field as a threat.
By giving authors the option to influence the rendered HTML, for example, by adding tables and lists, or changing the text size, a developer’s lovingly designed layout could get destroyed or breakpoints might stop working as intended. That is the reason developers prefer to restrict RichText fields as much as possible.
We can't decide for you how to set up your CMS or who gets their way. What we can do, however, is give you the flexibility to limit or increase the functionality of RichText fields based on your needs and ways of collaborating. You can even set up different capabilities for different RichText fields across the system. We will explain various options in this blog post and provide examples that you can easily and quickly use in your project.
Behind the scenes of the RichText field
The RichText field is powered by CKEditor 4, which is part of Magnolia’s UI Framework. Its default configuration provides a set of standard functionalities as well as Magnolia-specific extensions, allowing authors to select images and pages from Magnolia and directly link them to the editor. An additional benefit of the CKEditor is that it is customizable.
Customizing the CKEditor
You can find an overview of all CKEditor features in its documentation and together with the examples below, you will be able to flexibly tailor your RichText fields to your needs.
Limiting the functionality
To limit the functionality of a RichText field, you can disable various plugins, leaving you with the options in the following example.
This is the configuration file config-minimal.js:
var VAADIN_DIR_URL = typeof CKEDITOR.vaadinDirUrl !== 'undefined'? CKEDITOR.vaadinDirUrl : "../../../";
// Loads magnoliaFileBrowser replacing CKEditor file browser. This is added to the custom config below at config.extraPlugins
CKEDITOR.plugins.addExternal('magnoliaFileBrowser', VAADIN_DIR_URL + 'js/filebrowser/');
CKEDITOR.editorConfig = function( config ) {
removePlugins = [];
removePlugins.push("justify");
removePlugins.push("image");
removePlugins.push("enterkey");
removePlugins.push("indent");
removePlugins.push("list");
removePlugins.push("sourcearea");
removePlugins.push("table");
removePlugins.push("tabletools");
removePlugins.push("colorbutton");
removePlugins.push("colordialog");
removePlugins.push("font");
removePlugins.push("fontSize");
removePlugins.push("elementspath");
removePlugins.push("filebrowser");
config.removePlugins = removePlugins.join(",");
config.extraPlugins = "magnolialink,magnoliaexpand,magnoliaFileBrowser";
config.baseFloatZIndex = 150;
config.resize_enabled = false;
config.toolbar = "Magnolia";
config.toolbar_Magnolia = [
{name: "basicstyles", items: ["Bold", "Italic", "Underline", "SpecialChar"]},
{name: "links", items: ["Link", "InternalLink", "DamLink", "Unlink" ]},
{name: "undo", items: [ "Undo", "Redo" ] },
];
};
Light Development
Inspired by frontend development practices, Magnolia's unique light-weight development approach will get you started faster and finished sooner.
CKEditor’s default configuration
CKEditor’s default configuration provides the full range of functionality:
This is the configuration file config-default.js:
CKEDITOR.editorConfig = function( config ) {
};
However, this configuration does not provide any Magnolia-specific features. Besides, the number of options is almost too large and too unstructured to manage.
Magnolia’s default configuration
Magnolia provides only those CKEditor options that are needed by content authors and adds a set of Magnolia-specific features:
This is the configuration file config-magnolia.js:
var VAADIN_DIR_URL = typeof CKEDITOR.vaadinDirUrl !== 'undefined'? CKEDITOR.vaadinDirUrl : "../../../";
// Loads magnoliaFileBrowser replacing CKEditor file browser. This is added to the custom config below at config.extraPlugins
CKEDITOR.plugins.addExternal('magnoliaFileBrowser', VAADIN_DIR_URL + 'js/filebrowser/');
CKEDITOR.editorConfig = function( config ) {
// MIRROR info.magnolia.ui.field.RichTextFieldDefinition
definition = {
alignment: false,
images: false,
lists: true,
source: false,
tables: false,
colors: null,
fonts: null,
fontSizes: null
}
// MIRROR info.magnolia.ui.field.RichTextFieldDefinition
removePlugins = [];
// magnolialink AND REMOVAL OF elementspath FROM DEFAULT RICH TEXT FIELD FACTORY
removePlugins.push("elementspath");
removePlugins.push("filebrowser");
config.removePlugins = removePlugins.join(",");
config.extraPlugins = "magnolialink,magnoliaexpand,magnoliaFileBrowser";
config.baseFloatZIndex = 150;
config.resize_enabled = false;
config.toolbar = "Magnolia";
config.toolbar_Magnolia = [
{name: "basicstyles", items: ["Bold", "Italic", "Underline", "SpecialChar"] },
{name: "paragraph", items: ["NumberedList", "BulletedList", "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock", "Image", "Table" ]},
{name: "links", items: [ "Link", "InternalLink", "DamLink", "Unlink"]},
{name: "styles", items: ["Font", "FontSize", "TextColor", "ColorButton"]},
{name: "clipboard", items: ["Cut", "Copy", "Paste", "PasteText", "PasteFromWord"]},
{name: "undo", items: [ "Undo", "Redo" ] },
{name: "tools", items: [ "Source" ] },
{name: "view", items: [ "Expand" ] }
];
};
Customizing the RichText field
Now that you know your options, you can use the CKEditor configuration in Magnolia.
Adding the config file to your module
The first step to change the configuration is adding the configuration file to a Magnolia module. You can either use a Maven-based module or a Magnolia Light Module.
In any case, the file must be placed in the webresources folder of the module. You can create a subfolder “CKEditor” to structure the webresources folder for easier management.
<module-name>/
├── ...
└── webresources/
└── ckeditor/
└── config-magnolia-extended.js
Changing the field configuration
Once the CKEditor configuration has been added to a module, you can assign the configuration to any of your RichText fields by adding the property "configJsFile" to its dialog definition. The property’s value must be set to the path of the configuration file within the module folder, for example:
/.resources/customized-ck-editor/webresources/ckeditor/config-magnolia-extended.js
This is the dialog definition for a content app called bookshelf:
!content-type:bookshelf-app
name: bookshelf-app
icon: icon-content-app
subApps:
detail:
form:
properties:
<!-- more content -->
isbn13:
$type: richTextField
configJsFile: /.resources/customized-ck-editor/webresources/ckeditor/config-magnolia-extended.js
<!-- more content -->
Testing the configuration
Testing the configuration
You can verify the change by opening the dialog or checking the Definitions app.
If the richText field is part of a component or page dialog, you can find the definition in the Definitions app under “dialogs”. If it is part of a Content App, you can find it under “apps”:
If you don’t see the change in the dialog, your browser probably caches JavaScript files. To resolve the issue, clear your browser’s cache.
In Google Chrome, you can clear the cache of your current browser tab only:
Open DevTools by pressing F12
- Ctrl+Shift+I
- or Opt+Cmd+I on macOS
Leave DevTools open and right-click or click and hold the reload button next to the address bar. A hidden menu opens.
Click "Empty Cache and Hard Reload"
Other browsers might have similar functionality.
Adding plug-ins
To further extend the RichText field’s functionality, you can add other plug-ins, such as WordCount, using a Java module. In the following section, we show you how to add WordCount and activate it through the configuration. You can adapt this procedure to integrate many other plug-ins.
You can find an example of integrating the Special Characters plug-in on our Git.
Adding the WordCount plug-in
First, download the WordCount and Notification plug-ins. Note that the Notification plug-in is required by the WordCount plug-in.
Copy the parent folders of plugin.js into your Java module’s VAADIN folder under src/main/resources/VAADIN/js:
<maven-module-name>/
├── ...
└── src/
└── main/
├── ...
└── resources/
├── VAADIN/
└── js/
└── notification/
│ ├── lang/
│ └── plugin.js
└── wordcount/
├── css/
├── lang/
├── plugin.js
└── samples/
Enabling the WordCount plug-in
To enable the plug-in in Magnolia, create a copy of your preferred configuration in your webresources folder and update the configuration:
1. Import the plug-ins
Add the following:
CKEDITOR.plugins.addExternal("wordcount", CKEDITOR.vaadinDirUrl + "js/wordcount/");
CKEDITOR.plugins.addExternal("notification", CKEDITOR.vaadinDirUrl + "js/notification/");
2. Activate the plug-in
Add wordcount and notification to config.extraPlugins:
config.extraPlugins = "magnolialink,magnoliaexpand,magnoliaFileBrowser,wordcount,notification";
3. Configure the plug-in
Add the configuration in CKEDITOR.editorConfig = function( config ) { }:
config.wordcount = {
// Whether or not you want to show the Paragraphs Count
showParagraphs: false,
// Whether or not you want to show the Word Count
showWordCount: true,
// Whether or not you want to show the Char Count
showCharCount: true,
// Whether or not you want to count Spaces as Chars
countSpacesAsChars: true,
// Whether or not to include Html chars in the Char Count
countHTML: true,
// Maximum allowed Word Count, -1 is default for unlimited
maxWordCount: -1,
// Maximum allowed Char Count, -1 is default for unlimited
maxCharCount: -1,
};
Using the WordCount plug-in
Update configJsFile in your dialog definition to refer to your new configuration file.
Your richText field now shows the word count.
Conclusion
It’s easy to create different CKEditor configurations, allowing you to tailor RichText field options to your project requirements. You can define each RichText field’s functionality independently, giving you maximum flexibility to customize the options in a way that suits content authors and developers.