twitter typeaheadはいろいろ改良されていた

Bootstrap内にもauto complete機能としてtypeaheadがあるが、日本語の扱いに難があるみたい。
[Bootstrap Typeaheadの日本語入力対応 | PLUS](http://plus.vc/web/javascript/6376/)
[ARKの技術メモ: [Twitter Bootstrap]typeaheadでの日本語入力問題への対策](http://arkmemo.blogspot.jp/2013/03/twitter-bootstraptypeahead_26.html "ARKの技術メモ: [Twitter Bootstrap]typeaheadでの日本語入力問題への対策")

だが、Bootstrap内とは別にtwitter制作のtypeaheadライブラリがあり、これを使用してみると日本語問題はないっぽい。しかも、機能も強化されている。
[twitter/typeahead.js](https://github.com/twitter/typeahead.js "twitter/typeahead.js")
[typeahead.js – examples](http://twitter.github.io/typeahead.js/examples/ "typeahead.js – examples")

そこで、いくつかサンプルを。
なお、この説明に使用しているtypeahead.jsのバージョンは0.9.3になります。
2014年2月5日現在、バージョンは0.10.0となっており、設定が違っているみたいです（コメントありがとうございました）なので、参考までにしてください。

## データ埋め込みサンプル
もっとも簡単に、データを直接埋め込むサンプル。
CSSは[jharding/typeahead.js-bootstrap.css](https://github.com/jharding/typeahead.js-bootstrap.css "jharding/typeahead.js-bootstrap.css")から拝借。

```html:
<!DOCTYPE html>
<link href="bootstrap.min.css" media="screen" rel="stylesheet" type="text/css" />
<link href="typeahead.js-bootstrap.css" media="screen" rel="stylesheet" type="text/css" />
<div class="container">
  <h1>テスト</h1>
<input type="text" class="ta" name="name">
</div>
<script src="jquery.js" type="text/javascript"></script>
<script src="typeahead.js" type="text/javascript"></script>
<script src="sample.js" type="text/javascript"></script>
```

```js:sample.js
$(function() {
  return $('.ta').typeahead({
    name: 'names',
    local: ["斉藤", "斉木", "大野", "大原"],
    limit: 10
  });
});
```
![type1.png](https://qiita-image-store.s3.amazonaws.com/0/26556/ef744162-f9c1-4f0f-ad4a-b756d2cce657.png)
・・・動いた

## jsonで別ファイルに持つサンプル
以後は、サーバー上でないと動かない。
まず、データファイルはjson形式で別に持つことができる。

```json:
[
  {
    "value":"斉藤",
    "tokens":["さいとう","saito"]
  },{
    "value":"斉木",
    "tokens":["さいき","saiki"]
  },{
    "value":"大野",
    "tokens":["おおの","oono"]
  },{
    "value":"大原",
    "tokens":["おおはら","oohara"]
  }
]
```
ここで、
* valueは、実際にテキストボックスに入る値
* tokensは、入力された文字列に反応させたい値を配列で入れる。
上記の例では、「斉藤」は、「さいとう」でも、「saito」でもヒットするように設定している。
これを、サーバー上の適当な場所に保存（ここではルートに保存）

```js:sample.js
$(function() {
  return $('.ta').typeahead({
    name: 'names',
    prefetch: '/sample.json',
    limit: 10
  });
});
```

(htmlはそのまま)

![type2.png](https://qiita-image-store.s3.amazonaws.com/0/26556/ca88c9c4-8bc3-cb1f-6903-bed4c271b5b4.png)
![type3.png](https://qiita-image-store.s3.amazonaws.com/0/26556/de40b0ef-59b0-5cc5-b399-75363ef6990b.png)
できた。

## idもhiddenフィールドとして保存したい
これまでのサンプルのようなユーザーデータで、ユーザーごと名前をテキストボックスに
保存するだけでなく、IDも一緒に保存したいとする。ついでに、部署情報も追加して
テンプレートシステムを利用してみる。テンプレートエンジンは、本家にならって
[twitter/hogan.js](https://github.com/twitter/hogan.js "twitter/hogan.js")
を利用してみる。
用意したサンプルのjsonは以下の通り。

```json:
[
  {
    "value":"斉藤",
    "id": 1,
    "busho": "営業部",
    "tokens":["さいとう","saito"]
  },{
    "value":"斉木",
    "id": 2,
    "busho": "経理部",
    "tokens":["さいき","saiki"]
  },{
    "value":"大野",
    "id": 3,
    "busho": "営業部",
    "tokens":["おおの","oono"]
  },{
    "value":"大原",
    "id": 4,
    "busho": "管理部",
    "tokens":["おおはら","oohara"]
  }
]
```
htmlも、以下のように、IDを保持するためのhidden属性のinputを用意する

```html:
<input class="ta" name="prefs" type="text" />
<input id="hidden_id" name="id" type="hidden" />
```

javascript部分も以下のように変更。

```js:sample.js
$(function() {
  return $('.ta').typeahead({
    name: 'name-busho2',
    prefetch: '/sample.json',
    template: '<div style="width:10em"><p style="float:right">{{busho}}</p><p>ID:{{id}}</p><p style="font-weight:bold">{{value}}</p></div>',
    engine: Hogan
  }).on("typeahead:selected typeahead:autocomplete", function(e, datum) {
    return $('#hidden_id').val(datum.id);
  });
});
```

ここで、name属性は一応変更（任意の値でいいみたい）。
また、templateではヒットしたものをどのように表示するのか、ここで自由に指定できる。内容は普通のHTMLで、コード中に{{属性の項目名}}で、その項目名を埋め込むことができる（この表記はテンプレートエンジンHoganの表記法）。この自由さがtwitter typeaheadの魅力だと思う。Bootstrapのtypeaheadでもできるにはできたが、面倒だったはず。これで、valueとIDだけでなく、自由に項目を追加、扱うことができる。

実際に選んだあとの処理は、カスタムイベントの`typeahead:selected`と`typeahead:autocomplete`が定義されているので、そのイベント発生時の処理を`on("typeahead～`以下に記述する。
functionはeとdatumの２つの引数をとるが、datumに、実際選ばれたオブジェクトの情報が入っている。idは`datum.id`でとれるので、あとは普通に所定のものにセットするだけ（部署情報はdatum.bushoなど、ほかの値も自由にとれる）

実際の画面はこんな感じに。
![type4.png](https://qiita-image-store.s3.amazonaws.com/0/26556/89cfb212-818d-f820-abb3-63246b8c3068.png)
firebugでhidden_idを見ると、更新されている。
![type5.png](https://qiita-image-store.s3.amazonaws.com/0/26556/e5cf08fa-bc8d-51b7-4cdd-7aa94b14fd9c.png)

## リモートでやり取りしたい
ここまでくると簡単で、javascriptコードの
`prefetch: ～`
の部分を
`remote: "/usr/find/%QUERY"`
に変更するとajax通信をする。タイプされた内容は`%QUERY`の中に入る。なので、単純に
`remote: "/usr/find?name=%QUERY"`
とすると、params[:name]でタイプされた内容をサーバー側で補足することができる。
もちろん、サーバーからの返事はjsonが無難。
また、上記のremote設定は簡略版で、詳細版はremote部分を

```js:
remote: {
    url: '/states?q=%WILDCARD',
    wildcard: '%WILDCARD',
    rateLimitFn: 'throttle',
    rateLimitWait: 300, // rateLimitWait or wait? i think i prefer the former
    maxConcurrentConnections: 4,
    dataType: 'json',
    timeout: 2000,
    cache: true,
    beforeSend: function(jqXhr, settings) { /* set headers, etc. */ },
    filter: function(resp) { /* parse suggestions out of response  */ }
  }
```
このようなオプションを指定することができる。