Two Level Navigation In Plone
Whilst creating full menu systems for site navigation is generally a
bad idea, often there is a need to show one more level in a navigation
system. Such two level systems are actually fairly easy to create with Plone using just a simple change to one template and the clever use of portal_actions
The basic idea
The principle behind this idea is that each sublevel is, effectively, another unordered list that happens to be associated with the top-level list item its within. This trick uses the actions tool, together with markup from APlus, to create two-level navigation in Plone 2.
The markup
The markup we're trying to generate is as follows:
<ul id="portal-globalnav">
<li><a href="#">section 1</a>
<ul>
<li><a href="#">subsection 1-1</a></li>
<li><a href="#">subsection 1-2</a></li>
<li><a href="#">subsection 1-3</a></li>
<li><a href="#">subsection 1-4</a></li>
<li><a href="#">subsection 1-5</a></li>
</ul>
</li>
<li><a href="#">section 2</a></li>
<li class="selected"><a href="#">section 3</a>
<ul>
<li><a href="#">rubsection 3-1</a></li>
<li class="selected"><a href="#">rubsection 3-2</a></li>
<li><a href="#">rubsection 3-3</a></li>
</ul>
</li>
<li><a href="#">section 4</a>
<ul>
<li><a href="#">subsec 4-1</a></li>
<li><a href="#">subsec 4-2</a></li>
</ul>
</li>
</ul>
To achieve this please customise your global_sections template (in portal_skins/plone_templates) and replace it with the following:
2.1.x:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
i18n:domain="plone">
<body>
<!-- THE SECTION TABS DEFINITION -->
<div metal:define-macro="portal_tabs"
tal:omit-tag=""
tal:define="selected_tabs python:here.selectedTabs('index_html', here, portal_tabs);
selected_portal_tab selected_tabs/portal;"
tal:condition="portal_tabs">
<h5 class="hiddenStructure" i18n:translate="heading_sections">Sections</h5>
<ul id="portal-globalnav">
<tal:tabs tal:repeat="tab portal_tabs"><li tal:attributes="id string:portaltab-${tab/id};
class python:test(selected_portal_tab==tab['id'], 'selected', 'plain');">
<a href=""
tal:content="tab/name"
tal:attributes="href tab/url;
title tab/description|nothing">
Tab Name
</a>
<tal:block omit-tag=""
tal:define="sublevel string:portaltab-${tab/id};
subnav actions/?sublevel|nothing;">
<tal:block omit-tag="" tal:condition="subnav">
<ul class="nn-twolevel-subnav">
<tal:tabs tal:repeat="subtab subnav">
<li tal:attributes="id string:portaltab-${subtab/id};">
<a href="" class="" tal:attributes="href subtab/url;" accesskey="accesskeys-tabs" i18n:attributes="accesskey">
<tal:block omit-tag="" i18n:translate="" >
<span tal:replace="subtab/name">Tab Name</span>
</tal:block>
</a>
</li>
</tal:tabs>
</ul>
</tal:block>
</tal:block>
</li></tal:tabs>
</ul>
</div>
</body>
</html>
2.0.x
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US"
i18n:domain="plone">
<body>
<!-- THE SECTION TABS DEFINITION -->
<div metal:define-macro="portal_tabs"
tal:omit-tag=""
tal:define="selected_tabs python:here.selectedTabs(template_id, here);
selected_portal_tab selected_tabs/portal;" >
<h5 class="hiddenStructure" i18n:translate="heading_sections">Sections</h5>
<ul id="portal-globalnav">
<tal:tabs tal:repeat="tab portal_tabs">
<li tal:attributes="id string:portaltab-${tab/id};
class python:test(selected_portal_tab==tab['id'], 'selected', 'plain');">
<a href="" class="" tal:attributes="href tab/url;"
accesskey="accesskeys-tabs" i18n:attributes="accesskey" >
<tal:block omit-tag="" i18n:translate="" >
<span tal:replace="tab/name">Tab Name</span>
</tal:block>
</a>
<tal:block omit-tag=""
tal:define="sublevel string:portaltab-${tab/id};
subnav actions/?sublevel|nothing;">
<tal:block omit-tag="" tal:condition="subnav">
<ul class="nn-twolevel-subnav">
<tal:tabs tal:repeat="subtab subnav">
<li tal:attributes="id string:portaltab-${subtab/id};">
<a href="" class="" tal:attributes="href subtab/url;" accesskey="accesskeys-tabs" i18n:attributes="accesskey">
<tal:block omit-tag="" i18n:translate="" >
<span tal:replace="subtab/name">Tab Name</span>
</tal:block>
</a>
</li>
</tal:tabs>
</ul>
</tal:block>
</tal:block>
</li>
</tal:tabs>
</ul>
</div>
</body>
</html>
The above code generates an unordered list of subtabs for any tab that has them. To add subtabs to a tab (with ID, news say) then create actions in portal_actions as you would normally, but rather than give the actions the category portal_tabs, give it the category portaltab-PARENTTABID. For example, if your tab has ID news, the children of news should have the category portaltab-news.
CSS styling
The above markup should be styled with CSS based on the following:
#portal-globalnav {
position: relative;
}
#portal-globalnav li ul {
background-color: #eee;
width: 100%;
display: block;
visibility: hidden;
position: absolute;
margin: 0;
left: -1.5em;
padding: 0 0 0 1.5em;
border-top: 1px solid #8cacbb;
}
#portal-globalnav li ul li a {
margin: 0;
border-collapse: collapse;
border-style: none solid none none !important;
}
#portal-globalnav li.selected ul, #portal-globalnav li:hover ul, #portal-globalnav li.over ul {
visibility: visible;
}
#portal-globalnav li.selected ul li a, #portal-globalnav li:hover ul li a, #portal-globalnav li.over ul li a{
background-color: #eee !important;
}
#portal-globalnav li.selected ul {
z-index: 10;
}
#portal-globalnav li:hover ul, #portal-globalnav li.over ul { /* lists nested under hovered list items */
z-index: 100;
}
* html #portal-globalnav li.over ul, * html #portal-globalnav li.selected ul {
top: 1.2em;
left: 0;
}
#portal-personaltools {
margin-top: 1.566em;
}
The above CSS moves the personal tool bar down to allow space for the two level navigation and styles the sublevel tabs. It should be adapted to fit your own skin. Please note that in order for this to work in IE, you must have used a hover trick.
I did not used the css above to test it on 2.1.2 rc2 but I used my custom css:
/* The global section tabs. */
#portal-globalnav {
margin: 0 0 0em 0;
position: relative;
}
#portal-globalnav ul {
margin: 0;
padding: 0em;
border: 0;
list-style-type: none;
}
#portal-globalnav li {
margin: 0;
padding: 0 0 0.6em 0;
border: 0;
display: inline;
}
#portal-globalnav li ul {
width: 100%;
display: block;
visibility: hidden;
position: absolute;
left: 0;
}
#portal-globalnav li.selected ul, #portal-globalnav li:hover ul, #portal-globalnav li.over ul {
visibility: visible;
}
#portal-globalnav li.selected ul {
z-index: 10;
top: 2em;
}
#portal-globalnav li:hover ul, #portal-globalnav li.over ul {
z-index: 99;
top: 2em; /* \*/top: 2em;/* */
}
* html #portal-globalnav li.over ul, * html #portal-globalnav li.selected ul {
top: 2em; /* \*/top: 2em;/* */
left: 0;
/* IE5/Mac: \*//*/
top: 1.2em;
/* */
}
#portal-globalnav {
font-size: 10px;
font-weight: bold;
color: #E7EFFF;
background: #000066 url(/images/buttonbg2.gif) repeat-x;
padding: 0.4em 0em;
}
#portal-globalnav a {
color: #ffffff;
text-decoration: none;
padding: 0 10px .6em 10px;
}
#portal-globalnav ul {
color: #000;
background-color: #E7EFFF;
}
#portal-globalnav li {
border-right: 1px solid #9a9faa;
}
#portal-globalnav li ul {
font-weight: normal;
line-height: 2em;
}
#portal-globalnav li ul li {
border-right: 1px dotted #6B96CE;
font-weight: normal;
}
#portal-globalnav li ul a {
color: #3971BD;
}
#portal-globalnav li ul a:hover {
text-decoration: underline;
}
#portal-globalnav li.selected {
color: #000;
background-color: #E7EFFF;
}
#portal-globalnav li.selected a {
color: #000066;
}
#portal-globalnav li:hover, #portal-globalnav li.over {
color: #000;
background-color: #fc6;
}
#portal-globalnav li:hover ul, #portal-globalnav li.over ul {
background-color: #fc6;
}
#portal-globalnav li:hover a, #portal-globalnav li.over a {
color: #000;
}
#portal-globalnav li a:hover {
text-decoration: underline;
}
I have tested my site http://zicklin.baruch.cuny.edu with IE, Firefox, Netscape, Opera and Safari.
