Page tree
Skip to end of metadata
Go to start of metadata

Motivation

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 by default it will be 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.

Dialogs

Editor with Magnolia link button

Choose link dialog

CKEditors default link chose dialog (as a reference)

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.

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

/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

 

1 Comment

  1. To do: The second part about extending the CKEditor is something we should document for users. It is an advanced topic. Check with Samuli if the code snippets are usable as such and accurate. (Antti)