atlas by clearpeople

Working with search.clientcontrols.js in SharePoint

24 January 2018
  

Working with search.clientcontrols.js in SharePoint

 

Some time ago I worked on a listing page in SharePoint online and I had to customise the way the search results were displayed. One of the solutions would have been to create a new result type and define the display template for it. I ended up discarding this because I would have needed to duplicate the result types I had already to apply the change in all of them. Finally, I decided to investigate how the search controls are rendered by default, and whether I would be able to execute custom code in between.

 

This blog post is a summary of what I found, a sneak peek into the JavaScript library search.clientcontrols.js. This library defines the namespace “Srch” and contains the methods that search related controls (refiners, search box, search results…) execute.

 

In my case, I included some custom functionality in a control display template, and I configured the search results component to use it. The general idea is to load the control you want to customise and execute custom code after they are rendered through the events provided by the control.

 

Get page search controls

Using a display template, it is pretty easy to get the current control, using the context. Use the following:

AddPostRenderCallback(ctx, function()
{
var ctrlId = ctx.ClientControl.get_id();
var currentControl = $find(ctrlId);
}

To get any other control, you can use the following method:

function getSearchComponentId(componentType)
{
for (var prop in Sys.Application._components) 
{
if (Sys.Application._components[prop] instanceof componentType)
return prop;
}
return null;
}

$find(getSearchComponentId(Srch.Result)) //Search results webpart
$find(getSearchComponentId(Srch.SearchBox)) //Search box webpart
$find(getSearchComponentId(Srch.Refinement)) //Search refiners webpart

 

Customising search results

Search results control calls an event called "resultRendered" every time a new page is rendered. With the method add_resultRendered you can push a function that will be executed when the event is fired:

var resultsWPObj = $find(getSearchComponentId(Srch.Result));
resultsWPObj.add_resultRendered(function(context, eventArgs){
renderGroup(context.get_currentResultTableCollection());
});

function renderGroup(resultTables) {
var resultTable = resultTables.ResultTables.filter(function(x) {
return x.TableType == "RelevantResults";
})[0];
if(resultTable){
for (var i = 0; i < resultTable.ResultRows.length; i++) {
var currentResult = resultTable.ResultRows[i];
var idElement = currentResult.csr_id + "_itemBody";
var resultElement = document.getElementById(idElement);
var testContent = document.createElement("div"); 
testContent.innerHTML = "Hello world";
resultElement.appendChild(testContent);
}
}
}

Customising refiners

In a similar way, we can apply customisations to refiners without modifying the display template (perhaps recording which refiners are most used?)

var refinementWPObj = $find(getSearchComponentId(Srch.Refinement));
refinementWPObj.add_resultRendered(function(context, eventArgs){
var refinersArray = eventArgs.result.ResultTables.filter(function(x) {
return x.TableType == "RefinementResults";
})[0];
if(refinersArray){
for (var i = 0; i < refinersArray.ResultRows.length; i++) {
var currentRefiner = refinersArray.ResultRows[i];
//Your customization
}
}
});

 

Last step

When you have your code ready, you need a way to execute it when the page loads. You can use the following:

Sys.Application.get_events()._list.load.push(#yourFunctionName#);

 

And that's it. Hopefully this information is useful for somebody. Ideally we should use display templates for these customisations, but it is always good to have alternatives, right?

Author bio

Guillermo Ruiz

Guillermo Ruiz

I'm one of the developers on the SharePoint team. I feel passionate about JavaScript and all the related technologies and I'm always trying to learn more about it. I can never get enough of the acronyms! Out of work hours, I love playing videogames and watching e-sports.

View all articles by this author View all articles by this author

Get our latest posts in your inbox