Typeahead with Bloodhound
What's ahead
- Setting up a remote source
- Installing Typeahead
- Getting End-point data
- Wire up to View
- Demo
- Try it yourself
Setting up a remote source
- Choose favorable end-point
- Set-up reverse proxy to API
Choose favorable end-point
- Mean response time should be ~< 200ms
- Acceptable rate limiting on end-point
In other words, look for something like Elastic Search with a generous rate limit. Tools like Compose.io offer hosted solutions.
Set-up reverse proxy to API
Hapi = require('hapi')
path = require('path')
exports.startServer = (port, publicPath, callback) ->
# Start server on port specified in brunch-config
server = new Hapi.Server port
# Reverse proxy to Untappd API
server.route
method: '*'
path: '/api/untappd/search/{path*}'
handler:
proxy:
mapUri: (request, callback) ->
url = "http://api.untappd.com/v4/search/#{request.params.path}?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&q=#{request.query.q}"
callback null, url
redirects: 5
timeout: 5000
# Serve static files
server.route
method: '*'
path: '/{path*}'
handler:
directory:
path: publicPath
# Start up server
server.start ->
console.log "Server running at #{server.info.uri}"
Getting End-point data
- Create domain models
- Create search model
- Create search controller
Create domain models
Model = require('models/base/model')
module.exports = class Beer extends Model
###
Collection = require('models/base/collection')
Beer = require('./beer')
module.exports = class Beers extends Collection
url: "/api/untappd/search/beer"
model: Beer
parse: (data, options) ->
{items} = data.response.beers
(beer for beer in _.pluck items, 'beer')
Create search model
Beers = require('models/beers')
# @requires {Component} backbone.nested-types
module.exports = NestedTypes.Model.extend
defaults:
results: Beers
initialize: (attrs, opts) ->
{@query} = opts
Create search controller
Typeahead = require('views/site/typeahead')
BeerSearch = require('models/beer-search')
BeerCollectionView = require('views/beer/beer-collection-view')
module.exports = class SearchController extends Controller
beforeAction: (params, route, options) ->
@search = new BeerSearch [], {query: options.query}
@reuse 'typeahead', Typeahead, {collection: @search.results, region: 'secondary'}
index: ->
@view = new BeerCollectionView {collection: @search.results, region: 'main'}
Wire up to view
- Configure Bloodhound
- Extend a typeahead control
- Style to your liking
Installing Typeahead
bower install --save typeahead.js
bower typeahead.js#* cached git://github.com/twitter/typeahead.js.git#0.10.5
bower typeahead.js#* validate 0.10.5 against git://github.com/twitter/typeahead.js.git#*
bower typeahead.js#~0.10.5 install typeahead.js#0.10.5
typeahead.js#0.10.5 bower_components/typeahead.js
└── jquery#2.0.3
Configure Bloodhound
View = require('views/base/view')
module.exports = class TypeaheadView extends View
className: 'typeahead-view'
template: require('./templates/typeahead')
events:
'submit form': '_onFormSubmit'
listen:
'router:match mediator': '_onRouterMatch'
# @require {Component} typeahead.js
initialize: (attrs) ->
super
do =>
filter = (data) =>
@collection.reset @collection.parse data
({name} for name in @collection.pluck 'beer_name')
@engine = new Bloodhound
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
dupDetector: (remoteMatch, localMatch) ->
remoteMatch.name == localMatch.name
limit: 50
prefetch: {filter, url: @collection.url}
remote: {filter, url: "#{@collection.url}?q=%QUERY"}
@engine.initialize()
Extend a typeahead control
attach: ->
super
@$form = @$('#searchform')
@$searchInpt = @$('input#search')
@$searchInpt.typeahead
minLength: 1
,
name: 'beers' # appended to tt-dataset- to form class name of containing element
displayKey: 'name'
source: @engine.ttAdapter()
.select()
.on('typeahead:selected', @_onTypeaheadSelected.bind @)
.on('typeahead:autocompleted', @_onTypeaheadAutocompleted.bind @)
.keydown @_onTypeaheadKeydown.bind @
Style to your liking
/**
* Twitter Typeahead
* https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#look-and-feel
*/
$border-color-Typeahead: #D6DCE3;
$border-radius-Typeahead: 5px;
$highlight-color-Typeahead: #4183C4;
$hint-color-Typeahead: #999;
.twitter-typeahead {
display: block !important;
max-width: 100%;
}
.tt-dropdown-menu {
display: none !important; /* Hide Typeahead drop-down */
}
Demo
Try it yourself!
(requires Untapped API access)
git clone https://github.com/jhabdas/hopstop.git && cd $_
git checkout -b ratchet origin/ratchet
npm install
jake server:dev
Typeahead with Bloodhound
By Josh Habdas
Typeahead with Bloodhound
Present code to enable search auto-completion using Twitter Typeahead with a Bloodhound remote source using Brunch with Panache.
- 6,468