Click here to Skip to main content
15,880,891 members
Articles / Web Development / ASP.NET

jQuery SearchBox AutoComplete Widget

Rate me:
Please Sign up or sign in to vote.
4.80/5 (10 votes)
28 Jun 2011CPOL2 min read 66.1K   3.1K   42   5
jQuery widget for autocompletion of categorized data through the hierarchies

Introduction

SearchBoxAutoComplete is auto-completion jQuery widget that enables you to search the categorized data through the hierarchies, i.e., Brand/Categories/Products or Category/Brands/Products.

Background

Many Virtual Stores are offering Products classified by Categories and Brands. Usually there are a lot of Categories, Sub-Categories and Brands, and a user has difficulties to find the appropriate Category, Brand or Product.

SearchBoxAutoComplete widget enables a user to quickly find and select the wanted Category or Brand. By entering 2 or more characters, the user can filter down the list to better matches.

SearchBoxAutoComplete1.PNG

After user selects Category, the widget offers a drop-down list with all the Brands that products of the selected Category belong.

If user selected the Brand, widget would offer drop-down list with all the Categories that Brand’s Products belong to.

SearchBoxAutoComplete2.PNG

User can select multiple items from the offered list, or enter new characters to start a new hierarchy. Results from multiple hierarchies are aggregated at the server.

Here is the sample of 2 hierarchies: categ1: brand1: brand2; categ2: brand3:

SearchBoxAutoComplete jQuery Widget

jQuery Widgets resolve the problem that jQuery Plugins have with associating an JavaScript Object with a DOM element, avoiding circular references and memory leaks.

SearchBoxAutoComplete jquery.ui.searchboxautocomplete.js” widget uses standard “jquery.ui.autocomplete.js” widget.

Instead of hacking the existing widget, SearchBoxAutoCompelete modifies the behavior of the existing widget by extending or overriding/sub-classing the widget properties, methods and events.

JavaScript
$.widget("ui.searchboxautocomplete", $.ui.autocomplete, {
	_create: function () { 
		...
	},
 	_init: function () {
		// call the base class
		$.ui.autocomplete.prototype._init.apply(this, arguments);
		this.element.bind("searchboxautocompleteclose", function () {
			self.options.offeringSecondLevel = false;
		});
		…
	}, 
	options: { 
		select: function (event, ui) { … },
		cache: {},
		autocompleteRows: [],
		separator: ": ",
		…
	} 
}

SearchBoxAutoCompleteRows widget uses Ajax JSON call to get the data from the server.

List of: AutocompleteRow { category: 'Brands', label:'Bikes', value:11 }
is serialized at the client by:

JavaScript
JSON.stringify(this.options.autocompleteRows).

At the server, it is deserialized with:

C#
var selectedRows = new JavaScriptSerializer().Deserialize<List<AutocompleteRow>>(acRows); 

Form

HTML
<form id="searchbox" action="/search/productlist" method="post">
   <input type="text" id="search" value=""/> 
   <input id="searchbutton" type="submit" value="Search"/> 
   <input type="hidden" id="selectedAutocompleteRows"  />
</form>  
JavaScript
$("#search")
    .setSearchText(autocompleteRows)
    .searchboxautocomplete({
        autocompleteRows: autocompleteRows,
        source: function (request, response) {
            var term = $.ui.searchboxautocomplete.extractLast(request.term);
            var data = this.options.getCachedData(term);
            if (data != null) {
                response(data);
                return true;
            }
            var that = this;
            this.options.lastXhr =
                $.getJSON("/Search/GetBrandsAndCategories",
                    {term:term, acRows:JSON.stringify(this.options.autocompleteRows)},
                     function (data, status, xhr) {
                        that.options.setCachedData(term, data);
                        if (xhr === that.options.lastXhr) {
                            response(data);
                        }
                    })
        },
        search: function () {
            if (term.length < 2) {
                return false;
            }
        }
    })      

Data are received from server by Ajax $.getJSON() call. Arguments sent to the server are:

  • Last search term
  • Array of already selected rows

This is done by:

JavaScript
{ term: term, acRows: JSON.stringify(this.options.autocompleteRows) } 

Data returned from the server are rendered by function response(data) called upon successful Ajax call.

Default fields are: category, label, value. You can override _renderItem function and display your fields.

Data returned from the server are in JSON format, something like this:

JavaScript
var data = [
{category:"Categories", label:"Mountain Bikes", value:"1"},
{category:"Categories", label:"Road Bikes", value:"2"},
{category:"Categories", label:"Touring Bikes", value:"3"},
{category:"Brands", label:"Mountain Bikes", value:"12"}
]

Here is the MVC 2.0 server method that returns the data in JSON format:

C#
public JsonResult GetBrandsAndCategories(string acRows, string term)
{
     var selectedRows = new JavaScriptSerializer()
           .Deserialize<List<AutocompleteRow>>(acRows);
    var firstRow = selectedRows[0];
    term = term.Trim().ToLower(); 
    if (term == "secondlevel")
    {
        var list = new List<AutocompleteRow>();
        if (firstRow.category == "Brands")
        {
            var brand = Brand.GetById(int.Parse(firstRow.value));
            list = brand.Categories
                .Select(c => new AutocompleteRow { 
                    category = "Categories", label = c.Name, value = c.Id.ToString() 
                })
                .ToList<AutocompleteRow>();
        }
        else
        {
            // . . . 
        }
        return Json(list, JsonRequestBehavior.AllowGet);
    }
}  

Demo Data Repository

The structure of data is usually like this:

XML
 <categories> 
   <category id="3" name="Clothing">
      <sub-categories>
         <sub-category id="22" name="Shorts">
            <products>
               <product id="841" name = "Men's Sports Shorts, S">
                  <brands>
                     <brand id="29" name="Integrated Sport" price="20.00">
                     <brand id="102" name="Fitness Association" price="19.80">
                  </brands>
               </product>
            </products>
         </sub-category>
      </sub-categories>
    </category>
</categories>  

History

  • 28th June, 2011: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Freelancer
Serbia Serbia
June 2011. – Present, Freelancer
• Took part in development of Web Platform for automated trading.
Thanks to Lightstreamer.com as the real-time bi-directional data delivery we realized Long Polling Push pattern. Also, thanks to ASP.NET MVC 4 mobile features, application renders different HTML markups for different display devices, mobile specific or agent specific (i.e. iPhone).
As the Data Access Layer, we used SQL Server and Entity Framework Repository Pattern.
At client side intensive usage of jQuery, Bootstrap, Knockout.js and Widgets developed by custom bindings of Knockout.js.

September 2010. – May 2011. TekNuvo

• Developed application for coupon and promotional data for advertisers. Technologies: ASP.NET MVC 3, C#, LINQ, Entity Framework 4.0, Code-First, Scaffolding …
• Extracted and integrated Lucene Search Modules from Orchard CMS Project Source.
• Using Unity as Dependency Injection Container, and Interfaces instead of specific classes, i.e. accessing data through an abstract repository interface, we enabled easy way of unit testing. Used TDD as the method of a design, specifying desired behaviors in the form of unit tests, and then provided implementations to fit.
• Developed several jQuery plugins.
• Developed Shopping Cart application using “ASP.NET MVC 2”, “LINQ to SQL” and NUnit.

March 2008. – August 2010. Mogul Balkan

• Developed Windows Service for integration of Active Directory Groups and Users with SharePoint Groups and Users.
• Integration of InfoPath Forms services with SharePoint.
Developed PowerShell script for automatic unpacking, modifying and packaging of the InfoPath Forms.
• Created custom Moss 2007 Publishing Portal Site Definition with automatic creation of sites structure for extranet project.
• Developed Publishing Feature for WSS 3.0 only.
• Customization and extension of Content Query Web Part.
• Customization of CQWP XSLT files.
• Deployment of SharePoint packages using VSeWSS 1.3 and WSPBuilder
• Deploymen

Comments and Discussions

 
QuestionThanks Pin
tidkerohit25-Jun-12 5:14
tidkerohit25-Jun-12 5:14 
QuestionMy vote 5 - excellent Pin
bluesoniq18-Aug-11 9:41
bluesoniq18-Aug-11 9:41 
GeneralMy vote of 5 Pin
jayantbramhankar28-Jun-11 18:35
jayantbramhankar28-Jun-11 18:35 
GeneralRe: My vote of 5 Pin
Sandesh M Patil29-Jun-11 3:45
Sandesh M Patil29-Jun-11 3:45 
GeneralRe: My vote of 5 Pin
Slavko.Parezanin29-Jun-11 4:01
Slavko.Parezanin29-Jun-11 4:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.