Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

Motivation

Rich Magnolia uses CKEditor as it's rich text editor implementation. CKEditor provides a link dialog where the user can define a link to any external resource. This is however not very suitable for creating links to internal Magnolia resources as the user would need to be aware of implementation details of how pages are referenced in Magnolia. 

...

Solution

To solve the problem of hiding details of how pages are referenced we introduced a new button to the rich text editor which opens the Pages App as a dialog window and the user can choose a page from the list. Workflow will be similar with dealing with external links where rich text editor allows to add, modify and remove links. Link to a Magnolia page will be shown with same style as external link and in general by default it will be in format: "/some-page"named after the page title.

As an implementation side effect an communications scheme with the CKEditor and server was created and this API is published to app developers to make the customisation of the rich text field easier.

Stories

  1. User would click add Magnolia link
  2. Pages App will be shown embedded in a dialog
  3. User selects a page from the dialog
  4. Rich text editor now has link to external resource
  1. User opens up context menu of selected link
  2. Context menu offers option to modify or remove the link
  3. On modifying Pages App will be shown to allow the selection of a link source
  1. User opens up context menu of selected link
  2. Context menu offers option to modify or remove the link
  3. On removing link the link nature is removed leaving the link as plain text

Implementation notes

  • Creating a link will be handled on server side. Client side will make a request to create link and the server will respond to that with a link.
  • Links are stored in HTML formatted rich text as they were stored in Magnolia 4. Client side plugin is necessary to render the appearance.
  • Functionality is implemented as a plugin for CKEditor. Will investigate possibility to create plugins purely on server side. 
    • This would make it possible to allow modifying plugins during runtime.

Dialogs

Basic use case

Image Removed

Image Removed

Image Removed

External link choosing (as a reference)

Dialogs

Editor with Magnolia link button

Image Added

Choose link dialog

Image Added

CKEditors default link chose dialog (as a reference)

Image Added

Extensions

It is possible to extend the underlying CKEditor with custom plugins. Normal CKEditor API is extended to enable communications with server side.

Here an example would construct a rich text field with custom plugin and upon construction sends an event to it. Plugin will react on event and send another event back to server.

Code Block
languagejava
titleServer side declaration of rich text field
MagnoliaRichTextFieldConfig config = new MagnoliaRichTextFieldConfig();
//Under /PATH/TO/JS/ there should be a file called plugin.js that declares a CK editor plugin called "myplugin".
config.addPlugin("myplugin", "/PATH/TO/JS/");
 
//Need to declare what events server side would like to receive. Beware of namespace clashes if you have multiple plugins.
config.addListenedEvent("eventFromPlugin");
 
MagnoliaRichTextField richtexteditor = new MagnoliaRichTextField(config);

 
richtexteditor.addListener(new MagnoliaRichTextField.PluginListener() {
	@Override
	public void onPluginEvent(String eventName, String value) {
		if (eventName.equals("eventFromPlugin")) {
			//Do something according to event
		}
	}
});
 
//You can piggyback JSON for more complex data structures in value parameter.
richtexteditor.firePluginEvent("eventToPlugin", "value data to plugin");

In client side declare a CKEditor plugin. Please note that path to plugin.js is relative to the widgetset folder and must not span to another site. This limitation is from the CKEditor.

Code Block
languagejavascript
title/PATH/TO/JS/plugin.js
(function() {
	//Register plugin to CKEditor
	CKEDITOR.plugins.add('myplugin', {
		init: function(editor) {
			//listen events from server
			editor.on('eventToPlugin', function(e) {
				//e.data holds the data server sent.
				//Do something with it if necessary.
 
				//Now send another event back to the server.
				editor.fire('eventFromPlugin', e.data);
			});		
		}
	});
})();

For developing CKEditor plugins please refer to it's tutorials at http://docs.cksource.com/CKEditor_3.x/Tutorials

Know issues

Problem with iOS and rich-text editing.

CK Editor allows for editing HTML in a WYSIWYG fashion and thus needs a sandbox for it. The standard way of doing such operations is to use an iFrame. Unfortunately, iFrame support in Mobile Safari is far from being ideal. In case of text editing  (any <input> tag is affected) within an iFrame - text selection and sometimes text editing is damaged. For instance, selecting the text block in the middle of a paragraph might be problematic - the cursor jumps to either en end or a beginning of the line. The problem appears when there is an 'ontouchstart' listener in the DOM hierarchy above or on the same level as an iFrame. In our case - this is inevitable.

However, the workaround exists - if the user triggers the magnifier glass to appear, it is possible to select the desire text blocks.

SO discussion links:

http://stackoverflow.com/questions/6876706/text-selection-bug-in-mobile-safari-with-iframes-and-ontouchstart
http://stackoverflow.com/questions/6175455/ipad-input-in-iframe

Apple issue report reference:

http://openradar.appspot.com/12967017

 Image Removed