Goal
A sample 3 step wizard for selecting assets from different folders, provide additional information in steps and submit for project specific processing; useful for creating custom screens the AEM way
For selecting assets using list view check this post
Demo | Package Install | Git Hub
Wizard - http://localhost:4502/apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard.html
Structure in CRX
Solution
1) Login to CRXDE Lite - http://localhost:4502/crx/de/index.jsp and create nt:folder /apps/eaem-wizard-select-assets-column-view
2) Create /apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard of type cq:Page with the following content
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Page">
<jcr:content
jcr:mixinTypes="[sling:VanityPath]"
jcr:primaryType="nt:unstructured"
jcr:title="EAEM 3 Step Wizard"
sling:resourceType="/apps/eaem-wizard-select-assets-column-view/page">
<head jcr:primaryType="nt:unstructured">
<viewport
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/admin/page/viewport"/>
<favicon
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/page/favicon"/>
<clientlibs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs"
categories="[coralui3,granite.ui.coral.foundation,eaem.wizard]"/>
</head>
<body
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/page/body">
<items jcr:primaryType="nt:unstructured">
<form
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form"
action="/apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard/jcr:content"
foundationForm="{Boolean}true"
maximized="{Boolean}true"
method="post"
novalidate="{Boolean}true"
style="vertical">
<successresponse
jcr:primaryType="nt:unstructured"
jcr:title="Success"
sling:resourceType="granite/ui/components/coral/foundation/form/responses/openprompt"
open="/apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard.html"
redirect="/apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard.html"
text="Your data was submitted"/>
<items jcr:primaryType="nt:unstructured">
<charset
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/hidden"
name="_charset_"
value="utf-8"/>
<wizard
jcr:primaryType="nt:unstructured"
jcr:title="Experience AEM 3 Step Wizard"
sling:resourceType="granite/ui/components/coral/foundation/wizard">
<items jcr:primaryType="nt:unstructured">
<step1
jcr:primaryType="nt:unstructured"
jcr:title="Select Folder"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
margin="{Boolean}false"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<assetsPath
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/pathbrowser"
fieldLabel="Assets Path"
name="eaemAssetsPath"
rootPath="/content/dam"/>
</items>
</column>
</items>
</title>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="Next"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</step1>
<step2
jcr:primaryType="nt:unstructured"
jcr:title="Column View"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/include"
path="/libs/dam/gui/content/assets/jcr:content/views/column"/>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="Next"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</step2>
<step3
jcr:primaryType="nt:unstructured"
jcr:title="Additional Info"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<footer
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
margin="{Boolean}false"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<text
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Text"
name="eaemText"/>
</items>
</column>
</items>
</footer>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="GO"
type="submit"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</step3>
</items>
<granite:data
jcr:primaryType="nt:unstructured"
suffix="${requestPathInfo.suffix}"/>
</wizard>
</items>
</form>
</items>
</body>
</jcr:content>
</jcr:root>
3) The extension clientlib #19, for page created above - eaem.wizard is added in next steps
4) #69, in step 1, select the folder path from where assets are to be picked by default
5) #98, in step 2, provide a column view of the assets in folder selected in step 1; column view here includes otb column view from Assets Console http://localhost:4502/assets.html/content/dam - /libs/dam/gui/content/assets/jcr:content/views/column and extends it to provide the Selected Files section
6) #133, in step 3, provide a text area widget for entering additional information
7) #28 has the wizard form action /apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard/jcr:content of sling:resourceType /apps/eaem-wizard-select-assets-column-view/page
8) Create /apps/eaem-wizard-select-assets-column-view/page with the following content
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="sling:Folder"
sling:resourceSuperType="granite/ui/components/coral/foundation/page"/>
9) Create nt:file /apps/eaem-wizard-select-assets-column-view/page/POST.jsp with the necessary logic to process selected assets...
<%@include file="/libs/granite/ui/global.jsp"%>
<%@page session="false"%>
<%
String eaemSelectedAssets = request.getParameter("eaemSelectedAssets");
String eaemText = request.getParameter("eaemText");
log.info("eaemText-------" + eaemText);
log.info("eaemSelectedAssets-------" + eaemSelectedAssets);
%>
10) Create clientlib (type cq:ClientLibraryFolder) /apps/eaem-wizard-select-assets-column-view/clientlib with categories String[] eaem.wizard and dependencies String[] underscore to add some dynamic behavior to the wizard while navigating between the steps
11) Create nt:file /apps/eaem-wizard-select-assets-column-view/clientlib/js.txt and add the following content
handle-wizard.js
12) Create nt:file /apps/eaem-wizard-select-assets-column-view/clientlib/handle-wizard.js, add the following logic
(function ($, $document) {
var WIZARD_URL = "/apps/eaem-wizard-select-assets-column-view/eaem-3-step-wizard.html",
COLUMN_VIEW = "coral-columnview",
FOUNDATION_CONTENT_LOADED = "foundation-contentloaded",
FOUNDATION_WIZARD_STEPCHANGE = "foundation-wizard-stepchange",
FOUNDATION_WIZARD = "foundation-wizard",
FOUNDATION_SELECTIONS_CHANGE = "foundation-selections-change",
FOUNDATION_SELECTIONS_ITEM = "foundation-selections-item",
FOUNDATION_COLLECTION = ".foundation-collection",
FOUNDATION_COLLECTION_ITEM_ID = "foundation-collection-item-id",
CORAL_COLUMN_VIEW_LOAD_ITEMS = 'coral-columnview:loaditems',
CORAL_COLUMNVIEW_ITEM = "coral-columnview-item",
SELECTION_MODE = "selectionmode",
SUFFIX = "suffix",
TABLES_DIV = "eaem-column-view-selections",
TABLES_IN_ROW = 5,
EAEM_ASSETS_PATH = "eaemAssetsPath",
EAEM_SELECTED_ASSETS = "eaemSelectedAssets";
var selectedAssets = {}, $sfContainer,
tableWidth = (($(window).width() / TABLES_IN_ROW) - 5),
itemTpl = Handlebars.compile(getItemTemplate()),
sectionTpl = Handlebars.compile(getSectionTemplate());
$document.on(FOUNDATION_CONTENT_LOADED, ifSuffixAvailableBuildUIMoveToStep2);
$document.on(FOUNDATION_WIZARD_STEPCHANGE, handleSteps);
function ifSuffixAvailableBuildUIMoveToStep2(){
var $wizard = $("." + FOUNDATION_WIZARD);
if(_.isEmpty($wizard)){
return;
}
var suffix = $wizard.data(SUFFIX);
if(_.isEmpty(suffix)){
return;
}
var $columnView = $(COLUMN_VIEW);
if(_.isEmpty($columnView)){
return;
}
createSelectedAssetsUI($columnView);
registerListeners($columnView);
$wizard.adaptTo(FOUNDATION_WIZARD).next();
}
function handleSteps(event, nextStep, currentStep){
if(_.isUndefined(currentStep)){
return;
}
var $eaemAssetsPath = $("[name=" + EAEM_ASSETS_PATH + "]");
if(isSecondStep() && !_.isEmpty($eaemAssetsPath.val())){
$(nextStep).hide();
redirectTo(WIZARD_URL + $eaemAssetsPath.val());
}else if(isThirdStep()){
addSelectedAssetsToForm();
}
}
function registerListeners($columnView){
$document.on(FOUNDATION_SELECTIONS_CHANGE, FOUNDATION_COLLECTION, collectAssets);
$columnView.on(CORAL_COLUMN_VIEW_LOAD_ITEMS, listenerOnLoadedItems);
}
function addSelectedAssetsToForm(){
if(_.isEmpty(selectedAssets)){
return;
}
var $form = $("form"),
$selectedAssets = $("[name=" + EAEM_SELECTED_ASSETS + "]");
if(_.isEmpty($selectedAssets)){
$selectedAssets = $('<input />').attr('type', 'hidden')
.attr('name', EAEM_SELECTED_ASSETS)
.appendTo($form);
}
var assetPaths = Object.keys(selectedAssets);
$selectedAssets.val(assetPaths.join(","));
if(_.isEmpty(assetPaths)){
disableWizardNext();
}else{
enableWizardNext();
}
}
function createSelectedAssetsUI($columnView){
var height = $(window).height() - 350;
$columnView.height(height).attr(SELECTION_MODE, Coral.ColumnView.selectionMode.SINGLE);
$sfContainer = $("<div/>").appendTo($columnView.parent());
addHeader($sfContainer);
addNoSelFilesDiv($sfContainer);
}
function collectAssets(){
var $asset, path;
$("." + FOUNDATION_SELECTIONS_ITEM).each(function(index, asset){
$asset = $(asset);
path = $asset.data(FOUNDATION_COLLECTION_ITEM_ID);
if(selectedAssets.hasOwnProperty(path)){
return;
}
if(!isAsset($asset)){
$asset.removeAttr("selected").removeClass(FOUNDATION_SELECTIONS_ITEM);
return;
}
selectedAssets[path] = {
path: path,
thumbnail: $asset.find("coral-columnview-item-thumbnail > img").attr("src"),
text: $asset.data("item-title")
};
});
buildTable(selectedAssets, $sfContainer);
}
function buildTable(selectedAssets, $container) {
if(_.isEmpty(selectedAssets)){
addNoSelFilesDiv($sfContainer);
return;
}
enableWizardNext();
var itemHtml = "", index = 0,
rowsInTable = getNoOfRowsInEachTable(selectedAssets),
$tablesDiv = getTablesDiv();
_.each(selectedAssets, function(itemData){
itemHtml = itemHtml + itemTpl(itemData);
if( (++index % rowsInTable) !== 0 ){
return;
}
addToSection($tablesDiv, itemHtml);
itemHtml = "";
index = 0;
});
if(itemHtml){
addToSection($tablesDiv, itemHtml);
}
$container.find("#" + TABLES_DIV).remove();
$tablesDiv.appendTo($container);
handleSelections($tablesDiv);
}
function handleSelections($tablesDiv){
_.defer(function(){
$tablesDiv.find("coral-checkbox").click().on('change', handleChecks);
});
function handleChecks(){
var path = $(this).closest("tr").data("path");
delete selectedAssets[path];
buildTable(selectedAssets, $sfContainer);
}
}
function addToSection($tablesDiv, itemHtml){
var sectionHtml = sectionTpl({
width: tableWidth + "px",
itemHtml: itemHtml
});
$(sectionHtml).appendTo($tablesDiv);
}
function listenerOnLoadedItems(){
$(CORAL_COLUMNVIEW_ITEM).click(ignoreFolderSelections);
}
function ignoreFolderSelections(){
var $item = $(this);
if(isAsset($item)){
return;
}
_.defer(function(){
$item.removeAttr("selected");
});
}
function getNoOfRowsInEachTable(selectedAssets){
return Math.ceil(Object.keys(selectedAssets).length / TABLES_IN_ROW);
}
function addHeader($container) {
var html = "<div style='text-align:center; padding: 5px; background-color: rgba(0,0,0,0.05)'>" +
"<h3>Selected Files</h3>" +
"</div>";
return $(html).appendTo($container);
}
function addNoSelFilesDiv($container) {
$container.find("#" + TABLES_DIV).remove();
disableWizardNext();
var html = "<div style='text-align:center' id='" + TABLES_DIV + "'>" +
"<h4>No files have been added." +
"To add files, select the file by clicking on file thumnbnail</h4>" +
"</div>";
return $(html).appendTo($container);
}
function getItemTemplate() {
return '<tr is="coral-tr" data-path="{{path}}">' +
'<td is="coral-td" coral-tr-select></td>' +
'<td is="coral-td">' +
'<img src="{{thumbnail}}" class="image">' +
'</td>' +
'<td is="coral-td">{{text}}</td>' +
'</tr>'
}
function getSectionTemplate(){
return '<coral-table selectionmode="row" multiple style="display:inline-block" >' +
'<table is="coral-table-inner" style="width: {{width}}; overflow: hidden">' +
'<colgroup>' +
'<col is="coral-col" fixedwidth>' +
'<col is="coral-col" fixedwidth>' +
'<col is="coral-col" sortable alignment="left">' +
'</colgroup>' +
'<tbody is="coral-tbody">' +
'{{{itemHtml}}}' +
'</tbody>' +
'</table>' +
'</coral-table>'
}
function isAsset($item){
return ($item.data("item-type") === "asset");
}
function getTablesDiv(){
return $("<div id='" + TABLES_DIV + "'></div>");
}
function disableWizardNext(){
toggleWizard(false);
}
function enableWizardNext(){
toggleWizard(true);
}
function toggleWizard(isEnable){
var $wizard = $("." + FOUNDATION_WIZARD);
if(_.isEmpty($wizard)){
return;
}
var wizardApi = $wizard.adaptTo(FOUNDATION_WIZARD);
wizardApi.toggleNext(isEnable);
}
function getStepNumber(){
var $wizard = $("." + FOUNDATION_WIZARD),
currentStep = $wizard.find(".foundation-wizard-step-active"),
wizardApi = $wizard.adaptTo(FOUNDATION_WIZARD);
return wizardApi.getPrevSteps(currentStep).length + 1;
}
function isSecondStep(){
return (getStepNumber() === 2);
}
function isThirdStep(){
return (getStepNumber() === 3);
}
function redirectTo(url){
var ui = $(window).adaptTo("foundation-ui");
ui.wait($("form"));
window.location = url;
}
}(jQuery, jQuery(document)));





No comments:
Post a Comment