Thursday, June 6, 2013

Add a “Clear Filters” link to your search page in SharePoint 2013

Using refiners or filters on a search page is an easy way to narrow down on the content you are looking for. If you need to start from scratch you can just click the search button again, but this may not be the best UI.

I’ve worked on many projects where they also want a “Clear filters” link.

As all calls on the 2013 search page is done using AJAX, the real query is added to the hash part of the url, the part coming after the # character. If you want to clear all filters and the search terms, then you can add what designers call a dummy link with a # to the page, and that will reset your query.

<a href=”#”>Clear filters</a>

A simple solution it so add a Content Editor Web Part above the refiner panel with the above markup.
image

As long as the query originated from the search start page, and you have not changed it, then this will work as your query will be part of the url with ?k=query.

However, if you change your query, the url changes. If your original query was test and the new one was sharepoint your url would look like this:

https://intranet.contoso.com/search/Pages/results.aspx?k=test#k=sharepoint

where the value after the hash is what is actually executed. Clearing the filters with the above link would bring you back to the original search term of test. And when you click a refiner, the query changes completely. Url decoded it looks something like this

https://intranet.contoso.com/search/Pages/results.aspx?k=test#Default={"k":"sharepoint","r":[{"n":"WebTemplate","t":["equals(\"STS\")"],"o":"or","k":false,"m":null}]}

where the search term and refiner has been added into a JSON array assigned to the Default hash part. If you want to reset all filters, we now have to do some javascript manipulation.

var hash = window.location.hash;
if( hash.indexOf('Default') == 1 ) {
    hash = unescape(hash)
    var kIdx = hash.indexOf('"k":'); 
    var rIdx = hash.indexOf('","'); 
    var query = hash.substring(kIdx+5,rIdx);
    query = query.replace(/\\/g, '');
    window.location.href = window.location.pathname + window.location.search + '#k=' + escape(query);
} else {
    window.location.href = window.location.pathname + window.location.search + "#";
}

What the above script does is grab the k part from the JSON array, and remove everything else.

A possibly simpler solution is to use the fact that the search query is part of the document title. This we can do as a one liner, and use following markup instead of the one at the top of the post in the Content Editor Web Part.

<a onclick="window.location.href = window.location.pathname + window.location.search + '#k=' + escape(document.title.substr(document.title.indexOf(':')+2))" style="cursor:pointer">Clear filters</a>

--Update 2016-06-01--

Here's a better piece of code which does it correct. It uses the query group "Default" which works on a search page when you have one result web part. If you have multiple you need to make sure you clear the filters on all or the correct web part.

var scriptManager = Srch.ScriptApplicationManager.get_current()
var queryGroup = scriptManager.queryGroups["Default"];
var searchControls = queryGroup.displays;
for (var i = 0; i < searchControls.length; i++) {
 if (searchControls[i] instanceof Srch.Refinement) {
  searchControls[i].clearAllRefiners();
  break;
 }
}