Zend_Controller-ActionHelpers-AutoComplete.xml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <!-- EN-Revision: 14978 -->
  4. <sect3 id="zend.controller.actionhelpers.autocomplete">
  5. <title>AutoComplete</title>
  6. <para>
  7. 多くの AJAX 用 javascript ライブラリでは、
  8. オートコンプリート機能を提供しています。
  9. これは、ユーザがタイプした内容にマッチする可能性のある候補の一覧を表示するものです。
  10. <code>AutoComplete</code> ヘルパーは、
  11. このような場合に使用できるレスポンスを返すためのものです。
  12. </para>
  13. <para>
  14. オートコンプリート機能の実装方法は JS ライブラリによって異なるので、
  15. <code>AutoComplete</code> では多くのライブラリで使用する共通機能を抽象化しています。
  16. そして、個々のライブラリにあわせた実装を用意しています。
  17. 返り値の型は、JSON 形式の文字列の配列か
  18. JSON 形式の配列の配列 (内部の配列は、選択リストを作成する際に使用するメタデータの連想配列)
  19. あるいは HTML となります。
  20. </para>
  21. <para>
  22. どの実装についての基本的な使用法は同じです。
  23. </para>
  24. <programlisting role="php"><![CDATA[
  25. class FooController extends Zend_Controller_Action
  26. {
  27. public function barAction()
  28. {
  29. // 何かの処理をします...
  30. // エンコードしたレスポンスを送信します
  31. $this->_helper->autoCompleteDojo($data);
  32. // あるいは明示的に
  33. $response = $this->_helper->autoCompleteDojo
  34. ->sendAutoCompletion($data);
  35. // あるいは単純にオートコンプリート用のレスポンスを準備します
  36. $response = $this->_helper->autoCompleteDojo
  37. ->prepareAutoCompletion($data);
  38. }
  39. }
  40. ]]>
  41. </programlisting>
  42. <para>
  43. デフォルトでは以下のような作業を行います。
  44. </para>
  45. <itemizedlist>
  46. <listitem><para>
  47. レイアウト機能と ViewRenderer を無効にする。
  48. </para></listitem>
  49. <listitem><para>
  50. 適切なレスポンスヘッダを設定する。
  51. </para></listitem>
  52. <listitem><para>
  53. レスポンスボディにエンコード/フォーマットしたデータを設定する。
  54. </para></listitem>
  55. <listitem><para>
  56. レスポンスを送信する。
  57. </para></listitem>
  58. </itemizedlist>
  59. <para>
  60. このヘルパーでは次のようなメソッドが使用できます。
  61. </para>
  62. <itemizedlist>
  63. <listitem><para>
  64. <code>disableLayouts()</code> は、レイアウト機能と
  65. ViewRenderer を無効にします。一般に、これは
  66. <code>prepareAutoCompletion()</code> の中でコールされます。
  67. </para></listitem>
  68. <listitem><para>
  69. <code>encodeJson($data, $keepLayouts = false)</code>
  70. はデータを JSON 形式にエンコードし、オプションでレイアウト機能の有効/無効
  71. を切り替えます。一般に、これは
  72. <code>prepareAutoCompletion()</code> の中でコールされます。
  73. </para></listitem>
  74. <listitem><para>
  75. <code>prepareAutoCompletion($data, $keepLayouts = false)</code>
  76. は、各種具象実装にあわせてレスポンスデータをフォーマットし、
  77. オプションでレイアウト機能の有効/無効を切り替えます。
  78. 返り値は実装によって異なります。
  79. </para></listitem>
  80. <listitem><para>
  81. <code>sendAutoCompletion($data, $keepLayouts = false)</code>
  82. は、各種具象実装にあわせてフォーマットしたレスポンスデータを送信します。
  83. これは、<code>prepareAutoCompletion()</code> をコールしたあとでレスポンスを送信します。
  84. </para></listitem>
  85. <listitem><para>
  86. <code>direct($data, $sendNow = true, $keepLayouts =
  87. false)</code> は、このヘルパーをヘルパーブローカのメソッドとしてコールする場合に使用します。
  88. <code>$sendNow</code> フラグは、
  89. <code>sendAutoCompletion()</code> と
  90. <code>prepareAutoCompletion()</code> のどちらをコールするかを指定するものです。
  91. </para></listitem>
  92. </itemizedlist>
  93. <para>
  94. 現在 <code>AutoComplete</code> がサポートしている AJAX
  95. ライブラリは、Dojo と Scriptaculous です。
  96. </para>
  97. <sect4 id="zend.controller.actionhelpers.autocomplete.dojo">
  98. <title>Dojo でのオートコンプリート</title>
  99. <para>
  100. Dojo には、オートコンプリートのためだけのウィジェットはありません。
  101. しかし、ComboBox と FilteringSelect
  102. のふたつのウィジェットがオートコンプリート機能を持っています。
  103. どちらのウィジェットも、QueryReadStore
  104. を実装したデータを必要とします。詳細は
  105. <ulink url="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/data-retrieval-dojo-data-0">dojo.data</ulink>
  106. のドキュメントを参照ください。
  107. </para>
  108. <para>
  109. Zend Framework では、単純な数値添字の配列を
  110. AutoCompleteDojo ヘルパーに渡します。
  111. そうすると、適切な形式の JSON オブジェクトを返します。
  112. </para>
  113. <programlisting role="php"><![CDATA[
  114. // コントローラのアクション内で
  115. $this->_helper->autoCompleteDojo($data);
  116. ]]>
  117. </programlisting>
  118. <example id="zend.controller.actionhelpers.autocomplete.dojo.example1">
  119. <title>Zend MVC を使用した、Dojo でのオートコンプリート</title>
  120. <para>
  121. Zend MVC で Dojo によるオートコンプリートを使用するには、
  122. いくつかの準備が必要です。オートコンプリートを使用したい
  123. ComboBox 用にフォームオブj稀有とを作成し、
  124. オートコンプリートの結果を提供するためのコントローラアクションを作成し、
  125. オートコンプリートアクションに接続するための
  126. 独自の QueryReadStore を作成し、
  127. サーバ側でオートコンプリートを行わせるための javascript
  128. を作成することになります。
  129. </para>
  130. <para>
  131. まずは、必要となる javascript を見ていきましょう。
  132. Dojo は javascript によるオブジェクト指向プログラミングを行うための
  133. 完全なフレームワークで、ちょうど PHP における Zend Framework
  134. のようなものです。その中には、
  135. ディレクトリ構造を用いて擬似的な名前空間を作成する機能もあります。
  136. ここでは、Dojo の配布ファイルの Dojo
  137. ディレクトリと同じ階層に 'custom' ディレクトリを作成します。
  138. そのディレクトリの中に TestNameReadStore.js
  139. という javascript ファイルを作成し、次のようなコードを書きます。
  140. </para>
  141. <programlisting role="javascript"><![CDATA[
  142. dojo.provide("custom.TestNameReadStore");
  143. dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
  144. fetch:function (request) {
  145. request.serverQuery = { test:request.query.name };
  146. return this.inherited("fetch", arguments);
  147. }
  148. });
  149. ]]>
  150. </programlisting>
  151. <para>
  152. このクラスは、単に Dojo 自身の QueryReadStore
  153. クラスを継承したものです。継承元のクラス自体は抽象クラスです。
  154. そこにリクエスト用のメソッドを定義し、'test'
  155. 要素に割り当てています。
  156. </para>
  157. <para>
  158. 次に、オートコンプリートを行うためのフォーム要素を作成します。
  159. </para>
  160. <programlisting role="php"><![CDATA[
  161. class TestController extends Zend_Controller_Action
  162. {
  163. protected $_form;
  164. public function getForm()
  165. {
  166. if (null === $this->_form) {
  167. $this->_form = new Zend_Form();
  168. $this->_form->setMethod('get')
  169. ->setAction(
  170. $this->getRequest()->getBaseUrl() . '/test/process'
  171. )
  172. ->addElements(array(
  173. 'test' => array('type' => 'text', 'options' => array(
  174. 'filters' => array('StringTrim'),
  175. 'dojoType' => array('dijit.form.ComboBox'),
  176. 'store' => 'testStore',
  177. 'autoComplete' => 'false',
  178. 'hasDownArrow' => 'true',
  179. 'label' => 'Your input:',
  180. )),
  181. 'go' => array('type' => 'submit',
  182. 'options' => array('label' => 'Go!'))
  183. ));
  184. }
  185. return $this->_form;
  186. }
  187. }
  188. ]]>
  189. </programlisting>
  190. <para>
  191. ここでは、単に 'test' と 'go' メソッドのみを持つフォームを作成します。
  192. 'test' メソッドは、特別な Dojo 固有の属性
  193. dojoType、store、autoComplete および hasDownArrow
  194. を追加します。dojoType では、これから ComboBox
  195. を作成することを指定します。そして、それを 'testStore' のデータストア
  196. (キー 'store') にリンクします。詳細は後ほど説明します。
  197. 'autoComplete' を false に設定することで、
  198. 最初にマッチしたものを自動選択するのではなく
  199. マッチしたものの一覧を表示するよう Dojo に指示します。
  200. 最後に 'hasDownArrow' でセレクトボックス風の下向き矢印を作ります。
  201. これで、マッチしたものを表示したり隠したりできるようになります。
  202. </para>
  203. <para>
  204. では、フォームを表示するためのメソッドと
  205. オートコンプリートの処理用のエンドポイントを作成してみましょう。
  206. </para>
  207. <programlisting role="php"><![CDATA[
  208. class TestController extends Zend_Controller_Action
  209. {
  210. // ...
  211. /**
  212. * 最初のページ
  213. */
  214. public function indexAction()
  215. {
  216. $this->view->form = $this->getForm();
  217. }
  218. public function autocompleteAction()
  219. {
  220. if ('ajax' != $this->_getParam('format', false)) {
  221. return $this->_helper->redirector('index');
  222. }
  223. if ($this->getRequest()->isPost()) {
  224. return $this->_helper->redirector('index');
  225. }
  226. $match = trim($this->getRequest()->getQuery('test', ''));
  227. $matches = array();
  228. foreach ($this->getData() as $datum) {
  229. if (0 === strpos($datum, $match)) {
  230. $matches[] = $datum;
  231. }
  232. }
  233. $this->_helper->autoCompleteDojo($matches);
  234. }
  235. }
  236. ]]>
  237. </programlisting>
  238. <para>
  239. <code>autocompleteAction()</code>
  240. ではいくつかの作業を行っています。
  241. まず、POST リクエストを受け取ったことを確実にし、
  242. 'format' パラメータの値を 'ajax' に設定します。
  243. これにより、余計なクエリがアクションに送られることを減らします。
  244. 次に、'test' パラメータの内容を確認し、私たちのデータと比較します
  245. (ここでは、<code>getData()</code> の実装は意図的に控えています。
  246. 何らかのデータソースを使用することになるでしょう)。
  247. 最後に、マッチした内容を AutoCompletion ヘルパーに送信します。
  248. </para>
  249. <para>
  250. これでバックエンド側の準備はすべて整いました。
  251. 次に、ページのビュースクリプト側ではどうすればいいのかを考えてみましょう。
  252. まず、データストアを用意しなければなりません。
  253. 次にフォームをレンダリングし、最後に適切な Dojo ライブラリ
  254. (使用するデータストアも含む) を読み込みます。
  255. ビュースクリプトを見てみましょう。
  256. 適宜コメントを入れてあります。
  257. </para>
  258. <programlisting role="php"><![CDATA[
  259. <?php // データストアの準備 ?>
  260. <div dojoType="custom.TestNameReadStore" jsId="testStore"
  261. url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
  262. requestMethod="get"></div>
  263. <?php // フォームのレンダリング ?>
  264. <?php echo $this->form ?>
  265. <?php // Dojo 関連の CSS の、HTML head での読み込み ?>
  266. <?php $this->headStyle()->captureStart() ?>
  267. @import "<?php echo $this->baseUrl()
  268. ?>/javascript/dijit/themes/tundra/tundra.css";
  269. @import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
  270. <?php $this->headStyle()->captureEnd() ?>
  271. <?php // 必要な Dojo ライブラリを含む javascript の、
  272. // HTML head での読み込み ?>
  273. <?php $this->headScript()
  274. ->setAllowArbitraryAttributes(true)
  275. ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
  276. 'text/javascript',
  277. array('djConfig' => 'parseOnLoad: true'))
  278. ->captureStart() ?>
  279. djConfig.usePlainJson=true;
  280. dojo.registerModulePath("custom","../custom");
  281. dojo.require("dojo.parser");
  282. dojo.require("dojox.data.QueryReadStore");
  283. dojo.require("dijit.form.ComboBox");
  284. dojo.require("custom.TestNameReadStore");
  285. <?php $this->headScript()->captureEnd() ?>
  286. ]]>
  287. </programlisting>
  288. <para>
  289. headStyle や headScript といったビューヘルパーのコールに注意しましょう。
  290. これらはプレースホルダで、ビュースクリプトをレンダリングする際に
  291. HTML の head セクションとなります。
  292. </para>
  293. <para>
  294. これで、Dojo のオートコンプリートを動作させるための準備がすべて整いました。
  295. </para>
  296. </example>
  297. </sect4>
  298. <sect4 id="zend.controller.actionhelpers.autocomplete.scriptaculous">
  299. <title>Scriptaculous でのオートコンプリート</title>
  300. <para>
  301. <ulink url="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter">Scriptaculous</ulink>
  302. は、所定の形式の HTML レスポンスを受け取ることを想定しています。
  303. </para>
  304. <para>
  305. このライブラリで使用するヘルパーは 'AutoCompleteScriptaculous' です。
  306. このヘルパーにデータの配列を渡せば、Ajax.Autocompleter
  307. に対応した形式の HTML レスポンスができあがります。
  308. </para>
  309. </sect4>
  310. </sect3>
  311. <!--
  312. vim:se ts=4 sw=4 et:
  313. -->