[Zope3-dev] <script> - the anti-pattern

Phillip J. Eby pje at telecommunity.com
Wed Sep 10 13:39:24 EDT 2003


At 11:58 AM 9/10/03 -0400, Paul Winkler wrote:
>On Wed, Sep 10, 2003 at 08:37:30AM -0400, Phillip J. Eby wrote:
> > For what it's worth, there exists a templating approach that makes it
> > *impossible* to put code into templates, but still makes it possible to
> > create arbitrary dynamic content in an extensible way.  There are three
> > different Python systems that use this approach: PSO, twisted.web.woven,
> > and peak.web.templates.  Essentially, in all three approaches, a special
> > attribute of an XML/XHTML tag specifies a factory for a Python object that
> > will be responsible for rendering the contents of that tag.
> >
> > Thus, the visual designer is limited to expressing only concepts that are
> > made available by the author of the Python objects.
>
>(snip)
>What does the invocation of a factory buy you?
>How is this better than <foo tal:content="container/bit_of_code"></foo> ?

Visual parameters.  In your example, 'bit_of_code' has no access to the 
*original* content of the <foo> block.  To illustrate, here's an example 
use of a hypothetical "selected-list" component:

PEAK syntax
-----------
<ul pwt:domlet="selected-list:something">
     <li>This item is just an example and will not show up in the output</li>
     <li pwt:define="unselected">This is how an unselected item is 
rendered</li>
     <li pwt:define="selected"><b>This is how the selected item is 
rendered</b></li>
     <li>This item is just an example and will not show up in the output</li>
</ul>


Woven syntax
------------
<ul view="selected-list" model="something">
     <li>This item is just an example and will not show up in the output</li>
     <li pattern="unselected">This is how an unselected item is rendered</li>
     <li pattern="selected"><b>This is how the selected item is 
rendered</b></li>
     <li>This item is just an example and will not show up in the output</li>
</ul>

Regardless of how you spell it, the hypothetical "selected-list" component 
would be instantiated and given the containing DOM nodes (or DOMlets) as 
its contents.  Note that an individual component can be both a parameter 
(define/pattern) *and* executable (domlet/view).  Thus a component can 
invoke the content nodes for rendering.  A slightly more complex example to 
illustrate this:

<ul pwt:domlet="selected-list:something">
     <li>This item is just an example and will not show up in the output</li>
     <li pwt:define="unselected" pwt:domlet="text:title">
         The item title will replace this text
     </li>
     <li pwt:define="selected">
         <b pwt:domlet="text:title">Selected item title goes here in bold</b>
     </li>
     <li>This item is just an example and will not show up in the output</li>
</ul>

In the Woven implementation, "views" get passed a DOM of their contents, 
while in PEAK the contents are objects implementing IDOMletNode: a very 
simple interface optimized for fast rendering.  The container elements must 
implement IDOMletElement, which provides methods for adding text or element 
subnodes, and supplying "define" parameters.  IDOMletElement includes 
support for controlling how subnodes are created, so a given component can 
even control the factory namespace for nested DOMlets.  IOW, let's say that 
you created a "form" DOMlet, it could provide a special "field" DOMlet that 
would only be accessible in the contents of that "form" element.

Anyway, these examples should suffice to show that the "visual components" 
or "active elements" approach is different from TAL/TALES.  The 
similarities are that 1) it can also be implemented in a way that's 
XML/XHTML-compatible, 2) it also allows a page to be edited in a WYSIWYG 
editor, and 3) the parameter mechanism is akin to METAL's define-slot, 
except that it allows complex "macros" to be written in Python.

It is different, however, in that effectively only simple path expressions 
are allowed, and there are no built-in control structures.  It is 
considered preferable to use higher-level abstractions (fields, forms, 
widgets, etc.) as components.

Interestingly, I would think this approach to be a *very* good fit with the 
Z3CA, since there are all these menus and schemas and vocabularies and 
such.  Rather than script TAL/TALES to render these things, there could be 
Python components.  And, if you could use METAL macros as XML components, 
then "scripters" would be able to make components of their own, at least 
for pure-layout purposes.  And there would be a distinct boundary between 
"scripting" and "making components", with an obvious motivation to learn 
how to "make a component".

If you're curious, the PEAK DOMlet interfaces can be viewed at:

http://cvs.eby-sarna.com/PEAK/src/peak/web/interfaces.py?rev=HEAD&content-type=text/vnd.viewcvs-markup

See the IDOMlet* interfaces at the end of the file.  The current 
implementation draft (including simple "List", "Text", and "URL" 
components) is at:

http://cvs.eby-sarna.com/PEAK/src/peak/web/templates.py?rev=HEAD&content-type=text/vnd.viewcvs-markup

(The interfaces and implementation include an optimization to make static 
content render more quickly, similar to ZPT bytecode optimization.  Nodes 
whose output is static can be joined by their container into a single 
static node, reducing the number of nodes processed when the "compiled" 
template is executed.)




More information about the Zope3-dev mailing list