I just noticed that there was generosity in this question, so I decided to share some optimizations that I made with my original answer.
The basic functions are in the included file:
typeahead.js
function setBHPrefetchOpts(cache, prefetchUrl, prefetchFilter) { var prefetchOptions = {}; prefetchOptions['url'] = prefetchUrl; prefetchOptions['cache'] = cache; prefetchOptions['filter'] = prefetchFilter; return prefetchOptions; } function setBHRemoteOpts(cache, wildcard, remoteUrl, remoteFilter) { var remoteOptions = {}; remoteOptions['url'] = remoteUrl; remoteOptions['cache'] = cache; remoteOptions['wildcard'] = wildcard; remoteOptions['filter'] = remoteFilter; return remoteOptions; } function setBHOptions(sufficient, datumToken, queryToken, prefetchOptions, remoteOptions) { var token = Bloodhound.tokenizers.whitespace; var options = {}; options['sufficient'] = sufficient; options['datumTokenizer'] = datumToken === null ? token : datumToken; options['queryTokenizer'] = queryToken === null ? token : queryToken; if (prefetchOptions != null) options['prefetch'] = prefetchOptions; if (remoteOptions != null) options['remote'] = remoteOptions; return options; } function initTypeaheadOptions(hint, highlight, minLength) { var options = {}; options['hint'] = hint; options['highlight'] = highlight; options['minLength'] = minLength; return options; }; function initTypeaheadDataset(name, displayKey, limit, source) { var dataset = {}; dataset['name'] = name; dataset['displayKey'] = displayKey; dataset['limit'] = limit; dataset['source'] = source; return dataset; };
To initialize a prefetch (json) type:
var prefetchOpts = setBHPrefetchOpts(false, '/recipe/resources/measures.json', null); var bhOpts = setBHOptions(50, null, null, prefetchOpts, null); var measureBH = new Bloodhound(bhOpts); function initMeasuresTA() { var options = initTypeaheadOptions(true,true,1); var dataset = initTypeaheadDataset('measures', null, 50, measureBH); $('.ingredQtyType').typeahead(options,dataset); };
To initialize a remote type:
var remoteOpts = setBHRemoteOpts(false, '%QUERY', '/recipe/recipe/getQualifiers?searchStr=%QUERY', null); var bhOpts = setBHOptions(50, null, null, null, remoteOpts); var qualifierBH = new Bloodhound(bhOpts); function initQualifiersTA() { var options = initTypeaheadOptions(true,true,1); var dataset = initTypeaheadDataset('qualifiers', null, 50, qualifierBH); $('.ingredQual').typeahead(options,dataset); };
In both of the above, json consists of separate elements, for example,
["Cup", "Cup", "Ounce", "ounce," pound "," pound sterling "," Tea "," teaspoons "," Dining "," Spoons "]
To initialize both prefetch and remote with more complex json as follows:
{"ingredients": [{"ID": "142", "name": "flour"}, {"identifier": "144", "name": "sugar"}]}
function ingredDatumToken(datum) { return Bloodhound.tokenizers.whitespace(datum.name); }; function ingredPrefetchFilter(data) { return $.map(data.ingredients, function (ingredient) { return { id : ingredient.id, name : ingredient.name }; }); }; function ingredRemoteFilter(data) { return $.map(data, function (data) { return { id : data.id, name : data.name }; }); }; var prefetchOpts = setBHPrefetchOpts(false, '/recipe/resources/ingredients.json', ingredPrefetchFilter); var remoteOpts = setBHRemoteOpts(false, '%QUERY', '/recipe/recipe/getIngredients?searchStr=%QUERY', ingredRemoteFilter); var bhOpts = setBHOptions(50, ingredDatumToken, null, prefetchOpts, remoteOpts); var ingredBH = new Bloodhound(bhOpts); function initIngredientsTA() { var options = initTypeaheadOptions(true,true,1); var dataset = initTypeaheadDataset('ingredients', 'name', 50, ingredBH); $('.ingredDesc').typeahead(options,dataset); };
Dynamic query example:
function setSourceUrl(url, query) { var source = $('#inputSource').val(); var newurl = url + '?searchStr=' + query + '&type=' + source; return newurl; }; var remoteOpts = setBHRemoteOpts(false, '%QUERY', '/recipe/recipe/getSources', null); var remoteOpts['replace'] = function(url, query) {return setSourceUrl(url, query);}; var bhOpts = setBHOptions(50, null, null, null, remoteOpts); var sourceBH = new Bloodhound(bhOpts); function initSourceTA() { var options = initTypeaheadOptions(true,true,1); var dataset = initTypeaheadDataset('source', null, 20, sourceBH); $('.srcTA').typeahead(options,dataset); };
Filters can probably be added as generic functions in typeahead.js, but I only have one dataset that required them, so I did not. The same goes for the "replace" option. As said earlier, I'm still relatively new to javascript / jQuery, so I'm sure this solution could be improved, but it made it a lot easier for me than simplifying the setup.