RoxenCMS 5.4System Developer Manual PikeRoxen CMS-Specific Module APIsEditor Components

   

Overview
Implementation
API Reference

Overview

Basic concepts

A component consists of two parts: a Roxen module and an XSLT template. The module implements the user interface for entering and modifying content which the system stores in XML files in the site repository. The XSLT template controls how the transformation of the XML content takes place when rendered as part of a web page.

Roxen CMS keeps track of all active component modules and make them available in the page editor user interface. It also manages adding, moving, deleting or editing of component data as well as loading from and saving to XML content. Furthermore, it abstracts most of the hard work in building the data entry page the component uses. As a result the actual component module will normally be very simple, mostly consisting of declarations that give the component a name plus code that describes the input form.

Conceptually a component corresponds to an XML element in the page. The page is structured as follows:

<?xml version="1.0"?> <page-components> <some-component> ... </some-component> <another-component> ... </another-component> </page-components>

The top-level element must be named page-components for the editor to recognize it. Moreover, it's a requirement that all component tags have the suffix -component (this comes from the factory-defined XSLT templates and not the Roxen CMS framework, though).

The contents of a component element, e.g. <some-component> in the previous example, also has a standard structure. It consists of zero or more fields where each field contains component-specific data. Fields may be added by Roxen CMS itself (see discussion on <id> below).

Fields can come in any order so the component should only depend on the name of a field. It's also helpful, but not required, for the the component to substitute default values for missing fields. This is particularly useful when web developers insert components on the fly in a plain text editor.

A sample component with some fields can look like this:

<cartoon-component> <variant>3</variant> <cartoon>Donald Duck</cartoon> <rating>4</rating> <review><p>This one is <b>nice</b>!</p></review> <id>comp:1f93:e804:9012:51c4</id> </cartoon-component>

The fields here are <variant>, <cartoon>, <rating>, <review> and <id>.The last one, <id>, is created by Roxen CMS itself and is intended to be unique across all components and all pages in a site. There is no data of value hidden in the id value, and if you remove that field a new id will be added when someone edits the page. The id value is used, among other things, by the editor itself to handle versioning conflicts and by the link browser to link to a subsection of a page.

The example above includes another field called <variant>. It's an optional field but when included it gets special treatment. The page editor will query the component module for a list of available variants and display a popup menu at the top of the editing form. Variants have no special function in the XSLT transformation but is by convention used to handle layouts variations for a single component (e.g. left/right alignment of link titles, border/no border for tables etc).

The remaining fields, <cartoon>, <rating>, and <review>, are examples of fields with distinct types. For the rest of this chapter, let's assume that <cartoon> holds an alphanumeric string suitable for a name, <rating> holds an integer value and <review> contains free-form HTML markup. Roxen CMS have pre-defined content handlers for several types and will create form input elements suitable for editing them:

  • rich-text editor

  • plain text

  • select menu

  • color

  • URL

  • picture

  • file

  • user

With the exception of the first data type (rich-text editor), all types are read and written in plain text form without use of tags. The Roxen CMS editor framework is very easy to use for these data types. In case of rich text the editor is still abstracted but the saving of contents will require an extra step to function correctly.

Editing

When opening a page in the page editor Roxen CMS will match all component tags with those component modules that have been loaded into the server. Any unknown tags are ignored but preserved in the editing process. This is important since it also applies to regular HTML tags, comments etc. Note that these ignored tags are not presented to the person working on the page.

During editing operations Roxen CMS operates on the page in a tree form (not unlike the DOM model implemented by web browsers). The editor tries to keep the resulting XML code easy to read by insering or removing white-space text nodes between component elements; that should however be considered a bonus and is not guaranteed to behave identically in future versions.

Roxen CMS tracks all data related to each individual component (thus making it possible to have multiple but separate instances of the same component in one page) and stores temporary changes in RAM until the user decides on saving or canceling. If the server is restarted or a vital Roxen CMS module is reloaded by an administrator the RAM state will be lost.

While stored in memory the individual component fields can be quickly read or set by the component module. It is also possible to get direct access to the internal XML node object but it's important to remember that the node tree is not updated during editing operations and hence only reflects the file content when the editing session was started.

In case of deleting a component the corresponding XML tag is simply removed from the page content. Moving components will swap position with the preceding or following component in the page.

Adding components creates a new component tag and asks the component module to provide default values for its fields. A relevant issue here is exactly where to insert the component tag in the XML code in case there are other tags in the source file (e.g. unknown components or HTML/RXML tags). From the user's point of view the behavior is outside of his control, but internally Roxen CMS implements the following strategy: A new component is inserted directly after the closest preceding component element. If no such element exists the insertion takes place after the last tag in the top-level <page-components> element, which in turn is created if it's missing.

The last action to describe is the actual editing of the component data. When the user decides to edit the component, Roxen CMS asks the component module to render its edit form. In order to give a consistent user interface the component should then use the provided framework methods for building the necessary input fields. Normally this is handled by repeatedly calling a field render method for each of the wanted fields, and in each call supply the field name, the title and some additional parameters and flags. The result from these calls are HTML strings that the component should concatenate and then return back to the framework. This model gives the module an extra degree of flexibility in that it can include custom HTML code (e.g. extra form elements, JavaScript actions etc); however, for best result the layout part should be left to the framework since it guarantees the greatest amount of forward compatibility in case the editor interface is modified.

As currently designed the component module only declares field types in the call to the field render method. This lets the component decide on a suitable field type in a dynamic fashion. For future compatibility it is suggested that the component module keep types constant as much as possible since the editor framework is likely to be developed in this direction.

The user may perform multiple changes to a component form and even cause it to reload during normal editing. The Roxen CMS framework takes care of preserving input data in such circumstances but the component module may need special adjustment in case it builds custom HTML input widgets. All form variables belonging to a given component should use a name that is prefixed with a string supplied by the framework. This enables future versions of the editor to display multiple instances of the same component editing form in parallel without name conflicts.

Saving

When the editing is finished there are two types of save actions that the component module should handle. The first is the one where the given component form is completed and the latest data should be stored in RAM. This happens e.g. when the user starts editing of another component in the same page. It is signalled by a call to the component module where current data should be extracted from the corresponding form variables and be stored in memory.

The second type of save action is when the page itself is complete. In this situation Roxen CMS will write updated XML code to disk to reflect the changes the user has made. Invididual components are not directly involved in this step, but during this process they have an opportunity to perform additional modifications on the file itself. A typical use for this callback is to update file metadata. It should be noted that any other change (such as modifying content or metadata for the file being edited) is strictly prohibited at all other times since it will cause the current editing session to be marked invalid and therefore cancel any changes the user has made.