Goal
Asset Finder in Touch UI is Content Finder of Classic UI. In AEM 61 ( not 60 ) we can search for pages in Asset Finder. In this extension we provide additional filtering of pages by providing Search by Template (Granite/TouchUI/Coral UI sample Select)
Demo | Source Code | Package Install
A similar extension for Classic UI is here
Solution
1) We need a servlet to return templates as json. So code one and install as OSGI bundle
package apps.experienceaem.pagefilters;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.commons.json.io.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.servlet.ServletException;
import java.io.IOException;
@SlingServlet(
paths="/bin/experience-aem/touch-ui/page-filters/templates",
methods = "GET",
metatype = false,
label = "Get Templates Servlet"
)
public class GetTemplates extends SlingAllMethodsServlet {
private static final Logger log = LoggerFactory.getLogger(GetTemplates.class);
@Override
protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
JSONWriter jw = new JSONWriter(response.getWriter());
try{
ResourceResolver resolver = request.getResourceResolver();
Session session = resolver.adaptTo(Session.class);
QueryManager qm = session.getWorkspace().getQueryManager();
String stmt = "//element(*,cq:Template)[jcr:like(@jcr:path, '/apps/%')] order by @jcr:title";
Query q = qm.createQuery(stmt, Query.XPATH);
NodeIterator results = q.execute().getNodes();
Node node = null, tNode = null; String path = null;
jw.array();
while(results.hasNext()){
node = results.nextNode();
path = node.getProperty("jcr:content/sling:resourceType").getString();
if(path.startsWith("/apps/")){
path = path.substring(6);//remove /apps/
}
jw.object();
jw.key("id").value(path);
jw.key("name").value(node.getProperty("jcr:title").getString());
jw.endObject();
}
jw.endArray();
}catch(Exception e){
log.error("Error getting templates",e);
throw new ServletException(e);
}
}
}
2) JS logic for showing templates is added using Clientlibs. Login to CRXDE Lite (http://localhost:4502/crx/de) and create folder /apps/touch-ui-page-filters
2) Create node /apps/touch-ui-page-filters/clientlib of type cq:ClientLibraryFolder and add a String property categories with value cq.authoring.editor.hook.assetfinder and String property dependencies with value cq.jquery.ui
3) Create file (nt:file) /apps/touch-ui-page-filters/clientlib/js.txt and add
page-filters.js
4) Create file (nt:file) /apps/touch-ui-page-filters/clientlib/page-filters.js and add the following code
(function (document, $, assetFinder) {
var TEMPLATE_SELECT_ID = "experience-aem-filter-template";
var c$templateSelect = null;
//id assetfinder-filter and class .assetfilter.type are defined in
///libs/wcm/core/content/editor/jcr:content/sidepanels/edit/items/assetsTab/items/filterPanel/items/views/items/search/items/searchpanel
var $assetFinderFilter = $('#assetfinder-filter');
var $assetFinderType = $assetFinderFilter.find(".assetfilter.type");
var addTemplateSelect = function () {
var templateMarkup = '<span class="coral-Select" data-init="select" id="' + TEMPLATE_SELECT_ID + '">' +
'<button type="button" class="coral-Select-button coral-MinimalButton">' +
'<span class="coral-Select-button-text">Select</span>' +
'</button>' +
'<select class="coral-Select-select">' +
'<option value="ALL">Of All Templates</option>' +
'</select>' +
'</span>';
var $optionTemplate = $('<script type="text/x-jquery-tmpl">' +
'<option value="${id}">${name}</option>' +
'</script>').appendTo($assetFinderType);
var promise = $.ajax({
type: 'GET',
url: "/bin/experience-aem/touch-ui/page-filters/templates"
});
promise.done(function (data) {
$("<div/>").appendTo($assetFinderType).append($(templateMarkup));
$optionTemplate.tmpl(data).appendTo("#" + TEMPLATE_SELECT_ID + " .coral-Select-select");
c$templateSelect = new CUI.Select({
element: "#" + TEMPLATE_SELECT_ID,
visible: true
});
c$templateSelect.hide();
});
promise.fail(function(){
alert("error");
});
$assetFinderType.find("select").on('change', function (event) {
var type = $(event.target).find("option:selected").val();
if (type == "Pages") {
c$templateSelect.show();
}else{
c$templateSelect.hide();
}
});
};
var pagesController = assetFinder.registry["Pages"];
var loadAssets = pagesController.loadAssets;
$.extend(pagesController, {
loadAssets: function(query, lowerLimit, upperLimit){
var template = c$templateSelect.getValue();
if(template && ( template != "ALL")){
query = '"jcr:content/sling:resourceType":"' + template + '"' + query;
}
return loadAssets.call(this, query, lowerLimit, upperLimit);
}
});
addTemplateSelect();
}(document, jQuery, Granite.author.ui.assetFinder));
5) In the above logic #32 we use JQuery templates to fill options in Select
$optionTemplate.tmpl(data).appendTo("#" + TEMPLATE_SELECT_ID + " .coral-Select-select");
6) The following logic #34 creates Touch UI Select Widget
c$templateSelect = new CUI.Select({
element: "#" + TEMPLATE_SELECT_ID,
visible: true
});
7) Structure in CRXDE Lite