May 26, 2020
Estimated Post Reading Time ~

Opening properties html in a New Tab on Card Click in Omnisearch

Introduction:
Omnisearch can be triggered by pressing “/” (forward slash) on a sites.html page, or clicking on the Magnifying glass icon in the top bar.

Fig. 1 – Opening Omnisearch 

By default, the results are displayed as cards in an aesthetically pleasing manner. Clicking on a result card opens its properties page in the same tab, but this erases our results page. Going back takes us to the sites.html page from which we initiated the search. If we want to get the same results again, we have to enter the same search term and scroll to the same position. This can get really tiring when you have multiple items to check/modify.

Fig. 2 – Results in Card view  

Requirement:
Preserve Omnisearch results in sites.html
We want to preserve the results, so that we can go back and forth without any overheads. This would increase authors’ efficiency and thus save time.  

Analysis:
In Omnisearch, an AJAX call passes the search parameters to a Sling servlet which returns the results’ HTML markup. Granite UI receives this rudimentary markup, picks only the tags and attributes it needs, translates them to Coral UI-specific tags, and modifies the DOM dynamically. The rendering and behaviour is handled by Coral UI. Sites.html (Touch UI) has thus been designed as a Single Page Application (SPA), powered by the Coral UI and Granite UI libraries.
When we go back from the properties page, it redirects us to the previous URL. Since it did not store the search results, we don’t see them. Only the initial page source (which is stored in the browser history/cache) is served.  

Proposed solution:
The card click should open the link in a new tab
When the user clicks on the card, the properties page will open in a new tab, thereby preserving the results as they were. After the user is done with the property changes, they can close the tab and return to the results.
Limitation is that this will only work on card click for sites.html. It will not work for:
Clicking the Quick Icons (they appear on mouse hover on the card)
List view
Assets, projects, or any other admin interface.  

Discovery:
The following are the relevant points from the control flow:
There is <link rel=”properties” href=”…”/> a node in every card’s DOM. The href attribute stores the address to which we have to navigate.
Shell clientlib listens for clicks on the cards. On being invoked, the listener picks the link tag with the rel=”properties” property from the relevant card, and navigates to it. 

Search results rendering is not a simple task in AEM. Features were probably added over a long time and by different teams with different architects, which has resulted in a spaghetti implementation. Control flow follows confusing paths and there is no consistent data source. Some datasource paths are defined in /libs and can be overridden, while some are hardcoded into the Omnisearch bundle, which makes extending capabilities very tough. This is why the scope of this blog is limited to its current state.
Nevertheless, the new tab functionality for sites.html can be modified without meddling too much with Adobe code.

Fig. 3 – Desired result. Properties page opens in a new tab
Approach:
Overlay the Shell clientlib.
We shall overlay the Shell clientlib under /apps, which lets us accomplish our task with minimal effort.  

Implementation
Copy the folder: “/libs/granite/ui/components/shell”
Paste it under /apps such that the path is: “/apps/granite/ui/components/shell”
Delete all the files in this folder, except “js/omnisearch.js”
Open “js/omnisearch.js”
Go to line 827 

Replace the existing function with: $(document).on("click", "#granite-omnisearch-result-content .foundation-collection-navigator", function(event) { var element = $(event.currentTarget).find("link[rel=properties]"); if(this.hasAttribute("data-foundation-collection-navigator-href")){ var href = element.attr("href"); if (href) { window.location = href; } } else { var href = element.attr("href"); if (href) { window.open(href, "_blank"); } } event.preventDefault(); });

Fig. 4 – The overlaid JS file and modified content
Line 838 is the relevant code for sites.html. We changed it from window.location = href to window.open(href,“_blank”) which opens the page in a new tab.
The condition on Line 829 detects if the search was performed in assets.html. If it evaluates to true, then the default/old code is executed. Had we not placed the check, then a card-click in assets.html would have opened the link in the same tab and a new tab as well. This is because assets.html cards have an additional attribute called data-foundation-collection-navigator-href. When this attribute is combined with the attribute data-foundation-collection-navigator, Granite UI treats the card as a link. So, that would have opened the new page in the same tab, and our code (line 829) would have opened it in a new tab.

Conclusion:
Now when you go to “host:port/sites.html/” and search something, the card click will open the properties page in a new tab.



By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.