JBoss.orgCommunity Documentation
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.)
Create fields in the Product content type
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:
<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>
Other fields are created almost in the same way:
Title:
<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>
Illustration image:
<% 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>
Summary:
<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>
Benefits:
<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>
Features:
<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>
Develop the Product's view form
The illustration image, title and summary are grouped together:
<!-- 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>
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).
<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>
The jQuery-based feature is used to display the product's images (in the coverflow view) from the images folder.
<div class="jQProBoxC"> <!-- Begin jCarouselLite part --> <button class="jQprev"> </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"> </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>
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:
<td class="FieldLabel"><%=_ctx.appRes("Product.dialog.label.summary")%></td> (...) <h1><%=_ctx.appRes("Product.view.label.seeItInAction")%></h1>
This can be achieved by adding locale files. For example:
<Product>
<view>
<label>
<benefits>Benefits</benefits>
<features>Features</features>
<seeItInAction>See it in action</seeItInAction>
<resources>Resources</resources>
<videos>Videos</videos>
</label>
</view>
</Product>
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:
<value>locale.wcm.dialogs</value>
<value>locale.wcm.views</value>