Goal
Add custom metadata columns and support sorting (Name, Modified and on Custom Columns) in Asset Search - http://localhost:4502/aem/search.html
Similar posts for adding custom columns discussed here and here may cause wonky UI behavior (columns adjusting in UI when there are too many results etc.); the following solution works by parsing results before loading them in UI providing seamless experience...
For adding custom metadata columns in Assets console List View check this post
Bug fix - empty space added when switching between card and list views is available in github (and source code below)
Demo | Package Install | Github
Configure Columns
Search Results (with Sorting)
Solution
1) Login to CRXDE and create nt:folder /apps/eaem-assets-metadata-columns-sort-search
2) Configure the columns in /apps/eaem-assets-metadata-columns-sort-search/columns
3) Create a clientlib /apps/eaem-assets-metadata-columns-sort-search/clientlib with categories cq.gui.common.admin.searchpanel, dependencies lodash
4) Add /apps/eaem-assets-metadata-columns-sort-search/clientlib/js.txt with the following content
metadata-columns.js
5) Add file (nt:file) /apps/eaem-assets-metadata-columns-sort-search/clientlib/metadata-columns.js, add the following code
(function ($, $document) { var FOUNDATION_CONTENT_LOADED = "foundation-contentloaded", GRANITE_OMNI_SEARCH_RESULT = "#granite-omnisearch-result", EAEM_METADATA_REL_PATH = "data-eaem-metadata-rel-path", ROW_SELECTOR = "tr.foundation-collection-item", EAEM_SEARCH_PATH_COLUMN_HEADER = "Path", GRANITE_OMNI_SEARCH_CONTENT = ".granite-omnisearch-content", EAEM_META_COLUMNS_URL = "/apps/eaem-assets-metadata-columns-sort-search/columns.1.json", STORAGE = window.localStorage, EAEM_SORT_PARAMETER = "eaem-search-parameter", SORT_DIRECTION_STORAGE_KEY = "apps.eaem.assets.searchSortDirection", PARSER_KEY = "foundation.adapters.internal.adapters.foundation-util-htmlparser", metaParams = {}, sortHandlersAdded = false; loadCustomColumnHeaders(); extendHtmlParser(); $document.ready(function(){ var $form = $(GRANITE_OMNI_SEARCH_CONTENT); STORAGE.removeItem(SORT_DIRECTION_STORAGE_KEY); addSortParameter($form, "nodename", "asc"); }); $document.on(FOUNDATION_CONTENT_LOADED, GRANITE_OMNI_SEARCH_CONTENT, function(event){ _.defer(function(){ handleContentLoad(event); }); }); function handleContentLoad(event){ var layout = $(GRANITE_OMNI_SEARCH_RESULT).data("foundationLayout"); if(sortHandlersAdded || !layout || (layout.layoutId !== "list")){ return; } sortHandlersAdded = true; var $container = $(GRANITE_OMNI_SEARCH_CONTENT), $headRow = $container.find("thead > tr"), sortBy = STORAGE.getItem(SORT_DIRECTION_STORAGE_KEY), direction; if(_.isEmpty(sortBy)){ sortBy = "nodename"; direction = "ascending"; }else{ direction = sortBy.substring(sortBy.lastIndexOf("=") + 1); sortBy = sortBy.substring(0, sortBy.lastIndexOf("=")); } addSortHandler($headRow,"Name", "nodename", sortBy, direction); addSortHandler($headRow,"Modified", "@jcr:content/jcr:lastModified", sortBy, direction); addSortHandler($headRow,"EAEM Desc", "@jcr:content/metadata/eaemDesc", sortBy, direction); addSortHandler($headRow,"EAEM Keywords", "@jcr:content/metadata/eaemKeywords", sortBy, direction); addSortHandler($headRow,"EAEM Title", "@jcr:content/metadata/eaemTitle", sortBy, direction); } function removeSortParameter(){ var $form = $(GRANITE_OMNI_SEARCH_CONTENT), $sortParam = $form.find("." + EAEM_SORT_PARAMETER); if(!_.isEmpty($sortParam)){ $sortParam.remove(); } } function addSortParameter($form, parameter, direction){ removeSortParameter(); $form.append(getSortHtml(parameter, direction)); } function getSortHtml(parameter, direction){ return "<span class='" + EAEM_SORT_PARAMETER + "' >" + "<input type='hidden' name='orderby' value='" + parameter + "'/>" + "<input type='hidden' name='orderby.sort' value='" + direction + "'/>" + "</span>" } function addSortHandler($headRow, header, sortBy, metaPath, direction){ var $col = $headRow.find("th:eq(" + getIndex($headRow, header) + ")") .attr("sortabledirection", "default") .attr("sortable", "sortable").click(handleSort); if(sortBy == metaPath){ $col.attr("sortabledirection", direction) } return $col; } function handleSort(){ var $form = $(GRANITE_OMNI_SEARCH_CONTENT), $th = $(this), sortBy = "nodename", thContent = $th.find("coral-table-headercell-content").html().trim(), direction = "ascending"; if($th.attr("sortabledirection") == "ascending"){ direction = "descending"; } $th.attr("sortabledirection", direction); if(thContent == "Modified"){ sortBy = "@jcr:content/jcr:lastModified"; }else if(thContent == "EAEM Title"){ sortBy = "@jcr:content/metadata/eaemTitle"; }else if(thContent == "EAEM Desc"){ sortBy = "@jcr:content/metadata/eaemDesc"; }else if(thContent == "EAEM Keywords"){ sortBy = "@jcr:content/metadata/eaemKeywords"; } STORAGE.setItem(SORT_DIRECTION_STORAGE_KEY, sortBy + "=" + direction); addSortParameter($form, sortBy, (direction == "descending" ? "desc" : "asc")); $form.submit(); } function extendHtmlParser(){ var htmlParser = $(window).data(PARSER_KEY), otbParse = htmlParser.instance.parse; htmlParser.instance.parse = function(html, avoidMovingExisting){ var $parsedResponse = $(html); if( ($parsedResponse[0].tagName === "CORAL-MASONRY") || !_.isEmpty($parsedResponse.find("coral-masonry"))){ return otbParse.call(htmlParser.instance, html, avoidMovingExisting); } if(!_.isEmpty($parsedResponse.find(GRANITE_OMNI_SEARCH_RESULT))){ addCustomHeaders($parsedResponse); fillColumnData(fetchCustomColumnValues(), $parsedResponse); }else if( GRANITE_OMNI_SEARCH_RESULT == ("#" + $parsedResponse.attr("id"))){ if(!checkHeadersAdded($parsedResponse)){ addCustomHeaders($parsedResponse); fillColumnData(fetchCustomColumnValues(), $parsedResponse); html = reconstructHtml(html, $parsedResponse); }else{ fillColumnData(fetchCustomColumnValues(), $parsedResponse); html = $parsedResponse[0].outerHTML; } } return otbParse.call(htmlParser.instance, html, avoidMovingExisting); } } function reconstructHtml(html, $parsedResponse){ var reHtml = html.substring(0, html.indexOf("<thead")), parsedHtml = $parsedResponse[0].outerHTML; reHtml = reHtml + parsedHtml.substring(parsedHtml.indexOf("<thead"), parsedHtml.indexOf("</tbody>")) + "</tbody>"; reHtml = reHtml + html.substring(html.indexOf("</tbody>") + "</tbody>".length); return reHtml; } function checkHeadersAdded($container){ return !_.isEmpty($container.find("th[" + EAEM_METADATA_REL_PATH + "]")); } function addCustomHeaders($parsedResponse){ var $container = $parsedResponse.find(GRANITE_OMNI_SEARCH_RESULT); if(_.isEmpty($container)){ $container = $parsedResponse; } var $headRow = $container.find("thead > tr"); if(_.isEmpty($headRow)){ return; } _.each(metaParams, function(header, metaPath){ $headRow.append(getTableHeader(header, metaPath)); }); $(getTableHeader(EAEM_SEARCH_PATH_COLUMN_HEADER, "jcr:path")).appendTo($headRow); } function fillColumnData(results, $parsedResponse){ $parsedResponse.find(ROW_SELECTOR).each(function(index, item){ itemHandler($(item) ); }); function itemHandler($row){ if(!_.isEmpty($row.find("[" + EAEM_METADATA_REL_PATH + "]"))){ return; } if(_.isEmpty($row.find("td.foundation-collection-item-title"))){ return; } var itemPath = $row.data("foundation-collection-item-id"), metadata, metaProp, $td = $row.find("td:last"); _.each(metaParams, function(header, metaPath){ metadata = (results[itemPath] || {}); metaProp = metaPath.substring(metaPath.lastIndexOf("/") + 1); $td = $(getListCellHtml(metaPath, metadata[metaProp])).insertAfter($td); }); $td = $(getListCellHtml("jcr:path", itemPath)).insertAfter($td); $(getEmptyListCell()).insertAfter($td); } } function fetchCustomColumnValues() { var $form = $("form.foundation-form"), results = {}, query = "/bin/querybuilder.json?" + $form.serialize(); query = query + "&999_property=jcr:primaryType&999_property.value=dam:Asset&p.hits=selective&p.limit=-1&p.properties=jcr:path"; query = query + "+" + Object.keys(metaParams).join("+"); $.ajax({ url: query, async: false }).done(function(data){ if(!data || (data.results <= 0) ){ return; } _.each(data.hits, function(hit){ results[hit["jcr:path"]] = hit["jcr:content"]["metadata"]; }); }); return results; } function getEmptyListCell(){ return '<td is="coral-table-cell" style="display:none"></td>'; } function getIndex($headRow, header){ return $headRow.find("th coral-table-headercell-content:contains('" + header + "')").closest("th").index(); } function getListCellHtml(metaPath, metaValue){ metaValue = (metaValue || ""); return '<td is="coral-table-cell" ' + EAEM_METADATA_REL_PATH + '="' + metaPath + '" >' + metaValue + '</td>'; } function getTableHeader(colText, metadataPath) { return '<th is="coral-table-headercell" ' + EAEM_METADATA_REL_PATH + '="' + metadataPath + '" >' + colText + '</th>'; } function loadCustomColumnHeaders(){ $.ajax( { url: EAEM_META_COLUMNS_URL, async: false} ).done(function(data){ _.each(data, function(colData){ if(_.isEmpty(colData.header) || _.isEmpty(colData.metadataPath)){ return; } metaParams[colData.metadataPath] = colData.header; }); }); } })(jQuery, jQuery(document));
No comments:
Post a Comment