In this series:
- Search Refiners part 1 – Expanding the OOTB search Refinement Panel
- Search Refiners part 2 – Use of CustomFilters
- Search Refiners part 3 – Chart based
- Search Refiners part 4 – User selection based (this post)
After building a chart based search refiner, now it’s time to get some interaction in the selection of search terms. In this post I will show you how to use jQuery in combination with the RefinementManager.
With interaction I mean the user can drag a search term to a place on the screen to refine the results. Unfortunately the OOTB Refinement Panel and the results webpart ‘talk’ to each other by the parameters in the url. Therefor a postback must occur to actually refine the results with the selected term. But a little animation just looks great.
For the drag and drop functionality I used the standard jQuery library and a custom jQuery UI selection. With this functionality in hand I created my own drag and drop implementation for this specific solution.
Script part
Because I already have a little experience with programming against the RefinementManager class in the chart based example I first focused on the drag drop functionality.
Two divs are placed on the screen:
1. to list all the terms the user can choose from to select
2. the already selected terms by the user
The items in both divs has to have the ability to drag items from and to drop items to. The user has to have the possibility to drag items from the ‘terms to select’ part to the ‘selected terms’ part and vice versa.
Both the divs contain an unordered list with list items.
So a single div with items in it looks in plain HTML like:
<div> <ul> <li>item01</li> <li>item02</li> </ul> </div>
A single item has to be draggable to move it from the ‘terms to select’ to the ‘selected terms’ part(and vice versa). So the li element has to be draggable.
On the other hand when a li element a dragged, the list to which the single item has to be added has to be droppable, the ul element.
To accomplish this just a few lines of jQuery are neccesary, the rest is alredy build in the jQuery libraries.
var $currentSelectedItems = $("#selectedTerms"), $baseItemList = $("#termsToSelect");</pre> //make the li's in the selectedTerms div draggable $("li", $currentSelectedItems).draggable({ appendTo: $baseItemList, helper: "clone" }); //make the ul in the selectedTerms div droppable $("ul", $currentSelectedItems).droppable({ accept: "#termsToSelect li", hoverClass: "ui-state-hover", drop: function (event, ui) { moveTerm(ui.draggable, $currentSelectedItems); } });
The draggable functionality is nothing special. The element passed to appendTo is the container during dragging. Second the clone helper is used here, which means a clone of the actual item is dragged around. Another option here is original, which drags the original item around.
The droppable functionality uses different options. First I’m telling the element what items to accept: an li element within ‘termsToSelect’. Second a nice hover class and finally a function is specified what to do when the actual drop occurs: move the term to from ‘terms to select’ to ‘selected terms’ and navigate to the url which the item received from the RefinementPanel (getting there soon).
//move term function moveTerm($item, $listToAdjust) { $item.fadeOut(function () { var $list = $("ul", $listToAdjust); $item.appendTo($list).fadeIn(); window.location.href = $item.find('a').attr("href"); }); }
The script above is the script which act on the ‘selected terms’ part ($currentSelectedItems or $(“#selectedTerms”)). The same functionality have to be added to the ‘terms to select’ part. Because it’s almost the same this code it’s left out here for readability.
That’s is with all the script, let’s move the code behind all this.
The webpart
The code behind this (just a regular webpart) works with the RefinmentManager class of the page as in the chart based example, the previous post in this series. The extra functionality here is that the selected term is needed from the RefinmentManager’s filter. If a term is selected or not is just another node in the refinement xml, just as Value and Url as shown in the following code listing:
string filterValue = filter.SelectSingleNode("Value").InnerText; string filterUrl = filter.SelectSingleNode("Url").InnerText; if (filter.SelectSingleNode("Selection").InnerText.Equals("Selected")) { dateSelectedList.Add(new ListItem(filterValue, filterUrl)); } else { dateToSelectList.Add(new ListItem(filterValue, filterUrl)); }
dateSelectedList and dateToSelectList are both generic lists of ListItems and in the RenderContents method the items in the lists are added to the appropriate containers.
After putting this all together it looks like the folowing image when no selection are made by the user:
When dragging starts from ‘terms to select’ the location where to drag to is highlighted:
Because ‘helper’ was set to ‘clone’ earlier the item that’s dragged, ‘Past Week’, is still in the ‘terms to select’ container and also moving around the screen.
When dropping the item for a moment the screen looks like (because of the ‘appendto’ option):
And then a postback occurs and it looks like:
And the terms displayed behave just like the OOTB refiners.
Summary
The OOTB refinement functionality is great, but it can be made much more attractive with just a little script as shown in this post. What I’ve shown you here is just a little example with one of the possibilities to make it more attractive. There are a lot of jQuery libraries with excellent functionality which you can use to do all kinds of stuff and don’t forget the design. This example looks nothing like a nice production ready refiner, but go wild and make it look awesome.
Pingback: Search Refiners (part 2) – Use of CustomFilters
Can u help me with group refiners and adding sub refiners to grouped refiners.
its like this
see u get refiners as
refiner 1
refiner 2
refiner 3
refiner 4
refiner 5
i wnt it this way
refiner group1(refiner 1 ,refiner 2)
refiner group2(refiner 3,refiner 4,refiner 4)
and can i add refiners to 1 and 2 after grouping ..