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">
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" />
13 <h1>Roadmap to UCW Codebase
</h1>
14 <div class=
"contents">
17 <a href=
"#sec1">Abstract
</a>
20 <a href=
"#sec2">Roadmap
</a>
25 <a href=
"#sec3">Applications
</a>
30 <a href=
"#sec4">Cookie
</a>
33 <a href=
"#sec5">L10n
</a>
36 <a href=
"#sec6">Secure
</a>
41 <a href=
"#sec7">Components
</a>
46 <a href=
"#sec8">Windows
</a>
49 <a href=
"#sec9">Containers
</a>
52 <a href=
"#sec10">Dialogs
</a>
55 <a href=
"#sec11">Forms
</a>
58 <a href=
"#sec12">Templates
</a>
61 <a href=
"#sec13">Utility Mixin Components
</a>
66 <a href=
"#sec14">Control Flow
</a>
71 <a href=
"#sec15">Calling
</a>
74 <a href=
"#sec16">Actions
</a>
77 <a href=
"#sec17">Entry Points
</a>
82 <a href=
"#sec18">Dispatching
</a>
87 <a href=
"#sec19">Simple Dispatcher
</a>
92 <a href=
"#sec20">Server
</a>
95 <a href=
"#sec21">Debugging
</a>
100 <a href=
"#sec22">Inspector
</a>
107 <a href=
"#sec23">Tips
</a>
112 <a href=
"#sec24">Getting dojo to load
</a>
115 <a href=
"#sec25">Specials Bound During Rendering
</a>
118 <a href=
"#sec26">Printing to the yaclml stream
</a>
126 <!-- Page published by Emacs Muse begins here --><h2><a name=
"sec1" id=
"sec1"></a>
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
—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>
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>
146 <h2><a name=
"sec2" id=
"sec2"></a>
149 <h3><a name=
"sec3" id=
"sec3"></a>
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>
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>
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.
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>))
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>
186 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">modular-application-mixin
</span> ()
188 (
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"Superclass for all application mixins."</span>))
190 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">modular-application
</span> (standard-application modular-application-mixin)
194 <h4><a name=
"sec4" id=
"sec4"></a>
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>
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.
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>))
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>
213 <h4><a name=
"sec5" id=
"sec5"></a>
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>
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>))
224 <h4><a name=
"sec6" id=
"sec6"></a>
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>
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>))
241 <h3><a name=
"sec7" id=
"sec7"></a>
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>
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>
253 (
<span style=
"color: #00ffff;">defmacro
</span> <span style=
"color: #87cefa;">defcomponent
</span> (name supers slots
<span style=
"color: #98fb98;">&rest
</span> options)
254 <span style=
"color: #b3b3b3;">"Macro for defining a component class.
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.
260 NAME, SUPERS and SLOTS as treated as per defclass. The following
261 extra options are allowed:
263 (:ENTRY-POINT url (&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.
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.
274 (:RENDER (&optional COMPONENT) &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.
280 (:ACTION &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>)
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:
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.
294 :component [ TYPE | ( TYPE &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
305 <h4><a name=
"sec8" id=
"sec8"></a>
308 <p class=
"first">A window-component represents a top level browser window, naturally.
</p>
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>
313 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">window-component
</span> ()
316 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">simple-window-component
</span> (window-component)
319 (javascript
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"List of javascript includes.
321 Each element must be a list whose first value is either the
324 (:SRC url) - writes <script src=\"URL\
"></script> tag.
325 (:JS form) - equivalent to (:SCRIPT (js:js* form))
326 (:SCRIPT string) - write <script>STRING</script>.
328 The elements will be rendered in order."</span>)
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
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>
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>
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>
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>)
358 (
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"Stateless status bar to display messages."</span>))
360 (
<span style=
"color: #00ffff;">defgeneric
</span> <span style=
"color: #87cefa;">add-message
</span> (status-bar msg
<span style=
"color: #98fb98;">&key
</span> severity
<span style=
"color: #98fb98;">&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>))
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))))
371 (
<span style=
"color: #00ffff;">defmethod
</span> <span style=
"color: #87cefa;">show-status-bar
</span> ((win status-bar-mixin))
372 (render (status-bar win)))
374 (
<span style=
"color: #00ffff;">defgeneric
</span> <span style=
"color: #87cefa;">show-message
</span> (msg
<span style=
"color: #98fb98;">&key
</span> severity
<span style=
"color: #98fb98;">&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>))
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>
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.
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.
395 The redirect component never answers."</span>))
398 <p>There is also a
<code>meta-refresh
</code> procedure.
</p>
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>)
410 <h4><a name=
"sec9" id=
"sec9"></a>
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>
416 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">container
</span> ()
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.
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
426 Each contained component has a \"key\
" associated with it which
427 is used to retrieve a particular component. Keys are compared with
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>))
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> -
>
442 <code>add-component CONTAINER COMPONENT KEY
</code></li>
446 <h5>Switching Container
</h5>
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>
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.
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.
458 The switching-container component class is generally used as the super
459 class for navigatation components and tabbed-pane like
460 components."</span>))
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>
469 <li><code>container.current-component COMPONENT
</code></li>
470 <li><code>(setf container.current-component CONTAINER) COMPONENT
</code></li>
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>
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>))
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>
490 <h4><a name=
"sec10" id=
"sec10"></a>
493 <p class=
"first">A few convenience dialogs are provided for grabbing data from the
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>
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.
505 This component, which must be embedded in another component,
506 presents the user with a simple two fielded login form.
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\
"
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))
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>))
526 (defaction login-successful ((l login))
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>
533 (defcomponent user-login (simple-window-component status-bar-mixin)
534 ((username string-field) (password password-field)))
537 <p>Used by
<code>secure-application-module
</code> to provide a user login. Relevant
538 protocol details follow.
</p>
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))
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>))
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>
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))
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))
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>
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.
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))
592 <h5>option-dialog
</h5>
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>
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.
602 The value of the slot MESSAGE is used as a general heading.
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,
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))
614 <p>A macro to present an option dialog is provided.
</p>
617 (
<span style=
"color: #00ffff;">defmacro
</span> <span style=
"color: #87cefa;">option-dialog
</span> ((message-spec
<span style=
"color: #98fb98;">&rest
</span> message-args)
<span style=
"color: #98fb98;">&body
</span> options)
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>
627 <h4><a name=
"sec11" id=
"sec11"></a>
630 <p class=
"first">Reasonably useful forms library that integrates easily with TAL.
</p>
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>
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>)))
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>))
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>))
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>)))
659 <p>Fields are rendered into the extended
<code><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>
665 (deftag-macro
<ucw:input (
<span style=
"color: #98fb98;">&attribute
</span> accessor action reader writer name id (default nil)
666 <span style=
"color: #98fb98;">&allow-other-attributes
</span> others)
667 <span style=
"color: #b3b3b3;">"Generic INPUT tag replacement.
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.
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>)
681 <p>Validation of form fields are supported by adding to the validators
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)))
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>))
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.
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>))
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>))
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>))
706 <h5>Standard Form Fields
</h5>
709 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">string-field
</span> (generic-html-input)
710 ((input-size) (maxlength)))
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))
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
725 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">textarea-field
</span> (generic-html-input)
728 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">date-field
</span> (form-field widget-component)
729 ((year) (month) (day)))
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))
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
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>))
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 <ucw:option tag."</span>))
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
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))
756 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">radio-group
</span> (generic-html-input)
759 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">radio-button
</span> (generic-html-input)
761 (group
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"The RADIO-GROUP this button is a part
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>))
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>)
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)
775 <h5>File Upload Field
</h5>
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>
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.
786 The alist must be of the form (NAME . VALUE) where both NAME and
787 VALUE are strings."</span>))
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>))
795 <h5>Standard Validators
</h5>
798 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">not-empty-validator
</span> (validator))
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>))
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)))
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>))
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)))
817 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">e-mail-address-validator
</span> (regex-validator))
819 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">phone-number-validator
</span> (regex-validator))
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))
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)))
830 <h5>Simple Form Helper
</h5>
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>
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>))
849 <h4><a name=
"sec12" id=
"sec12"></a>
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>
854 <p>Infrastructure for loading TAL templates as a view of a component.
</p>
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)))
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.
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))
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.
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,
877 (make-standard-environment `((component . ,component)) component))
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.
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)))
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>
898 <h4><a name=
"sec13" id=
"sec13"></a>
899 Utility Mixin Components
</h4>
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>
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.
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.
915 The generic function RENDER-RANGE-VIEW-ITEM is used to render
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))
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 <:as-html)."</span>
930 (
<span style=
"color: #00ffff;">declare
</span> (ignore range-view))
931 (
<:as-html item)))
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>
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>
943 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">html-element
</span> (component)
949 (
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"An HTML element.
951 HTML elements control aspects that are relevant to almost all tags.
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
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
961 (event parenscript-statement*)
963 For example (\"onclick\
" (alert \"You clicked!\
") (return nil)). If
964 the element has a dom-id, these event handlers are automatically
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>
971 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">widget-component
</span> (html-element)
973 (
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"A widget which should be wrapped in a <div>."</span>))
975 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">inline-widget-component
</span> (html-element)
977 (
<span style=
"color: #b0c4de;">:documentation
</span> <span style=
"color: #b3b3b3;">"A widget which should be wrapped in <span> and not <div>"</span>))
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)))
984 <h5>Transactions
</h5>
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,
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>
997 (defcomponent transaction-mixin ()
1000 (defmethod/cc open-transaction ((comp transaction-mixin)))
1001 (defmethod/cc close-transaction ((comp transaction-mixin)))
1007 <p><code>(defaction start ...)
</code> on subclass to run a series of actions bundled
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>
1013 (
<span style=
"color: #00ffff;">defclass
</span> <span style=
"color: #98fb98;">task-component
</span> (standard-component)
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.
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>))
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>))
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>
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
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.
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.
1053 Do not use CACHED-COMPONENT directly, use one its subclasses."</span>))
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>))
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>))
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>))
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>))
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>
1083 <h3><a name=
"sec14" id=
"sec14"></a>
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>
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>
1090 <h4><a name=
"sec15" id=
"sec15"></a>
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>
1099 (
<span style=
"color: #00ffff;">defmacro
</span> <span style=
"color: #87cefa;">call
</span> (component-type
<span style=
"color: #98fb98;">&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.
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.
1110 This macro assumes that the lexcial variable UCW:SELF is bound to
1111 the calling component."</span>)
1113 (answer VAL)
<span style=
"color: #ff7f24;">;
</span><span style=
"color: #ff7f24;">answer parent component ONLY IN ACTIONS
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
1118 (jump COMPONENT-NAME
<span style=
"color: #98fb98;">&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)
1124 <p><code>(call COMPONENT-NAME
&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>
1129 <h4><a name=
"sec16" id=
"sec16"></a>
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>
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))
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
"hmm, why is
1146 this not working ... where did that come from in the
1147 macroexpansion!
").
</p>
1150 <h4><a name=
"sec17" id=
"sec17"></a>
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
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>
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)
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-
>bytes (open
1175 <span style=
"color: #b0c4de;">:element-type
</span> 'unsigned-byte)))))
1180 <h3><a name=
"sec18" id=
"sec18"></a>
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>
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.
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>))
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
1202 These methods may modify context as they wish since they'r
1203 matched, request will be closed after this method is run."</span>))
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.
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>))
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)
1223 <h4><a name=
"sec19" id=
"sec19"></a>
1224 Simple Dispatcher
</h4>
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)
1231 Unlike all other UCW dispatchers a simple-dispatcher must not use
1232 CALL, and must perform the rendering directly within the handler."</span>)
1237 <h3><a name=
"sec20" id=
"sec20"></a>
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>
1243 (
<span style=
"color: #00ffff;">defun
</span> <span style=
"color: #87cefa;">create-server
</span> (
<span style=
"color: #98fb98;">&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*)
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*.
1254 BACKEND is a list of (BACKEND-TYPE &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
1262 APPLICATIONS is a list of defined applications to be loaded into the
1265 Logs are generated in verbosity defined by LOG-LEVEL and directed to
1266 LOG-ROOT-DIRECTORY if defined."</span>
1268 server)
<span style=
"color: #ff7f24;">;
</span><span style=
"color: #ff7f24;">return server, naturally
1272 <h3><a name=
"sec21" id=
"sec21"></a>
1275 <h4><a name=
"sec22" id=
"sec22"></a>
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>
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))
1289 <h2><a name=
"sec23" id=
"sec23"></a>
1292 <h3><a name=
"sec24" id=
"sec24"></a>
1293 Getting dojo to load
</h3>
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>
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>))
1308 <h3><a name=
"sec25" id=
"sec25"></a>
1309 Specials Bound During Rendering
</h3>
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>
1316 <h3><a name=
"sec26" id=
"sec26"></a>
1317 Printing to the yaclml stream
</h3>
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>
1326 <!-- Page published by Emacs Muse ends here -->
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>
1334 <a href=
"http://www.anybrowser.org/campaign/"><img
1335 src=
"img/buttons/w3c_ab.png" alt=
"[ Viewable With Any Browser
1338 <a href=
"http://www.debian.org/"><img
1339 src=
"img/buttons/debian.png" alt=
"[ Powered by Debian ]" /></a>
1341 <a href=
"http://hcoop.net/">
1342 <img src=
"img/buttons/hcoop.png"
1343 alt=
"[ Hosted by HCoop]" />
1346 <a href=
"http://www.fsf.org/register_form?referrer=114">
1347 <img src=
"img/buttons/fsf_member.png"
1348 alt=
"[ FSF Associate Member ]" />
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
1358 <p class=
"cke-timestamp">Last Modified: