portals-jetspeed-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Santiago Gala <sg...@hisitech.com>
Subject Re: Jetspeed Proposal: iframe portlet control
Date Tue, 05 Mar 2002 17:10:38 GMT
Glenn Golden wrote:

>Here is a proposal for Jetspeed.  We (the CHEF team at U of M) need this in
>our Jetspeed, and I'd like to develop it for Jetspeed proper.  I'd like to
>get your feedback, comments, and suggestions, and to find out if we can put
>this into the product.
> 
>* * *
> 
>1.0 Goals:
> 
>To select any portlet to be placed into an iframe in the portal page.  This
>allows the portlet:
> 
>1.1  page size control with scrolling
> 
>Users would be able to specify the size of the portlet on the page, probably
>just the height, as the layout figures the width.  If the portlet content is
>larger than the footprint, scroll bars would appear to allow the portlet to
>be scrolled independently of the rest of the portal page.
> 
>1.2  independent updating, scriptable
> 
>Each portlet in an iframe could have its contents refreshed without having
>the rest of the page refreshed.  This would happen if the user pressed a
>link or a form submit within the portlet content, or if javascript in the
>portal page caused the iframe to refresh (usually by changing the src=
>attribute of the iframe).  Nothing else on the page would change when a
>portlet refreshes.  Multiple portlets in iframes on the same portal page
>could refresh concurrently, independently.
> 
>1.3  directed form processing
> 
>When a form from an iframe'ed portlet is submitted, it is sent to a URL
>which causes just the portlet to be displayed back into the iframe.  For
>Velocity portlets, this means that just that one addressed portlet would get
>a change to process the form data.  This focuses the submit to the one
>portlet, which is usually what we want.
> 
>When an AbstractPortlet is placed in an iframe, it would be using real
>Turbine actions encoded into the form submit, which are already focused on
>the portlet's action class.
> 
>* * *
> 
>2.0  Details
> 
>2.1  Title Bar in Portal, Portlet in iframe
> 
>When a portlet is placed into an iframe, the portlet title bar and controls
>are left in the portal page, with the iframe just below and sized to fit the
>width of the portlet's footprint on the screen.
> 
>2.2  User's select, Mix and match
> 
>Users would be able to mix portlets on a portal page that are directly on
>the page with those that are in iframes.  Any portlet can be placed into an
>iframe.
> 
>2.3  Portlet Content URL
> 
>To support the iframe's addressing of a single portlet, a special URL if
>formed to address the portlet content.
> 
>* * *
> 
>3.0  Implementation
> 
>3.1  Portlet Content
> 
>I distinguish between the portlet's full display, including the
>PortletControl, and just the display from the portlet itself, calling the
>later the portlet content.  To get a display of just the portlet content, a
>new screen is added to Jetspeed called "Content".  This consists of a screen
>template, Content.vm, and a page layout template, also called Content.vm.
>
Content looks as a confusing name. I would prefer if both the screen and 
the layout are named "clear", instead of content. We used to have clear 
screens before (in 1.3a1), to mean screens where there were no 
navigation, control, etc.

Otherwise (see my small comment on jlink below), I agree with the proposal.

I'm beeing careful about naming, since the names stand a lot on the way 
we understand code, and getting good understanding of source code is 
needed if we are going to keep improving jetspeed. If anyone has a 
better suggestion on naming, please stand up!

> 
>3.1.1  The layout template achieves the goal of delivering just the screen
>without any navigation:
> 
><html>
>  <head>
>    <base href="$clink.External" />
>    <link href="$clink.setURI("css/default.css").Absolute" type="text/css"
>rel="stylesheet" /> 
>  </head>
>  <body bgcolor="#ffffff">
>    $screen_placeholder
>  </body>
></html>
>
>3.1.2  The screen template achieves the goal of delivering just the portlet
>content, not the whole page, not the portlet control:
> 
>#if ($data.Portlet)
> $jetspeed.getPortletContent($data.Portlet)
>#else
> <p>Portlet missing</p>
>#end
>
>Notice that there is a new method added to the JetspeedTool:
>getPortletContent().  This is just like getPortlet(), except that when the
>named portlet is found, getPortlet() points at the control, and
>getPortletContent() points at the portlet within the control.
> 
>3.1.3  Here's the code to add to JetspeedTool:
> 
>    /** 
>     * Return the content of a named portlet, without the controller. This
>portlet is sought in 
>     * the current PSML resource.
>     *
>     * @param name the name of the portlet to render
>     * @return the rendered content of the portlet
>     */
>    public ConcreteElement getPortletContent(String name)
>    {
>        ConcreteElement result = null;
>        Portlet found = null;
>        Stack sets = new Stack();
>        sets.push(rundata.getProfile().getRootSet());
>        
>        while ((sets.size() > 0) && (found==null))
>        {
>            PortletSet set = (PortletSet)sets.pop();
>            
>            if (set.getName().equals(name))
>            {
>                found = set;
>            }
>            else
>            {
>                Enumeration en = set.getPortlets();
>                while((found==null) && en.hasMoreElements())
>                {
>                    Portlet p = (Portlet)en.nextElement();
>                        
>                    // unstack the controls to find the real PortletSets
>                    Portlet real = p;
>                    while (real instanceof PortletControl)
>                    {
>                        real = ((PortletControl)p).getPortlet();
>                    }
>                        
>                    if (real instanceof PortletSet)
>                    {
>                        // we'll explore this set afterwards
>                        sets.push(real);
>                    }
>                    else if (p.getName().equals(name))
>                    {                        
>                        found = real;
>                    }
>                }
>            }
>        }
>        
>        if (found!=null)
>        {
>            result = found.getContent(rundata);
>        }
>        
>        if (result==null)
>        {
>            //the customizer already streamed its content, return a stub
>            result = new ConcreteElement();
>        }
> 
>        return result;
>    }
>
>3.1.4  An action called Content is available to select the new content
>screen for a request: 
> 
>public class Content extends Action
>{
>    public void doPerform(RunData data)
>    {
>        // pick the "Content" screen, and matching page layout
>        jdata.setScreenTemplate("Content");
>    }
>}
>
>3.1.5  URLs
> 
>To invoke this new screen, the URL looks like this:
> 
>/jetspeed/portal/template/Content/portlet/<portlet name>
> 
>or
> 
>/jetspeed/portal/template/Content?portlet=<portlet name>
> 
>or, using the action:
> 
>/jetspeed/portal?action=Content&portlet=<portlet name>
> 
> 
>3.1.6  Portlet Identifier
> 
>The portlet name is used to find the portlet, much as it is used in the
>jetspeed tool's getPortlet.  I see that this is being extended with
>"&container=".  Whatever we decide on to uniquely identify and find a
>portlet within a portal page, we need to use here as well, and the above
>URL's would be extended, extending the portlet=<name> with the additional
>information.
> 
>3.1.7  Form Action
> 
>Portlets in an iframe need to specify a different form action, to make sure
>that when the form is submitted, only the portlet content comes back.  The
>action url is the same as those in 3.1.5 above.  In a velocity template,
>this can be achieved with:
> 
>$jlink.setPortlet("$!data.Portlet")
> 
>
I have just deprecated setPortlet, due to confusing naming when we added 
void setPortlet( portlet) to JetspeedTemplateLink. I proposed 
forPortlet() instead.

Thus, your example would be:

$jlink.forPortlet("$!data.Portlet")

which looks cleaner to me. Is is read as "give me the jetspeed link for 
portlet $!data.Portlet"


>
>giving us the url of the form:
> 
>/jetspeed/portal/template/Content/portlet/<portlet name>
> 
>Note, if additional information is needed to identify the portlet, this
>additional information needs to be placed into $data so it can be used in
>the link, or, better yet, a new method could be added to $jlink (or
>setPortlet() updated?) to handle the properly id a portlet.
>
>If the portlet is in the portal page directly, not in an iframe, the above
>link works, with the /portlet/ being ignored.  Actually, the url becomes
> 
>/jetspeed/portal/template/Home/portlet/null.
> 
>We could enhance the JetspeedTemplateLink.setPortlet() call to do nothing if
>the portlet is null.
> 
>Note that if the portlet is in an iframe, the form submit request will be
>given only to that portlet, achieving our direct form processing goal.
> 
>3.2  Portlet Control
> 
>To place a portlet into an iframe, we can set a new portlet control for the
>portlet.  This new control, the iFramePortletControl, takes care of placing
>the portlet into the iframe.  Only portlets with this control would be
>placed into iframes; other portlets would be placed directly into the portal
>page.
> 
>Another option would be to have an optional parameter to any portlet, the
>"iframe" boolean, which all the portlet controls would look for.  In this
>case.  This may be easier to implement in the customizer, and give more
>flexibility.  For this proposal, I describe the iFramePortletControl
>approach.
>
>
> 
>3.2.1  iFramePortletControl
> 
>This is a velocity based portlet control, using an extension of the
>VelocityPortletControl to provide more context.  The iframe.vm file is a
>copy of the jetspeed.vm file, with one change:  Instead of placing the
>portlet content with:
> 
>$!portlet.getContent($data)
> 
>It places the iframe, in the same place, with:
> 
>                <iframe
>                    name="$portlet.Name"
>                    width="100%"
>                    frameborder="0"
>                    marginwidth="0"
>                    marginheight="0"
>                    scrolling="auto"
>                    align="middle"
>                    src="$iframeSrc">
>                </iframe>
>
>Note: rather than making a copy of jetspeed.vm as iframe.vm and modifying
>it, I'd like to use the one jetspeed.vm, enhanced to know to place iframe or
>not.  This plays into the other approach that makes all the controls iframe
>aware.
> 
>The $iframeSrc is made much like the actions in VelocityPortletControl by
>the extended class (see section 3.2.3).
> 
>3.2.2  iFramePortletControl registry entry
> 
>The entry for the new portlet control is:
> 
>    <portlet-control-entry name="iFramePortletControl" hidden="true">
>        <classname>umich.chef.util.VelocityPortletIFrameControl</classname>
>        <parameter name="theme" value="iframe.vm"/>
>        <meta-info>
>            <title>iFramePortletControl</title>
>        </meta-info>
>        <media-type ref="wml"/>
>        <media-type ref="html"/>
>    </portlet-control-entry>
>
>Note: the class is currently in my "umich.chef.util" package, but we would
>want to place it into a jetspeed package.
> 
>3.2.3  VelocityPortletIFrameControl
> 
>The extension to VelocityPortletControl to add the $iframeSrc to the context
>is:
> 
>public class VelocityPortletIFrameControl extends VelocityPortletControl
>{
>    /**
>     * This method allows subclasses of the VelocityPortletControl
>     * to populate the context of this control before rendering by
>     * the template engine.
>     *
>     * @param rundata the RunData object for this request
>     * @param context the Context used by the template
>     */
>    public void buildContext( RunData rundata, Context context )
>    {
>        Portlet portlet = getPortlet();
> 
>        String container = "na";
>        if ( portlet.getPortletConfig().getPortletSet() != null)
>        {
>             container =
>portlet.getPortletConfig().getPortletSet().getName();
>        }
> 
>        String iframeSrc = new RelativeDynamicURI( rundata )
>                            .addQueryData("action", "Content" )
>                            .addQueryData("portlet", portlet.getName() )
>                            .addQueryData("container", container )
>                            .toString();
>        context.put("iframeSrc", iframeSrc);
>    }
>}
>
>Note: This continues the container work, and would need to be updated to
>whatever methods we are using to id a portlet.
> 
>3.3  Customization
> 
>The customizers need to be modified to allow the user the choice of the
>control for the portlet.  Or, if we take the other approach, the user needs
>to be able to indicate iframe or not, and some iframe parameters (such as
>height).  I have not done this, nor do I know much about how this works
>(yet).
> 
>For now, to make a portlet be in an iframe, the .psml needs to be hand
>edited:
> 
> <entry parent="whoever">
>  <control name = "iFramePortletControl"/>
> </entry>
>
>4.0  Summary and Conclusion
> 
>I'd like to incorporate this work into the 1.3a3 jetspeed.  This would
>involve:
> 
>-update to the JetspeedTool (getPortletContent())
>-addition of the Content screen and layout templates
>-addition of the Content action, placed into the jetspeed package
>org.apache.jetspeed.modules.actions.controls
>-(possible) update to $jlink.setPortlet() to have it take care of the
>current portlet unique naming scheme, or (possibly) a new entry
>-addition of the iFramePortletControl to the controls.xreg
>-addition of the iframe.vm
>-addition of the VelocityPortletIFrameControl class, placed in the package
>org.apache.jetspeed.portal.controls
>-or- some changes to the set of controls to recognize a common set of
>portlet parameters for iframe
> 
> 
>4.1  Decisions
> 
>Do we want this in Jetspeed?
>
Why not? +1

> 
>Are there improvements to these details that better fit the jetspeed code
>and intentions?
>
I pointed small comments up, mostly terminology.

> 
>Do we want a single portlet control, or updates to them all?
>
I'm not sure about this one. We could have a property called "iframe", 
meaning that you want the portlet to be rendered in a separate (inline) 
frame. This could be taken as a hint to the portlet container. If the 
media allows for iframes, then iframe you get. If not, you could get a 
pop-up window connected through javascript with the main window (your 
get frame, but not inline) or current inline behaviour (no frame, but 
inline content). That would depend on implementation templates and 
client capabilities. Opinions?

> 
>How are we going to identify a portlet within a portal page?  What code will
>support forming this id and finding?
> 
>
A portlet is a relatively long lived object. It can (ideally) be 
rendered in several places in the same psml, and in different places for 
different users.

A portlet can be referred in two different ways:

- "positional id", like I want portlet "default.1.2.1" which means the 
first portlet of the second portletset of the first portletset in the 
default.psml resource. This breaks when the user rearranges (customizes) 
the resources.
- "absolute id". The name is independent of its position in psml. It can 
be achieved in two forms: the entry name (or id) itself, given in the 
registry for all instances and controlled by the site admin, or some 
metainfo name (or id), different per instance and controlled by the psml 
writer/customizer. It would be carried with the PortletConfig.

Some kind of metainfo id could be used for most applications. It could 
be generated as the PSML is parsed, or just filled in by hand (maybe 
this could be a good way to bootstrap it). Even if they are hand-written 
in PSML and are not guaranteed unique per psml, they could be useful to 
test the concepts.

>
>How to change the customizers to support portlet control choice?
> 
>Should we surface more iframe control to the user, such as height?
> 
>Should we make the iframe parameters different (bigger height) when the
>portlet is maximized?
> 
>* * *
> 
>I have preliminary versions of this coded and working.  I am happy to make
>changes based on the group's feedback and decisions.  I can then email files
>ready for checkin to a committer who would work with me on this.
> 
>Thanks for your time and attention.
> 
>- Glenn
> 
>--------------------------------------------
>Glenn R. Golden, Systems Research Programmer
>University of Michigan School of Information
> <mailto:ggolden@umich.edu> ggolden@umich.edu               734-615-1419
> <http://www-personal.si.umich.edu/~ggolden/>
>http://www-personal.si.umich.edu/~ggolden/
>--------------------------------------------
>
> 
>




--
To unsubscribe, e-mail:   <mailto:jetspeed-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:jetspeed-dev-help@jakarta.apache.org>


Mime
View raw message