h1. What is Navigation By Content? {anchor:id=DEV.NewFeatures.NavigationByContent.whatisNavigationByContent}
*Navigation By Content* is a feature which allows users to browse content of each page easily. 
With this feature, users experiencing eXo Platform can navigate from a page to another or browse site content inside one page directly from a contextual menu.

h1. Actual content navigation {anchor:id=DEV.NewFeatures.NavigationByContent.ContentNavigation}

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 contents 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, the _/site contents/live/acme/events/All_ node will be used.

*To add "Actual content navigation" to a page:*

*1.* Log in to the sample ACME website.

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

*3.* Parameterize this page with the two-column container.

*4.* Add two content list portlets.

*i. First portlet:*

!images/navigation_by_content_feature/browseByCLV.png|align="center"!

In which:

* *Folder path* = _/site contents/live/acme/events/All_: The path to the location of a folder that contains the content.
* *Header* = _Browse by_: The title of all contents that are listed in the content list viewer. 
* *Template* = _CatgoryTree.gtmpl_: The template is used to view 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. Second portlet:*

!images/navigation_by_content_feature/showListCLV.png|align="center"!

In which:

* *Folder path* = _/site contents/live/acme/events/All_: The path to the location of a folder that contains the content.
* *Template* = _OneColumnCLVTemplate.gtmpl_: The template is used to view 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* = _{noformat}content-id{noformat}_: 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"!

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

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

h1. How-To {anchor:id=DEV.NewFeatures.NavigationByContent.HowTo}

*You need to attach your root folder/node to some page nodes from the homepage (the drop-down menu holds your new contextual menu):*

*1.* Go to the *Content Explorer* page and navigate to _/site contents/live/acme/events/All_.

*2.* Click the *Content Navigation* button.

*3.* Fill values into the navigation form, including:

* *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/Overview* homepage.

You will see changes from the *Events* drop-down menu.

!images/navigation_by_content_feature/contextualMenu.png|align="center"!

In which:

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

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

* *Clickable*: The _/site contents/live/acme/events/All_ node is not clickable but all 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 and see that contents of the _Earth_ directory are rendered in a separate page (catalog):

!images/navigation_by_content_feature/listEarth.png|align="center"!

* *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 which is displayed in a separate page (details):

!images/navigation_by_content_feature/event1.png|align="center"!

h1. Actions on Navigation By Content {anchor:id=DEV.NewFeatures.NavigationByContent.ActionsNavigationByContent}

*To restrict the visibility of some contents:*

*1.* Go to the *Content Explorer* page and navigate under _/site contents/live/acme/events/All/Fire_.

*2.* Click the *Content Navigation* button.

*3.* Uncheck the field visible and save.

*4.* Go back to the homepage and see that the Fire sub-menu is not displayed in the contextual menu.

*To sort elements of the contextual menu:*

*1.* Go to the *Content Explorer* page and navigate under _/site contents/live/acme/events/All_.

*2.* Select the _/site contents/live/acme/events/All/Earth_ node.

*3.* Click the *Content Navigation* button.

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

*5.* Select the _/site contents/live/acme/events/All/Water_ node.

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

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

*8.* Select the _/site contents/live/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 homepage and see that the display order from the contextual menu is sorted to Earth, Water, Air. Note that the Fire sub-menu is not displayed because it is set to "invisible" in the previous example.

*To restore a node to the contextual menu (if you already removed it) and attach it to another page:*

*1.* Go to the *Content Explorer* page and navigate under _/site contents/live/acme/events/All/Fire_.

*2.* Click the *Content Navigation* button.

*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 and see that the Fire node is attached to the *News* drop-down menu from the site menu:

!images/navigation_by_content_feature/fireNode.png|align="center"!

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

*To add your newly created contents to the contextual menu:*

*1.* Go to the *Content Explorer* page and navigate under _/site contents/live/acme/events/All/Fire_.

*2.* Click the *Manage Actions* button and add the *{noformat}exo:populateToMenu{noformat}* action.

!images/navigation_by_content_feature/populateToMenuAction.png|align="center"!

*3.* Create a document under _/site contents/live/acme/events/All/Fire_ (for example, uploading a file) and publish it.

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

!images/navigation_by_content_feature/docPDF.png|align="center"!

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

!images/navigation_by_content_feature/productsMenu.png|align="center"!

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

!images/navigation_by_content_feature/visionSubMenuList.png|align="center"!

For example, select the X-Ray content and see the newly implemented content using new visual effects.

* "Benefits" and "Features" tabs:

!images/navigation_by_content_feature/benefits.png|align="center"!

* Coverflow section:

!images/navigation_by_content_feature/coverflow.png|align="center"!

* Related documents:

!images/navigation_by_content_feature/relatedDocuments.png|align="center"!

h2. Create a new product {anchor:id=DEV.NewFeatures.NavigationByContent.CreateNewProduct}

*To create a new product:*

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

*2.* Click the *Add Document* button.

*3.* Select *Product*.

*4.* Fill the product dialog form.

* 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 goes with the illustration.
* Benefits: The benefits of the product.
* Features: The features of the product.

*5.* Save changes.

*To improve your newly created product, for example "sampleProduct":*

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

*2.* Upload some images and publish them.

!images/navigation_by_content_feature/sampleProductImages.png|align="center"!

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

*4.* Upload a video and publish it.

!images/navigation_by_content_feature/sampleProductVideos.png|align="center"!

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

*6.* Create two directories, including Sales materials and Technical documentation.

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

!images/navigation_by_content_feature/sampleProductDocuments.png|align="center"!

*8.* Add *sampleProduct* to some categories or add it to *Content List Portlet*.

Your newly created product is 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"!

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

!images/navigation_by_content_feature/sampleProductDetail.png|align="center"!

h2. Develop your product content {anchors:id=DEV.NewFeatures.NavigationByContent.HowCreateNewProduct.DevelopProductContent}

The product content is composed of fields and folders:

* Fields: Name, Title, Illustration Image, Summary, Benefits, and Features.

* Folders: documents, medias/images, medias/videos.

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}

Now let's look at the product's view form.

*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}

* *Benefits and Features fields are rendered in two tabs. It uses 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 display of the product's images (coverflow) 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 (document or video).

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

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

Note the use of this instruction as below:

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

This is 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}