File: examples.html

package info (click to toggle)
libapache2-mod-rivet 3.2.2-1
  • links: PTS
  • area: main
  • in suites: bookworm
  • size: 6,296 kB
  • sloc: xml: 8,554; tcl: 7,568; ansic: 7,094; sh: 5,017; makefile: 195; sql: 91; lisp: 78
file content (512 lines) | stat: -rw-r--r-- 28,356 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Examples and Usage</title><link rel="stylesheet" type="text/css" href="rivet.css"><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot"><link rel="home" href="index.html" title="Apache Rivet 3.2"><link rel="up" href="index.html" title="Apache Rivet 3.2"><link rel="prev" href="xml.html" title="xml"><link rel="next" href="tcl_packages.html" title="Rivet Tcl Packages"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Examples and Usage</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="xml.html"><img src="images/prev.png" alt="Prev"></a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="tcl_packages.html"><img src="images/next.png" alt="Next"></a></td></tr></table></div><div class="section"><div class="titlepage"><div><div><hr><h2 class="title" style="clear: both"><a name="examples"></a>Examples and Usage</h2></div></div></div><p style="width:90%">
        Some examples of Rivet usage follow.  Some prior Tcl knowledge
        is assumed.  If you don't know much Tcl, don't worry, it's easy,
        and there are some good resources available on the web that will
        get you up to speed quickly.  Go to the 
        <a class="link" href="help.html#websites" title="Web Sites">web sites</a> section and have a look.
    </p><div class="example"><a name="hello_world"></a><p class="title"><b>Example 1. Hello World</b></p><div class="example-contents"><p style="width:90%">
			As with any tool, it's always nice to see something work, so
			let's create a small "Hello World" page.
	    </p><p style="width:90%">
			Assuming you have Apache configured correctly, create a file
			called <code class="filename">hello.rvt</code> where Apache can find
			it, with the following content:
        </p><pre class="programlisting">&lt;?
puts "Hello World"
?&gt;

</pre><p style="width:90%">
			If you then access it with your browser, you should see a
			blank page with the text "Hello World" (without the quotes) on it.
            The command <span style="font-family:monospace"><span class="command"><strong>puts</strong></span></span> is the good old Tcl command for
            terminal printing, which appends to the argument string the control
            characters needed to open a newline. When you don't have to run through
            complex elaboration and the output can be lumped
            in a single string (just like in the 'Hello World' example) you
            can draw on the popular shorthand syntax for string
            output that comes handy in many cases
        </p><pre class="programlisting">&lt;?= "Hello World" ?&gt;
</pre><p style="width:90%">
            which is translated into 
            </p><pre class="programlisting">puts -nonewline "Hello World"</pre><p style="width:90%">
        </p></div></div><br class="example-break"><div class="example"><a name="idm1976"></a><p class="title"><b>Example 2. Generate a Colorful Table</b></p><div class="example-contents"><p style="width:90%">
	   	In another simple example, we dynamically generate a table selecting
	   	a different background color for each cell. The font color is determined
	   	through a simple CSS rule embedded in a HTML &lt;style&gt; element. Create
	   	the file colortable.rvt and put the following code in it
	  	</p><pre class="programlisting">&lt;html&gt;&lt;head&gt;
    &lt;style&gt;
        td { 
            font-size: 12px;
            font-family: monospace;
            text-align: center;
            padding-left: 3px;
            padding-right: 3px
        }
        td.bright { color: #eee; }
        td.dark   { color: #222; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;table&gt;
&lt;?
# we create a 9x9 table selecting a different background for each cell

for {set i 0} { $i &lt; 9 } {incr i} {
    puts "&lt;tr&gt;"
    for {set j 0} {$j &lt; 9} {incr j} {

        set r [expr int(255 * ($i + $j) / 16)] 
        set g [expr int(255 * (8 + $j - $i) / 16)]
        set b [expr int(255 * (abs (4 - $i) + abs(4 - $j)) / 8)]

# determining the background luminosity (YIQ space of NTSC) and choosing
# the foreground color accordingly in order maintain maximum contrast

        if { [expr ($r*0.29894)+($g*0.58704)+($b*0.11402)] &gt; 148.0} {
            set cssclass "dark"
        } else {
            set cssclass "bright"
        }

        set cell [format "%3d %3d %3d" $r $g $b]

        puts [format \
            "&lt;td bgcolor=\"%02x%02x%02x\" class=\"%s\"&gt;%s&lt;/td&gt;" \
                                            $r $g $b $cssclass $cell]
    }
    puts "&lt;/tr&gt;"
}
?&gt;
    &lt;/table&gt;
&lt;/body&gt;&lt;/html&gt;
</pre><p style="width:90%">
	    	If you read the code, you can see that this is pure Tcl.  We
	    	could take the same code, run it outside of Rivet, and it
	    	would generate the same HTML
	  	</p><p style="width:90%">
	    	The result should look something like this:
	  	</p><div><img src="images/color-table.png"></div></div></div><br class="example-break"><div class="example"><a name="variable_access"></a><p class="title"><b>Example 3. Variable Access</b></p><div class="example-contents"><p style="width:90%">
			Here, we demonstrate how to access variables set by GET or
			POST operations.
      </p><p style="width:90%">
			Given an HTML form like the following:
      </p><pre class="programlisting">&lt;form action="vars.rvt"&gt;
  &lt;table&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;b&gt;Title:&lt;/b&gt;&lt;/td&gt;
        &lt;td&gt;&lt;input name="title" /&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;b&gt;Salary:&lt;/b&gt;&lt;/td&gt;
        &lt;td&gt;&lt;input name="salary" /&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;b&gt;Boss:&lt;/b&gt;&lt;/td&gt;
        &lt;td&gt;&lt;input name="boss" /&gt;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;b&gt;Skills:&lt;/b&gt;&lt;/td&gt;
        &lt;td&gt;
          &lt;select name="skills" multiple="multiple"&gt;
            &lt;option&gt;C&lt;/option&gt;
            &lt;option&gt;Java&lt;/option&gt;
            &lt;option&gt;Tcl&lt;/option&gt;
            &lt;option&gt;Perl&lt;/option&gt;
          &lt;/select&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;input type="submit" /&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/form&gt;

</pre><p style="width:90%">
			We can use this Rivet script to get the variable values:
      </p><pre class="programlisting">&lt;?
set errlist {}
if { [::rivet::var exists title] } {
    set title [::rivet::var get title]
} else {
    set errlist "You need to enter a title"
}

if { [::rivet::var exists salary] } {
    set salary [::rivet::var get salary]
    if { ! [string is digit $salary] } {
        lappend errlist "Salary must be a number"
    }
} else {
    lappend errlist "You need to enter a salary"
}

if { [::rivet::var exists boss] } {
    set boss [::rivet::var get boss]
} else {
    set boss "Mr. Burns"
}

if { [::rivet::var exists skills] } {
    set skills [::rivet::var list skills]
} else {
    lappend errlist "You need to enter some skills"
}

if { [llength $errlist] != 0 } {
    foreach err $errlist {
        puts "&lt;b&gt; $err &lt;/b&gt;"
    }
} else {
    puts "Thanks for the information!"
    ?&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;b&gt;Title:&lt;/b&gt;&lt;/td&gt;
          &lt;td&gt;&lt;?= $title ?&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;b&gt;Boss:&lt;/b&gt;&lt;/td&gt;
          &lt;td&gt;&lt;?= $boss ?&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;b&gt;Salary:&lt;/b&gt;&lt;/td&gt;
          &lt;td&gt;&lt;?= $salary ?&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&lt;b&gt;Skills:&lt;/b&gt;&lt;/td&gt;
          &lt;td&gt;&lt;?= $skills ?&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
    &lt;?
}
?&gt;

</pre><p style="width:90%">
			The first statement checks to make sure that the
			<code class="varname">boss</code> variable has been passed to the
			script, and then does something with that information.  If
			it's not present, an error is added to the list of errors.
      </p><p style="width:90%">
	In the second block of code, the variable
	<code class="varname">salary</code> is fetched, with one more error
	check - because it's a number, it needs to be composed of
	digits.
      </p><p style="width:90%">
	The <code class="varname">boss</code> variable isn't required to have
	been sent - we set it to "Mr. Burns" if it isn't among the
	information we received.
      </p><p style="width:90%">
	The last bit of variable handing code is a bit trickier.
	Because <code class="varname">skills</code> is a listbox, and can
	potentially have multiple values, we opt to receive them as a
	list, so that at some point, we could iterate over them.
      </p><p style="width:90%">
	The script then checks to make sure that
	<code class="varname">errlist</code> is empty and outputting a thankyou
	message.  If <code class="varname">errlist</code> is not empty, the list
	of errors it contains is printed.
      </p></div></div><br class="example-break"><div class="example"><a name="file_upload"></a><p class="title"><b>Example 4. File Upload</b></p><div class="example-contents"><p style="width:90%">
			The <span style="font-family:monospace"><span class="command"><strong>::rivet::upload</strong></span></span> command endows Rivet with an
			interface to access files transferred over http as parts of a
			multipart form.  The following HTML in one file, say,
			<code class="filename">upload.html</code> creates a form with a text
			input entry. By clicking the file chooser button the file
			browser shows up and the user selects the file to be uploaded
			(the file path will appear in the text input).  In order to make
			sure you're uploading the whole file you must combine the
			action of the enctype and method attributes of the
			&lt;form...&gt; tag in the way shown in the example.  Failure
			to do so would result in the client sending only the file's
			path, rather than the actual contents.
      </p><pre class="programlisting">&lt;form action="foo.rvt" enctype="multipart/form-data" method="post"&gt;
&lt;input type="file" name="MyUpload"&gt;&lt;/input&gt;
&lt;input type="submit" value="Send File"&gt;&lt;/input&gt;
&lt;/form&gt;

</pre><p style="width:90%">
			In the script invoked by the form
			(<code class="filename">upload.rvt</code>) <span style="font-family:monospace"><span class="command"><strong>upload</strong></span></span>
			 ?<span style="font-family:monospace; font-weight: bold;">argument ...</span>? commands can be used to manipulate the
			various files uploaded.
      </p><pre class="programlisting">&lt;?
::rivet::upload save MyUpload /tmp/uploadfiles/file1
puts "Saved file [::rivet::upload filename MyUpload] \
	([::rivet::upload size MyUpload] bytes) to server"
?&gt;

</pre><p style="width:90%">
			Don't forget that the apache server must have write access to
			the directory where files are being created.  The Rivet Apache
			directives have a substantial impact on the upload process,
			you have to carefully read the docs in order to set the
			appropriate directives values that would match your
			requirements.
      </p><p style="width:90%">
			It is also important to understand that some 
			<span style="font-family:monospace"><span class="command"><strong>upload</strong></span></span> commands are effective only when
			used in a mutually exclusive way.  Apache stores the data in
			temporary files which are read by the <span style="font-family:monospace"><span class="command"><strong>upload save
			 ?<span style="font-family:monospace; font-weight: bold;">upload name</span>? ?<span style="font-family:monospace; font-weight: bold;">filename</span>?</strong></span></span> or by the
			<span style="font-family:monospace"><span class="command"><strong>upload data  ?<span style="font-family:monospace; font-weight: bold;">upload name</span>?</strong></span></span>
			command. Subsequent calls to these 2 commands using the same
			 ?<span style="font-family:monospace; font-weight: bold;">upload name</span>? argument will return no data on the
			second call.  Likewise <span style="font-family:monospace"><span class="command"><strong>upload channel  ?<span style="font-family:monospace; font-weight: bold;">upload
			name</span>?</strong></span></span> will return a Tcl file channel that you
			can use in regular Tcl scripts only if you haven't already
			read the data, for example with a call to the <span style="font-family:monospace"><span class="command"><strong>upload
			data  ?<span style="font-family:monospace; font-weight: bold;">upload name</span>?</strong></span></span> command.
      </p></div></div><br class="example-break"><div class="example"><a name="file_download"></a><p class="title"><b>Example 5. File Download</b></p><div class="example-contents"><p style="width:90%">
			In general setting up a data file for being sent over http is 
			as easy as determining the file's URI and letting Apache's
			do all that is needed. If this approach fits your design all 
			you have to do is to keep the downloadable files somewhere 
			within Apache's DocumentRoot (or in any of the directories 
			Apache has right to access).
      </p><p style="width:90%">
			When a client sends a request for a file, Apache takes
			care of determining the filetype, sends appropriate headers to
			the client and then the file content. The client is responsible
			for deciding how to handle the data accordingly to the 
			"content-type" headers and its internal design. For example
			when browsers give up trying to display a certain "content-type"
			they display a download dialog box asking for directions from
			the user. 
      </p><p style="width:90%">
            Rivet can help if you have more sofisticated needs.  For
            instance you may be developing an application that uses
            webpages to collect input data. This information might be
            passed on to scripts or programs for processing. 
            In this case a real file representing the
            data doesn't exist and the content is generated on demand 
            by the server. 
            In other circumstances you may need to dynamically inhibit 
            the download of specific files and hide them away, 
            Your scripts may expunge from the pages
            every link to these files (your pages are dynamic, aren't
            they?) and move them out of way, but it looks like a
            cumbersome solution.
      </p><p style="width:90%">
            Putting Tcl and Rivet in charge of the whole download
            mechanism helps in building cleaner and safer approaches to
            the download problem.
      </p><p style="width:90%">
            In this example a procedure checks for the existence of a
            parameter passed in by the browser. The parameter is the name
            (without extension) of a pdf file.  
            Pdf files are stored in a directory whose path is
            in the <span style="font-family:monospace"><span class="command"><strong>pdf_repository</strong></span></span> variable.
      </p><p style="width:90%">
            This code is reported as an example of how to control 
            the protocol using the <span style="font-family:monospace"><span class="command"><strong>headers</strong></span></span> command.
      </p><pre class="programlisting"># Code example for the transmission of a pdf file. 

if {[::rivet::var exists pdfname]} {
    set pdfname [::rivet::var get pdfname]

# let's build the full path to the pdf file. The 'pdf_repository'
# directory must be readable by the apache children

    set pdf_full_path [file join $pdf_repository ${pdfname}.pdf]
    if {[file exists $pdf_full_path]} {

# Before the file is sent we inform the client about the file type and
# file name. The client can be proposed a filename different from the
# original one. In this case, this is the point where a new file name
# must be generated.

        ::rivet::headers type                       "application/pdf"
        ::rivet::headers add Content-Disposition    "attachment; filename=${pdfname}.pdf"
        ::rivet::headers add Content-Description    "PDF Document"

# The pdf is read and stored in a Tcl variable. The file handle is
# configured for a binary read: we are just shipping raw data to a
# client. The following 4 lines of code can be replaced by any code
# that is able to retrieve the data to be sent from any data source
# (e.g. database, external program, other Tcl code)

        set paper       [open $pdf_full_path r]
        fconfigure      $paper -translation binary
        set pdf         [read $paper]
        close $paper

# Now we got the data: let's tell the client how many bytes we are
# about to send (useful for the download progress bar of a dialog box)

        ::rivet::headers add Content-Length  [string length $pdf]

# Let's send the actual file content

        puts $pdf
    } else {
        source pdf_not_found_error.rvt
    }
} else {
    source parameter_not_defined_error.rvt
}

</pre><p style="width:90%">
            Before the pdf is sent the procedure sets the
            <code class="constant">Content-Type</code>, 
            <code class="constant">Content-Disposition</code>,
            <code class="constant">Content-Description</code> and
            <code class="constant">Content-Length</code> headers to inform
            the client about the file type, name and size. Notice that in
            order to set the <code class="constant">Content-Type</code> header Rivet 
            uses a specialiezed form of the <span style="font-family:monospace"><span class="command"><strong>headers</strong></span></span> 
            command. Headers must be sent before data gets sent down the 
            output channel. Messing with this prescription causes an error 
            to be raised (in fact the protocol itself is been violated)
      </p><p style="width:90%">
	More information about the meaning of the mime headers in the
	http context can be found at 
	<a class="ulink" href="http://www.w3.org/Protocols/rfc2616/rfc2616.html" target="_top">http://www.w3.org/Protocols/rfc2616/rfc2616.html</a>
      </p></div></div><br class="example-break"><div class="example"><a name="ajax_xml_messaging"></a><p class="title"><b>Example 6. XML Messages and Ajax</b></p><div class="example-contents"><p style="width:90%">
	The <span style="font-family:monospace"><span class="command"><strong>headers</strong></span></span> command is crucial for generating 
	XML messages that have to be understood by JavaScript code used 
	in Ajax applications. 
      </p><p style="width:90%">
	    Ajax is a web programming technique that heavily relies on the abilty of a web browser to run in backround
	    JavaScript functions. JavaScript functions can be run as callbacks of events generated by a user interaction 
	    but they can also react to other I/O events, for example network events. 
	    Modern browsers endow JavaScript with the ability to build http GET/POST requests to be sent to a remote
	    webserver. Generally these requests refer to scripts (e.g. Tcl scripts run by Rivet) which inherit as 
	    variables the arguments encoded in the request. 
	    The output produced by these scripts is sent back to the browser where callbacks functions extract 
	    information and hand it down to functions that directly manipulate a page's DOM.
	    Therefore through Ajax becomes possible to build web applications that are more responsive and flexible: 
	    instead of going through the cycle of request-generation-transfer-display 
	    of a whole page, Ajax scripts request from a webserver only the essential data to be displayed.
	    Ajax emphasizes the requirement of separation between data and user interface, saves 
	    the server from sending over the same html code and graphics if only a fraction of a page has to be 
	    updated, allows the programmer to design flexible solutions for complex forms and makes possible
	    to find new innovative approaches to simple problems (e.g. Google tips that show up as you type in
	    a query). A downside of this approach is the large number of complexities, subtleties and incompatibilities 
	    that still exist in the way different versions of popular browsers handle the DOM elements of a page.
      </p><p style="width:90%">
	    JavaScript can handle the communication between client and server through an instance of a 
	    specialized object. For quite a long time 2 approaches existed, the non-IE world (Firefox,Safari,Opera...) 
	    used the XMLHttpRequest class to create this object, whereas IE (before IE7) used the ActiveXObject class.
	    With the release of IE7 Microsoft introduced native support for XMLHttpRequest class objects thus enabling
	    programmers with a unique method for the development of dynamic pages. 
	</p><p style="width:90%">
	    By creating an instance of this class a POST or GET request can be sent to the server and the response is 
	    stored in a property ('returnedText') of the communication object. It's become widely customary to encode 
	    these responses in XML messages. You can invent your own message structure (either based on XML or anything 
	    else), but one has to be aware that if the http headers are properly set and the message returned to the 
	    client is a well formed XML fragment, also the property XMLResponse is assigned with a reference to an object 
	    that represents the DOM of the XML response. By means of the XML W3C DOM interface the programmer can easily
	    manipulate the data embedded in the XML message.
	</p><p style="width:90%">
	    In this example a Rivet script initializes an array with the essential data regarding a few of the major 
	    composers of the european music. This array plays the role of a database. The script sends back to the 
	    client two types of responses: a catalog of the composers or a single record of a composer.
	</p><pre class="programlisting">#
# Ajax query servelet: a pseudo database is built into the dictionary 'composers' with the
# purpose of emulating the role of a real data source. 
# The script answers with  2 types of responses: a catalog of the record ids and a database 
# entry matching a given rec_id. The script obviously misses the error handling and the
# likes. Just an example to see rivet sending xml data to a browser. The full Tcl, JavaScript
# and HTML code are available from http://people.apache.org/~mxmanghi/rivet-ajax.tar.gz

# This example requires Tcl8.5 or Tcl8.4 with package 'dict' 
# (http://pascal.scheffers.net/software/tclDict-8.5.2.tar.gz)
# 

# A pseudo database. rec_id matches a record in the db

set composers [dict create  \
                1 {first_name Claudio middle_name "" last_name Monteverdi   \
                    lifespan 1567-1643 era Renaissance/Baroque}             \
                2 {first_name Johann middle_name Sebastian last_name Bach   \
                    lifespan 1685-1750 era Baroque }                        \
                3 {first_name Ludwig middle_name "" last_name "van Beethoven" \
                    lifespan 1770-1827 era Classical/Romantic}              \
                4 {first_name Wolfgang middle_name Amadeus last_name Mozart \
                    lifespan 1756-1791 era Classical }                      \
                5 {first_name Robert middle_name "" last_name Schumann      \
                    lifespan 1810-1856 era Romantic} ]

# we use the 'load' argument in order to determine the type of query
#
# load=catalog:         we have to return a list of the names in the database
# load=composer&amp;amp;res_id=&lt;id&gt;: the script is supposed to return the record
#               having &lt;id&gt; as record id

if {[::rivet::var exists load]} {

# the xml declaration is common to every message (error messages included)

    set xml "&lt;?xml version=\"1.0\" encoding=\"ISO-8859-1\"?&gt;\n"
    switch [::rivet::var get load] {
        catalog {
            append xml "&lt;catalog&gt;\n"
            foreach nm [dict keys $composers] {
                set first_name  [dict get $composers $nm first_name]
                set middle_name [dict get $composers $nm middle_name]
                set last_name   [dict get $composers $nm last_name]
                append xml "    &lt;composer key=\"$nm\"&gt;$first_name "
                if {[string length [string trim $middle_name]] &gt; 0} {
                    append xml "$middle_name "
                }
                append xml "$last_name&lt;/composer&gt;\n"
            }
            append xml "&lt;/catalog&gt;\n"
        }
        composer {
            append xml "&lt;composer&gt;\n"
            if {[::rivet::var exists rec_id]} {
                set rec_id [::rivet::var get rec_id]
                if {[dict exists $composers $rec_id]} {
                    foreach {k v} [dict get $composers $rec_id] {
                        append xml "&lt;$k&gt;$v&lt;/$k&gt;\n"
                    }
                }
            }
            append xml "&lt;/composer&gt;\n"
        }
    }

# we have to tell the client this is an XML message. Failing to do so
# would result in an XMLResponse property set to null

    ::rivet::headers type "text/xml"
    ::rivet::headers add Content-Length [string length $xml]
    puts $xml
}


</pre><p style="width:90%">
	    For sake of brevity the JavaScript and HTML will not listed here. They can be downloaded (along with the Tcl 
	    script) stored in the <a class="ulink" href="http://people.apache.org/~mxmanghi/rivet-ajax.tar.gz" target="_top">rivet-ajax.tar.gz</a> archive. 
	    By simply opening this tar archive in a directory accessible 
	    by your apache server and pointing your browser to the rivetService.html page you should see a page with a 
	    drop-down list. Every time a different name is picked from the list a new query is sent and logged in the 
	    apache access.log file, even though the html is never reloaded.
	</p></div></div><br class="example-break"><div class="example"><a name="calendar_example"></a><p class="title"><b>Example 7. A Calendar Utility</b></p><div class="example-contents"><p style="width:90%">
	    Rivet comes with a <span class="emphasis"><em>Calendar</em></span> package that provides classes for printing 
	    calendar tables in various forms.	
	</p><p style="width:90%">
		The <span class="emphasis"><em>HtmlCalendar</em></span> class prints a calendar table in a similar form the Unix 
		program 'cal' does. Example: the following code
		</p><pre class="programlisting">package require Calendar

proc ::cal_cell_attributes { day month year weekday } {
    if {$weekday == 3} {
        return [list class curr_wkday]
    }
}

set htmlc [HtmlCalendar #auto]
set html_txt [$htmlc emit -container {table class calendar} -current_weekday 3 \
                          -cell_function cal_cell_attributes ]
puts $html_txt
</pre><p style="width:90%">

	    with some CSS styling would print
	 </p><p style="width:90%">
		</p><div><img src="images/calendar.png"></div><p style="width:90%">
	 </p></div></div><br class="example-break"></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="xml.html"><img src="images/prev.png" alt="Prev"></a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="tcl_packages.html"><img src="images/next.png" alt="Next"></a></td></tr><tr><td width="40%" align="left" valign="top">xml </td><td width="20%" align="center"><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a></td><td width="40%" align="right" valign="top"> Rivet Tcl Packages</td></tr></table></div></body></html>