Zend_Controller-ActionHelpers-AutoComplete.xml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <sect3 id="zend.controller.actionhelpers.autocomplete">
  2. <title>AutoComplete</title>
  3. <para>
  4. Многие JavaScript-библиотеки для AJAX предоставляют функционал для
  5. автодополнения, с его помощью отображается список
  6. возможных соответствий в то время, пока пользователь набирает текст.
  7. Помощник <code>AutoComplete</code> предназначен для облегчения возврата
  8. допустимых ответов для функционала такого рода.
  9. </para>
  10. <para>
  11. Поскольку не все JavaScript-библиотеки реализуют автодополнение
  12. одинаково, то помощник <code>AutoComplete</code> предоставляет в
  13. абстрактном классе некоторый базовый функционал, необходимый для
  14. большинства библиотек, и конкретные реализации для отдельных библиотек.
  15. Возвращаемые данные в
  16. основном - JSON-массивы строк, JSON-массивы массивов (в которых каждый
  17. массив-член является ассоциативным массивом метаданных, используемых при
  18. создании списка), либо HTML.
  19. </para>
  20. <para>
  21. Базовое использование одинаково для всех реализаций:
  22. </para>
  23. <programlisting role="php"><![CDATA[
  24. class FooController extends Zend_Controller_Action
  25. {
  26. public function barAction()
  27. {
  28. // Выполнение некоторой логики...
  29. // Кодирование и отправка ответа:
  30. $this->_helper->autoCompleteDojo($data);
  31. // То же самое явным образом:
  32. $response = $this->_helper->autoCompleteDojo
  33. ->sendAutoCompletion($data);
  34. // Или просто подготовьте ответ для автодополнения:
  35. $response = $this->_helper->autoCompleteDojo
  36. ->prepareAutoCompletion($data);
  37. }
  38. }
  39. ]]>
  40. </programlisting>
  41. <para>
  42. По умолчанию этот помощник делает следующее:
  43. </para>
  44. <itemizedlist>
  45. <listitem><para>
  46. Отключает макеты и ViewRenderer.
  47. </para></listitem>
  48. <listitem><para>
  49. Устанавливает необходимые заголовки ответа.
  50. </para></listitem>
  51. <listitem><para>
  52. Устанавливает тело ответа с закодированными данными в нужном
  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. зависимости от используемой реализации.
  80. </para></listitem>
  81. <listitem><para>
  82. <code>sendAutoCompletion($data, $keepLayouts = false)</code>
  83. используется для отправки данных в формате, необходимом для
  84. конкретной реализации. Он вызывает
  85. <code>prepareAutoCompletion()</code> и затем отправляет ответ.
  86. </para></listitem>
  87. <listitem><para>
  88. <code>direct($data, $sendNow = true, $keepLayouts =
  89. false)</code>
  90. используется, когда помощник вызывается как метод брокера
  91. помощников. Флаг <code>$sendNow</code> используется для
  92. определения того, какой метод вызывать -
  93. <code>sendAutoCompletion()</code> или
  94. <code>prepareAutoCompletion()</code>. По умолчанию ответ
  95. отправляется сразу.
  96. </para></listitem>
  97. </itemizedlist>
  98. <para>
  99. В настоящее время <code>AutoComplete</code> поддерживает AJAX-библиотеки
  100. Dojo и Scriptaculous.
  101. </para>
  102. <sect4 id="zend.controller.actionhelpers.autocomplete.dojo">
  103. <title>Автодополнение c Dojo</title>
  104. <para>
  105. В Dojo нет собственно виджета для автодополнения, но есть два
  106. виджета, которые могут производить автодополнение: ComboBox и
  107. FilteringSelect. В обоих случаях они требуют использования хранилища
  108. данных, который реализует QueryReadStore, читайте документацию по
  109. <ulink url="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/data-retrieval-dojo-data-0">dojo.data</ulink> для получения более подробной информации по этой теме.
  110. </para>
  111. <para>
  112. В Zend Framework вы можете передавать простой индексный массив для
  113. помощника AutoCompleteDojo, и он будет возвращен в формате,
  114. пригодном для использования с хранилищем в Dojo:
  115. </para>
  116. <programlisting role="php"><![CDATA[
  117. // в контроллере действий:
  118. $this->_helper->autoCompleteDojo($data);
  119. ]]>
  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 role="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. ]]>
  151. </programlisting>
  152. <para>
  153. Этот класс просто наследует от класса QueryReadStore фреймворка
  154. Dojo, который сам по себе является абстрактным. Мы просто
  155. определяем метод, по которому производится запрос, и присваиваем
  156. его элементу 'test'.
  157. </para>
  158. <para>
  159. Далее создадим элемент формы, для которого хотим реализовать
  160. автодополнение:
  161. </para>
  162. <programlisting role="php"><![CDATA[
  163. class TestController extends Zend_Controller_Action
  164. {
  165. protected $_form;
  166. public function getForm()
  167. {
  168. if (null === $this->_form) {
  169. $this->_form = new Zend_Form();
  170. $this->_form->setMethod('get')
  171. ->setAction(
  172. $this->getRequest()->getBaseUrl() . '/test/process'
  173. )
  174. ->addElements(array(
  175. 'test' => array('type' => 'text', 'options' => array(
  176. 'filters' => array('StringTrim'),
  177. 'dojoType' => array('dijit.form.ComboBox'),
  178. 'store' => 'testStore',
  179. 'autoComplete' => 'false',
  180. 'hasDownArrow' => 'true',
  181. 'label' => 'Your input:',
  182. )),
  183. 'go' => array('type' => 'submit',
  184. 'options' => array('label' => 'Go!'))
  185. ));
  186. }
  187. return $this->_form;
  188. }
  189. }
  190. ]]>
  191. </programlisting>
  192. <para>
  193. Здесь мы просто создаем форму с методами 'test' и 'go'. Метод
  194. 'test' добавляет несколько специальных, специфических для Dojo
  195. атрибутов: dojoType, store, autoComplete и hasDownArrow. Через
  196. 'dojoType' мы указываем, что создается ComboBox, он связан
  197. с хранилищем данных (ключ 'store') 'testStore'. Устанавливая
  198. 'autoComplete' в false, мы говорим Dojo, чтобы он не выбирал
  199. автоматически первое соответствие, а вместо этого показывал
  200. список соответсвий. Наконец, 'hasDownArrow' создает стрелку
  201. наподобие той, что присутствует в выпадающем списке, чтобы можно
  202. было выводить и убирать список соответствий.
  203. </para>
  204. <para>
  205. Добавим метод для отображения формы и действие для обработки
  206. автодополнения:
  207. </para>
  208. <programlisting role="php"><![CDATA[
  209. class TestController extends Zend_Controller_Action
  210. {
  211. // ...
  212. /**
  213. * Страница с формой
  214. */
  215. public function indexAction()
  216. {
  217. $this->view->form = $this->getForm();
  218. }
  219. public function autocompleteAction()
  220. {
  221. if ('ajax' != $this->_getParam('format', false)) {
  222. return $this->_helper->redirector('index');
  223. }
  224. if ($this->getRequest()->isPost()) {
  225. return $this->_helper->redirector('index');
  226. }
  227. $match = trim($this->getRequest()->getQuery('test', ''));
  228. $matches = array();
  229. foreach ($this->getData() as $datum) {
  230. if (0 === strpos($datum, $match)) {
  231. $matches[] = $datum;
  232. }
  233. }
  234. $this->_helper->autoCompleteDojo($matches);
  235. }
  236. }
  237. ]]>
  238. </programlisting>
  239. <para>
  240. В методе <code>autocompleteAction()</code> мы делаем несколько
  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. </para>
  256. <programlisting role="php"><![CDATA[
  257. <? // установка хранилища данных: ?>
  258. <div dojoType="custom.TestNameReadStore" jsId="testStore"
  259. url="<?= $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
  260. requestMethod="get"></div>
  261. <? // рендеринг формы: ?>
  262. <?= $this->form ?>
  263. <? // подключение css для Dojo в HTML-заголовке: ?>
  264. <? $this->headStyle()->captureStart() ?>
  265. @import "<?= $this->baseUrl() ?>/javascript/dijit/themes/tundra/tundra.css";
  266. @import "<?= $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
  267. <? $this->headStyle()->captureEnd() ?>
  268. <? // подключение javascript в HTML-заголовке, включая все
  269. // необходимые библиотеки для Dojo: ?>
  270. <? $this->headScript()
  271. ->setAllowArbitraryAttributes(true)
  272. ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
  273. 'text/javascript',
  274. array('djConfig' => 'parseOnLoad: true'))
  275. ->captureStart() ?>
  276. djConfig.usePlainJson=true;
  277. dojo.registerModulePath("custom","../custom");
  278. dojo.require("dojo.parser");
  279. dojo.require("dojox.data.QueryReadStore");
  280. dojo.require("dijit.form.ComboBox");
  281. dojo.require("custom.TestNameReadStore");
  282. <? $this->headScript()->captureEnd() ?>
  283. ]]></programlisting>
  284. <para>
  285. Обратите внимание на вызовы помощников видов, таких, как
  286. headStyle м headScript, - это метки заполнения, которые могут
  287. затем рендериться в HTML-заголовке скрипта макета.
  288. </para>
  289. <para>
  290. Теперь у нас есть всё для того, чтобы автодополнение с Dojo заработало.
  291. </para>
  292. </example>
  293. </sect4>
  294. <sect4 id="zend.controller.actionhelpers.autocomplete.scriptaculous">
  295. <title>Автодополнение с Scriptaculous</title>
  296. <para>
  297. <ulink url="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter">Scriptaculous</ulink>
  298. ожидает HTML-ответ в определенном формате.
  299. </para>
  300. <para>
  301. С этой библиотекой используется помощник
  302. 'AutoCompleteScriptaculous'.
  303. Просто передавайте ему массив данных, и он создает ответ HTML,
  304. совместимый с Ajax.Autocompleter.
  305. </para>
  306. </sect4>
  307. </sect3>
  308. <!--
  309. vim:se ts=4 sw=4 et:
  310. -->