1. insight3110
Changes in body
Source | HTML | Preview
@@ -1,173 +1,174 @@
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")
そこで、いくつかサンプルを。
## データ埋め込みサンプル
もっとも簡単に、データを直接埋め込むサンプル。
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の2つの引数をとるが、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 */ }
}
```
このようなオプションを指定することができる。