Declarative Menus

Declarative menus are used to add new or customize default navigation elements in displayed portal pages. These PSML declarations are part of the page and folder elements. As with other PSML elements, effective menu declarations available for a given page are those that are explicity defined in the page along with all defined in parent folders. For this reason, global site menus are defined in the PSML associated with the site root folder. Menu definitions in a specific page or folder override menus with the same name found in parent folders.

Portal layout decorators access page menu declarations by name while rendering portal content. Menus are used to create dynamic navigation panes, portal page tabs, bread crumb links, and pull downs. The Portal Site Component is responsible for fleshing out the dynamic menu definition options with page specific PSML elements from the site. For instance, a global menu declaration would typically be involved in the following sequence of events while a portal page is being composed:

  1. The portal layout decorator would request a menu definition by name,
  2. the definition would be inherited by the current page and located in the root folder PSML,
  3. the Portal Site Component would interpret the menu definition in the context of the current page and populate page, folder, and link menu options,
  4. the decorator would display the menu rendering titles and text from the menu definition itself and the computed menu options into portal navigation content.

There are default global menu declarations supported internally by the Portal Site Component that do not need to be explicitly defined in any page or folder PSML elements of the site:

  • pages: relative pages menu used to define the page tabs above the portal.
  • breadcrumbs: paths to page used to provide history links below the page tabs.
  • navigations: relative subfolders and root level links menu used to define the navigation pane beside the portal.
  • back: parent folder menu used to define the single "back" link above the portal page tabs.
As one would expect, these built in menu definitions can be overridden by declaring menus in the site PSML with the same name.

The remainder of this guide provides more information on specifying and using declarative menu definitions within Jetspeed2:

Menu Definition

The <menu> element defines a menu to be used by the layout decorators or a nested menu within another menu. There are many valid attributes for the menu element:

Attribute Description
name Identifies menu name for retrieval from template code and/or menu reference. This attribute is required for top level nodes and ignored for nested menus.
options Specifies root document path for this menu if deep inclusion of documents and folders is specified by this menu. This attribute may also define document paths that specify page, folder, or link menu options. Paths specified in this attribute are Page URIs; these URIs may or may not directly reflect the folder and page hierarchy. The Portal Site Component maps these options paths to PSML folder and page elements. Multiple option paths can be specified as a comma separated list of paths and/or regular expression patterns. Relative paths are interpreted as relative to the current page. Special patterns, '~' or '@', can be used to reference the current page.
depth Specifies deep inclusion of documents from option folders, (depth < 0 specifies infinite depth). Menu options are created to represent each visible page or link in the site; folders are converted into nested menus constrained by this setting.
paths Boolean attribute to enable the "path" expansion of options: specified options are expanded to include paths from the root to the specified options. For example, if options is specified to be "/folder/page.psml", setting this attribute would result in the menu containing options for "/", "/folder", and "/folder/page.psml". This setting is typically used to generate "history" or "bread crumb" menus.
regexp A boolean attribute the specifies whether wild card/regular expression processing be performed on options values. File system command line regular expression syntax is supported.
profile Specified name of Profile Locator to be used when evaluating option values. This attribute also sets the default profile value for options and nested menus. Specifying '*' forces the acceptance of all Profile Locator names; this can be used to override parent menu selects a profile name.
order Comma separated list of regexp patterns matched against list or regular expression document path values to determine order of matched options. This attribute will be applied as a default options value for any options elements, but is not used to reorder multiple options children matches. If not specified, multiple options are included in the order returned by the underlying folder document orderings. Option paths not matched by this attribute are appended after ordered matches.
skin Optional decorator defined layout hint for the menu. This attribute is also used as the default skin value for options and nested menus. This hint is not currently used by Jetspeed2 decorators.

The <menu> element contains a number of other menu definition PSML elements. With the exception of the title and metadata elements, the relative order of these elements determines the order that the layout decorators present them:

Element Description
title? Simple element text specifies default locale-independent title for the menu. The title of the menu is considered its long description and is used as rollover text in some decorators if the short title is available for the menu text. If not specified, the name of the menu will be used.
short-title? Simple element text specifies default locale-independent short title for the menu. The short title, if available, is used as menu text in some decorators. If not specified, the title text is used.
metadata* Optionally specifies additional locale-specific titles and short titles.
options* This ordered menu element specifies content elements for this menu definition.
separator* An ordered menu element used to specify text lines to be included inline in this menu definition.
menu* Another ordered menu element used to define a nested menu contained in this menu definition.
include* Specifies a menu to nest within or options from a another menu to be included in this menu definition. The name of the menu to include is the text of this ordered menu element.
exclude* Specifies options and nested menus from another menu to be excluded from this menu definition. The name of the menu with elements to exclude is the text of this ordered menu element.

Examples:

<!-- simple menu composed of 2 pages -->
<menu name="simple">
    <options>/some-top-page.psml,/custom/some-other-page.psml</options>
</menu>
<!-- site menu for the top 2 levels: folders result in nested menus -->
<menu name="top-2-levels" options="/" depth="2" skin="dhtml-pull-down"/>
<!-- menu containing top level elements profiled by roles -->
<menu name="top-role-pages" regexp="true" options="/*" profile="roles"/>
<!-- contrived example demonstrating element syntax -->
<menu name="top-custom">
    <title>Top Menu</title>
    <metadata name="title" xml:lang="fr">Haut</metadata>
    <options regexp="true" profile="groups">/group-pages/*</options>
    <menu options="/" profile="page">
        <separator>
            <text>-- Top Pages --</text>
            <title>Top Pages</title>
        </separator>
        <options regexp="true">/*</options>
        <separator>
            <title>Custom Pages</title>
        </separator>
        <options depth="2">/custom-folder/</options>
    </menu>
    <exclude>top-role-pages</exclude>
    <separator>More Top Pages</separator>
    <include nest="true">top-role-pages</include>
</menu>

The definitions for the default global menu declarations supported internally by the Portal Site Component:

<!-- standard pages tabs menu -->
<menu name="pages" regexp="true" options="*.psml"/>
<!-- standard history breadcrumbs menu -->
<menu name="breadcrumbs" options="~" paths="true"/>
<!-- standard navigations panel menu -->
<menu name="navigations">
  <separator>Folders</separator>
  <options regexp="true">./*/</options>
  <include>page-navigations</include>
  <separator>Additional Links</separator>
  <options regexp="true">/*.link</options>
</menu>
<!-- standard parent folder link menu -->
<menu name="back" options="../"/>

Note that the separator text of these definitions is localized internally.

Menu Options Definition

The <options> element defines a single or multiple options within a menu. The text of this simple element specifies document paths that yield page, folder, or link menu options. Paths specified in this element are Page URIs; these URIs may or may not directly reflect the folder and page hierarchy. The Portal Site Component maps these options paths to PSML folder and page elements. Multiple option paths can be specified as a comma separated list of paths and/or regular expression patterns. Relative paths are interpreted as relative to the current page. Special patterns, '~' or '@', can be used to reference the current page. This element shares many attributes in common with the menu element:

Attribute Description
depth Specifies deep inclusion of documents from option folders, (depth < 0 specifies infinite depth). Menu options are created to represent each visible page or link in the site; folders are converted into nested menus constrained by this setting.
paths Boolean attribute to enable the "path" expansion of options: specified options are expanded to include paths from the root to the specified options. For example, if options is specified to be "/folder/page.psml", setting this attribute would result in the menu containing options for "/", "/folder", and "/folder/page.psml". This setting is typically used to generate "history" or "bread crumb" menus.
regexp A boolean attribute the specifies whether wild card/regular expression processing be performed on options values. File system command line regular expression syntax is supported.
profile Specified name of Profile Locator to be used when evaluating option values. This attribute also sets the default profile value for options and nested menus. Specifying '*' forces the acceptance of all Profile Locator names; this can be used to override parent menu selects a profile name.
order Comma separated list of regexp patterns matched against list or regular expression document path values to determine order of matched options. This attribute will be applied as a default options value for any options elements, but is not used to reorder multiple options children matches. If not specified, multiple options are included in the order returned by the underlying folder document orderings. Option paths not matched by this attribute are appended after ordered matches.
skin Optional decorator defined layout hint for the menu options. Skin attribute values from each page, folder, or link will be used to populate menu options if this hint is not specified here. Otherwise, the skin hint from the containing menu will be used. This hint is not currently used by Jetspeed2 decorators.

Example:

<menu>
    ...
    <options regexp="true" order="*.psml,*.link">/some-top-page.psml,/custom/some-other-page.psml,/*.link</options>
    ...
</menu>

Menu Separator Definition

The <separator> element defines a separator to be included in a menu. The separator will be included only if options or nested menus appear below this element within a menu definition. The text of the separator can be specified in the contained text of this element or in the text menu definition element. There is only one attribute accepted by the separator element:

Attribute Description
skin Optional decorator defined layout hint for the menu separator. This hint is not currently used by Jetspeed2 decorators.

The <separator> element contains a number of other menu definition PSML elements:

Element Description
title? Simple element text specifies default locale-independent title for the separator. The title of the separator is considered its long description and is used as rollover text in some decorators if the separator text is available.
text? Simple element text specifies default locale-independent text for the separator. The required separator text, whether specified by this attribute or as the contained text of the separator element, is the text to be inserted in the menu by the layout decorator.
metadata* Optionally specifies additional locale-specific titles and separator text.

Examples:

<menu>
    ...
    <separator>-------------</separator>
    ...
    <separator>
        <text>-- Top 10 Pages --</text>
        <metadata name="text" xml:lang="fr">Haut Pages</metadata>
        <title>Top 10 pages as voted by the Jetspeed2 users!</title>
    </separator>
    ...
</menu>

Menu Include Definition

The <include> element includes options or nested menus from another menu. The name of the menu to include is specified as the text value of this element. There is only one valid attribute for the include element:

Attribute Description
nest Boolean flag that controls whether the specified menu is to be nested. If this attribute is set to 'true', the included menu will be nested as a submenu; otherewise, all options and nested menus from the specified menu will be inserted inline into this menu.

Examples:

<menu>
    ...
    <include nest="true">navigations</include>
    ...
</menu>

Menu Exclude Definition

The <exclude> element excludes options or nested menus from another menu. This option is used primarily to remove menu options that already appear on the portal page in another menu from this menu. Matching options or menus will be excluded only if they appear above this element within a menu definition. The name of the menu to include is specified as the text value of this simple element.

Examples:

<menu>
    ...
    <exclude>pages</exclude>
    ...
</menu>

Page Layout Decorators

The page layout decorators request menus from the Portal Site Component when the page is being rendered in the Jetspeed2 pipeline. The decorators expect certain menus to be provided by the PSML declarations. Before custom menus can be displayed in the portal, the decorators need to be modified to render the custom menu. Here is an example taken from a Velocity layout decorator header.vm file:

...
#set($pagesStandardMenu = $site.getMenu("pages"))
#if(!$pagesStandardMenu.empty)
  <div class="tabs">
#includeTabsNavigation($pagesStandardMenu $LEFT_TO_RIGHT)
  </div>
#end
...

This code block renders the standard pages tabs menu within a portal page. The Portal Site Component is exposed as the $site Velocity context variable. The test for an empty menu definition is designed to ensure that empty menus are not rendered into the page content. Finally, a decorator macro is executed to expand the menu content. This approach is taken in general to support the rendering of nested menus with recursive invocations of the macro. In this case, the decorator is expecting only page options. Here is the macro implementation used to render the pages tabs menu:

#macro (includeTabsNavigation $_menu $_orientation)
  <table border="0" cellpadding="0" cellspacing="0">
  <tr>
    #foreach($element in $_menu.elements.iterator())
      #if($element.elementType == "option")
        #set($tabTitle = $element.getTitle($preferedLocale))
        #set($tabName = $element.getShortTitle($preferedLocale))
        #if($_orientation == $LEFT_TO_RIGHT)
          #if($element.isSelected($site))
            <td class="LTabLeft" nowrap="true">&nbsp;</td>
            <td class="LTab" align="center" valign="middle" nowrap="true" title="$!tabTitle">${tabName}</td>
            <td class="LTabRight"  nowrap="true">&nbsp;</td>
          #else
            #set($tabUrl = $jetspeed.getAbsoluteUrl($element.url))
            <td class="LTabLeftLow"  nowrap="true">&nbsp;</td>
            <td class="LTabLow" align="center" valign="middle" nowrap="true" title="$!tabTitle"><a href="$tabUrl">${tabName}</a></td>
            <td class="LTabRightLow"  nowrap="true">&nbsp;</td>
          #end
        #end
      #end
    #end
  </tr>
  </table>
#end

This macro iterates over the computed page menu options supplied by the Portal Site Component, rendering a series of table data HTML elements that make up each displayed tab. The whole menu is rendered as a HTML table with a single row.

The declarative menu Portal Site Component objects exposed to the layout decorators are documented in the Jetspeed API. Here is a list of the primary interfaces that make up this interface:

Please refer to the javadocs for these interfaces and sample Velocity decorators for more information.

Jetspeed2 provides many sample decorators including those that will render tabs, navigation panes with nested submenus, history breadcrumb links, and even DHTML JSCookMenu nested pulldown menus... all from the declarative menu elements documented here.

Portal Site Component

In conjunction with the Jetspeed Profiler Component, the Portal Site Component performs two closely related functions:

  1. Map portal request URLs from a user to PSML page or folder elements in the site, and
  2. construct site navigational menus and their options that reflect what is available to the user from the site.
At first glance, these functions seem relatively simple: searching within and traversing the PSML site definition. However, once the complexities of Profiler composition and Security Constraints filtering are taken into account, the mapping is often not trivial.

Menu definition options paths are specified as Page URIs to leverage this mapping functionality. A Page URI is essentially the tail portion of a portal request URL that is used to address a page or folder. Using Page URIs for options allows menu definitions to be shared by all users of the portal: the user specific profile and effective security constraints are applied to generate the menu options. This implies that the physical paths used internally within the Page Manager file system or database cannot be specified to directly address a specific PSML element.

For example, suppose the following:

  • the default "j2" profiling rules are in effect for the 'someone' user,
  • the following physical PSML site structure is available in the Page Manager,
    • .../page0.psml
    • .../page1.psml
    • .../page2.psml
    • .../hidden-page0.psml
    • .../_user/someone/page0.psml
  • security constraints denied access to '/page2.psml' for the user, and
  • '/hidden-page.psml' is declared hidden in the page PSML.
The current Profile Locator for the user would specify that the Portal Site Component map the following portal request URLs to the specific PSML elements:
Portal Request URL PSML Element Selected
http://.../jetspeed/portal/page0.psml .../_user/someone/page0.psml
http://.../jetspeed/portal/page1.psml .../page0.psml
http://.../jetspeed/portal/page2.psml Fails security test.
http://.../jetspeed/portal/hidden-page.psml .../hidden-page.psml
The same Profile Locator is used to evaluate menu options. Here are several valid menu options paths and how they are resolved:
Menu Options Page URIs PSML Elements Included in Menu
/page0.psml .../_user/someone/page0.psml
/page0.psml,/page1.psml .../_user/someone/page0.psml,.../page1.psml
/*.psml .../_user/someone/page0.psml,.../page1.psml
/* .../_user/someone/page0.psml,.../page1.psml
/_user/someone/page0.psml Not a valid Page URI.
Notes:
  • Menu options attempting to use invalid Page URIs are ignored. Invalid URIs include those containing reserved folders such as '_user', '_role', etc. or other physical paths specific to the the Page Manager implementation.
  • Security constrained pages or folders cannot be referenced by requests and will not appear in menus.
  • Hidden pages and/or folders can be requested, but are not visible in menus. There is one exception for pages: a hidden page is considered visible if it is the request page.