Вы находитесь на странице: 1из 63

6.

0 Theme and Skin Development


By Ryan Wilson and Jim Barnes
rywilson@us.ibm.com, jwbarnes@us.ibm.com
This edition applies to version 6, release 0, modification 0 of WebSphere_Portal (product number
6.0.0.0) and to all subsequent releases and modifications until otherwise indicated in new
editions.

© Copyright International Business Machines Corporation 1996, 1999. All rights reserved.
US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP
Schedule Contract with IBM Corp.

Special Thanks to William Trotman and Morgan Kinne for valuable help in preparing this
document.
Table of Contents
Chapter 1 - Theme and skins basics.....................................................................................4
JSP files for themes......................................................................................................... 5
JSP files for portlet layout and rendering........................................................................6
JSP files used for stylesheets...........................................................................................6
JSP files used for JavaScript........................................................................................... 7
Additional JSP files used by the portal theme................................................................ 8
Tags used by portal JSPs.................................................................................................9
Special Notes:................................................................................................................11
Chapter 2 – Theme policy..................................................................................................12
Exporting and updating a theme policy........................................................................ 14
Adding custom policy attributes................................................................................... 16
Accessing standard theme policy attributes.................................................................. 18
Chapter 3 – Color palette................................................................................................... 20
Creating the palette....................................................................................................... 20
Assigning the palette to a page......................................................................................21
Referencing a color palette in CSS............................................................................... 21
Chapter 5 – Flyouts and context menus.............................................................................37
Flyouts...........................................................................................................................37
Context menus...............................................................................................................39
Chapter 6 – Development tools..........................................................................................42
Chapter 7 – Migrating to version 6.0 from version 5.1..................................................... 45
Adding drag and drop ...................................................................................................45
Considerations when migrating.....................................................................................49
Appendix A – Changing properties of the flyout...............................................................51
Appendix B – Removing unwanted space......................................................................... 54
Appendix C – Drop down navigation example ..............................................................55
Appendix D – Right navigation example ....................................................................57
Notices............................................................................................................................... 58
Chapter 1 - Theme and skins basics

Before you start coding your new custom theme and skin, get an understanding of how all the
parts of the version 6.0 themes fit together. If this is the first time you are looking at customizing
themes for Portal you can get confused by what each JSP and JSPF will do for the overall portal
and what is appropriate to add to a JSP.

NOTE: Avoid customizing the Out of the Box provided theme. It is best practice to copy
the IBM directory, and then giving it your own name and use that for your sample. Also it
is best to only assign it to a page and not the whole portal while doing development on it.

In this article we have included a theme and a skin that gives you the same theme and skin as
shown above in your own portal environment. This process is best done on a stand-alone test
environment and is not intended for a clustered configuration. To install, simply extract the zip
files using a zip utility or the jar command into the following locations.

For themes:
profiles/wp_profile/installedApps/nodename/wps.ear/wps.war/themes/html/

For skins:
profiles/wp_profile/installedApps/nodename/wps.ear/wps.war/skins/html/

Use the provided XML file (install_whitepaper.xml) to install the themes and skins and sample
pages into your portal.
This installation creates a tab labeled White Paper, with pages under it with several example
themes and skins to go along with the white paper.

After the installation is complete, open the page in your browser to display the screen capture
shown above. This page lets you see what part of the overall markup is coming from which JSPs.
You will also be able to see how they all fit together on the page to make one finished HTML
document.
Note: This sample is best viewed with the Firefox browser.

Consider that the theme is going to control the look and feel of your portal, and the navigation
throughout the site. The rest of the layout of the portal page, which includes how the portlets
exist in relation to each other, is controlled by the default skin for that theme.

The look and feel of the portlet itself, is controlled by the skin you have configured for that
portlet. If no skin is configured, the portlet renders the default skin. If you select a skin for a
portlet, not all of its JSPs are called. Only the control.jsp file is called for that skin to
render that portlet. This limitation allows these files to change their rendering based on any
theme extensions.

JSP files for themes


Default.jsp
This file is the JSP that renders the portal page after the portal servlet has completed its
initial preprocessing. This JSP includes numerous other JSPs, JSPFs, and, tag lib
definitions. This file also calls the js.jsp and the styles.jsp files, so that they
are compiled and the styles and JavaScripts can include JSP logic to change the behavior
of the portal dynamically.

Head.jspf
This fragment is called to set up the header area of the page. Theme extensions
implementing the MetaTagDataItems are included in at this time. Several JNDI look up
operations are performed in this JSPF file. This file also sets up links to the JavaScript
and styles JSP files. Additionally this jspf set up some of the resources needed for the
flyouts, and get other variables ready for the main menu (Launch Button).
Banner.jspf
This fragment is the first visible JSP fragment to be included in the portal. It represents
the top layer of the page and it holds the launch button, the breadcrumb trail, the search
control, and the toolbar JSPF files.

TopNav.jspf
This fragment controls the look and feel of the top navigational bar. This bar can be one
or two layers, depending on the theme policy selected. Edit this JSP file if you want to
create a drop-down navigational structure. This JSPF file also holds logic to render the
context menus for the page.

SideNav.jspf
This fragment controls the side navigation, and only has visible content if needed. This
page also has logic to expand and contract the child pages and build the context menus
for the pages.
Footer.jspf
The final fragment is the footer and it holds the normal footer information for page
navigation and quick links to other pages for the users.

JSP files for portlet layout and rendering


The container JSP files are called from the default skin for them to lay the portlets in columns and
rows. The skin selected for the portlet does not affect the stacking of the portlets into columns or
rows. It is always the default skin for the theme that holds the container JSP files which control
the layout of rows and columns. If the default skin does not contain these JSP unlayered
containers as listed below, then the aggregation engine pulls them from the base skin/html
directory.

UnlayeredContainer-V.jsp
This JSP file controls the vertical columns for the portlets and how they are arranged
within that column. The tags in the JSP file help control the drag-and-drop feature.

UnlayeredContainer-H.jsp
This JSP file controls the horizontal appearance of the portlets. This file can contain the
UnlayeredContainer-V.jsp.

Control.jsp
This JSP file controls the look and feel of the portlet itself. It renders the menu items, the
title bar, and the table that holds the portlet content. It also provides drag-and-drop
handles for moving the portlet around on the portlet page.

These files contain references back to the theme to maintain the same look and feel, which
include images and colors. The files that are containers(UnlayeredContainer-V.jsp, and
UnlayeredContainer-H.jsp are used to render the rows and columns, In the image above for
example you can see that there is one row, rendered by UnlayeredContainer-H.jsp with two
columns with both being rendered by UnlayeredContainer-V.jsp. These rows and columns
correspond to the layout from the edit layout page of the administration portlet. So for each
column or row you will have separate rendering of the above files.

JSP files used for stylesheets


In version 6.0, there is one JSP file that is called and is compiled based on various items
from the request, theme policy, and color palette.
Styles.jsp
This file is the main JSP file that is called when included in the theme. It is empty
of any real content and includes the following JSPF files:
styles_cacheSettings.jspf, styles_rules.jspf,
styles_theme.jspf, styles_portlet.jspf,
styles_help.jspf, styles_oob.jspf, styles_ibm.jspf,
styles_palette.jspf, styles_extensions.jspf

The JSPF files control the style declarations for the following pieces.
styles_cacheSettings.jspf - Declares how long the cascading stylesheet (CSS) files
should be cached for. This file is used to improve performance on the browser side so
that it does not have to constantly request this resource.
styles_extensions.jspf – Loops through and pulls any theme extension pieces styles.
styles_help.jspf – Styles for help related text and controls.
styles_ibm.jspf – Styles used for admin portlets, which generally should not be changed.
styles_oob.jspf – Styles for portlets and controls that are ready to use as is.
styles_palette.jspf – Styles used for the palettes and drop-down controls.
styles_portlet.jspf – Styles used for portlets that follow the WSRP portlet standard.
styles_rules.jspf – Styles used for browser and locale-specific CSS files. All CSS JSP
files should include this one file.
styles_theme.jspf – Styles used in the base theme and in the drag-and-drop tags.

JSP files used for JavaScript


The themes and skins in version 6.0 make extensive use of JavaScript. Be careful when
adding your own JavaScript so that there are no collisions with the already existing
JavaScript in the theme. Like the other parts of portal, there is one main JavaScript file
which includes several other JavaScript files.
js.jsp
This JSP file includes the following files:
js_cacheSettings.jspf, AsynchronousContextMenu.js,
browserDimensions.js,
ElementJavascriptEventController.js, flyout.js,
js_extensions.jspf

These files do the following.


js_cacheSettings.jspf –Similar to the cache settings file for stylesheets, this file allows
the JavaScript files to be cached by the browser instead of requiring it to be reloaded on
every request.
AsynchronousContextMenu.js – This file is used for the context menus that portal
renders (such as from the portlet drop-down and the theme drop-down controls.) This file
should not be modified.
browserDimensions.js –Determines the browser window size for such elements as
flyouts.
ElementJavascriptEventController.js –Contains helper methods for the other
JavaScript files which should not be modified.
flyout.js –Contains methods that control the speed and look of the flyouts used in portal.
Take care when modifying these controls.
js_extensions.jspf –Searches for and loads any theme extensions that are present. Any
custom extensions that you have created that implement the JavascriptItems
interface are pulled in.

Adding items to the onload


In the course of your theme or portlet development you might want to add items to the
onLoad() event of the page. The default themes make extensive use of this event. A
better approach is to use an addEvent method and add items to the onLoad() event.
For example:

if (window.addEventListener) //DOM method for binding an event


window.addEventListener("load", methodName(), false)
else if (window.attachEvent) //IE exclusive method for binding an
event
window.attachEvent("onload", methodName())

Additional JSP files used by the portal theme


flyout.jspf
This file renders the flyouts for the dynamic menus used by the portal. Take care
when modifying this file.
head_pageMenu.jspf
This file renders the launch button and should not be modified. To add pages to
the Main Menu, create pages at the first level underneath Content Root. All Pages
are picked up by default there. To have pages not visible that are created at this
level, s
et the hidden flag for the page parameter for the content-node tag in XML.
Note: You can still view and work with pages that are marked as hidden in
Administration portlets. You can also create a direct URL to the hidden page so
that the page can be accessed from other areas of the site, such as the page menu.
You can use the following XML snippet:
<content-node action="update" ...>
....
<parameter name="com.ibm.portal.Hidden" type="string"
update="set"><![CDATA[true]]></parameter>
...
</content-node>

Or you can use personalization rules to hide pages. See the information center for
details about.
http://publib.boulder.ibm.com/infocenter/wpdoc/v6r0/index.jsp?topic=/com.ibm.
wp.ent.doc/wps/gs_visibilityrules.html

pageContextMenu.jsp, portletContextMenu.jsp
These files render the page and portlet context menus that you see as drop-down
controls. These files should not be modified.

Tags used by portal JSPs


When creating your own theme, the most commonly used JSP tags used are the <portal-
navigation/> tags. These tags should not be used in portlets and are reserved for use only inside
the themes and skins.
Navigational tags
<portal-navigation:navigation> - This tag is used to set up parameters for the navigation tags.
Mainly you pass in the start and stop level for the navigation loop, being if you want it to start at
navigation level 2, and stop at navigation level 3 it will render the first level of navigation under
portal home. Such that you will see all the pages, labels, and urls from that level..

<portal-navigation:navigationLoop> - This tag always occurs inside the <portal-


navigation:navigation> tag. It loops through the navigation levels specified in the navigation tag
above and displays the markup contained in the loop for each node that is pulled out. This would
be the markup that exists between the begin and end tags. This body of this tag should contain
your markup for creating the links to the page and for calling the context menus for the page if it
is within the selection path. See the existing sidenav.jspf for more information on what the body
of this tag should include.

<portal-navigation:navigationShift by="number" maxPages="number"> - This tag is


available for shifting between visible pages, so that if you are currently showing the first five
pages, you can scroll over however many pages you have specified. If the tag is not used then all
pages are shown for that current level of navigation.

An example of this tag’s usage is:

<portal-navigation:navigationShift by="-5" maxPages="6">

<portal-logic:if pageAvailablePrevious="yes">
<td class="wpsUnSelectedPage">
<a href="<portal-skin:urlParent />"> - </a>
</portal-logic:if>
<portal-logic:if pageAvailablePrevious="no">
<td class="wpsUnSelectedPage">
</portal-logic:if>
</portal-navigation:navigationShift>
<portal-navigation:navigationShift by="+5" maxPages="6">
<portal-logic:if pageAvailableNext="yes">
<a href='<portal-skin:urlParent/>'> + </a>
</td>
</portal-logic:if>
<portal-logic:if pageAvailableNext="no">
</td>
</portal-logic:if>
</portal-navigation:navigationShift>

To use this example, you will also have to add this tag lib to the default.jsp file:
<%@ taglib
uri="http://www.ibm.com/xmlns/prod/websphere/portal/v6.0/portal-skin"
prefix="portal-skin" %>

<portal-navigation:navigationUrl type="link|expand|collapse|launch"
varname="node_name" var="variable_name"/> - This tag is always used within the
navigation loop tags to render links to various navigation nodes. Link and Launch are very
similar, the other two are used when that page has a child node and you want to expand the list to
see the child nodes. To create the link you would add code like the following <a href="<portal-
navigation:navigationUrl type='link' />"><portal-fmt:title/></a>

<portal-navigation:url> - This tag allows you to create links to the screens, commands, or home
attributes from within your theme.

<portal-navigation:urlGeneration> - This tag lets you create links directly to various portal
resources, either pages or portlets, and is very similar to the urls you can create via the url
generation api. The infocenter and various technotes go into further detail in creating these links.

<portal-navigation:urlParam name="parameter_name" value="parameter_value"> - With


this tag, you can add various params to the URL. If you have targeted a portlet, the parameters
can then be retrieved by the getParameter method of the portlet request for a standard portlet. If
the url tag that is the holder for this param tag, targets just a page, the parameters are available to
all portlets written to the IBM Portlet API on the page, but will not be available to JSR 168
Compliant portlets.

Format tags
<portal-fmt:title varname="scripting_variable"/> - When used inside a navigation loop tag,
this tag pulls the page’s title based on the locale, but allows you to pull the title for any item that
supports the localized interface.
<portal-fmt:description varname="scripting_variable" /> - This tag pulls the description for
the object that supports the localized interface.

<portal-fmt:text key="key" bundle="bundle"> - This tag returns the given text in the
specified language. (Java Standard Tag Library)JSTL should be used instead of these tags where
applicable.

<portal-fmt:textParam> - This tag can only be used within the text tag. If the key in the bundle
file has a place holder in the format of {0}, then this tag can be used to substitute a value for the
place holders.
For example, the file nls.engine contains:
welcome = Welcome {0}!
Then, in the JSP file, you can put this snippet:
<portal-fmt:text key="welcome" bundle="nls.engine">
<portal-fmt:textParam>World</portal:textParam>
</portal-fmt:text>

The value for {0} will be replaced with World.


<portal-fmt:user attribute="value"/> - This tag returns any attribute as defined in (WebSphere
Member Manager) WMM for the current user.

Logic tags
<portal-logic:if attribute="value"> - This tag checks a variety of conditions that might exist,
including loggedIn, nodeInSelectionPath, portletMaximized, and portletState. You can use this
tag to change various aspects of the theme to be conditional.

<portal-logic:pageMetaData/> - This tag accesses the metadata for the page.

<portal-logic:unless> - This tag is the opposite of the <portal-logic:if attribute="value"> tag


above, but works on the same conditional states as that tag, That is if the condition is true the
content of the tag is not written to the HTML output, otherwise the content is rendered.

<portal-logic:urlFindInSkin file="file_name"> and <portal-logic:urlFindInTheme


file="file_name"> - These tags let you build URLs that point to the files as they exist in either
the theme or skin without having to hard code the URL. You can have the URL for all your
images use this tag and place the images in your theme directory and portal will find them and
generate the correct URL. Using this tag will allow you to have the Portal Engine determine the
correct URL path for the image and write that to the HTML output. An example is as follows
<portal-logic:urlFindInTheme file="images/toolBar/help.gif"/> where the gif file exists at the
following location on the file system wps.ear\wps.war\themes\html\IBM\images\toolBar.

Other items affecting theme rendering


When using the default theme as the basis for your new custom theme or when developing your
own theme using the guidelines found in the information center, you need to be mindful of the
theme policy. The theme policy affects how parts of the portal provided tags render. Theme
policies can cause these to change and can leave you with a different theme than the default
theme. Such as some of the theme policies instruct the theme to not render the theme extensions,
so the theme extension tags do not render any output when called.

Another item to affect rendering is the color palette. You can select various color palettes based
upon several factors to change what color scheme the theme uses. For example, you can use the
same theme but a different palette to deploy across different business units.

You can extend your theme by using the theme extensions framework. These items will be
examined in detail.

Special Notes:
When you want to modify the look and feel of the palettes, please be aware that these are separate
portal pages and they have their own assigned themes. If you want to modify properties such as
the colors, and images you will need to make sure to edit the correct theme. They are using the
IBM theme by default.

To change the icon for the portlet you have to define the name of the gif in the config parameters
for the portlet. The Parameter name is "portlet_Icon_name" and the value for example is just the
name of the file "my_weather.gif". Check the "My Weather" portlet if you still have it installed
as a guide. The image file will need to be located in the <theme>/images/palette/portlets
directory.
After making the change in the config of the portlet you made need to logout and open a new
browser before you see the new image.
Chapter 2 – Theme policy
The theme policy is a new concept that was introduced with the product at version 6.0. This
policy controls how various parts of the theme are displayed on the page. Using various theme
policies, you can have one theme but have several looks to your portal.

The only way to update a given theme policy is through the XML configuration interface. This
policy can either be applied using the properties portlet or the XML configuration tool. As with
many other aspects of themes, you only need to set a theme policy on a page if it needs to be
different than the parent policy. Once this setting is set on a page, it is handled through the
concept of inheritance and will cascade down through any children pages, until it gets to a page
with an explicit definition.

The theme policy contains several attributes, each one controlling a single aspect of the page. For
example, the Boolean renderBreadCrumb attribute controls whether the breadcrumb displays
and the breadCrumbMaxLevels attribute controls the number of steps listed in the
breadcrumb trail when it is displayed.

The theme policy can control if any theme extensions are run and rendered into your theme. Be
mindful of this control when setting the renderExtensions attribute to false, as it can cause
all of the theme extensions not to work.

The following table lists all possible theme policy attributes and their type.

Table 1. Theme policy attributes


Attribute Type Function
renderMainMenu Boolean If true, the main menu is rendered.
renderTopNavigation Boolean If true, top navigation is rendered.
renderMainMenuActions Boolean If true, the main menu actions are
rendered.
renderSelfCare Boolean If true, Selfcare is rendered.
renderBreadCrumbTrail Boolean If true, the breadcrumb trail is rendered.
render renderSearch Boolean If true, search is rendered.
renderToolBar Boolean If true, the toolbar is rendered.
renderContentPalette Boolean If true, the portlet palette is rendered.
renderPeoplePalette Boolean If true, the people palette is rendered.
renderContextMenus Boolean If true, context menus are render.
renderSideNavigation Boolean If true, side navigation is rendered.
renderTaskBar Boolean If true, the task bar is rendered.
renderFavorites Boolean If true, favorites is rendered.
Attribute Type Function
renderExtensions Boolean If true, extensions are rendered.
renderBannerTitleGraphic Boolean If true, the banner title graphic is rendered,
as long as one exists.
renderPortletFragmentIDAnchor Boolean Determines if the user is on a palette page.
renderBannerTitle Boolean If true, the banner title is rendered, as long
as one exists.
breadCrumbMaxLevels Integer Indicates the number of steps listed in the
breadcrumb trail.
breadCrumbStartLevel Integer Indicates which level to start the
breadcrumb trail.
rootNavigationStartLevel Integer Indicates the start level for root navigation.
rootNavigationStopLevel Integer Indicates the stop level for root navigation.
topNavigationNumRows Integer Indicates the number of rows to render for
top navigation.
topNavigationStartLevel Integer Indicates the start level for top navigation.
topNavigationStopLevel Integer Indicates the stop level for top navigation.
sideNavigationStartLevel Integer Indicates the start level for side navigation.

The default portal installation comes with ready to use policies, including: SingleTopNav,
SingleTopNavMinimal, DoubleTopNav, DoubleTopNavMinimal, SideNavOnly,
SideNavOnlyMinimal, NoTheme, Federation, SingleTopNavLevel2, and Palette.

The last three policies should not be modified because they are used on various parts of the
default theme for flyouts, and other pieces of the interactive theme. Additionally, the Federation
policy cannot be applied to any page using the XML configuration tool or the properties portlet.

SingleTopNav – This theme policy is used when you only want one level of top navigation. It
will render only five levels in the breadcrumb trail and only three levels of side level navigation.

SingleTopNavMinimal – This theme policy is similar to the one above. Use this policy when
you want a minimal amount of navigation options and links on the page. The self care,
breadcrumb trail, search control, toolbar, pallettes, context menus, favorites, extensions, title and
graphics in the title bar are not rendered. Top and side navigation and the main menu are
rendered, but all the actions in the main menu are not rendered.

DoubleTopNav – This theme policy is very similar to the SingleTopNav except that two levels of
navigation are rendered along with the top level. All other navigation is picked up by the side
navigation.

DoubleTopNavMinimal - This theme policy is very similar to the SingleTopNavMinimal, but


with the navigation, changes as in DoubleTopNav.
SideNavOnly – This theme policy causes all levels of navigation to be rendered in the side
navigation area.

SideNavMinimal – Similar to the other minimal policies, but all side navigation is rendered on
the side navigation area.

NoTheme – This theme has all elements of the theme not to be rendered. This policy is similar to
a plain theme template which could be used for a print preview, if you wanted just to print the
content of the portlet.

More information on these theme policies and their specific attributes, please see the information
center topic,
http://publib.boulder.ibm.com/infocenter/wpdoc/v6r0/index.jsp?topic=/com.ibm.wp.ent.doc/wps/
dgn_thempolicy.html.

When working with the theme policy in your JSP files, use the <portal-theme-
ext:initthemepolicy/> tag to set up the theme policy. This tag is in the IBM theme in
the default.jsp file and makes two variables available to the JSP files:
portalThemePolicyMap and portalThemePolicyPath.

The theme policy path is the theme policy name, like SideNavMinimal. This attribute is the same
attribute you use when exporting the theme policies. This tag checks to see if a theme policy has
been set via the URL state, and if not, it checks on the page to determine if a theme policy has
been set. If it cannot find the theme policy, uses the default value of SingleTopNav. Add this
code snippet to your default jsp file in your theme to load the map into a bean for easy
access elsewhere in your JSP.
<jsp:useBean id="themePolicy" class="com.ibm.portal.theme.
policy.ThemePolicyBean" scope="page"/>
<% themePolicy.setValuesMap(portalThemePolicyMap);%>

Exporting and updating a theme policy


To update the theme policy, first export it using the XML configuration utility indirectly. The
URL location specified points to an XML file that you want it to create. The xmlaccess files are
indirectly used to access the theme policy utility. Use this example as your input file:

<?xml version="1.0" encoding="UTF-8"?>


<request xsi:noNamespaceSchemaLocation="PortalConfig_1.4.xsd"
create-oids="true" type="export"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<portal action="locate">
<policy-node action="export" label="WebPage"
type="theme" path="">
<url>file:///c:/temp/exportThemePolicies.xml</url>
</policy-node>
</portal>
</request>
If you want to export only one policy, replace the path attribute with the name of the theme
policy. For example, if you had a policy named TestThemePolicy, replace path="" with
path="TestThemePolicy".

After you have the exported XML file, update any attributes then use file that as your import file
into the XML configuration tool. This operation is necessary to use when we get to the next step
of creating your own theme policy pieces. The XML file that is generated cannot be used as an
import file to the XML configuration utility. You always have to pass the utility an XML file that
points to the actual policy XML file. This file will either be the file used to update the existing
policy or to create the file when doing an export operation.

<?xml version="1.0" encoding="UTF-8"?>


<request xsi:noNamespaceSchemaLocation="PortalConfig_1.4.xsd"
create-oids="true" type="update"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<portal action="locate">
<policy-node action="update" label="WebPage" type="" path="">
<url>file:///c:/ibm/PortalServer/bin/exportThemePolicies.x
ml</url>
</policy-node>
</portal>
</request>

If you wanted to delete your theme policy, the XML would look like this:
<request xsi:noNamespaceSchemaLocation="PortalConfig_1.4.xsd"
create-oids="true" type="update"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<portal action="locate">
<policy-node action="delete" label="WebPage"
type="theme" path="TestThemePolicy">
</policy-node>
</portal>
</request>

After you have created your new theme, assign it to a page by specifying the metadata attribute
com.ibm.portal.ThemePolicy.

This example sets the theme policy SingleTopNavMinimal to the page


ThemePolicyPageTest:

<request type="update" create-oids="true"


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="PortalConfig_1.4.xsd">
<portal action="locate">
<content-node action="update" ordinal="last"
uniquename="ibm.portal.ThemePolicyPageTest" content-
parentref="Content.Root"
active="true" allportletsallowed="false" create-type="explicit"
objectid="wp.theme.policytestpage" type="page">
<supported-markup markup="html" update="set"/>
<!--@LocaleData_1@-->
<parameter name="com.ibm.portal.ThemePolicy"
type="string"
update="set">theme/SingleTopNavMinimal</parameter>
</content-node>

</portal>
</request>

Tips to follow when updating a theme policy include:

If you are only updating a theme policy, the following steps are necessary.
• Export the theme policy.
• Edit the values of the attributes to be updated.
• Use the XML configuration interface to import your file, which is referenced from the
actual input file to xmlaccess.

When updating, if you are also extending a theme policy by adding attributes to it, the attributes
must also be added to the root theme policy.
• Export the entire theme policy structure.
• Edit the root theme policy.
• Edit the theme policy to be updated by adding the attribute if the value is different than
the root theme policy.
• Import the file that references the file which has the updated definitions.

If you are only modifying the value of an attribute that already exists in a theme policy, use the
following guidelines:
• Export the theme policy you want to modify.
• Make the appropriate changes to the attribute.
• Import the file that references the file which has the updated definitions.

Adding custom policy attributes


When creating your own theme policy, you can also add your own custom attributes. These
attributes can be of type integer, Boolean, or string. These attributes can then be used in your JSP
file to control the rendering of certain parts of your theme.
To create your own custom theme policy attribute, export the root theme policy. by just exporting
everything as described above.
After you have the output, add the following to the root policy definition that exists at the top of
the XML file that was created from the export operation.
<policyValue
Name="renderTestAttribute"
Factory="com.ibm.wps.policy.parse.BooleanFactory">
<value>false</value>
</policyValue>
<policyValue
Name="renderTestAttributeLock"
Factory="com.ibm.wps.policy.parse.BooleanFactory">
<value>false</value>
</policyValue>

Then import the file back in to portal using the configuration interface, which will add them to all
theme policies.
In one of your theme JSP files put the following code snippet:
<% boolean isTestAttribute =
themePolicy.getValueAsBoolean("renderTestAttribute", false);
if(isTestAttribute){%>
<p> Display this paragrah if renderTestAttribute is true. </p>
<%}%>

Because this value is a Boolean type, we used getValueAsBoolean method, but the theme
policy object actually has
three accessor methods:
• getValueAsBoolean(String key, boolean defaultValue);
• getValueAsInt(String key, int defaultValue);
• getValueAsString(String key, String defaultValue);
where key is the name of the attribute as defined in the theme policy and defaultValue is the
value that is used if the attribute value cannot be retrieved from the theme policy.

Next, create your own policy called test policy. Included in the files that accompany this white
paper, is an file to be used to import this theme policy (newtesttheme.xml). The theme
policy contained in the newtesttheme.xml is a copy of the DoubleTopNav, but with the added
item of the renderTestAttribute. This file has the renderTestAttribute set to true and once
we apply it to a page, we will be able to see the HTML text rendered in the page that was
contained in the if tag that we added above. After creating our own test policy and importing it,
we assign the test policy to a page that has the theme that we modified to have the scriptlet above.

<policyValue
Name="renderTestAttribute"
Factory="com.ibm.wps.policy.parse.BooleanFactory">
<value>true</value>
</policyValue>

In the following image, we see that based upon the theme policy, the paragraph is visible.
Accessing standard theme policy attributes
Another way to access the theme policy attributes in a JSP file is to load it directly into the page
for reference inside the expression language for the JSP. Add the following snippet in the
default.jsp file for the standard IBM Theme.
<portal-theme-ext:initthemepolicy/>
<jsp:useBean id="themePolicy" class="com.ibm.portal.theme.
policy.ThemePolicyBean" scope="page"/>
<% themePolicy.setValuesMap(portalThemePolicyMap);%>

Then in your JSP code, retrieve the value:


<c:if test="${themePolicy.renderTopNavigation}">
<p> Display this paragrah if renderTopNavigation is true and we are
loading from the page map. </p>
</c:if>

The one limitation is that only the standard theme policy attributes are available in this way. You
will have to use the standard getter methods to get any values that you add to extend the theme
policy.

If you want to extend this access so that you can call the bean as above for your own attributes,
you can do the following.

First in Rational Application Developer create a Java™ project, pointing to the portal 6.0 runtime
and JDK. Next, add the following jar file from /shared/app to the buildpath
wp.theme.themepolicy.jar file. Finally, create a class like the following:

package com.ibm.wps.l2.themepolicy;
import com.ibm.portal.theme.policy.ThemePolicyBean;
public class MyThemePolicyBean extends ThemePolicyBean {

private static final String RENDER_TEST_ATTRIBUTE =


"renderTestAttribute";
/**
* Controls whether the theme should render the title in the banner.
* @return Returns the renderBannerTitle.
*/
public boolean isRenderTestAttribute() {
return
this.getValueAsBoolean(MyThemePolicyBean.RENDER_TEST_ATTRIBUTE, true);
}
}
Add as many getter methods to the class for all of your custom attributes. Export this file as a jar
file and place it into the shared/app directory, then restart the server.

Change the policy bean loading to the following:


<jsp:useBean id="themePolicy"
class="com.ibm.wps.l2.themepolicy.MyThemePolicyBean" scope="page"/>
<% themePolicy.setValuesMap(portalThemePolicyMap);%>
Then, you can retrieve your values like this:
<c:if test="${themePolicy.renderTestAttribute}">
<p> Display this paragrah if renderTestAttribute is true and we are
loading from the page map. </p>
</c:if>
Chapter 3 – Color palette
The color palette lets you keep colors and certain icons separated from your stylesheets. This
separation lets you change the color used on the page and not need to change any theme code.
For example, public pages could be one color and authenticated pages could be another color.
The palette is defined by a properties file that is loaded by the stylesheet JSP files, then used to
dynamically pull the properties to configure settings within the stylesheet files. The default
palette can be overridden on a per page basis.

Creating the palette


The IBM provided palettes are stored in the following location:
/profiles/profilename/installedApps/nodename/wps.ear/wps.war/them
es/html/IBM/colors. In this directory is a file called
default.properties and a directory called default where the
default color §palette is included.
A color §palette is defined by an identifier, which is the name
of the directory and the name of the properties file. To create
a new color §palette, for example testthis, create a properties
file labeled testthis.properties and a folder labeled testthis.
This property file stores parameters as key value pairs. In the
default theme, all keys are prefaced with a setX, where X is a
number. This preface is used to group the properties into sets
of like properties. These are just a convenience and are not
needed when creating your own §palette, but all color definitions
must contain the same keys. The following figure contains a
sample of some of these properties.

In the above samples, set1Text1 defines the text color in the selectedPage style class, but
set1Text2 and set1Text3 do not have corresponding elements in the CSS box model.
These values are included to provide multiple text colors for emphasis. These values could be
used, for example, to specify the text color for <h1> and <h3> elements, or for <strong> text.
If you need more values, add them. If you do not need them at all, they can be deleted., There is
no requirement for the contents of the property file, only that the keys used here correspond to
their use in the stylesheet JSP files, and that all properties files contain the same keys.

Assigning the palette to a page


After you have defined all of your colors, you can then assign the palette to a page. The theme
determines what color palette is in use by the metadata in the head.jspf file of the theme.
<portal-logic:pageMetaData varname="pageMetaData">
<!-- pageMetadatatag colorPalette: ${pageMetaData.colorPalette} -->
<c:set var="colorPalette" scope="request">
<c:out value="${pageMetaData.colorPalette}" default="default"/>
</c:set>
</portal-logic:pageMetaData>

It gets a value from the page metadata, and if none is found it uses a default color palette. It is
important that all of your themes have a default color palette and not only custom ones so that if
the metadata is missing, the page still renders. By default, pages do not have a colorPalette
metadata value.
For example, to assign the testthis color palette as a default to the pages, do the following:

1. Click the Page properties of the page in which you want to use a specific color palette.
2. Expand Advanced options.
3. Click I want to set parameter.
4. Enter color§Palette as New parameter.
5. Enter the name of the color palette property file as the New value. For example, enter
testthis to assign testthis.properties.

Referencing a color palette in CSS


The Styles_rules.jspf file loads the [color§Palette].properties file and
stores it in a map request attribute, colors, for use by the cascading stylesheet (CSS) style
definitions.
The most efficient way to reference the values is with Expression Language (EL) expressions. EL
expressions let you reference a map's values by a simplified dot notation.
For example, ${colors.set1Background} retrieves the set1Background color.
If you are only creating a new color palette for the existing theme, you do not need to modify the
styles_*.jspf files. This modification is only required if you have added or removed keys
from the properties files.
For example, you have added a new key that has a font color and a key for font size. You have
two properties files, blue and red, and you have added this to the default.properties file.
Next, add a style to the stylesheet JSP files so that this new key is pulled. Then,assign that style
to the parts of the markup that you want.
Chapter 4 – Theme extensions
Extensions aid in the building of a modular product with loosely coupled components. Extension
points define how the component is to be extended and the extensions comprise the additional
functionality. WebSphere Portal uses the Eclipse plug-in framework to define the theme
extensions. Visit eclipse.org for complete details on the plug-in framework and API.

Like the Eclipse framework, theme extensions provide extension points to create and extend
plugins.
This extension allows for a highly customizable theme with little or no coding changes. Theme
extensions provide the ability to add content to the rendered page without updating JSP files.
WebSphere Portal provides several extensions that are ready to use as is. Some of the default
extensions include functionality to add flyouts or context menu items.

Theme extension APIs


The APIs for theme extensions consists of several interfaces and a set of classes that provide a
default implementation to the core interfaces. We will briefly discuss the interfaces and then
discuss the default implementations in more detail.

Interfaces
ThemeContent:
All theme extensions indirectly extend the ThemeContent interface. Any element which
contributes content to the theme using a defined extension point is of type ThemeContent.
Two methods are defined in this interface:
 getOrdinal
Determines the priority, in which the lower the value, the higher priority is.
If no value is specified using the plugin.xml file, then a value of -1 should be
returned.
 init(ThemeContext context)
Initializes the ThemeContext.

Inherited methods

 isActive method is inherited from


com.ibm.portal.ActiveFlag.
Returns true if the include should be rendered, otherwise
false is returned.

 SetInitializationData is inherited from


org.eclipse.core.runtime.IExecutableExtension
Sets the initialization data that is used to get attributes
from the plugin.xml file.
This method is passed an IconfigurationData object. This
object represents the plugin.xml file of the extension and
contains methods for extracting the attributes defined in
the item element of the plugin.xml file.

The following three methods are inherited from


com.ibm.portal.Localized:
 getDescription
Returns the description.
 getLocales
<lookup>
 getTitle
Returns the title.

There are two types of ThemeContent: ThemeItems and ThemeIncludes.

ThemeItem
Theme items are responsible for contributing content directly
to the page.
Two methods are defined in this interface:
 getTooltip(java.util.Locale)
Returns the tooltip text for the current locale. If no
value is specified or if there is an exception then null
should be returned.
 newIconURL(com.ibm.portal.state.access.url.portalresource.S
tate state)
Returns the URL of type com.ibm.portal.state.DisposableURL
for the specified icon. If the URL cannot be created or
does not exist, a null value is returned. This method can
throw a StateException.

There are two types of ThemeItem: ThemetextItem and


ThemeLinkItem
ThemetextItem
Contributes simple text.
This interface adds one method:

getText(java.util.Locale)
Returns the text to be contributed to the markup.

ThemeLinkItem
Creates a URL to contribute to the theme.
This interface adds two methods:
newURL
Returns the generated URL of type
com.ibm.portal.state.EngineURL or null if the user is not
allowed to access the resource.

RequiresPOST
If the URL is the target of an action, this method should
return true.

ThemeIncludes
ThemeIncludes are responsible for rendering their own content.
RequestDispatcher should be used to include a JSP. The content
is included using the render method.

One method is defined in this interface:

render()
The render method is responsible for including the JSP.

ThemeJspInclude:
A ThemeJspInclude is responsible for rendering itself by
invoking a JSP using a RequestDispatcher. The invoked JSP is
responsible for maintaining the look and feel of the overall
theme.
One method is included in this interface:
getJspPath()
Returns the JSP path to be included.

ThemeContext
Describes the current theme context. This interface formalizes the current context for a
specific ThemeContent. An extension can declare a custom context in the plugin.xml file
by including the context attribute in the markup describing the extension.
Three methods are defined in this interface:
 getRequest()
Returns the request associated with this context.
 getResponse()
Returns the response associated with this context.
 initContext(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response )
Initializes the context.

Constants:
There are three interfaces for defining constants to be used in theme extension. The constants
represent the attribute names used in the default implementation of the theme extensions and
match the attribute names as defined in the plugin.xml file. For example, the
ThemeItemDescriptorConstants contains a constant named TOOLTIP_ATTRIBUTE. This
constant maps to the tooltip attribute in the plugin.xml file.

<item id="jsmith"
class="com.ibm.wps.themeext.sample.ContactNames"
firstName="John"
lastName="Smith"
email="jsmith@us.ibm.com"
tooltip="John Smith"/>

ThemeContentDescritporConstants:
Constants describing the XML attributes for a DefaultThemeContent.
ThemeItemDescriptorConstants:
Constants describing the XML attributes for a ThemeItem.
ThemeJspIncludeDescriptorConstants:
Constants describing the XML attributes for a DefaultThemeJspInclude.

See the API for detailed information about all the interfaces discussed, this is up on the Portal
Support site..

Default implementations
The theme extension APIs provide default implementations for the interfaces listed above. These
provide a convenient extension point to the APIs without having to implement all the required
methods.
You can use these implementations rather than writing your own classes.

In this section we will discuss the attributes for each of the implementation classes. While most
of the attributes are optional, some are required. We will identify which ones are required.

Some attributes do not fit to a particular type and are global:


 id (optional)
Specifies identification for this element. While it is not required to make this value
unique, it is a best practice to do so.
 class (required)
Identifies which class should be used for this element.
 tooltip (only used in theme items) (optional)
This text is rendered using the ThemeExtensionItemToolTip tag.
 context (optional)
Identifies a custom ThemeContext to be used. If a context is not specified then a default
one will be provided.

DefaultThemeContent
This class is the default implementation of ThemeContent and provides access to the following
attributes defined in the plugin.xml file. All default implementations of ThemeItems
(DefaultThemeLinkItem and DefaultThemeTextItem) extend this class, which means that they
are inherently able to access these attributes when defined in the plugin.xml file.

 description (optional)
Provides a description about the extension.
 ordinal (optional)
This method determines the priority, in which the lower the value, the higher the priority
is.
The extension will be ordered based on their ordinal value, if specified.
 title (optional but should be included)
Defines the title for the extension.

DefaultThemeItem
This call provides a default implementation for ThemeItems and handles all the icon processing
for the newIconURL method. This class works in conjunction with the
ThemeExtensionItemIconUrl tag.
Only the following attribute is defined for this default class.

 iconName
Defined the path and name of the icon to be used for this extension.

DefaultThemetextItem
Provides an implementation for a ThemetextItem. The text defined is rendered to the theme
using the ThemeExtensionItemText tag. The following attribute is the only one added by this
class:

 text (required)
Text to be contributed to the markup.

DefaultThemeLinkItem:
This implementation creates a portal link to the specified content node. For this
implementation the following methods return false or null.
RequiresPOST (returns null)
getTooltip (returns null)
getOrdinal (returns 0)
isActive (returns false)
getLocales (returns false)
isAllowed will always return true

The following additional attributes are added:


 contentNode
This attribute should be the uniqueName of the page you are targeting.
 useNewWindow
Used when targeting new windows like flyouts. The value would be true.

DefaultThemeJSPInclude
This class provides the implementation to include a JSP in the theme. The render method is
invoked to call the RequestDispather to include the desired JSP file. The following attributes
are added with this class:

 Jsp (required)
The relative path to the JSP to be included.

The previous section discusses the default implementations and the attributes required in the
plugin.xml file. If you decide not to use the default implementation and create your own,
it is important to understand how these attributes are resolved. While it would be a best
practice to use the attribute names described above, it is not required.

There might also be cases where you need to extend the default implementation to add more
attributes.

The following is a snippet of a plugin.xml file that uses a ThemeTextItem. For this
example, we are only using a few of the possible predefined attributes and we also add a
custom attribute.

<extension point="com.myco.theme.plugin.Sample" id="Sample_01"


name="Test_01" >
<item id="Page1"
class="com.myco.sample.TextSample"
description="This is sample text"
text="some value for page 1"
text2=”some other text”/>
</extension>

This extension uses a class named TextSample as defined in the class attribute. TextSample
extends DefaultThemeTextItem and overrides the setInitializationData method to process
that new attribute text2. When the setInitializationData method is called on TextSample
the IConfigurationElement is used to retrieve the text2 attribute. The
IconfigurationElement object contains a method to retrieve all attributes defined in the item
element of the plugin.xml file.

Example:
public void setInitializationData(IConfigurationElement element,
String arg1,
Object arg2) throws CoreException {

super.setInitializationData(element, arg1, arg2);


String value = element.getAttribute(“text2”);
if(value != null){
myCustomValue = value;
}
}

The attribute is retrieved from the IconfigurationElement using the getAttribute method.
This is how the plugin.xml attributes are realized in the theme extension code.

Default extension points


The default themes provide a set of extension points. The Suggested Interface field
describes the interface which provides the information the default extension point requires. Type
enforcement is not performed at runtime. However, if an implementation does not provide at
least the information required by the Suggested Interface, the extension might not
display correctly in the theme.

The following list describes the extension points provided:

com.ibm.portal.theme.plugin.MetaTagDataItems
 description
Provides components the ability to add data to the meta tags of a page.
 content type
ThemeItem
 Interface
ThemeTextItem

com.ibm.portal.theme.plugin.Styles
 description
Provides components the ability to contribute CSS to the page.
 content type
ThemeItem
 Interface
ThemeTextItem

com.ibm.portal.theme.plugin.Javascript
 description
Provides components the ability to add JavaScript to the page.
 content type
ThemeItem
 Interface
ThemeTextItem

com.ibm.portal.theme.plugin.HorizontalPageBarItems
 description
Provides components the ability to add JSP content to the horizontal page bar.
 content type
ThemeInclude
 Interface
ThemeJspInclude

com.ibm.portal.theme.plugin.VerticalPageBarItems
 description
Provides components the ability to add JSP content to the vertical page bar.
 content type
ThemeInclude
 Interface
ThemeJspInclude

com.ibm.portal.theme.plugin.MainContextMenuItems
 description
Provides components the ability to add an item to the main context menu.
 content type
ThemeItem
 Interface
ThemeLinkItem

com.ibm.portal.theme.plugin.PageContextMenuItems
 description
Provides components the ability to add an item to the page context menu.
 content type
ThemeItem
 Interface
ThemeLinkItem

com.ibm.portal.theme.plugin.PortletContextMenuItems
 description
Provides components the ability to add an item to the portlet context menu.
 content type
ThemeItem
 Interface
ThemeLinkItem

com.ibm.portal.theme.plugin.Flyouts
 description
Provides components the ability to add flyouts to the page.
 content type
ThemeInclude
 Interface
ThemeJspInclude

Plugin.xml
The plugin.xml file is used to define extensions and extension points.
The following elements should be used within the plugin.xml file:
plugin
This element is the root of the XML file and the following attributes should be defined:
 id
This attribute is the root identification for the plug-in. This ID combined with the ID in
the extension-point element are used to determine the entire extension point. For
example, if the ID defined in the plugin element is
com.ibm.portal.theme.plugin and the ID attribute in the extension-point
element is “Styles”, then these would combine to give the fully qualified extension
point the name of com.ibm.portal.theme.plugin.Styles.

 name
Name used to identify the plug-in.
 version
The version number of the plug-in.
 provider-name
This name should identify the vendor writing the plug-in.

extension-point
Used when defining a new extension point. This element is a child element of the plugin element
and has the following attribute:
 id
Unique identifier of this extension point which is used in conjunction with the id attribute
in the plugin element to determine the fully qualified extension-point.

extension
This element is also a child element of the plugin element and is used to extend an extension
point. When participating in theme extensions, this element will be used the most. The following
attribute are defined:

 point
Fully qualified name of the extension point you want to extend.
 id
Unique identifier for the extension.
 name
unique name for the extension.
item
This element is a child of the extension element and is used to define the ThemeContent. The
attributes for this element vary depending on the extension-point being targeted. As outlined
above we have defined the attributes required for the default implementation and also outlined
how to define custom attributes.

The following is an example of a plugin.xml file using a custom extension point.


<?xml version="1.0" encoding="UTF-8"?>
<plugin id="com.myco.theme.plugin" name="Theme Extensions Plug-in Page
Value Samples"
version="1.0.1" provider-name="IBM">

<!-- Creates a new extention-point named com.myco.theme.plugin -->


<extension-point id="Sample" />

<extension point="com.myco.theme.plugin.Sample" id="Sample_01"


name="Test_01" >
<item id="Page1"
class="com.myco.sample.TextSample"
description="This is sample text"
text="some value for page 1"
text2=”some other text”/>
</extension>
</plugin>

Theme extentions in a JSP


Portal defines a set of JSP tags to initialize and process theme extensions. These tags should only
be used within themes and skins and are not supported for use in portlets. For a complete listing
of attributes, see the information center.

themeExtension
Starts the processing of the theme extension. The id attribute is used to identify the fully
qualified extension point.

themeExtensionLoop
Iterates through all extensions defined in the plugin.xml file. This tag makes the ThemeItem
object available with a variable named themeExtension.

themeExtensionItemTooltip
Prints the tooltip specified. If a tooltip was not identified, then nothing is rendered.

themeExtensionItemText
Prints the text associated with the extension. The class defined in the plugin.xml for the
extension must be of type TextItem.

themeExtensionItemUrl
Prints the URL associated with a ThemeLinkItem.

themeExtensionItemIconUrl
Creates a URL for the extension icon.

themeExtensionRenderInclude
Renders the content associated with a ThemeInclude. ThemeIncludes are responsible for
rendering their own content.

Extensions are instantiated each time they are used via the
IConfigurationElement#createExecutableExtension method.
This instantiaion for each access can have a performance impact, so the placement of an
extension should be carefully considered. Avoid placing the extension inside nested loops.

Custom extension point


We will create a simple custom theme extension for displaying user contact information.

When creating a custom theme extension you will need to perform the following:

1. Create a plugin.xml file defining your extension point and extensions.


2. If needed , create classes and interfaces for your extension.
3. Bundle your classes and plugin.xml file into a JAR file.
4. Place this JAR file under the portal/shared/app directory.
5. Update the theme to read the plug-in and properly render the extension.
6.
7. Restart the server to force your new classes to be loaded.

We will start with creating the plugin.xmlfile.

First, define the XML document.


<?xml version="1.0" encoding="UTF-8"?>

Next, define the root of the XML file, for the plugin.xml it will be plug-in. The id attribute used
in this element is combined with the extension-point ID to form the full extension point ID. Also,
define the name, version, and provider-name.

<plugin id="com.myco.theme.plugin" name="Theme Extensions Contact


Samples"
version="1.0" provider-name="IBM">

Next, define the extension-point and give it an id of “ContactNames”.

<extension-point id="ContactNames" />

Next, define an extension for this extension-point.

<extension point="com.myco.theme.plugin.ContactNames"
id="ContactNames_01"
name="names_01">

Use the combination of the ID of the plugin and the ID of the extension-point. The id and name
are used during logging. While uniqueness is not enforced, try to create names unique to your
plug-in.

Next we define items that correspond to the ThemeItem objects used in the theme. For a single
extension-point you can have multiple items defined. The item also needs to define the class to
be used and an ID.

This example lists contacts with a first name, last name, and e-mail ID.

<item id="rywilson"
class="com.ibm.wps.themeext.sample.ContactNames"
firstName="Ryan"
lastName="Wilson"
email="rywilson@us.ibm.com" />

Add a few more contacts and the complete file will look like this:

<?xml version="1.0" encoding="UTF-8"?>


<plugin id="com.myco.theme.plugin" name="Theme Extensions Contact
Samples” version="1.0" provider-name="IBM">
<extension-point id="ContactNames" />

<extension point="com.myco.theme.plugin.ContactNames"
id="ContactNames_01" name="names_01">
<item id="rywilson"
class="com.ibm.wps.themeext.sample.ContactNames"
firstName="Ryan"
lastName="Wilson"
email="rywilson@us.ibm.com" />
<item id="jwbarnes"
class="com.ibm.wps.themeext.sample.ContactNames"
firstName="James"
lastName="Barnes"
email="jwbarnes@us.ibm.com" />
</extension>
</plugin>

Because custom attributes were used, we need to create a class that will read them. In this class,
define some constants that define the attribute names and override the setInitializationData
method to read these attributes from the IconfigurationElement object. For this example we will
extend the DefaultThemeTextItem class and take advantage of the default implementations.

Create an interface named IContactNamesItem

Add the following constants to identify the attribute names from the item element.
public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
public static final String EMAIL_ID = "email";

Next, define a set of Strings used to store the values of these attributes.
private String firstName;
private String lastName;
private String email;

Our interface will define the following getters and our implementation will set and return the
values.
public String getEmail();
public String getFirstName();
public String getLastName();

Create a class that extends DefaultThemeTextItem and also implements


IContactNamesItem.
Next override the setInitialization method to retrieve the data.

public void setInitializationData(IConfigurationElement element, String


arg1, Object arg2) throws CoreException {
super.setInitializationData(element, arg1, arg2);

String value = element.getAttribute(FIRST_NAME);


if(value != null){
firstName = value;
}
value = null;
value = element.getAttribute(LAST_NAME);
if(value != null){
lastName = value;
}
value = null;
value = element.getAttribute(EMAIL_ID);
if(value != null){
email = value;
}
}

This coding is needed to create the bean that represents the ThemeItem. We could have
optionally added another method to generate the markup to e-mail this customer.

While defining the getters in the interface works when using a small number of attributes, there is
a better solution if there are many more attributes defined.

You could use a Map to store all the data, then have one method for retrieving the desired
attribute. We could rework the example so that the interface looked like this:

public interface IContactNamesItem {


public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
public static final String EMAIL_ID = "email";

public String getAttribute(String key);

Our implementation would now change to the following:


public class ContactNames extends DefaultThemeTextItem implements
IContactNamesItem{
private Map attributes = new HashMap();

public void setInitializationData(IConfigurationElement element,


String arg1, Object arg2) throws CoreException {
super.setInitializationData(element, arg1, arg2);

String value = element.getAttribute(FIRST_NAME);


if(value != null){
attributes.put(FIRST_NAME, value);
}
value = null;
value = element.getAttribute(LAST_NAME);
if(value != null){
attributes.put(LAST_NAME, value);
}
value = null;
value = element.getAttribute(EMAIL_ID);
if(value != null){
attributes.put(EMAIL_ID, value);
}
}

public String getAttribute(String key){


if(key !=null){
return (String)attributes.get(key);
}
return null;
}
}

This implementation provides a cleaner solution, especially when there are a large number of
attributes.

To display the list of contacts on the top of the page, add this code in the default.jsp.
The taglib for the theme extensions is already defined for the IBM provided themes. If you are
using a custom theme, add the theme extensions taglib definition.
<%@ taglib
uri="http://www.ibm.com/xmlns/prod/websphere/portal/v6.0/portal-theme-
ext"
prefix="portal-theme-ext"%>

The policies can determine whether theme extensions are enabled or not enabled, so place
your theme extension code after the theme policy initialization tag.
<portal-theme-ext:initthemepolicy />
<jsp:useBean id="themePolicy"
class="com.ibm.portal.theme.policy.ThemePolicyBean" scope="page"
/>
<%themePolicy.setValuesMap(portalThemePolicyMap);%>

Using the themeExtension tag, specify the extension point to include. We have defined the
extension-point to be com.myco.theme.plugin.ContactNames, so this the is value to use in the id
attribute.
<portal-theme-ext:themeExtension
id="com.myco.theme.plugin.ContactNames" >

Next, we iterate through all extension that have this point defined. This is the advantage is using
theme extensions. Other portal administrators could create their own plug-in that extends this
extension point and provide additions to the contact list. Developers could also create a custom
class that implements IcontactNamesItem and defines some custom logic. All this can be done
without having to change the theme.

While looping through the extension we will cast the implicit themeExtension object that is
provided in the themeExtensionLoop tag.

<portal-theme-ext:themeExtensionLoop>
<%
com.ibm.wps.themeext.sample.ContactNames contact =
(com.ibm.wps.themeext.sample.IContactNamesItem)themeExtension;

After we have this object, we can use it to create a mailto link to this contact.
out.println("<a href='mailto:" +
contact.getAttribute(contact.EMAIL_ID) + "'>" +
contact.getAttribute(contact.FIRST_NAME) + " " +
contact.getAttribute(contact.LAST_NAME) + "</a><br>");
%>
</portal-theme-ext:themeExtensionLoop>
</portal-theme-ext:themeExtension>
Chapter 5 – Flyouts and context menus
Flyouts
Flyouts are customizations that take advantage of the theme extensions so that you do not have to
modify any theme JSP files. You can drop these JAR files in to your shared app directory,
restart the server, and theses extensions are added to the theme as it renders.

In this example we create a link to the enable tracing page so that it renders as a flyout.

We will need to create a Java project in Rational Application Developer (or your tool of choice).
Then, add the portal runtime to the build path, and finally these three jar files:
portal_root\shared\app\wp.theme.extensions.api.jar
portal_root\shared\app\wp.theme.extensions.impl.jar
portal_root\shared\ext\eclipse-runtime.jar

For our example, create a class that extends the following, ThemeLinkItem

The following methods in that class are doing most of the work.

This method creates the URL using a URL generation API. This method makes use of a helper
class to do all of the URL creation. More information can be found at Advanced URL
Generation.
public EngineURL newURL() throws StateException
{
EngineURL result = null;
try {
result =
ServletURLGenerator.generateUrlForFlyout("ibm.portal.Enable Tracing",
"wps.p.Enable Tracing", aContext.getRequest(), aContext.getResponse() );
} catch (Exception ex) {
System.out.println("There was a problem generating a flyout
url");
}
return result;
}

The following method specifies which graphic to display into the theme for expanding and
collapsing this new flyout. This example uses a graphic of a pencil writing. You can use any
graphic you want, but keep the size of the graphic to 21 pixels square. We use the helper class to
generate the URL for us which makes use of the URL generation API.

public DisposableURL newIconURL( State state ) throws StateException {


DisposableURL url = null;
try {
url =
ServletURLGenerator.getDisposableURL(aContext.getRequest(),
aContext.getResponse(), "images/toolBar/tracing.gif");
} catch (Exception ex) {
System.out.println("Unable to create the url");
}
return url;
}
This method returns the title to be shown when hovering over the icon. This will also be used if
the graphic URL cannot be retrieved.

public String getTitle( Locale arg0 ) {


return "Enable Tracing";
}

This method renders in a new window instead of the current one. In a flyout, this will let it
actually flyout over the current window instead of trying to be in the window.

public boolean isNewWindow()


{
return true;
}
Finally in your Java project at the root level, you need a plugin.xml file.

<?xml version="1.0" encoding="UTF-8"?>


<plugin id="com.ibm.wps.l2.whitepaper.samples" name="Theme Extensions
Plug-in Samples" version="1.0.1" provider-name="IBM">
<extension point="com.ibm.portal.theme.plugin.Flyouts"
id="WPSToolBaryFlyouts" name="ToolBarFlyouts">
<item id="DebuggingFlyout"

class="com.ibm.wps.l2.whitepaper.samples.TracingFlyout"
title="My Portal Extension" />
</extension>
</plugin>

This tells portal where to load your extension from, and where to add it to in the theme extension
hierarchy. Because we have not defined any new extension points, we do not have the tag for the
extension-point. Instead there is the extension we are adding to the already existing extension
points.

To deploy this implementation, put the graphic into the theme in use, that will go under
app_server_root/profiles/profilename/installedApps/nodename/wps.e
ar/wps.war/themes/html/themename/images/toolBar/. Next, export this Java
project from your development environment. Note: Make sure you have specified 1.4 as the
compiler compliance level, as Rational Application Developer uses 5.0 by default for Java
projects.
Take this jar file and drop it into portal_server_root/shared/app, and then restart the
portal server. Using our example, you should now see the image for tracing in the upper right
corner of your theme.
Context menus
Several context menus are included by default. At this time do not use the theme extension
points to create your own context menu. Use the extension points to add items to the context
menus, either for the page, the portlet, or the whole portal. You can selectively enable these
menu items at runtime, based upon criteria.

To create a context menu item, create a class that extends the following:
ThemeLinkItem
In this class, we have overridden the setInitializationData to pull in the properties from our
plugin.xml file to parameterize this class. This is discussed in more detail in the theme
extensions chapter.

public void setInitializationData( IConfigurationElement arg0,


String arg1, Object arg2 ) throws CoreException
{
String titleValue = null;
titleValue = arg0.getAttribute( TITLE_ATTRIBUTE );
if ( titleValue != null ) {
this.title = titleValue;
}

String descriptionValue = null;


descriptionValue = arg0.getAttribute( DESCR_ATTRIBUTE );

if ( descriptionValue != null ) {
this.description = descriptionValue;
}

String urlValue = null;


urlValue = arg0.getAttribute( EXTERNAL_URL_ATTRIBUTE );

if ( urlValue != null) {
this.externalUrl = urlValue;
}
}

Based upon those values that we pulled in, we create a URL to an external site.

public EngineURL newURL() throws StateException {


return new ExternalURL( this.externalUrl );
}

Finally, we tell it to open the page in the existing window.


public boolean isNewWindow() {
return false;
}

Then, in the plugin.xml file, add the following.


<extension point="com.ibm.portal.theme.plugin.PortletContextMenuItems"
id="WPSExternalPortletMenuLinks" name="ExternalPortletMenuLinks">
<item id="GoogleLink3"
class="com.ibm.wps.l2.whitepaper.samples.ExternalLinkItem"
title="Google"
description="Search for relevant items."
url="http://www.google.com" />
</extension>

This code loads these parameters into the class using the setInitializationParameterData method.
In this way, you can reuse the code above to create several links to add to the context menu of
your choice (page, portal, or portlet).

Just by changing it to this example, it is added to the Main Menu instead of the Portlet Context
Menu.
<extension point="com.ibm.portal.theme.plugin.MainContextMenuItems"
id="WPSExternalMainMenuLinks" name="ExternalMainMenuLinks">
<item id="GoogleLink1"
class="
com.ibm.wps.l2.whitepaper.samples.ExternalLinkItem”
title="Google"
description="Search for relevant items."
url="http://www.google.com" />
</extension>

It would display in the drop-down control from the launch button instead of anywhere else in
portal.

Also included in the source code is an example of a Page Context Menu item that points to a
portal page. The class is InternalLinkItem and extends the ThemeLinkItem. This link points to a
custom Create Page that could exist anywhere inside your portal, but will be accessible from the
page context menus of any page, as long as the theme policy to render theme extensions is set to
true.

The method to create the URL also used the helper class and looks like the following. This
helper class could allow you to target a portlet and pass parameters to it.

public EngineURL newURL() throws StateException {


EngineURL result = null;
try {
result = ServletURLGenerator.generateUrlStringServlet(page,
null, null, context.getRequest(), context.getResponse());
} catch (Exception ex) {
System.out.println("This exception in this code = " + ex);
}
return result;
}

In the plugin.xml file, we have the following to describe this new item
<extension point="com.ibm.portal.theme.plugin.PageContextMenuItems"
id="WPSExternalPageMenuLinks" name="ExternalPageMenuLinks">
<item id="LinkToSearchResults"

class="com.ibm.wps.l2.whitepaper.samples.InternalLinkItem"
title="Create Page"
description="Create a New Page."
page="Create_Page" />
</extension>

For full source code listing, see the attached code. Several methods that are needed are defined in
the source, but we have not modified them in any significant way. More information on these
methods is also in the Javadoc for theme extensions, that can be found at: http://www-
1.ibm.com/support/docview.wss?rs=688&context=SSHRKX&context=SSBRWT&context=SSQ
KRQ&context=SS3NNG&context=SSYJ99&context=SSRUWN&context=SS6JVW&q1=theme
&uid=swg21247155&loc=en_US&cs=utf-8&lang=en
Chapter 6 – Development tools
As the new version contains a significant level of complexity and improvement from previous
versions, debugging all these interactions can be quite tricky. Luckily there are tools that make
both HTML and JavaScript debugging easier.

The tools that we have used the most are plug-ins for Firefox which allow you to make real time
changes to the source code and see how it changes the look without requiring you to refresh the
browser. Also, you will be able to pinpoint which area needs changing easier.

The first of these tools is the Web developer plug-in for Firefox: https://addons.mozilla.org/en-
US/firefox/addon/60 .

The second of these is called Firebug which is helpful for debugging issues with JavaScript and
CSS: https://addons.mozilla.org/en-US/firefox/addon/1843

With these plug-ins both installed, you can inspect the rendered Web site in the following
manner.
Right-click an element, then choose Inspect Element.

That action will display window at the bottom of the browser that lets you see the HTML source
for the current element.
Additionally you can view the stylesheets, the JavaScripts, the DOM, and Net, which shows you
the response time for various pieces to load.

Next, on the right side, see the stylesheet definitions in use for this element.

You can click to edit one of these or add a new setting to see how it would look in the rendered
output. This change only affects this page view and will not be persisted.

With the Web developer toolbar you can also validate the HTML and CSS. You can outline all
table elements, which can be helpful when the page is failing to load correctly. Line guides are
also available to help with positioning of items when using pixels measurements. A ruler is
available that you can stretch directly on the page to measure distances between visual objects.
There is a wealth of other options and both of these tools we have found very useful when
developing themes and skins.
Chapter 7 – Migrating to version 6.0 from version 5.1
Adding drag and drop
When migrating to version 6.0, you will not want to convert all of your skins and themes to full
6.0 style. With these steps you will not have to rebuild your version 5.1 skins to support the drag
and drop functionality of version 6.0.

See the information center about the necessary tags you will need in your skin JSP files to support
this functionality.
http://publib.boulder.ibm.com/infocenter/wpdoc/v6r0/index.jsp?topic=/com.ibm.wp.ent.doc/wps/
dgn_dndtags.html

The main tags are:


<dnd:DNDPortletHelper/> - This tag must be in the JSP or else it will not work. This tag
loads several JavaScripts that are needed to make the drag and drop work.
<dnd:drag/> - Designates which part of the actual content is dragable.
<dnd:drop/> - Sets up a drop zone.
<dnd:dragHandle/> - Designates a part of the portlet to be used as the handle for drag and
drop.

First in the control.jsp file, you need to add the following import:
<%@ page import="com.ibm.portal.content.LayoutNode"%>
and tag lib declaration:
<%@ taglib uri="/WEB-INF/tld/dnd.tld" prefix="dnd" %>

After the wps:constant tag, add the following:

<%!
private static com.ibm.portal.identification.Identification
identification;
public void jspInit(){
try{
/* only perform this JNDI lookup once as this is an expensive call
performance wise */
javax.naming.Context ctx=new javax.naming.InitialContext();
identification=(com.ibm.portal.identification.Identification)
ctx.lookup("portal:service/Identification");
}
catch (javax.naming.NamingException ne){
}
}
%>
<%
String currentLayoutNodeStr="";
if (pageContext.getAttribute("currentLayoutNode",
pageContext.REQUEST_SCOPE) != null) {
LayoutNode
currLayoutNode=(LayoutNode)pageContext.getAttribute("currentLayoutNode"
, pageContext.REQUEST_SCOPE);
currentLayoutNodeStr=identification.serialize(currLayoutNode.getObjectI
D());
}
else {
LayoutNode
currLayoutNode=(LayoutNode)pageContext.getRequest().getAttribute("com.i
bm.wps.composition.element");
currentLayoutNodeStr=identification.serialize(currLayoutNode.getObjectI
D());
}
%>
<dnd:DNDPortletHelper />

These will set up certain items in the context of the page so that they are available for the later
tags for the drag and drop feature.

Next, directly after this, add:

<dnd:drag namespace="wp" type="portlet_windowID"


value="<%=currentLayoutNodeStr%>" includeDragHandle="false"
validator="com.ibm.wps.dnd.impl.DNDDragPortletValidator">

Then add a closing drag tag after the end of the portlet content in the control.jsp file.
</dnd:drag>

The next two tags you need to add are:


<dnd:dragHandle>
</dnd:dragHandle>

The easiest place to add them is around the display part for the portlet title.

Drop zones

You need to add a drop tag inside some element, either a div or table, so that it is actually large
enough to interact with.
Start with UnlayeredContainer-H.jsp
and first add:
<%@ taglib uri="/WEB-INF/tld/dnd.tld" prefix="dnd" %>
<dnd:DNDPortletHelper/>

This area will be the start area:


<dnd:drop namespace="wp" type="portlet_windowID" action="#"
name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_INSTANCE_ID%>"
validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
optionalActionJavascript="DND_MOVE_PORTLET_JS">

Then at the end of the section, add:

<dnd:additionalAction namespace="wp" type="portlet_ID" action="#"


name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_ID%>"
validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
supportsMultiselect="true" multiselectDelimiter="__DND_DELIM__"
optionalActionJavascript="DND_ADD_PORTLET_JS"/></dnd:drop>

The easiest way to do this would be to add the following above your layout node:
<dnd:drop namespace="wp" type="portlet_windowID" action="#"
name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_INSTANCE_ID%>"
validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
optionalActionJavascript="DND_MOVE_PORTLET_JS"><table><%-- We use these
rows to make the vertical drop zones large enough to interact with.
There is a problem when trying to get a table to expand to fill an
entire region vertically. --%><tr valign="top"><td>&nbsp;</tr><tr
style="height:100%;"><td>&nbsp;</td></tr><tr
valign="bottom"><td>&nbsp;</td></tr></table><dnd:additionalAction
namespace="wp" type="portlet_ID" action="#"
name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_ID%>"
validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
supportsMultiselect="true" multiselectDelimiter="__DND_DELIM__"
optionalActionJavascript="DND_ADD_PORTLET_JS"/></dnd:drop>

Then add your layout node loop.

Then at the end, add the following:

<td style="width:10px;" valign="top"><dnd:drop namespace="wp"


type="portlet_windowID" action="#"
name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_INSTANCE_ID%>"
validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
optionalActionJavascript="DND_MOVE_PORTLET_JS"><table><%-- We use these
rows to make the vertical drop zones large enough to interact with.
There is a problem when trying to get a table to expand to fill an
entire region vertically. --%><tr valign="top"><td>&nbsp;</tr><tr
style="height:100%;"><td>&nbsp;</td></tr><tr
valign="bottom"><td>&nbsp;</td></tr></table><dnd:additionalAction
namespace="wp" type="portlet_ID" action="#"
name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_ID%>"
validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
supportsMultiselect="true" multiselectDelimiter="__DND_DELIM__"
optionalActionJavascript="DND_ADD_PORTLET_JS"/></dnd:drop>

This code lets you drag before or after the portlet in that row.

Next, modify the Unlayered-Container-V.jsp file to be able to drag and drop in the
columns.

Add this tag lib:


<%@ taglib uri="/WEB-INF/tld/dnd.tld" prefix="dnd" %>

and this tag:


<dnd:DNDPortletHelper/>

Then in your layout loop, add this code into a row or div element above where your portlet is
called to render.
<dnd:drop namespace="wp" type="portlet_windowID" action="#"

name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_INSTANCE_ID%>"

validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
optionalActionJavascript="DND_MOVE_PORTLET_JS">&nbsp;
<dnd:additionalAction namespace="wp" type="portlet_ID" action="#"

name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_ID%>"

validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
supportsMultiselect="true"
multiselectDelimiter="__DND_DELIM__"
optionalActionJavascript="DND_ADD_PORTLET_JS" />
</dnd:drop>

Then, after the layout loop you should add a row or div like the following:
<dnd:drop namespace="wp" type="portlet_windowID" action="#"
name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_INSTANCE_ID%>"

validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
optionalActionJavascript="DND_MOVE_PORTLET_JS">&nbsp;
<dnd:additionalAction namespace="wp" type="portlet_ID" action="#"

name="<%=com.ibm.wps.dnd.util.Constants.PORTLET_ID%>"

validator="com.ibm.wps.dnd.impl.DNDPortletActionValidator"
supportsMultiselect="true"
multiselectDelimiter="__DND_DELIM__"
optionalActionJavascript="DND_ADD_PORTLET_JS" />
</dnd:drop>

These lines will give you the drop zones before and after the portlets in the column.

Theme changes

Finally you need to add the stylesheet for the page, These styles give your drop zones visible
areas during the drag and drop so that it is easy to see what areas can be dropped into (very
helpful when you have removed all portlets from a column).

/* DRAG AND DROP */


.dndDropAware{
border: 0px;
background-color: #FFEBC5;
}
.dndDropActive{
border: 0px;
background-color: #FF9000;
}
.dndDragging{
width: 100%;
filter: alpha(opacity=40);
}
.dndDragSelected{
border: 1px;
background-color: #DDDDDD;
}
.dndMoveCursor{
cursor:move;
}
.dndDropCursor{
cursor: pointer;
}
.dndNoDropCursor{
cursor: not-allowed;
}

.layoutRow {width: 100%; }


.layoutColumn {width: 100%; }

The easiest way to do the drop zones is to copy the Unlayered-Container-v and h.jsp
files to your skin from the IBM one, as this will set up the drag and drop areas easily for you.

Considerations when migrating


Default navigational state
This setting tells the portal container whether to render navigation nodes either in an expanded or
collapsed mode. This setting affects the rendering of the navigation tree as it appears on the left
side by default.

In version 5, this setting was set to true so that all nodes were shown as expanded on the right
side. This setting caused the navigational loop tags to loop through all the child tags and display
links to all the child pages.

In version 6, this default state is set to false. If you are using any coding to create drop downs or
flyouts that rely on the navigation loop tags producing links to all the children, you need to set
this value back to false. Otherwise it will generate links to only the top level and your drop down
lists will not appear fully populated.

To override this setting in version 6 you need to change the setting


navigation.expansion.defaultstate to true in the Configuration Service.
For more information on setting properties in version 6, see the Information center on this
topic
http://publib.boulder.ibm.com/infocenter/wpdoc/v6r0/topic/com.ibm.wp.ent.doc/wps/ads
etcfg.html

Behavior of Skins
When running with your 5.1 skins on 6.0 you will have an issue if your portlet supports the edit
mode. In version 6.0 the concept of edit defaults and personalize modes were added. The
standard edit mode is not referred to as personalize and those values are stored to the
customization database domain. But edit defaults will save the preferences to the release domain.
When using any 5.1 theme on 6.0, and clicking on edit this will go to the personalize mode even
if it is an administrator or manager doing the editing. To have this feature work correctly you
will need to add the edit defaults compatibility mode to your portlet, and add a link to your skin
so now have edit show the text as personalize, and the edit defaults as edit shared settings. The
following is an example from the 6.0 menu
<portal-navigation:urlGeneration contentNode="<%=pageID%>"
layoutNode="<%=windowID%>" portletMode="edit" themeTemplate="" ><c:set var="title"><a
href=<%= wpsURL.write(escapeXmlWriter); %>'<portal-fmt:text bundle="nls.titlebar"
key="edit" /></a>
<portal-navigation:urlGeneration contentNode="<%=pageID%>"
layoutNode="<%=windowID%>" portletMode="edit_defaults" themeTemplate="" ><c:set
var="title"><a href=”<% wpsURL.write(escapeXmlWriter); %>”><portal-fmt:text
bundle="nls.titlebar" key="edit.defaults" /></a>
Appendix A – Changing properties of the flyout

IBM provides two flyouts with the base theme: the people palette and the portlet palette. In your
implementation, you might have your own directory search portlet that you want to place on the
flyout page instead of using the default user People search portlet. If you remove the existing
portlet from the people palette, and place your own directory search portlet on the page, you will
encounter some problems (such as, the URL is not able to be created and exceptions are listed in
the log). When you removed the old portlet from the page, you removed a portlet instance with
the unique name of ibm.portal.People Palette Control.

The theme code that creates the URL to the flyout uses the URL generation services and targets
the original People Search portlet by name. After you remove it, the URL generation services
cannot find that portlet instance on the people palette page and it is unable to render the icon. You
have two options to fix this problem.

The recommended way is to give one of the portlets on that page the unique name as above
following only steps 2, 3, and 4 from the technote documented at: http://www-
1.ibm.com/support/docview.wss?rs=688&uid=swg21220164

Export the page (people palette) with this XML code:

<?xml version="1.0" encoding="UTF-8"?>


<request type="export" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" xsi:noNamespaceSchemaLocation="PortalConfig_1.2.xsd">
<portal action="locate">
<content-node action="export" uniquename="ibm.portal.People
Palette" />
</portal>
</request>

The result will be similar to the output listed here:

<component action="update" active="true" deletable="false" domain="rel"


modifiable="false" objectid="7_UV9FQLI11O1BF026LUV0FD08G3" ordinal="-1"
orientation="H" type="container" width="undefined">
<component action="update" active="true"
deletable="false" domain="rel" modifiable="false"
objectid="7_UV9FQLI11O1BF026LUV0FD08G7" ordinal="100" orientation="V"
type="container" width="undefined">
<component action="update" active="true"
deletable="false" domain="rel" modifiable="undefined"
objectid="7_UV9FQLI11O1BF026LUV0FD0880" ordinal="100" type="control"
uniquename="ibm.portal.People Palette Control" width="undefined">
<portletinstance action="update" domain="rel"
objectid="5_UV9FQLI11O1BF026LUV0FD0884"
portletref="3_UV9FQLI11O1BF026LUV0FD00C6"/>
</component>
</component>
</component>

Notice the line uniquename=”ibm.portal.People Palette Control”.


Reading from your output, you need to modify one of the components surrounding the portlet and
put the uniquename attribute on it with this exact value ibm.portal.People Palette
Control.

Another way, which was not tested, to fix the problem is to


edit the URL generation tag in the head.jspf file
and remove the layoutNode attribute from this line:

url:"<portal-navigation:urlGeneration contentNode='ibm.portal.People
Palette' layoutNode='ibm.portal.People Palette Control'
newWindow='true' portletWindowState='Normal'><% wpsURL.write(out); %></
portal-navigation:urlGeneration>",

If you put more than one portlet on the page, you will also have to change the size of the flyout.

To change the width, change the following lines in the file styles_theme.jspf.

<%--===================================================
FLYOUT
===================================================--%>
.portalFlyout{
position: absolute;
left: -390px;
width: 382px;
background-color: ${colors.bodyBackground};
}

Next, make sure that styles.jsp gets recompiled. If you do not have reloading enabled, you
will need to restart the server after editing the file.

In our example, we changed it to the following:

<%--===================================================
FLYOUT
===================================================--%>
.portalFlyout{
position: absolute;
left: -600px;
width: 600px;
background-color: ${colors.bodyBackground};
}

When making these changes, also change the size of the scrollable area for the flyout.

<div id="wpsFLYflyout" class="portalFlyout" >


<iframe class="portalFlyoutIframe" id="wpsFLY_flyoutIFrame"
frameborder="0px" width="380px" name="wpsFLY_flyoutIFrame"
src="<portal-logic:urlFindInTheme file="./flyoutInit.html" />"
scrolling="auto"></iframe>
</div>
In the flyout.jspf file, the value of 380 px needs to be changed to whatever you had set the
flyout site to above. In our example we set it to 600 .

Then if you want to change the speed at which the flyout happens, change
two parts of the JavaScript. First in the js directory, open the flyout.js
file and change these lines:

wpsFLY_minFlyout=0;var wpsFLY_move=25;if (wpsFLY_isIE)


wpsFLY_move=20;var wpsFLY_scrollSpeed=1;var wpsFLY_timeoutID=1;var
wpsFLY_fromTop=100;var wpsFLY_leftResize;var
wpsFLY_browserDimensions=new

The move variable needs to be changed if you want to change the speed of the flyout.

Then, in the same file farther down, change these two lines:
setTimeout('wpsFLY_internalScroll()',1);};function
wpsFLY_internalScrollLeft() {

By default it is 20. In the example, it is 1.

Then on this line, change these lines:


setTimeout('wpsFLY_internalScrollLeft()',1);};function
wpsFLY_internalResizeLeft(){

After making these changes, the flyout will move at a faster speed.

These methods wait X number of milliseconds (from the timeout above) to move it what you
specified above (in the wpsFly_move settings).
Appendix B – Removing unwanted space
Other customizations you might want to make on your portal, include:

Reducing space between portlets


The portlet has several things that control the spacing
this is controlled by the style
#mainContent {
padding:5px;
}

change it to 0 and most of that space goes away


the last bit comes from
.wpsPortletBody {
background-image:none;
margin:5px;
}

The wpsPortlet CSS has a 0px padding and the rest should go away
.wpsPortlet{
margin:5px;
border-left: 1px solid;
border-right: 1px solid;
border-bottom: 1px solid;
border-color: #CACACA;
background-image:none;
}

Additionally the drag-and-drop controls take up an amount of space. If you reduce the padding
above you can make it hard to interact with these controls. These controls are the drop zones for
where you can drop the item you are dragging. If you want to disable drag and drop
functionality, you can remove these tags from the portlet skin that is the default for the theme.
Appendix C – Drop down navigation example

Drop-down navigation is a common request for changing the navigational structure of portal.

You could replace the table with whatever you wanted from this example.

If you want to create a drop-down menu in the new version 6 theme, use the URL generation
services and the navigation model API.

In the JSP or servlet, find the following:


NavigationModelHome home = (NavigationModelHome)
ctx.lookup("portal:service/model/NavigationModel");

PortalStateManagerServiceHome serviceHome =
(PortalStateManagerServiceHome)
ctx.lookup("portal:service/state/PortalStateManager");
PortalStateManagerService service =
serviceHome.getPortalStateManagerService(request, response);

Then, add the following:


// do something (create URLs etc.)
urlFactory = service.getURLFactory();
EngineURL eUrl = urlFactory.newURL(Constants.SMART_COPY);
//EngineURL eUrl = urlFactory.newURL(new StateHolder(), false, false,
Constants.SMART_COPY);
final SelectionAccessorFactory selectionFct =
(SelectionAccessorFactory)
service.getAccessorFactory(SelectionAccessorFactory.class);
// get a selection controller that operates on the URL-specific state
final SelectionAccessorController selectionCtrl =
selectionFct.getSelectionAccessorController(eUrl.getState());

Then, loop through the navigation model:


NavigationModelProvider provider = (NavigationModelProvider)
home.getNavigationModelProvider();
NavigationModel model = provider.getNavigationModel(request, response);
NavigationNode nodeA = (NavigationNode)model.getRoot();
NavigationNode childNode = null;
NavigationNode childNode2ndLevel = null;
if(model.hasChildren(nodeA)) {
Iterator iter = model.getChildren(nodeA);
NavigationNode homeNode = (NavigationNode)iter.next();
Iterator homeIter = model.getChildren(homeNode);
while (homeIter.hasNext()) {

childNode = (NavigationNode)homeIter.next();
selectionCtrl.setSelection(childNode.getObjectID());

The root node is always ContentRoot, in most all cases, Home is the first node under the Content
Root, Iterate through those children to build the URL. The URLs will be built from this piece of
code href="<%=eUrl%> and the title comes from
childNode.getTitle(localCurrent).

In your default.jsp file, remove the sidenav.jsp include because you will not need side
navigation any more.

The files to update in your theme include: flyoutTop.js, topNav.jsp, spacer.gif, and style.css

You will find these in the zip file that goes along with this document, under the following
directory filesforwhitepaper\themes\testDropDown .
Appendix D – Right navigation example

To make this change, change this line in the default.jsp file:

From this:
<table style="width:100%; height:100%;" cellpadding="0px"
cellspacing="0px">
<tr><td valign="top"><portal-logic:if portletSolo="no"><%@ include
file="./sideNav.jspf" %></portal-logic:if></td><td width="100%"
height="100%" valign="top"><a name="wpsMainContent"></a><%-- Call the
portal engine command to render the portlets for this page --%><div
id="mainContent"><portal-core:screenRender/></div></td></tr></table>

To this:

<table style="width:100%; height:100%;" cellpadding="0px"


cellspacing="0px">
<tr><td width="100%" height="100%" valign="top"><a
name="wpsMainContent"></a><%-- Call the portal engine command to render
the portlets for this page --%><div id="mainContent"><portal-
core:screenRender/></div></td><td valign="top"><portal-logic:if
portletSolo="no"><%@ include file="./sideNav.jspf" %></portal-
logic:if></td></tr></table>
Notices
This information was developed for products and services offered in the U.S.A.

IBM may not offer the products, services, or features discussed in this document in other
countries. Consult your local IBM representative for information on the products and
services currently available in your area. Any reference to an IBM product, program, or
service is not intended to state or imply that only that IBM product, program, or service
may be used. Any functionally equivalent product, program, or service that does not
infringe any IBM intellectual property right may be used instead. However, it is the user's
responsibility to evaluate and verify the operation of any non-IBM product, program, or
service.

IBM may have patents or pending patent applications covering subject matter described
in this document. The furnishing of this document does not grant you any license to these
patents. You can send license inquiries, in writing, to:

IBM Director of Licensing


IBM Corporation
North Castle Drive
Armonk, NY 10504-1785
U.S.A.

The following paragraph does not apply to the United Kingdom or any other
country where such provisions are inconsistent with local law: INTERNATIONAL
BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-
INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE. Some states do not allow disclaimer of express or implied warranties in
certain transactions, therefore, this statement may not apply to you.

This information could include technical inaccuracies or typographical errors. Changes


are periodically made to the information herein; these changes will be incorporated in
new editions of the publication. IBM may make improvements and/or changes in the
product(s) and/or the program(s) described in this publication at any time without notice.

Any references in this information to non-IBM Web sites are provided for convenience
only and do not in any manner serve as an endorsement of those Web sites. The materials
at those Web sites are not part of the materials for this IBM product and use of those Web
sites is at your own risk.
IBM may use or distribute any of the information you supply in any way it believes
appropriate without incurring any obligation to you.

Any performance data contained herein was determined in a controlled environment.


Therefore, the results obtained in other operating environments may vary significantly.
Some measurements may have been made on development-level systems and there is no
guarantee that these measurements will be the same on generally available systems.
Furthermore, some measurements may have been estimated through extrapolation. Actual
results may vary. Users of this document should verify the applicable data for their
specific environment

Information concerning non-IBM products was obtained from the suppliers of those
products, their published announcements or other publicly available sources. IBM has not
tested those products and cannot confirm the accuracy of performance, compatibility or
any other claims related to non-IBM products. Questions on the capabilities of non-IBM
products should be addressed to the suppliers of those products.

All statements regarding IBM's future direction or intent are subject to change or
withdrawal without notice, and represent goals and objectives only.

All IBM prices shown are IBM's suggested retail prices, are current and are subject to
change without notice. Dealer prices may vary.

This information is for planning purposes only. The information herein is subject to
change before the products described become available.

This information contains examples of data and reports used in daily business operations.
To illustrate them as completely as possible, the examples include the names of
individuals, companies, brands, and products. All of these names are fictitious and any
similarity to the names and addresses used by an actual business enterprise is entirely
coincidental.

This information contains sample application programs in source language, which


illustrate programming techniques on various operating platforms. You may copy,
modify, and distribute these sample programs in any form without payment to IBM, for
the purposes of developing, using, marketing or distributing application programs
conforming to the application programming interface for the operating platform for
which the sample programs are written. These examples have not been thoroughly tested
under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability,
or function of these programs.

If you are viewing this information softcopy, the photographs and color illustrations may
not appear.
Alphabetical Index
A.............................................................................................................................................
AsynchronousContextMenu.js........................................................................................ 7
B.............................................................................................................................................
Banner.jspf...................................................................................................................... 5
browserDimensions.js..................................................................................................... 7
C.............................................................................................................................................
Control.jsp....................................................................................................... 5, 6, 45, 46
D.............................................................................................................................................
Default.jsp..................................................................................... 5, 9, 14, 18, 35, 56, 57
DefaultThemeItem........................................................................................................ 26
Drag And Drop........................................................................6, 7, 45, 46, 47, 48, 49, 54
MetaTagDataItems.................................................................................................... 5, 28
E.............................................................................................................................................
ElementJavascriptEventController.js.............................................................................. 7
Extension.........................7, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 38, 39, 40, 41
F.............................................................................................................................................
description..................................................................................................................... 10
Flyout.......................................................... 5, 7, 8, 13, 22, 27, 29, 37, 38, 49, 51, 52, 53
flyout.js..................................................................................................................7, 8, 53
flyout.jspf.................................................................................................................. 8, 53
Flyouts.....................................................................5, 7, 8, 13, 22, 27, 29, 37, 38, 49, 51
Footer.jspf....................................................................................................................... 5
text.................................................................................................................................10
textParam.......................................................................................................................10
title.................................................................................................................................10
user................................................................................................................................ 10
H.............................................................................................................................................
head_pageMenu.jspf....................................................................................................... 8
Head.jspf............................................................................................................. 5, 21, 52
HorizontalPageBarItems............................................................................................... 28
J..............................................................................................................................................
Javascript.................................................................5, 7, 8, 28, 42, 43, 45, 46, 47, 48, 53
js_cacheSettings.jspf....................................................................................................... 7
js_extensions.jspf........................................................................................................ 7, 8
js.jsp............................................................................................................................ 5, 7
L.............................................................................................................................................
if.......................................................................................................................... 9, 11, 57
pageMetaData......................................................................................................... 11, 21
unless.............................................................................................................................11
urlFindInSkin................................................................................................................ 11
M............................................................................................................................................
MainContextMenuItems......................................................................................... 29, 40
N.............................................................................................................................................
navigation.................................................................................................................. 9, 10
navigationLoop............................................................................................................... 9
navigationShift................................................................................................................ 9
navigationUrl.................................................................................................................10
url............................................................................................................................ 10, 52
urlGeneration...........................................................................................................10, 52
urlParam........................................................................................................................ 10
O.............................................................................................................................................
onload.............................................................................................................................. 8
P.............................................................................................................................................
pageContextMenu.jsp......................................................................................................8
PageContextMenuItems.......................................................................................... 29, 40
Palette................................................................................ 6, 7, 11, 12, 13, 20, 21, 51, 52
Policy.........................................................5, 6, 11, 12, 13, 14, 15, 16, 17, 18, 19, 35, 40
portletContextMenu.jsp...................................................................................................8
PortletContextMenuItems....................................................................................... 29, 40
S.............................................................................................................................................
SideNav.jspf.............................................................................................................. 5, 57
Styles............................................................................. 5, 6, 7, 20, 21, 28, 30, 43, 48, 52
styles_cacheSettings.jspf.............................................................................................6, 7
styles_extensions.jspf..................................................................................................6, 7
styles_help.jspf............................................................................................................6, 7
styles_ibm.jspf............................................................................................................ 6, 7
styles_oob.jspf.............................................................................................................6, 7
styles_portlet.jspf........................................................................................................ 6, 7
styles_rules.jspf..................................................................................................... 6, 7, 21
styles_theme.jspf................................................................................................... 6, 7, 52
Styles.jsp............................................................................................................... 5, 6, 52
T.............................................................................................................................................
ThemeContent............................................................................................. 23, 25, 26, 30
ThemeContentDescritporConstants.............................................................................. 25
ThemeContext................................................................................................... 23, 25, 26
themeExtension........................................................................................... 26, 31, 35, 36
themeExtensionItemIconUrl................................................................................... 26, 31
themeExtensionItemText........................................................................................ 26, 31
themeExtensionItemTooltip.................................................................................... 26, 31
themeExtensionItemUrl................................................................................................ 31
themeExtensionLoop...............................................................................................31, 35
themeExtensionRenderInclude..................................................................................... 31
ThemeIncludes.................................................................................................. 23, 24, 31
ThemeItemDescriptorConstants....................................................................................25
ThemeItems.............................................................................................................23, 26
ThemeJspInclude.........................................................................................24, 25, 27, 29
ThemeJspIncludeDescriptorConstants.......................................................................... 25
ThemeLinkItem.........................................................................24, 26, 29, 31, 37, 39, 40
ThemetextItem................................................................................ 24, 26, 27, 28, 33, 34
TopNav.jspf.....................................................................................................................5
U.............................................................................................................................................
UnlayeredContainer-H.jsp........................................................................................ 6, 46
UnlayeredContainer-V.jsp.............................................................................................. 6
V.............................................................................................................................................
VerticalPageBarItems................................................................................................... 29