Bootstrap内にもauto complete機能としてtypeaheadがあるが、日本語の扱いに難があるみたい。
Bootstrap Typeaheadの日本語入力対応 | PLUS
ARKの技術メモ: [Twitter Bootstrap]typeaheadでの日本語入力問題への対策
だが、Bootstrap内とは別にtwitter制作のtypeaheadライブラリがあり、これを使用してみると日本語問題はないっぽい。しかも、機能も強化されている。
twitter/typeahead.js
typeahead.js – examples
そこで、いくつかサンプルを。
なお、この説明に使用しているtypeahead.jsのバージョンは0.9.3になります。
2014年2月5日現在、バージョンは0.10.0となっており、設定が違っているみたいです(コメントありがとうございました)なので、参考までにしてください。
データ埋め込みサンプル
もっとも簡単に、データを直接埋め込むサンプル。
CSSはjharding/typeahead.js-bootstrap.cssから拝借。
<!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>
$(function() {
return $('.ta').typeahead({
name: 'names',
local: ["斉藤", "斉木", "大野", "大原"],
limit: 10
});
});
jsonで別ファイルに持つサンプル
以後は、サーバー上でないと動かない。
まず、データファイルはjson形式で別に持つことができる。
[
{
"value":"斉藤",
"tokens":["さいとう","saito"]
},{
"value":"斉木",
"tokens":["さいき","saiki"]
},{
"value":"大野",
"tokens":["おおの","oono"]
},{
"value":"大原",
"tokens":["おおはら","oohara"]
}
]
ここで、
- valueは、実際にテキストボックスに入る値
- tokensは、入力された文字列に反応させたい値を配列で入れる。
上記の例では、「斉藤」は、「さいとう」でも、「saito」でもヒットするように設定している。
これを、サーバー上の適当な場所に保存(ここではルートに保存)
$(function() {
return $('.ta').typeahead({
name: 'names',
prefetch: '/sample.json',
limit: 10
});
});
(htmlはそのまま)
idもhiddenフィールドとして保存したい
これまでのサンプルのようなユーザーデータで、ユーザーごと名前をテキストボックスに
保存するだけでなく、IDも一緒に保存したいとする。ついでに、部署情報も追加して
テンプレートシステムを利用してみる。テンプレートエンジンは、本家にならって
twitter/hogan.js
を利用してみる。
用意したサンプルの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を用意する
<input class="ta" name="prefs" type="text" />
<input id="hidden_id" name="id" type="hidden" />
javascript部分も以下のように変更。
$(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など、ほかの値も自由にとれる)
実際の画面はこんな感じに。
firebugでhidden_idを見ると、更新されている。
リモートでやり取りしたい
ここまでくると簡単で、javascriptコードの
prefetch: ~
の部分を
remote: "/usr/find/%QUERY"
に変更するとajax通信をする。タイプされた内容は%QUERY
の中に入る。なので、単純に
remote: "/usr/find?name=%QUERY"
とすると、params[:name]でタイプされた内容をサーバー側で補足することができる。
もちろん、サーバーからの返事はjsonが無難。
また、上記のremote設定は簡略版で、詳細版はremote部分を
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 */ }
}
このようなオプションを指定することができる。