[ZPT] dynamic navigation menus

Thom Wysong TWysong@DevIS.com
Wed, 31 Jul 2002 19:39:03 -0400


Something got b0rked with the spacing of my original response. Here it is
again. Hopefully in a more readable format. 

Apologies for the duplicate emails. 

-Thom

---------- 

Mark McEahern wrote: 
>>> 1. If I want the user to be able to sort Folders within the ZMI in an
arbitrary way, is there a simpler/easier/less problematic approach than
adding an integer property called "sort_order" to each Folder and then
sorting by that in the ZPT macro? <<<

As was already mentioned, the OrderedFolder product works very well for
this. I seem to recall, however, it uses code that is not yet fully
debugged/working on Windows. I'm not sure if that's still an issue or not.
http://www.zope.org/Members/srichter/Products/OrderedFolder 

If OrderedFolder doesn't work, then adding a "sort_order" property to your
content folders should work. 


>>> 2. How do I determine the current section and subsection and use that to
distinguish from selected and unselected tabs (for example)? <<< 

A python script should be able to determine the current section and
subsection. Then a tal:condition could be used to determine whether to
output 'selected' or 'unselected' css/html tags. 

However, trying to use a tabbed interface might be tricky. My guess is you
want the values of the top-level tabs to remain static as you move through
the site - with the only thing changing on them being which one(s) are
highlighted/selected. However, using here/objectValues and
container/objectValues probably will output values for the tabs that are
relative to where you are in the site - changing the titles/links that show
up in the tabs. 


>>> 3. How do I determine and set the default section and subsection? <<<

The easiest way would probably be to set a "default_secton_id" or
"default_section_path" property on the root content folder. The property
would then be accessible by any object in that root folder via acquisition. 


>>> My goal is to to create a template for a dynamic navigation menu ..
[snip] .. The particular look I was after was a tabbed navigation menu with
two levels of menus. <<< 

The site could be viewed as being three levels - with the 'root content
folder' being level 1, 'sections' being level 2, and 'subsections' being
level 3. At each level you'll want the tabs to display the objectValues for
the root content folder, and for whichever 'section' the user is in (if
any). However, depending on which level in the site the user is at, the way
you get those values will change (if you try to use container/objectValues,
etc in your tal). Sometimes it will be objectValues for the current
container and each of its children (level 1). Sometimes it will be
objectValues for the parent of the current container and the current
container itself (level 2). Sometimes it will be objectValues for the
grandparent and parent of the current container (level 3). 

Another way of handling this would be to have a python script in the root
content folder return a data structure of the entire site, that the ZPT then
uses to build tabs off of. That data structure could be built dynamically by
spidering the site (tricky) or by hard-coding the section/subsection values
into the python script (not dynamic, but easier to begin with). The script
should be accessible to the ZPTs anywhere on the site via acquisition. 


>>> Rather than comingling my experiment with everything else in the Root
folder, I created a folder called navtest.  Within navtest, I created ..
[snip] .. I noticed the ZMI ... required using the mouse more than I would
have liked .. <<< 

In the ZMI, when creating multiple instances of the same type of object,
it's probably faster to create only one instance of it, then copy & paste a
bunch of copies of it where you want. Then do a mass rename (click the
checkboxes for all the copy_of_ instances, click the 'Rename' button, then
rename all the copies at once). This is faster than filling in a numerous
'Add' forms. 


>>> Once I looked at the HTML, several problems became obvious: ... 2. I
needed to separate the content folders from folders like images and styles
that I did not intend to reflect in the menu. ... Solution:  Create a
content folder and move the section folders into it. <<<

If you are able to use OrderedFolders, then you could simply filter your
objectValues - listing out only OrderedFolders. 

If not, then you could add a Boolean property to your root content folder
called in_nav_menu. Set it to 'true' (check the box). Then every folder that
is intended to be in the navigation menu will automatically acquire this
property. Every folder that is not a intended to be in the navigation menu
(ie images, styles) will need their own in_nav_menu property, set to
'false'. Then use a <tal:condition="seq_item.in_nav_menu"> inside the
tal:repeat loop to only output items that have in_nav_menu set to 'true'. 


>>> 3. I needed to handle the case of a section not having any subsections.
... Solution:  I wasn't sure how to handle this yet, so I punted on it. <<< 

Load the objectValues for the selected section into a variable using
tal:define (ie. subsection_list). Then use a tal:condition="subsection_list"
statement (or something close to this) on the set of tabs listing out the
subsections. If the variable (subsection_list) is empty, then the subsection
tabs won't show up. If it has something in it, then ZPT will output them.
Put the tal:repeat for the subsections on a tag that's inside the tag
containing the tal:condition="subsection_list". 

If you need an extra tag in there just for processing, you can use a <span>
tag, then add a tal:omit-tag="" onto it so it doesn't show up in your html. 


>>> 4. I anticipated having problems with the URIs.  Notice how Zope inserts
the <base href=""/> tag.  Will I need to suppress that? Will my solution to
problem 2 (above) create problems with relative URIs? ... Solution:  I
wasn't sure how to handle this yet, so again I just punted on it. <<<

As mentioned in the previous email on this topic, put a <base /> tag at the
top of your ZPT template. That should prevent Zope from mucking up any
relative URI addressing you use. 


>>> I used the Cut/Paste feature of ZMI to move the section folders from the
navtest folder to a new content folder. ... [snip] <<< 

This was unnecessary (see above), but it is another way of handling the
issue. 


>>> I had to replace section/getId with section.getId().  That's probably
obvious, but I'm not sure precisely HOW I'd document this in the ZPT
documentation. <<< 

As a rule of thumb, when placing an expression after "python:" inside a ZPT
tag, you need to use python syntax. Use ZPT syntax elsewhere inside ZPT
tags.

Python syntax --> object.method() .. object.property 
ZPT syntax -----> object/method .... object/property 


>>> 5. I needed to define default positioning within the menu as well as a
method of determining the current position. <<<

Default positioning .. set a property on the root content folder. 

Determining current position .. this can be tricky .. will probably need to
be done in a python script .. might want to investigate pulling the URL
parameter out of the REQUEST variable .. then parsing it to help determine
where the user is in the site. 

-tgw