Update index this time...
[clinton/website/site/unknownlamer.org.git] / UCWNotes.html
CommitLineData
2aff8b5c 1<?xml version="1.0" encoding="utf-8" ?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4<html xmlns="http://www.w3.org/1999/xhtml">
5 <head>
6 <title>Roadmap to UCW Codebase</title>
7 <meta name="generator" content="muse.el" />
8 <meta http-equiv="Content-Type"
9 content="text/html; charset=utf-8" />
10<link rel="stylesheet" href="default.css" media="screen" />
11 </head>
12 <body>
13 <h1>Roadmap to UCW Codebase</h1>
14 <div class="contents">
15<dl>
16<dt>
17<a href="#sec1">Abstract</a>
18</dt>
19<dt>
20<a href="#sec2">Roadmap</a>
21</dt>
22<dd>
23<dl>
24<dt>
25<a href="#sec3">Applications</a>
26</dt>
27<dd>
28<dl>
29<dt>
30<a href="#sec4">Cookie</a>
31</dt>
32<dt>
33<a href="#sec5">L10n</a>
34</dt>
35<dt>
36<a href="#sec6">Secure</a>
37</dt>
38</dl>
39</dd>
40<dt>
41<a href="#sec7">Components</a>
42</dt>
43<dd>
44<dl>
45<dt>
46<a href="#sec8">Windows</a>
47</dt>
48<dt>
49<a href="#sec9">Containers</a>
50</dt>
51<dt>
52<a href="#sec10">Dialogs</a>
53</dt>
54<dt>
55<a href="#sec11">Forms</a>
56</dt>
57<dt>
58<a href="#sec12">Templates</a>
59</dt>
60<dt>
61<a href="#sec13">Utility Mixin Components</a>
62</dt>
63</dl>
64</dd>
65<dt>
66<a href="#sec14">Control Flow</a>
67</dt>
68<dd>
69<dl>
70<dt>
71<a href="#sec15">Calling</a>
72</dt>
73<dt>
74<a href="#sec16">Actions</a>
75</dt>
76<dt>
77<a href="#sec17">Entry Points</a>
78</dt>
79</dl>
80</dd>
81<dt>
82<a href="#sec18">Dispatching</a>
83</dt>
84<dd>
85<dl>
86<dt>
87<a href="#sec19">Simple Dispatcher</a>
88</dt>
89</dl>
90</dd>
91<dt>
92<a href="#sec20">Server</a>
93</dt>
94<dt>
95<a href="#sec21">Debugging</a>
96</dt>
97<dd>
98<dl>
99<dt>
100<a href="#sec22">Inspector</a>
101</dt>
102</dl>
103</dd>
104</dl>
105</dd>
106<dt>
107<a href="#sec23">Tips</a>
108</dt>
109<dd>
110<dl>
111<dt>
112<a href="#sec24">Getting dojo to load</a>
113</dt>
114<dt>
115<a href="#sec25">Specials Bound During Rendering</a>
116</dt>
117<dt>
118<a href="#sec26">Printing to the yaclml stream</a>
119</dt>
120</dl>
121</dd>
122</dl>
123</div>
124
125
126<!-- Page published by Emacs Muse begins here --><h2><a name="sec1" id="sec1"></a>
127Abstract</h2>
128
129<p><a href="http://common-lisp.net/project/ucw/">UnCommon Web</a> is a very powerful and mature web framework for Common
130Lisp, but is a bit difficult to learn. It is documented
131extensively&mdash;in the form of docstrings. These are extremely helpful
132once you've figured out the rough structure of UCW, but they are of no
133help when first learning unless you just read most of the source. I
134ended up having to do that, and after some urging along by folks in
135<code>#ucw</code> I decided to clean up my planner notes and publish them for
136public consumption.</p>
137
138<p>The roadmap is presented with major sections ordered in a logical
139order for learning the framework. The sections are ordered internally
140in order of most immediately useful to least, but it may be worth
141hopping between major sections before reading all of the details. I
142have used abridged class definitions and docstrings with occasional
143commentary to clarify things.</p>
144
145
146<h2><a name="sec2" id="sec2"></a>
147Roadmap</h2>
148
149<h3><a name="sec3" id="sec3"></a>
150Applications</h3>
151
152<p class="first">Applications are a bundle of entry points. The base class is,
153naturally, <code>standard-application</code>, but you should instead derive your
154application class from <code>modular-application</code> and any standard or custom
155application mixins you find useful.</p>
156
157<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/standard-classes.lisp">src/rerl/standard-classes.lisp</a></p>
158
159<pre class="src">
160(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">standard-application</span> (application)
161 ((url-prefix <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:url-prefix</span>
162 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A string specifying the
163start (prefix) of all the urls this app should handle.
164
165This value is used by the standard-server to decide what app a
166particular request is aimed at and for generating links to
167actions within the app. "</span>)
168 (www-roots <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:www-roots</span>
169 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A list of directories (pathname
170specifiers) or cons-cell (URL-subdir . pathname) to use when looking for static files."</span>)
171 (dispatchers <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:dispatchers</span>
172 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A list of request
173dispatchers. The user supplied list of dispatchers is extended
174with other dispatchers that are required for UCW to function
175properly (action-dispatcher, a parenscript-dispatcher, etc). If
176you want full control over the active dispatchers use the (setf
177application.dispatchers) accessor or, if you want control over
178the order of the dispathcers, (slot-value instance
179'dispatchers)."</span>))
180 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The default UCW application class."</span>))
181</pre>
182
183<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/modular-application/modular-application.lisp">src/rerl/modular-application/modular-application.lisp</a></p>
184
185<pre class="src">
186(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">modular-application-mixin</span> ()
187 ()
188 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Superclass for all application mixins."</span>))
189
190(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">modular-application</span> (standard-application modular-application-mixin)
191 ...)
192</pre>
193
194<h4><a name="sec4" id="sec4"></a>
195Cookie</h4>
196
197<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/modular-application/cookie-module.lisp">src/rerl/modular-application/cookie-module.lisp</a></p>
198
199<pre class="src">
200(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">cookie-session-application-module</span> (modular-application-mixin)
201 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Class for applications which use cookies for sesion tracking.
202
203Cookie session applications work exactly like
204standard-applications except that when the session is not found
205using the standard mechanisms the id is looked for in a cookie."</span>))
206</pre>
207
208<p>This is the most useful of the application components. It makes your
209application urls readable by stashing the session id into a cookie
210rather than as a set of long and ugly GET parameters.</p>
211
212
213<h4><a name="sec5" id="sec5"></a>
214L10n</h4>
215
216<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/modular-application/l10n-module.lisp">src/rerl/modular-application/l10n-module.lisp</a></p>
217
218<pre class="src">
219(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">l10n-application-module</span> (modular-application-mixin)
220 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Application class which can handle l10n requests."</span>))
221</pre>
222
223
224<h4><a name="sec6" id="sec6"></a>
225Secure</h4>
226
227<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/modular-application/security-module.lisp">src/rerl/modular-application/security-module.lisp</a></p>
228
229<pre class="src">
230(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">secure-application-module</span> (modular-application-mixin)
231 (<span style="color: #b0c4de;">:documentation</span>
232 <span style="color: #b3b3b3;">"Mixin class for applications which require authorized access.
233Concrete application must specialize the following methods:
234APPLICATION-FIND-USER (APPLICATION USERNAME)
235APPLICATION-CHECK-PASSWORD (APPLICATION USER PASSWORD)
236APPLICATION-AUTHORIZE-CALLZE-CALL (APPLICATION USER FROM-COMPONENT TO-COMPONENT)."</span>))
237</pre>
238
239
240
241<h3><a name="sec7" id="sec7"></a>
242Components</h3>
243
244<p class="first">A component is a special class that handles the complexities of
245continuation suspension and such for you. New components are derived
246from the existing ones by using <code>defcomponent</code> instead of <code>defclass</code>. This
247adds a few extra slot and class options, and ensures that the proper
248metaclass is set.</p>
249
250<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/standard-component/standard-component.lisp">src/rerl/standard-component/standard-component.lisp</a></p>
251
252<pre class="src">
253(<span style="color: #00ffff;">defmacro</span> <span style="color: #87cefa;">defcomponent</span> (name supers slots <span style="color: #98fb98;">&amp;rest</span> options)
254 <span style="color: #b3b3b3;">"Macro for defining a component class.
255
256This macro is used to create component classes and provides
257options for easily creating the methods which often accompany a
258component definition.
259
260NAME, SUPERS and SLOTS as treated as per defclass. The following
261extra options are allowed:
262
263 (:ENTRY-POINT url (&amp;key application class)) - Define an
264 entry-point on the url URL which simply calls an instance of
265 this component. Any request parameters passed to the entry-point
266 are used to initialize the slots in the component. This option
267 may appear multiple times.
268
269 (:DEFAULT-BACKTRACK function-designator) - Unless the slots
270 already have a :backtrack option FUNCTION-DESIGNATOR is
271 added. As with the 'regular' :backtrack options if you pass T
272 here it is assumed to mean #'IDENTITY.
273
274 (:RENDER (&amp;optional COMPONENT) &amp;body BODY) - Generate a render
275 method specialized to COMPONENT. COMPONENT may be a symbol, in
276 which case the method will be specialized on the componnet
277 class. If COMPONNET is omited the component is bound to a
278 variable with the same name as the class.
279
280 (:ACTION &amp;optional NAME) - Generate a defaction form named
281 NAME (which defaults to the name of the component) which simply
282 CALL's this component class passing all the arguments passed to
283 the action as initargs."</span>)
284
285<span style="color: #ff7f24;">;;; </span><span style="color: #ff7f24;">Extra Slot Options
286</span><span style="color: #b3b3b3;">"Other than the initargs for standard slots the following
287options can be passed to component slots:
288
289:backtrack [ T | NIL | FUNCTION-NAME ] - Specify that this slot
290should be backtracked (or not if NIL is passed as the value). If
291the value is neither T nor NIL then it must be a function which
292will be used as the copyer.
293
294:component [ TYPE | ( TYPE &amp;rest INITARGS ) ] - Specify that this
295slot is actually a nested component of type TYPE. When instances
296of the class are created this slot will be set to an instance of
297type TYPE and it's place will be set to this slot. If a list is
298passed to :component then TYPE (which isn't evaluated) will be
299passed as the first argument to make-instance. The INITARGS will
300be eval'd and apply'd to make-instance. The result of this call
301to make-instance will be used as the effective component
302object."</span>
303</pre>
304
305<h4><a name="sec8" id="sec8"></a>
306Windows</h4>
307
308<p class="first">A window-component represents a top level browser window, naturally.</p>
309
310<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/window.lisp">src/components/window.lisp</a></p>
311
312<pre class="src">
313(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">window-component</span> ()
314 ((content-type)))
315
316(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">simple-window-component</span> (window-component)
317 ((title)
318 (stylesheet)
319 (javascript <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"List of javascript includes.
320
321Each element must be a list whose first value is either the
322symbol :SRC or :JS.
323
324 (:SRC url) - writes &lt;script src=\"URL\"&gt;&lt;/script&gt; tag.
325 (:JS form) - equivalent to (:SCRIPT (js:js* form))
326 (:SCRIPT string) - write &lt;script&gt;STRING&lt;/script&gt;.
327
328The elements will be rendered in order."</span>)
329 ...))
330</pre>
331
332<p><code>window-component</code> could be useful for doing things like dumping binary
333data to the user, or just deriving your own funky top level window
334type.</p>
335
336<p><code>simple-window-component</code> is the easiest for displaying standard
337webpage. It provides a wrapping method on render that displays the
338html boilerplate based on your component slot values which is what one
339wants most of the time. The initargs to <code>simple-window-component</code> have
340the same names as the slots.</p>
341
342<h5>Status Bar</h5>
343
344<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/status-bar.lisp">src/components/status-bar.lisp</a></p>
345
346<p>There is a generic status bar interface. Messages severity is one of
347<code>(:error :warn :info)</code>. Note that the default status bar render method
348just shows a div with status messages. A derivative could be defined
349to insert messages into the browser status bar.</p>
350
351<pre class="src">
352(defcomponent status-bar ()
353 ((messages <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"An ALIST of the messages to
354show. Each element is a cons of the form (SEVERITY .
355MESSAGE). SEVERITY is one of :ERROR, :WARN, :INFO and MESSAGE is
356a string which will be html-escaped."</span>)
357 ...)
358 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Stateless status bar to display messages."</span>))
359
360(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">add-message</span> (status-bar msg <span style="color: #98fb98;">&amp;key</span> severity <span style="color: #98fb98;">&amp;allow-other-keys</span>)
361 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Add the message text MSG to STATUS-BAR with
362severity SEVERITY."</span>))
363</pre>
364
365<pre class="src">
366(defcomponent status-bar-mixin ()
367 ((status-bar <span style="color: #b0c4de;">:accessor</span> status-bar
368 <span style="color: #b0c4de;">:initarg</span> status-bar
369 <span style="color: #b0c4de;">:component</span> (status-bar))))
370
371(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">show-status-bar</span> ((win status-bar-mixin))
372 (render (status-bar win)))
373
374(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">show-message</span> (msg <span style="color: #98fb98;">&amp;key</span> severity <span style="color: #98fb98;">&amp;allow-other-keys</span>)
375 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Show a message in the status bar. Only works if
376 current window is a status-bar-mixin"</span>))
377</pre>
378
379
380<h5>Redirect</h5>
381
382<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/redirect.lisp">src/components/redirect.lisp</a></p>
383
384<pre class="src">
385(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">redirect-component</span> ()
386 ((target <span style="color: #b0c4de;">:accessor</span> target <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:target</span>))
387 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class)
388 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Send a client redirect.
389
390This component, which must be used as a window-component,
391redirects the client to the url specified in the target slot. A
392302 (as opposed to 303) response code is sent to ensure
393compatability with older browsers.
394
395The redirect component never answers."</span>))
396</pre>
397
398<p>There is also a <code>meta-refresh</code> procedure.</p>
399
400<pre class="src">
401(defun/cc meta-refresh ()
402 <span style="color: #b3b3b3;">"Cause a meta-refresh (a freshly got (GET) url) at this point.
403This is useful in order to have a GET url after a form POST's
404actions have completed running. The user can then refresh to his
405heart's content."</span>)
406</pre>
407
408
409
410<h4><a name="sec9" id="sec9"></a>
411Containers</h4>
412
413<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/container.lisp">src/components/container.lisp</a></p>
414
415<pre class="src">
416(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">container</span> ()
417 (...)
418 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class)
419 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Allow multiple components to share the same place.
420
421The container component serves to manage a set of components.
422It does not provide any render impementation, which is the
423resposibility of the subclasses (e.g. switching-container or
424list-container).
425
426Each contained component has a \"key\" associated with it which
427is used to retrieve a particular component. Keys are compared with
428container.key-test.
429
430The :contents inintarg, if provided, must be either a list of (key .
431component) or a list of components. In the latter case it will
432be converted into (component . component) form."</span>))
433</pre>
434
435<h5>Protocol</h5>
436
437<ul>
438<li><code>child-components</code></li>
439<li><code>find-component CONTAINER KEY</code></li>
440<li><code>remove-component</code></li>
441<li><code>(setf find-component CONTAINER KEY) COMPONENT</code> -&gt;
442<code>add-component CONTAINER COMPONENT KEY</code></li>
443</ul>
444
445
446<h5>Switching Container</h5>
447
448<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/container.lisp">src/components/container.lisp</a></p>
449
450<pre class="src">
451(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">switching-container</span> ...
452 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A simple renderable container component.
453
454This component is like the regular CONTAINER but serves to manage a set
455of components which share the same place in the UI. Therefore it provides
456an implementation of RENDER which simply renders its current component.
457
458The switching-container component class is generally used as the super
459class for navigatation components and tabbed-pane like
460components."</span>))
461</pre>
462
463<p>Subclass and <code>(defmethod render :around ...)</code> to render navigation using
464<code>(call-next-method)</code> to render the selected component.</p>
465
466<h5>Protocol</h5>
467
468<ul>
469<li><code>container.current-component COMPONENT</code></li>
470<li><code>(setf container.current-component CONTAINER) COMPONENT</code></li>
471</ul>
472
473
474
475<h5>Tabbed Pane</h5>
476
477<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/tabbed-pane.lisp">src/components/tabbed-pane.lisp</a></p>
478
479<pre class="src">
480(defcomponent tabbed-pane (switching-container)
481 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Component for providing the user with a standard \"tabbed pane\" GUI widget."</span>))
482</pre>
483
484<p>Provides a generic tabbed pane that renders a nested div split into a
485naviation and content box. The navigation box is a set of styled divs
486containing the navigation links.</p>
487
488
489
490<h4><a name="sec10" id="sec10"></a>
491Dialogs</h4>
492
493<p class="first">A few convenience dialogs are provided for grabbing data from the
494user.</p>
495
496<h5>login</h5>
497
498<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/login.lisp">src/components/login.lisp</a></p>
499
500<pre class="src">
501(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">login</span> ()
502 ((username) (password) (message))
503 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Generic login (input username and password) component.
504
505This component, which must be embedded in another component,
506presents the user with a simple two fielded login form.
507
508When the user attempts a login the action try-login is called,
509try-login calls the generic function check-credentials passing it
510the login component. If check-credentials returns true then the
511login-successful action is called, otherwise the message slot of
512the login component is set (to a generic \"bad username\"
513message).
514
515The default implementaion of login-successful simply answers t,
516no default implementation of check-credentials is
517provided. Developers should use sub-classes of login for which
518all the required methods have been definined."</span>)
519 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class))
520</pre>
521
522<pre class="src">
523(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">check-credentials</span> (login)
524 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Returns T if LOGIN is valid."</span>))
525
526(defaction login-successful ((l login))
527 (answer t))
528</pre>
529
530<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/user-login.lisp">src/components/user-login.lisp</a></p>
531
532<pre class="src">
533(defcomponent user-login (simple-window-component status-bar-mixin)
534 ((username string-field) (password password-field)))
535</pre>
536
537<p>Used by <code>secure-application-module</code> to provide a user login. Relevant
538protocol details follow.</p>
539
540<pre class="src">
541(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">check-credentials</span> ((self user-login))
542 (<span style="color: #00ffff;">let*</span> ((username (value (username self)))
543 (password (value (password self)))
544 (user (find-application-user username)))
545 (<span style="color: #00ffff;">when</span> (and user (check-user-password user password))
546 user)))
547
548(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">application-find-user</span> (application username)
549 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Find USER by USERNAME for APPLICATION."</span>))
550</pre>
551
552
553<h5>error</h5>
554
555<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/error.lisp">src/components/error.lisp</a></p>
556
557<pre class="src">
558(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">error-message</span> (simple-window-component)
559 ((message <span style="color: #b0c4de;">:accessor</span> message <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:message</span> <span style="color: #b0c4de;">:initform</span> <span style="color: #b3b3b3;">"ERROR [no message specified]"</span>))
560 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Generic component for showing server side
561 error messages."</span>)
562 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class))
563
564(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">error-component</span> (error-message)
565 ((condition <span style="color: #b0c4de;">:accessor</span> error.condition <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:condition</span> <span style="color: #b0c4de;">:initform</span> nil)
566 (backtrace <span style="color: #b0c4de;">:accessor</span> error.backtrace <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:backtrace</span>))
567 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Generic component for showing server side
568 error conditions. Unlike ERROR-MESSAGE this component also
569 attempts to display a backtrace."</span>)
570 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class))
571</pre>
572
573
574<h5>message</h5>
575
576<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/message.lisp">src/components/message.lisp</a></p>
577
578<pre class="src">
579(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">info-message</span> ()
580 ((message <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:message</span> <span style="color: #b0c4de;">:accessor</span> message)
581 (ok-text <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:ok-text</span> <span style="color: #b0c4de;">:accessor</span> ok-text <span style="color: #b0c4de;">:initform</span> <span style="color: #b3b3b3;">"Ok."</span>))
582 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Component for showing a message to the user.
583
584If the OK-TEXT slot is non-NIL component will use that as the
585text for a link which, when clicked, causes the component to
586answer. It follows that if OK-TEXT is NIL this component will
587never answer."</span>)
588 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class))
589</pre>
590
591
592<h5>option-dialog</h5>
593
594<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/option-dialog.lisp">src/components/option-dialog.lisp</a></p>
595
596<pre class="src">
597(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">option-dialog</span> (template-component)
598 ((message) (options) (confirm))
599 (<span style="color: #b0c4de;">:default-initargs</span> <span style="color: #b0c4de;">:template-name</span> <span style="color: #b3b3b3;">"ucw/option-dialog.tal"</span>)
600 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Component for querying the user.
601
602The value of the slot MESSAGE is used as a general heading.
603
604The OPTIONS slot must be an alist of (VALUE . LABEL). LABEL (a
605string) will be used as the text of a link which, when clikced,
606will answer VALUE.
607
608If the CONFIRM slot is T the user will be presented with a second
609OPTION-DIALOG asking the user if they are sure they want to
610submit that value."</span>)
611 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class))
612</pre>
613
614<p>A macro to present an option dialog is provided.</p>
615
616<pre class="src">
617(<span style="color: #00ffff;">defmacro</span> <span style="color: #87cefa;">option-dialog</span> ((message-spec <span style="color: #98fb98;">&amp;rest</span> message-args) <span style="color: #98fb98;">&amp;body</span> options)
618 ...)
619</pre>
620
621<p><code>message-spec</code> is passed to <code>format</code> if <code>message-args</code> are supplied, and
622used as a string literal otherwise. This does not provide a way to set
623the confirm property which makes the macro not so generally useful.</p>
624
625
626
627<h4><a name="sec11" id="sec11"></a>
628Forms</h4>
629
630<p class="first">Reasonably useful forms library that integrates easily with TAL.</p>
631
632<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/form.lisp">src/components/form.lisp</a></p>
633
634<pre class="src">
635(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">form-field</span> ()
636 ((validators <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"List of validators which will be
637 applied to this field."</span>)
638 (initially-validate <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"When non-NIL the
639 validators will be run as soon as the page
640 is rendered."</span>)))
641
642(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">value</span> (form-field)
643 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The lispish translated value that represents the form-field."</span>))
644
645(<span style="color: #00ffff;">defgeneric</span> (<span style="color: #87cefa;">setf value)</span> (new-value form-field)
646 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Set the value of a form-field with translation to client."</span>))
647
648(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">generic-html-input</span> (form-field html-element)
649 ((client-value <span style="color: #b0c4de;">:accessor</span> client-value <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:client-value</span>
650 <span style="color: #b0c4de;">:initform</span> <span style="color: #b3b3b3;">""</span>
651 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The string the client submitted along with this field."</span>)
652 (name <span style="color: #b0c4de;">:accessor</span> name <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:name</span> <span style="color: #b0c4de;">:initform</span> nil)
653 (accesskey <span style="color: #b0c4de;">:accessor</span> accesskey <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:accesskey</span> <span style="color: #b0c4de;">:initform</span> nil)
654 (tooltip <span style="color: #b0c4de;">:accessor</span> tooltip <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:tooltip</span> <span style="color: #b0c4de;">:initform</span> nil)
655 (tabindex <span style="color: #b0c4de;">:accessor</span> tabindex <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:tabindex</span> <span style="color: #b0c4de;">:initform</span> nil))
656 (<span style="color: #b0c4de;">:default-initargs</span> <span style="color: #b0c4de;">:dom-id</span> (js:gen-js-name-string <span style="color: #b0c4de;">:prefix</span> <span style="color: #b3b3b3;">"_ucw_"</span>)))
657</pre>
658
659<p>Fields are rendered into the extended <code>&lt;ucw:input</code> yaclml tag which
660supports a few fancy features. The <code>:accessor</code> for all form elements is
661set to <code>(client-value FIELD)</code>, and you should use <code>value</code> to access the
662Lisp value associated with it.</p>
663
664<pre class="src">
665(deftag-macro &lt;ucw:input (<span style="color: #98fb98;">&amp;attribute</span> accessor action reader writer name id (default nil)
666 <span style="color: #98fb98;">&amp;allow-other-attributes</span> others)
667 <span style="color: #b3b3b3;">"Generic INPUT tag replacement.
668
669If the ACCESSOR attribute is specified then it must be a PLACE
670and it's value will be used to fill the input, when the form is
671submitted it will be set to the new value.
672
673If ACTION is specefied then when the form is submitted via this
674input type=\"submit\" tag the form will be eval'd. when the
675submit (or image) is clicked. DEFAULT means that the ACTION
676provided for this input tag will be the default action of the
677form when pressing enter in a form field. If more then one, then
678the latest wins."</span>)
679</pre>
680
681<p>Validation of form fields are supported by adding to the validators
682list.</p>
683
684<pre class="src">
685(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">validator</span> ()
686 ((message <span style="color: #b0c4de;">:accessor</span> message <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:message</span> <span style="color: #b0c4de;">:initform</span> nil)))
687
688(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">validate</span> (field validator)
689 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Validate a form-field with a validator."</span>))
690
691(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">javascript-check</span> (field validator)
692 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Generate javascript code for checking FIELD against VALIDATOR.
693
694This is the convenience entry point to generate-javascript-check,
695methods defined on this generic funcition should return a list of
696javascript code (as per parenscript) which tests against the
697javascript variable value."</span>))
698
699(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">javascript-invalid-handler</span> (field validator)
700 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The javascript code body for when a field is invalid."</span>))
701
702(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">javascript-valid-handler</span> (field validator)
703 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Generate the javascript body for when a field is valid."</span>))
704</pre>
705
706<h5>Standard Form Fields</h5>
707
708<pre class="src">
709(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">string-field</span> (generic-html-input)
710 ((input-size) (maxlength)))
711
712(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">password-field</span> (string-field))
713(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">number-field</span> (string-field))
714(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">integer-field</span> (number-field))
715
716(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">in-field-string-field</span> (string-field)
717 ((in-field-label <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"This slot, if non-NIL, will be
718 used as an initial field label. An initial
719 field label is a block of text which is placed
720 inside the input element and removed as soon
721 as the user edits the field. Obviously this
722 field is overidden by an initial :client-value
723 argument."</span>)))
724
725(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">textarea-field</span> (generic-html-input)
726 ((rows) (cols)))
727
728(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">date-field</span> (form-field widget-component)
729 ((year) (month) (day)))
730
731(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">dmy-date-field</span> (date-field)
732 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Date fields which orders the inputs day/month/year"</span>))
733(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">mdy-date-field</span> (date-field))
734
735(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">select-field</span> (generic-html-input)
736 ((data-set <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The values this select chooses
737 from."</span>))
738 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Form field used for selecting one value from a
739 list of available options."</span>))
740
741(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">render-value</span> (select-field value)
742 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"This function will be passed each value in the field's
743 data-set and must produce the body of the corresponding
744 &lt;ucw:option tag."</span>))
745
746(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">mapping-select-field</span> (select-field)
747 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Class used when we want to chose the values of
748 a certain mapping based on the keys. We render the keys in the
749 select and return the corresponding value from the VALUE
750 method."</span>))
751
752(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">hash-table-select-field</span> (mapping-select-field))
753(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">alist-select-field</span> (mapping-select-field))
754(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">plist-select-field</span> (mapping-select-field))
755
756(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">radio-group</span> (generic-html-input)
757 ((value-widgets)))
758
759(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">radio-button</span> (generic-html-input)
760 ((value)
761 (group <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The RADIO-GROUP this button is a part
762 of."</span>))
763 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A widget representing a single radio
764 button. Should be used in conjunction with a RADIO-GROUP."</span>))
765
766(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">add-value</span> ((group radio-group) value)
767 <span style="color: #b3b3b3;">"Adds radio-button with value to group"</span>)
768
769(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">checkbox-field</span> (generic-html-input))
770(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">file-upload-field</span> (generic-html-input))
771(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">submit-button</span> (generic-html-input)
772 ((label)))
773</pre>
774
775<h5>File Upload Field</h5>
776
777<p>Calling <code>value</code> on a <code>file-upload-field</code> returns a mime encoded body
778part. <code>(mime-part-body (value FIELD))</code> will return a <strong>binary stream</strong>
779attached to the contents of the file. The <code>Content-Type</code> header should
780be set to the MIME type of the file being uploaded.</p>
781
782<pre class="src">
783(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">mime-part-headers</span> (mime-part)
784 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Returns an alist of the headers of MIME-PART.
785
786The alist must be of the form (NAME . VALUE) where both NAME and
787VALUE are strings."</span>))
788
789(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">mime-part-body</span> (mime-part)
790 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Returns the body of MIME-PART."</span>))
791</pre>
792
793
794
795<h5>Standard Validators</h5>
796
797<pre class="src">
798(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">not-empty-validator</span> (validator))
799
800(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">value-validator</span> (validator)
801 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Validators that should only be applied if there is a value.
802That is, they always succeed on nil."</span>))
803
804(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">length-validator</span> (value-validator)
805 ((min-length <span style="color: #b0c4de;">:accessor</span> min-length <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:min-length</span>
806 <span style="color: #b0c4de;">:initform</span> nil)
807 (max-length <span style="color: #b0c4de;">:accessor</span> max-length <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:max-length</span>
808 <span style="color: #b0c4de;">:initform</span> nil)))
809
810(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">string=-validator</span> (validator)
811 ((other-field <span style="color: #b0c4de;">:accessor</span> other-field <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:other-field</span>))
812 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Ensures that a field is string= to another one."</span>))
813
814(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">regex-validator</span> (value-validator)
815 ((regex <span style="color: #b0c4de;">:accessor</span> regex <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:regex</span> <span style="color: #b0c4de;">:initform</span> nil)))
816
817(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">e-mail-address-validator</span> (regex-validator))
818
819(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">phone-number-validator</span> (regex-validator))
820
821(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">is-a-number-validator</span> (value-validator))
822(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">is-an-integer-validator</span> (is-a-number-validator))
823
824(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">number-range-validator</span> (is-a-number-validator)
825 ((min-value <span style="color: #b0c4de;">:accessor</span> min-value <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:min-value</span> <span style="color: #b0c4de;">:initform</span> nil)
826 (max-value <span style="color: #b0c4de;">:accessor</span> max-value <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:max-value</span> <span style="color: #b0c4de;">:initform</span> nil)))
827</pre>
828
829
830<h5>Simple Form Helper</h5>
831
832<p>UCW provides a helper class for developing forms. Subclass and add the
833elements you wish to include in the form. A <code>:wrapping</code> method renders
834the form boilerplate and then calls your <code>render</code>.</p>
835
836<pre class="src">
837(defcomponent simple-form (html-element)
838 ((submit-method <span style="color: #b0c4de;">:accessor</span> submit-method
839 <span style="color: #b0c4de;">:initform</span> <span style="color: #b3b3b3;">"post"</span>
840 <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:submit-method</span>)
841 (dom-id <span style="color: #b0c4de;">:accessor</span> dom-id
842 <span style="color: #b0c4de;">:initform</span> (js:gen-js-name-string <span style="color: #b0c4de;">:prefix</span> <span style="color: #b3b3b3;">"_ucw_simple_form_"</span>)
843 <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:dom-id</span>))
844 (<span style="color: #b0c4de;">:default-initargs</span> <span style="color: #b0c4de;">:dom-id</span> <span style="color: #b3b3b3;">"ucw-simple-form"</span>))
845</pre>
846
847
848
849<h4><a name="sec12" id="sec12"></a>
850Templates</h4>
851
852<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/template.lisp">src/components/template.lisp</a></p>
853
854<p>Infrastructure for loading TAL templates as a view of a component.</p>
855
856<pre class="src">
857(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">template-component</span> (component))
858(defcomponent simple-template-component (template-component)
859 ((environment <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:environment</span> <span style="color: #b0c4de;">:initform</span> nil)))
860
861(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">template-component-environment</span> (component)
862 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Create the TAL environment for rendering COMPONENT's template.
863
864Methods defined on this generic function must return a TAL
865environment: a list of TAL binding sets (see the documentation
866for YACLML:MAKE-STANDARD-ENVIRONMENT for details on TAL
867environments.)"</span>)
868 (<span style="color: #b0c4de;">:method-combination</span> nconc))
869
870(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">template-component-environment</span> nconc ((component template-component))
871 <span style="color: #b3b3b3;">"Create the basic TAL environment.
872
873Binds the symbol ucw:component to the component object itself,
874also puts the object COMPONENT on the environment (after the
875binding of ucw:component) so that slots are, by default,
876visable."</span>
877 (make-standard-environment `((component . ,component)) component))
878
879(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">render</span> ((component template-component))
880 <span style="color: #b3b3b3;">"Render a template based component.
881
882Calls the component's template. The name of the template is the
883value returned by the generic function
884template-component.template-name, the template will be rendered
885in the environment returned by the generic function
886template-component-environment."</span>
887 (render-template *context*
888 (template-component.template-name component)
889 (template-component-environment component)))
890
891</pre>
892
893<p>Subclass and override methods. <code>simple-template-component</code> only provides
894the ability to set environment variables in initarg. Subclass to
895provide automagic template file name generation and such.</p>
896
897
898<h4><a name="sec13" id="sec13"></a>
899Utility Mixin Components</h4>
900
901<h5>Range View</h5>
902
903<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/range-view.lisp">src/components/range-view.lisp</a></p>
904
905<pre class="src">
906(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">range-view</span> (template-component)
907 (<span style="color: #b0c4de;">:default-initargs</span> <span style="color: #b0c4de;">:template-name</span> <span style="color: #b3b3b3;">"ucw/range-view.tal"</span>)
908 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Component for showing the user a set of data one \"window\" at a time.
909
910The data set is presented one \"window\" at a time with links to
911the the first, previous, next and last window. Each window shows
912at most WINDOW-SIZE elements of the data. The data is passed to
913the range-view at instance creation time via the :DATA initarg.
914
915The generic function RENDER-RANGE-VIEW-ITEM is used to render
916each item of DATA.
917
918In order to change the rendering of the single elements of a
919range view developer's should create a sub class of RANGE-VIEW
920and define their RENDER-RANGE-VIEW-ITEM methods on that."</span>)
921 (<span style="color: #b0c4de;">:metaclass</span> standard-component-class))
922</pre>
923
924<pre class="src">
925(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">render-range-view-item</span> (range-view item)
926 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Render a single element of a range-view."</span>)
927 (<span style="color: #b0c4de;">:method</span> ((range-view range-view) (item t))
928 <span style="color: #b3b3b3;">"Standard implementation of RENDER-RANGE-VIEW-ITEM. Simply
929applies ITEM to princ (via &lt;:as-html)."</span>
930 (<span style="color: #00ffff;">declare</span> (ignore range-view))
931 (&lt;:as-html item)))
932</pre>
933
934
935<h5>Widget</h5>
936
937<p>Mixin with existing component to wrap in a div or span. This is handy
938for defining lightweight widgets embedded within other components.</p>
939
940<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/html-element.lisp">src/components/html-element.lisp</a></p>
941
942<pre class="src">
943(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">html-element</span> (component)
944 ((css-class)
945 (dom-id)
946 (css-style)
947 (extra-tags)
948 (events))
949 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"An HTML element.
950
951HTML elements control aspects that are relevant to almost all tags.
952
953Firstly they provide a place to store the class, id, and style of the
954component. The specific render methods of the components themselves
955must pass these values to whatever code is used to render the actual
956tag.
957
958Secondly, they allow javascript event handlers to be registered for a
959tag. The events slot can be filled with a list of lists in the form
960
961 (event parenscript-statement*)
962
963For example (\"onclick\" (alert \"You clicked!\") (return nil)). If
964the element has a dom-id, these event handlers are automatically
965added."</span>))
966</pre>
967
968<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/widget.lisp">src/components/widget.lisp</a></p>
969
970<pre class="src">
971(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">widget-component</span> (html-element)
972 ()
973 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A widget which should be wrapped in a &lt;div&gt;."</span>))
974
975(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">inline-widget-component</span> (html-element)
976 ()
977 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A widget which should be wrapped in &lt;span&gt; and not &lt;div&gt;"</span>))
978
979(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">render</span> <span style="color: #b0c4de;">:wrap-around</span> ((widget widget-component)))
980(<span style="color: #00ffff;">defmethod</span> <span style="color: #87cefa;">render</span> <span style="color: #b0c4de;">:wrap-around</span> ((widget inline-widget-component)))
981</pre>
982
983
984<h5>Transactions</h5>
985
986<p>A mixin to provide transactions. <code>(open-transaction component)</code> and
987<code>(close-transaction component)</code> open and closed nested
988transactions. After a transaction has been closed an attempt to
989backtrack into a step inside the transaction will result in jumping up
990one level of transactions (or out of the transaction entirely if at
991the top level). This ensures that the transaction is only run once,
992naturally.</p>
993
994<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/transaction-mixin.lisp">src/components/transaction-mixin.lisp</a></p>
995
996<pre class="src">
997(defcomponent transaction-mixin ()
998 (...))
999
1000(defmethod/cc open-transaction ((comp transaction-mixin)))
1001(defmethod/cc close-transaction ((comp transaction-mixin)))
1002</pre>
1003
1004
1005<h5>Task</h5>
1006
1007<p><code>(defaction start ...)</code> on subclass to run a series of actions bundled
1008into a task.</p>
1009
1010<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/task.lisp">src/components/task.lisp</a></p>
1011
1012<pre class="src">
1013(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">task-component</span> (standard-component)
1014 (...)
1015 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A controller for a single task or operation to
1016 be performed by the user.
1017
1018 A task component's START action is called as soon as the
1019component is instantiated. Task components do not have their own
1020RENDER method, in fact they have no graphical representation but
1021serve only to order a sequence of other components."</span>))
1022
1023(defgeneric/cc start (task)
1024 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"action which gets called automatically when
1025task-component is active. Use defaction to define your own
1026\"start\" action"</span>))
1027</pre>
1028
1029
1030<h5>Cached</h5>
1031
1032<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/components/cached.lisp">src/components/cached.lisp</a></p>
1033
1034<pre class="src">
1035(defcomponent cached-component ()
1036 ((cached-output <span style="color: #b0c4de;">:accessor</span> cached-output <span style="color: #b0c4de;">:initform</span> nil
1037 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"A string holding the output to
1038 use for this component. This string will be
1039 written directly to the html stream and is
1040 changed by the REFRESH-COMPONENT-OUTPUT
1041 method."</span> )
1042 (timeout <span style="color: #b0c4de;">:accessor</span> timeout <span style="color: #b0c4de;">:initarg</span> <span style="color: #b0c4de;">:timeout</span>
1043 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"An value specifying how often this
1044 component needs to be refreshed. The exact
1045 interpretation of the value depends on the type of
1046 caching used class."</span>))
1047 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Component which caches its output.
1048
1049The component caching API is built around the generic functions
1050COMPONENT-DIRTY-P and REFRESH-COMPONENT-OUTPUT and a method on
1051RENDER, see the respective docstrings for more details.
1052
1053Do not use CACHED-COMPONENT directly, use one its subclasses."</span>))
1054
1055(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">component-dirty-p</span> (component)
1056 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Returns T is COMPONENT's cache is invalid."</span>))
1057
1058(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">update-cache</span> (component)
1059 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Update COMPONENT's cache variables after a refresh."</span>))
1060
1061(defcomponent timeout-cache-component (cached-component)
1062 ((last-refresh <span style="color: #b0c4de;">:accessor</span> last-refresh <span style="color: #b0c4de;">:initform</span> nil
1063 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"The time, exrpessed as a
1064 universal time, when the component was last rendered."</span>))
1065 (<span style="color: #b0c4de;">:default-initargs</span>
1066 <span style="color: #b0c4de;">:timeout</span> (* 30 60 60))
1067 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Render the component at most every TIMEOUT seconds."</span>))
1068
1069(defcomponent num-hits-cache-component (cached-component)
1070 ((hits-since-refresh <span style="color: #b0c4de;">:accessor</span> hits-since-refresh
1071 <span style="color: #b0c4de;">:initform</span> nil
1072 <span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Number of views since last refresh."</span>))
1073 (<span style="color: #b0c4de;">:default-initargs</span> <span style="color: #b0c4de;">:timeout</span> 10)
1074 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Render the component every TIMEOUT views."</span>))
1075</pre>
1076
1077<p>Subclass and override <code>component-dirty-p</code> to do something useful
1078(e.g. flip mark bit when object being presented changes).</p>
1079
1080
1081
1082
1083<h3><a name="sec14" id="sec14"></a>
1084Control Flow</h3>
1085
1086<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/standard-component/control-flow.lisp">src/rerl/standard-component/control-flow.lisp</a></p>
1087
1088<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/standard-action.lisp">src/rerl/standard-action.lisp</a></p>
1089
1090<h4><a name="sec15" id="sec15"></a>
1091Calling</h4>
1092
1093<p class="first">Most of what you do in UCW will be calling components so this is a bit
1094important. Note that calling interrupts the current control flow so if
1095you want to render a component in place as part of another component
1096just call <code>render</code> on it instead.</p>
1097
1098<pre class="src">
1099(<span style="color: #00ffff;">defmacro</span> <span style="color: #87cefa;">call</span> (component-type <span style="color: #98fb98;">&amp;rest</span> component-init-args)
1100 <span style="color: #b3b3b3;">"Stop the execution of the current action and pass control to
1101a freshly created component of type COMPONENT-TYPE.
1102
1103COMPONENT-INIT-ARGS are passed directly to the underlying
1104make-instance call. This form will return if and when the call'd
1105component calls answer, the value returned by this form is
1106whatever the call'd component passed to answer.
1107
1108Notes:
1109
1110This macro assumes that the lexcial variable UCW:SELF is bound to
1111the calling component."</span>)
1112
1113(answer VAL) <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">answer parent component ONLY IN ACTIONS
1114</span>
1115(ok SELF VAL) <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">Used to answer a component anywhere and what answer
1116</span> <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">expands into
1117</span>
1118(jump COMPONENT-NAME <span style="color: #98fb98;">&amp;REST</span> ARGS) <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">is similar to call, but replaces
1119</span> <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">the current component with the new
1120</span> <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">one and drops any backtracks (back
1121</span> <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">button will no longer work)
1122</span></pre>
1123
1124<p><code>(call COMPONENT-NAME &amp;ARGS INIT-ARGS)</code> calls <code>COMPONENT-NAME</code> and returns
1125the value returned by <code>(ok SELF RETURN-VALUE)</code> called from within
1126<code>COMPONENT-NAME</code></p>
1127
1128
1129<h4><a name="sec16" id="sec16"></a>
1130Actions</h4>
1131
1132<p class="first">Actions are methods on components. The first argument <strong>must</strong> be a
1133component for most of UCW to work.</p>
1134
1135<pre class="src">
1136(defaction NAME (first ...) ...)
1137 <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">(roughly) expands into
1138</span>(defmethod/cc NAME (first ...)
1139 (<span style="color: #00ffff;">let</span> ((self first))
1140 ...))
1141</pre>
1142
1143<p><code>Self</code> being bound in the current lexical environment is required for
1144most UCW control flow things to work. <code>defaction</code> hides this from you,
1145and was a big source of confusion for me early on (mostly &quot;hmm, why is
1146this not working ... where did that come from in the
1147macroexpansion!&quot;).</p>
1148
1149
1150<h4><a name="sec17" id="sec17"></a>
1151Entry Points</h4>
1152
1153<pre class="src">
1154(defentry-point url (<span style="color: #b0c4de;">:application</span> APPLICATION
1155 <span style="color: #b0c4de;">:class</span> DISPATCHER-CLASS)
1156 (PARAM1 ... PARAMN) <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">GET / POST vars, bound in body
1157</span> body)
1158</pre>
1159
1160<p>An entry point is what it sounds like: a static URL matched using the
1161mater of <code>DISPATCHER-CLASS</code> that enters into <code>APPLICATION</code> running the
1162code in <code>body</code>. An example from a test program I have written
1163follows. The entry point allows files to be streamed to user when the
1164url audio.ucw?file=FOO is used.</p>
1165
1166<pre class="src">
1167(defentry-point <span style="color: #b3b3b3;">"^(audio.ucw|)$"</span> (<span style="color: #b0c4de;">:application</span> *golf-test-app*
1168 <span style="color: #b0c4de;">:class</span> regexp-dispatcher)
1169 (file)
1170 (call 'audio-file-window
1171 <span style="color: #b0c4de;">:audio-file</span> (make-instance 'audio-file
1172 <span style="color: #b0c4de;">:type</span> <span style="color: #b0c4de;">:vorbis</span>
1173 <span style="color: #b0c4de;">:data</span> (file-&gt;bytes (open
1174 file
1175 <span style="color: #b0c4de;">:element-type</span> 'unsigned-byte)))))
1176</pre>
1177
1178
1179
1180<h3><a name="sec18" id="sec18"></a>
1181Dispatching</h3>
1182
1183<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/rerl/standard-dispatcher.lisp">src/rerl/standard-dispatcher.lisp</a></p>
1184
1185<pre class="src">
1186(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">matcher-match</span> (matcher application context)
1187 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Abstract method for subclasses to implement a
1188matcher. This method would return multiple-values according to
1189matcher internal nature.
1190
1191No methods defined on this function may rebind *context*, nor
1192change CONTEXT's application. Only if the method matches the
1193request, it is allowed to modify CONTEXT or APPLICATION, even in
1194that case methods defined on this function must not modify
1195CONTEXT's application nor rebind *context*."</span>))
1196
1197(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">handler-handle</span> (handler application context matcher-result)
1198 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Abstract function for handler classes to
1199implement in order to handle a request matched by relevant
1200matcher.
1201
1202These methods may modify context as they wish since they'r
1203matched, request will be closed after this method is run."</span>))
1204
1205(<span style="color: #00ffff;">defgeneric</span> <span style="color: #87cefa;">dispatch</span> (dispatcher application context)
1206 (<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"Entry point into a dispatcher. Must return T
1207 if the context has been handled or NIL if it hasn't.
1208
1209No methods defined on this function may rebind *context*, nor
1210change CONTEXT's application. Only if the method returns T is it
1211allowed to modify CONTEXT or APPLICATION, even in that case
1212methods defined on this function must not modify CONTEXT's
1213application nor rebind *context*."</span>))
1214</pre>
1215
1216<pre class="src">
1217(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">my-matcher</span> (abstract-matcher) ...)
1218(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">my-handler</span> (abstract-handler) ...)
1219(<span style="color: #00ffff;">defclass</span> <span style="color: #98fb98;">my-dispatcher</span> (abstract-dispatcher my-matcher my-handler)
1220 ...)
1221</pre>
1222
1223<h4><a name="sec19" id="sec19"></a>
1224Simple Dispatcher</h4>
1225
1226<pre class="src">
1227(<span style="color: #b0c4de;">:documentation</span> <span style="color: #b3b3b3;">"This class of dispatchers avoids all of UCW's
1228 standard call/cc (and therefore frame/backtracking/component)
1229 mechanism.
1230
1231Unlike all other UCW dispatchers a simple-dispatcher must not use
1232CALL, and must perform the rendering directly within the handler."</span>)
1233</pre>
1234
1235
1236
1237<h3><a name="sec20" id="sec20"></a>
1238Server</h3>
1239
1240<p><a href="http://www.uncommon-web.com/darcsweb/darcsweb.cgi?r=ucw_dev;a=headblob;f=/src/control.lisp">src/control.lisp</a></p>
1241
1242<pre class="src">
1243(<span style="color: #00ffff;">defun</span> <span style="color: #87cefa;">create-server</span> (<span style="color: #98fb98;">&amp;key</span>
1244 (backend `(,*ucw-backend-type* <span style="color: #b0c4de;">:host</span> ,*ucw-backend-host*
1245 <span style="color: #b0c4de;">:port</span> ,*ucw-backend-port*))
1246 (applications *ucw-applications*)
1247 (start-p t)
1248 (server-class *ucw-server-class*)
1249 (log-root-directory (truename *ucw-log-root-directory*))
1250 (log-level *ucw-log-level*))
1251 <span style="color: #b3b3b3;">"Creates and returns a UCW server according to SERVER-CLASS, HOST and
1252PORT. Affects *DEFAULT-SERVER*.
1253
1254BACKEND is a list of (BACKEND-TYPE &amp;rest INITARGS). BACKEND-TYPE
1255may be :HTTPD, :MOD-LISP, :ASERVE, :ARANEIDA, an existing
1256backend, an existing UCW server backend or :DEFAULT in which case
1257it attempts to return a sane default from the UCW backends loaded
1258and available, or any other value for which a valid MAKE-BACKEND
1259method has been defined. INITARGS will be passed, unmodified, to
1260MAKE-BACKEND.
1261
1262APPLICATIONS is a list of defined applications to be loaded into the
1263server.
1264
1265Logs are generated in verbosity defined by LOG-LEVEL and directed to
1266LOG-ROOT-DIRECTORY if defined."</span>
1267 ...
1268 server) <span style="color: #ff7f24;">; </span><span style="color: #ff7f24;">return server, naturally
1269</span></pre>
1270
1271
1272<h3><a name="sec21" id="sec21"></a>
1273Debugging</h3>
1274
1275<h4><a name="sec22" id="sec22"></a>
1276Inspector</h4>
1277
1278<p><a href="/home/clinton/src/ucw/darcs/ucw_dev/src/components/ucw-inspector.lisp">/home/clinton/src/ucw/darcs/ucw_dev/src/components/ucw-inspector.lisp</a></p>
1279
1280<pre class="src">
1281(defaction call-inspector ((component component) datum)
1282 <span style="color: #b3b3b3;">"Call an inspector for DATUM on the component COMPONENT."</span>
1283 (call 'ucw-inspector <span style="color: #b0c4de;">:datum</span> datum))
1284</pre>
1285
1286
1287
1288
1289<h2><a name="sec23" id="sec23"></a>
1290Tips</h2>
1291
1292<h3><a name="sec24" id="sec24"></a>
1293Getting dojo to load</h3>
1294
1295<p class="first">I had some trouble getting dojo to work properly with UCW. The way
1296that the <code>:www-roots</code> option for an application works is a bit
1297confusing, and it is unforgiving if you mess the pathname up. A
1298directory <strong>must</strong> have a <code>/</code> at the end, and the directory you are serving
1299must also have the <code>/</code> (which is counterintuitive given the behavior of
1300most unix things that don't want the <code>/</code> at the end of the name).</p>
1301
1302<pre class="src">
1303<span style="color: #b0c4de;">:www-roots</span> (list '(<span style="color: #b3b3b3;">"dojo/"</span> .
1304 #P<span style="color: #b3b3b3;">"/home/clinton/src/ucw/darcs/ucw_dev/wwwroot/dojo/"</span>))
1305</pre>
1306
1307
1308<h3><a name="sec25" id="sec25"></a>
1309Specials Bound During Rendering</h3>
1310
1311<p class="first">The current request context is bound to <code>ucw:*context*</code>, and the current
1312component is bound to <code>ucw:*current-component*</code> in the dynamic extent of
1313<code>render</code>.</p>
1314
1315
1316<h3><a name="sec26" id="sec26"></a>
1317Printing to the yaclml stream</h3>
1318
1319<p class="first">Occasionally it can be useful to do something like write a byte array
1320as an ascii string to the client. Inside of <code>render</code> the variable
1321<code>yaclml:*yaclml-stream*</code> is bound to the stream that you can write to if
1322you wish to have content interspersed with yaclml tags.</p>
1323
1324
1325
1326 <!-- Page published by Emacs Muse ends here -->
1327
1328 <p class="cke-buttons">
1329 <!-- validating badges, any browser, etc -->
1330 <a href="http://validator.w3.org/check/referer"><img
1331 src="http://www.w3.org/Icons/valid-xhtml10"
1332 alt="Valid XHTML 1.0!" /></a>
1333
1334 <a href="http://www.anybrowser.org/campaign/"><img
1335 src="img/buttons/w3c_ab.png" alt="[ Viewable With Any Browser
1336 ]" /></a>
1337
1338 <a href="http://www.debian.org/"><img
1339 src="img/buttons/debian.png" alt="[ Powered by Debian ]" /></a>
1340
1341 <a href="http://hcoop.net/">
1342 <img src="img/buttons/hcoop.png"
1343 alt="[ Hosted by HCoop]" />
1344 </a>
1345
1346 <a href="http://www.fsf.org/register_form?referrer=114">
1347 <img src="img/buttons/fsf_member.png"
1348 alt="[ FSF Associate Member ]" />
1349 </a>
1350 </p>
1351
cb44b69b 1352<p class="cke-footer"> How can you accept social supression
1353 This weak state of mind in our time
1354 I demand release from hypocrisy
1355 I'd rather die than be held down, forced down
1356
2aff8b5c 1357</p>
1358<p class="cke-timestamp">Last Modified:
1359 March 13, 2008</p>
1360 </body>
1361</html>