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