[GENERIC] Zend_Translate:
[zend.git] / documentation / manual / en / module_specs / Zend_Controller-ActionHelpers-AutoComplete.xml
blob322a4dac5446dc1b75dca5e287e3d7213792e388
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect3 id="zend.controller.actionhelpers.autocomplete">
4     <title>AutoComplete</title>
6     <para>
7         Many <acronym>AJAX</acronym> javascript libraries offer functionality for providing
8         autocompletion whereby a selectlist of potentially matching results is
9         displayed as the user types. The <emphasis>AutoComplete</emphasis> helper aims
10         to simplify returning acceptable responses to such methods.
11     </para>
13     <para>
14         Since not all JS libraries implement autocompletion in the same way, the
15         <emphasis>AutoComplete</emphasis> helper provides some abstract base
16         functionality necessary to many libraries, and concrete implementations
17         for individual libraries. Return types are generally either <acronym>JSON</acronym> arrays
18         of strings, <acronym>JSON</acronym> arrays of arrays (with each member array being an
19         associative array of metadata used to create the selectlist), or <acronym>HTML</acronym>.
20     </para>
22     <para>
23         Basic usage for each implementation is the same:
24     </para>
26    <programlisting language="php"><![CDATA[
27 class FooController extends Zend_Controller_Action
29     public function barAction()
30     {
31         // Perform some logic...
33         // Encode and send response;
34         $this->_helper->autoCompleteDojo($data);
36         // Or explicitly:
37         $response = $this->_helper->autoCompleteDojo
38                                   ->sendAutoCompletion($data);
40         // Or simply prepare autocompletion response:
41         $response = $this->_helper->autoCompleteDojo
42                                   ->prepareAutoCompletion($data);
43     }
45 ]]></programlisting>
47     <para>
48         By default, autocompletion does the following:
49     </para>
51     <itemizedlist>
52         <listitem><para>Disables layouts and ViewRenderer.</para></listitem>
53         <listitem><para>Sets appropriate response headers.</para></listitem>
55         <listitem>
56             <para>Sets response body with encoded or formatted autocompletion data.</para>
57         </listitem>
59         <listitem><para>Sends response.</para></listitem>
60     </itemizedlist>
62     <para>
63         Available methods of the helper include:
64     </para>
66     <itemizedlist>
67         <listitem>
68             <para>
69                 <methodname>disableLayouts()</methodname> can be used to disable layouts and
70                 the ViewRenderer. Typically, this is called within
71                 <methodname>prepareAutoCompletion()</methodname>.
72             </para>
73         </listitem>
75         <listitem>
76             <para>
77                 <methodname>encodeJson($data, $keepLayouts = false)</methodname> will encode
78                 data to <acronym>JSON</acronym>, optionally enabling or disabling layouts.
79                 Typically, this is called within
80                 <methodname>prepareAutoCompletion()</methodname>.
81             </para>
82         </listitem>
84         <listitem>
85             <para>
86                 <methodname>prepareAutoCompletion($data, $keepLayouts = false)</methodname>
87                 is used to prepare data in the response format necessary for the
88                 concrete implementation, optionally enabling or disabling
89                 layouts. The return value will vary based on the implementation.
90             </para>
91         </listitem>
93         <listitem>
94             <para>
95                 <methodname>sendAutoCompletion($data, $keepLayouts = false)</methodname>
96                 is used to send data in the response format necessary for the
97                 concrete implementation. It calls
98                 <methodname>prepareAutoCompletion()</methodname>, and then sends the
99                 response.
100             </para>
101         </listitem>
103         <listitem>
104             <para>
105                 <methodname>direct($data, $sendNow = true, $keepLayouts =
106                     false)</methodname> is used when calling the helper as a method of
107                 the helper broker. The <varname>$sendNow</varname> flag is used to
108                 determine whether to call <methodname>sendAutoCompletion()</methodname> or
109                 <methodname>prepareAutoCompletion()</methodname>, respectively.
110             </para>
111         </listitem>
112     </itemizedlist>
114     <para>
115         Currently, <emphasis>AutoComplete</emphasis> supports the Dojo and Scriptaculous
116         <acronym>AJAX</acronym> libraries.
117     </para>
119     <sect4 id="zend.controller.actionhelpers.autocomplete.dojo">
120         <title>AutoCompletion with Dojo</title>
122         <para>
123             Dojo does not have an AutoCompletion widget per se, but has two
124             widgets that can perform AutoCompletion: ComboBox and
125             FilteringSelect. In both cases, they require a data store that
126             implements the QueryReadStore; for more information on these topics, see the <ulink
127                 url="http://dojotoolkit.org/reference-guide/dojo/data.html">dojo.data</ulink>
128             documentation.
129         </para>
131         <para>
132             In Zend Framework, you can pass a simple indexed array to the
133             AutoCompleteDojo helper, and it will return a <acronym>JSON</acronym> response suitable
134             for use with such a store:
135         </para>
137         <programlisting language="php"><![CDATA[
138 // within a controller action:
139 $this->_helper->autoCompleteDojo($data);
140 ]]></programlisting>
142         <example id="zend.controller.actionhelpers.autocomplete.dojo.example1">
143             <title>AutoCompletion with Dojo Using Zend MVC</title>
145             <para>
146                 AutoCompletion with Dojo via the Zend <acronym>MVC</acronym> requires several
147                 things: generating a form object for the ComboBox on which you
148                 want AutoCompletion, a controller action for serving the
149                 AutoCompletion results, creating a custom QueryReadStore to connect
150                 to the AutoCompletion action, and generation of the javascript
151                 to use to initialize AutoCompletion on the server side.
152             </para>
154             <para>
155                 First, let's look at the javascript necessary. Dojo offers a
156                 complete framework for creating <acronym>OOP</acronym> javascript, much as Zend
157                 Framework does for <acronym>PHP</acronym>. Part of that is the ability to create
158                 pseudo-namespaces using the directory hierarchy. We'll create a
159                 'custom' directory at the same level as the Dojo directory
160                 that's part of the Dojo distribution. Inside that directory,
161                 we'll create a javascript file, <filename>TestNameReadStore.js</filename>, with the
162                 following contents:
163             </para>
165             <programlisting language="javascript"><![CDATA[
166 dojo.provide("custom.TestNameReadStore");
167 dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
168     fetch:function (request) {
169         request.serverQuery = { test:request.query.name };
170         return this.inherited("fetch", arguments);
171     }
173 ]]></programlisting>
175             <para>
176                 This class is simply an extension of Dojo's own QueryReadStore,
177                 which is itself an abstract class. We simply define a method by
178                 which to request, and assigning it to the 'test' element.
179             </para>
181             <para>
182                 Next, let's create the form element for which we want
183                 AutoCompletion:
184             </para>
186             <programlisting language="php"><![CDATA[
187 class TestController extends Zend_Controller_Action
189     protected $_form;
191     public function getForm()
192     {
193         if (null === $this->_form) {
194             $this->_form = new Zend_Form();
195             $this->_form->setMethod('get')
196                 ->setAction(
197                     $this->getRequest()->getBaseUrl() . '/test/process'
198                 )
199                 ->addElements(array(
200                     'test' => array('type' => 'text', 'options' => array(
201                         'filters'        => array('StringTrim'),
202                         'dojoType'       => array('dijit.form.ComboBox'),
203                         'store'          => 'testStore',
204                         'autoComplete'   => 'false',
205                         'hasDownArrow'   => 'true',
206                         'label' => 'Your input:',
207                     )),
208                     'go' => array('type' => 'submit',
209                                   'options' => array('label' => 'Go!'))
210                 ));
211         }
212         return $this->_form;
213     }
215 ]]></programlisting>
217             <para>
218                 Here, we simply create a form with 'test' and 'go' methods. The
219                 'test' method adds several special, Dojo-specific attributes:
220                 dojoType, store, autoComplete, and hasDownArrow. The dojoType is
221                 used to indicate that we are creating a ComboBox, and we will
222                 link it to a data store (key 'store') of 'testStore' -- more on
223                 that later. Specifying 'autoComplete' as <constant>FALSE</constant> tells
224                 Dojo not to automatically select the first match, but instead show a list of
225                 matches. Finally, 'hasDownArrow' creates a down arrow similar to
226                 a select box so we can show and hide the matches.
227             </para>
229             <para>
230                 Let's add a method to display the form, as well as an end point
231                 for processing AutoCompletion:
232             </para>
234             <programlisting language="php"><![CDATA[
235 class TestController extends Zend_Controller_Action
237     // ...
239     /**
240      * Landing page
241      */
242     public function indexAction()
243     {
244         $this->view->form = $this->getForm();
245     }
247     public function autocompleteAction()
248     {
249         if ('ajax' != $this->_getParam('format', false)) {
250             return $this->_helper->redirector('index');
251         }
252         if ($this->getRequest()->isPost()) {
253             return $this->_helper->redirector('index');
254         }
256         $match = trim($this->getRequest()->getQuery('test', ''));
258         $matches = array();
259         foreach ($this->getData() as $datum) {
260             if (0 === strpos($datum, $match)) {
261                 $matches[] = $datum;
262             }
263         }
264         $this->_helper->autoCompleteDojo($matches);
265     }
267 ]]></programlisting>
269             <para>
270                 In our <methodname>autocompleteAction()</methodname> we do a number of
271                 things. First, we look to make sure we have a post request, and
272                 that there is a 'format' parameter set to the value 'ajax';
273                 these are simply to help reduce spurious queries to the action.
274                 Next, we check for a 'test' parameter, and compare it against
275                 our data. (I purposely leave out the implementation of
276                 <methodname>getData()</methodname> here -- it could be any sort of data
277                 source.) Finally, we send our matches to our AutoCompletion
278                 helper.
279             </para>
281             <para>
282                 Now that we have all the pieces on the backend, let's look at
283                 what we need to deliver in our view script for the landing page.
284                 First, we need to setup our data store, then render our form,
285                 and finally ensure that the appropriate Dojo libraries --
286                 including our custom data store -- get loaded. Let's look at the
287                 view script, which comments the steps:
288             </para>
290             <programlisting language="php"><![CDATA[
291 <?php // setup our data store: ?>
292 <div dojoType="custom.TestNameReadStore" jsId="testStore"
293     url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
294     requestMethod="get"></div>
296 <?php // render our form: ?>
297 <?php echo $this->form ?>
299 <?php // setup Dojo-related CSS to load in HTML head: ?>
300 <?php $this->headStyle()->captureStart() ?>
301 @import "<?php echo $this->baseUrl()
302 ?>/javascript/dijit/themes/tundra/tundra.css";
303 @import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
304 <?php $this->headStyle()->captureEnd() ?>
306 <?php // setup javascript to load in HTML head, including all required
307    // Dojo libraries: ?>
308 <?php $this->headScript()
309         ->setAllowArbitraryAttributes(true)
310         ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
311             'text/javascript',
312             array('djConfig' => 'parseOnLoad: true'))
313         ->captureStart() ?>
314 djConfig.usePlainJson=true;
315 dojo.registerModulePath("custom","../custom");
316 dojo.require("dojo.parser");
317 dojo.require("dojox.data.QueryReadStore");
318 dojo.require("dijit.form.ComboBox");
319 dojo.require("custom.TestNameReadStore");
320 <?php $this->headScript()->captureEnd() ?>
321 ]]></programlisting>
323             <para>
324                 Note the calls to view helpers such as headStyle and headScript;
325                 these are placeholders, which we can then render in the <acronym>HTML</acronym>
326                 head section of our layout view script.
327             </para>
329             <para>
330                 We now have all the pieces to get Dojo AutoCompletion working.
331             </para>
332         </example>
333     </sect4>
335     <sect4 id="zend.controller.actionhelpers.autocomplete.scriptaculous">
336         <title>AutoCompletion with Scriptaculous</title>
338         <para>
339             <ulink
340                 url="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter">Scriptaculous</ulink>
341             expects an <acronym>HTML</acronym> response in a specific format.
342         </para>
344         <para>
345             The helper to use with this library is 'AutoCompleteScriptaculous'.
346             Simply provide it an array of data, and the helper will create an
347             <acronym>HTML</acronym> response compatible with Ajax.Autocompleter.
348         </para>
349     </sect4>
350 </sect3>
351 <!--
352 vim:se ts=4 sw=4 et: