In the legacy Portal theme used on Administration pages there is a side navigation available. In this article we will discuss taking a similar approach in the Portal 7.0.0.2 theme by creating a new dynamic-content spot that will render a side navigation using the navigation JSP tags. This example will create a basic side navigation structure that replaces the secondary navigation and can extended to accommodate more complex designs.
Create the Side Navigation JSP
1. Create a file named sideNav.jsp
2. Use this code as the contents of the file:
<%@ page session="false" buffer="none" %>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ include file="../includePortalTaglibs.jspf" %>
<portal-core:constants/><portal-core:defineObjects/>
<portal-navigation:navigation startLevel="3">
<% int previousNavLevel=0;%>
<portal-navigation:navigationLoop>
<% boolean isNodeSelected = wpsSelectionModel.isNodeSelected(wpsNavNode);
boolean nodeHasChildren = wpsNavModel.hasChildren(wpsNavNode);
boolean isExpanded = ((Boolean)((com.ibm.portal.state.StateModel)wpsNavModel).getState(wpsNavNode,
com.ibm.portal.state.StateType.EXPANSION)).booleanValue();
boolean isLabel = com.ibm.portal.content.ContentNodeType.LABEL.equals(wpsNavNode.getContentNode().getContentNodeType());
int currentNavLevel = wpsNavLevel.intValue(); %>
<c:set var="sideNavItemTitle"><portal-fmt:title/></c:set>
<%-- ****************** open/close nav levels ****************** --%>
<c:choose>
<%-- new unordered list is created when current nav level is higher than previous nav level--%>
<c:when test="<%=currentNavLevel > previousNavLevel%>">
<% for(int i = currentNavLevel; i > previousNavLevel; i--){%>
<ul>
<%} %>
</c:when>
<%-- unordered list is closed and list item that the list is placed inside is also closed--%>
<c:when test="<%=currentNavLevel < previousNavLevel %>"><% for(int i = currentNavLevel; i < previousNavLevel; i++){%>
</ul></li>
<%} %>
</c:when>
</c:choose>
<li>
<span>
<%-- ****************** render expand/collapse ****************** --%>
<c:choose>
<c:when test="<%=nodeHasChildren && isExpanded %>">
<a href='<portal-navigation:navigationUrl type="collapse"/>'>-</a>
</c:when>
<c:when test="<%=nodeHasChildren && !isExpanded %>">
<a href='<portal-navigation:navigationUrl type="expand"/>'>+</a>
</c:when>
<c:otherwise>
<img alt="" src="<%=wpsBaseURL%>/images/dot.gif" />
</c:otherwise>
</c:choose>
<%-- ****************** render node ****************** --%>
<c:choose>
<c:when test="<%=isLabel%>">
<span><c:out value='${sideNavItemTitle}' escapeXml='true' /></span>
</c:when>
<c:otherwise>
<a <%if(isNodeSelected){%>class="wpthemeSelected" <%}%>href='<portal-navigation:navigationUrl type="launch"/>' >
<c:out value='${sideNavItemTitle}' escapeXml='true' />
</a>
</c:otherwise>
</c:choose>
</span>
<c:if test="<%=(!nodeHasChildren || !isExpanded)%>">
</li>
</c:if>
<%previousNavLevel = currentNavLevel;%>
</portal-navigation:navigationLoop>
<c:if test="<%=previousNavLevel > 0 %>">
<% for(int i = previousNavLevel; i > 1; i--){%>
</ul></li>
<%} %>
</ul>
</c:if>
</portal-navigation:navigation>
3. Deploy this JSP to Portal within a WAR file.
Note:
Dynamic-content spots can be shared across themes, so it is not required to deploy the JSP to the theme WAR where Default.jsp is located. It can be deployed in a WAR that just includes JSPs for dynamic-content spots if desired.
Create the Side Navigation Dynamic-content Spot Definition
1. Login to the WAS console
2. Go to: Resources > Resource Environment > Resource environment providers > WP DynamicContentSpotMappings
3. Select "Custom Properties" on the right side of the panel
4. Select "New"
5. Enter "7002theme_sideNav" as the name and enter the URI of where the "sideNav.jsp" file is located.
Example:
res:/someContextRoot/staticResources/sideNav.jsp
6. Select OK
7. Save the changes
8. Restart Portal
Update the theme
1. Open the theme template, for this example the default theme template shipped for the Portal 7.0.0.2 theme on WebDAV will be referenced. The localized template is located here:
/fs-type1/themes/Portal7.0.0.2/nls/
2. Remove the secondary navigation dynamic-content spot from the theme template, highlighted in bold:
<div class="wpthemeSecondaryBanner">
<div class="wpthemeInner">
<a rel="dynamic-content" href="dyn-cs:id:7002theme_secondaryNav"></a>
<a rel="dynamic-content" href="dyn-cs:id:7002theme_search"></a>
<div class="wpthemeClear"></div>
</div>
</div><!--end secondary banner-->
3. Replace the main content area of the theme template (wpthemeMainContent) to add the new sidenav dynamic-content spot and rearrange some other elements:
<div class="wpthemeMainContent">
<a rel="dynamic-content" href="dyn-cs:id:7002theme_crumbTrail"></a>
<div class="wpthemeClear"></div>
<div class="wpthemeSideNavigation wpthemeLeft">
<a rel="dynamic-content" href="dyn-cs:id:7002theme_sideNav"></a>
</div>
<!-- required - do not remove -->
<a rel="dynamic-content" href="state.portlet:portlet?include=windowState&include=portletMode&mime-type=text/html"></a>
<div id="layoutContainers" class="wpthemeLayoutContainers wpthemeLayoutContainersHidden wpthemeLeft" role="main">
<div id="wpthemeStatusBarContainer"></div>
<a rel="dynamic-content" href="dyn-cs:id:7002theme_layout"></a>
<div class="wpthemeClear"></div>
</div>
<div class="wpthemeClear"></div>
</div><!--end main content-->
Note: Perform steps 2 & 3 for all of the localized templates that are utilized, i.e. theme_en.html
4. Styles are used to create 2 columns in the main content area, one for the side navigation and the other for the page contents. The width's are arbitrary and can be adjusted to your desired value. If you modify the values and the columns wrap, check to see that margin is accounted for. Place these styles in the style sheet used by the theme:
.wpthemeLayoutContainers {width: 79%;}
.wpthemeSideNavigation{width:17%;}
.wpthemeSideNavigation .wpthemeSelected {font-weight: bold;}
.wpthemeSideNavigation ul {list-style-type: none;}
You now should have a basic side navigation rendering in your theme.
Note:
This example will not work for bi-directional languages, but the code can be extended to render correctly if desired.
Using images for the expand and collapse controls
In this example, the expand control is a plus character and the collapse control is a dash character. These controls can be modified to use images if desired. In the example below, the images are "minus.gif" and "plus.gif", these would be located in a folder called "icons" that is a peer to the sideNav.jsp.
Example:
<%-- ****************** render expand/collapse ****************** --%>
<c:choose>
<c:when test="<%=nodeHasChildren && isExpanded %>">
<a href='<portal-navigation:navigationUrl type="collapse"/>'>
<img alt="<portal-fmt:text key='link.collapse' bundle='nls.engine'/>"
title="<portal-fmt:text key='link.collapse' bundle='nls.engine'/>"
src="<portal-logic:urlFindInTheme file='icons/minus.gif' />">
</a>
</c:when>
<c:when test="<%=nodeHasChildren && !isExpanded %>">
<a href='<portal-navigation:navigationUrl type="expand"/>'>
<img alt="<portal-fmt:text key='link.expand' bundle='nls.engine'/>"
title="<portal-fmt:text key='link.expand' bundle='nls.engine'/>"
src="<portal-logic:urlFindInTheme file='icons/plus.gif' />">
</a>
</c:when>
<c:otherwise>
<img alt="" src="<%=wpsBaseURL%>/images/dot.gif" />
</c:otherwise>
</c:choose>