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

Phillip J. Eby pje at telecommunity.com
Wed Sep 10 16:55:43 EDT 2003


At 03:21 PM 9/10/03 -0400, Paul Winkler wrote:
>On Wed, Sep 10, 2003 at 12:39:24PM -0400, Phillip J. Eby wrote:
> > 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>
>(snip)
> > 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.
>
>Very very interesting. I like the look of it. But I'm a bit
>confused. The selected-list instance gets the whole <ul>
>node including all its child nodes?

Yes.


>And I gather the selected-list has a sequence of text streams,
>which are somehow marked "selected" or "unselected".

I left that bit out, but there would presumably be a ISelectList interface 
that the object referenced by the 'something' path would have to support.


>And somehow it figures out that you want the selected
>text to go inside the <b> tag? How?

Actually, that first example just displays the text as-is, it doesn't 
insert anything.  The first example would actually output something like:

<ul>
<li>This is how an unselected item is rendered</li>
<li>This is how an unselected item is rendered</li>
<li><b>This is how the selected item is rendered</b></li>
<li>This is how an unselected item is rendered</li>
<li>This is how an unselected item is rendered</li>
</ul>

(Assuming there were five items in the list, and the third was the one 
selected.  And there would be fewer newlines in the output.)

If you look at the later example in my e-mail, it actually inserts a 
"title" value as text to replace the contents of certain elements.  I 
skipped over that issue on the first example in order to have a simpler 
example to start with.


>  What if I had this:
>
>  <li pwt:define="selected"><b>This</b> is how the selected item is
>  rendered</li>
>
>What happens there?

Same as I just showed above...  it's copied as-is to the output, since 
there's nothing dynamic there.


>Also, what might simple code for selected-list look like?
>
>I had a look at the code URLs you provided, but the answers were not
>clear to me.


Something like:


from peak.web.templates import ContentReplacer

class SelectList(ContentReplacer):

     def renderFor(self, data, state):

         if self.dataSpec:
             # traverse to the 'something' part of 'select-list:something'
             data, state = self._traverse(data, state)

         # Write our opening tag
         state.write(self._openTag)

         unselected = self.params['unselected']
         selected   = self.params['selected']
         theList   = adapt(data.subject, IListWithSelection)

         selectedItem = theList.getSelectedItem()

         for item in theList.getItems():
             if item is selectedItem:
                 selected.renderFor(data.subcontext(None,item),state)
             else:
                 unselected.renderFor(data.subcontext(None,item),state)

         # Write our closing tag
         state.write(self._closeTag)

This (very rough) code is dependent upon a hypothetical 
'IListWithSelection' that provides 'getSelectedItem()' and 'getItems()' 
methods.  It also assumes (without error checking) that is has been given 
definitions for both 'unselected' and 'selected'.

The 'data' and 'state' parameters to 'renderFor()' implement 
peak.web.ITraversalContext and peak.web.IDOMletState, 
respectively.  'data.subcontext()' is used to get a new traversal context 
for an object that you've manually traversed to (as is done by getting 
items from the getItems() method).  'data.subject' is the traversed-to 
object.  'state.write()' is used to send output.

Notice that the parameters also implement IDOMletNode; thus, we can call 
'selected.renderFor()' on them to pass through a new current traversal 
context, while keeping the same 'state'.  One aspect of this model, used in 
both PEAK and Twisted, is that traversal context is carried through to 
nested tags, in a logical hierarchy.  Twisted also has an acquisition-like 
namespace stack, but PEAK doesn't do that, so that you can reason about the 
paths' behavior while looking only at the template.




More information about the Zope3-dev mailing list