h1. Actual content navigation {anchor:id=DEV.WorkWithContent.NavigationByContent.ContentNavigationRoleNotInToc}

One of the powerful features of Enterprise Content Management System (ECMS) that comes out with eXo Platform 3.5 is the ability to navigate in site content using taxonomies.
This functionality can easily be added in a page with the help of two *Content List Viewer* (CLV) portlets. The pre-configured example can be found in the *News* page of the sample ACME website.
In this example, all content in the _/Sites Management/acme/events/All_ node will be used.

{docbook}
<citetitle>
<para>
<emphasis role="bold">Add "Actual content navigation" to a page</emphasis>
</para>
</citetitle>
{docbook}

*1.* Log into the sample ACME website.

*2.* Add a new page, for example "Events".

*3.* Parameterize this page with the *Autofit Two Columns* container.

*4.* Add two *Content List* portlets to each column.

*5.* Add content.

*i. Configure the left portlet as follows*:

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

In which:

* *Folder path* = _/Sites Management/acme/events/All_: The path to the folder that contains the content.
* *Header* = _Browse by_: The title of all content that is listed in the content list viewer.
* *Template* = _CategoryTree.gtmpl_: The template used for displaying the content list.
* *Contextual Folder* = _Disabled_: The Contextual Content property is set to "Disable", the Advanced pane is closed by default and a single content will be opened by an URL containing the content path. 
* *Show in page* =_Events_: A single content in CLV will be shown in the *Events* page.
* *With* = _folder-id_: The parameter containing the content path. 

*ii. Configure the right portlet as follows*:

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

In which:

* *Folder path* = _/Sites Management/acme/events/All_: The path to the folder that contains the content.
* *Template* = _OneColumnCLVTemplate.gtmpl_: The template used for displaying the content list.
* *Contextual Folder* = _Enabled_: The Contextual Content property is set to "Enable". This portlet is configured with the provided parameter (content-id by default).
* *Show in page* = _Details_: A single content in CLV will be shown in the "Details" page.
* *With* = _content-id_: The parameter containing the content path.

As a result, the created *Events* page will look like:

!images/navigation_by_content_feature/eventsPage.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

You can now navigate from the left portlet to see content displayed in the right portlet.

The new *Navigation By Content* feature will traduce this example in a contextual menu.


h1. Add content to the navigation {anchor:id=DEV.WorkWithContent.NavigationByContent.Add_content_to_the_navigationRoleNotInToc}

{docbook}
<citetitle>
<para>
<emphasis role="bold">Attach your root folder/node to some page nodes from the homepage (the drop-down menu holds your new contextual menu)
</emphasis>
</para>
</citetitle>
{docbook}

*1.* Go to the *Sites Explorer* page and navigate to _/Sites Management/acme/events/All_.

*2.* Click the *Content Navigation* button, the *Navigation* form will appear. If you do not see this button on the *Action* bar, add this button via the *Content Administration* page.

*3.* Fill values into the *Content Navigation* form:

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

In which:

* *Visible* = true. This node will be navigable.

* *Target parent navigation* = Events. The contextual menu will be attached to the *Events* drop-down menu.

* *Clickable* = false. This node will not be clickable.

* *Page for list* = catalog. This page is a system page that contains a *Content List Viewer* portlet and will be used to display the list of child nodes.

* *Page for detail* = detail. This page is a system page that contains a *Single Content Viewer* portlet and will be used to display details of child nodes.

*4.* Save changes, then go back to the ACME homepage. You will see changes from the *Events* drop-down menu.

!images/navigation_by_content_feature/contextualMenu.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

In which:

* *Visible*: The _/Sites Management/acme/events/All_ node is navigable and its child nodes are rendered in the contextual menu.

* *Target parent navigation*: The _/Sites Management/acme/events/All_ node is attached to the site menu item called *Events*.

* *Clickable*: The _/Sites Management/acme/events/All_ node is not clickable but all of its child nodes are clickable.

* *Page for list*: The list of child nodes (if a child node is *directory/folder*) will be rendered in the following page.

Click the *Earth* menu item from the contextual menu, you will see that content of the *Earth* directory are rendered in a separate page (catalog):

!images/navigation_by_content_feature/listEarth.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

* *Page for detail*: The details of child nodes (if a child node is a sample content) will be rendered in this page.

Select the *Power 1 - Fire* menu item from the contextual menu to see the *Fire* content displayed in a separate page (details):

!images/navigation_by_content_feature/Power1_fire_item.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

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

{docbook}
<citetitle>
<para>
<emphasis role="bold">Restrict the visibility of some content</emphasis>
</para>
</citetitle>
{docbook}

*1.* Go to the *Sites Explorer* page and navigate to the _/Sites Management/acme/events/All/Fire_ node.

*2.* Click the *Content Navigation* button to open the *Navigation* form.

*3.* Uncheck the *Visible* field and save.

*4.* Go back to the ACME homepage. You will see that the *Fire* sub-menu is not displayed in the contextual menu anymore.

!images/navigation_by_content_feature/Restrict_content_visibility.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

{docbook}
<citetitle>
<para>
<emphasis role="bold">Sort elements of the contextual menu</emphasis>
</para>
</citetitle>
{docbook}

*1.* Go to the *Sites Explorer* page and navigate to the _/Sites Management/acme/events/All_ node.

*2.* Select the _/Sites Management/acme/events/All/Earth_ node.

*3.* Click the *Content Navigation* button to open the *Navigation* form.

*4.* Set the *Display order* field to "1" and save.

*5.* Select the _/Sites Management/acme/events/All/Water_ node.

*6.* Click the *Content Navigation* button.

*7.* Set the *Display order* field to "2" and save.

*8.* Select the _/Sites Management/acme/events/All/Air_ node.

*9.* Click the *Content Navigation* button.

*10.* Set the *Display order* field to "3" and save.

*11.* Go back to the ACME homepage. You will see that the display order from the contextual menu is *Earth*, *Water*, *Air*. Note that the *Fire* sub-menu is not displayed because it is set to "Invisible" in the previous example.

{docbook}
<citetitle>
<para>
<emphasis role="bold">Restore a node to the contextual menu and attach it to another page</emphasis>
</para>
</citetitle>
{docbook}

*1.* Go to the *Sites Explorer* page and navigate to the _/Sites Management/acme/events/All/Fire_ node.

*2.* Click the *Content Navigation* button to open the *Navigation* form.

*3.* Fill values into the *Navigation* form fields, including:

* *Visible* = true
* *Target parent navigation* = News
* *Clickable* = false
* *Page for list* = catalog
* *Page for detail* = detail

*4.* Save changes and go back to the *Acme/Overview* homepage. You will see that the *Fire* node is attached to the *News* drop-down menu from the site menu:

!images/navigation_by_content_feature/Attach_node_ to_another_page.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

However, if you want to add your newly created content directly to the contextual menu, you need to add the *populateToMenu* action first.


{docbook}
<citetitle>
<para>
<emphasis role="bold">Add your newly created content to the contextual menu</emphasis>
</para>
</citetitle>
{docbook}


*1.* Go to the *Sites Explorer* page and navigate to the _/Sites Management/acme/events/All/Fire_ node.

*2.* Click the *Actions* button and add the *exo\:populateToMenu* action.

!images/navigation_by_content_feature/populateToMenuAction.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

*3.* Create a document under the _/Sites Management/acme/events/All/Fire_ node and publish it.

*4.* Go back to the homepage. You will see that your newly created document is added to the contextual menu.

!images/navigation_by_content_feature/docPDF.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

The sample ACME website comes with a configured navigation by content menu:

!images/navigation_by_content_feature/productsMenu.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

You can click the *Vision* sub-menu and see content of *Vision* directory rendered in the *catalog* page:

!images/navigation_by_content_feature/visionSubMenuList.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

Select the *X-Ray* content and see the newly implemented content using new visual effects and presentation.

* "Benefits" and "Features" tabs:

!images/navigation_by_content_feature/Benefits_tab.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

* Coverflow section:

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

* Related documents:

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

h1. Create data for Navigation By Content {anchor:id=DEV.WorkWithContent.NavigationByContent.CreateDataForNavigationByContentExamplesRoleNotInToc}

{docbook}
<para>
<itemizedlist>
          <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.NavigationByContent.CreateDataForNavigationByContentExamples.CreateNewProductPage">Create a Product page</link>
            </para>
			<para>Steps to create content and to add media files to enrich the Product page.</para>
          </listitem>
		   <listitem>
            <para>
              <link linkend="DEV.WorkWithContent.NavigationByContent.CreateDataForNavigationByContentExamples.DevelopProductContent">Develop your own Product content</link>
            </para>
			<para>Steps to create fields in the Product content type, and to develop the Product's view form.</para>
          </listitem>
</itemizedlist>
</para>
{docbook}

{note}
By following 2 typical examples above, you can create data for Navigation By Content easily.
{note}

h2. Create a Product page {anchor:id=DEV.WorkWithContent.NavigationByContent.CreateDataForNavigationByContentExamples.CreateNewProductPageRoleNotInToc}

{docbook}
<citetitle>
<para>
<emphasis role="bold">Create content about the product</emphasis>
</para>
</citetitle>
{docbook}

*1.* Go to the *Sites Explorer* page and navigate to _somePath/someDirectory_.

*2.* Click the *New Content* button on the *Action* bar. There will be a several content type appears.

*3.* Select the *Product* content type. 

*4.* Fill the *Product* dialog form.

*5.* Save changes.


{docbook}
<citetitle>
<para>
<emphasis role="bold">Add media files to enrich the Product page</emphasis>
</para>
</citetitle>
{docbook}


*1.* Go to _somePath/someDirectory/sampleProduct/medias/images_.

*2.* Click *Upload* on the *Action* bar to upload some images from your local device and publish them.

!images/navigation_by_content_feature/sampleProductImages.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

*3.* Go to _somePath/someDirectory/sampleProduct/medias/videos_.

*4.* Click *Upload* on the *Action* bar to upload some videos from your local device and publish it.

!images/navigation_by_content_feature/sampleProductVideos.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0" !

*5.* Go to _somePath/someDirectory/sampleProduct/documents_.

*6.* Create two directories, including *Sale Materials* and *Technical Documentations*.

*7.* Upload a PDF document and publish it under each sub-folder.

!images/navigation_by_content_feature/sampleProductDocuments.png|align="center" width="150mm" fo:scalefit="1" html:scalefit="0"!

*8.* Add your *sampleProduct* to some categories or add it to the *Content List* portlet.

Your newly created product is now ready to be displayed in some pages.

*9.* Publish your newly created product. Note that you can select this content from a CLV:

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

As a result, the content will be displayed in a detailed page as follows:

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

h2. Develop your own Product content {anchor:id=DEV.WorkWithContent.NavigationByContent.CreateDataForNavigationByContentExamples.DevelopProductContentRoleNotInToc}

The sample *Product* page is composed of the following fields and folders:

* *Product* content type fields: Name, Title, Illustration Image, Summary, Benefits, and Features.

(The *Product* content type is the template specified for the *Product* page.)

*  Other content folders: documents, medias/images, medias/videos.

(These folders contain documents and media files to enrich the *Product* page.)


{docbook}
<citetitle>
<para>
<emphasis role="bold">Create fields in the Product content type</emphasis>
</para>
</citetitle>
{docbook}


* *Name*
Other content folders are created within the product content when the *Name* field is created. This can be achieved (from the .gtmpl product dialog) as follows:

{code:html}<tr>
	<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.name")%></td>
	<td class="FieldComponent">
	<%
	String[] productFieldName = ["jcrPath=/node", "mixintype=mix:votable,mix:commentable","editable=if-null","validate=name,empty"] ;
	uicomponent.addTextField("name", productFieldName) ;
	String[] documentsFolder = ["jcrPath=/node/documents", "nodetype=nt:folder","mixintype=exo:documentFolder", "defaultValues=documents"] ;
	String[] mediasFolder = ["jcrPath=/node/medias", "nodetype=exo:multimediaFolder", "defaultValues=medias"] ;
	String[] imagesFolder = ["jcrPath=/node/medias/images", "nodetype=nt:folder", "defaultValues=images"] ;
	String[] videoFolder = ["jcrPath=/node/medias/videos", "nodetype=nt:folder", "defaultValues=videos"] ;
	uicomponent.addHiddenField("documentsFolder", documentsFolder);
	uicomponent.addHiddenField("mediasFolder", mediasFolder);
	uicomponent.addHiddenField("imagesFolder", imagesFolder);
	uicomponent.addHiddenField("videoFolder", videoFolder);
	%>
	</td>
</tr>{code}


*Other fields are created almost in the same way:*

* *Title:*

{code:html}<tr>
	<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.title")%></td>
	<td class="FieldComponent">
	<%
		String[] productFieldTitle = ["jcrPath=/node/exo:title", "validate=empty", "editable=if-null"];
		uicomponent.addTextField("title", productFieldTitle) ;
	%>
	</td>
</tr>{code}

* *Illustration image*:

{code:html}<%
private void setUploadFields(name) {
	String[] illustrationHiddenField1 = ["jcrPath=/node/medias/images/illustration", "nodetype=nt:file", "mixintype=mix:referenceable", "defaultValues=illustration"];
	String[] illustrationHiddenField2 = ["jcrPath=/node/medias/images/illustration/jcr:content", "nodetype=nt:resource", "mixintype=dc:elementSet", "visible=false"];
	String[] illustrationHiddenField3 = ["jcrPath=/node/medias/images/illustration/jcr:content/jcr:encoding", "visible=false", "UTF-8"];
	String[] illustrationHiddenField4 = ["jcrPath=/node/medias/images/illustration/jcr:content/jcr:lastModified", "visible=false"];
	String[] illustrationHiddenField5 = ["jcrPath=/node/medias/images/illustration/jcr:content/dc:date", "visible=false"];
	uicomponent.addHiddenField("illustrationHiddenField1", illustrationHiddenField1);
	uicomponent.addHiddenField("illustrationHiddenField2", illustrationHiddenField2);
	uicomponent.addHiddenField("illustrationHiddenField3", illustrationHiddenField3);
	uicomponent.addCalendarField("illustrationHiddenField4", illustrationHiddenField4);
	uicomponent.addCalendarField("illustrationHiddenField5", illustrationHiddenField5);
	String[] fieldImage = ["jcrPath=/node/medias/images/illustration/jcr:content/jcr:data"] ;
	uicomponent.addUploadField(name, fieldImage) ;
}
%>
<tr>
	<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.illustrationImage")%></td>
	<td class="FieldComponent">
		<%
			String illustration = "illustration";
			if(ProductNode != null && ProductNode.hasNode("medias/images/illustration") && (uicomponent.findComponentById(illustration) == null)) {
				def imageNode = ProductNode.getNode("medias/images/illustration") ;
				def resourceNode = imageNode.getNode("jcr:content");
				if(resourceNode.getProperty("jcr:data").getStream().available() > 0) {
					def imgSrc = uicomponent.getImage(imageNode, "jcr:content");
					def actionLink = uicomponent.event("RemoveData", "/medias/images/illustration/jcr:content");
					%>
						<div>
							<image src="$imgSrc" width="100px" height="80px"/>
							<a onclick="$actionLink">
								<img src="/eXoResources/skin/DefaultSkin/background/Blank.gif" class="ActionIcon Remove16x16Icon"/>
							</a>
						</div>
					<%
				} else {
					setUploadFields(illustration);
				}
			} else {
				setUploadFields(illustration);
			}
		%>
	</td>
</tr>{code}

* *Summary:*

{code:html}<tr>
	<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.summary")%></td>
	<td class="FieldComponent">
	<%
		String[] fieldSummary = ["jcrPath=/node/exo:summary", "options=Basic", ""] ;
		uicomponent.addRichtextField("summary", fieldSummary) ;
	%>
	</td>
</tr>{code}

* *Benefits:*

{code:html}<tr>
	<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.benefits")%></td>
	<td class="FieldComponent">
	<div class="UIFCKEditor">
	<%
		String[] productFieldBenefits = ["jcrPath=/node/exo:productBenefits", "options=toolbar:CompleteWCM", ""] ;
		uicomponent.addRichtextField("productBenefits", productFieldBenefits) ;
	%>
	</div>
	</td>
</tr>{code}

* *Features:*

{code:html}<tr>
	<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.features")%></td>
	<td class="FieldComponent">
	<div class="UIFCKEditor">
	<%
		String[] productFieldFeatures = ["jcrPath=/node/exo:productFeatures", "options=toolbar:CompleteWCM", ""] ;
		uicomponent.addRichtextField("productFeatures", productFieldFeatures) ;
	%>
	</div>
	</td>
</tr>{code}


{docbook}
<citetitle>
<para>
<emphasis role="bold">Develop the Product's view form</emphasis>
</para>
</citetitle>
{docbook}

*The illustration image, title and summary are grouped together:*

{code:html}<!-- Hot news -->
<div class="BigNews ClearFix">
	<!-- Begin illustrative image -->
		<%
		RESTImagesRendererService imagesRenderer = uicomponent.getApplicationComponent(RESTImagesRendererService.class);
		def imageURI = imagesRenderer.generateImageURI(currentNode.getNode("medias/images/illustration"),null);
		if (imageURI != null){
		%>
	<a class="Image"><img width="93" src="$imageURI" alt=""></a>
		<%
		}
		%>
	<div class="Content">
	<!-- Begin title -->
	<%
	  if(currentNode.hasProperty("exo:title")) {
		def title = currentNode.getProperty("exo:title").getString();
		%>
		<a href="#" class="Title">$title</a>
		<div class="Index1">$title</div>
		<%
	  }
	%>
	<!-- End title -->
	<!-- Begin summary -->
		<%
		if(currentNode.hasProperty("exo:summary")) {
		def summary = currentNode.getProperty("exo:summary").getString();
		%>
		<div class="Summary">$summary</div>
		<%
		}
		%>
	<!-- End summary -->
	</div>
</div>{code}

In which:

* Name: The name of the product.
* Title: The title of the product.
* Illustration Image: The image that is used as an illustration for the product.
* Summary: The summary about the product that goes with the illustration.
* Benefits: The benefits of the product.
* Features: The features of the product.

*Benefits and Features fields are rendered in two tabs using the jQuery library (already integrated into eXo Platform 3.5).*

{code:html}<div id="sectionsTabs" class="ui-tabs">
	<ul class="ui-tabs-nav ClearFix">
		<li class="ui-state-default">
			<!-- Begin Benefits head section -->
			<a class="ArrowCtrl" href="#tab-benefits"><%=_ctx.appRes("Product.view.label.benefits")%></a>
			<!-- End Benefits head section -->
		</li>
		<li class="ui-tabs-selected">
			<!-- Begin Features head section -->
			<a class="ArrowCtrl" href="#tab-features"><%=_ctx.appRes("Product.view.label.features")%></a>
			<!-- End Features head section -->
		</li>
	</ul>
	<div id="tab-benefits">
	  <%
		  if(currentNode.hasProperty("exo:productBenefits")) {
			def benefits = currentNode.getProperty("exo:productBenefits").getString();
			print benefits;
		  }
	  %>
	</div>
	<div id="tab-features">
	  <%
		  if(currentNode.hasProperty("exo:productFeatures")) {
			def features = currentNode.getProperty("exo:productFeatures").getString();
			print features;
		  }
	  %>
	</div>
</div>

<script type="text/javascript">
	jQuery.noConflict();
	jQuery(document).ready(function() {
		jQuery("#sectionsTabs").tabs();
	});
</script>{code}

* The jQuery-based feature is used to display the product's images (in the coverflow view) from the images folder.*

{code:html}<div class="jQProBoxC">
<!-- Begin jCarouselLite part -->
<button class="jQprev">&nbsp;</button>
<div class="jCarouselLite">
	<ul>
	   <%
             FOR IMAGE IN PRODUCT'S IMAGE FOLDER
		String imgSrc = "";
		/*
		GET THE IMAGE PATH
		imgSrc = GET THE IMAGE PATH;
		*/
		%>
		<li><img src="$imgSrc" width="204" height="200"/></li>
		<%
	    %>
	</ul>
</div>
<button class="jQnext">&nbsp;</button>
<!-- End jCarouselLite part -->
</div>
<script type="text/javascript">
jQuery.noConflict();
   jQuery(document).ready(function(){
  //jQuery.noConflict();
	jQuery(".jCarouselLite").jCarouselLite({
	btnNext: ".jQprev",
	btnPrev: ".jQnext",
	//auto: 500,
	//speed: 500
});
});
</script>{code}

* Documents and videos are simply displayed within the view form as follows:*

*1.* Get the node path to a document or video.

*2.* Use some customized CSS classes to display a link for this node.

Labels and/or messages are displayed in the dialog and the view form are localized.

The use of this instruction is described as below:

{code:html}<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.summary")%></td>
(...)
<h1><%=_ctx.appRes("Product.view.label.seeItInAction")%></h1>{code}

This can be achieved by adding locale files. For example:

{code:xml}<Product>
  <view>
    <label>
      <benefits>Benefits</benefits>
      <features>Features</features>
      <seeItInAction>See it in action</seeItInAction>
      <resources>Resources</resources>
      <videos>Videos</videos>
    </label>
  </view>
</Product>{code}

Make sure that locale files are added to the resource bundle configuration. If locale files (dialogs and views) are under the _classes/locale/wcm_ directory, use the following code:

{code:xml}<value>locale.wcm.dialogs</value>
<value>locale.wcm.views</value>{code}