Loading rico1 and rico3 files
[infodrom/rico3] / documentation / LiveGridAjax.html
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
5 <title>Rico LiveGrid AJAX</title>
6 <link href="ricoDocs.css" rel="Stylesheet" type="text/css">
7
8 <style type="text/css">\r
9 .request, .response {
10   border: 1px solid black;
11   background-color: #FFF8DC;
12   padding: 4px;
13 }
14 dt span {
15   font-weight:normal;
16   font-style:italic;
17 }
18 </style>
19 </head>
20
21 <body>
22 <h1>Rico LiveGrid AJAX</h1>
23
24 <p><a href='LiveGridAjax_ja.html'><img src='images/japanese.gif' alt='View this page in Japanese'></a>\r
25 <a href='LiveGridAjax_ja.html'>View this page in Japanese</a></p>\r
26 \r
27 <p>One of the key features of the Rico LiveGrid is its ability to load data dynamically
28 via AJAX. This document focuses on the format of the LiveGrid AJAX requests and responses. 
29 More specifically, it is the LiveGrid <strong>Buffer</strong> object that is
30 generating requests and processing responses. So if you are in a situation where data
31 is coming from a web service that is out of your control, you could create a custom
32 LiveGrid buffer class that would serve as an interface between the web service
33 and LiveGrid. However, in this document we will focus on the request and response
34 formats of the buffer classes that come with the Rico distribution.
35
36 <p>The Rico distribution includes 4 distinct buffer classes:
37 <dl>
38 <dt>Rico.Buffer.Base
39 <dd>Used for static datasets, no AJAX (i.e. no calls to XMLHttpRequest).
40 Data can be loaded from an HTML table or from a javascript array.
41 Since this buffer does not use AJAX, it will not be discussed further in this document. 
42 <dt><a href='#AjaxXML'>Rico.Buffer.AjaxXML</a>
43 <dd>All LiveGrid data is loaded in a single AJAX call, data returned in XML format
44 <dt><a href='#AjaxSQL'>Rico.Buffer.AjaxSQL</a>
45 <dd>LiveGrid data is loaded in chunks as the user scrolls through the grid, data returned in XML format
46 <dt><a href='#AjaxJSON'>Rico.Buffer.AjaxJSON</a>
47 <dd>Same as AjaxSQL, except that responses are in JSON format
48 </dl>
49
50 <h2><a name='AjaxXML'>Rico.Buffer.AjaxXML</a></h2>
51
52 <p>An AjaxXML buffer will only perform a single XMLHttpRequest 
53 regardless of the amount of scrolling a user does in a LiveGrid.
54 An AjaxXML buffer is created using the following javascript:
55
56 <pre>
57 buffer=new Rico.Buffer.AjaxXML(url,options,ajaxOptions)
58 </pre>
59
60 <dl>
61 <dt>url
62 <dd>A string containing the url to the data provider.
63 <dt>options
64 <dd>A Rico buffer options object, which may contain any of the following:
65
66 <dl>
67 <dt>bufferTimeout
68 <dd>An integer that specifies the number of milliseconds a wait message should be presented to the
69 user before indicating a timeout. Default is 20000 (20 seconds).
70
71 <dt>requestParameters
72 <dd>An array of strings of the form "parm=value" that get added to the
73 search string of the XMLHttpRequest.
74
75 <dt>isEncoded
76 <dd>Specifies whether the response will be HTML encoded or not. Default is true.
77 All plug-ins supplied with Rico encode the response.
78
79 <dt>waitMsg
80 <dd>The message that gets displayed to the user while waiting for and XMLHttpRequest response.
81 Default is RicoTranslate.getPhraseById("waitForData").
82 Note that this can be an image tag, for example: 
83 <pre>
84 buffer=new Rico.Buffer.AjaxXML(
85   url,
86   {waitMsg: "&lt;img src='MySpinner.gif'&gt;"},
87   ajaxOptions);
88 </pre>
89
90 <dt>canFilter
91 <dd>A boolean value indicating whether the buffer supports filtering. Default is true.
92 </dl>
93
94 <dt>ajaxOptions
95 <dd>An <a href='http://prototypejs.org/api/ajax/options'>Ajax options object</a>
96 that is passed to Prototype's Ajax.Request method.
97 The "parameters" and "onComplete" options are used by Rico
98 and have no effect if specified. The "method" option
99 defaults to "get", but can be overridden.
100 </dl>
101
102 Here is an example taken from ex3livegridxml.php:
103 <pre>
104 buffer=new Rico.Buffer.AjaxXML('ricoXMLquery.php');\r
105 ex3=new Rico.LiveGrid ('ex3', buffer, grid_options);\r
106 </pre>
107
108 <h3>AjaxXML Request</h3>
109
110 <p>Assuming grid_options.prefetchBuffer is true (which is the default),
111 then a single XMLHttpRequest will be generated during grid initialization
112 that will fetch data from ricoXMLquery.php. The URL will include the
113 following querystring (search) parameters:
114
115 <dl>
116 <dt>id
117 <dd>The id of the grid that was specified as the first parameter in the call to
118 Rico.LiveGrid(), "ex3" in the previous example.
119 <dt>offset
120 <dd>The first record in the dataset that should be returned. Always "0" for AjaxXML.
121 <dt>page_size
122 <dd>The number of records that should be returned in the dataset. 
123 Always "-1" for AjaxXML, meaning all records should be returned.
124 </dl>
125
126 <p>Plus, if any options.requestParameters were specified, they would be included also.
127 So the complete URL that would be used to fetch data for ex3 would be:
128 <pre class='request'>
129 ricoXMLquery.php?id=ex3&amp;offset=0&amp;page_size=-1
130 </pre>
131
132 <h3><a name='AjaxXMLresponse'>AjaxXML Response</a></h3>
133
134 <p>Here is a sample response that will populate our ex3 LiveGrid:
135
136 <pre class='response'>
137 &lt;?xml version="1.0" encoding="UTF-8"?&gt;
138 &lt;ajax-response&gt;\r
139   &lt;response type='object' id='ex3_updater'&gt;\r
140     &lt;rows update_ui='true' offset='0'&gt;\r
141     &lt;tr&gt;&lt;td&gt;Data for row 1, cell 1&lt;/td&gt;&lt;td&gt;Data for row 1, cell 2&lt;/td&gt;&lt;/tr&gt;\r
142     &lt;tr&gt;&lt;td&gt;Data for row 2, cell 1&lt;/td&gt;&lt;td&gt;Data for row 2, cell 2&lt;/td&gt;&lt;/tr&gt;\r
143     &lt;/rows&gt;
144     &lt;rowcount&gt;2&lt;/rowcount&gt;\r
145     &lt;debug&gt;Generated by test server&lt;/debug&gt;\r
146   &lt;/response&gt;\r
147 &lt;/ajax-response&gt;\r
148 </pre>\r
149
150 <p>When you are creating the response in your request handler you must set the\r
151 content-type of the response header to text/xml. Also you will need to specify the\r
152 xml version and <a href='http://www.opentag.com/xfaq_enc.htm'>character encoding</a>. 
153 The encoding value is very important and depends on your specific environment.
154 Two common values are "UTF-8" and "iso-8859-1".
155 Here is how the first couple of lines would look in Java Server Pages\r
156 (JSP):\r
157 <pre>
158 &lt;% response.setHeader(“Content-Type”, “text/xml”); %&gt;\r
159 &lt;?xml version="1.0" encoding="UTF-8"?&gt;\r
160 </pre>
161
162 And this is how they would look in PHP:\r
163 <pre>
164 header("Content-type: text/xml");\r
165 echo "&lt;?xml version='1.0' encoding='UTF-8'?"."&gt;\n";\r
166 </pre>
167
168 <p>Notice several important items about the Ajax response.\r
169
170 <p>First the response is wrapped in the tags &lt;ajax-response&gt;&lt;/ajax-response&gt;. 
171 Every Rico Ajax response must have this element as the root of the XML returned.\r
172 Second, notice the response contained within the ajax-response. 
173 The response tags (&lt;response&gt;&lt;/response&gt;) wrap the response content.
174 The type and id attributes of the &lt;response&gt; tag were required in Rico 1.1, 
175 but are ignored by Rico 2.0.
176 Finally, notice the &lt;rowcount&gt; element.
177 This specifies the total number of rows in the dataset. In an AjaxXML response,
178 this should match the number of &lt;tr&gt; elements.
179
180 <p>The debug tag (&lt;debug&gt;&lt;/debug&gt;) is optional. The response
181 may contain 0, 1, or more of them. The content of each debug tag is
182 sent to Rico's <a href='LiveGrid.html#debug'>message logging facility</a>.
183 The Rico plug-ins can return the actual SQL queries that get
184 executed by setting ricoXmlResponse.sendDebugMsgs to true in
185 ricoXMLquery.php/asp/aspx. This can be very useful during development
186 but should be turned off in production, as it is a security risk (gives
187 users visibility to actual table and column names).
188
189 <p>If an error occurs on the server during the processing of the request,
190 the server can return error information to the user by enclosing an
191 error message in &lt;error&gt;&lt;/error&gt; tags. For example:
192
193 <pre class='response'>
194 &lt;?xml version="1.0" encoding="UTF-8"?&gt;
195 &lt;ajax-response&gt;\r
196   &lt;response type='object' id='ex3_updater'&gt;\r
197     &lt;rows update_ui='true' offset='0'&gt;\r
198     &lt;/rows&gt;
199     &lt;rowcount&gt;0&lt;/rowcount&gt;\r
200     &lt;error&gt;Unable to retrieve the data&lt;/error&gt;\r
201   &lt;/response&gt;\r
202 &lt;/ajax-response&gt;\r
203 </pre>\r
204
205 <p>The mere presence of the &lt;error&gt; tag will cause any row data and the rowcount to be ignored.
206 Thus, &lt;rows&gt; and &lt;rowcount&gt; can be included or omitted when returning an error.
207 The Rico plug-ins will send the database-generated error message when an error occurs.
208
209
210 <h2><a name='AjaxSQL'>Rico.Buffer.AjaxSQL</a></h2>
211
212 <p>The AjaxSQL buffer extends the capabilities provided by the AjaxXML buffer.
213 Many of the concepts are the same, but the AjaxSQL buffer is more complex.
214 Query results are returned to the buffer in chunks, rather than returning
215 all rows in a single response. Also, an AjaxSQL buffer assumes filtering
216 and sorting will occur on the server. So filtering and sorting parameters
217 must be sent in each request and the server must process those parameters correctly.
218 Fortunately, the Rico plug-ins take care of this complexity for you.
219
220 <p>An AjaxSQL buffer is created using the following javascript:
221
222 <pre>
223 buffer=new Rico.Buffer.AjaxSQL(url,options,ajaxOptions)
224 </pre>
225
226 Here is an example taken from ex2simple.php:
227 <pre>
228 buffer=new Rico.Buffer.AjaxSQL(
229   'ricoXMLquery.php', 
230   {TimeOut:&lt;? print array_shift(session_get_cookie_params())/60 ?&gt;});\r
231 orderGrid=new Rico.LiveGrid ('ex2', buffer, opts);\r
232 </pre>
233
234 <dl>
235 <dt>url
236 <dd>A string containing the url to the data provider.
237 <dt><a name='AjaxSQLoptions'>options</a>
238 <dd>A Rico buffer options object, which may contain any of the following:
239
240 <dl>
241 <dt>bufferTimeout
242 <dd>An integer that specifies the number of milliseconds a wait message should be presented to the
243 user before indicating a timeout. Default is 20000 (20 seconds).
244
245 <dt>requestParameters
246 <dd>An array of strings of the form "parm=value" that get added to the
247 search string of the XMLHttpRequest.
248
249 <dt>isEncoded
250 <dd>Specifies whether the response will be HTML encoded or not. Default is true.
251 All plug-ins supplied with Rico encode the response.
252
253 <dt>waitMsg
254 <dd>The message that gets displayed to the user while waiting for and XMLHttpRequest response.
255 Default is RicoTranslate.getPhraseById("waitForData").
256 Note that this can be an image tag, for example: 
257 <pre>
258 buffer=new Rico.Buffer.AjaxXML(
259   url,
260   {waitMsg: "&lt;img src='MySpinner.gif'&gt;"},
261   ajaxOptions);
262 </pre>
263
264 <dt>canFilter
265 <dd>A boolean value indicating whether the buffer supports filtering. Default is true.
266
267 <dt>largeBufferSize
268 <dd>Used to set the size of the buffer. Default value is 7. The actual buffer size is set to: 
269 (the number of visible grid rows) * largeBufferSize; but no less than 50.
270 So a grid with 4 rows visible would get the minimum buffer size of 50, while a grid
271 with 30 visible rows would have a buffer size of 210.
272
273 <dt>nearLimitFactor
274 <dd>Used to determine when the user has scrolled near the end of the buffer,
275 triggering a new request for data. Default value is 1. The nearLimit value is set to: 
276 (the number of visible grid rows) * nearLimitFactor.
277
278 <dt>TimeOut
279 <dd>The Rico plug-ins store the SQL query in a 
280 <a href='http://www.talkphp.com/general/1077-understanding-life-session.html'>session variable</a>. 
281 The server can respond to data requests for only as long as the session is valid. The TimeOut
282 option is used to measure the time remaining in the session. If option.TimeOut has been
283 specified and there is an html element in the document with an id of "MyGridId_timer", then
284 the innerHTML of that element will be populated with the remaining time in the session.
285 The TimeOut value is specified in minutes and has no default.
286
287 <dt><a name='sortParmFmt'>sortParmFmt</a>
288 <dd>If set, then sortParmFmt should be the name of an attribute in the Rico column object.
289 Set to "displayName" in order generate requests in a format compatible with Rico 1.1:
290 <pre class='request'>
291 ricoXMLquery.php?id=ex2&amp;...&amp;sort_col=Column0&amp;sort_dir=ASC
292 </pre>
293 Set to "index" in order generate requests in this format:
294 <pre class='request'>
295 ricoXMLquery.php?id=ex2&amp;...&amp;sort_col=0&amp;sort_dir=ASC
296 </pre>
297 When unspecified (the default), then sort parameters are sent in this format 
298 ('s' followed by the column number). This is what the Rico plug-ins expect.
299 <pre class='request'>
300 ricoXMLquery.php?id=ex2&amp;...&amp;s0=ASC
301 </pre>
302 </dl>
303
304 <dt>ajaxOptions
305 <dd>An <a href='http://prototypejs.org/api/ajax/options'>Ajax options object</a>
306 that is passed to Prototype's Ajax.Request method.
307 The "parameters" and "onComplete" options are used by Rico
308 and have no effect if specified. The "method" option
309 defaults to "get", but can be overridden.
310 </dl>
311
312
313
314 <h3><a name='AjaxSQLrequests'>AjaxSQL Request</a></h3>
315
316 <p>An XMLHttpRequest will be generated every time the AjaxSQL buffer needs more data.
317 Data is requested in chunks as specified by the offset and page_size parameters.
318 This makes it possible for a LiveGrid to efficiently display hundreds of thousands of records;
319 because only a small portion of those records would reside in the client-side buffer
320 at any one time.
321 The URL will include the following querystring (search) parameters:
322
323 <dl>
324 <dt>id
325 <dd>The id of the grid that was specified as the first parameter in the call to
326 Rico.LiveGrid(), "ex2" in the previous example.
327
328 <dt>offset
329 <dd>The first record in the dataset that should be returned. Always "0" for AjaxXML.
330
331 <dt>page_size
332 <dd>The number of records that should be returned in the dataset. 
333 Always "-1" for AjaxXML, meaning all records should be returned.
334
335 <dt>get_total
336 <dd>If true, then the response should include a &lt;rowcount&gt; element
337 that contains the total number of rows in the dataset (not just
338 the chunk being requested), with the specified filters.
339 "get_total=true" will be sent during the first request to populate
340 a grid and any time the user has changed the filters.
341 <pre class='request'>
342 ricoXMLquery.php?id=ex2&amp;...&amp;get_total=true
343 </pre>
344
345 <dt>sX <span>(where X is the column #)</span>
346 <dd>Specifies that results should be sorted by column X.
347 Parameter will be ASC or DESC. See also <a href='#sortParmFmt'>options.sortParmFmt</a>.
348 Even though this parameter format theoretically allows for sorting on more than
349 one column at a time, this is not possible with the current LiveGrid UI.
350 <pre class='request'>
351 ricoXMLquery.php?id=ex2&amp;...&amp;s0=ASC
352 </pre>
353
354 <dt>f[X][op] <span>(where X is the column #)</span>
355 <dd>Specifies the filter operator being applied to column X.
356 Parameter will be one of the following: EQ (equal), NE (not equal),
357  GE (greater than or equal), LE (less than or equal), LIKE, NULL, NOTNULL
358 <pre class='request'>
359 ricoXMLquery.php?id=ex2&amp;...&amp;f[0][op]=EQ
360 </pre>
361
362 <dt>f[X][len] <span>(where X is the column #)</span>
363 <dd>Specifies the number of filter values being supplied.
364 This will be 1 for EQ, GE, LE, and LIKE filter operators.
365 It will be 0 for NULL and NOTNULL operators. It will be
366 1 or more for NE.
367 <pre class='request'>
368 ricoXMLquery.php?id=ex2&amp;...&amp;f[0][op]=EQ&amp;f[0][len]=1
369 </pre>
370
371 <dt>f[X][Y] <span>(where X is the column #)</span>
372 <dd>Specifies the filter value(s) for EQ, NE, GE, LE, and LIKE filter operators.
373 Y will range from 0 to f[X][len]-1.
374 For the LIKE operator, '*' is treated as the wildcard character,
375 which gets converted to '%' by the Rico plug-in for most databases.
376 <pre class='request'>
377 ricoXMLquery.php?id=ex2&amp;...&amp;f[0][op]=EQ&amp;f[0][len]=1&amp;f[0][0]=Column0Value
378 </pre>
379 </dl>
380
381 <p>Plus, if any options.requestParameters were specified, they would be included also.
382 So the complete URL that would be used to fetch data for ex2 would be:
383 <pre class='request'>
384 ricoXMLquery.php?id=ex2&amp;offset=0&amp;page_size=28
385 </pre>
386
387
388 <h3>AjaxSQL Response</h3>
389
390 <p>The format of the AjaxSQL response is exactly the same as the 
391 <a href='#AjaxXMLresponse'>AjaxXML response</a>.
392
393
394 <h2><a name='AjaxJSON'>Rico.Buffer.AjaxJSON</a></h2>
395
396 <p>The AjaxJSON buffer was created by Jeremy Green and is an extension to the AjaxSQL buffer.
397 An AjaxJSON buffer is created using the following javascript:
398
399 <pre>
400 buffer=new Rico.Buffer.AjaxJSON(jsonUrl,options)
401 </pre>
402
403 <dl>
404 <dt>url
405 <dd>A string containing the url to the JSON data provider.
406
407 <dt>options
408 <dd>A Rico buffer options object. The values available in AjaxJSON are same as those in 
409 <a href='#AjaxSQLoptions'>AjaxSQL</a>.
410 </dl>
411
412
413 <h3>AjaxJSON Request</h3>
414
415 <p>The format of AjaxJSON requests are exactly the same as 
416 <a href='#AjaxSQLrequests'>AjaxSQL requests</a>.
417
418
419 <h3>AjaxJSON Response</h3>
420
421 <p>Here is an example of a LiveGrid response in JSON format.\r
422 \r
423 <pre class='response'>
424 {
425 "update_ui": true,
426 "offset": 0,
427 "rows": [
428 ["10248","VINET","Vins et alcools Chevalier","Reims","France","1996-07-04 00:00:00","1996-07-16 00:00:00"],
429 ["10249","TOMSP","Toms Spezialitäten","Münster","Germany","1996-07-05 00:00:00","1996-07-10 00:00:00"],
430 ["10250","HANAR","Hanari Carnes","Rio de Janeiro","Brazil","1996-07-08 00:00:00","1996-07-12 00:00:00"],
431 ["10251","VICTE","Victuailles en stock","Lyon","France","1996-07-08 00:00:00","1996-07-15 00:00:00"],
432 ["10252","SUPRD","Suprêmes délices","Charleroi","Belgium","1996-07-09 00:00:00","1996-07-11 00:00:00"],
433 ["10253","HANAR","Hanari Carnes","Rio de Janeiro","Brazil","1996-07-10 00:00:00","1996-07-16 00:00:00"],
434 ["10254","CHOPS","Chop-suey Chinese","Bern","Switzerland","1996-07-11 00:00:00","1996-07-23 00:00:00"]
435 ],
436 "rowCount": 830
437 }
438 </pre>
439 \r
440 <p>The format closely follows the XML based data consumed by the Rico.Buffer.AjaxSQL buffer 
441 and all values should be returned accordingly.\r
442 The ‘rows’ value object of the data object is a normal JS Array with each element 
443 being a JS hash that represents the row. For the hash the key/value combo should be colName/colValue.\r
444
445
446 </body>
447 </html>