{docbook}
<abstract>
<para>This chapter represents issues related to creating a new content manually via the following topics:</para>
<itemizedlist>
  <listitem>
	<para>
	  <emphasis role="bold"><link linkend="DEV.WorkWithContent.NodeType">Node type</link></emphasis>
	</para>
	<para>
	Ways to define your node type and document type, as well as to select types of Content template.
	</para>
  </listitem>
  <listitem>
	<para>
	 <emphasis role="bold"><link linkend="DEV.WorkWithContent.DialogSyntax">Dialog Syntax</link></emphasis>
	</para>
	<para>
	Groovy Templates that generate forms by mixing static HTML fragments and Groovy calls to the components responsible for building the UI at runtime.
	</para>
  </listitem>
  <listitem>
	<para>
	 <emphasis role="bold"> <link linkend="DEV.WorkWithContent.CKEditor">Customize CKEditor</link></emphasis>
	</para>
	<para>
	A WYSIWYG editor (text editor) which allows you to see what the published results look like while editing your text.
	</para>
  </listitem>
  <listitem>
	<para>
	  <emphasis role="bold"><link linkend="DEV.WorkWithContent.Taxonomy">Taxonomy</link></emphasis>
	</para>
	<para>
	A particular classification arranged in a hierarchical structure that helps you organize your content into categories.
	</para>
  </listitem>
  <listitem>
	<para>
	  <emphasis role="bold"><link linkend="DEV.WorkWithContent.ManageTemplateService">Template Service</link></emphasis>
	</para>
	<para>
	A service which allows developers to create dialogs and view templates for each node type register.
	</para>
  </listitem>
  <listitem>
	<para>
	  <emphasis role="bold"><link linkend="DEV.WorkWithContent.NavigationByContent">Navigation By Content</link></emphasis>
	</para>
	<para>
	A feature which allows developers to browse content of each page easily. With this feature, users experiencing eXo Platform 3.5 can navigate from a page to another or browse site content inside one page directly from a contextual menu.
	</para>
  </listitem>
</itemizedlist>
</abstract>
{docbook}

{note}
eXo Platform provides you with 2 options to create the content for your new extension:
* Create new content manually.
* Import an existing content into your extension.
{note}

h1. Node type {anchor:id=DEV.WorkWithContent.NodeType}

To create a content for your extension, you first need to define a node type which represents the document type in the JCR. There are 2 ways to define your node type:

* Via the *Content Administration* portlet. For more details on how to create a note type via the *Content Administration* portlet, see the *[Manage node types|../../../user-guide/html/sect-User_Guide-Content_Types-Manage_Node_Types.html]* in the eXo Platform 3.5 user guide.
* Via the .xml configuration files by creating a _nodetypes-configuration.xml_ file in your extension as below.

{code:xml}
<nodeType name="exo:newnodetype" isMixin="true" hasOrderableChildNodes="false" primaryItemName=""> 
  <supertypes>
    <supertype>exo:article</supertype>
  </supertypes>
  <propertyDefinitions>
    <propertyDefinition name="text" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY"
    protected="false" multiple="false">
      <valueConstraints/>
    </propertyDefinition>
    <propertyDefinition name="date" requiredType="Date" autoCreated="false" mandatory="true" onParentVersion="COPY"
    protected="false" multiple="false">
      <valueConstraints/>
    </propertyDefinition>

  </propertyDefinitions>
</nodeType>
{code}

By defining a supertype, you can reuse other node types and extend them with more properties (just like inheritance in Object Oriented Programming).

{docbook}
<para xml:id="DEV.WorkWithContent.DocumentType">
<citetitle>
<emphasis role="bold">
Document type
</emphasis>
</citetitle>
</para>
{docbook}

The *Document Type* checkbox is to define if the node type should be a *Document Type* or not. If this checkbox is selected, the *Sites Explorer* considers such nodes as user content and applies the following behavior:

* The *View* template will be used to display the *DocumentType* nodes.

* The document types nodes can be created by the *Add Content* action. The forms shown in the *Add Document* action are the corresponding *Dialog* templates of each document type.

* Non-document types are hidden unless the *Show Non-document Nodes* option is checked.

Templates are written using Groovy Templates and will require experiences with JCR API and HTML notions.

{docbook}
<para xml:id="DEV.WorkWithContent.WCMTemplate">
<citetitle>
<emphasis role="bold">
Content template
</emphasis>
</citetitle>
</para>
{docbook}

After defining your node type, you need to select templates which are applied to a node type or a metadata mixin type. eXo Platform provides 2 types of Content templates, including:

* *dialogs* which are HTML forms for creating node instances.
* *views* which are HTML fragments for displaying nodes.

From the *Content Administration* portlet, the *Manage Template* module lists all existing node types that have been associated with *Dialog* and/or *View* templates.
These templates can be attached to permissions (in the usual _membership\:group_ form), so which specific templates are displayed according to user rights (which can be useful in a content validation workflow activity).

{docbook}
<para>
<citetitle>
<emphasis role="bold">
Enable JavaScrip
</emphasis>
</citetitle>
</para>
{docbook}

In eXo Platform, you can specify whether JavaScript is allowed to run on a field of the content template or not by using the _"option"_ parameter.

*1.* Go to *Content Administration --> Content Presentation --> Manage Templates*.

*2.* Edit your desired template.

*3.* Select the *Dialog* tab, and then edit the content of _Dialog1_ in the *View & Edit Template* form.

*4.* Add _option = noSanitization_ to the code in the *Main* field as the example below.

For example:
{code}
String [] htmlArguments = ["jcrPath = / node / default.html / JCR: content / JCR: data", "options = toolbar: CompleteWCM, height: '410px ', noSanitization" htmlContent];
{code}

{note}
By default, JavaScript is disabled for any fields of some content templates to prevent the XSS attacks.
{note}

{docbook}
<para>
<prompt>
    <emphasis role="bold">See also</emphasis>
</prompt>
</para>
{docbook}
* [Dialog Syntax|#DEV.WorkWithContent.DialogSyntax]
* [Customize CKEditor|#DEV.WorkWithContent.CKEditor]
* [Taxonomy|#DEV.WorkWithContent.Taxonomy]
* [Template Service|#DEV.WorkWithContent.ManageTemplateService]
* [Navigation By Content|#DEV.WorkWithContent.NavigationByContent]
h1. Dialog Syntax {anchor:id=DEV.WorkWithContent.DialogSyntax}

{docbook}
<highlights>
        <itemizedlist>
          <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.Interceptors">Interceptors</link>
            </para>
			<para>
			By placing interceptors in your template, you will be able to execute a Groovy script just before and just after saving the node. 
			</para>
          </listitem>
          <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.HiddenFields">Hidden fields</link>
            </para>
			<para>
			Information about the hidden fields of Content.
			</para>
          </listitem>
        </itemizedlist>
<para>Dialogs are Groovy Templates that generate forms by mixing static HTML fragments and Groovy calls to the components responsible for building the UI at runtime. As a result, you will get a simple but powerful syntax.</para>
</highlights>
{docbook}

{docbook}
<para>
<prompt>
    <emphasis role="bold">See also</emphasis>
</prompt>
</para>
{docbook}
* [Node type|#DEV.WorkWithContent.NodeType]
* [Customize CKEditor|#DEV.WorkWithContent.CKEditor]
* [Taxonomy|#DEV.WorkWithContent.Taxonomy]
* [Template Service|#DEV.WorkWithContent.ManageTemplateService]
* [Navigation By Content|#DEV.WorkWithContent.NavigationByContent]

h2. Interceptors {anchor:id=DEV.WorkWithContent.InterceptorsRoleNotInToc}

By placing interceptors in your template, you will be able to execute a Groovy script just before and just after saving the node. Pre-save interceptors are mostly used to validate input values and their overall meaning while the post-save interceptor can be used to do some manipulations or references for the newly created node, such as binding it with a forum discussion or wiki space.

To place interceptors, use the following fragment:

{code:groovy}
<% uicomponent.addInterceptor("ecm-explorer/interceptor/PreNodeSaveInterceptor.groovy", "prev");%>
{code}

Interceptor Groovy scripts are managed in the 'Manage Script' section in the ECM admin portlet. They must implement the CmsScript interface. Pre-save interceptors obtain input values within the context:

{code:java}
public class PreNodeSaveInterceptor implements CmsScript {

  public PreNodeSaveInterceptor() {
  }

  public void execute(Object context) {
    Map inputValues = (Map) context;
    Set keys = inputValues.keySet();
    for(String key : keys) {
      JcrInputProperty prop = (JcrInputProperty) inputValues.get(key);
      println("   --> "+prop.getJcrPath());
    }
  }

  public void setParams(String[] params) {
  }

}
{code}

Whereas the post-save interceptor is passed the path of the saved node in the context:

{code:java}
<% uicomponent.addInterceptor("ecm-explorer/interceptor/PostNodeSaveInterceptor.groovy", "post");%>

public class PostNodeSaveInterceptor implements CmsScript {

  public PostNodeSaveInterceptor() {
  }

  public void execute(Object context) {
    String path = (String) context;

    println("Post node save interceptor, created node: "+path);
  }

  public void setParams(String[] params) {
  }
}
{code}

h2. Hidden fields {anchor:id=DEV.WorkWithContent.HiddenFieldsRoleNotInToc}

In the next code sample, each argument is composed of a set of keys and values. The order of arguments are not important and only the key matters. That example defines a field with the id as "hiddenField2", which will generate a hidden field. The value of this field will be automatically set to UTF-8 and no visible field will be printed on the form.

{code:groovy}
String[] hiddenField2 = ["jcrPath=/node/jcr:content/jcr:encoding", "visible=false", "UTF-8"];
uicomponent.addHiddenField("hiddenInput2", hiddenField2);
{code}

Once the form has been saved, the date value will be saved under the relative JCR path ./exo:image/jcr:lastModified.

{docbook}
<para xml:id="DEV.WorkWithContent.Non-ValueField">
<citetitle>
<emphasis role="bold">Non-value field</emphasis>
</citetitle>
</para>
{docbook}


You cannot either see the non-value field on the form or input value for them. Its value will be automatically created or defined when you are managing templates.

{code:groovy}
String[] hiddenField1 = ["jcrPath=/node/jcr:content", "nodetype=nt:resource", "mixintype=dc:elementSet", "visible=false"] ;
uicomponent.addHiddenField("hiddenInput1", hiddenField1) ;
{code}

{docbook}
<para xml:id="DEV.WorkWithContent.Non-EditableFields">
<citetitle>
<emphasis role="bold">Non-editable fields</emphasis>
</citetitle>
</para>
{docbook}

It is possible to create widgets that are non-editable (and then only used to print some information).

{code:java}
String[] fieldCategories = ["jcrPath=/node/exo:category", "multiValues=true", "reference=true", "editable=false"]; uicomponent.addTextField("categories", fieldCategories);
{code}

{docbook}
<para xml:id="DEV.WorkWithContent.CreateNodeTypeOrMixinType">
<citetitle>
<emphasis role="bold">Create node type or mixin type</emphasis>
</citetitle>
</para>
{docbook}

In many cases, when creating an instance where the node is out of form, you must still specify the CMS service about the node structure. Particularly, you must define if which node type is child of the newly created node or if the current node has any mixin type attributed.

By defining these arguments, the node and its children are created with the correct node type and mixin type.

See the following example:

{code:groovy}
String[] hiddenField = ["jcrPath=/node/jcrcontent", "nodetype=nt:resource", "mixintype=exo:rss-enable", "visible=false"] ;
uicomponent.addHiddenField("hiddenInput", hiddenField) ; 
{code}

{docbook}
<para xml:id="DEV.WorkWithContent.HiddenFieldWithDefaultValue">
<citetitle>
<emphasis role="bold">Hidden field with default value</emphasis>
</citetitle>
</para>
{docbook}

In the previous sample, the value was automatically created and set according to the current date. However, it is also possible to set a default value for a field.

{code:groovy}
String[] hiddenField = ["jcrPath=/node/jcrcontent/jcr:mimeType", "image/jpeg"] ;
uicomponent.addHiddenField("hiddenInput", hiddenField) ;
{code}

{docbook}
<para xml:id="DEV.WorkWithContent.VisibleWithoutNullFields">
<citetitle>
<emphasis role="bold">Visible without null fields</emphasis>
</citetitle>
</para>
{docbook}

It is possible to tell that a widget should be visible only if its value is not null or when the form is used to edit the node which has been existing.

{code:groovy}
String nameArgs[] = ["jcrPath=/node", "mixintype=mix:votable", "visible=if-not-null"];
uicomponent.addMixinField("name", nameArgs ) 
{code}

{docbook}
<para xml:id="DEV.WorkWithContent.WYSIWYGWidget">
<citetitle>
<emphasis role="bold">WYSIWYG widget</emphasis>
</citetitle>
</para>
{docbook}

Widgets are natively part of the eXo Platform product to provide a simple and easy way for users to get information and notification on their application. They complete the portlet application that focuses on more transactional behaviors. 

WYSIWYG stands for What You See Is What You Get. This widget is one of the most powerful tools. It renders an advanced JavaScript text editor with many functionalities, including the ability to dynamically upload images or flash assets into a JCR workspace and then to refer to them from the created HTML text.

{code:groovy}
String[] fieldSummary = ["jcrPath=/node/exo:summary", "options=basic"] ;
uicomponent.addWYSIWYGField("summary", fieldSummary) ;
{code}


{code:groovy}
String[] fieldContent = ["jcrPath=/node/exo:text", "options=toolbar:CompleteWCM,'height:410px'", ""] ;
uicomponent.addRichtextField("content", fieldContent)
{code}

The "options" argument is used to tell the component which toolbar should be used.

By default, there are five options for the toolbar: CompleteWCM, Default, BasicWCM, Basic, SuperBasicWCM.

* CompleteWCM: a full set of tools is shown.

The following buttons are shown: Source, Templates, Show Blocks, Cut, Copy, Paste Text, Undo, Redo, SpellCheck, WCM Insert Gadget, Flash, Table, 
Insert Special Character, WCM Insert Content Link, Bold, Italic, Underline, Strike Through, Justify Left, Justify Center, Justify Right, Justify Full,
Ordered List, Unordered List, Text Color, Background Color, Remove Format, Link, WCM Insert Portal Link, Unlink, Anchor, Style, Font Format, Font Name, Font Size, Maximize.

!images/CompleteWCMToolbar.png|align="center" width="100mm" fo:scalefit="1" html:scalefit="0"!

* Default: a large set of tools is shown, no "options" argument is needed in that case.

The following buttons are shown: Source, Templates, Cut, Copy, PasteText, Undo, Redo, SpellCheck, RemoveFormat, Bold, Italic, Underline, Strike Through, Ordered List, Unordered List, Link, Unlink, Anchor, Image, Flash, Table, Special Character, Text Color, Background Color, Show Blocks, Style, Font Format, Font Name, Font Size, Maximize.

!images/DefaultToolbar.png|align="center" width="100mm" fo:scalefit="1" html:scalefit="0"!

* BasicWCM: a minimal set of tools is shown. 

The following buttons are shown: Source, Bold, Italic, Underline, Strike Through, OrderedList, UnorderedList, Outdent, Indent, Justify Left, Justify Center, Justify Right, JustifyFull, Blockquote, Link, Unlink, WCM Insert Portal Link, WCM Insert Content Link, Show Blocks, Style, Font Format, Font Name, FontSize, Maximize.

!images/BasicWCMToolbar.png|align="center" width="100mm" fo:scalefit="1" html:scalefit="0"!

* Basic: 

The following buttons are shown: Source, Bold, Italic, Underline, Strike Through, Ordered List, Unordered List, Outdent, Indent, Justify Left, Justify Center, Justify Right, Justify Full, Blockquote, Link, Unlink, Show Blocks, Style, Font Format, Font Name, Font Size, Maximize.

!images/BasicTools.png|align="center" width="100mm" fo:scalefit="1" html:scalefit="0"!

* SuperBasicWCM: 

The following buttons are shown: Source, Bold, Italic, Underline, Justify Left, Justify Center, Justify Right, Justify Full, Link, Unlink, WCM Insert Portal Link, WCM Insert Gadget, WCM Insert Content Link.

!images/SuperBasicWCMToolbar.png|align="center" width="100mm" fo:scalefit="1" html:scalefit="0"!

There is also a simple text area widget, which has text-input area only: 

{code:groovy}
String [] descriptionArgs = ["jcrPath=/node/exo:title", "validate=empty"];
uicomponent.addTextAreaField("description", descriptionArgs) ;
{code}

{docbook}
<para xml:id="DEV.WorkWithContent.Create_a_custom_Richtext_editor_fields">
<citetitle>
<emphasis role="bold">Create a custom RichText editor fields</emphasis>
</citetitle>
</para>
{docbook}

In the [WYSIWYG widget|#DEV.WorkWithContent.WYSIWYGWidget] section, you already know about a set of default toolbars (CompleteWCM, Default, BasicWCM, Basic, SuperBasicWCM). In this section, you will learn how to create a *RichText* editor with custom buttons.

Just edit the configuration file and modify or add new items to the configuration file of the *RichText* editor is located in: _apps/resource-static/src/main/Webapp/eXoConfig.js_

Take a look at the eXoConfig.js file to see a definition of a custom toolbar named "MyCustomToolbar":

{code:java}
FCKConfig.ToolbarSets["MyCustomToolbar"] = [
  ['Source','Templates','-','FitWindow','ShowBlocks'],
 ['Cut','Copy','PasteText','-','SpellCheck','-','Undo','Redo'],
 ['WCMInsertGadget','Flash','Table','SpecialChar', 'WCMInsertContent'],
 '/',
 ['Bold','Italic','Underline','StrikeThrough','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyFull','-','OrderedList','UnorderedList','-','TextColor','BGColor','-','RemoveFormat'],
 ['Link','WCMInsertPortalLink','Unlink','Anchor'],
 '/',
 ['Style','FontFormat','FontName','FontSize']
] ;
{code}

Every toolbar set is composed of a series of "toolbar bands" that are grouped in the final toolbar layout. The bands items move together on new rows when resizing the editor.

Every toolbar band is defined as a separated JavaScript array of strings. Each string corresponds to an available toolbar item defined in the editor code or in a plugin.

* Put the desired button names in square bracket ("\[" & "\]") and separate them by commas to create a toolbar band. You can look at the above code to know all the possible toolbar item. If the toolbar item does not exist, a message will be displayed when loading the editor.

* Include a separator in the toolbar band by putting the "-" string on it.

* Separate each toolbar brands with commas.

* Use slash ("/") to tell the editor that you want to force the next bands to be rendered in a new row and not following the previous one.

{note}
The last toolbar band must have no comma after it.
{note}

{docbook}
<para xml:id="DEV.WorkWithContent.SimpleSelectBoxWidget">
<citetitle>
<emphasis role="bold">Simple select box widget</emphasis>
</citetitle>
</para>
{docbook}

The select box widget enables you to render a select box with static values. These values are enumerated in a comma-separated list in the "options" argument. The argument with no key (here "text/html") is selected by default.

{code:groovy}
String[] mimetype = ["jcrPath=/node/jcrcontent/jcr:mimeType", "text/html", "options=text/html,text/plain"] ;
uicomponent.addSelectBoxField("mimetype", mimetype) ;
{code}

As usual, the value will be stored at the relative path defined by the jcrPath directive argument.

For more examples on how to create WCM templates, refer to the [WCM Templates|../../../reference/html/CONTref.InsideWCMTemplates.html] section.

{docbook}
<para xml:id="DEV.WorkWithContent.AdvancedDynamicSelectBox">
<citetitle>
<emphasis role="bold">Advanced dynamic select box</emphasis>
</citetitle>
</para>
{docbook}

In many cases, the previous solution with static options is not good enough and one would like to have the select box checked dynamically. 
That is what eXo Platform provide thanks to the introduction of a Groovy script as shown in the code fragment below.

{code:groovy}
String[] args = ["jcrPath=/node/exodestWorkspace", "script=ecm-explorer/widget/FillSelectBoxWithWorkspaces:groovy", "scriptParams=production"];
uicomponent.addSelectBoxField("destWorkspace", args) ;
{code}

The script itself implements the CMS Script interface and the cast is done to get the select box object as shown in the script code which fills the select box with the existing JCR workspaces.

{code:java}
import java.util.List ;
import java.util.ArrayList ;

import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;

import org.exoplatform.webui.form.UIFormSelectBox;
import org.exoplatform.webui.core.model.SelectItemOption;
import org.exoplatform.services.cms.scripts.CmsScript;

public class FillSelectBoxWithWorkspaces implements CmsScript {

  private RepositoryService repositoryService_;

  public FillSelectBoxWithWorkspaces(RepositoryService repositoryService) {
    repositoryService_ = repositoryService;
  }

  public void execute(Object context) {
    UIFormSelectBox selectBox = (UIFormSelectBox) context;

    ManageableRepository jcrRepository = repositoryService_.getRepository();
    List options = new ArrayList();
    String[] workspaceNames = jcrRepository.getWorkspaceNames();
    for(name in workspaceNames) {
      options.add(new SelectItem(name, name));
    }
    selectBox.setOptions(options);
  }

  public void setParams(String[] params) {
  }
}
{code}

{note}
It is also possible to provide a parameter to the script by using the argument "scriptParams".
{note}

{docbook}
<para xml:id="DEV.WorkWithContent.WidgetWithSelector">
<citetitle>
<emphasis role="bold">Widget with selector</emphasis>
</citetitle>
</para>
{docbook}

One of the most advanced functionalities of this syntax is the ability to plug your own component that shows an interface, enabling you to select the value of the field.

In the generated form, you will see an icon which is configurable thanks to the selectorIcon argument. The syntax is a bit more complex but not much.

{code:groovy}
String[] groupArgs = ["jcrPath=/node/exogroup", "selectorClass=org:exoplatform:ecm:webui:selector:UIGroupMemberSelector"];
uicomponent.addActionField("group", groupArgs);
{code}

You can plug your own component using the selectorClass argument. It must follow the eXo UIComponent mechanism and implements the interface ComponentSelector:

{code:java}
package org.exoplatform.ecm.webui.selector;

import org.exoplatform.webui.core.UIComponent;
public interface ComponentSelector {
  public UIComponent getSourceComponent() ;
  public void setSourceComponent(UIComponent uicomponent, String[] initParams) ;    
}

{code}

{docbook}
<para xml:id="DEV.WorkWithContent.Multi-valueWidget">
<citetitle>
<emphasis role="bold">Multi-valued widget</emphasis>
</citetitle>
</para>
{docbook}

A widget can have multiple values if you add the argument "multiValues=true" to the directive.

h1. Customize CKEditor  {anchor:id=DEV.WorkWithContent.CKEditor}
{include:document=CKEditor.wiki|syntax=confluence/1.0}

h1. Taxonomy {anchor:id=DEV.WorkWithContent.Taxonomy}

Taxonomy is a particular classification arranged in a hierarchical structure. The Taxonomy trees in eXo Platform will help you organize your content into categories.

When you create a new taxonomy tree, you will add a pre-configured _exo\:action_ (_exo\:scriptAction_ or _exo\:businessProcessAction_) to the root node of the taxonomy tree. This action is triggered when a new document is added anywhere in the taxonomy tree. The default action moves the document to the physical storage location and replaces the document in the taxonomy tree with a symlink of the _exo\:taxonomyLink_ type pointing to it. The physical storage location is defined by a workspace name, a path and the current date and time.

* Like adding document types, taxonomy trees can be managed through the *Content Administration* portlet, or by adding .xml configuration files.

{docbook}
<para>
<citetitle>
<emphasis role="bold">
Configure a taxonomy tree by adding the configuration files in the <emphasis>/webapp/WEB-INF/conf/acme-portal/wcm/taxonomy/</emphasis> directory
</emphasis>
</citetitle>
</para>
{docbook}
Create a new file called _$taxonomyName-taxonomies-configuration.xml_. For example, if the name of your taxonomy tree is "acme", the file should be named _acme-taxonomies-configuration.xml_.

* You can view the file in _$PLF-HOME\_/samples/acme-website/webapp/src/main/webapp/WEB-INF/conf/acme-portal/wcm/taxonomy/acme-taxonomies-configuration.xml_.
** The value-params enable you to define the repository, workspace, name of the tree and its JCR path. 
** You can then configure permissions for each group of users in the portal, and the triggered action when a new document is added to the taxonomy tree. 
** Finally, you can describe the structure and names of the categories inside your taxonomy tree.

{docbook}
<para>
<prompt>
    <emphasis role="bold">See also</emphasis>
</prompt>
</para>
{docbook}
* [Node type|#DEV.WorkWithContent.NodeType]
* [Dialog Syntax|#DEV.WorkWithContent.DialogSyntax]
* [Customize CKEditor|#DEV.WorkWithContent.CKEditor]
* [Template Service|#DEV.WorkWithContent.ManageTemplateService]
* [Navigation By Content|#DEV.WorkWithContent.NavigationByContent]

h1. Template Service {anchor:id=DEV.WorkWithContent.ManageTemplateService}

*Template Service* enables you to create dialogs and view templates for each registered node type. Each node type may have many dialogs and view templates. The template will be used when creating or viewing nodes.

You can find the template service configuration in _/webapps/ecm-wcm-core/WEB-INF/conf/wcm-core/core-services-configuration.xml_.

{code:xml}
<component>
  <key>org.exoplatform.services.cms.templates.TemplateService</key>
  <type>org.exoplatform.services.cms.templates.impl.TemplateServiceImpl</type>
</component>
{code}

As usual, one can register a plugin inside the service. This plugin initializes default dialogs and views template of any node type as nt:file, exo:article, exo:workflowAction, exo:sendMailAction, and more.

{code:xml}
<component-plugins>
  <component-plugin>
    <name>addTemplates</name>
    <set-method>addTemplates</set-method>
    <type>org.exoplatform.services.cms.templates.impl.TemplatePlugin</type>
    .........
  </component-plugin>
</component-plugins>
{code}

With init-parameters as:

{code:xml}
<init-params>
  <value-param>
    <name>autoCreateInNewRepository</name>
    <value>true</value>
  </value-param>
  <value-param>
    <name>storedLocation</name>
    <value>war:/conf/ecm/artifacts/templates</value>
  </value-param>
  <value-param>
    <name>repository</name>
    <value>repository</value>
  </value-param>
  <object-param>
    <name>template.configuration</name>
    <description>configuration for the location of templates to inject in jcr</description>
    <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig">
      <field name="nodeTypes">
        <collection type="java.util.ArrayList">
          <value>
            <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$NodeType">
              <field name="nodetypeName">
                <string>exo:article</string>
              </field>
              <field name="documentTemplate">
                <boolean>true</boolean>
              </field>
              <field name="label">
                <string>Article</string>
              </field>
              <field name="referencedView">
                <collection type="java.util.ArrayList">
                  <value>
                    <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
                      <field name="templateFile">
                        <string>/article/views/view1.gtmpl</string>
                      </field>
                      <field name="roles">
                        <string>*</string>
                      </field>
                    </object>
                  </value>
                </collection>
              </field>
              <field name="referencedDialog">
                <collection type="java.util.ArrayList">
                  <value>
                    <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
                      <field name="templateFile">
                        <string>/article/dialogs/dialog1.gtmpl</string>
                      </field>
                      <field name="roles">
                        <string>*</string>
                      </field>
                    </object>
                  </value>
                </collection>
              </field>
            </object>
          </value>
        </collection>
      </field>
    </object>
  </object-param>
</init-params>    
{code}

{docbook}
<para>
<prompt>
    <emphasis role="bold">See also</emphasis>
</prompt>
</para>
{docbook}
* [Node type|#DEV.WorkWithContent.NodeType]
* [Dialog Syntax|#DEV.WorkWithContent.DialogSyntax]
* [Customize CKEditor|#DEV.WorkWithContent.CKEditor]
* [Taxonomy|#DEV.WorkWithContent.Taxonomy]
* [Navigation By Content|#DEV.WorkWithContent.NavigationByContent]

h1. Navigation By Content {anchor:id=DEV.WorkWithContent.NavigationByContent}

{docbook}
<highlights>
        <itemizedlist>
          <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.NavigationByContent.ContentNavigation">Actual content navigation</link>
            </para>
			<para>Steps to add "actual content navigation" to a page, including the way to configure the right and left portlets.</para>
          </listitem>
          <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.NavigationByContent.Add_content_to_the_navigation">Add content to the navigation</link>
            </para>
			<para>The detailed procedure to attach your root folder/node to some page nodes.</para>
          </listitem>
          <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.NavigationByContent.ActionsNavigationByContent">Actions on Navigation By Content</link>
            </para>
			<para>Instructions on how to restrict the visibility of some content, to sort elements of the contextual menu, to restore a node to the contextual menu and attach it to another page, and to add your newly created content to the contextual menu.</para>
          </listitem>
		  <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.NavigationByContent.CreateDataForNavigationByContentExamples">Create data for Navigation By Content</link>
            </para>
			<para>TWO typical examples of creating data for <emphasis role="bold">Navigation By Content</emphasis>, including how to create a Product page, and to develop your own Product content.</para>
          </listitem>
		  <listitem>
			<para>
			  <link linkend="DEV.WorkWithContent.CreateNewContentListTemplate">Create a new Content List template</link>
			</para>
			<para>
			Knowledge and typical steps to create a new template that is used in the <emphasis role="bold">Content List</emphasis> portlet.
			</para>
		  </listitem>
        </itemizedlist>
<para><emphasis role="bold">Navigation By Content</emphasis> is a feature which allows users to browse content of each page easily. With this feature, users experiencing eXo Platform 3.5 can navigate from a page to another or browse site content inside one page directly from a contextual menu.</para>
</highlights>
{docbook}

{docbook}
<para>
<prompt>
    <emphasis role="bold">See also</emphasis>
</prompt>
</para>
{docbook}
* [Node type|#DEV.WorkWithContent.NodeType]
* [Dialog Syntax|#DEV.WorkWithContent.DialogSyntax]
* [Customize CKEditor|#DEV.WorkWithContent.CKEditor]
* [Taxonomy|#DEV.WorkWithContent.Taxonomy]
* [Template Service|#DEV.WorkWithContent.ManageTemplateService]

{include:document=navigation_by_content_feature.wiki|syntax=confluence/1.0}
h2. Create a new Content List template  {anchor:id=DEV.WorkWithContent.CreateNewContentListTemplateRoleNotInToc}

eXo Platform provides many powerful features to manipulate and expose any types of content on a page. This is due to the fact that eXo Platform stores all the content in its Java Content Repository (JCR) and renders the content on a page using Groovy Templates.

In this section, you will learn how to create a new template that is used in the *Content List* portlet. For example, in the sample ACME site, you can show the content in One-column or Two-column display just by selecting different templates:

!images/ExampleTypesOfColumns.png|width="120mm" align="center" fo:scalefit="1" html:scalefit="0"!

Before writing a new template, it is important to learn where templates are stored.

{docbook}
<para>
<citetitle>
<emphasis role="bold">eXo Content Service: Template Storage</emphasis>
</citetitle>
</para>
{docbook}

Like many things inside eXo Platform, eXo JCR is used to store templates. Templates are just a special type of content. This allows developers to easily write and test code without following a complex deployment process, but also it makes it easy to export a running configuration to another one.
To do this, you just need to use the standard JCR export/import features.

All templates and eXo Content Service configurations are stored inside a specific JCR workspace named "dms-system".

Each template type (for example, Document Type, or Content List) is stored in a specific location. In this case, you are going to work on the *Content List* portlet so templates are stored inside the {{/exo:ecm/views/templates/content-list-viewer/list/}} folder.

The following steps allow you to inspect this folder using the eXo CRaSH utility. If you are not interested in it, you can jump to the [next section|#DEV.WorkWithContent.CreateNewContentListTemplateUsingIDE]. CRaSH is a shell for Java Content Repositories, the source of CRaSH is available on Google Code. So in the terminal window:

{docbook}
<para><emphasis role="bold">1.</emphasis> Connect to CRaSH using the telnet client: <command>telnet 127.0.0.1 5000</command>.</para>
{docbook}

{docbook}
<para><emphasis role="bold">2.</emphasis> Connect to the JCR workspace using the following command: <command>connect -u root -p gtn -c portal dms-system</command>.</para>
{docbook}

Where: {{-u}} is the user, {{-p}} is the password, {{-c}} is the Portal Container, and {{dms-system}} is the workspace to use.

{docbook}
<para><emphasis role="bold">3.</emphasis> Move the folder that contains all templates for the <emphasis role="bold">Content List</emphasis> portlet: <command>cd /exo:ecm/views/templates/content-list-viewer/list/</command>.</para>
{docbook}

{docbook}
<para>
<emphasis role="bold">4.</emphasis> List all templates using the <command>ls</command> command.
</para>
{docbook}

You can see the list of all templates available for the *Content List* portlet.

{docbook}
<para xml:id="DEV.WorkWithContent.CreateNewContentListTemplateUsingIDE">
<citetitle>
<emphasis role="bold">Create a new Content List template using IDE</emphasis>
</citetitle>
</para>
{docbook}

Before doing the following steps, be sure that you are connected to a user who belongs to the _/Developer_ group. The _root_ user can be used for the simplicity reason.

*1.* Access IDE by clicking !images/gear_icon.png|width=3mm fo:scalefit="1" html:scalefit="0"! *--> IDE*.

*2.* Switch to the _dms\-system_ workspace by clicking *My Spaces --> on Window --> Select Workspace* from the IDE menu. Next, select the _dms\-system_ location in the dialog box and click *OK*.

*3.* Navigate to the template location from the file structure on the left: {{/exo:ecm/views/templates/content-list-viewer/list/}}

*4.* Create a new template by clicking *File --> New --> Groovy Template* from the IDE menu.

*5.* Save the file as "MyNewTemplate.gtmpl".

*6.* Enter some basic codes:

{code}
<h1>This is my template</h1>
The date is <= new Date()>
{code}

*7.* Save the template, then go back to the homepage of the ACME site.

*8.* Switch to the *Edit* mode by clicking *Edit* on the *Administration* bar.

*9.* Hover your cursor over the top of the list of news and click !images/PreferencesIcon.png|width="3mm" fo:scalefit="1" html:scalefit="0"!.

*10.* Select "MyNewTemplate" from the list of templates, then click *Save*.

!images/SelectTemplate.png|align="center" width="120mm" fo:scalefit="1" html:scalefit="0"!

You have created your new template, and use it on a page. Now, you should add some more interesting codes to the template to really loop over the content based on the portlet configuration. But before this, you need to understand caching and code modification.

{docbook}
<para>
<citetitle>
<emphasis role="bold">eXo Template and Cache</emphasis>
</citetitle>
</para>
{docbook}

To improve performance and a running system, the compiled version of the template is cached by default. This is the reason why you do not see any change when you are modifying a template. There are 2 ways to work around this:

* Run eXo Platform in the Debug mode. In this case, nothing is cached.
* Invalidate the cache manually using JMX.

Since working with no cache at all is not an option, here is the MBean you have to use for invalidating the Template Service cache:

* {{exo:portal="portal",service=cache,name="TemplateService"}}

Then, call the {{clearCache}} operation on it.

You can use any methods to call your MBeans operation. Here, JConsole will be used:

!images/TemplateServiceCacheMbean.png|align="center" width="50mm" fo:scalefit="1" html:scalefit="0"!

Do not forget to call this operation each time you modify your template to ensure that eXo recompiles the template.

{docbook}
<para>
<citetitle>
<emphasis role="bold">Access content in the template</emphasis>
</citetitle>
</para>
{docbook}

The current code of the template is really simple. Now, you need to add code to print the content in the page. To do this, you are going to use some *Content* programmings once again in IDE.

The template used by the *Content List* portlet is based on the following Java class: {{org.exoplatform.wcm.webui.clv.UICLVPresentation}}. This class is responsible for setting the complete context that you can use in the template, such as:

* The folder or category that contains the content to show. The *Folder Path* field is in the preference screen.
* The display settings: title, number of documents, elements to show and more.

Here is the code to access these preferences:

{code:java}
// import all the classes need in the template
import javax.jcr.Node;
import org.exoplatform.wcm.webui.paginator.UICustomizeablePaginator;
import org.exoplatform.wcm.webui.clv.UICLVPortlet;
import org.exoplatform.wcm.webui.Utils;
import org.exoplatform.services.wcm.core.NodeLocation;

// get the portlet preferences

def header = uicomponent.getHeader();
def isShowRssLink = uicomponent.isShowRssLink();
def isShowHeader = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_HEADER);
def isShowRefresh = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_REFRESH_BUTTON);

def isShowTitle = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_TITLE);
def isShowDate = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_DATE_CREATED);
def isShowLink = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_LINK);
def isShowReadmore = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_READMORE);
def isShowImage = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_ILLUSTRATION) ;
def isShowSummary = uicomponent.isShowField(UICLVPortlet.PREFERENCE_SHOW_SUMMARY);
{code}

The {{uicomponent}} object is defined by the container class of the portlet that calls the template. This class contains many utility methods.
The code above retrieves all the preferences of the portlet. Because the name is self-explanatory, it is not necessary to detail them, especially when you look at the preferences screen below:

!images/ContentListPreference.png|align="center" width="120mm" fo:scalefit="1" html:scalefit="0"!

Now, the template has all the preferences, it is time to loop on the content on printing the information.

The *Content Service* provides API to manipulate the content, including pagination of content. The idea behind this is to let the Content Service manage the JCR query, sorting, caching and pagination of data.
So in your template, you will mainly manage 2 classes to loop through the content to show:

* {{uicomponent.getUIPageIterator()}} - a paginator object that is configured based on the portlet preferences.
* {{uicomponent.getCurrentPageData()}} - a list of the content (JCR Nodes) that should be printed on the current page.

So, you can print all the content of the page as a simple HTML list:

{code:html}
<ul style="margin: 20px">
<%
      for (viewNode in uicomponent.getCurrentPageData()) {
        def title = viewNode.getProperty("exo:title").getString()
        print("<li>$title</li>");
      }
%>
</ul>
{code}

Just copy this code to your template, save it, then refresh the cache and go to your page. You should see the list of the content in a simple HTML list.

On each content (Node), the *Content API* provides some helper methods to easily manipulate the content and avoid using the JCR API directly. In the following code, you can see the most important methods accessing the content properties:

{code:java}
def itemName = viewNode.getName();
def itemLink = uicomponent.getURL(viewNode);
def webdDavLink = uicomponent.getWebdavURL(viewNode);
def itemDateCreated = uicomponent.getCreatedDate(viewNode);
def itemModifiedDate = uicomponent.getModifiedDate(viewNode);
def itemAuthor = uicomponent.getAuthor(viewNode);
def imgSrc = uicomponent.getIllustrativeImage(viewNode);
def itemTitle = uicomponent.getTitle(viewNode);
def itemSummary = uicomponent.getSummary(viewNode);
{code}

One important point is the fact that these methods are responsible for many things, for example: formatting dates, returning complete URLs that depends on the context of the portlet.

Based on these methods, you can now work on the presentation of the information on the page. For example, you can  click the image and the title to go in the detailed view of the article. This is done simply by using the following code:

{code:java}
<%
  for (viewNode in uicomponent.getCurrentPageData()) {
    def itemName = viewNode.getName();
    def itemLink = uicomponent.getURL(viewNode);
    def webdDavLink = uicomponent.getWebdavURL(viewNode);
    def itemDateCreated = uicomponent.getCreatedDate(viewNode);
    def itemModifiedDate = uicomponent.getModifiedDate(viewNode);
    def itemAuthor = uicomponent.getAuthor(viewNode);
    def imgSrc = uicomponent.getIllustrativeImage(viewNode);
    def itemTitle = uicomponent.getTitle(viewNode);
    def itemSummary = uicomponent.getSummary(viewNode);

    %>
<div style="overflow: auto;">
  <img src="$imgSrc" align="left">
  <h3><a href="$itemLink">$itemTitle</a></h3>
  $itemSummary
</div>

<%
  }
%>
{code}

For the simplicity reason, this code does not manage any null value. Also, the template does not deal with the portlet preferences, such as the "Header", "RSS" links. The Website should look like:

!images/NewSite.png|align="center" width="120mm" fo:scalefit="1" html:scalefit="0"!

The last important point is to add the support for the in-context editing that allows users to edit the content directly from the template. Once again, this is done with a method of the {{uicomponent}} object that creates a DIV around the content:

{code:java}
<%
  for (viewNode in uicomponent.getCurrentPageData()) {
    def itemName = viewNode.getName();
    def itemLink = uicomponent.getURL(viewNode);
    def webdDavLink = uicomponent.getWebdavURL(viewNode);
    def itemDateCreated = uicomponent.getCreatedDate(viewNode);
    def itemModifiedDate = uicomponent.getModifiedDate(viewNode);
    def itemAuthor = uicomponent.getAuthor(viewNode);
    def imgSrc = uicomponent.getIllustrativeImage(viewNode);
    def itemTitle = uicomponent.getTitle(viewNode);
    def itemSummary = uicomponent.getSummary(viewNode);

    %>
<div style="overflow: auto;">
  <%=uicomponent.addQuickEditDiv("MyTemplateContentEditor", viewNode)%>
  <img src="$imgSrc" align="left">
  <h3><a href="$itemLink">$itemTitle</a></h3>
  $itemSummary
  < /div>
</div>

<%
  }
%>
{code}

The 15 and 19 lines are new in this template and provide support for the *Quick Edit* feature.

After creating your own template for *Content Service* using the embedded IDE, you are free to use your imagination for adding cool features to your site.