Customize the Plone 3 navigation.
Purpose
The portal navigation is a great feature of Plone and fits for most needs. But sometimes, you may need a more 'classic' website navigation. This is a short guide how you may do this.
See on the right side how the navigaton will/should look like when you are finished
(of course, colors can be customized :-) ).
Prerequisities
You need to have a few knowledge of how to customize plone portlets and views in the Zope 3 manner. If you have no idea how this works, the book of Martin Aspeli "Professional Plone Develoment" or further documentation on plone.org is strongly recommand.
Furthermore, the way how we customized the navigaton may not be "best practice". It's just one way how you can create a website navigation for Plone. Feel free to make other propositions.
Step by step
This are the steps you need to do:
- Customize the templates navigation.pt and navigation_recurse.pt.
- Customize your stylesheet main.css or modify the stylesheet you registered.
1. Customize the navigation templates
The navigation of Plone 3 has been modified. It's now build in the Zope 3 way. This meens that you have to add a few lines in your browser/configure.zcml to customize the navigation templates.
browser/configure.zcml:
(...)
<plone:portlet
name="mediamit.Navigation"
interface="plone.app.portlets.portlets.navigation.INavigationPortlet"
assignment="plone.app.portlets.portlets.navigation.Assignment"
renderer=".navigation.Renderer"
addview="plone.app.portlets.portlets.navigation.AddForm"
editview="plone.app.portlets.portlets.navigation.EditForm"
/>
<plone:portletRenderer
portlet="plone.app.portlets.portlets.navigation.INavigationPortlet"
layer=".interfaces.IThemeSpecific"
template="templates/navigation.pt"
/>
(...)
This presumes that your templates are installed in browser/templates/.
Copy the navigation view navigation.py from plone/app/portlets/portlets/ to your browser/ folder and overwrite the Renderer class.
browser/navigation.py:
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone.app.portlets.portlets import navigation
class Renderer(navigation.Renderer):
"""Modification of the Navigation templates"""
_template = ViewPageTemplateFile('templates/navigation.pt')
recurse = ViewPageTemplateFile('templates/navigation_recurse.pt')
Copy navigation.pt and recure_navigation.pt from plone/app/portlets/portlets/ to your browser/ folder and first make the following changes to navigation.pt:
- add a id attribute portlet-navigation to the first dl tag. This is nessessary to decouple navigation styles from the rest of the Plone standard styles.
- Your may delete the portletHeader tag but we prefere to add a display:none instruction later on in the stylesheets.
- You have to delete the <img /> tags, so that no icon are shown up even if you want the user to see the icons elsewhere.
browser/templates/navigation.pt:
<tal:block i18n:domain="plone">
<dl id="portlet-navigation"
class="portlet portletNavigationTree"
tal:define="root view/navigation_root">
<dt class="portletHeader">
<span class="portletTopLeft"></span>
<a href="#"
class="tile"
tal:condition="not:view/title"
tal:attributes="href string:${root/absolute_url}/sitemap"
i18n:translate="box_navigation">Navigation</a>
<a href="#"
class="tile"
tal:condition="view/title"
tal:attributes="href string:${root/absolute_url}/sitemap"
tal:content="view/title">Navigation</a>
<span class="portletTopRight"></span>
</dt>
<dd class="portletItem lastItem">
<ul class="portletNavigationTree navTreeLevel0">
<li class="navTreeItem"
tal:condition="view/include_top">
<div tal:define="selectedClass view/root_item_class;
rootIsPortal view/root_is_portal;">
<a tal:attributes="href root/absolute_url;
title root/Description;
class selectedClass">
<!-- (or delete it)
<img src="" height="16" width="16" alt=""
tal:condition="view/root_icon"
tal:attributes="src view/root_icon" />
-->
<span tal:omit-tag=""
tal:condition="rootIsPortal"
i18n:translate="tabs_home">Home</span>
<span tal:condition="not:rootIsPortal"
tal:replace="root/Title">Root item title</span>
</a>
</div>
</li>
<li tal:replace="structure view/createNavTree">
SUBTREE
</li>
</ul>
<span class="portletBottomLeft"></span>
<span class="portletBottomRight"></span>
</dd>
</dl>
</tal:block>
Add a new class attribute item in navigation_recurse.pt. We also need it for the stylesheets.
browser/templates/navigation_recurse.pt:
<tal:master define="level options/level|python:0;
children options/children | nothing;
bottomLevel options/bottomLevel | nothing;"
i18n:domain="plone">
<metal:main define-macro="nav_main">
<tal:navitem repeat="node children">
<li tal:define="show_children node/show_children;
children node/children;
item_url node/getURL;
item_icon node/item_icon;
remote_url node/getRemoteUrl;
link_remote node/link_remote;
is_current node/currentItem;
is_in_path node/currentParent;
li_class python:is_current and ' navTreeCurrentNode' or '';
li_extr_class python:is_in_path and ' navTreeItemInPath' or '';
li_folder_class python:show_children and ' navTreeFolderish' or '';"
tal:attributes="class string:navTreeItem visualNoMarker${li_class}${li_extr_class}${li_folder_class}"
tal:condition="python:bottomLevel <= 0 or level <= bottomLevel">
<tal:level define="item_class string:state-${node/normalized_review_state}">
<div class="item"
tal:define="item_class python:is_current and item_class + ' navTreeCurrentItem' or item_class" >
<a tal:attributes="href python:link_remote and remote_url or item_url;
title node/Description;
class string:$item_class${li_class}${li_extr_class}${li_folder_class}">
<span tal:content="node/Title">Selected Item Title</span>
</a>
</div>
<ul tal:attributes="class python:'navTree navTreeLevel'+str(level)"
tal:condition="python: len(children) > 0 and show_children">
<span tal:replace="structure
python:view.recurse(children=children, level=level+1, bottomLevel=bottomLevel)" />
</ul>
</tal:level>
</li>
</tal:navitem>
</metal:main>
</tal:master>
That's all for the templates. Perhaps someone will find a better solution to customize the navigation without changing the navigations templates. This would be much smarter but so far we could not find a better solution.
2. Customize the stylesheets
Next step is to customize the stylesheets. You may put a main.css in your stylesheets folder (usualy browser/stylesheets/) or change it in your skin folder (i.e. skins/myproject/myproject_styles/navigation.css) .
browser/stylesheets/main.css:
(...)
/* ============================================== */
/* NAVIGATION */
/* ============================================== */
/* Customized Portlet-Style */
#portlet-navigation {
background-color:white; !important;
}
#portlet-navigation .portletHeader {
display:none;
}
#portlet-navigation .portletItem {
padding:0;
}
#portlet-navigation ul,
#portlet-navigation li {
margin:0px !important;
padding:0px !important;
line-height: 1.8em !important;
}
#portlet-navigation a {
border:none !important;
}
#portlet-navigation a:hover {
border:none !important;
background-color:transparent;
}
#portlet-navigation .item {
border-bottom:2px solid white;
}
/* --- here is the best place for customization ---- */
.navTreeLevel0 { background-color:#ffdd00; }
.navTreeLevel1 { background-color:#ffdd33; }
.navTreeLevel2 { background-color:#ffdd66; }
.navTreeLevel3 { background-color:#ffdd99; }
.navTreeLevel4 { background-color:#ffddcc; }
.navTreeLevel5 { background-color:#ffddff; }
.navTreeLevel0 .navTreeItemInPath { background-color:#dddd00; font-weight:bold}
.navTreeLevel1 .navTreeItemInPath { background-color:#dddd33; font-weight:bold}
.navTreeLevel2 .navTreeItemInPath { background-color:#dddd66; font-weight:bold}
.navTreeLevel3 .navTreeItemInPath { background-color:#dddd99; font-weight:bold}
.navTreeLevel4 .navTreeItemInPath { background-color:#ddddcc; font-weight:bold}
.navTreeLevel6 .navTreeItemInPath { background-color:#ddddff; font-weight:bold}
.navTreeLevel0 a { margin-left: 10px !important; font-weight:normal;}
.navTreeLevel1 a { margin-left: 20px !important; font-weight:normal;}
.navTreeLevel2 a { margin-left: 30px !important; font-weight:normal;}
.navTreeLevel3 a { margin-left: 40px !important; font-weight:normal;}
.navTreeLevel4 a { margin-left: 50px !important; font-weight:normal;}
.navTreeLevel5 a { margin-left: 60px !important; font-weight:normal;}
.navTreeLevel0 a:hover {
margin-left: 0px; padding-left:10px; background-color:#ffcc00 !important;}
.navTreeLevel1 a:hover {
margin-left: 0px; padding-left:20px; background-color:#ffcc33 !important;}
.navTreeLevel2 a:hover {
margin-left: 0px; padding-left:30px; background-color:#ffcc66 !important;}
.navTreeLevel3 a:hover {
margin-left: 0px; padding-left:40px; background-color:#ffcc99 !important;}
.navTreeLevel4 a:hover {
margin-left: 0px; padding-left:50px; background-color:#ffcccc !important;}
.navTreeLevel5 a:hover {
margin-left: 0px; padding-left:60px; background-color:#ffccff !important;}
.navTreeLevel0 a.navTreeCurrentItem {
margin-left: 0px !important; padding-left:10px; background-color:#ffcc00;
color:white !important; font-weight:bold;}
.navTreeLevel1 a.navTreeCurrentItem {
margin-left: 0px !important; padding-left:20px; background-color:#ffcc33;}
.navTreeLevel2 a.navTreeCurrentItem {
margin-left: 0px !important; padding-left:30px; background-color:#ffcc66;}
.navTreeLevel3 a.navTreeCurrentItem {
margin-left: 0px !important; padding-left:40px; background-color:#ffcc99;}
.navTreeLevel4 a.navTreeCurrentItem {
margin-left: 0px !important; padding-left:50px; background-color:#ffcccc;}
.navTreeLevel5 a.navTreeCurrentItem {
margin-left: 0px !important; padding-left:60px; background-color:#ffccff;}
That's it! Play around with the colors, font-size and font-weight.
Instead of using background-color, you may also use background-images.
Feel free to commend this How-to.

Author: