Creating components
The Process development kit lets improving EasySite by giving you the possibility to develop your own components.
The components are unit elements that can be added to a page,a block,a page template or a block template. They correspond to the smaller element handled in EasySite.
A component is at least composed of this group of elements:
- Definition: component XML description;
- Translation file: translation XML file of the character strings;
- Controller: events render management;
- Extension of properties editing: setting management;
- Render mode: the supported display types are the Process screens and the JSP pages.
Every file assigned to a component should be placed under the WEB-INF/storage/custom/components/project/package
root. The JSP files should be placed in a sub-level « views ».
Component XML definition
The components’ definition file must be named components.xml
. This file enables in fact to define several components. Every component defined in the XML file will be put together inside a same package and will be displayed as the same menu option in the WYSIWYG design tool.
In this XML file, each component is represented by a tag element. Under the tag element is the component definition.
<controller>
: Java Class branched off the BaseComponentController enabling to position the values of the bookmarks accessible for the JSP renders.<extension>
: Java Class branched off the BaseEditorExtension enabling to handle the group of properties present in the tag section.<depends>
: enables to specify the dependencies to JavaScript or CSS files.<navigation>
: the « navigation » tag enables to associate a Process screen to the developed component. Use the “screen” attribute with, as value the concatenation of the screen and the action name separated by a comma.<view>
: enables to define a JSP page that will display the graphical render of the component.<alternateView>
: enables to define the intermediate render when the page is displayed in “design” mode. You may declare either a render JSP page, either a sequence of field names surrounded by the $ character.<configuration>
: holds two sections:properties
andadvancedProperties
enabling to configure the developed component. Each section hasfield
tags whose description is very similar to the one you can find in the Process screens. Thepreview
attribute enables to indicate that the field value will be displayed in “tool tip” on the intermediate render of the component.
Example of an XML File
This example shows how to define a component inside a package. Please note the tags project
, package
, component
will be replaced respectively by the project system name, the package system name and the component system name. These names correspond to the folders created under the /custom/components
root too.
<?xml version="1.0" encoding="UTF-8"?>
<package name="<project>.<package>" provider="education.com" version="1.0">
<runtime/>
<depends/>
<components>
<element name="<project>.<package>.dummy">
<def>
<controller className="com.vdocsoftware.<project>.components.<package>.dummy.SimpleController"/>
<extension type="editor" className="com.vdocsoftware.<project>.components.<package>.dummy.SimpleEditorExtension"/>
<navigation screen="dummy.edit"/>
<alternateView>$fldTextBox$</alternateView>
<depends>
<ref type="javascript" value="/resources/external/js/beautiful.js"/>
<ref type="stylesheet" value="/resources/external/css/lovely.css"/>
</depends>
<configuration>
<section name="properties">
<fields>
<field name="fldTextBox" ctrl="text" width="long" mandatory="true"/>
<field name="fldTextArea" ctrl="textarea" width="long" cssclass="textarea" preview="true"/>
<field name="fldCheckBox" ctrl="checkbox" boolean-value="true"/>
</fields>
</section>
<section name="advancedProperties">
<fields/>
</section>
</configuration>
</def>
</element>
</components>
</package>
Translation file
The translation XML file concerning the developed components must be named strings.xml
and placed under the root of the package (/custom/components/project/package
).
This file must contain all the strings useful for the components defined in the definition XML file (components.xml).
Example of the translation XML file
In this example, the system name used for the “value” attribute is important. It is composed of the following elements separated by dots :
- the compulsory system prefix “ezs.component”;
- the project name;
- the package name;
- the component name.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<res>
<id value="ezs.component.<project>.<package>.label">
<lang value="fr">Mon composant</lang>
<lang value="en">My component</lang>
</id>
<id value="ezs.component.<project>.<package>.description">
<lang value="fr">Description de mon composant</lang>
<lang value="en">My component description</lang>
</id>
<id value="ezs.component.<project>.<package>.<component>.label">
<lang value="fr">Mon élément</lang>
<lang value="en">My element</lang>
</id>
<id value="ezs.component.<project>.<package>.<component>.description">
<lang value="fr">Description de mon élément</lang>
<lang value="en">My element description</lang>
</id>
</res>
In the case of using section fields, the strings should follow the following rule:
<id value="ezs.component.<project>.<package>.<component>.<field>.label">
<lang value="fr">Mon champ</lang>
<lang value="en">My field</lang>
</id>
<id value="ezs.component.<project>.<package>.<component>.<field>.description">
<lang value="fr">Description de mon champ</lang>
<lang value="en">My field description</lang>
</id>
Component controller
Each component may be associated to a controller which aims to receipt and process the events and to position the bookmarks values.
To implement a component controller, you just have to create a Java class which extends the class named BaseComponentController. This class must be defined in the controller tag of the components’ definition XML file (components.xml).
The full name of the basic class is: com.axemble.vdoc.sdk.impl.base.BaseComponentController
.
Method of the basis class BaseComponentController
This basic class gives access to the site module that itself enables to handle the whole site API and the execution context.
public abstract class BaseComponentController implements IComponentController {
final protected ISiteModule getSiteModule();
final public IComponent getComponent();
final public Map getComponentContext();
protected abstract void prepareModel( IRenderModel model ) throws Exception;
protected abstract void processEvent( String eventName, String eventValue ) throws Exception;
}
Example of component controller implementation
The following example shows how to position and to recover values from the current component context and how to manipulate the render template.
public class SimpleController extends BaseComponentController {
protected void processEvent( String eventName, String eventValue ) throws Exception {
// check the incoming event
if ( eventName.equals( "refresh" ) && eventValue.equals( "true" ) ) {
// store an information into the component context
this.getComponentContext().put( "forceRefresh", "true" );
}
}
protected void prepareModel( IRenderModel model ) throws Exception {
// retrieve the information from the component context
if ( this.getComponentContext().get( "forceRefresh" ).equals( "true" ) ) {
// set a value into the render model
model.setValue( "executeRefresh", Boolean.TRUE );
} else {
model.setValue( "executeRefresh", Boolean.FALSE );
}
}
}
Properties edition extension
An extension class of component properties enables to process the dynamic aspect display of the properties present in the component definition XML file.
To implement a component properties’ extension class, you just have to branch off the BaseEditorExtension class. This class must be defined in the component definition XML file (components.xml).
The full name of the class is: com.axemble.vdoc.sdk.document.extensions.BaseEditorExtension
.
Method of the BaseEditorExtension base class
This base class recovers the documentary base classes: BaseDocumentExtension and BaseResourceExtension. It gives access to the site and workflow modules, provides methods to access the information assigned to the current page. And it enables to manipulate the document assigned to the properties and to the graphical component representing the properties edition form (CtlAbstractForm).
public abstract class BaseEditorExtension implements IEditorExtension {
// initialization
public void init()
// events
public boolean onBeforeLoad()
public boolean onAfterLoad()
public boolean onBeforeSave()
public boolean onAfterSave()
public boolean onBeforeRemove()
public boolean onAfterRemove()
// validate event
public boolean validate()
// document access
final public AbstractDocument getDocument()
final public boolean isCreation()
// graphical elements access
final public CtlAbstractForm getForm()
final public IResourceController getResourceController()
// site elements
final public IContentContainer getContentContainer()
final public IContent getContent()
final public IContentComponent getContentComponent()
final public IBlock getRootBlock()
final public IBlock getParentBlock()
final public String getComponentName()
// modules
final public IBaseWorkflowModule getWorkflowModule()
final public IBaseSiteModule getSiteModule()
}
Render mode
The Process development kit offers two render modes of EasySite components:
- in the form of Process screens: define a Process screen as associated to the component;
- using JSP pages: define a group of JSP pages that must be present in the « views » component folder;
However we recommend the developments based on the Process screens.
“Process Screens” mode
The Process screen mode is activated if you use the “navigation” tag in the component definition XML description. Then you just have to fill-in the “screen” attributes with the concatenation of the name and the action screen separated by a dot.
<navigation screen="dummy.edit" />
“JSP Page” mode
The JSP Page mode is activated if you use the “view” tag in the component definition XML description. The tag view enables to define a JSP page that will make the graphical render.
<view>default.jsp</view>
Example
This example displays the using of new tags available in the Process development kit:
- recipientMessage: enables to send message to a recipient;
- event: enables to trigger an event;
- resource: enables to translate a string identifier.
<%@ taglib uri='http://www.vdocsoftware.com/enhancement' prefix='sdk' %>
<button type="button" name="sendAMessage" onclick="<sdk:recipientMessage recipient="basket" eventType="2" eventBody="-1" class="button2">
<span>
<sdk:resource id="send.a.message" />
</span>
</button>
<button type="button" name="fireAnEvent" onclick="<sdk:event name="basket" value="2" />" class="button2">
<span>
<sdk:resource id="fire.an.event" />
</span>
</button>
Notion d’héritage
Dans la conception de composants dédiés aux sites WEB Easysite, il est possible de construire une notion d’héritage.
Soit 20 composants disposant chacun du besoin de renseigner les mêmes champs dans leur configuration.
Au lieu de réaliser un copier-coller, il est possible de définir ces champs dans un composant “père” dont les 20 composants vont hériter.
Exemple
Soit un groupe de composants dans lesquels il faut saisir les champs de configuration suivants :
- Champ1
- Champ2
- Champ3
- Champ4
De plus, tous les composants ont une dépendance vers les mêmes CSS et JS externes.
Enfin, une classe d’extension d’éditeur se chargera de gérer les champs (alimentation des listes, valeurs par défaut, évènement onChange, …).
Conception d’un composant abstrait
La logique d’un composant “abstrait” reprend la même notion d’abstraction que la notion “objets”.
Un composant “abstrait” ne sera pas directement disponible sur le site WEB; cependant, d’autres composants pourront en hériter et sont disponibles sur le site WEB.
Voici à quoi pourrait ressembler la définition de du composant abstrait (abstract="true"
) :
<element name="dev.floor.MyAbstractComponent">
<def abstract="true">
<controller className=""/>
<extension type="editor" className="com.vdoc.dev.floor.MyAbstractComponentEditorExtension" />
<navigation screen=""/>
<alternateView/>
<depends>
<ref type="javascript" value="/resources/MyAbstractComponent/MyAbstractComponent.js" />
<ref type="stylesheet" value="/resources/MyAbstractComponent/MyAbstractComponent.css" />
</depends>
<configuration>
<section name="properties">
<fields>
<field name="Champ1" ctrl="text" mandatory="true" />
<field name="Champ2" ctrl="text" mandatory="true" />
<field name="Champ3" ctrl="text" mandatory="true" />
<field name="Champ4" ctrl="text" mandatory="true" />
</fields>
</section>
<section name="advancedProperties">
<fields>
</fields>
</section>
</configuration>
</def>
</element>
Création d’un composant fils avec ajout de nouvelles configurations
Ce composant hérite du composant abstrait, il doit donc proposer les champs “Champ1, Champ2, Champ3, Champ4”.
Deux nouveaux champs “Champ5, Champ6” sont ajoutés et sont spécifiques à ce composant.
On utilise la syntaxe : extends="dev.floor.MyAbstractComponent"
<element name="dev.floor.Component1">
<def extends="dev.floor.MyAbstractComponent">
<configuration>
<section name="properties">
<fields>
<field name="Champ5" ctrl="text" mandatory="true" />
</fields>
</section>
<section name="advancedProperties">
<fields>
<field name="Champ6" ctrl="text" mandatory="true" />
</fields>
</section>
</configuration>
</def>
</element>
La surcharge peut se faire en déclarant de nouveaux composants. Tout ce qui sera défini ou redéfini dans les composants fils restera, le reste prendra sa source dans le composant abstrait.
Il s’agit ici d’exmples avec les “fields”, mais on pourrait fait la même chose pour déclarer un “Controller” différent ou encore une “navigation” ou une “JSP” différente pour le rendu.
Création d’un composant fils simple avec suppression de configurations héritées
Dans ce deuxième composant, le composant hérité doit être présent pas le champ “Champ4”; il faut donc retirer ce noeud de l’héritage avec l’instruction override="delete"
.
<element name="dev.floor.Component2">
<def extends="dev.floor.MyAbstractComponent">
<configuration>
<section name="properties">
<fields>
<field name="Champ4" override="delete" />
</fields>
</section>
<section name="advancedProperties">
<fields>
</fields>
</section>
</configuration>
</def>
</element>
Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/HowToBuildExtendedSiteComponents