[Zope3-Users] Re: menus, menu items and actions

Philipp von Weitershausen philipp at weitershausen.de
Wed Jun 1 18:07:16 EDT 2005


Jan-Wijbrand Kolman wrote:
> Hi,
> 
> 
> I'm working an application that will have some sort of 'main menu' of actions,
> that should always be available in the UI of this applications.
> 
> So, I register a menu:
> 
>   <menu
>     id="foo_menu"
>     title="The Main Foo Menu"
>   />
> 
> and a menu item for it:
> 
>   <menuItem
>     title="Do Bar"
>     description="Do Bar In This Application"
>     for="*"
>     menu="foo_menu"
>     action="bar"
>     permission="zope.Public"
>   />
> 
> When rendering the HTML for this menu, the menu item's action is basically used
> as  a relative URL (relative to the current location in e.g. a content object
> tree).
> 
> However, what I would like is to point to a specific URL relative to my
> application root - since 'bar' is a specific view on my app.root.
> 
> At the moment, I solved it by implementing a custom menu class, subclassing
> BrowserMenu:
> 
>   from zope.app.publisher.browser.menu import BrowserMenu
>   class FooMenu(BrowserMenu):
>     def getMenuItems(self, object, request):
>       items = super(FooMenu, self).getMenuItems(object, request)
>       base = 'http://baz.qux.com/' # the base URL will be the absolute url for
>                                    # my application root
>       for item in items:
>           item['action'] = '%s/%s' % (base, item['action'])
>       return items
> 
> And register my foo menu like so:
> 
>   <menu
>     id="foo_menu"
>     title="The Main Foo Menu"
>     class="fooapplication.browser.menu.FooMenu"
>   />
> 
> 
> This does work, but feels a bit icky - although I cannot really say why. Is
> there a better way to achieve this?

You don't really need to treat the action path in the menu class. You 
can just as well assemble it in the Page Template where you're actually 
looping over the menu items.

For a simple setup (e.g. the one I use on worldcookery.com), I used:

<metal:macro define-macro="navigation_tree_box">
   <div class="box" id="navigationTree">
     <h4 i18n:translate="">Navigation</h4>
     <tal:loop define="request_url request/URL/-1;
                       stem_url    request/URL/0"
               repeat="nav context/@@view_get_menu/wcsite_navigation">
       <div tal:define="selected python:request_url == stem_url + 
nav['action']"
            tal:attributes="class python:selected and 'navitem_selected' 
or 'navitem'">
         <a href="" tal:attributes="href string:${stem_url}${nav/action};"
            tal:content="nav/title"
            i18n:translate="">label</a>
       </div>
     </tal:loop>
   </div>
</metal:macro>

If you need a more complex setup, e.g. have your 'stem_url' always be 
the URL of some object that is not the root of your Virtual Host, you 
could define a browser view (not a page!) named 'get_application_root' 
or so, have that traverse the acquisition path to the object and return 
it and then use that object's @@absolute_url.

Hard coding a URL in Python is definitely not very useful.

Philipp



More information about the Zope3-users mailing list