Bootstrapで、オートコンプリートで絞り込む検索ボックスを実装しようと思ってプラグインを探したところ typeahead.js がよく使われていそうな感じだったので試してみました。

先に説明用のコード全体を貼りました。

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <link rel="stylesheet" href="css/bootstrap.min.css">
  <link rel="stylesheet" href="css/typeahead.css">
</head>
<body>

<div class="container">
  <div class="form-group">
    <label>Station</label>
    <input type="text" class="form-control">
  </div>
</div>

<script src="js/jquery-1.11.0.min.js"></script>
<script src="js/typeahead.bundle.min.js"></script>
<script>
  var engine = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: [{ value: '東京' }, { value: '新宿' }, { value: '池袋' }, { value: '渋谷' }]
  });

  engine.initialize();

  $(':input').typeahead(null, {
    name:'stations',
    source: engine.ttAdapter()
  })
</script>
</body>
</html>

ブラウザで表示するとこんな感じです。

typeahead-example

1. 必要なフィアルの読み込み

上記の例では、スタイルシートは css ディレクトリに、Javascriptは js ディレクトリに入れています。

typeahead 本体のjsは、Githubリポジトリ から取得した typeahead.bundle.js を js ディレクトリに置いています。

ところで、typeaheadのリポジトリにはなぜか、cssが含まれていません。
検索すると、Bootstrap3 用の typeahead.js のCSSはいくつか見つかるので、とりあえず hyspace / typeahead.js-bootstrap3.less を試しました。
typeahead.js-bootstrap3.less から typeahead.css を追加しています。

2. テキストボックスに対して Typehead を有効にする

  $(':input').typeahead(null, {
    name:'stations',
    source: engine.ttAdapter()
  })

typehead の第1引数は、オプションを指定します。全部デフォルトの場合は null を指定しておきます。

第2引数は、データセット のオプションを指定します。

  • name: プルダウンのclass名に使われます。
  • displayKey: デフォルトでは、プルダウンオプションの値とラベルはどちらも value が使われますが、表示用フィールドを別にしたい場合は displayKey で指定できます。
  • source: 第1引数にtypeaheadを有効にしたテキストボックスに入力された文字列、題2引数にコールバックが渡される関数を指定します(例: examplesのThe Basic)。または、パッケージに含まれるスジェッションエンジン Bloodhound を利用することもできます。上記の例では Bloodhound を使っています。

2. Bloodhoundを初期化

source に直接関数をしていするよりも、機能が豊富な Bloodhound を利用する方がおすすめです。

  var engine = new Bloodhound({
    datumTokenizer: function(d){ return d.value },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: [{ value: '東京' }, { value: '新宿' }, { value: '池袋' }, { value: '渋谷' }]
  });

初期化のオプション
以下の項目を押さえれば後は、Githubのドキュメントやソースをみれば応用できると思います。

  • datumTokenizer: 必須です。Javascriptオブジェクトの配列(Datums)の各要素を引数に取り、検索対象のプロパティを返す関数を指定します。
  • queryTokenizer: 必須です。テキストボックスに入力された文字列を引数に取り、適当に文字列を分割した配列を返します。英語だと空白で分割してさらに絞り込みとかできますが、日本語だとあまり使えなさそう。
  • local: 最初に保持しておく、Datums
  • prefetch: 最初にAjaxでロードするDatums
  • remote: local または prefetch で最初に用意したデータで間に合わなくなった場合に、さらにAjaxでDatumsをロードする場合に指定します。

今回は、検索対象がデータベースで、それなりに量が多かったので、remoteを指定してサーバーから候補を取得するように実装しましたが、リクエストのタイミングも良きに計らってくれるのでとても便利です。

参考:
ちょっと古いのでscript側は使えませんが、サーバー再度まで含めた例が参考になります。
Bootstrap Auto Complete in php mysql | jQuery Auto Suggest