Better Best Bets with JQuery

I haven’t blogged in a while because I have been crushed with both project work and dog training. The project work has exposed me to some JQuery techniques that I have wanted to learn. I have also been reviewing the new features of SharePoint 2010 search and FAST Search Server for SharePoint 2010. There are some great new features coming out with both products, features that many of my clients have been asking for. One feature that is supported by FAST and not oob with SharePoint 2010 is the Visual Best Bet, essentially a best bet that uses HTML rather than just text like the Best Bets in SharePoint 2007 (and unchanged in SharePoint 2010). I have to say, I really like JQuery. I can’t say “love” yet… I would not have gotten this far if it wasn’t for some great examples on Jan Tielens site.

SharePoint Best Bets

Best Bets

FAST Search Server 2010 for SharePoint Visual Best Bets

FAST Visual Best Bet

Creating Better Best Bets

As I was working through learning what was possible with JQuery and SharePoint it occurred to me that I could easily create the same effect with JQuery and the Lists Web Service of SharePoint 2007. (I’ll create a SharePoint 2010 example that uses the Client Object Model later.) The overview of the process is this:

  1. Create a list to hold your HTML. I called mine VBB. It has two fields: Title and Html. Create the content in the list for your Best Bets. Here is the HTML List

  2. Configure your Keywords and Best Bets. In my case I decided that if the first best bet was from this list I’d display the contents above all the other Best Bets. Here is the Keyword definition for SharePoint. The first Best Bet points to my VBB list item. Best Bet Delivered

  3. Test the search configuration by running a search for the term “SharePoint” and you should see your Keyword and Best Bets in the Bet Bets Web part. Default Best Bet

  4. Next you just have to add some logic to the page to wire up the JQuery. In my case I created a new Search Results Page Layout and added the necessary lines to refer to the JQuery files I stored in my Style Library. (Alternatively you could add the lines to the Master Page, it’s your call.) In the AdditionalPageHead content placeholder I added the following:

    <script type="text/javascript">
        $(document).ready(function(){ 
      //Fetch the Visual Best Bet if it exists 
      getBB($("div.#vbb").attr("SPID")); 
      }); 
    </script>
  5. Then I added a file I named vbb.js to the Style Library in a folder called JQuery. You’ll need to edit in in places depending on how you decide to implement your solution, but this should get you started. The function creates a query that returns the list item that matches the ID passed from the page layout. Then calls the Lists web service. My list is at the root of the site, if yours is somewhere else then you will need to change the URL parameter. Finally when the result comes back we stuff it into our div with the ID “vbb”. Here is what the file looks like:

    function getBB(id) 
    { 
    var soapEnv = 
    "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'> \ 
    <soapenv:Body> \ 
         <GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \ 
          <listName>VBB</listName> \ 
          <query> \  
           <Query> 
            <Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>" + id + "</Value></Eq></Where> 
           </Query> \  
          </query> \  
          <viewFields> \  
           <ViewFields> \  
            <FieldRef Name='Title' /> \  
            <FieldRef Name='Html' /> \  
           </ViewFields> \  
          </viewFields> \  
         </GetListItems> \  
        </soapenv:Body> \  
       </soapenv:Envelope>";
    
        $.ajax({ 
            url: "_vti_bin/lists.asmx", 
            type: "POST", 
            dataType: "xml", 
            data: soapEnv, 
            complete: processResult, 
            contentType: "text/xml; charset=\"utf-8\"" 
        }); 
    }    
    
    function processResult(xData, status) { 
        //alert(xData.responseText); 
      $(xData.responseXML).find("z\\:row").each(function() { 
                //$("#debug").append($(this).text()); 
            var liHtml = $(this).attr("ows_Html"); 
            $("#vbb").empty().append(liHtml); 
          }); 
        } 
    
  6. Finally we need to add code to the Best Bets Web part to create the conditional formatting in the event we actually find our keyword and need to create the div container that will hold the HTML from our list. Open the search results page and edit the Best Bets web part. This code adds a conditional test to see if our better best bet is in the first position. If it is it calls the “BetterBB” template, if not it displays the regular Best Bet. Locate the template that begins with

    <xsl:template match="All_Results/BestBetResults/Result">... 
    and change the entire template to:

    <xsl:template match="All_Results/BestBetResults/Result"> 
    <xsl:if test="$DisplayBB = 'True'" > 
         <xsl:choose> 
             <xsl:when test="position() = 1 and url[contains(.,'VBB')]"> 
                 <xsl:call-template name="BetterBB"> 
                     <xsl:with-param name="url" select="url"/> 
                 </xsl:call-template> 
             </xsl:when> 
             <xsl:otherwise> 
              <xsl:if test="position() <= $BBLimit" > 
              <xsl:variable name="url" select="url"/> 
              <xsl:variable name="id" select="id" /> 
              <div class="srch-BB-Result"> 
              <xsl:if test="$DisplayTitle = 'True'" > 
                <span class="srch-BestBetsTitle"> 
                 <img src="/_layouts/images/sts_site16.gif" alt="" /> 
                 <a href="{$url}" id="{concat('BBR_',$id)}"> 
                  <xsl:value-of select="title"/> 
                 </a> 
                </span> 
              </xsl:if> 
              <xsl:if test="$DisplayDescription = 'True' and description[. != '']" > 
                  <div class="srch-BB-Description"> 
                  <xsl:value-of select="description"/> 
                  </div> 
              </xsl:if> 
              <xsl:if test="$DisplayUrl = 'True'" > 
                 <span class="srch-BB-URL"> 
                 <a href="{$url}" id="{concat('BBR_U_',$id)}" dir="ltr"> 
                  <xsl:value-of select="$url"/> 
                 </a> 
                 </span> 
              </xsl:if> 
              </div> 
              </xsl:if> 
          </xsl:otherwise> 
         </xsl:choose> 
    </xsl:if>   
    </xsl:template>
  7. Then add the following template just below the previous template.

    <xsl:template name="BetterBB"> 
        <xsl:param name="url"/> 
        <xsl:element name="div"> 
            <xsl:attribute name="ID">vbb</xsl:attribute> 
            <xsl:attribute name="SPID"><xsl:value-of select="substring-after($url,'?ID=')" /></xsl:attribute> 
            <xsl:value-of select="$url" /> (<xsl:value-of select="substring-after($url,'?ID=')" />) 
        </xsl:element> 
    </xsl:template>

  8. Now you have to test everything. When you execute the query the page loads (which registers the JavaScript files). If the Best Bet web part finds the first best bet URL contains the text “VBB” then it creates the div tag with the id “vbb” and the attribute “SPID” and the ID of the list item. On page ready the JQuery function checks for the existence of the div with the ID “vbb”. If it’s there it passes the SPID to the getBB function and populates the div tag with the HTML in the list item. So in our case the list item associated with the keyword “SharePoint” renders the first Best Bet like this:

Best Bet Bet Ever

That’s it! I know that there are a lot of cool effects that I could add to make the Best Bet dance around with JQuery, but I just wanted to show the technique to render the darn thing. Feel free to embellish as you see fit.

|| Search || SharePoint 2007 || SharePoint 2010

comments powered by Disqus

Let's Get In Touch!


Ready to start your next project with us? That’s great! Give us a call or send us an email and we will get back to you as soon as possible!

+1.512.539.0322