JTec menu framework

You need menu structure for you site? Breadcrumbs? Opening menu panes? It could take a lot of work to edit all the pages, but there is better solution.

short introduction

To make your life easier, you really should use sitemesh and edit only decorator leaving content pages alone, but strictly speaking it is not necessary - you just got to work more. This menu system is degined to be used in pico/nanocontainer web applications, but also can be used without it. ( With some additional effort )

Define menu structure

Menu strutire is defined in xml file: ( this is fragment menu srtucture used for linkmatic

<root>
    <title>menu.home</title>
    <path>/</path>
    <key>menu.home</key>
    <entries>
        <entry>
            <title>menu.login</title>
            <path>/login/login!input.action</path>
            <key>menu.login</key>
        </entry>
        <entry>
            <title>menu.sites</title>
            <path>/sites</path>
            <key>menu.sites</key>
            <entries>
                <entry>
                    <title>menu.sites.site</title>
                    <path>/sites/site</path>
                    <key>menu.sites.site</key>
                </entry>
            </entries>
        </entry>
        <entry>
            <title>menu.contact</title>
            <path>/contact/contact!input.action</path>
            <key>menu.contact</key>
        </entry>
        <entry>
            <title>menu.legal</title>
            <path>/legal/</path>
            <key>menu.legal</key>
            <entries>
                <entry>
                    <title>menu.legal.owner</title>
                    <path>/legal/owner.vm</path>
                    <key>menu.legal.owner</key>
                </entry>
                <entry>
                    <title>menu.legal.tos</title>
                    <path>/legal/tos.vm</path>
                    <key>menu.legal.tos</key>
                </entry>
                <entry>
                    <title>menu.legal.privacy</title>
                    <path>/legal/privacy.vm</path>
                    <key>menu.legal.privacy</key>
                </entry>
            </entries>
        </entry>
    </entries>
</root>
                    

This structure corresponds with properties of de.jtec.menu.Entry and is read with a help of betwixt (by class de.jtec.menu.betwixt.BetwixtEntry) Title, description and path are self explanatory, and key got to be unique and is used to reference entries directly.

Register objects in scopes

As there is DI environment ( pico/nanoccontainer ) we have to register our components in respective scopes. Menu structure itself is shared, and comes into WEB-INF/classes/nano-application.xml:

<container>
    <!-- menu structure -->
    <implementation key="menuRoot" class="de.jtec.menu.betwixt.BetwixtEntry">
        <constant>
            <string>menu.xml</string>
        </constant>
    </implementation>
    <!-- locate entries by keys -->
    <implementation key="entryLocator" class="de.jtec.menu.util.DirectEntryLocator"/>
</container>
                    

We store actual menu state in the session scope so it is sticky, even between page invocations. We could also place it into application scope, but then we would have to take care of correct menu entry selection on every request. This way we change menu state only when necessary. (Breadcrumbs extracts path from root to current active entry) WEB-INF/classes/nano-application.xml:

<container>
    <implementation key="siteMenu" class="de.jtec.menu.Menu"/>
    <implementation key="breadcrumbs" class="de.jtec.menu.util.Breadcrumbs"/>
</container>                       
                    

Activate entry

How our infrastructure is in place, but somehow we are going to activate it. Nanocontainer provides web sirectory based container chains - such directory container is perfect place to activate menu entry. (nano.xml somewhere in a website directory):

<container>
    <!-- activate menu entry -->
    <implementation class="de.jtec.menu.util.EntryActivator">
        <dependency key="siteMenu"/>
        <dependency key="entryLocator"/>
        <constant>
            <string>menu.legal</string>
        </constant>
    </implementation>
</container>   
                    

This would instantiate EntryActivator, which would "activate" menu entry with configured key ( menu.legal). Now we are ready to rumble render. ( see how it looks)

Render this

Reference site uses sitemesh and velocity templating. So, everything surrounding content is actually rendered by decorator. Here come breadcrumbs:

#*
    display breadcrumbs
*#
#pico_component( $breadcrumbs 'breadcrumbs')
<div id="breadcrumbs">
    <ul>
        #foreach( $crumb in $breadcrumbs.breadcrumbs )
            <li>
                <a href="$url.setPage($crumb.path)" class="button">
                    #wwtext("name=$crumb.title")
                </a>
            </li>
        #end
    </ul>
</div>                    
                    

And side menu:

#*
    display side menu - current node and her silbings
*#
#pico_component( $menu 'siteMenu')
<div id="sidebar">
    <ul>
        <li>
             <a href="$url.setPage($menu.current.path)" class="button">
                    #wwtext("name=$menu.current.title")
             </a>
        </li>
        #foreach( $entry in $menu.current.entries )
            <li>
                <a href="$url.setPage($entry.path)" class="button">
                    #wwtext("name=$entry.title")
                </a>
            </li>
        #end
    </ul>
</div>
                    

See full picture at: http://www.yook.de/linkomatic

Putting it all together

We have created website menu system. It is non-intrusive, does not require any struts actions or whatever and content pages are unaware of it. Whale else do you need?

Special thanks go to (you can not find them in dependency list, project does not depend on them. That's dependency injection):