In some designs you may have only one menu that lists the entire site hierarchy while in other designs there may be multiple menus to structure the display of the site hierarchy into different groupings such has having a horizontal tab style menu at the top that only shows top level pages and a vertical sub-menu that shows child pages below the top level. We include a variety of skins with mojoPortal and in the extra-skins.zip download that we update for each release to illustrate the possibilities. You can study the layout.master file of the included skins to learn how to configure various menu possibilities. It is not always immediately obvious what the menu structure of the included skins is capable of because to see it you often have to create a site hierarchy of pages that shows the different levels.
Skins That Use a Single Menu
Examples of skins that use a single menu are jqueryui-1 which uses a Superfish menu for the entire site hierarchy, and mitchinson-earthy, mitchinson-earthy-alt1. Some of the Artisteer skins also use a single menu such as artisteer-greenlagoon and artisteer-flashclouds.
Skins That Use Two Menus
There are quite a few skins that illustrate this common pattern where we have a top level menu that shows only root level pages (often styled as tabs), and then there is a vertical menu for child pages below the top level pages, usually configured as a TreeView that can expand to show the rest of the site hierarchy. All of the dcarter and styleshout skins use this approach. Some of the Artisteer skins such as artisteer-verticalmenu1 and artisteer-verticalmenu2 also use this approach
Skins That Use Three Menus
The andreasvicklund-02 skin implements two levels of horizontal tabs and then a vertical treeview for pages below the top two levels.
Skins That Use Four Menus
The andreasvicklund-02-alt1 is almost identical to andreasvicklund-02 except it uses three levels of horizontal tabs instead of two, and then uses a vertical treeview menu for pages deeper than that. It also illustrates using a slide show in the header.
SiteMenu and PageMenu
When you study the layout.master file of skins that use multiple menus you will see that all skins use the SiteMenu control for the topmost menu and then use PageMenu controls for additional menu levels. The functionality of SiteMenu and PageMenu is almost identical today but they evolved differently. PageMenu was developed the first time that we implemented a skin with two menus and it was designed for showing the child pages below the pages in the SiteMenu which would be configured to show only one top level of pages. Over time both SiteMenu and PageMenu have evolved to be very similar and to meet a variety of configuration needs. Probably if I were starting the project from scratch today I would have implemented just one control but once you have shipped a product and people are using it you have to consider upgrades and not breaking anything for existing sites, so we have continued using both controls.
You can have up to four menus, for the topmost menu you should use SiteMenu and for all others, you should use PageMenu. The IDs used on the controls are also important. SiteMenu should have the ID "SiteMenu1", and the PageMenu control(s) can be "PageMenu1", "PageMenu2", and "PageMenu3". These IDs are important because they are used to hide the menu when they have no data. For example, if a top-level page has no child pages then the PageMenu will not be displayed when you visit that page.
Each menu also uses a SiteMapDataSource which must be present also in layout.master. Shown below is a complete set of four menus and their SiteMapDataSource controls as illustrated in andreasvicklund-02-alt1.
Note that the SiteMapDataSource controls should be the first thing inside the <form in layout.master.
<asp:SiteMapDataSource ID="SiteMapData" runat="server" ShowStartingNode="false" />
<asp:SiteMapDataSource ID="PageMapDataSource" runat="server" ShowStartingNode="false" />
<asp:SiteMapDataSource ID="level3datasource" runat="server" ShowStartingNode="false" />
<asp:SiteMapDataSource ID="level4datasource" runat="server" ShowStartingNode="false" />
<portal:SiteMenu id="SiteMenu1" runat="server" UseTreeView="false" HideMenuOnSiteMap="false" Direction="Horizontal" TopLevelOnly="true"></portal:SiteMenu>
<portal:PageMenu id="PageMenu1" runat="server" UseTreeView="false" Direction="Horizontal" DynamicDisplayLevels="0" />
<portal:PageMenu id="PageMenu2" runat="server" UseTreeView="false" Direction="Horizontal" SiteMapDataSource="level3datasource" StartingNodeOffset="2" DynamicDisplayLevels="0" />
<portal:PageMenu id="PageMenu3" runat="server" SiteMapDataSource="level4datasource" UseTreeView="true" StartingNodeOffset="3" TreeViewShowExpandCollapse="true" MenuSkinID="PageMenu3" />
Note that the Direction setting does not really control the direction but it does control the CSS class used on the container and the CSS is what makes a menu horizontal or vertical.
The CSS Classes and other properties for the Menu or TreeView controls used by SiteMenu and PageMenu can be configured from the theme.skin file. Note that the SkinID is used in theme.skin to differentiate different menus that need to be configured differently. By default, the SiteMenu has the SkinID "SiteMenu" and typically you won't have any need to change that. The PageMenu by default uses the SkinID "PageMenu", however, if you have more than one PageMenu and you need to configure them differently you can specify the MenuSkinID property on PageMenu and then use that as the SkinID in theme.skin.
Interesting Properties of SiteMenu
Under the hood both SiteMenu and PageMenu use either mojoMenu or mojoTreeView controls, so it is these controls that you configure from the theme.skin file. But some properties are set directly on SiteMenu and PageMenu.
mojoTreeView and mojoMenu both render as a list of ul and li elements, so in practice, you could choose either one for any menu scenario. However, mojoTreeView has some capabilities that are useful for large site hierarchies because it supports populate on demand. For example, if your site has thousands of pages, you would not want all of the nested ul and li elements to render in the page because that would be a lot of markup and would make the page very heavy and slow down the load time of the page. Instead, you would use mojoTreeView with populate on demand enabled so that only top-level items would render and as you drill down through the menu it renders the child elements on demand as needed. For sites that don't have a huge hierarchy, you might prefer to have all the items render at once. Dynamic flyout menus like Superfish or the horizontal menus in Artisteer skins need all the elements to be rendered in the markup in order to produce the flyout effects by showing and hiding items based on mouse over activity.
Tip: Don't Get Carried Away With Trying to Reduce Markup or Content
You might think from the above that you should always try to optimize and use TreeView and PopulateOnDemand to make your pages lighter. This is wrong thinking, remember that the fastest lightest page will have no content at all, but the content is king, it is what people come to your site for. If your site does not have thousands of pages, consider that there may be some SEO (Search Engine Optimization) value in having those internal links in the menu.
UseTreeView (true or false) controls whether mojoMenu or mojoTreeView is used.
Used For Both mojoTreeView and mojoMenu
Used For TreeView Only
Used only For mojoMenu
Interesting Properties of PageMenu
PageMenu is similar to SiteMenu and setting information shown above applies but there are some minor differences.
StartingNodeOffset default is 0, can be used to set the starting depth of a menu. Used to make it show child pages starting at a specific depth. Note that 0 is used for the first level of child pages as shown in the example above from the andreasvicklund-02-alt1 skin.
IsSubMenu true by default because page menu is designed to show child pages. In Artisteer designs, it is fairly common to have a vertical menu that mirrors the main menu rather than acting as a sub menu. If that is what you want you can set this to false. To me, it seems unnatural to duplicate the menu and more natural to use a sub menu for secondary menus.