Blame | Last modification | View Log | RSS feed
Migrating to typeahead.js v0.10.0=================================Preamble--------v0.10.0 of typeahead.js ended up being almost a complete rewrite. Many thingsstayed the same, but there were a handful of changes you need to be aware ofif you plan on upgrading from an older version. This document aims to call outthose changes and explain what you need to do in order to have an painlessupgrade.Notable Changes----------------### First Argument to the jQuery PluginIn v0.10.0, the first argument to `jQuery#typeahead` is an options hash thatcan be used to configure the behavior of the typeahead. This is in contrastto previous versions where `jQuery#typeahead` expected just a series of datasetsto be passed to it:```javascript// pre-v0.10.0$('.typeahead').typeahead(myDataset);// v0.10.0$('.typeahead').typeahead({highlight: true,hint: false}, myDataset);```If you're fine with the default configuration, you can just pass `null` as thefirst argument:```javascript$('.typeahead').typeahead(null, myDataset);```### Bloodhound Suggestion EngineThe most notable change in v0.10.0 is that typeahead.js has been decomposed intoa suggestion engine and a UI view. As part of this change, the way you configuredatasets has changed. Previously, a dataset config would have looked like:```javascript{valueKey: 'num',local: [{ num: 'one' }, { num: 'two' }, { num: 'three' }],prefetch: '/prefetch',remote: '/remote?q=%QUERY'}```In v0.10.0, an equivalent dataset config would look like:```javascript{displayKey: 'num',source: mySource}```As you can see, `local`, `prefetch`, and `remote` are no longer defined at thedataset level. Instead, all you set in a dataset config is `source`. `source` isexpected to be a function with the signature `function(query, callback)`. When atypeahead's query changes, suggestions will be requested from `source`. It'sexpected `source` will compute the suggestion set and invoke `callback` with an arrayof suggestion objects. The typeahead will then go on to render those suggestions.If you're wondering if you can still configure `local`, `prefetch`, and`remote`, don't worry, that's where the Bloodhound suggestion engine comes in.Here's how you would define `mySource` which was referenced in the previouscode snippet:```var mySource = new Bloodhound({datumTokenizer: function(d) {return Bloodhound.tokenizers.whitespace(d.num);},queryTokenizer: Bloodhound.tokenizers.whitespace,local: [{ num: 'one' }, { num: 'two' }, { num: 'three' }],prefetch: '/prefetch',remote: '/remote?q=%QUERY'});// this kicks off the loading and processing of local and prefetch data// the suggestion engine will be useless until it is initializedmySource.initialize();```In the above snippet, a Bloodhound suggestion engine is initialized and that'swhat will be used as the source of your dataset. There's still one last thingthat needs to be done before you can use a Bloodhound suggestion engine as thesource of a dataset. Because datasets expect `source` to be function, theBloodhound instance needs to be wrapped in an adapter so it can meet thatexpectation.```mySource = mySource.ttAdapter();```Put it all together:```javascriptvar mySource = new Bloodhound({datumTokenizer: function(d) {return Bloodhound.tokenizers.whitespace(d.num);},queryTokenizer: Bloodhound.tokenizers.whitespace,local: [{ num: 'one' }, { num: 'two' }, { num: 'three' }],prefetch: '/prefetch',remote: '/remote?q=%QUERY'});mySource.initialize();$('.typeahead').typeahead(null, {displayKey: 'num',source: mySource.ttAdapter()});```### Tokenization Methods Must Be ProvidedThe Bloodhound suggestion engine is token-based, so how datums and queries aretokenized plays a vital role in the quality of search results. Pre-v0.10.0,it was not possible to configure the tokenization method. Starting in v0.10.0,you **must** specify how you want datums and queries tokenized.The most common tokenization methods split a given string on whitespace ornon-word characters. Bloodhound provides implementations for those methodsout of the box:```javascript// returns ['one', 'two', 'twenty-five']Bloodhound.tokenizers.whitespace(' one two twenty-five');// returns ['one', 'two', 'twenty', 'five']Bloodhound.tokenizers.nonword(' one two twenty-five');```For query tokenization, you'll probably want to use one of the above methods.For datum tokenization, this is where you may want to do something a tad bitmore advanced.For datums, sometimes you want tokens to be dervied from more than one property.For example, if you were building a search engine for GitHub repositories, it'dprobably be wise to have tokens derived from the repo's name, owner, andprimary language:```javascriptvar repos = [{ name: 'example', owner: 'John Doe', language: 'JavaScript' },{ name: 'another example', owner: 'Joe Doe', language: 'Scala' }];function customTokenizer(datum) {var nameTokens = Bloodhound.tokenizers.whitespace(datum.name);var ownerTokens = Bloodhound.tokenizers.whitespace(datum.owner);var languageTokens = Bloodhound.tokenizers.whitespace(datum.language);return nameTokens.concat(ownerTokens).concat(languageTokens);}```There may also be the scenario where you want datum tokenization to be performedon the backend. The best way to do that is to just add a property to your datumsthat contains those tokens. You can then provide a tokenizer that just returnsthe already existing tokens:```javascriptvar sports = [{ value: 'football', tokens: ['football', 'pigskin'] },{ value: 'basketball', tokens: ['basketball', 'bball'] }];function customTokenizer(datum) { return datum.tokens; }```There are plenty of other ways you could go about tokenizing datums, it reallyjust depends on what you are trying to accomplish.### String Datums Are No Longer SupportedDropping support for string datums was a difficult choice, but in the end itmade sense for a number of reasons. If you still want to hydrate the suggestionengine with string datums, you'll need to use the `filter` function:```javascriptvar engine = new Bloodhound({prefetch: {url: '/data',filter: function(data) {// assume data is an array of strings e.g. ['one', 'two', 'three']return $.map(data, function(str) { return { value: str }; });},datumTokenizer: function(d) {return Bloodhound.tokenizers.whitespace(d.value);},queryTokenizer: Bloodhound.tokenizers.whitespace}});```### Precompiled Templates Are Now RequiredIn previous versions of typeahead.js, you could specify a string template alongwith the templating engine that should be used to compile/render it. Inv0.10.0, you can no longer specify templating engines; instead you must provideprecompiled templates. Precompiled templates are functions that take oneargument: the context the template should be rendered with.Most of the popular templating engines allow for the creation of precompiledtemplates. For example, you can generate one using Handlebars by doing thefollowing:```javascriptvar precompiledTemplate = Handlebars.compile('<p>{{value}}</p>');```[Handlebars]: http://handlebarsjs.com/### CSS Class Changes`tt-is-under-cursor` is now `tt-cursor` - Applied to a hovered-on suggestion (either via cursor or arrow key).`tt-query` is now `tt-input` - Applied to the typeahead input field.Something Missing?------------------If something is missing from this migration guide, pull requests are accepted :)