Customizing the RichText field using CKEditor

by Tobias Kerschbaum, Solution Architect at Magnolia
Feb 23, 2021 | 9 MIN

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.

Learn more

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:

  1. Open DevTools by pressing F12, Ctrl+Shift+I, or Opt+Cmd+I on macOS

  2. Leave DevTools open and right-click or click and hold the reload button next to the address bar. A hidden menu opens.

  3. 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.

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.

Tobias Kerschbaum

About the Author

As a solution architect, Tobias works closely with customers and partners, sharing his knowledge and expertise. He helps organizations evaluate and understand how Magnolia can meet project requirements. He contributes to the project plan and ensures the right modules and technologies are chosen. Besides delivering tailored workshops, Tobias also gets involved when customers and partners need to implement new functionality or custom requirements.