Wednesday, February 29, 2012

Select multiple Refiners via the UI with xsl & js (part 2)

Just by extending the XSL of the Refinement Panel and adding a little javascript it is possible to select multiple Refiners via the UI:


After selection of multiple Refiners:


Add the following javascript to the Search results page:
<script type="text/javascript">
function Filter(url)
{
var inputs = document.getElementsByTagName("input");
var idValues = [];
for (var i = 0; i < inputs.length; i++) {   
  if ((inputs[i].type == "checkbox") && (inputs[i].checked)) {
idValues.push((GetUrlKeyValue("r",false,inputs[i].value)).substr((GetUrlKeyValue("r",false,url)).length));
}}
window.location = SP.Utilities.UrlBuilder.replaceOrAddQueryString(url, "r", GetUrlKeyValue("r",false,url)+decodeURI(idValues.toString().replace(/\,/g,"%20")));
}
</script>
(2012-03-01) Correction: changed the boolean value in all three GetUrlKeyValue functions to false.

Extend the XSL of the Filterlink template in the Refinement Panel web part:
  <xsl:template name="FilterLink">
    <xsl:param name="Url"/>
    <xsl:param name="UrlTooltip"/>
    <xsl:param name="Value"/>
    <xsl:param name="FilterSelection"/>
    <xsl:param name="ShowCounts"/>
    <xsl:param name="Count"/>
    <xsl:param name="Percentage"/>
    <xsl:param name="Indentation"/>
    <!-- HW -->
    <xsl:param name="ManagedProperty" />
    <!-- HW -->
    <xsl:variable name="SecureUrl">
      <xsl:call-template name="GetSecureUrl">
        <xsl:with-param name="Url" select="$Url" />
      </xsl:call-template>
    </xsl:variable>
    <li class="ms-searchref-filter {$FilterSelection}">
      <xsl:if test="($Indentation = '1')">
        <span class="ms-searchref-indenticon">&#8627;&#160;</span>
      </xsl:if>
      <!-- HW -->
      <xsl:if test="($ManagedProperty = 'Author' or $ManagedProperty = 'FileExtension') and $FilterSelection != 'ms-searchref-unselected' and not(starts-with($Value, 'Any '))">
        <input name="{$Value}" type="checkbox" align="center" title="OR {$Value}" value="{$SecureUrl}" checked="yes" />
      </xsl:if>
      <xsl:if test="($ManagedProperty = 'Author' or $ManagedProperty = 'FileExtension') and $FilterSelection = 'ms-searchref-unselected' and not(starts-with($Value, 'Any '))">
        <input name="{$Value}" type="checkbox" align="center" title="OR {$Value}" value="{$SecureUrl}" />
      </xsl:if>
      <xsl:choose>
        <xsl:when test="(starts-with($Value, 'Any Result Type') or starts-with($Value, 'Any Author')) and $FilterSelection != 'ms-searchref-unselected'">
          <a href="javascript:Filter('{$SecureUrl}')"><img align="absmiddle" src="/_layouts/images/filter.gif" border="0" title="Join selected Refiners"/></a>
        </xsl:when>
        <xsl:when test="(starts-with($Value, 'Any Result Type') or starts-with($Value, 'Any Author')) and $FilterSelection = 'ms-searchref-unselected'">
          <a href="{$SecureUrl}"><img align="absmiddle" src="/_layouts/images/filteroff.gif" border="0" title="Reset selected Refiners"/></a>
        </xsl:when>
        <xsl:when test="starts-with($Value, 'Any ')">
          <img align="absmiddle" src="/_layouts/images/asterisk.png" border="0" />
        </xsl:when>
        <xsl:when test="$ManagedProperty = 'SiteName'">
          <a href="http://{$Value}" target="_blank" title="Open site in new window"><img align="absmiddle" src="/_layouts/images/SharePointFoundation16.png" border="0" /></a>
        </xsl:when>
        <xsl:when test="ddwrt:MapToIcon('', $Value) != 'icgen.gif'">
          <img align="absmiddle" src="/_layouts/images/{ddwrt:MapToIcon('', $Value)}" border="0" />
        </xsl:when>
        <xsl:when test="$Value = 'Word'">
          <img align="absmiddle" src="/_layouts/images/icdocx.png" border="0" />
        </xsl:when>
        <xsl:when test="$Value = 'Excel'">
          <img align="absmiddle" src="/_layouts/images/icxlsx.png" border="0" />
        </xsl:when>
        <xsl:when test="$Value = 'PowerPoint'">
          <img align="absmiddle" src="/_layouts/images/icpptx.gif" border="0" />
        </xsl:when>
        <xsl:when test="$Value = 'Webpage'">
          <img align="absmiddle" src="/_layouts/images/icaspx.gif" border="0" />
        </xsl:when>
        <xsl:when test="$ManagedProperty = 'Author'">
          <a href="/SearchCenter/Pages/peopleresults.aspx?k={$Value}" target="_blank" title="Search for user profile"><img align="absmiddle" src="/_layouts/images/ACA16.gif" border="0" /></a>
        </xsl:when>
        <xsl:otherwise>
          <img align="absmiddle" src="/_layouts/images/{$Value}.gif" onError="this.src='/_layouts/images/bullet.gif';" border="0" />
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text> </xsl:text>
      <!-- HW -->
      <a class="ms-searchref-filterlink" href="{$SecureUrl}" title="{$RefineByHeading}: {$UrlTooltip}">
        <xsl:value-of select="Value"/>
      </a>
      <xsl:choose>
        <xsl:when test="($ShowCounts = 'Count') and ($Count != '')">
          <span class="ms-searchref-count">
            <xsl:if test="$IsRTL = 'True'">&#x200f;</xsl:if> 
            (<xsl:value-of select="Count"/>)
          </span>
        </xsl:when>
        <xsl:when test="($ShowCounts = 'Percentage') and ($Percentage != '')">
          <span class="ms-searchref-count">
            <xsl:if test="$IsRTL = 'True'">&#x200f;</xsl:if> 
            (<xsl:value-of select="format-number($Percentage, '0%')"/>)
          </span>
        </xsl:when>
      </xsl:choose>
    </li>
  </xsl:template>

That's all folks!

Notice: The Display Language should be English, because I check for the word 'Any' in the XSL. You can/should adjust this by yourself in rows 30, 33, 36 for your preferred language.

Zip file with two webparts:
- HTML Form Web Part.dwp with navigation and the javascript;
- Refinement Panel.webpart with the extended XSL and customized categories.
Add the web parts to the Left Zone in the Search results page, and remove the original Refinement Panel web part.

References:
- See how to propagate the ManagedProperty parameter;
- Working with URLs in SharePoint 2010 JavaScripts;
- Helpful SharePoint JavaScript functions.

13 comments:

  1. It's a very nice tool, but it doesn't work as it should I think:
    Nothing happens after checking the checkboxes!

    What can be the mistake? Is it a problem of our system?
    I only copy/paste your code!

    Does someone have an idea?

    Thanx a lot!!

    ReplyDelete
    Replies
    1. Hi there,

      You should click on the filter icon (in front of the Any) to activate the multiselct.

      Delete
  2. Unfortunately the solution doesn't work (at least not for Result type). Refiners for the same managed property are always concatinated with AND. The result type of an item can never be Word AND Pdf at the same time :-(
    In the javascript above you combine the refiner values even for the same refiner (on same managed propety).
    The solution is to use filter (set with the a parameter) e. g. a=fileextension:ASPX%20AND%20fileextension:PDF. Don't forget to set the checkboxes to checked ;-)

    ReplyDelete
    Replies
    1. Hi John,

      The Display Language should be English, because I check for the word 'Any' in the xslt. You can/should adjust this by yourself in rows 30, 33, 36.
      You are wrong about the search syntax. If you analyse the url with the refiner 'Word' active for the Result Type, you will see that the parameter 'fieextension' is repeatedly used in an OR construct: fileextension%3D%22doc%22%20fileextension%3D%22docm%22%20fileextension%3D%22docx%22%20fileextension%3D%22dot%22%20fileextension%3D%22nws%22.
      This is explained in the first part of my solution:
      http://theressomethingaboutsharepoint.blogspot.nl/2012/02/select-multiple-refiners-in-same.html

      Delete
  3. Hmmm, my Result Type refiner looks like yours and far as having the cascading images, yet the other's one do not, they just has some orange squares. Also I do not see any checkboxes.

    - Charlie

    ReplyDelete
    Replies
    1. Hi Charlie,

      Please read my blog post (http://theressomethingaboutsharepoint.blogspot.nl/2011/08/ugly-bad-and-good-part-3.html) about how I obtain the images. If you miss the PDF icon, you should modify the docicon.xml file on the server and add the pdf.gif file to the images folder.
      About the missing checkboxes: did you add the javascrript to the page as well?

      Delete
  4. Here it doesn't work also.

    I see bullet.gif (line 61) and I see the filter icon but I don't see any checkboxes.

    If I click on a link, I don't see the filter icon anymore.

    I added the javascript, tried it with the javascript above and under the refinement panel...

    ReplyDelete
    Replies
    1. Hi John,

      Did you propagate the ManagedProperty parameter? You must use the customized xslt in the refiner web part.
      It won't work if you use FAST-search because of the different query syntax.
      And the Display Language should be English.

      Delete
    2. indeed,I found this friday.

      You need to add more code in the XSL in the Refinement Panel web part, like:

      in FilterCategory template:


      and so on

      Delete
  5. Hi Hans,

    It works but I have a problem if for example the "filter" contains a ","

    Maybe with an example:
    Author
    Any Author
    Author 1
    Author 2
    Author ,3
    Author 4

    Then you can filter on author 1,2 and 4. But if you check "Author,3" then you don't have results.

    Any idea how we can solve this problem?

    ReplyDelete
  6. I have a requirement for Multi select search refinement web part. Were you able to get this to work?

    ReplyDelete
    Replies
    1. Hi John Silver,

      Yes, I got it to work just by using some javascript and custom XSL.
      If you're looking for a server side solution, there's an inspiring article in issue #5 of the DIWUG SharePoint eMagazine:
      •SharePoint 2010 WCM site based on search
      Link: http://www.diwug.nl/DIWUG_SharePoint_eMagazine5.pdf

      Delete
  7. This is working here. The only problem is if a value contains a "&"... Any solution for this?

    You can filter with values like this, but if you refilter after having fitered with a "&" value, you get "Property doesn't exist or is used in a manner inconsistent with schema settings."

    Any idea?

    ReplyDelete