Simple Client Side Typeahead

March 2014

After recently implementing a simple client-only typeahead, I thought I'd share. The implementation takes pre-existing data and shows a result set within a specified container.

The first thing we need is a collection we can search for matches on, that won't traverse the DOM every time we type. We also want to be able to take a match and show the result easily. Map your collection into an array, taking the text and a clone of the node. For this example, I'll assume your collection is a list.

      
  var source = $('ul').children().map(function (index, el) {
    return {
      clone: $(el).clone(),
      text: $(el).text()
    };
  });
      
    

Awesome, now we have an array we can search without iterating the DOM. Next we'll need a key event on our typeahead input.

      
  $('input').on('keyup', function (e) {
    var val = $(this).val(),
      matches;

    // use this to set your min search length
    if (val.length >= 3) {
      matches = findMatches(val);
    }
  });
      
    

Next, our matching function. jQuery.grep() or _.filter() work well.

      
  function findMatches (val) {
    // use this to restrict your result set
    var numResults = 0;

    return $.grep(source, function (item, index) {
      if (item.text.indexOf(val) !== -1 && numResults < 5) {
        ++numResults;
        return true;
      }
    });
  }
      
    

Now that we have our result set, all we need to do is append the cloned nodes to our target. Depending where and how you want to show the results varies.

      
  $('input').on('keyup', function (e) {
    var val = $(this).val(),
      matches,
      clones;

    // use this to set your min search length
    if (val.length >= 3) {
      matches = findMatches(val);

      // giving jQuery an array will use a document fragment
      clones = $.map(matches, function (index, item) {
        return item.clone;
      });
      $('#search-results').empty().append(clones);
    }
  });
      
    

And our search / filter is done. Feedback welcome.

comments powered by Disqus