I recently worked on a project where the client wanted to have two new tabs in the search center along with the default All Sites and People tabs: One to search only images and the other to search all office documents and PDFs. So, basically the requirement is to filter results by their file type. Best thing about Search in MOSS is a lot of customization can be achieved without writing a single line of code. I’ll be going through the setup for Image search; similar steps are required for documents.
Below is the screenshot of what we are trying to achieve.
As you can see, results contain only images. I had to tweak XSLT little bit to show the thumb nail type preview of the image and also to pretty up the text associated with the results. Without any further ado let’s see how easy it is to achieve something like this.
SSP Settings:
Content Sources: In my case Local Office SharePoint Servers is the only content source.
Content Sources and Crawl Schedules
Add the required content sources. Be advised that the search results XML will be different for data coming from different content sources. Schema will be the same but the data is formatted in a different way. This needs some attention if doing any XSLT changes.
File Types
Any file type that needs to be part of content index should be listed in the “Manage File Types” list. The default SSP configuration includes all major file types but surprisingly didn’t include any of the Image file types. New file types can be added by navigating to File Types -> New File Type. “Jpg”, “Jpeg”, and “bmp” were added as new file types to include in the content index.
Metadata property mappings:
Any metadata property that needs to be part of search results should be configured to be used in scopes. One metadata property of particular interest for us is “FileExtension”. “FileExtension” is used to setup scopes to get results of desired file types. By default, this property is not included in scopes. To change this, in search settings select “Metadata property mappings” and select “FileExtension”. Select the checkbox to include the property in scopes and click Ok.
Scopes
New scope called “Images” needs to be created, follow the steps below:
· Navigate to Scopes under Search Settings and click “New Scope”.
· Enter “Images” for Title. For Target Results Page option select “Specify a different page for searching this scope” and click Ok.
· Images scope will come up in the scopes list and it will indicate to add rules. Click “Add Rules”.
· Under “Scope Rule Type” section select Property Query.
· Select “FileExtension” in the Add property restrictions dropdown and provide the desired file extension in the “=” text box.
· For Behavior section, keep the default selected Include radio button and click Ok to create the rule.
· Follow the same steps to add all the desired file extensions. Note that every file extension should be setup as a separate rule. I went with two rules one for JPEG files and the other for BMP files.
Site Collection Settings:
Since the desired scopes were setup at the SSP level they will be available for all the site collections under that SSP. They can be seen under Top Level Site Settings -> Site Collection Administration -> Search Scopes. Scopes available for a site collection are grouped as Display Groups. For our setup we’ll create two new display groups, one for Documents and one for Images. Steps to setup display groups are listed below:
· Navigate to Top Level Site Settings -> Search Scopes.
· Click “New Scope”.
· Enter Images for Title.
· Check the check box next to Images scope. Default scope should be set to Images automatically.
· Click Ok to create the display group.
Search Center:
A custom tab titled Images and two pages, one for Search and another for search results, are created in the search center. In the miscellaneous section of the Search box web part properties, set Target Search Results Page to the new page created and set Scope Display Group to Images.
Similarly, configure miscellaneous section of Search Core Results web part to apply Images Scope.
I deleted High Confidence results web part from the image search results page since it doesn’t make much sense here.
XSLT
Below is the XSL that takes care of styling, Happy Searching 🙂
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:output method="html" indent="no"/>
<xsl:decimal-format NaN=""/>
<xsl:param name="FileName" />
<xsl:param name="dvt_apos">'</xsl:param>
<xsl:param name="ResultsBy" />
<xsl:param name="ViewByUrl" />
<xsl:param name="ViewByValue" />
<xsl:param name="IsNoKeyword" />
<xsl:param name="IsFixedQuery" />
<xsl:param name="ShowActionLinks" />
<xsl:param name="MoreResultsText" />
<xsl:param name="MoreResultsLink" />
<xsl:param name="CollapsingStatusLink" />
<xsl:param name="CollapseDuplicatesText" />
<xsl:param name="AlertMeLink" />
<xsl:param name="AlertMeText" />
<xsl:param name="SrchRSSText" />
<xsl:param name="SrchRSSLink" />
<xsl:param name="ShowMessage" />
<xsl:param name="IsThisListScope" />
<xsl:param name="DisplayDiscoveredDefinition" select="True" />
<xsl:variable name="dvt_1_automode">0</xsl:variable>
<!– XSL transformation starts here –>
<xsl:template match="/">
<xsl:if test="$AlertMeLink">
<input type="hidden" name="P_Query" />
<input type="hidden" name="P_LastNotificationTime" />
</xsl:if>
<xsl:choose>
<xsl:when test="$IsNoKeyword = ‘True’" >
<xsl:call-template name="dvt_1.noKeyword" />
</xsl:when>
<xsl:when test="$ShowMessage = ‘True’">
<xsl:call-template name="dvt_1.empty" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="AllResultsDiscoveredDefinitions">
<xsl:with-param name="AllResults" select="/All_Results/DiscoveredDefinitions" />
</xsl:call-template>
<xsl:call-template name="dvt_1.body"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!– When there is keyword to issue the search –>
<xsl:template name="dvt_1.noKeyword">
<span class="srch-description">
<xsl:choose>
<xsl:when test="$IsFixedQuery">
Please set the ‘Fixed Query’ property for the webpart.
</xsl:when>
<xsl:otherwise>
Enter one or more words to search for in the search box.
</xsl:otherwise>
</xsl:choose>
</span>
</xsl:template>
<!– When empty result set is returned from search –>
<xsl:template name="dvt_1.empty">
<div class="srch-sort">
<xsl:if test="$AlertMeLink and $ShowActionLinks">
<span class="srch-alertme" >
<a href ="{$AlertMeLink}" id="CSR_AM1" title="{$AlertMeText}">
<img style="vertical-align: middle;" src="/_layouts/images/bell.gif" alt="" border="0"/>
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
<xsl:value-of select="$AlertMeText" />
</a>
</span>
</xsl:if>
<xsl:if test="string-length($SrchRSSLink) > 0 and $ShowActionLinks">
<xsl:if test="$AlertMeLink">
|
</xsl:if>
<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">&nbsp;</xsl:text>
<xsl:value-of select="$SrchRSSText"/>
</a>
</xsl:if>
</div>
<br/>
<br/>
<span class="srch-description" id="CSR_NO_RESULTS">
No results matching your search were found.
<ol>
<li>Check your spelling. Are the words in your query spelled correctly?</li>
<li>Try using synonyms. Maybe what you’re looking for uses slightly different words.</li>
<li>Make your search more general. Try more general terms in place of specific ones.</li>
<li>Try your search in a different scope. Different scopes can have different results.</li>
</ol>
</span>
</xsl:template>
<xsl:template name="dvt_1.body">
<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">&nbsp;</xsl:text>
<xsl:value-of select="$AlertMeText" />
</a>
</span>
</xsl:if>
<xsl:if test="string-length($SrchRSSLink) > 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">&nbsp;</xsl:text>
<xsl:value-of select="$SrchRSSText"/>
</a>
</xsl:if>
</div>
<br />
<br />
</xsl:if>
<xsl:apply-templates />
</div>
<xsl:call-template name="DisplayMoreResultsAnchor" />
</xsl:template>
<xsl:template match="Result">
<xsl:variable name="id" select="id"/>
<xsl:variable name="url" select="url"/>
<tr>
<td width="100%" class="ms-vb">
<a href="{url}">
<xsl:choose>
<xsl:when test="contains(url, ‘.jpg’)">
<img src="{url}" width="100" height="100"></img>
</xsl:when>
<xsl:when test="contains(url, ‘.jpeg’)">
<img src="{url}" width="100" height="100"></img>
</xsl:when>
<xsl:when test="contains(url, ‘.bmp’)">
<img src="{url}" width="100" height="100"></img>
</xsl:when>
<xsl:when test="contains(url, ‘.gif’)">
<img src="{url}" width="100" height="100"></img>
</xsl:when>
<xsl:otherwise>
<img src="http://pbc_workflow_la/Docs/Documents/PreviewImageNA.gif" width="100" height="100"></img>
</xsl:otherwise>
</xsl:choose>
</a>
</td>
</tr>
<tr>
<td width="100%" class="ms-vb">
<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>
</td>
</tr>
<tr>
<td width="100%" class="ms-vb">
Uploaded By:
<xsl:value-of select="author" />
<br />Date:
<xsl:value-of select="write" />
<br />File Location:
<a href="{sitename}" style="color:#008800">
<xsl:value-of select="sitename"/>
</a>
<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 ><hr style="color:#E0DED5; height:1px" />
<br />
</td>
</tr>
</xsl:template>
<xsl:template name="HitHighlighting">
<xsl:param name="hh" />
<xsl:apply-templates select="$hh"/>
</xsl:template>
<xsl:template match="ddd">
…
</xsl:template>
<xsl:template match="c0">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c1">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c2">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c3">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c4">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c5">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c6">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c7">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c8">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template match="c9">
<b style="color:#0000CC">
<xsl:value-of select="."/>
</b>
</xsl:template>
<xsl:template name="AllResultsDiscoveredDefinitions">
<xsl:param name="AllResults" />
<xsl:variable name="FoundIn" select="$AllResults/DDFoundIn" />
<xsl:variable name="DDSearchTerm" select="$AllResults/DDSearchTerm" />
<xsl:if test="$DisplayDiscoveredDefinition = ‘True’ and string-length($DDSearchTerm) > 0">
<script language="javascript">
function ToggleDefinitionSelection()
{
var selection = document.getElementById("definitionSelection");
if (selection.style.display == "none")
{
selection.style.display = "inline";
}
else
{
selection.style.display = "none";
}
}
</script>
<div>
<a href="#" onclick="ToggleDefinitionSelection(); return false;" style="font-size:12pt;color:#0000CC">
What people are saying about <b>
<xsl:value-of select="$DDSearchTerm"/>
</b>
</a>
<div id="definitionSelection" class="srch-Description" style="display:none;">
<xsl:for-each select="$AllResults/DDefinitions/DDefinition">
<br/>
<xsl:variable name="DDUrl" select="DDUrl" />
<xsl:value-of select="DDStart"/>
<b>
<xsl:value-of select="DDBold"/>
</b>
<xsl:value-of select="DDEnd"/>
<br/>
<xsl:value-of select="$FoundIn"/>
<a href="{$DDUrl}">
<xsl:value-of select="DDTitle"/>
</a>
</xsl:for-each>
</div>
</div>
<br />
</xsl:if>
</xsl:template>
<xsl:template match="All_Results/DiscoveredDefinitions">
</xsl:template>
<!– The "view more results" for fixed query –>
<xsl:template name="DisplayMoreResultsAnchor">
<xsl:if test="$MoreResultsLink">
<a href="{$MoreResultsLink}" id="CSR_MRL">
<xsl:value-of select="$MoreResultsText"/>
</a>
</xsl:if>
</xsl:template>
</xsl:stylesheet>