Saturday, August 6, 2011

Facebook like Autosuggest in Asp.net

This article is about using AjaxToolKit AutoCompleteExtender, to make Facebook like Autosuggest in asp.net. To use AutoCompleteExtender is simple, but we can modify the code little bit and make it more user friendly. Check out following Image. (Download Demo code for better understanding.)

Note: Democode is developed in VS2010 and .net framework 4.0

AutoComplete extender can be used to extend behaviour of any ASP.NET TextBox control. Ajaxtoolkit autocomplete extender associates textbox control with a popup panel to display words which begins with the prefix that is entered into the text box. We can define the minimum length of charachters, after which extender displays a popup containing words or phrases that start with that value.

</div> </div><h2> AutoComplete Demonstration</h2> Type some characters in this textbox. The web service returns names which contains text you have typed. <table> <tbody> <tr> <td> <asp:textbox autocomplete="off" id="txtAutoComplete" runat="server" width="300"></asp:textbox></td> <td><div id="divLoading" style="display: none;"> Loading...</div> </td> </tr> </tbody></table> <ajaxtoolkit:autocompleteextender behaviorid="AutoCompleteEx" completioninterval="500" completionlistcssclass="completionListClass" completionlisthighlighteditemcssclass="CompletionListHighlightedItemClass" completionlistitemcssclass="completionlistItemClass" completionsetcount="0" delimitercharacters=";, :" enablecaching="true" id="autoComplete1" minimumprefixlength="2" onclienthidden="ListPopulated" onclientitemselected="onSelection" onclientpopulated="ItemSelected" onclientpopulating="ListPopulating" runat="server" servicemethod="GetCompletionList" servicepath="AutoComplete.asmx" showonlycurrentwordincompletionlistitem="true" targetcontrolid="txtAutoComplete"> <animations> <onshow> <sequence> <%-- Make the completion list transparent and then show it --%> <opacityaction opacity="0"> <hideaction visible="true"> <%--Cache the original size of the completion list the first time the animation is played and then set it to zero --%> <scriptaction script=" // Cache the size and setup the initial size var behavior = $find('AutoCompleteEx'); if (!behavior._height) { var target = behavior.get_completionList(); behavior._height = target.offsetHeight - 2; target.style.height = '0px'; }"> <%-- Expand from 0px to the appropriate size while fading in --%> <parallel duration=".4"> <fadein> <length endvaluescript="$find('AutoCompleteEx')._height" propertykey="height" startvalue="0"> </length></fadein></parallel> </scriptaction></hideaction></opacityaction></sequence> </onshow> <onhide> <;%-- Collapse down to 0px and fade out --%>; <parallel duration=".4"> <fadeout> <length endvalue="0" propertykey="height" startvaluescript="$find('AutoCompleteEx')._height"> </length></fadeout></parallel> </onhide> </animations> </ajaxtoolkit:autocompleteextender> <%-- Prevent enter in textbox from causing the collapsible panel from operating --%> <input style="display: none;" type="submit" /> <div id="divAddressDetails"> </div> </div>

To Make AutoExtender work, we need to define certain properties.
  1. TargetControlID: The TextBox control where the user types content to be automatically completed.
  2. ServicePath: The path to the web service that the extender will pull the word\sentence completions from. If this is not provided, the service method should be a page method.
  3. ServiceMethod - The web service method to be called. The signature of this method must match the following:
    [System.Web.Services.WebMethod]
    [System.Web.Script.Services.ScriptMethod]
    public string[] YourFunctionName(string prefixText,int count)
    

    Syntax of the function should remain same.
  4. CompletionListCssClass - Css Class that will be used to style the completion list flyout.
  5. CompletionListItemCssClass - Css Class that will be used to style an item in the AutoComplete list flyout.
  6. CompletionListHighlightedItemCssClass - Css Class that will be used to style a highlighted item in the AutoComplete list flyout.
(Refer DEMO CODE for better Understanding...)

In above HTML Autocompletete extender; we can display loading image; this will make user understand that something is happening behind the screen. We have used three properties to display & Hide loading image and to display YELLOW background for the text as in above screen shot...
  1. OnClientPopulating: This adds event handler to Client side populating event. In our demo we have used ListPopulating function as event handler, we use this handler to display loading image, which is as follows.

    function ListPopulating(source, e) {
       window.document.getElementById('divLoading').style.display = "";
      
       var textboxControl = window.document.getElementById(source.get_element().id);
       // Get the textbox control.
      
       textboxControl.style.background = "url(Images/loader.gif) no-repeat right";
      //Above code displays loading image inside text box...
                    }
    
  2. OnClientHidden: This adds event handler to Client side hidden event of AutoExtentender. This handler gets fired when Autocomplete popup goes hidden. We have used ListPopulated function to handle this event. We use this event to hide loading image.

    function ListPopulated(source, e) {
    
      window.document.getElementById('divLoading').style.display = "none";
                        
      var textboxControl = window.document.getElementById(source.get_element().id); 
      // Get the textbox control.
                        
      textboxControl.style.background = "";
      }


  3. OnClientPopulated: This event handler can be used when Autosuggest list is populated. We have used this event handler to display YELLOW background in typed text. Check out above screenshot. Function name for this event is ItemSelected, this JavaScript function is as follows.

    function ItemSelected(source, e) {
       window.document.getElementById('divLoading').style.display = "none";
       var customers = source.get_completionList().childNodes;
       var searchText = source.get_element().value;
    
       for (var i = 0; i < customers.length; i++) {
    
       var customer;//  eval('(' + customers[i]._value + ')');
    
       customers[i].innerHTML = customers[i].innerHTML.replace(new RegExp('(' + searchText + ')', 'gi'), "$1");
    
       //We can modify the innerHTML if we want to display more information.
       // e.g. some logo or image
            }  
       }
    

Apart from HTML and javascript we used a webmethod naming GetCompletionList which is as follows


[WebMethod]
    public string[] GetCompletionList(string prefixText, int count)
    {

        //string sql = "WRITE SQL QUERY with Like Statement and use prefix text e.g. PartnerName like '%" + prefixText + "%'";

        //SqlDataAdapter da = new SqlDataAdapter(sql, "ConnectionString");
       
        DataTable dt = DT;// new DataTable();
        DataRow [] dr = dt.Select("Name LIKE '%" + prefixText + "%'");
        //    da.Fill(dt);
        //    da.Dispose();
        
        if (count == 0)
        {
            count = dr.Length;
            //count = dt.Rows.Count;
        }

       
        List items = new List(count);
        for (int i = 0; i < count; i++)
        {
            string value = dr[i]["City"].ToString() + "|" + dr[i]["State"].ToString() + "|" + dr[i]["Country"].ToString() + "|" + dr[i]["PostalCode"].ToString();
            var Items = AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(dr[i]["Name"].ToString(), value);
            //Using this we can send Name, Value pair client side. 
            //Value can be used to display related data of selected Name.

            //string value = dt.Rows[i]["City"].ToString() + "|" + dt.Rows[i]["State"].ToString() + "|" + dt.Rows[i]["Country"].ToString() + "|" + dt.Rows[i]["PostalCode"].ToString();
            //var items1 = AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(dt.Rows[i]["Name"].ToString(), value);

            items.Add(Items);
        }
        

        return items.ToArray();
    }

//Ignore above string string tag it is coming due to some editor issue of auto completing tags, some syntax issue.

Check out follwing screen shot, on selection of User we are displaying his/her information. (Note that we have created Name-Value pair in above code to display the information in following screen shot format.)


Now to display Selected User related address information as in the Screen shot, we used event handler of AutoCompleteExtender naming OnClientItemSelected
  • OnClientItemSelected: Handler to attach to the client-side itemSelected event. We used function naming onSelection to display Address details, this JavaScript function is as follows
function onSelection(source, e) {

var htmlString = "
Address Details " + "
City" + e._value.split("|")[0] + "
State" + e._value.split("|")[1] + "
Country" + e._value.split("|")[2] + "
Postal Code" + e._value.split("|")[3] + "
"; // Above alignement might disorder due to HTML rules of blogger, make sure in coding you handle it. window.document.getElementById('divAddressDetails').innerHTML = htmlString; var customers = source.get_completionList().childNodes; //Following is used to put value in Textbox, as we are overriding it to display address. if (document.all) { window.document.getElementById(source.get_element().id).value = e._item.innerText; } else window.document.getElementById(source.get_element().id).value = e._item.textContent; }

We are done with development of Facebook Like Autosuggest in Asp.net.
Donwload demo code here --> Facebook Like AutoSuggest in Asp.net.zip
Submit this story to DotNetKicks