wataメモ

日々のメモをつらつらと書くだけ

BootstrapのTypeaheadを使って入力可能なプルダウンを実装してみた

 ライブラリやフレームワークを使うのもいいが、使われているだけでは一流の技術者とは言えない。自分で足りないところを改善したり、もっと良いものを創り上げてこそ一流足りえる。と、大げさに書いたが、単純にTypeaheadを見た時に、「これは入力可能なプルダウンに使えるのではないか」と思いついたので実装してみただけ。

 Typeaheadとは何か、簡単に言うとオートコンプリート機能である。

f:id:wata_htn:20120215234838p:plain

 オートコンプリートは何か文字を入力すると、候補データ一覧からマッチするものを表示し、その中から選択することで入力補助する機能である。イメージしている入力できるプルダウンとの違いは以下。

  1. 何も入力せずにクリックだけで一覧を表示
  2. 表示件数に制限はなく、多く表示される場合はスクロールバーが出る
  3. 何か入力されても候補を絞る必要はない(場合によって絞られた方がいいが)
  4. 選択(テキストボックスの値)されている値がある場合にプルダウンを出すと同じ値が選択された状態で表示(スクロール位置も)

 今回作ろうと思ったのは時間のプルダウン。Google Calendarの時間入力部分のイメージ。

f:id:wata_htn:20120216000546p:plain

 表示処理とか、公開されていないと呼び出せないかなと思っていたら、実装的にjQuerydata関数でTypeaheadオブジェクトを保持していたので、取り出せば好き勝手できることが分かった。

$('#target').typeahead({
  source: time // プルダウンの一覧['00:00', '00:15', ...]
  , matcher: function() { return 0; } // 何を入力してもマッチしない(候補を表示しない)
}).on('click', function() { // テキストボックスのクリックイベントを捕捉
  var th = $(this).data('typeahead'); // typeaheadオブジェクトを取り出す
  var t = $(this).val(); // テキストボックスの値を取得
  // データ全件を表示
  th.render(th.options.source).show().$menu.find('li').each(function(idx, l) {
    // 一覧のデータとテキストボックスの値が同じ場合は選択状態にし
    // スクロール位置をずらす
    if ($(l).text() == t) {
      th.$menu.scrollTop($(l).addClass('active').height() * idx);
      return false;
    }
  });
});

  実際に作った結果のイメージは以下。開始と終了があるパターンだったので、開始より後の時間しか表示しないとか細かい事は上のソースより追加している。

f:id:wata_htn:20120216001836p:plain

 それなりに上手く行ったが気になった点もある。

  1. プルダウンと違って表示とパラメータとして送る値を自分で工夫しないと分けられない(Google Calendarの様に「09:30(30分間)」と表示するがパラメータとしては「09:30」だけ送りたい等)
  2. cssでコントロールすればいいが、Typeaheadのデザイン的に横幅が決まっている(調整しないとIEで横スクロールバーが出た)
  3. 入力させたい値の制限は自分で実装しなければならない(「abcd」と入れられた場合はクリアしたり、エラー表示にしたい等)
 他に同じ事を考えた人がいないのかと検索したら、Bootstrapに実装してくれと要望を上げている人がいた。Chosen使えば?と却下?されたみたいだったが。