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