Created by Samuel Clay, @samuelclay.

VisualSearch.js enhances ordinary search boxes with the ability to autocomplete faceted search queries. Specify the facets for completion, along with the completable values for any facet. You can retrieve the search query as a structured object, so you don't have to parse the query string yourself.

Here's an example of a search on that uses facets.

The project is hosted on GitHub. You can report bugs and discuss features on the issues page, on Freenode in the #documentcloud channel, or send tweets to @documentcloud.

VisualSearch.js is an open-source component of DocumentCloud.
The complete annotated source code is also available.

Table of Contents

Demo | Downloads | Usage | Links | Change Log

Demo Try searching for: account, filter, access, title, city, state, or country.


Downloads (Right-click, and use "Save As")

0. Everything (
Download everything
1. VisualSearch JavaScript (visualsearch.js)
Production Version (0.5.0) 7kb, Minified and Gzipped
Development Version (0.5.0) 63kb, Uncompressed with Comments
2. VisualSearch Stylesheets (visualsearch.css)
You should include both the datauri and image urls versions. See how to include both
Production Version - datauri 4kb, Minified and Gzipped
Production Version - image urls 4kb, Minified and Gzipped
Development Version 8kb, Uncompressed with Comments
3. VisualSearch Images
Search Glyph 4kb, embedded in visualsearch-datauri.css
Cancel Button 4kb, embedded in visualsearch-datauri.css
4. VisualSearch Dependencies (jQuery 1.4+, jQuery UI 1.8+, Underscore.js, Backbone.js)
You should only include the dependencies you don't already have.
Production Version - All 49kb, Minified and Gzipped
Development Version - All 340kb, Uncompressed with Comments
jQuery 1.11.0 267kb, Uncompressed with Comments
jQuery UI 1.10.4:
Core Position Widget Menu Autocomplete
72kb, Uncompressed with Comments
Underscore 1.5.2 41kb, Uncompressed with Comments
Backbone 1.1.0 59kb, Uncompressed with Comments


To use VisualSearch.js on your site, follow these instructions on installation, configuration, and customization.

  1. Insert the JavaScript and CSS into your page:
    <script src="visualsearch.js" type="text/javascript"></script>
    <!--[if (!IE)|(gte IE 8)]><!-->
      <link href="visualsearch-datauri.css" media="screen" rel="stylesheet" type="text/css" />
    <!--[if lte IE 7]><!-->
      <link href="visualsearch.css" media="screen" rel="stylesheet" type="text/css" />
  2. Initialize the Visual Search box:
    <div class="visual_search"></div>
    <script type="text/javascript" charset="utf-8">
      $(document).ready(function() {
        var visualSearch = VS.init({
          container : $('.visual_search'),
          query     : '',
          callbacks : {
            search       : function(query, searchCollection) {},
            facetMatches : function(callback) {},
            valueMatches : function(facet, searchTerm, callback) {}
  3. Customize the autocompleted facets and values:
    callbacks : {
      // These are the facets that will be autocompleted in an empty input.
      facetMatches : function(callback) {
          'account', 'filter', 'access', 'title',
          { label: 'city',    category: 'location' },
          { label: 'address', category: 'location' },
          { label: 'country', category: 'location' },
          { label: 'state',   category: 'location' },
      // These are the values that match specific categories, autocompleted
      // in a category's input field.  searchTerm can be used to filter the
      // list on the server-side, prior to providing a list to the widget.
      valueMatches : function(facet, searchTerm, callback) {
        switch (facet) {
        case 'account':
              { value: '1-amanda', label: 'Amanda' },
              { value: '2-aron',   label: 'Aron' },
              { value: '3-eric',   label: 'Eric' },
              { value: '4-jeremy', label: 'Jeremy' },
              { value: '5-samuel', label: 'Samuel' },
              { value: '6-scott',  label: 'Scott' }
          case 'filter':
            callback(['published', 'unpublished', 'draft']);
          case 'access':
            callback(['public', 'private', 'protected']);
          case 'title':
              'Pentagon Papers',
              'CoffeeScript Manual',
              'Laboratory for Object Oriented Thinking',
              'A Repository Grows in Brooklyn'
  4. Inspect the Visual Search box
    // Returns the unstructured search query
    // "country: "South Africa" account: 5-samuel title: "Pentagon Papers""
    // Returns an array of Facet model instances
    // [FacetModel<country:"South Africa">, 
    //  FacetModel<account:5-samuel>, 
    //  FacetModel<title:"Pentagon Papers">]
    // Set the search query with raw text
    visualSearch.searchBox.value("Country: US State: \"New York\" Key: Value")

Search.js July 22nd, 2013
A fork of VisualSearch.js that provides support for dynamic operators and HTML5 input types (numbers and dates).

Change Log

0.5.0 February 9th, 2014
Add readOnly: true to your options to create a read-only search box. Also upgraded all vendorized dependencies to latest versions (jQuery 1.11.0, jQuery UI 1.10.4, Backbone 1.1.0, Underscore 1.5.2). Also fixed a number of issues:

0.4.0 January 27th, 2013
Add placeholder: "Search for documents..." to your options to create an auto-hiding placeholder in an empty search box. Also upgraded all vendorized dependencies to latest versions (jQuery 1.9.0, jQuery UI 1.10.0, Backbone 0.9.10, Underscore 1.4.3). Also fixed a number of issues:

0.3.0 September 20th, 2012
Add showFacets: true to your options to have all available facets automatically show up when the search text box is focused. You can also pass multiple facet names to withoutCategory, like so: searchQuery.withoutCategory('country', 'account').

0.2.2 March 10th, 2012
If you do not want to automatically filter the value matches, you can pass an options hash with preserveMatches: true as the second argument to the callback. See pull request #44 for details.

0.2.1 November 14th, 2011
The autocompleted facets and values that are provided by your callbacks facetMatches and valueMatches can now preserve the order of items you give them. Simply pass an options hash with preserveOrder: true as the second argument to the callback. See the demo page for an example.

0.2.0 August 10th, 2011
Multiple instances of VisualSearch on a single page. VS.init now returns a reference to the instance. The search callback now contains both the serialized search query and a reference to the search query collection (as a Backbone.Collection), which can be used to manipulate each facet directly. See the source code for search_query.js for available methods on the collection.

0.1.0 June 23rd, 2011
Initial release of VisualSearch.js.

A DocumentCloud Project