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 href=
"http://feeds.unknownlamer.org/rss/site-updates"
11 rel=
"alternate" type=
"application/rss+xml" title=
"Updates Feed" />
13 <link rel=
"stylesheet" href=
"default.css" />
16 <h1>Roadmap to UCW Codebase
</h1>
17 <div class=
"contents">
20 <a href=
"#sec1">Abstract
</a>
23 <a href=
"#sec2">Roadmap
</a>
28 <a href=
"#sec3">Applications
</a>
33 <a href=
"#sec4">Cookie
</a>
36 <a href=
"#sec5">L10n
</a>
39 <a href=
"#sec6">Secure
</a>
44 <a href=
"#sec7">Components
</a>
49 <a href=
"#sec8">Windows
</a>
52 <a href=
"#sec9">Containers
</a>
55 <a href=
"#sec10">Dialogs
</a>
58 <a href=
"#sec11">Forms
</a>
61 <a href=
"#sec12">Templates
</a>
64 <a href=
"#sec13">Utility Mixin Components
</a>
69 <a href=
"#sec14">Control Flow
</a>
74 <a href=
"#sec15">Calling
</a>
77 <a href=
"#sec16">Actions
</a>
80 <a href=
"#sec17">Entry Points
</a>
85 <a href=
"#sec18">Dispatching
</a>
90 <a href=
"#sec19">Simple Dispatcher
</a>
95 <a href=
"#sec20">Server
</a>
98 <a href=
"#sec21">Debugging
</a>
103 <a href=
"#sec22">Inspector
</a>
110 <a href=
"#sec23">Tips
</a>
115 <a href=
"#sec24">Getting dojo to load
</a>
118 <a href=
"#sec25">Specials Bound During Rendering
</a>
121 <a href=
"#sec26">Printing to the yaclml stream
</a>
129 <!-- Page published by Emacs Muse begins here --><h2><a name=
"sec1" id=
"sec1"></a>
132 <p><a href=
"http://common-lisp.net/project/ucw/">UnCommon Web
</a> is a very powerful and mature web framework for Common
133 Lisp, but is a bit difficult to learn. It is documented
134 extensively
—in the form of docstrings. These are extremely helpful
135 once you've figured out the rough structure of UCW, but they are of no
136 help when first learning unless you just read most of the source. I
137 ended up having to do that, and after some urging along by folks in
138 <code>#ucw
</code> I decided to clean up my planner notes and publish them for
139 public consumption.
</p>
141 <p>The roadmap is presented with major sections ordered in a logical
142 order for learning the framework. The sections are ordered internally
143 in order of most immediately useful to least, but it may be worth
144 hopping between major sections before reading all of the details. I
145 have used abridged class definitions and docstrings with occasional
146 commentary to clarify things.
</p>
149 <h2><a name=
"sec2" id=
"sec2"></a>
152 <h3><a name=
"sec3" id=
"sec3"></a>
155 <p class=
"first">Applications are a bundle of entry points. The base class is,
156 naturally,
<code>standard-application
</code>, but you should instead derive your
157 application class from
<code>modular-application
</code> and any standard or custom
158 application mixins you find useful.
</p>
160 <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>
163 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">standard-application
</span> (application)
164 ((url-prefix
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:url-prefix
</span>
165 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A string specifying the
166 start (prefix) of all the urls this app should handle.
168 This value is used by the standard-server to decide what app a
169 particular request is aimed at and for generating links to
170 actions within the app. "</span>)
171 (www-roots
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:www-roots
</span>
172 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A list of directories (pathname
173 specifiers) or cons-cell (URL-subdir . pathname) to use when looking for static files."</span>)
174 (dispatchers
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:dispatchers
</span>
175 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A list of request
176 dispatchers. The user supplied list of dispatchers is extended
177 with other dispatchers that are required for UCW to function
178 properly (action-dispatcher, a parenscript-dispatcher, etc). If
179 you want full control over the active dispatchers use the (setf
180 application.dispatchers) accessor or, if you want control over
181 the order of the dispathcers, (slot-value instance
182 'dispatchers)."</span>))
183 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The default UCW application class."</span>))
186 <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>
189 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">modular-application-mixin
</span> ()
191 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Superclass for all application mixins."</span>))
193 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">modular-application
</span> (standard-application modular-application-mixin)
197 <h4><a name=
"sec4" id=
"sec4"></a>
200 <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>
203 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">cookie-session-application-module
</span> (modular-application-mixin)
204 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Class for applications which use cookies for sesion tracking.
206 Cookie session applications work exactly like
207 standard-applications except that when the session is not found
208 using the standard mechanisms the id is looked for in a cookie."</span>))
211 <p>This is the most useful of the application components. It makes your
212 application urls readable by stashing the session id into a cookie
213 rather than as a set of long and ugly GET parameters.
</p>
216 <h4><a name=
"sec5" id=
"sec5"></a>
219 <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>
222 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">l10n-application-module
</span> (modular-application-mixin)
223 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Application class which can handle l10n requests."</span>))
227 <h4><a name=
"sec6" id=
"sec6"></a>
230 <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>
233 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">secure-application-module
</span> (modular-application-mixin)
234 (
<span class=
"emacs-face-builtin">:documentation
</span>
235 <span class=
"emacs-face-string">"Mixin class for applications which require authorized access.
236 Concrete application must specialize the following methods:
237 APPLICATION-FIND-USER (APPLICATION USERNAME)
238 APPLICATION-CHECK-PASSWORD (APPLICATION USER PASSWORD)
239 APPLICATION-AUTHORIZE-CALLZE-CALL (APPLICATION USER FROM-COMPONENT TO-COMPONENT)."</span>))
244 <h3><a name=
"sec7" id=
"sec7"></a>
247 <p class=
"first">A component is a special class that handles the complexities of
248 continuation suspension and such for you. New components are derived
249 from the existing ones by using
<code>defcomponent
</code> instead of
<code>defclass
</code>. This
250 adds a few extra slot and class options, and ensures that the proper
251 metaclass is set.
</p>
253 <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>
256 (
<span class=
"emacs-face-keyword">defmacro
</span> <span class=
"emacs-face-function-name">defcomponent
</span> (name supers slots
<span class=
"emacs-face-type">&rest
</span> options)
257 <span class=
"emacs-face-doc">"Macro for defining a component class.
259 This macro is used to create component classes and provides
260 options for easily creating the methods which often accompany a
261 component definition.
263 NAME, SUPERS and SLOTS as treated as per defclass. The following
264 extra options are allowed:
266 (:ENTRY-POINT url (&key application class)) - Define an
267 entry-point on the url URL which simply calls an instance of
268 this component. Any request parameters passed to the entry-point
269 are used to initialize the slots in the component. This option
270 may appear multiple times.
272 (:DEFAULT-BACKTRACK function-designator) - Unless the slots
273 already have a :backtrack option FUNCTION-DESIGNATOR is
274 added. As with the 'regular' :backtrack options if you pass T
275 here it is assumed to mean #'IDENTITY.
277 (:RENDER (&optional COMPONENT) &body BODY) - Generate a render
278 method specialized to COMPONENT. COMPONENT may be a symbol, in
279 which case the method will be specialized on the componnet
280 class. If COMPONNET is omited the component is bound to a
281 variable with the same name as the class.
283 (:ACTION &optional NAME) - Generate a defaction form named
284 NAME (which defaults to the name of the component) which simply
285 CALL's this component class passing all the arguments passed to
286 the action as initargs."</span>)
288 <span class=
"emacs-face-comment-delimiter">;;;
</span><span class=
"emacs-face-comment">Extra Slot Options
289 </span><span class=
"emacs-face-string">"Other than the initargs for standard slots the following
290 options can be passed to component slots:
292 :backtrack [ T | NIL | FUNCTION-NAME ] - Specify that this slot
293 should be backtracked (or not if NIL is passed as the value). If
294 the value is neither T nor NIL then it must be a function which
295 will be used as the copyer.
297 :component [ TYPE | ( TYPE &rest INITARGS ) ] - Specify that this
298 slot is actually a nested component of type TYPE. When instances
299 of the class are created this slot will be set to an instance of
300 type TYPE and it's place will be set to this slot. If a list is
301 passed to :component then TYPE (which isn't evaluated) will be
302 passed as the first argument to make-instance. The INITARGS will
303 be eval'd and apply'd to make-instance. The result of this call
304 to make-instance will be used as the effective component
308 <h4><a name=
"sec8" id=
"sec8"></a>
311 <p class=
"first">A window-component represents a top level browser window, naturally.
</p>
313 <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>
316 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">window-component
</span> ()
319 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">simple-window-component
</span> (window-component)
322 (javascript
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"List of javascript includes.
324 Each element must be a list whose first value is either the
327 (:SRC url) - writes <script src=\"URL\
"></script> tag.
328 (:JS form) - equivalent to (:SCRIPT (js:js* form))
329 (:SCRIPT string) - write <script>STRING</script>.
331 The elements will be rendered in order."</span>)
335 <p><code>window-component
</code> could be useful for doing things like dumping binary
336 data to the user, or just deriving your own funky top level window
339 <p><code>simple-window-component
</code> is the easiest for displaying standard
340 webpage. It provides a wrapping method on render that displays the
341 html boilerplate based on your component slot values which is what one
342 wants most of the time. The initargs to
<code>simple-window-component
</code> have
343 the same names as the slots.
</p>
347 <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>
349 <p>There is a generic status bar interface. Messages severity is one of
350 <code>(:error :warn :info)
</code>. Note that the default status bar render method
351 just shows a div with status messages. A derivative could be defined
352 to insert messages into the browser status bar.
</p>
355 (defcomponent status-bar ()
356 ((messages
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"An ALIST of the messages to
357 show. Each element is a cons of the form (SEVERITY .
358 MESSAGE). SEVERITY is one of :ERROR, :WARN, :INFO and MESSAGE is
359 a string which will be html-escaped."</span>)
361 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Stateless status bar to display messages."</span>))
363 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">add-message
</span> (status-bar msg
<span class=
"emacs-face-type">&key
</span> severity
<span class=
"emacs-face-type">&allow-other-keys
</span>)
364 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Add the message text MSG to STATUS-BAR with
365 severity SEVERITY."</span>))
369 (defcomponent status-bar-mixin ()
370 ((status-bar
<span class=
"emacs-face-builtin">:accessor
</span> status-bar
371 <span class=
"emacs-face-builtin">:initarg
</span> status-bar
372 <span class=
"emacs-face-builtin">:component
</span> (status-bar))))
374 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">show-status-bar
</span> ((win status-bar-mixin))
375 (render (status-bar win)))
377 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">show-message
</span> (msg
<span class=
"emacs-face-type">&key
</span> severity
<span class=
"emacs-face-type">&allow-other-keys
</span>)
378 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Show a message in the status bar. Only works if
379 current window is a status-bar-mixin"</span>))
385 <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>
388 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">redirect-component
</span> ()
389 ((target
<span class=
"emacs-face-builtin">:accessor
</span> target
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:target
</span>))
390 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class)
391 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Send a client redirect.
393 This component, which must be used as a window-component,
394 redirects the client to the url specified in the target slot. A
395 302 (as opposed to 303) response code is sent to ensure
396 compatability with older browsers.
398 The redirect component never answers."</span>))
401 <p>There is also a
<code>meta-refresh
</code> procedure.
</p>
404 (defun/cc meta-refresh ()
405 <span class=
"emacs-face-string">"Cause a meta-refresh (a freshly got (GET) url) at this point.
406 This is useful in order to have a GET url after a form POST's
407 actions have completed running. The user can then refresh to his
408 heart's content."</span>)
413 <h4><a name=
"sec9" id=
"sec9"></a>
416 <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>
419 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">container
</span> ()
421 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class)
422 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Allow multiple components to share the same place.
424 The container component serves to manage a set of components.
425 It does not provide any render impementation, which is the
426 resposibility of the subclasses (e.g. switching-container or
429 Each contained component has a \"key\
" associated with it which
430 is used to retrieve a particular component. Keys are compared with
433 The :contents inintarg, if provided, must be either a list of (key .
434 component) or a list of components. In the latter case it will
435 be converted into (component . component) form."</span>))
441 <li><code>child-components
</code></li>
442 <li><code>find-component CONTAINER KEY
</code></li>
443 <li><code>remove-component
</code></li>
444 <li><code>(setf find-component CONTAINER KEY) COMPONENT
</code> -
>
445 <code>add-component CONTAINER COMPONENT KEY
</code></li>
449 <h5>Switching Container
</h5>
451 <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>
454 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">switching-container
</span> ...
455 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A simple renderable container component.
457 This component is like the regular CONTAINER but serves to manage a set
458 of components which share the same place in the UI. Therefore it provides
459 an implementation of RENDER which simply renders its current component.
461 The switching-container component class is generally used as the super
462 class for navigatation components and tabbed-pane like
463 components."</span>))
466 <p>Subclass and
<code>(defmethod render :around ...)
</code> to render navigation using
467 <code>(call-next-method)
</code> to render the selected component.
</p>
472 <li><code>container.current-component COMPONENT
</code></li>
473 <li><code>(setf container.current-component CONTAINER) COMPONENT
</code></li>
480 <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>
483 (defcomponent tabbed-pane (switching-container)
484 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Component for providing the user with a standard \"tabbed pane\
" GUI widget."</span>))
487 <p>Provides a generic tabbed pane that renders a nested div split into a
488 naviation and content box. The navigation box is a set of styled divs
489 containing the navigation links.
</p>
493 <h4><a name=
"sec10" id=
"sec10"></a>
496 <p class=
"first">A few convenience dialogs are provided for grabbing data from the
501 <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>
504 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">login
</span> ()
505 ((username) (password) (message))
506 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Generic login (input username and password) component.
508 This component, which must be embedded in another component,
509 presents the user with a simple two fielded login form.
511 When the user attempts a login the action try-login is called,
512 try-login calls the generic function check-credentials passing it
513 the login component. If check-credentials returns true then the
514 login-successful action is called, otherwise the message slot of
515 the login component is set (to a generic \"bad username\
"
518 The default implementaion of login-successful simply answers t,
519 no default implementation of check-credentials is
520 provided. Developers should use sub-classes of login for which
521 all the required methods have been definined."</span>)
522 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class))
526 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">check-credentials
</span> (login)
527 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Returns T if LOGIN is valid."</span>))
529 (defaction login-successful ((l login))
533 <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>
536 (defcomponent user-login (simple-window-component status-bar-mixin)
537 ((username string-field) (password password-field)))
540 <p>Used by
<code>secure-application-module
</code> to provide a user login. Relevant
541 protocol details follow.
</p>
544 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">check-credentials
</span> ((self user-login))
545 (
<span class=
"emacs-face-keyword">let*
</span> ((username (value (username self)))
546 (password (value (password self)))
547 (user (find-application-user username)))
548 (
<span class=
"emacs-face-keyword">when
</span> (and user (check-user-password user password))
551 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">application-find-user
</span> (application username)
552 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Find USER by USERNAME for APPLICATION."</span>))
558 <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>
561 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">error-message
</span> (simple-window-component)
562 ((message
<span class=
"emacs-face-builtin">:accessor
</span> message
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:message
</span> <span class=
"emacs-face-builtin">:initform
</span> <span class=
"emacs-face-string">"ERROR [no message specified]"</span>))
563 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Generic component for showing server side
564 error messages."</span>)
565 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class))
567 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">error-component
</span> (error-message)
568 ((condition
<span class=
"emacs-face-builtin">:accessor
</span> error.condition
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:condition
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)
569 (backtrace
<span class=
"emacs-face-builtin">:accessor
</span> error.backtrace
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:backtrace
</span>))
570 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Generic component for showing server side
571 error conditions. Unlike ERROR-MESSAGE this component also
572 attempts to display a backtrace."</span>)
573 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class))
579 <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>
582 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">info-message
</span> ()
583 ((message
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:message
</span> <span class=
"emacs-face-builtin">:accessor
</span> message)
584 (ok-text
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:ok-text
</span> <span class=
"emacs-face-builtin">:accessor
</span> ok-text
<span class=
"emacs-face-builtin">:initform
</span> <span class=
"emacs-face-string">"Ok."</span>))
585 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Component for showing a message to the user.
587 If the OK-TEXT slot is non-NIL component will use that as the
588 text for a link which, when clicked, causes the component to
589 answer. It follows that if OK-TEXT is NIL this component will
590 never answer."</span>)
591 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class))
595 <h5>option-dialog
</h5>
597 <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>
600 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">option-dialog
</span> (template-component)
601 ((message) (options) (confirm))
602 (
<span class=
"emacs-face-builtin">:default-initargs
</span> <span class=
"emacs-face-builtin">:template-name
</span> <span class=
"emacs-face-string">"ucw/option-dialog.tal"</span>)
603 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Component for querying the user.
605 The value of the slot MESSAGE is used as a general heading.
607 The OPTIONS slot must be an alist of (VALUE . LABEL). LABEL (a
608 string) will be used as the text of a link which, when clikced,
611 If the CONFIRM slot is T the user will be presented with a second
612 OPTION-DIALOG asking the user if they are sure they want to
613 submit that value."</span>)
614 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class))
617 <p>A macro to present an option dialog is provided.
</p>
620 (
<span class=
"emacs-face-keyword">defmacro
</span> <span class=
"emacs-face-function-name">option-dialog
</span> ((message-spec
<span class=
"emacs-face-type">&rest
</span> message-args)
<span class=
"emacs-face-type">&body
</span> options)
624 <p><code>message-spec
</code> is passed to
<code>format
</code> if
<code>message-args
</code> are supplied, and
625 used as a string literal otherwise. This does not provide a way to set
626 the confirm property which makes the macro not so generally useful.
</p>
630 <h4><a name=
"sec11" id=
"sec11"></a>
633 <p class=
"first">Reasonably useful forms library that integrates easily with TAL.
</p>
635 <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>
638 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">form-field
</span> ()
639 ((validators
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"List of validators which will be
640 applied to this field."</span>)
641 (initially-validate
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"When non-NIL the
642 validators will be run as soon as the page
643 is rendered."</span>)))
645 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">value
</span> (form-field)
646 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The lispish translated value that represents the form-field."</span>))
648 (
<span class=
"emacs-face-keyword">defgeneric
</span> (
<span class=
"emacs-face-function-name">setf value)
</span> (new-value form-field)
649 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Set the value of a form-field with translation to client."</span>))
651 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">generic-html-input
</span> (form-field html-element)
652 ((client-value
<span class=
"emacs-face-builtin">:accessor
</span> client-value
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:client-value
</span>
653 <span class=
"emacs-face-builtin">:initform
</span> <span class=
"emacs-face-string">""</span>
654 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The string the client submitted along with this field."</span>)
655 (name
<span class=
"emacs-face-builtin">:accessor
</span> name
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:name
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)
656 (accesskey
<span class=
"emacs-face-builtin">:accessor
</span> accesskey
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:accesskey
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)
657 (tooltip
<span class=
"emacs-face-builtin">:accessor
</span> tooltip
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:tooltip
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)
658 (tabindex
<span class=
"emacs-face-builtin">:accessor
</span> tabindex
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:tabindex
</span> <span class=
"emacs-face-builtin">:initform
</span> nil))
659 (
<span class=
"emacs-face-builtin">:default-initargs
</span> <span class=
"emacs-face-builtin">:dom-id
</span> (js:gen-js-name-string
<span class=
"emacs-face-builtin">:prefix
</span> <span class=
"emacs-face-string">"_ucw_"</span>)))
662 <p>Fields are rendered into the extended
<code><ucw:input
</code> yaclml tag which
663 supports a few fancy features. The
<code>:accessor
</code> for all form elements is
664 set to
<code>(client-value FIELD)
</code>, and you should use
<code>value
</code> to access the
665 Lisp value associated with it.
</p>
668 (deftag-macro
<ucw:input (
<span class=
"emacs-face-type">&attribute
</span> accessor action reader writer name id (default nil)
669 <span class=
"emacs-face-type">&allow-other-attributes
</span> others)
670 <span class=
"emacs-face-string">"Generic INPUT tag replacement.
672 If the ACCESSOR attribute is specified then it must be a PLACE
673 and it's value will be used to fill the input, when the form is
674 submitted it will be set to the new value.
676 If ACTION is specefied then when the form is submitted via this
677 input type=\"submit\
" tag the form will be eval'd. when the
678 submit (or image) is clicked. DEFAULT means that the ACTION
679 provided for this input tag will be the default action of the
680 form when pressing enter in a form field. If more then one, then
681 the latest wins."</span>)
684 <p>Validation of form fields are supported by adding to the validators
688 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">validator
</span> ()
689 ((message
<span class=
"emacs-face-builtin">:accessor
</span> message
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:message
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)))
691 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">validate
</span> (field validator)
692 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Validate a form-field with a validator."</span>))
694 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">javascript-check
</span> (field validator)
695 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Generate javascript code for checking FIELD against VALIDATOR.
697 This is the convenience entry point to generate-javascript-check,
698 methods defined on this generic funcition should return a list of
699 javascript code (as per parenscript) which tests against the
700 javascript variable value."</span>))
702 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">javascript-invalid-handler
</span> (field validator)
703 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The javascript code body for when a field is invalid."</span>))
705 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">javascript-valid-handler
</span> (field validator)
706 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Generate the javascript body for when a field is valid."</span>))
709 <h5>Standard Form Fields
</h5>
712 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">string-field
</span> (generic-html-input)
713 ((input-size) (maxlength)))
715 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">password-field
</span> (string-field))
716 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">number-field
</span> (string-field))
717 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">integer-field
</span> (number-field))
719 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">in-field-string-field
</span> (string-field)
720 ((in-field-label
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"This slot, if non-NIL, will be
721 used as an initial field label. An initial
722 field label is a block of text which is placed
723 inside the input element and removed as soon
724 as the user edits the field. Obviously this
725 field is overidden by an initial :client-value
728 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">textarea-field
</span> (generic-html-input)
731 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">date-field
</span> (form-field widget-component)
732 ((year) (month) (day)))
734 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">dmy-date-field
</span> (date-field)
735 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Date fields which orders the inputs day/month/year"</span>))
736 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">mdy-date-field
</span> (date-field))
738 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">select-field
</span> (generic-html-input)
739 ((data-set
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The values this select chooses
741 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Form field used for selecting one value from a
742 list of available options."</span>))
744 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">render-value
</span> (select-field value)
745 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"This function will be passed each value in the field's
746 data-set and must produce the body of the corresponding
747 <ucw:option tag."</span>))
749 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">mapping-select-field
</span> (select-field)
750 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Class used when we want to chose the values of
751 a certain mapping based on the keys. We render the keys in the
752 select and return the corresponding value from the VALUE
755 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">hash-table-select-field
</span> (mapping-select-field))
756 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">alist-select-field
</span> (mapping-select-field))
757 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">plist-select-field
</span> (mapping-select-field))
759 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">radio-group
</span> (generic-html-input)
762 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">radio-button
</span> (generic-html-input)
764 (group
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The RADIO-GROUP this button is a part
766 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A widget representing a single radio
767 button. Should be used in conjunction with a RADIO-GROUP."</span>))
769 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">add-value
</span> ((group radio-group) value)
770 <span class=
"emacs-face-string">"Adds radio-button with value to group"</span>)
772 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">checkbox-field
</span> (generic-html-input))
773 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">file-upload-field
</span> (generic-html-input))
774 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">submit-button
</span> (generic-html-input)
778 <h5>File Upload Field
</h5>
780 <p>Calling
<code>value
</code> on a
<code>file-upload-field
</code> returns a mime encoded body
781 part.
<code>(mime-part-body (value FIELD))
</code> will return a
<strong>binary stream
</strong>
782 attached to the contents of the file. The
<code>Content-Type
</code> header should
783 be set to the MIME type of the file being uploaded.
</p>
786 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">mime-part-headers
</span> (mime-part)
787 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Returns an alist of the headers of MIME-PART.
789 The alist must be of the form (NAME . VALUE) where both NAME and
790 VALUE are strings."</span>))
792 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">mime-part-body
</span> (mime-part)
793 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Returns the body of MIME-PART."</span>))
798 <h5>Standard Validators
</h5>
801 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">not-empty-validator
</span> (validator))
803 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">value-validator
</span> (validator)
804 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Validators that should only be applied if there is a value.
805 That is, they always succeed on nil."</span>))
807 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">length-validator
</span> (value-validator)
808 ((min-length
<span class=
"emacs-face-builtin">:accessor
</span> min-length
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:min-length
</span>
809 <span class=
"emacs-face-builtin">:initform
</span> nil)
810 (max-length
<span class=
"emacs-face-builtin">:accessor
</span> max-length
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:max-length
</span>
811 <span class=
"emacs-face-builtin">:initform
</span> nil)))
813 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">string=-validator
</span> (validator)
814 ((other-field
<span class=
"emacs-face-builtin">:accessor
</span> other-field
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:other-field
</span>))
815 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Ensures that a field is string= to another one."</span>))
817 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">regex-validator
</span> (value-validator)
818 ((regex
<span class=
"emacs-face-builtin">:accessor
</span> regex
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:regex
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)))
820 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">e-mail-address-validator
</span> (regex-validator))
822 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">phone-number-validator
</span> (regex-validator))
824 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">is-a-number-validator
</span> (value-validator))
825 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">is-an-integer-validator
</span> (is-a-number-validator))
827 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">number-range-validator
</span> (is-a-number-validator)
828 ((min-value
<span class=
"emacs-face-builtin">:accessor
</span> min-value
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:min-value
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)
829 (max-value
<span class=
"emacs-face-builtin">:accessor
</span> max-value
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:max-value
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)))
833 <h5>Simple Form Helper
</h5>
835 <p>UCW provides a helper class for developing forms. Subclass and add the
836 elements you wish to include in the form. A
<code>:wrapping
</code> method renders
837 the form boilerplate and then calls your
<code>render
</code>.
</p>
840 (defcomponent simple-form (html-element)
841 ((submit-method
<span class=
"emacs-face-builtin">:accessor
</span> submit-method
842 <span class=
"emacs-face-builtin">:initform
</span> <span class=
"emacs-face-string">"post"</span>
843 <span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:submit-method
</span>)
844 (dom-id
<span class=
"emacs-face-builtin">:accessor
</span> dom-id
845 <span class=
"emacs-face-builtin">:initform
</span> (js:gen-js-name-string
<span class=
"emacs-face-builtin">:prefix
</span> <span class=
"emacs-face-string">"_ucw_simple_form_"</span>)
846 <span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:dom-id
</span>))
847 (
<span class=
"emacs-face-builtin">:default-initargs
</span> <span class=
"emacs-face-builtin">:dom-id
</span> <span class=
"emacs-face-string">"ucw-simple-form"</span>))
852 <h4><a name=
"sec12" id=
"sec12"></a>
855 <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>
857 <p>Infrastructure for loading TAL templates as a view of a component.
</p>
860 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">template-component
</span> (component))
861 (defcomponent simple-template-component (template-component)
862 ((environment
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:environment
</span> <span class=
"emacs-face-builtin">:initform
</span> nil)))
864 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">template-component-environment
</span> (component)
865 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Create the TAL environment for rendering COMPONENT's template.
867 Methods defined on this generic function must return a TAL
868 environment: a list of TAL binding sets (see the documentation
869 for YACLML:MAKE-STANDARD-ENVIRONMENT for details on TAL
870 environments.)"</span>)
871 (
<span class=
"emacs-face-builtin">:method-combination
</span> nconc))
873 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">template-component-environment
</span> nconc ((component template-component))
874 <span class=
"emacs-face-string">"Create the basic TAL environment.
876 Binds the symbol ucw:component to the component object itself,
877 also puts the object COMPONENT on the environment (after the
878 binding of ucw:component) so that slots are, by default,
880 (make-standard-environment `((component . ,component)) component))
882 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">render
</span> ((component template-component))
883 <span class=
"emacs-face-string">"Render a template based component.
885 Calls the component's template. The name of the template is the
886 value returned by the generic function
887 template-component.template-name, the template will be rendered
888 in the environment returned by the generic function
889 template-component-environment."</span>
890 (render-template *context*
891 (template-component.template-name component)
892 (template-component-environment component)))
896 <p>Subclass and override methods.
<code>simple-template-component
</code> only provides
897 the ability to set environment variables in initarg. Subclass to
898 provide automagic template file name generation and such.
</p>
901 <h4><a name=
"sec13" id=
"sec13"></a>
902 Utility Mixin Components
</h4>
906 <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>
909 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">range-view
</span> (template-component)
910 (
<span class=
"emacs-face-builtin">:default-initargs
</span> <span class=
"emacs-face-builtin">:template-name
</span> <span class=
"emacs-face-string">"ucw/range-view.tal"</span>)
911 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Component for showing the user a set of data one \"window\
" at a time.
913 The data set is presented one \"window\
" at a time with links to
914 the the first, previous, next and last window. Each window shows
915 at most WINDOW-SIZE elements of the data. The data is passed to
916 the range-view at instance creation time via the :DATA initarg.
918 The generic function RENDER-RANGE-VIEW-ITEM is used to render
921 In order to change the rendering of the single elements of a
922 range view developer's should create a sub class of RANGE-VIEW
923 and define their RENDER-RANGE-VIEW-ITEM methods on that."</span>)
924 (
<span class=
"emacs-face-builtin">:metaclass
</span> standard-component-class))
928 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">render-range-view-item
</span> (range-view item)
929 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Render a single element of a range-view."</span>)
930 (
<span class=
"emacs-face-builtin">:method
</span> ((range-view range-view) (item t))
931 <span class=
"emacs-face-string">"Standard implementation of RENDER-RANGE-VIEW-ITEM. Simply
932 applies ITEM to princ (via <:as-html)."</span>
933 (
<span class=
"emacs-face-keyword">declare
</span> (ignore range-view))
934 (
<:as-html item)))
940 <p>Mixin with existing component to wrap in a div or span. This is handy
941 for defining lightweight widgets embedded within other components.
</p>
943 <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>
946 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">html-element
</span> (component)
952 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"An HTML element.
954 HTML elements control aspects that are relevant to almost all tags.
956 Firstly they provide a place to store the class, id, and style of the
957 component. The specific render methods of the components themselves
958 must pass these values to whatever code is used to render the actual
961 Secondly, they allow javascript event handlers to be registered for a
962 tag. The events slot can be filled with a list of lists in the form
964 (event parenscript-statement*)
966 For example (\"onclick\
" (alert \"You clicked!\
") (return nil)). If
967 the element has a dom-id, these event handlers are automatically
971 <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>
974 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">widget-component
</span> (html-element)
976 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A widget which should be wrapped in a <div>."</span>))
978 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">inline-widget-component
</span> (html-element)
980 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A widget which should be wrapped in <span> and not <div>"</span>))
982 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">render
</span> <span class=
"emacs-face-builtin">:wrap-around
</span> ((widget widget-component)))
983 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">render
</span> <span class=
"emacs-face-builtin">:wrap-around
</span> ((widget inline-widget-component)))
987 <h5>Transactions
</h5>
989 <p>A mixin to provide transactions.
<code>(open-transaction component)
</code> and
990 <code>(close-transaction component)
</code> open and closed nested
991 transactions. After a transaction has been closed an attempt to
992 backtrack into a step inside the transaction will result in jumping up
993 one level of transactions (or out of the transaction entirely if at
994 the top level). This ensures that the transaction is only run once,
997 <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>
1000 (defcomponent transaction-mixin ()
1003 (defmethod/cc open-transaction ((comp transaction-mixin)))
1004 (defmethod/cc close-transaction ((comp transaction-mixin)))
1010 <p><code>(defaction start ...)
</code> on subclass to run a series of actions bundled
1013 <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>
1016 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">task-component
</span> (standard-component)
1018 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A controller for a single task or operation to
1019 be performed by the user.
1021 A task component's START action is called as soon as the
1022 component is instantiated. Task components do not have their own
1023 RENDER method, in fact they have no graphical representation but
1024 serve only to order a sequence of other components."</span>))
1026 (defgeneric/cc start (task)
1027 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"action which gets called automatically when
1028 task-component is active. Use defaction to define your own
1029 \"start\
" action"</span>))
1035 <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>
1038 (defcomponent cached-component ()
1039 ((cached-output
<span class=
"emacs-face-builtin">:accessor
</span> cached-output
<span class=
"emacs-face-builtin">:initform
</span> nil
1040 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"A string holding the output to
1041 use for this component. This string will be
1042 written directly to the html stream and is
1043 changed by the REFRESH-COMPONENT-OUTPUT
1045 (timeout
<span class=
"emacs-face-builtin">:accessor
</span> timeout
<span class=
"emacs-face-builtin">:initarg
</span> <span class=
"emacs-face-builtin">:timeout
</span>
1046 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"An value specifying how often this
1047 component needs to be refreshed. The exact
1048 interpretation of the value depends on the type of
1049 caching used class."</span>))
1050 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Component which caches its output.
1052 The component caching API is built around the generic functions
1053 COMPONENT-DIRTY-P and REFRESH-COMPONENT-OUTPUT and a method on
1054 RENDER, see the respective docstrings for more details.
1056 Do not use CACHED-COMPONENT directly, use one its subclasses."</span>))
1058 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">component-dirty-p
</span> (component)
1059 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Returns T is COMPONENT's cache is invalid."</span>))
1061 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">update-cache
</span> (component)
1062 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Update COMPONENT's cache variables after a refresh."</span>))
1064 (defcomponent timeout-cache-component (cached-component)
1065 ((last-refresh
<span class=
"emacs-face-builtin">:accessor
</span> last-refresh
<span class=
"emacs-face-builtin">:initform
</span> nil
1066 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"The time, exrpessed as a
1067 universal time, when the component was last rendered."</span>))
1068 (
<span class=
"emacs-face-builtin">:default-initargs
</span>
1069 <span class=
"emacs-face-builtin">:timeout
</span> (*
30 60 60))
1070 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Render the component at most every TIMEOUT seconds."</span>))
1072 (defcomponent num-hits-cache-component (cached-component)
1073 ((hits-since-refresh
<span class=
"emacs-face-builtin">:accessor
</span> hits-since-refresh
1074 <span class=
"emacs-face-builtin">:initform
</span> nil
1075 <span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Number of views since last refresh."</span>))
1076 (
<span class=
"emacs-face-builtin">:default-initargs
</span> <span class=
"emacs-face-builtin">:timeout
</span> 10)
1077 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Render the component every TIMEOUT views."</span>))
1080 <p>Subclass and override
<code>component-dirty-p
</code> to do something useful
1081 (e.g. flip mark bit when object being presented changes).
</p>
1086 <h3><a name=
"sec14" id=
"sec14"></a>
1089 <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>
1091 <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>
1093 <h4><a name=
"sec15" id=
"sec15"></a>
1096 <p class=
"first">Most of what you do in UCW will be calling components so this is a bit
1097 important. Note that calling interrupts the current control flow so if
1098 you want to render a component in place as part of another component
1099 just call
<code>render
</code> on it instead.
</p>
1102 (
<span class=
"emacs-face-keyword">defmacro
</span> <span class=
"emacs-face-function-name">call
</span> (component-type
<span class=
"emacs-face-type">&rest
</span> component-init-args)
1103 <span class=
"emacs-face-doc">"Stop the execution of the current action and pass control to
1104 a freshly created component of type COMPONENT-TYPE.
1106 COMPONENT-INIT-ARGS are passed directly to the underlying
1107 make-instance call. This form will return if and when the call'd
1108 component calls answer, the value returned by this form is
1109 whatever the call'd component passed to answer.
1113 This macro assumes that the lexcial variable UCW:SELF is bound to
1114 the calling component."</span>)
1116 (answer VAL)
<span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">answer parent component ONLY IN ACTIONS
1118 (ok SELF VAL)
<span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">Used to answer a component anywhere and what answer
1119 </span> <span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">expands into
1121 (jump COMPONENT-NAME
<span class=
"emacs-face-type">&REST
</span> ARGS)
<span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">is similar to call, but replaces
1122 </span> <span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">the current component with the new
1123 </span> <span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">one and drops any backtracks (back
1124 </span> <span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">button will no longer work)
1127 <p><code>(call COMPONENT-NAME
&ARGS INIT-ARGS)
</code> calls
<code>COMPONENT-NAME
</code> and returns
1128 the value returned by
<code>(ok SELF RETURN-VALUE)
</code> called from within
1129 <code>COMPONENT-NAME
</code></p>
1132 <h4><a name=
"sec16" id=
"sec16"></a>
1135 <p class=
"first">Actions are methods on components. The first argument
<strong>must
</strong> be a
1136 component for most of UCW to work.
</p>
1139 (defaction NAME (first ...) ...)
1140 <span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">(roughly) expands into
1141 </span>(defmethod/cc NAME (first ...)
1142 (
<span class=
"emacs-face-keyword">let
</span> ((self first))
1146 <p><code>Self
</code> being bound in the current lexical environment is required for
1147 most UCW control flow things to work.
<code>defaction
</code> hides this from you,
1148 and was a big source of confusion for me early on (mostly
"hmm, why is
1149 this not working ... where did that come from in the
1150 macroexpansion!
").
</p>
1153 <h4><a name=
"sec17" id=
"sec17"></a>
1157 (defentry-point url (
<span class=
"emacs-face-builtin">:application
</span> APPLICATION
1158 <span class=
"emacs-face-builtin">:class
</span> DISPATCHER-CLASS)
1159 (PARAM1 ... PARAMN)
<span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">GET / POST vars, bound in body
1163 <p>An entry point is what it sounds like: a static URL matched using the
1164 mater of
<code>DISPATCHER-CLASS
</code> that enters into
<code>APPLICATION
</code> running the
1165 code in
<code>body
</code>. An example from a test program I have written
1166 follows. The entry point allows files to be streamed to user when the
1167 url audio.ucw?file=FOO is used.
</p>
1170 (defentry-point
<span class=
"emacs-face-string">"^(audio.ucw|)$"</span> (
<span class=
"emacs-face-builtin">:application
</span> *golf-test-app*
1171 <span class=
"emacs-face-builtin">:class
</span> regexp-dispatcher)
1173 (call 'audio-file-window
1174 <span class=
"emacs-face-builtin">:audio-file
</span> (make-instance 'audio-file
1175 <span class=
"emacs-face-builtin">:type
</span> <span class=
"emacs-face-builtin">:vorbis
</span>
1176 <span class=
"emacs-face-builtin">:data
</span> (file-
>bytes (open
1178 <span class=
"emacs-face-builtin">:element-type
</span> 'unsigned-byte)))))
1183 <h3><a name=
"sec18" id=
"sec18"></a>
1186 <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>
1189 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">matcher-match
</span> (matcher application context)
1190 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Abstract method for subclasses to implement a
1191 matcher. This method would return multiple-values according to
1192 matcher internal nature.
1194 No methods defined on this function may rebind *context*, nor
1195 change CONTEXT's application. Only if the method matches the
1196 request, it is allowed to modify CONTEXT or APPLICATION, even in
1197 that case methods defined on this function must not modify
1198 CONTEXT's application nor rebind *context*."</span>))
1200 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">handler-handle
</span> (handler application context matcher-result)
1201 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Abstract function for handler classes to
1202 implement in order to handle a request matched by relevant
1205 These methods may modify context as they wish since they'r
1206 matched, request will be closed after this method is run."</span>))
1208 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">dispatch
</span> (dispatcher application context)
1209 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"Entry point into a dispatcher. Must return T
1210 if the context has been handled or NIL if it hasn't.
1212 No methods defined on this function may rebind *context*, nor
1213 change CONTEXT's application. Only if the method returns T is it
1214 allowed to modify CONTEXT or APPLICATION, even in that case
1215 methods defined on this function must not modify CONTEXT's
1216 application nor rebind *context*."</span>))
1220 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">my-matcher
</span> (abstract-matcher) ...)
1221 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">my-handler
</span> (abstract-handler) ...)
1222 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">my-dispatcher
</span> (abstract-dispatcher my-matcher my-handler)
1226 <h4><a name=
"sec19" id=
"sec19"></a>
1227 Simple Dispatcher
</h4>
1230 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-string">"This class of dispatchers avoids all of UCW's
1231 standard call/cc (and therefore frame/backtracking/component)
1234 Unlike all other UCW dispatchers a simple-dispatcher must not use
1235 CALL, and must perform the rendering directly within the handler."</span>)
1240 <h3><a name=
"sec20" id=
"sec20"></a>
1243 <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>
1246 (
<span class=
"emacs-face-keyword">defun
</span> <span class=
"emacs-face-function-name">create-server
</span> (
<span class=
"emacs-face-type">&key
</span>
1247 (backend `(,*ucw-backend-type*
<span class=
"emacs-face-builtin">:host
</span> ,*ucw-backend-host*
1248 <span class=
"emacs-face-builtin">:port
</span> ,*ucw-backend-port*))
1249 (applications *ucw-applications*)
1251 (server-class *ucw-server-class*)
1252 (log-root-directory (truename *ucw-log-root-directory*))
1253 (log-level *ucw-log-level*))
1254 <span class=
"emacs-face-doc">"Creates and returns a UCW server according to SERVER-CLASS, HOST and
1255 PORT. Affects *DEFAULT-SERVER*.
1257 BACKEND is a list of (BACKEND-TYPE &rest INITARGS). BACKEND-TYPE
1258 may be :HTTPD, :MOD-LISP, :ASERVE, :ARANEIDA, an existing
1259 backend, an existing UCW server backend or :DEFAULT in which case
1260 it attempts to return a sane default from the UCW backends loaded
1261 and available, or any other value for which a valid MAKE-BACKEND
1262 method has been defined. INITARGS will be passed, unmodified, to
1265 APPLICATIONS is a list of defined applications to be loaded into the
1268 Logs are generated in verbosity defined by LOG-LEVEL and directed to
1269 LOG-ROOT-DIRECTORY if defined."</span>
1271 server)
<span class=
"emacs-face-comment-delimiter">;
</span><span class=
"emacs-face-comment">return server, naturally
1275 <h3><a name=
"sec21" id=
"sec21"></a>
1278 <h4><a name=
"sec22" id=
"sec22"></a>
1281 <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>
1284 (defaction call-inspector ((component component) datum)
1285 <span class=
"emacs-face-string">"Call an inspector for DATUM on the component COMPONENT."</span>
1286 (call 'ucw-inspector
<span class=
"emacs-face-builtin">:datum
</span> datum))
1292 <h2><a name=
"sec23" id=
"sec23"></a>
1295 <h3><a name=
"sec24" id=
"sec24"></a>
1296 Getting dojo to load
</h3>
1298 <p class=
"first">I had some trouble getting dojo to work properly with UCW. The way
1299 that the
<code>:www-roots
</code> option for an application works is a bit
1300 confusing, and it is unforgiving if you mess the pathname up. A
1301 directory
<strong>must
</strong> have a
<code>/
</code> at the end, and the directory you are serving
1302 must also have the
<code>/
</code> (which is counterintuitive given the behavior of
1303 most unix things that don't want the
<code>/
</code> at the end of the name).
</p>
1306 <span class=
"emacs-face-builtin">:www-roots
</span> (list '(
<span class=
"emacs-face-string">"dojo/"</span> .
1307 #P
<span class=
"emacs-face-string">"/home/clinton/src/ucw/darcs/ucw_dev/wwwroot/dojo/"</span>))
1311 <h3><a name=
"sec25" id=
"sec25"></a>
1312 Specials Bound During Rendering
</h3>
1314 <p class=
"first">The current request context is bound to
<code>ucw:*context*
</code>, and the current
1315 component is bound to
<code>ucw:*current-component*
</code> in the dynamic extent of
1316 <code>render
</code>.
</p>
1319 <h3><a name=
"sec26" id=
"sec26"></a>
1320 Printing to the yaclml stream
</h3>
1322 <p class=
"first">Occasionally it can be useful to do something like write a byte array
1323 as an ascii string to the client. Inside of
<code>render
</code> the variable
1324 <code>yaclml:*yaclml-stream*
</code> is bound to the stream that you can write to if
1325 you wish to have content interspersed with yaclml tags.
</p>
1329 <!-- Page published by Emacs Muse ends here -->
1331 <p class=
"cke-buttons">
1332 <!-- validating badges, any browser, etc -->
1333 <a href=
"http://validator.w3.org/check/referer"><img
1334 src=
"http://www.w3.org/Icons/valid-xhtml10"
1335 alt=
"Valid XHTML 1.0!" /></a>
1337 <a href=
"http://www.anybrowser.org/campaign/"><img
1338 src=
"img/buttons/w3c_ab.png" alt=
"[ Viewable With Any Browser
1341 <a href=
"http://www.debian.org/"><img
1342 src=
"img/buttons/debian.png" alt=
"[ Powered by Debian ]" /></a>
1344 <a href=
"http://hcoop.net/">
1345 <img src=
"img/buttons/hcoop.png"
1346 alt=
"[ Hosted by HCoop]" />
1349 <a href=
"http://www.fsf.org/register_form?referrer=114">
1350 <img src=
"img/buttons/fsf_member.png"
1351 alt=
"[ FSF Associate Member ]" />
1355 <p class=
"cke-footer">And did those feet in ancient times
1356 Walk bare upon these lonely streets like mine?
1357 Does God watch us from that penthouse high above
1358 His children down below who live on air and love?
1360 <p class=
"cke-timestamp">Last Modified: