Sunday, March 28, 2010

A-Z Navigation for Core Search Result Webpart

Scenario:
XSLT means flexibility , and so for one of the requirement I was given the task to display Core Search Result Webpart results to support A-Z navigation.

Solution:
You need to patient first. I am providing the modified copy of Core Search Result Webpart XSLT which supports this. So download and use it as it is.

Download ( free ) for SP 2007

Download ( free ) for SP 2010


Result will look like :
az

Added Variables and Templates:

  <!-- Added some new variables : Start -->
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

<xsl:key name="keyTitle" match="Result" use="translate(substring(title,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
<!-- Added some new variables : End -->
<xsl:template name="Alphabets">
<Alpha>A</Alpha>
<Alpha>B</Alpha>
<Alpha>C</Alpha>
<Alpha>D</Alpha>
<Alpha>E</Alpha>
<Alpha>F</Alpha>
<Alpha>G</Alpha>
<Alpha>H</Alpha>
<Alpha>I</Alpha>
<Alpha>J</Alpha>
<Alpha>K</Alpha>
<Alpha>L</Alpha>
<Alpha>M</Alpha>
<Alpha>N</Alpha>
<Alpha>O</Alpha>
<Alpha>P</Alpha>
<Alpha>Q</Alpha>
<Alpha>R</Alpha>
<Alpha>S</Alpha>
<Alpha>T</Alpha>
<Alpha>U</Alpha>
<Alpha>V</Alpha>
<Alpha>W</Alpha>
<Alpha>X</Alpha>
<Alpha>Y</Alpha>
<Alpha>Z</Alpha>
</xsl:template>
<xsl:template name="dvt_1.rowview">
<xsl:param name="Rows" />
<xsl:for-each select="$Rows[generate-id(.) = generate-id(key('keyTitle', translate(substring(title,1,1),$smallcase,$uppercase))[1])]">
<xsl:sort select="translate(substring(title,1,1),$smallcase,$uppercase)" order="ascending" />
<xsl:if test ="string-length(title) &gt; 0">
<tr>
<td class="letterHeading" colspan="7">
<a>
<xsl:attribute name ="name">
<xsl:value-of select="translate(translate(substring(title,1,1),$smallcase,$uppercase),$smallcase, $uppercase)" />
</xsl:attribute>
</a>
<xsl:value-of select="translate(substring(title,1,1),$smallcase,$uppercase)" />
</td>
</tr>
<tr>
<td>
<xsl:variable name="thisTitle" select="translate(substring(title,1,1),$smallcase,$uppercase)"/>
<xsl:call-template name="DisplayItemRow">
<xsl:with-param name="curTitle" select="$thisTitle" />
</xsl:call-template>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="DisplayItemRow">
<xsl:param name="curTitle" />
<xsl:for-each select="key('keyTitle', translate(substring(title,1,1),$smallcase,$uppercase))[translate(substring(title,1,1),$smallcase,$uppercase) = $curTitle]">

<!-- Copied the content of OOTB Result template : Start -->
<xsl:variable name="id" select="id"/>
<xsl:variable name="url" select="url"/>

<span class="srch-Icon">
<a href="{$url}" id="{concat('CSR_IMG_',$id)}" title="{$url}">
<img align="absmiddle" src="{imageurl}" border="0" alt="{imageurl/@imageurldescription}" />
</a>
</span>
<span class="srch-Title">
<a href="{$url}" id="{concat('CSR_',$id)}" title="{$url}">
<xsl:choose>
<xsl:when test="hithighlightedproperties/HHTitle[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedproperties/HHTitle" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="title"/>
</xsl:otherwise>
</xsl:choose>
</a>
<br/>
</span>

<xsl:choose>
<xsl:when test="$IsThisListScope = 'True' and contentclass[. = 'STS_ListItem_PictureLibrary'] and picturethumbnailurl[. != '']">
<div style="padding-top: 2px; padding-bottom: 2px;">
<a href="{$url}" id="{concat('CSR_P',$id)}" title="{title}">
<img src="{picturethumbnailurl}" alt="" />
</a>
</div>
</xsl:when>
</xsl:choose>
<div class="srch-Description">
<xsl:choose>
<xsl:when test="hithighlightedsummary[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedsummary" />
</xsl:call-template>
</xsl:when>
<xsl:when test="description[. != '']">
<xsl:value-of select="description"/>
</xsl:when>
</xsl:choose>
</div >
<p class="srch-Metadata">
<span class="srch-URL">
<a href="{$url}" id="{concat('CSR_U_',$id)}" title="{$url}" dir="ltr">
<xsl:choose>
<xsl:when test="hithighlightedproperties/HHUrl[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedproperties/HHUrl" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="url"/>
</xsl:otherwise>
</xsl:choose>
</a>
</span>
<xsl:call-template name="DisplaySize">
<xsl:with-param name="size" select="size" />
</xsl:call-template>
<xsl:call-template name="DisplayString">
<xsl:with-param name="str" select="author" />
</xsl:call-template>
<xsl:call-template name="DisplayString">
<xsl:with-param name="str" select="write" />
</xsl:call-template>
<xsl:call-template name="DisplayCollapsingStatusLink">
<xsl:with-param name="status" select="collapsingstatus"/>
<xsl:with-param name="urlEncoded" select="urlEncoded"/>
<xsl:with-param name="id" select="concat('CSR_CS_',$id)"/>
</xsl:call-template>
</p>

<!-- Copied the content of OOTB Result template : End -->

</xsl:for-each>
</xsl:template >

<xsl:template name="Header">
<tr>
<th>Title</th>
</tr>
</xsl:template>

<xsl:template name="Footer">
<tr>
<th>Title</th>
</tr>
</xsl:template>
Modified Templates:
 <xsl:template name="dvt_1.body">
<!-- Added some more new variables : Start-->
<xsl:variable name="Rows" select="All_Results/Result" />
<xsl:variable name="dvt_RowCount" select="count($Rows)" />
<xsl:variable name="IsEmpty" select="$dvt_RowCount = 0" />
<!-- Added some more new variables : Start-->

<div class="srch-results">
<xsl:if test="$ShowActionLinks">
<div class="srch-sort">
<xsl:value-of select="$ResultsBy" />
<xsl:if test="$ViewByUrl">
|
<a href ="{$ViewByUrl}" id="CSR_RV" title="{$ViewByValue}">
<xsl:value-of select="$ViewByValue" />
</a>
</xsl:if>
<xsl:if test="$AlertMeLink">
|
<span class="srch-alertme" >
<a href ="{$AlertMeLink}" id="CSR_AM2" title="{$AlertMeText}">
<img style="vertical-align: middle;" src="/_layouts/images/bell.gif" alt="" border="0"/>
<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
<xsl:value-of select="$AlertMeText" />
</a>
</span>
</xsl:if>
<xsl:if test="string-length($SrchRSSLink) &gt; 0">
|
<a type="application/rss+xml" href ="{$SrchRSSLink}" title="{$SrchRSSText}" id="SRCHRSSL">
<img style="vertical-align: middle;" border="0" src="/_layouts/images/rss.gif" alt=""/>
<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
<xsl:value-of select="$SrchRSSText"/>
</a>
</xsl:if>
</div>
<br />
<br />
</xsl:if>
</div>

<!-- Added to render the A-Z Navigation Bar : Start-->
<ul>

<xsl:variable name="AlphabetNodes">
<xsl:call-template name="Alphabets"></xsl:call-template>
</xsl:variable >

<xsl:variable name ="AlphabetName">
<xsl:apply-templates select="msxsl:node-set($AlphabetNodes)/Alpha">
<xsl:sort select="." order ="ascending"/>
</xsl:apply-templates>
</xsl:variable>

<xsl:variable name="TitleNames">
<xsl:for-each select="$Rows[generate-id(.) = generate-id(key('keyTitle', translate(substring(title,1,1),$smallcase,$uppercase))[1])]">
<xsl:value-of select="translate(substring(title,1,1),$smallcase,$uppercase)" />
</xsl:for-each >
</xsl:variable>

<xsl:for-each select="msxsl:node-set($AlphabetNodes)/Alpha">
<xsl:if test ="position() &lt;= count(msxsl:node-set($AlphabetNodes)/Alpha)">
<xsl:variable name ="char" select ="child::node()[position()]"/>
<li style="display:inline;list-style-type:none;padding-right:3px;">
<xsl:choose>
<xsl:when test="contains($TitleNames,$char)">
<span>
<a>
<xsl:attribute name ="href">
#<xsl:value-of select ="child::node()[position()]"/>
</xsl:attribute>
<xsl:value-of select ="child::node()[position()]"/>
</a>
</span>
</xsl:when >
<xsl:otherwise >
<span class="empty">
<xsl:value-of select ="child::node()[position()]"/>
</span>
</xsl:otherwise>
</xsl:choose >
</li>
</xsl:if>
</xsl:for-each >

</ul>
<!-- Added to render the A-Z Navigation Bar : End-->

<div class="directoryListing">
<table class="standardDataTable">
<xsl:call-template name="Header" />
<xsl:call-template name="dvt_1.rowview">
<xsl:with-param name="Rows" select="$Rows" />
</xsl:call-template>
<xsl:call-template name="Footer"/>
</table >
</div >
<xsl:call-template name="DisplayMoreResultsAnchor" />
</xsl:template>

6 comments:

Anonymous,  September 20, 2010 at 4:31 AM  

Hi,

I think it is a solution that approaches my need.

you do not sort all the results of research, but you sorting the results of the current page of results.

you think it is possible to sort ALL the search results??

Maxime

Sandeep September 20, 2010 at 6:58 AM  

Its possible if you get the complete dataset but I dont think so that will be idle as some keywords can return thousands of row.. and on top of trying sorting them can take minutes before page loads.

Siva Subramanian March 10, 2011 at 1:12 PM  

I have a SharePoint Site Collection with regional settings changed to dd/mm/yyyy overall, all date picker controls change and I get the dd/mm/yyyy format.

I have an Enterprise Search Center in which we have the Advanced Search, where one can search for all content based on Created or Modified Date. Now, this continues to only take mm/dd/yyyy format of dates inspite of that site's regional settings being changed to dd/mm as well.

How do we change this and make all the date parameters in the Advanced Search work on dd/mm/yyyy?


also in free text when i search date (dd/mm/yyyy) its not returning any values.

let me know i need to do any setting on metadata propertis.

waiting for your valuable response Asap.

Karthick S April 16, 2011 at 6:29 AM  

Any solution on the Dd/MM Search Requirement?

Karthick S April 16, 2011 at 6:30 AM  

Search Center only seems to be understanding mm/dd dates and not dd/mm - can you help on this?

Sandeep April 16, 2011 at 7:25 AM  

Hi Kartik ,

Microsoft consistently “hard-code” date formats. I will suggest you to provide end-user date picker control for date range searches to avoid typing wrong date format.

Also if are bound to use Free-text , you can use Jquery to detect the date format and convert it over to mm/dd/yyyy format, before user hit the search button.