Sharepoint Insight by Namwar Rizvi

Sharepoint Tips, Tricks and inside knowledge from real world experience by Namwar Rizvi

Archive for the ‘Search’ Category

How to create a general purpose Search Results ticker in SharePoint by jQuery

Posted by namwar on May 22, 2010


Business Problem

Display SharePoint search results as a scrolling ticker.

Solution:

SharePoint has two very powerful web parts Search Core Results WebPart and Content Editor WebPart . By combining these two web parts along with some jQuery and jCarousel Lite plug-in we can achieve desired results very quickly. The technique described here is very generic and can be used in CQWP and other web parts too.

What we are doing is quite simple. We use jCarousel plugin for jQuery to scroll the elements of HTML unordered list i.e. <ul>. To achieve this we need an HTML code similar to following

<div class="wrapper">
   <ul id="listticker">
       <li>Item 1</li>
       <li>Item 2</li>
       <li>Item 3</li>
   </ul>
 </div>

We generate this code by updating the XSL of Search Core Results Web part.

Step 1 : Setup required javascript libraries:

  • jQuery: No need to download, we will use it from Google CDN.
  • jCarousel Lite: Please download it from here and store it either under _layouts folder or in a document library at your sharepoint web.

Step 2 : Add Content Editor Web Part (CEWP):

Add CEWP on your target page. Edit the CEWP and paste following code by clicking on Source Editor:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

//Replace the value of src attribute with the path of your jcarousellite.js file
<script type="text/javascript" src="http://moss-server/SearchCenter/Resources/jcarousellite/jcarousellite.js"></script>

<script type="text/javascript">
$(function() {
	$(".wrapper").jCarouselLite({
		vertical: true,
		hoverPause:true,
		visible: 1,
		auto:3000,
		speed:1000
	});
});
</script>

Step 3 : Add Search Core Results Web Part :

Add Search Core Results web part. Configure the web part as you wish. For example, I used it to display all documents by using  Fixed Keyword Query functionality as follows:

  • Fixed Keyword Query = IsDocument:1
  • Cross-Web Part query ID = Query 2

Step 4 : Update XSL of Search Core Results Web Part :

Click XSL Editor and paste following XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<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:param name="NoFixedQuery" />
<xsl:param name="NoKeyword" />
<xsl:param name="NoResults" />
<xsl:param name="NoResults1" />
<xsl:param name="NoResults2" />
<xsl:param name="NoResults3" />
<xsl:param name="NoResults4" />
<xsl:param name="DefinitionIntro" />

<!-- When there is keywory to issue the search -->
<xsl:template name="dvt_1.noKeyword">
  <span class="srch-description">
  <xsl:choose>
  <xsl:when test="$IsFixedQuery">
      <xsl:value-of select="$NoFixedQuery" />
  </xsl:when>
   <xsl:otherwise>
      <xsl:value-of select="$NoKeyword" />
   </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">&amp;nbsp;</xsl:text><xsl:value-of select="$AlertMeText" /></a>
    </span>
  </xsl:if>

  <xsl:if test="string-length($SrchRSSLink) &gt; 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">&amp;nbsp;</xsl:text><xsl:value-of select="$SrchRSSText"/></a>
  </xsl:if>
 </div>
 <br/> <br/>

  <span class="srch-description" id="CSR_NO_RESULTS">
   <xsl:value-of select="$NoResults" />

    <ol>
    <li><xsl:value-of select="$NoResults1" /></li>
    <li><xsl:value-of select="$NoResults2" /></li>
    <li><xsl:value-of select="$NoResults3" /></li>
    <li><xsl:value-of select="$NoResults4" /></li>
    </ol>
  </span>
</xsl:template>

<!-- Main body template. Sets the Results view (Relevance or date) options -->
<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">&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 class="wrapper">
			<ul id="listticker">
				<xsl:apply-templates />
			</ul>

	</div>

  </div>

  <xsl:call-template name="DisplayMoreResultsAnchor" />

</xsl:template><!-- This template is called for each result -->
<xsl:template match="Result">
  <xsl:variable name="id" select="id"/>
  <xsl:variable name="url" select="url"/>
	<li>
  <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>
	</li>
</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><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c1">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c2">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c3">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c4">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c5">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c6">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c7">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c8">
    <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="c9">
    <b><xsl:value-of select="."/></b>
</xsl:template>

<!-- The size attribute for each result is prepared here -->
<xsl:template name="DisplaySize">
  <xsl:param name="size" />
  <xsl:if test='string-length($size) &gt; 0'>
   <xsl:if test="number($size) &gt; 0">
   -
    <xsl:choose>
     <xsl:when test="round($size div 1024) &lt; 1"><xsl:value-of select="$size" /> Bytes</xsl:when>
     <xsl:when test="round($size div (1024 *1024)) &lt; 1"><xsl:value-of select="round($size div 1024)" />KB</xsl:when>
     <xsl:otherwise><xsl:value-of select="round($size div (1024 * 1024))"/>MB</xsl:otherwise>
    </xsl:choose>
   </xsl:if>
  </xsl:if>
</xsl:template>

<!-- A generic template to display string with non 0 string length (used for author and lastmodified time -->
<xsl:template name="DisplayString">
  <xsl:param name="str" />
  <xsl:if test='string-length($str) &gt; 0'>
   -
   <xsl:value-of select="$str" />
  </xsl:if>
</xsl:template>

<!-- document collapsing link setup -->
<xsl:template name="DisplayCollapsingStatusLink">
    <xsl:param name="status"/>
    <xsl:param name="urlEncoded"/>
    <xsl:param name="id"/>
    <xsl:if test="$CollapsingStatusLink">
      <xsl:choose>
          <xsl:when test="$status=1">
              <br/>
              <xsl:variable name="CollapsingStatusHref" select="concat(substring-before($CollapsingStatusLink, '$$COLLAPSE_PARAM$$'), 'duplicates:&quot;', $urlEncoded, '&quot;', substring-after($CollapsingStatusLink, '$$COLLAPSE_PARAM$$'))"/>
              <span class="srch-dup">
              [<a href="{$CollapsingStatusHref}" id="$id" title="{$CollapseDuplicatesText}">
              <xsl:value-of select="$CollapseDuplicatesText"/>
              </a>]
              </span>
          </xsl:when>
      </xsl:choose>
    </xsl:if>
</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:template match="All_Results/DiscoveredDefinitions">
  <xsl:variable name="FoundIn" select="DDFoundIn" />
  <xsl:variable name="DDSearchTerm" select="DDSearchTerm" />
  <xsl:if test="$DisplayDiscoveredDefinition = 'True' and string-length($DDSearchTerm) &gt; 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;">
        <xsl:value-of select="$DefinitionIntro" /><b><xsl:value-of select="$DDSearchTerm"/></b></a>
      <div id="definitionSelection" class="srch-Description" style="display:none;">
        <xsl:for-each select="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>
  </xsl:if>
</xsl:template>

<!-- 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="dvt_1.body"/>
   </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- End of Stylesheet -->
</xsl:stylesheet>

Step 5 : Enjoy! :
Click OK and exit from edit mode. Your ticker is ready, Enjoy.

Posted in Information, JavaScript, jQuery, Search, Solutions | Tagged: , , , , , , , , , | Leave a Comment »

How to Search on Last Modified By field in SharePoint Advanced Search

Posted by namwar on April 1, 2009


If you are wondering why you are unable to find any search result for Last Modified By filed in Advanced Search of SharePoint then don’t worry, you are not alone. This is one of the bug which still exist in SharePoint 2007 Server Search engine. I have found a solution posted by Pritam Dhake ina  SharePoint forum. I have used this solution and it works like a charm.

Here are the steps to manually hook the Last Modified By field to the creawled field.

  1. Open Central administration -> Shared Services -> SharedServices (X being the number of the shared services provider for the site you are creating a mapping)  – > search settings -> metadata property mappings 
  2. Click “Modifiedby” to edit the properties 
  3. Make sure  “Include values from all crawled properties mapped” is selected
  4. Click “add mapping” and select the “Office” category from the dropdown list. 
  5. look for a property named “OFFICE:8” , click “OK
  6. Click “add mapping” and select the “ows_Last_x0020_Modified(text)” from the ALL categories dropdown list, Click “OK
  7. Make sure the box is checked “Allow this property to be used in scopes”, click “OK
  8. Click on “Crawled Properties” link on the left side of the Shared Services Administration page. 
  9. Click On the “Office” Category.
  10. The mapped property you just created should be listed in the “Mapped To” column of the Office:8(Text) category.
  11. Click on the Office:8(Text) category to view the properties.
  12. In the “name and information” section, you should see the “property Set ID:” value is  ‘F29F85E0-4FF9-1068-AB91-08002B27B3D9‘ …This is very important!!!
  13. In the “Mappings to managed properties” section the managed property you edited in steps 2 – 7 should be listed. 
  14. The box to “Include values for this property in the search index” should be checked.
  15. Click “OK” to exit this page.
  16. Open “Shared Services administration” -> “ShareservicesX” -> “Search Settings” -> “Content Sources and crawl schedules” 
  17. Click on “Local Office SharePoint Server sites” to expand the dropdown list and select “Start full crawl” 
  18. When the crawl has completed, navigate to the site collection -> click on the search tab. 
  19. Select “Advanced Search” 
  20. In the properties dropdown list select “Last Modified By
  21. Select contains
  22. Enter a name that you know has added / edited a document
  23. Click the magnifier to execute the search
  24. Get back results.

Posted in Bugs, Search, Solutions | Tagged: , , , , | 3 Comments »