AutoComplete
多くの AJAX 用 javascript ライブラリでは、
オートコンプリート機能を提供しています。
これは、ユーザがタイプした内容にマッチする可能性のある候補の一覧を表示するものです。
AutoComplete ヘルパーは、
このような場合に使用できるレスポンスを返すためのものです。
オートコンプリート機能の実装方法は JS ライブラリによって異なるので、
AutoComplete では多くのライブラリで使用する共通機能を抽象化しています。
そして、個々のライブラリにあわせた実装を用意しています。
返り値の型は、JSON 形式の文字列の配列か
JSON 形式の配列の配列
(内部の配列は、選択リストを作成する際に使用するメタデータの連想配列)
あるいは HTML となります。
どの実装についての基本的な使用法は同じです。
_helper->autoCompleteDojo($data);
// あるいは明示的に
$response = $this->_helper->autoCompleteDojo
->sendAutoCompletion($data);
// あるいは単純にオートコンプリート用のレスポンスを準備します
$response = $this->_helper->autoCompleteDojo
->prepareAutoCompletion($data);
}
}
]]>
デフォルトでは以下のような作業を行います。
レイアウト機能と ViewRenderer を無効にする。
適切なレスポンスヘッダを設定する。
レスポンスボディにエンコード/フォーマットしたデータを設定する。
レスポンスを送信する。
このヘルパーでは次のようなメソッドが使用できます。
disableLayouts() は、レイアウト機能と
ViewRenderer を無効にします。一般に、これは
prepareAutoCompletion() の中でコールされます。
encodeJson($data, $keepLayouts = false)
はデータを JSON 形式にエンコードし、オプションでレイアウト機能の有効/無効
を切り替えます。一般に、これは
prepareAutoCompletion() の中でコールされます。
prepareAutoCompletion($data, $keepLayouts = false)
は、各種具象実装にあわせてレスポンスデータをフォーマットし、
オプションでレイアウト機能の有効/無効を切り替えます。
返り値は実装によって異なります。
sendAutoCompletion($data, $keepLayouts = false)
は、各種具象実装にあわせてフォーマットしたレスポンスデータを送信します。
これは、prepareAutoCompletion() をコールしたあとでレスポンスを送信します。
direct($data, $sendNow = true, $keepLayouts =
false) は、このヘルパーをヘルパーブローカのメソッドとしてコールする場合に使用します。
$sendNow フラグは、
sendAutoCompletion() と
prepareAutoCompletion() のどちらをコールするかを指定するものです。
現在 AutoComplete がサポートしている AJAX
ライブラリは、Dojo と Scriptaculous です。
Dojo でのオートコンプリート
Dojo には、オートコンプリートのためだけのウィジェットはありません。
しかし、ComboBox と FilteringSelect
のふたつのウィジェットがオートコンプリート機能を持っています。
どちらのウィジェットも、QueryReadStore
を実装したデータを必要とします。詳細は
dojo.data
のドキュメントを参照ください。
Zend Framework では、単純な数値添字の配列を
AutoCompleteDojo ヘルパーに渡します。
そうすると、適切な形式の JSON オブジェクトを返します。
_helper->autoCompleteDojo($data);
]]>
Zend MVC を使用した、Dojo でのオートコンプリート
Zend MVC で Dojo によるオートコンプリートを使用するには、
いくつかの準備が必要です。オートコンプリートを使用したい
ComboBox 用にフォームオブj稀有とを作成し、
オートコンプリートの結果を提供するためのコントローラアクションを作成し、
オートコンプリートアクションに接続するための
独自の QueryReadStore を作成し、
サーバ側でオートコンプリートを行わせるための javascript
を作成することになります。
まずは、必要となる javascript を見ていきましょう。
Dojo は javascript によるオブジェクト指向プログラミングを行うための
完全なフレームワークで、ちょうど PHP における Zend Framework
のようなものです。その中には、
ディレクトリ構造を用いて擬似的な名前空間を作成する機能もあります。
ここでは、Dojo の配布ファイルの Dojo
ディレクトリと同じ階層に 'custom' ディレクトリを作成します。
そのディレクトリの中に TestNameReadStore.js
という javascript ファイルを作成し、次のようなコードを書きます。
このクラスは、単に Dojo 自身の QueryReadStore
クラスを継承したものです。継承元のクラス自体は抽象クラスです。
そこにリクエスト用のメソッドを定義し、'test'
要素に割り当てています。
次に、オートコンプリートを行うためのフォーム要素を作成します。
_form) {
$this->_form = new Zend_Form();
$this->_form->setMethod('get')
->setAction(
$this->getRequest()->getBaseUrl() . '/test/process'
)
->addElements(array(
'test' => array('type' => 'text', 'options' => array(
'filters' => array('StringTrim'),
'dojoType' => array('dijit.form.ComboBox'),
'store' => 'testStore',
'autoComplete' => 'false',
'hasDownArrow' => 'true',
'label' => 'Your input:',
)),
'go' => array('type' => 'submit',
'options' => array('label' => 'Go!'))
));
}
return $this->_form;
}
}
]]>
ここでは、単に 'test' と 'go' メソッドのみを持つフォームを作成します。
'test' メソッドは、特別な Dojo 固有の属性
dojoType、store、autoComplete および hasDownArrow
を追加します。dojoType では、これから ComboBox
を作成することを指定します。そして、それを 'testStore' のデータストア
(キー 'store') にリンクします。詳細は後ほど説明します。
'autoComplete' を FALSE に設定することで、
最初にマッチしたものを自動選択するのではなく
マッチしたものの一覧を表示するよう Dojo に指示します。
最後に 'hasDownArrow' でセレクトボックス風の下向き矢印を作ります。
これで、マッチしたものを表示したり隠したりできるようになります。
では、フォームを表示するためのメソッドと
オートコンプリートの処理用のエンドポイントを作成してみましょう。
view->form = $this->getForm();
}
public function autocompleteAction()
{
if ('ajax' != $this->_getParam('format', false)) {
return $this->_helper->redirector('index');
}
if ($this->getRequest()->isPost()) {
return $this->_helper->redirector('index');
}
$match = trim($this->getRequest()->getQuery('test', ''));
$matches = array();
foreach ($this->getData() as $datum) {
if (0 === strpos($datum, $match)) {
$matches[] = $datum;
}
}
$this->_helper->autoCompleteDojo($matches);
}
}
]]>
autocompleteAction()
ではいくつかの作業を行っています。
まず、POST リクエストを受け取ったことを確実にし、
'format' パラメータの値を 'ajax' に設定します。
これにより、余計なクエリがアクションに送られることを減らします。
次に、'test' パラメータの内容を確認し、私たちのデータと比較します
(ここでは、getData() の実装は意図的に控えています。
何らかのデータソースを使用することになるでしょう)。
最後に、マッチした内容を AutoCompletion ヘルパーに送信します。
これでバックエンド側の準備はすべて整いました。
次に、ページのビュースクリプト側ではどうすればいいのかを考えてみましょう。
まず、データストアを用意しなければなりません。
次にフォームをレンダリングし、最後に適切な Dojo ライブラリ
(使用するデータストアも含む) を読み込みます。
ビュースクリプトを見てみましょう。
適宜コメントを入れてあります。
form ?>
headStyle()->captureStart() ?>
@import "baseUrl()
?>/javascript/dijit/themes/tundra/tundra.css";
@import "baseUrl() ?>/javascript/dojo/resources/dojo.css";
headStyle()->captureEnd() ?>
headScript()
->setAllowArbitraryAttributes(true)
->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
'text/javascript',
array('djConfig' => 'parseOnLoad: true'))
->captureStart() ?>
djConfig.usePlainJson=true;
dojo.registerModulePath("custom","../custom");
dojo.require("dojo.parser");
dojo.require("dojox.data.QueryReadStore");
dojo.require("dijit.form.ComboBox");
dojo.require("custom.TestNameReadStore");
headScript()->captureEnd() ?>
]]>
headStyle や headScript といったビューヘルパーのコールに注意しましょう。
これらはプレースホルダで、ビュースクリプトをレンダリングする際に
HTML の head セクションとなります。
これで、Dojo のオートコンプリートを動作させるための準備がすべて整いました。
Scriptaculous でのオートコンプリート
Scriptaculous
は、所定の形式の HTML レスポンスを受け取ることを想定しています。
このライブラリで使用するヘルパーは 'AutoCompleteScriptaculous' です。
このヘルパーにデータの配列を渡せば、Ajax.Autocompleter
に対応した形式の HTML レスポンスができあがります。