Details
-
New Feature
-
Status: Closed
-
Major
-
Resolution: Fixed
-
2.1-dev, 2.1
-
None
Description
Being able to "print" the contents of one portlet without any layout, navigation and window decoration is a commonly requested feature.
I'm going to provide a custom "print" mode, including a nice print portlet decorator action/icon, using the newly provided support for
custom PortletModes and WindowStates (see: JS2-523).
Rendering a portlet "separately", without any additional layout, navigation and/or window/portlet decoration isn't straightforward.
First of all, the preferred way of providing this is using a popup browser window.
Simply using something like the portlet pipeline won't do for rendering as that is just "raw" output: a HTML (or other content type) fragment only.
What we need is the rendering of the original page header and body, including and especially the css stylesheets, but now only with the content of the selected portlet.
Furthermore, this portlet might need to be interactive.
Meaning: a user still can interact with the portlet and possibly even change (render) parameters and portlet mode (sic!).
But, as this is a separate popup browser window and the same portlet (window) is also displayed in the original browser window, how should
changes to the (navigational) state in the one window effect the rendering in the other window?
Note: this isn't a "new" problem: any popup/secondary window displaying one or more portlets exhibits the same problems.
I'm going to provide a solution using a custom "solo" WindowState: navigational state of a Portlet in "solo" state will not be persisted in the session.
Note: if you happen to (have to) use PathNavigationalState instead of SessionNavigationalState, this isn't your problem, but then, you probably have others...
I've borrowed The "solo" WindowState from the (draft) WSRP 2.0 specification:
6.10.4 "wsrp:solo" Window State
The wsrp:solo window state is an indication the Portlet is the only Portlet being rendered in the aggregated page.
A Portlet SHOULD generate richer content when its window state is wsrp:solo
I will provide a new custom DecoratorActionsFactory: PrintSoloDecoratorActionsFactory using the custom "print" mode and "solo" state.
(see for a short description of the new Portlet DecoratorAction handling: JS2-523).
The PrintSoloDecoratorActionsFactory will feed the DecoratorValve with the custom "print" mode and "solo" state as supported actions.
If:
- a portlet decorator specifies this factory in its decorator.properties like this:
actions.factory=org.apache.jetspeed.decoration.PrintSoloDecoratorActionsFactory
- and the portlet to be decorated belongs to an PortletApplication supporting custom portlet mode "print" and custom window state "solo"
(possibly by mapping different named values using jetspeed-portlet.xml, seeJS2-523)
- and the portlet itself also supports the custom "print" mode as defined in its portlet.xml definition:
...
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>print</portlet-mode>
</supports>
...
- and both the "print" mode and "solo" state are current possible/allowed
Then:
The PrintSoloDecoratorActionsFactory will "merge" the "solo" state DecoratorActionTemplate with the "print" DecoratorActionTemplate,
leading to one "print" action which will invoke the portlet in "print" mode and "solo" state in a popup (_blank) target browser window.
If only "print" mode is possible/allowed, the "print" action/icon will be rendered as usual but only effect the portlet PortletMode.
If only "solo" state is possible/allowed, the PrintSoloDecoratorActionsFactory will remove the action and no action/icon will be shown for it.
Finally, if the current WindowState is "solo", all the other WindowState actions will be removed. This to prevent a user to "fall back" to
another WindowState within a "solo" popup window.
Note: normally a user won't notice this as the default portlet decorator (modified as described below) won't render any window decoration when in "solo" state.
The rendering of the "solo" state popup window content will be handled by a new layout portlet template called "solo".
The new "solo" template layout.vm will render only the selected portlet and delegate that to the portlet decorator.
I'll adjust the default portlet decorator.vm to handle rendering "solo" state portlets.
Right now, a normally (e.g. not "solo") rendered portlet is wrapped in a div with a "PContent" class.
Most portlet decorator css styles, have a border defined for this "PContent" class, which is a bit annoying when you want to render a portlet
"solo" without any window decoration effect.
So, I'm going to wrap a portlet rendered normally in another div with a new class "PContentBorder" and move the border definitions from
the "PContent" class to the "PContentBorder".
Then, when rendering a portlet in "solo" state, the portlet is only wrapped in the div with the "PContent" class and no extra decoration border
is shown anymore.
I'll showcase this new feature using the "PickANumberPortlet" portlet from the demo portlet application.
For this, I'll add custom-portlet-mode "print" and custom-window-state "popup" to its portlet.xml and add "print" as a supported mode of "PickANumberPortlet".
And I'll map the "popup" custom window state to the Jetspeed provided "solo" state using jetspeed-portlet.xml.
Finally, I'll extend the PickANumberPortlet to override the GenericPortlet.doDispatch method as that won't handle a custom PortletMode
(it will throw a PortletException if you don't override/handle this yourself).