Zend_Controller-ActionHelpers-AutoComplete.xml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 16509 -->
  3. <!-- Reviewed: no -->
  4. <sect3 id="zend.controller.actionhelpers.autocomplete">
  5. <title>AutoComplete</title>
  6. <para>
  7. Muchas bibliotecas de Javascript con
  8. <acronym>AJAX</acronym>
  9. ofrecen funcionalidad para
  10. proporcionar autocompletado según la cual un selectlist de
  11. resultados
  12. potencialmente concordantes se visualiza a medida que el usuario tipea.
  13. El ayudante
  14. <emphasis>AutoComplete</emphasis>
  15. pretende simplificar el retorno
  16. de respuestas aceptables a esos métodos.
  17. </para>
  18. <para>
  19. Dado que no todas la bibliotecas JS implementan el autocompletado de
  20. la misma manera, el
  21. ayudante
  22. <emphasis>AutoComplete</emphasis>
  23. ofrece algunas
  24. funcionalidades abstractas de base necesarias para muchas bibliotecas,
  25. e
  26. implementaciones concretas para distintas bibliotecas.
  27. Los tipos de datos de retorno son
  28. generalmente o bien arrays de strings
  29. <acronym>JSON</acronym>
  30. , array de arrays
  31. <acronym>JSON</acronym>
  32. (donde cada miembro del array está en un array
  33. asociativo de metadatos utilizado para crear
  34. la selectlist), o
  35. <acronym>HTML</acronym>
  36. .
  37. </para>
  38. <para>
  39. El uso básico para cada aplicación es el mismo:
  40. </para>
  41. <programlisting language="php"><![CDATA[
  42. class FooController extends Zend_Controller_Action
  43. {
  44. public function barAction()
  45. {
  46. // Ejecutar alguna lógica...
  47. // Codificar y enviar la respuesta;
  48. $this->_helper->autoCompleteDojo($data);
  49. // O explicitamente:
  50. $response = $this->_helper->autoCompleteDojo
  51. ->sendAutoCompletion($data);
  52. // O prepare simplemente la respuesta de autocompletado:
  53. $response = $this->_helper->autoCompleteDojo
  54. ->prepareAutoCompletion($data);
  55. }
  56. }
  57. ]]></programlisting>
  58. <para>
  59. Por defecto, el autocompletado hace lo siguiente:
  60. </para>
  61. <itemizedlist>
  62. <listitem>
  63. <para>
  64. Desactiva esquemas y a ViewRenderer.
  65. </para>
  66. </listitem>
  67. <listitem>
  68. <para>
  69. Establece las cabeceras apropiadas para la respuesta.
  70. </para>
  71. </listitem>
  72. <listitem>
  73. <para>
  74. Establece el cuerpo de la respuesta con datos
  75. codificados o formateados para
  76. autocompletar.
  77. </para>
  78. </listitem>
  79. <listitem>
  80. <para>
  81. Envía la respuesta.
  82. </para>
  83. </listitem>
  84. </itemizedlist>
  85. <para>
  86. Los métodos disponibles para el ayudante incluyen:
  87. </para>
  88. <itemizedlist>
  89. <listitem>
  90. <para>
  91. <methodname>disableLayouts()</methodname>
  92. puede ser utilizada para
  93. desactivar esquemas y a ViewRenderer. Típicamente, esto se
  94. llama dentro de
  95. <methodname>prepareAutoCompletion()</methodname>
  96. .
  97. </para>
  98. </listitem>
  99. <listitem>
  100. <para>
  101. <methodname>encodeJson($data, $keepLayouts = false)</methodname>
  102. codificará datos a
  103. <acronym>JSON</acronym>
  104. , y opcionalmente habilitando o
  105. deshabilitando esquemas. Típicamente, esto se llama
  106. dentro de
  107. <methodname>prepareAutoCompletion()</methodname>
  108. .
  109. </para>
  110. </listitem>
  111. <listitem>
  112. <para>
  113. <methodname>prepareAutoCompletion($data, $keepLayouts = false)</methodname>
  114. se utiliza para preparar datos en el formato necesario de la
  115. respuesta para la
  116. aplicación concreta, opcionalmente los
  117. esquemas pueden habilitarse o deshabilitarse.
  118. El valor de retorno variará dependiendo de la implementación.
  119. </para>
  120. </listitem>
  121. <listitem>
  122. <para>
  123. <methodname>sendAutoCompletion($data, $keepLayouts = false)</methodname>
  124. se utiliza para preparar datos en el formato necesario de la
  125. respuesta para la
  126. aplicación concreta. Esta llama a
  127. <methodname>prepareAutoCompletion()</methodname>
  128. , y entonces envía la
  129. respuesta.
  130. </para>
  131. </listitem>
  132. <listitem>
  133. <para>
  134. <methodname>direct($data, $sendNow = true, $keepLayouts =
  135. false)</methodname>
  136. se utiliza cuando se llama al ayudante como
  137. un método del ayudante intermediario. El flag
  138. <varname>$sendNow</varname>
  139. se utiliza para determinar si se debe
  140. llamar a
  141. <methodname>sendAutoCompletion()</methodname>
  142. o a
  143. <methodname>prepareAutoCompletion()</methodname>
  144. , respectivamente.
  145. </para>
  146. </listitem>
  147. </itemizedlist>
  148. <para>
  149. Actualmente,
  150. <emphasis>AutoComplete</emphasis>
  151. soporta las bibliotecas
  152. <acronym>AJAX</acronym>
  153. de
  154. Dojo y Scriptaculous.
  155. </para>
  156. <sect4 id="zend.controller.actionhelpers.autocomplete.dojo">
  157. <title>AutoCompletado con Dojo</title>
  158. <para>
  159. Dojo no tiene un widget de autocompletado per se, pero tiene dos
  160. widgets que pueden
  161. ejecutar AutoCompletado: ComboBox y
  162. FilteringSelect. En ambos casos, necesitan de un
  163. almacén de datos
  164. que implemente QueryReadStore; para obtener más información sobre
  165. estos
  166. temas, ver la documentación en
  167. <ulink
  168. url="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/data-retrieval-dojo-data-0"
  169. >dojo.data</ulink>
  170. </para>
  171. <para>
  172. En Zend Framework, puede pasar un simple array indexado al ayudante
  173. AutoCompleteDojo, y
  174. este regresará una adecuada respuesta
  175. <acronym>JSON</acronym>
  176. para su uso como almacenamiento:
  177. </para>
  178. <programlisting language="php"><![CDATA[
  179. // dentro del controlador de acción:
  180. $this->_helper->autoCompleteDojo($data);
  181. ]]></programlisting>
  182. <example id="zend.controller.actionhelpers.autocomplete.dojo.example1">
  183. <title>AutoCompletion con Dojo Usando Zend MVC</title>
  184. <para>
  185. AutoCompletion con Dojo via Zend
  186. <acronym>MVC</acronym>
  187. requiere varias cosas:
  188. generar un objeto form para el ComboBox en el que usted quiere
  189. AutoCompletado, un controlador de acción para prestar servicio
  190. a los resultados de
  191. AutoCompletion, creando un QueryReadStore
  192. personalizado para conectar a la acción
  193. AutoCompletion,
  194. y la generación del Javascript a utilizar en la inicializción
  195. de
  196. AutoCompletion del lado del servidor.
  197. </para>
  198. <para>
  199. En primer lugar, veamos el Javascript necesario. Dojo ofrece
  200. un marco completo para
  201. crear Javascript
  202. <acronym>OOP</acronym>
  203. , tal como lo hace
  204. Zend Framework para
  205. <acronym>PHP</acronym>
  206. . Parte de eso es la capacidad de
  207. crear pseudo-namespaces utilizando la jerarquía de
  208. directorios.
  209. Crearemos un directorio 'custom' en el mismo nivel en el cual
  210. el
  211. directorio de Dojo forma parte de la distribución Dojo.
  212. Dentro del directorio,
  213. crearemos un archivo Javascript,
  214. <filename>TestNameReadStore.js</filename>
  215. , con el siguiente contenido:
  216. </para>
  217. <programlisting language="javascript"><![CDATA[
  218. dojo.provide("custom.TestNameReadStore");
  219. dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
  220. fetch:function (request) {
  221. request.serverQuery = { test:request.query.name };
  222. return this.inherited("fetch", arguments);
  223. }
  224. });
  225. ]]></programlisting>
  226. <para>
  227. Esta clase es simplemente una extensión del propio
  228. QueryReadStore de Dojo, que es
  229. de por sí misma una clase
  230. abstracta. Simplemente definimos un método por el cual
  231. realizamos la solicitud, y se le asigna al elemento 'test'.
  232. </para>
  233. <para>
  234. A continuación, vamos a crear el elemento form para el que
  235. queremos AutoCompletion:
  236. </para>
  237. <programlisting language="php"><![CDATA[
  238. class TestController extends Zend_Controller_Action
  239. {
  240. protected $_form;
  241. public function getForm()
  242. {
  243. if (null === $this->_form) {
  244. $this->_form = new Zend_Form();
  245. $this->_form->setMethod('get')
  246. ->setAction(
  247. $this->getRequest()->getBaseUrl() . '/test/process'
  248. )
  249. ->addElements(array(
  250. 'test' => array('type' => 'text', 'options' => array(
  251. 'filters' => array('StringTrim'),
  252. 'dojoType' => array('dijit.form.ComboBox'),
  253. 'store' => 'testStore',
  254. 'autoComplete' => 'false',
  255. 'hasDownArrow' => 'true',
  256. 'label' => 'Your input:',
  257. )),
  258. 'go' => array('type' => 'submit',
  259. 'options' => array('label' => 'Go!'))
  260. ));
  261. }
  262. return $this->_form;
  263. }
  264. }
  265. ]]></programlisting>
  266. <para>
  267. Aquí, estamos simplemente creando un formulario con los métodos
  268. 'test' y 'go'. El
  269. método 'test' agrega varios atributos
  270. especiales específicos de Dojo: dojoType,
  271. store,
  272. <emphasis>AutoComplete</emphasis>
  273. y hasDownArrow. El dojoType es utilizado para indicar que
  274. estamos creando un
  275. ComboBox, y que vamos a vincularlo
  276. a un almacén de datos (clave 'store') de
  277. 'testStore'
  278. -- veremos más de esto más adelante.
  279. Especificando '
  280. <emphasis>AutoComplete</emphasis>
  281. ' como
  282. <constant>FALSE</constant>
  283. se le dice a Dojo que
  284. no seleccione automáticamente el primer acierto, sino mostrar
  285. una lista de aciertos. Por último, 'hasDownArrow' crea una
  286. flecha abajo similar a un
  287. select box para que podamos
  288. mostrar y ocultar los aciertos o concordancias.
  289. </para>
  290. <para>
  291. Vamos a añadir un método para mostrar la forma, así como un
  292. punto final para el
  293. procesamiento de AutoCompletion:
  294. </para>
  295. <programlisting language="php"><![CDATA[
  296. class TestController extends Zend_Controller_Action
  297. {
  298. // ...
  299. /**
  300. * Página final
  301. */
  302. public function indexAction()
  303. {
  304. $this->view->form = $this->getForm();
  305. }
  306. public function autocompleteAction()
  307. {
  308. if ('ajax' != $this->_getParam('format', false)) {
  309. return $this->_helper->redirector('index');
  310. }
  311. if ($this->getRequest()->isPost()) {
  312. return $this->_helper->redirector('index');
  313. }
  314. $match = trim($this->getRequest()->getQuery('test', ''));
  315. $matches = array();
  316. foreach ($this->getData() as $datum) {
  317. if (0 === strpos($datum, $match)) {
  318. $matches[] = $datum;
  319. }
  320. }
  321. $this->_helper->autoCompleteDojo($matches);
  322. }
  323. }
  324. ]]></programlisting>
  325. <para>
  326. En nuestro
  327. <methodname>autocompleteAction()</methodname>
  328. hacemos una serie
  329. de cosas. En primer lugar, esperamos a asegurarnos de que
  330. tengamos
  331. una petición post, y que existe un parámetro 'form'
  332. establecido al valor 'ajax'; esto
  333. es simplemente para ayudar a
  334. reducir preguntas espúreas a la acción.
  335. A continuación,
  336. vamos a comprobar el parámetro 'test', y
  337. compararlo contra nuestros datos. (Yo
  338. deliberadamente dejé de
  339. lado la implementación de
  340. <methodname>getData()</methodname>
  341. aquí --
  342. podría ser cualquier tipo de fuente de datos). Por último,
  343. enviamos nuestros
  344. aciertos a nuestro ayudante AutoCompletion.
  345. </para>
  346. <para>
  347. Ahora que tenemos todas las piezas en el backend, veamos lo que
  348. necesitamos para
  349. entregar en nuestro script de vista para la
  350. página final.
  351. En primer lugar, necesitamos
  352. configurar nuestro data store,
  353. luego hacer nuestro formulario, y finalmente
  354. garantizar que
  355. las biblotecas Dojo apropiadas -- incluyendo que nuestro data
  356. store
  357. personalizado -- estén cargadas.
  358. Veamos el script de vista, el cual comenta los
  359. pasos:
  360. </para>
  361. <programlisting language="php"><![CDATA[
  362. <?php // establecemos nuestro data store: ?>
  363. <div dojoType="custom.TestNameReadStore" jsId="testStore"
  364. url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
  365. requestMethod="get"></div>
  366. <?php // mostramos nuestro form: ?>
  367. <?php echo $this->form ?>
  368. <?php // establecemos CSS relacionado con Dojo a cargar en HTML head: ?>
  369. <?php $this->headStyle()->captureStart() ?>
  370. @import "<?php echo $this->baseUrl()
  371. ?>/javascript/dijit/themes/tundra/tundra.css";
  372. @import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
  373. <?php $this->headStyle()->captureEnd() ?>
  374. <?php // setup de javascript para cargar en HTML head, incluyendo todas las
  375. // bibliotecas Dojo requeridas: ?>
  376. <?php $this->headScript()
  377. ->setAllowArbitraryAttributes(true)
  378. ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
  379. 'text/javascript',
  380. array('djConfig' => 'parseOnLoad: true'))
  381. ->captureStart() ?>
  382. djConfig.usePlainJson=true;
  383. dojo.registerModulePath("custom","../custom");
  384. dojo.require("dojo.parser");
  385. dojo.require("dojox.data.QueryReadStore");
  386. dojo.require("dijit.form.ComboBox");
  387. dojo.require("custom.TestNameReadStore");
  388. <?php $this->headScript()->captureEnd()
  389. ]]></programlisting>
  390. <para>
  391. Note que las llamadas a los ayudantes de vista como headStyle
  392. y headScript; son
  393. ubicadores, que podemos suministrar a la
  394. sección 'head' del
  395. <acronym>HTML</acronym>
  396. de nuestro script de vista.
  397. </para>
  398. <para>
  399. Ahora tenemos todas las piezas para que el AutoCompletion
  400. de Dojo pueda trabajar.
  401. </para>
  402. </example>
  403. </sect4>
  404. <sect4 id="zend.controller.actionhelpers.autocomplete.scriptaculous">
  405. <title>AutoCompletion con Scriptaculous</title>
  406. <para>
  407. <ulink url="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter">Scriptaculous</ulink>
  408. espera una respuesta
  409. <acronym>HTML</acronym>
  410. en un formato específico.
  411. </para>
  412. <para>
  413. El ayudante para utilizar con esta biblioteca es
  414. 'AutoCompleteScriptaculous'. Simplemente
  415. proporcionarle un array de
  416. datos, y el ayudante creará una respuesta
  417. <acronym>HTML</acronym>
  418. compatible con
  419. Ajax.Autocompleter.
  420. </para>
  421. </sect4>
  422. </sect3>
  423. <!--
  424. vim:se ts=4 sw=4 et:
  425. -->