Zend_Controller-ActionHelpers-AutoComplete.xml 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect3 id="zend.controller.actionhelpers.autocomplete">
  4. <title>AutoComplete</title>
  5. <para>
  6. Многие JavaScript-библиотеки для AJAX предоставляют функционал для
  7. автодополнения, с его помощью отображается список
  8. возможных соответствий в то время, пока пользователь набирает текст.
  9. Помощник <code>AutoComplete</code> предназначен для облегчения возврата
  10. допустимых ответов для функционала такого рода.
  11. </para>
  12. <para>
  13. Поскольку не все JavaScript-библиотеки реализуют автодополнение
  14. одинаково, то помощник <code>AutoComplete</code> предоставляет в
  15. абстрактном классе некоторый базовый функционал, необходимый для
  16. большинства библиотек, и конкретные реализации для отдельных библиотек.
  17. Возвращаемые данные в
  18. основном - JSON-массивы строк, JSON-массивы массивов (в которых каждый
  19. массив-член является ассоциативным массивом метаданных, используемых при
  20. создании списка), либо HTML.
  21. </para>
  22. <para>
  23. Базовое использование одинаково для всех реализаций:
  24. </para>
  25. <programlisting language="php"><![CDATA[
  26. class FooController extends Zend_Controller_Action
  27. {
  28. public function barAction()
  29. {
  30. // Выполнение некоторой логики...
  31. // Кодирование и отправка ответа:
  32. $this->_helper->autoCompleteDojo($data);
  33. // То же самое явным образом:
  34. $response = $this->_helper->autoCompleteDojo
  35. ->sendAutoCompletion($data);
  36. // Или просто подготовьте ответ для автодополнения:
  37. $response = $this->_helper->autoCompleteDojo
  38. ->prepareAutoCompletion($data);
  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. формате для автодополнения.
  55. </para></listitem>
  56. <listitem><para>
  57. Отправляет ответ.
  58. </para></listitem>
  59. </itemizedlist>
  60. <para>
  61. Доступные методы помощника включают в себя:
  62. </para>
  63. <itemizedlist>
  64. <listitem><para>
  65. <code>disableLayouts()</code> может использоваться для
  66. отключения макетов и ViewRenderer. Обычно он вызывается в
  67. <code>prepareAutoCompletion()</code>.
  68. </para></listitem>
  69. <listitem><para>
  70. <code>encodeJson($data, $keepLayouts = false)</code> будет
  71. кодировать данные в формат JSON, при этом можно опционально
  72. включать или отключать макеты. Обычно этот метод вызывается в
  73. <code>prepareAutoCompletion()</code>.
  74. </para></listitem>
  75. <listitem><para>
  76. <code>prepareAutoCompletion($data, $keepLayouts = false)</code>
  77. используется для подготовки ответа в формате, необходимом для
  78. конкретной реализации, при этом можно опционально включать или
  79. отключать макеты. Возвращаемое значение может варьироваться в
  80. зависимости от используемой реализации.
  81. </para></listitem>
  82. <listitem><para>
  83. <code>sendAutoCompletion($data, $keepLayouts = false)</code>
  84. используется для отправки данных в формате, необходимом для
  85. конкретной реализации. Он вызывает
  86. <code>prepareAutoCompletion()</code> и затем отправляет ответ.
  87. </para></listitem>
  88. <listitem><para>
  89. <code>direct($data, $sendNow = true, $keepLayouts =
  90. false)</code>
  91. используется, когда помощник вызывается как метод брокера
  92. помощников. Флаг <varname>$sendNow</varname> используется для
  93. определения того, какой метод вызывать -
  94. <code>sendAutoCompletion()</code> или
  95. <code>prepareAutoCompletion()</code>. По умолчанию ответ
  96. отправляется сразу.
  97. </para></listitem>
  98. </itemizedlist>
  99. <para>
  100. В настоящее время <code>AutoComplete</code> поддерживает AJAX-библиотеки
  101. Dojo и Scriptaculous.
  102. </para>
  103. <sect4 id="zend.controller.actionhelpers.autocomplete.dojo">
  104. <title>Автодополнение c Dojo</title>
  105. <para>
  106. В Dojo нет собственно виджета для автодополнения, но есть два
  107. виджета, которые могут производить автодополнение: ComboBox и
  108. FilteringSelect. В обоих случаях они требуют использования хранилища
  109. данных, который реализует QueryReadStore, читайте документацию по
  110. <ulink url="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/data-retrieval-dojo-data-0">dojo.data</ulink> для получения более подробной информации по этой теме.
  111. </para>
  112. <para>
  113. В Zend Framework вы можете передавать простой индексный массив для
  114. помощника AutoCompleteDojo, и он будет возвращен в формате,
  115. пригодном для использования с хранилищем в Dojo:
  116. </para>
  117. <programlisting language="php"><![CDATA[
  118. // в контроллере действий:
  119. $this->_helper->autoCompleteDojo($data);
  120. ]]></programlisting>
  121. <example id="zend.controller.actionhelpers.autocomplete.dojo.example1">
  122. <title>Автодополнение с Dojo и Zend MVC</title>
  123. <para>
  124. Автодополнение с Dojo через Zend MVC требует реализации
  125. нескольких вещей:
  126. генерация объекта формы для того ComboBox, для которого нужно
  127. реализовать автодополнение, действие контроллера для
  128. обслуживания автодополнения, создание своего QueryReadStore для
  129. связи с этим действием и генерация javascript-кода для
  130. инициализации автодополнения.
  131. </para>
  132. <para>
  133. Для начала рассмотрим, что нужно сделать по части
  134. javascript. Dojo представляет собой полный фреймворк для
  135. создания объектно-ориентированного кода на языке JavaScript,
  136. почти так же, как Zend Framework на языке PHP. Он позволяет
  137. создавать псевдопространства имен, используя для этого иерархию
  138. директорий. Создадим директорию 'custom' на том же уровне,
  139. что и директория Dojo. В этой директории создадим файл
  140. TestNameReadStore.js со следующим содержимым:
  141. </para>
  142. <programlisting language="javascript"><![CDATA[
  143. dojo.provide("custom.TestNameReadStore");
  144. dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
  145. fetch:function (request) {
  146. request.serverQuery = { test:request.query.name };
  147. return this.inherited("fetch", arguments);
  148. }
  149. });
  150. ]]></programlisting>
  151. <para>
  152. Этот класс просто наследует от класса QueryReadStore фреймворка
  153. Dojo, который сам по себе является абстрактным. Мы просто
  154. определяем метод, по которому производится запрос, и присваиваем
  155. его элементу 'test'.
  156. </para>
  157. <para>
  158. Далее создадим элемент формы, для которого хотим реализовать
  159. автодополнение:
  160. </para>
  161. <programlisting language="php"><![CDATA[
  162. class TestController extends Zend_Controller_Action
  163. {
  164. protected $_form;
  165. public function getForm()
  166. {
  167. if (null === $this->_form) {
  168. $this->_form = new Zend_Form();
  169. $this->_form->setMethod('get')
  170. ->setAction(
  171. $this->getRequest()->getBaseUrl() . '/test/process'
  172. )
  173. ->addElements(array(
  174. 'test' => array('type' => 'text', 'options' => array(
  175. 'filters' => array('StringTrim'),
  176. 'dojoType' => array('dijit.form.ComboBox'),
  177. 'store' => 'testStore',
  178. 'autoComplete' => 'false',
  179. 'hasDownArrow' => 'true',
  180. 'label' => 'Your input:',
  181. )),
  182. 'go' => array('type' => 'submit',
  183. 'options' => array('label' => 'Go!'))
  184. ));
  185. }
  186. return $this->_form;
  187. }
  188. }
  189. ]]></programlisting>
  190. <para>
  191. Здесь мы просто создаем форму с методами 'test' и 'go'. Метод
  192. 'test' добавляет несколько специальных, специфических для Dojo
  193. атрибутов: dojoType, store, autoComplete и hasDownArrow. Через
  194. 'dojoType' мы указываем, что создается ComboBox, он связан
  195. с хранилищем данных (ключ 'store') 'testStore'. Устанавливая
  196. 'autoComplete' в false, мы говорим Dojo, чтобы он не выбирал
  197. автоматически первое соответствие, а вместо этого показывал
  198. список соответсвий. Наконец, 'hasDownArrow' создает стрелку
  199. наподобие той, что присутствует в выпадающем списке, чтобы можно
  200. было выводить и убирать список соответствий.
  201. </para>
  202. <para>
  203. Добавим метод для отображения формы и действие для обработки
  204. автодополнения:
  205. </para>
  206. <programlisting language="php"><![CDATA[
  207. class TestController extends Zend_Controller_Action
  208. {
  209. // ...
  210. /**
  211. * Страница с формой
  212. */
  213. public function indexAction()
  214. {
  215. $this->view->form = $this->getForm();
  216. }
  217. public function autocompleteAction()
  218. {
  219. if ('ajax' != $this->_getParam('format', false)) {
  220. return $this->_helper->redirector('index');
  221. }
  222. if ($this->getRequest()->isPost()) {
  223. return $this->_helper->redirector('index');
  224. }
  225. $match = trim($this->getRequest()->getQuery('test', ''));
  226. $matches = array();
  227. foreach ($this->getData() as $datum) {
  228. if (0 === strpos($datum, $match)) {
  229. $matches[] = $datum;
  230. }
  231. }
  232. $this->_helper->autoCompleteDojo($matches);
  233. }
  234. }
  235. ]]></programlisting>
  236. <para>
  237. В методе <code>autocompleteAction()</code> мы делаем несколько
  238. вещей. Сначала мы проверяем, был ли произведен POST-запрос и
  239. имеет ли параметр 'format' значение 'ajax', это помогает
  240. отсечь большинство ложных запросов. Далее мы получаем
  241. параметр 'test' и сравниваем его с нашими данными (здесь я
  242. намеренно опустил реализацию метода <code>getData()</code>,
  243. источники данных могут быть любыми). В конце выполнения
  244. передаем найденные соответствия помощнику AutoCompletion.
  245. </para>
  246. <para>
  247. Теперь на очереди написание скрипта вида для страницы с формой.
  248. В нем нужно установить хранилище данных, вывести
  249. форму и подключить все необходимые библиотеки
  250. Dojo, включая наше хранилище данных. Ниже приведен
  251. скрипт вида с комментариями:
  252. </para>
  253. <programlisting language="php"><![CDATA[
  254. <?php // установка хранилища данных: ?>
  255. <div dojoType="custom.TestNameReadStore" jsId="testStore"
  256. url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
  257. requestMethod="get"></div>
  258. <?php // рендеринг формы: ?>
  259. <?php echo $this->form ?>
  260. <? // подключение CSS для Dojo в HTML-заголовке: ?>
  261. <?php $this->headStyle()->captureStart() ?>
  262. @import "<?php echo $this->baseUrl()
  263. ?>/javascript/dijit/themes/tundra/tundra.css";
  264. @import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
  265. <?php $this->headStyle()->captureEnd() ?>
  266. <?php // подключение javascript в HTML-заголовке, включая все
  267. // необходимые библиотеки для Dojo: ?>
  268. <?php $this->headScript()
  269. ->setAllowArbitraryAttributes(true)
  270. ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
  271. 'text/javascript',
  272. array('djConfig' => 'parseOnLoad: true'))
  273. ->captureStart() ?>
  274. djConfig.usePlainJson=true;
  275. dojo.registerModulePath("custom","../custom");
  276. dojo.require("dojo.parser");
  277. dojo.require("dojox.data.QueryReadStore");
  278. dojo.require("dijit.form.ComboBox");
  279. dojo.require("custom.TestNameReadStore");
  280. <?php $this->headScript()->captureEnd() ?>
  281. ]]></programlisting>
  282. <para>
  283. Обратите внимание на вызовы помощников видов, таких, как
  284. headStyle м headScript, - это метки заполнения, которые могут
  285. затем рендериться в HTML-заголовке скрипта макета.
  286. </para>
  287. <para>
  288. Теперь у нас есть всё для того, чтобы автодополнение с Dojo заработало.
  289. </para>
  290. </example>
  291. </sect4>
  292. <sect4 id="zend.controller.actionhelpers.autocomplete.scriptaculous">
  293. <title>Автодополнение с Scriptaculous</title>
  294. <para>
  295. <ulink url="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter">Scriptaculous</ulink>
  296. ожидает HTML-ответ в определенном формате.
  297. </para>
  298. <para>
  299. С этой библиотекой используется помощник
  300. 'AutoCompleteScriptaculous'.
  301. Просто передавайте ему массив данных, и он создает ответ HTML,
  302. совместимый с Ajax.Autocompleter.
  303. </para>
  304. </sect4>
  305. </sect3>
  306. <!--
  307. vim:se ts=4 sw=4 et:
  308. -->