Fix index hopefully
[clinton/website/site/unknownlamer.org.git] / UCWNotes.html
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>
127 Abstract</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
130 Lisp, but is a bit difficult to learn. It is documented
131 extensively&mdash;in the form of docstrings. These are extremely helpful
132 once you've figured out the rough structure of UCW, but they are of no
133 help when first learning unless you just read most of the source. I
134 ended 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
136 public consumption.</p>
137
138 <p>The roadmap is presented with major sections ordered in a logical
139 order for learning the framework. The sections are ordered internally
140 in order of most immediately useful to least, but it may be worth
141 hopping between major sections before reading all of the details. I
142 have used abridged class definitions and docstrings with occasional
143 commentary to clarify things.</p>
144
145
146 <h2><a name="sec2" id="sec2"></a>
147 Roadmap</h2>
148
149 <h3><a name="sec3" id="sec3"></a>
150 Applications</h3>
151
152 <p class="first">Applications are a bundle of entry points. The base class is,
153 naturally, <code>standard-application</code>, but you should instead derive your
154 application class from <code>modular-application</code> and any standard or custom
155 application 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
163 start (prefix) of all the urls this app should handle.
164
165 This value is used by the standard-server to decide what app a
166 particular request is aimed at and for generating links to
167 actions 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
170 specifiers) 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
173 dispatchers. The user supplied list of dispatchers is extended
174 with other dispatchers that are required for UCW to function
175 properly (action-dispatcher, a parenscript-dispatcher, etc). If
176 you want full control over the active dispatchers use the (setf
177 application.dispatchers) accessor or, if you want control over
178 the 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>
195 Cookie</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
203 Cookie session applications work exactly like
204 standard-applications except that when the session is not found
205 using 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
209 application urls readable by stashing the session id into a cookie
210 rather than as a set of long and ugly GET parameters.</p>
211
212
213 <h4><a name="sec5" id="sec5"></a>
214 L10n</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>
225 Secure</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.
233 Concrete application must specialize the following methods:
234 APPLICATION-FIND-USER (APPLICATION USERNAME)
235 APPLICATION-CHECK-PASSWORD (APPLICATION USER PASSWORD)
236 APPLICATION-AUTHORIZE-CALLZE-CALL (APPLICATION USER FROM-COMPONENT TO-COMPONENT)."</span>))
237 </pre>
238
239
240
241 <h3><a name="sec7" id="sec7"></a>
242 Components</h3>
243
244 <p class="first">A component is a special class that handles the complexities of
245 continuation suspension and such for you. New components are derived
246 from the existing ones by using <code>defcomponent</code> instead of <code>defclass</code>. This
247 adds a few extra slot and class options, and ensures that the proper
248 metaclass 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
256 This macro is used to create component classes and provides
257 options for easily creating the methods which often accompany a
258 component definition.
259
260 NAME, SUPERS and SLOTS as treated as per defclass. The following
261 extra 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
287 options can be passed to component slots:
288
289 :backtrack [ T | NIL | FUNCTION-NAME ] - Specify that this slot
290 should be backtracked (or not if NIL is passed as the value). If
291 the value is neither T nor NIL then it must be a function which
292 will be used as the copyer.
293
294 :component [ TYPE | ( TYPE &amp;rest INITARGS ) ] - Specify that this
295 slot is actually a nested component of type TYPE. When instances
296 of the class are created this slot will be set to an instance of
297 type TYPE and it's place will be set to this slot. If a list is
298 passed to :component then TYPE (which isn't evaluated) will be
299 passed as the first argument to make-instance. The INITARGS will
300 be eval'd and apply'd to make-instance. The result of this call
301 to make-instance will be used as the effective component
302 object."</span>
303 </pre>
304
305 <h4><a name="sec8" id="sec8"></a>
306 Windows</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
321 Each element must be a list whose first value is either the
322 symbol :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
328 The 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
333 data to the user, or just deriving your own funky top level window
334 type.</p>
335
336 <p><code>simple-window-component</code> is the easiest for displaying standard
337 webpage. It provides a wrapping method on render that displays the
338 html boilerplate based on your component slot values which is what one
339 wants most of the time. The initargs to <code>simple-window-component</code> have
340 the 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
348 just shows a div with status messages. A derivative could be defined
349 to 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
354 show. Each element is a cons of the form (SEVERITY .
355 MESSAGE). SEVERITY is one of :ERROR, :WARN, :INFO and MESSAGE is
356 a 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
362 severity 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
390 This component, which must be used as a window-component,
391 redirects the client to the url specified in the target slot. A
392 302 (as opposed to 303) response code is sent to ensure
393 compatability with older browsers.
394
395 The 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.
403 This is useful in order to have a GET url after a form POST's
404 actions have completed running. The user can then refresh to his
405 heart's content."</span>)
406 </pre>
407
408
409
410 <h4><a name="sec9" id="sec9"></a>
411 Containers</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
421 The container component serves to manage a set of components.
422 It does not provide any render impementation, which is the
423 resposibility of the subclasses (e.g. switching-container or
424 list-container).
425
426 Each contained component has a \"key\" associated with it which
427 is used to retrieve a particular component. Keys are compared with
428 container.key-test.
429
430 The :contents inintarg, if provided, must be either a list of (key .
431 component) or a list of components. In the latter case it will
432 be 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
454 This component is like the regular CONTAINER but serves to manage a set
455 of components which share the same place in the UI. Therefore it provides
456 an implementation of RENDER which simply renders its current component.
457
458 The switching-container component class is generally used as the super
459 class for navigatation components and tabbed-pane like
460 components."</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
485 naviation and content box. The navigation box is a set of styled divs
486 containing the navigation links.</p>
487
488
489
490 <h4><a name="sec10" id="sec10"></a>
491 Dialogs</h4>
492
493 <p class="first">A few convenience dialogs are provided for grabbing data from the
494 user.</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
505 This component, which must be embedded in another component,
506 presents the user with a simple two fielded login form.
507
508 When the user attempts a login the action try-login is called,
509 try-login calls the generic function check-credentials passing it
510 the login component. If check-credentials returns true then the
511 login-successful action is called, otherwise the message slot of
512 the login component is set (to a generic \"bad username\"
513 message).
514
515 The default implementaion of login-successful simply answers t,
516 no default implementation of check-credentials is
517 provided. Developers should use sub-classes of login for which
518 all 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
538 protocol 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
584 If the OK-TEXT slot is non-NIL component will use that as the
585 text for a link which, when clicked, causes the component to
586 answer. It follows that if OK-TEXT is NIL this component will
587 never 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
602 The value of the slot MESSAGE is used as a general heading.
603
604 The OPTIONS slot must be an alist of (VALUE . LABEL). LABEL (a
605 string) will be used as the text of a link which, when clikced,
606 will answer VALUE.
607
608 If the CONFIRM slot is T the user will be presented with a second
609 OPTION-DIALOG asking the user if they are sure they want to
610 submit 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
622 used as a string literal otherwise. This does not provide a way to set
623 the confirm property which makes the macro not so generally useful.</p>
624
625
626
627 <h4><a name="sec11" id="sec11"></a>
628 Forms</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
660 supports a few fancy features. The <code>:accessor</code> for all form elements is
661 set to <code>(client-value FIELD)</code>, and you should use <code>value</code> to access the
662 Lisp 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
669 If the ACCESSOR attribute is specified then it must be a PLACE
670 and it's value will be used to fill the input, when the form is
671 submitted it will be set to the new value.
672
673 If ACTION is specefied then when the form is submitted via this
674 input type=\"submit\" tag the form will be eval'd. when the
675 submit (or image) is clicked. DEFAULT means that the ACTION
676 provided for this input tag will be the default action of the
677 form when pressing enter in a form field. If more then one, then
678 the latest wins."</span>)
679 </pre>
680
681 <p>Validation of form fields are supported by adding to the validators
682 list.</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
694 This is the convenience entry point to generate-javascript-check,
695 methods defined on this generic funcition should return a list of
696 javascript code (as per parenscript) which tests against the
697 javascript 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
778 part. <code>(mime-part-body (value FIELD))</code> will return a <strong>binary stream</strong>
779 attached to the contents of the file. The <code>Content-Type</code> header should
780 be 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
786 The alist must be of the form (NAME . VALUE) where both NAME and
787 VALUE 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.
802 That 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
833 elements you wish to include in the form. A <code>:wrapping</code> method renders
834 the 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>
850 Templates</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
864 Methods defined on this generic function must return a TAL
865 environment: a list of TAL binding sets (see the documentation
866 for YACLML:MAKE-STANDARD-ENVIRONMENT for details on TAL
867 environments.)"</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
873 Binds the symbol ucw:component to the component object itself,
874 also puts the object COMPONENT on the environment (after the
875 binding of ucw:component) so that slots are, by default,
876 visable."</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
882 Calls the component's template. The name of the template is the
883 value returned by the generic function
884 template-component.template-name, the template will be rendered
885 in the environment returned by the generic function
886 template-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
894 the ability to set environment variables in initarg. Subclass to
895 provide automagic template file name generation and such.</p>
896
897
898 <h4><a name="sec13" id="sec13"></a>
899 Utility 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
910 The data set is presented one \"window\" at a time with links to
911 the the first, previous, next and last window. Each window shows
912 at most WINDOW-SIZE elements of the data. The data is passed to
913 the range-view at instance creation time via the :DATA initarg.
914
915 The generic function RENDER-RANGE-VIEW-ITEM is used to render
916 each item of DATA.
917
918 In order to change the rendering of the single elements of a
919 range view developer's should create a sub class of RANGE-VIEW
920 and 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
929 applies 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
938 for 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
951 HTML elements control aspects that are relevant to almost all tags.
952
953 Firstly they provide a place to store the class, id, and style of the
954 component. The specific render methods of the components themselves
955 must pass these values to whatever code is used to render the actual
956 tag.
957
958 Secondly, they allow javascript event handlers to be registered for a
959 tag. The events slot can be filled with a list of lists in the form
960
961 (event parenscript-statement*)
962
963 For example (\"onclick\" (alert \"You clicked!\") (return nil)). If
964 the element has a dom-id, these event handlers are automatically
965 added."</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
988 transactions. After a transaction has been closed an attempt to
989 backtrack into a step inside the transaction will result in jumping up
990 one level of transactions (or out of the transaction entirely if at
991 the top level). This ensures that the transaction is only run once,
992 naturally.</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
1008 into 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
1019 component is instantiated. Task components do not have their own
1020 RENDER method, in fact they have no graphical representation but
1021 serve 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
1025 task-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
1049 The component caching API is built around the generic functions
1050 COMPONENT-DIRTY-P and REFRESH-COMPONENT-OUTPUT and a method on
1051 RENDER, see the respective docstrings for more details.
1052
1053 Do 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>
1084 Control 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>
1091 Calling</h4>
1092
1093 <p class="first">Most of what you do in UCW will be calling components so this is a bit
1094 important. Note that calling interrupts the current control flow so if
1095 you want to render a component in place as part of another component
1096 just 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
1101 a freshly created component of type COMPONENT-TYPE.
1102
1103 COMPONENT-INIT-ARGS are passed directly to the underlying
1104 make-instance call. This form will return if and when the call'd
1105 component calls answer, the value returned by this form is
1106 whatever the call'd component passed to answer.
1107
1108 Notes:
1109
1110 This macro assumes that the lexcial variable UCW:SELF is bound to
1111 the 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
1125 the 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>
1130 Actions</h4>
1131
1132 <p class="first">Actions are methods on components. The first argument <strong>must</strong> be a
1133 component 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
1144 most UCW control flow things to work. <code>defaction</code> hides this from you,
1145 and was a big source of confusion for me early on (mostly &quot;hmm, why is
1146 this not working ... where did that come from in the
1147 macroexpansion!&quot;).</p>
1148
1149
1150 <h4><a name="sec17" id="sec17"></a>
1151 Entry 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
1161 mater of <code>DISPATCHER-CLASS</code> that enters into <code>APPLICATION</code> running the
1162 code in <code>body</code>. An example from a test program I have written
1163 follows. The entry point allows files to be streamed to user when the
1164 url 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>
1181 Dispatching</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
1188 matcher. This method would return multiple-values according to
1189 matcher internal nature.
1190
1191 No methods defined on this function may rebind *context*, nor
1192 change CONTEXT's application. Only if the method matches the
1193 request, it is allowed to modify CONTEXT or APPLICATION, even in
1194 that case methods defined on this function must not modify
1195 CONTEXT'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
1199 implement in order to handle a request matched by relevant
1200 matcher.
1201
1202 These methods may modify context as they wish since they'r
1203 matched, 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
1209 No methods defined on this function may rebind *context*, nor
1210 change CONTEXT's application. Only if the method returns T is it
1211 allowed to modify CONTEXT or APPLICATION, even in that case
1212 methods defined on this function must not modify CONTEXT's
1213 application 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>
1224 Simple 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
1231 Unlike all other UCW dispatchers a simple-dispatcher must not use
1232 CALL, and must perform the rendering directly within the handler."</span>)
1233 </pre>
1234
1235
1236
1237 <h3><a name="sec20" id="sec20"></a>
1238 Server</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
1252 PORT. Affects *DEFAULT-SERVER*.
1253
1254 BACKEND is a list of (BACKEND-TYPE &amp;rest INITARGS). BACKEND-TYPE
1255 may be :HTTPD, :MOD-LISP, :ASERVE, :ARANEIDA, an existing
1256 backend, an existing UCW server backend or :DEFAULT in which case
1257 it attempts to return a sane default from the UCW backends loaded
1258 and available, or any other value for which a valid MAKE-BACKEND
1259 method has been defined. INITARGS will be passed, unmodified, to
1260 MAKE-BACKEND.
1261
1262 APPLICATIONS is a list of defined applications to be loaded into the
1263 server.
1264
1265 Logs are generated in verbosity defined by LOG-LEVEL and directed to
1266 LOG-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>
1273 Debugging</h3>
1274
1275 <h4><a name="sec22" id="sec22"></a>
1276 Inspector</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>
1290 Tips</h2>
1291
1292 <h3><a name="sec24" id="sec24"></a>
1293 Getting dojo to load</h3>
1294
1295 <p class="first">I had some trouble getting dojo to work properly with UCW. The way
1296 that the <code>:www-roots</code> option for an application works is a bit
1297 confusing, and it is unforgiving if you mess the pathname up. A
1298 directory <strong>must</strong> have a <code>/</code> at the end, and the directory you are serving
1299 must also have the <code>/</code> (which is counterintuitive given the behavior of
1300 most 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>
1309 Specials Bound During Rendering</h3>
1310
1311 <p class="first">The current request context is bound to <code>ucw:*context*</code>, and the current
1312 component 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>
1317 Printing to the yaclml stream</h3>
1318
1319 <p class="first">Occasionally it can be useful to do something like write a byte array
1320 as 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
1322 you 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
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
1357 </p>
1358 <p class="cke-timestamp">Last Modified:
1359 March 13, 2008</p>
1360 </body>
1361 </html>