CakePHP2 + jQueryUIでテキストボックスにオートコンプリート(オートサジェスト)機能をつける方法
2018/09/11
テキストボックスにオートコンプリート(オートサジェスト)機能を、CakePHP2 + jQuery UI 環境で作成したので作り方を備忘録としてポストします。
jQuery UI でオートコンプリートする方法【単純編】
基本的な作り方
まずは基本の方法。CakePHP2(データベース)を使わずに作ってみます。
jQuery UI の読み込み
jQuery を先に読んで、次に jQuery UI を読み込みます。
1 2 3 4 5 6 |
<!-- *** jquery *** --> <script src="/js/jquery-ui-1.11.4/external/jquery/jquery.js" type="text/javascript"></script> <!-- *** jQuery UI *** --> <script src="/js/jquery-ui-1.11.4/jquery-ui.min.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="/js/jquery-ui-1.11.4/jquery-ui.css" /> |
ビューでテキストボックスの用意
ID名もしくはclass名を付与。
今回は id ですが、class でも問題なし。
1 |
<input type ="text" id="autocomplete"> |
サジェスト内容の準備、抽出
サジェスト候補のマスタ配列(例:availableTags)を用意し、対象のテキストボックスに対してオートコンプリート機能を割り当てています。
ページ読み込みと同時に作動させるために、
$(function() {}
内へ必要なスクリプトを書き込みます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<script> $(function() { var availableTags = [ "ActionScript", "AppleScript", "Asp", "BASIC", "C", "C++", "Clojure", "COBOL", "ColdFusion", "Erlang", "Fortran", "Groovy", "Haskell", "Java", "JavaScript", "Lisp", "Perl", "PHP", "Python", "Ruby", "Scala", "Scheme" ]; $("#autocomplete").autocomplete({ source: availableTags, autoFocus: true, delay: 500, minLength: 1 }); }); </script> |
代表的なオプション
パラメータ | 概要 | 備考/初期値 |
---|---|---|
source |
型:Array or String or Function(Object request, Function response(Object data)) 初期値:無し(入力必須) 候補リストを定義 |
必須 |
autoFocus |
型:Boolean リスト表示に際してリストの1番目にするかを指定 |
false |
delay | 型:Integer キー入力からリスト表示までの遅延時間(ミリ秒) |
300 |
disabled |
型:Boolean オートコンプリートを無効化するかを指定 |
false |
minLength | オートコンプリート機能が働く最小文字数 | 1 |
デモ
デモはコチラから。
https://lightning-bolt.xyz/js/jqueryui.autosaggest/
軽い解説
先にサジェスト候補内容を作成し、それらをフォームに対して割り当てているだけです。
かなり簡単ですね。
コチラを利用する場合は先頭の文字から始まるものを候補として出すのではなく、1個のワード内に含まれる文字を探り当てて候補としてくれます。
具体的には、"a"と入れた場合、
- ActionScript
- AppleScript
- Asp
- BASIC
- Erlang
- Fortran
- Haskell
- Java
- JavaScript
- Scala
"o"と入れた場合、
- ActionScript
- Clojure
- COBOL
- ColdFusion
- Fortran
- Groovy
- Python
が候補として上がります。
CakePHPでサジェスト内容を作成する
ということで予想はつきますが、先に用意するサジェスト部分をデータベースから取得すれば簡単に出来そうです。
適当に以下の様なものを作ります。
コントローラー(TestsController)
最終的に、JSONデータに変換しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public function form() { $conditions = array( 'NOT' => array( 'OR' => array( 'Test.word' => NULL, 'Test.word' => '', ) ), 'AND' => array( 'Test.publish' => 1, ) ); $fields = array('Test.id', 'Test.word'); $suggestWordArray = $this->Test->find( 'list', array( 'conditions' => $conditions, 'fields' => $fields, 'recursive' => -1, 'order' => $order, ) ); // 重複を削除し、要素番号(キー)を0から振り直す $data = array_values(array_unique($suggestWordArray)); $suggestWordJson = json_encode($data); // 配列をJsonデータへ変換 $this->set('suggestWordJson', $suggestWordJson); } |
ビュー(/tests/form.ctp)
先ほどの、「availableTags」配列内容部分をPHPの出力にするだけ。
お手軽。
1 2 3 4 5 6 7 |
<script> var availableTags = [<?php echo $suggestWordJson; ?>]; $("#autocomplete").autocomplete({ source: availableTags }); </script> |
先頭文字で語句を指定、作成したい場合【応用1】
やってみたかったこと
先の場合、"a"を入れた場合、「語句に"a"が含まれるもの」を候補として上がっていましたが、「"a"から始まるもの」を候補として上げたい場合の方法です。
サジェスト内容の作成、抽出
ビュー(/tests/form.ctp)
1 2 3 4 5 6 7 8 9 10 |
<script> $(function() { $('#autocomplete').autocomplete({ source: '/tests/autoSuggest', // ← URLで指定 autoFocus: true, delay: 500, minLength: 1 }); }); </script> |
適当なコントローラーとアクションを作成し、URLで指定。これで、$_GET['term'] で指定URLにパラメータを渡せます。
そのパラメータを利用してサジェスト候補を作成すれば良いだけです。
コントローラー(TestsController)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
public function autoSuggest2() { $term = $this->params['url']['term']; $conditions = array( 'NOT' => array( 'OR' => array( 'Test.word' => NULL, 'Test.word' => '', ) ), 'AND' => array( 'Test.publish' => 1, ) ); $fields = array('Test.id', 'Test.word'); $suggestWordArray = $this->Test->find( 'list', array( 'conditions' => $conditions, 'fields' => $fields, 'recursive' => -1, 'order' => $order, ) ); // サジェスト候補の作成 $data = array(); if (!empty($term)) { foreach ($suggestWordArray as $word) { $position = strpos(strtolower($word), strtolower($term)); if ($position !== false && $position == 0) { $data[] = $word; } } } else { $data = $suggestWordArray; } echo json_encode($data); } |
結果
"a"と入れた場合、
- ActionScript
- AppleScript
- Asp
"o"と入れた場合は候補は表示されず、という感じです。
若干、レスポンスは遅いのですが、ほしい形になりました。
正直、採用するかどうかは微妙なところ。
CakePHPのAJAXを使って、ややこしくしてみた【応用2】
インプットに入力された文字からリアルタイムでSQL作成、候補として出力する方法を考えてみました。
最終的には採用しませんでしたが、いつか役に立つかも知れない備忘録なので載っけておきます。
ビュー
対象のフォームに対する keyup に bind する形のコードを書きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<script> $(document).ready(function(){ $('.autoComp').bind('keyup', function(){ var keyword = $(this).val(); availableTags = new Array(); $.ajax({ 'type': 'get', 'dataType': 'json', 'url': '/tests/autoSuggest?query=' + keyword, 'success': function(data) { if (data != '') { // 成功時の処理。Testテーブルからリストを取得する。 availableTags = data; $('#autocomplete').autocomplete({ source: availableTags, autoFocus: true, delay: 500, minLength: 1 }); } }, 'error': function() { // アクション側でExceptionが投げられた場合はここに来る。 // エラーをここで処理したい場合はExceptionを投げても良い } }); }); }); </script> |
コントローラ(TestController)
最終的にJSON形式にして出力しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public function autoSuggest() { $this->layout = false; $this->autoRender = false; $data = ''; $json = ''; // Ajax以外の通信の場合 if (!$this->request->is('ajax')) { throw new BadRequestException(); } if (!empty($this->params['url']['query'])) { $options = array( 'fields' => array('Test.id', 'Test.word'), 'conditions' => array( 'OR' => array( 'Test.word LIKE' => $this->params['url']['query'] . '%' ), ), 'limit' => 20 ); $datas = $this->Test->find('list', $options); $data = array_values(array_unique($datas)); } $json = json_encode($data); // Json形式に return $json; } |
これで、テキストボックスに語句を入力するたびに、SQLを作成し、候補を出力するようになりました。
CakePHP2 + AJAX がよくわかっていない上に、これも微妙にレスポンスが悪く、採用は見送りました。
多分、もっと良い方法がいろいろとあると思うのですが、今回はここまでということで。
参考にしたサイト様
http://api.jqueryui.com/1.10/autocomplete/#option-appendTo
http://d.hatena.ne.jp/solitary_shell/20101014/1287066107