Search This Blog

Monday, March 14, 2011

Implementing type ahead search using sharepoint javascript client OM : SharePoint 2010

While working on any searching functionality in sharepoint , one of the common requirements these days is to be able to implement a type ahead search which gives the search results to the user instantaneously,as soon as he types anything in the search box, without a postback.


We came across this requirement in one of our projects where we had to search documents in a document library in sharepoint using type ahead search.

In order to implement this , I used the sharepoint javascript client OM. In order to use the sharepoint
javascript client OM,we need to have a reference to the file 'SP.js' which comes with sharepoint and exists in the 14 hive's layouts folder.

If you are using an application page (as is the case in this article), we need not include any explicit reference to this file as it is already included in the sharepoint default master page.

In order to implement this, I created an application page and placed the HTML as well as javascript on it.

The HTML consists of a simple textbox to be used as a searchbox and a <span> tag to display the search results.
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<span><h3>Getting list items using type ahead search</h3></span>
<br /><br />
 
<div id="searchDiv"> 
         
<div>               
<label for="txtTypeAhead">Filename:</label>               
<input type="text" id="txtTypeAhead" />           
</div>      
    
<br />

<div>              
<span id="searchResultsLabel" />           
</div>  
        
<div/>  

</div>

</asp:Content>

I created a javascript method GetSearchResults() on the application page and associate it with the onkeyup event of the search box using the following code in the 'OnPreRender' method in the code behind for the application page.

 protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            string script= @" var searchResults;var txtBox = document.getElementById('txtTypeAhead');
                            if (txtBox) {
                            document.getElementById('txtTypeAhead').onkeyup=function (event) { GetSearchResults(); };
                            }";
            this.Page.ClientScript.RegisterStartupScript(this.GetType(),"typeahead",script,true);

        }

Once I have created this association, I added the code in the 'GetSearchResults()' method to get the results from the document library using javascript Client OM:

<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript">
//method that will be called when the text is changed in the search box.
//This method composes a CAML query to be run on the document library and returns the results by firing the query using
//'executeQueryAsync' to get results without postback

    function GetSearchResults() {
        var ctx = new SP.ClientContext.get_current();
        //get document library
        var docLib = ctx.get_web().get_lists().getByTitle('Type_Ahead_Test_Documents');
        //compose CAML query
        var query = new SP.CamlQuery();
        query.set_viewXml("<View><Query><Where><Contains><FieldRef Name='FileLeafRef'/><Value Type='Text'>" + document.getElementById('txtTypeAhead').value + "</Value></Contains></Where></Query></View>");

        //Get results
        searchResults = docLib.getItems(query);

        //To load results on client
        ctx.load(searchResults);

        //this query fires the request to the server to get results
        ctx.executeQueryAsync(getSearchResultsSuccess, getSearchResultsFailure);
    }

    //Method to be executed on success
    function getSearchResultsSuccess(sender, args) {      
        document.getElementById('searchResultsLabel').innerHTML = '';
        var resultEnumerator = searchResults.getEnumerator();
        while (resultEnumerator.moveNext()) {          
            document.getElementById('searchResultsLabel').innerHTML += resultEnumerator.get_current().get_item("FileLeafRef") + '<br />';
        }
    }

    //Method to be executed on failure
    function getSearchResultsFailure(sender, args) {
        alert('Fetch search results failure. \nError: ' + args.get_message() + '\ndetails: ' + args.get_stackTrace());
    }
 </script>


</asp:Content>

Now, I build the solution and deploy this application page and voila !! There's my type ahead search working.!!

Here's the complete code for the application page and the code behind:

TypeAheadSearch.aspx:

<%@ Assembly Name="Blog_Test_Project, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5518611c63730c3d" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TypeAheadSearch.aspx.cs" Inherits="Blog_Test_Project.Layouts.Blog_Test_Project.TypeAheadSearch" DynamicMasterPageFile="~masterurl/default.master" %>


<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">

<script type="text/javascript">
//method that will be called when the text is changed in the search box.
//This method composes a CAML query to be run on the document library and returns the results by firing the query using
//'executeQueryAsync' to get results without postback


    function GetSearchResults() {
        var ctx = new SP.ClientContext.get_current();


        //get document library
        var docLib = ctx.get_web().get_lists().getByTitle('Type_Ahead_Test_Documents');

        //compose CAML query
        var query = new SP.CamlQuery();
        query.set_viewXml("<View><Query><Where><Contains><FieldRef Name='FileLeafRef'/><Value Type='Text'>" + document.getElementById('txtTypeAhead').value + "</Value></Contains></Where></Query></View>");

        //Get results
        searchResults = docLib.getItems(query);


        //To load results on client
        ctx.load(searchResults);


        //this query fires the request to the server to get results
        ctx.executeQueryAsync(getSearchResultsSuccess, getSearchResultsFailure);
    }


    //Method to be executed on success
    function getSearchResultsSuccess(sender, args) {       


        document.getElementById('searchResultsLabel').innerHTML = '';


        var resultEnumerator = searchResults.getEnumerator();
        while (resultEnumerator.moveNext()) {          
            document.getElementById('searchResultsLabel').innerHTML += resultEnumerator.get_current().get_item("FileLeafRef") + '<br />';

        }
    }

    //Method to be executed on failure
    function getSearchResultsFailure(sender, args) {

        alert('Fetch search results failure. \nError: ' + args.get_message() + '\ndetails: ' + args.get_stackTrace());
    }


 </script>


</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<span><h3>Getting list items using type ahead search</h3></span>
<br /><br />
 
<div id="searchDiv"> 
         
<div>               
<label for="txtTypeAhead">Filename:</label>               
<input type="text" id="txtTypeAhead" />           
</div>      
    
<br />

<div>              
<span id="searchResultsLabel" />           
</div>  
        
<div/>  

</div>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
</asp:Content>

<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
Application Page
</asp:Content>

<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >
My Application Page
</asp:Content>


TypeAheadSearch.aspx.cs

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace Blog_Test_Project.Layouts.Blog_Test_Project
{
    public partial class TypeAheadSearch : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }


        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            string script= @" var searchResults;var txtBox = document.getElementById('txtTypeAhead');
                            if (txtBox) {
                            document.getElementById('txtTypeAhead').onkeyup=function (event) { GetSearchResults(); };
                            }";
            this.Page.ClientScript.RegisterStartupScript(this.GetType(),"typeahead",script,true);

        }
    }
}


 

No comments:

Post a Comment