[Bese-devel] Linking to resources (css, js) required by components

Anthony Juckel ajuckel at gmail.com
Fri Jul 30 14:14:42 UTC 2004


I've been thinking about some modifications to the rendering of
standard components (especially tabbed-pane).  The one issue that I'm
stuck on trying to find a resolution for is how to link to external
files for css and js content.

First, why link to external files?  Two reasons:  1) To make the
rendered page as clean (i.e. free of cruft) as possible and 2) to
allow for browser caching of said pages.

The first thing is, how do we register such requirements.  As an
example, my redesigned tabbed-pane requires a css file, lets call it
"tabbed-pane.css."  I think the option I'm leaning toward is the
following.  First, the component definition needs to be updated to
register the fact that it has required resources.  In this case, the
definition for tabbed-pane would end up something like the following:

(defcomponent tabbed-pane (standard-component)
  ((panes :accessor tabbed-pane.panes :initarg :panes)
   (current-pane :accessor tabbed-pane.current-pane :initarg :current-pane :ini\
tform 0))
  (:template "ucw/tabbed-pane.tal" [...snipped for brevity...])
  (:requires-external-resources t)
  (:documentation "Component for providing the user with a standard \"tabbed pa\
ne\" GUI widget."))

Next, there's a new generic function,

(defgeneric render-requirements (component))

with the following definition for tabbed-pane:

(defmethod render-requirements ((component tabbed-pane))
  (<:link :rel "stylesheet" :type "text/css" :href (concatenate
'string *ucw-resource-root* "tabbed-pane.css")))

This naturally requires that *ucw-resource-root* is defined within ucw
(much as *ucw-tal-root* is defined now), and appropriately served up
by the backend.

The last hurdle is to trigger the calling of render-requirements on
all components within a given page when rendering the <head> element
of the page.  To make it transparent, it would be nice if yaclml
supported registering hooks for elements, so we could do something
like the following:

(yaclml:register-hook (:head :end) #'(lambda ()
(ucw:render-requirements ucw:*all-components*)))

That would tell yaclml to call render-requirements and append the
output to the response before closing the <head> element.  This in
turn would require a new special variable ucw:*all-components* that is
simply a list of all components used within the rendering of a given
page.

All in all, this is looking quite ... crufty.  There's too much going
on to get a rather simple effect accomplished.  I'm open to
suggestions for streamlining all of this.  For instance, it would be
fairly simple to avoid the :requires-external-resources declaration
for the component by just providing:

(defmethod render-requirements ((component standard-component)))

and calling this method for all components.  What other ways could
this be accomplished?  Are there existing hooks within ucw/yaclml that
could provide similar functionality?

Anthony W. Juckel




More information about the bese-devel mailing list