| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| <html> |
| <head> |
| <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title>Configuring the Cocoon Portal</title> |
| <link href="http://purl.org/DC/elements/1.0/" rel="schema.DC"> |
| <meta content="Carsten Ziegeler" name="DC.Creator"> |
| <meta content="Joel Greenyer" name="DC.Creator"> |
| <meta content=" |
| This document describes the use and configuration |
| of the (new) cocoon portal block. |
| " name="DC.Description"> |
| </head> |
| <body> |
| |
| <h1>Introducing the Cocoon Portal</h1> |
| |
| <p> |
| This document describes the use and configuration |
| of the (new) cocoon portal that you can find in the "portal" block. |
| (Don't mix this with the older portal version that you can |
| find in the "portal-fw" block.) |
| </p> |
| |
| <h2>Important parts of the Cocoon Portal</h2> |
| <p>TBD |
| </p> |
| |
| <h2>How is a portal page created by Cocoon?</h2> |
| <p>TBD |
| </p> |
| |
| <h2>I want to build my own portal! An approach</h2> |
| <p>TBD |
| </p> |
| |
| |
| |
| <h1>Configuring the Portal contents</h1> |
| |
| <p> |
| The configuration of a coplet is done in several steps that are outlined |
| in the next chapters. |
| </p> |
| |
| <h2>Configuring Coplets</h2> |
| <p> |
| Configuring coplets is like defining a class and creating their instances. |
| So in fact, you define the available coplets (= classes) and each portal |
| view gets some instances of these coplets. |
| </p> |
| <h3>Available Coplet Types</h3> |
| <p> |
| Before you can define your available coplets, you have to define the |
| available coplet types, or the so called coplet base data. The current |
| sample contains an XML document for this: |
| </p> |
| <pre class="code"> |
| ... |
| <coplets> |
| <coplet-base-data id="URICoplet"> |
| <coplet-adapter>uri</coplet-adapter> |
| </coplet-base-data> |
| </coplets> |
| ... |
| </pre> |
| <p>In the example above, we define one coplet type, the <em>URICoplet</em>, |
| that uses the <em>uri coplet adapter</em>. By this we define a type, |
| that uses URIs to get the content of a coplet.</p> |
| <p>You can add different coplet types with additional configuration here, |
| but rarely have to touch this file.</p> |
| <h3>Available Coplets</h3> |
| <p> |
| Based on the coplet types, you can define the available coplets in your |
| portal application (= classes). In the example portal an own configuration |
| file contains these so called coplet datas. Here is an excerpt: |
| </p> |
| <pre class="code"> |
| ... |
| <coplets> |
| <coplet-data id="CZ Weblog" name="standard"> |
| <title>CZ's Weblog</title> |
| <coplet-base-data>URICoplet</coplet-base-data> |
| <attribute> |
| <name>uri</name> |
| <value xsi:type="java:java.lang.String" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">cocoon:/news/liverss?feed=http://radio.weblogs.com/0107211/rss.xml</value> |
| </attribute> |
| <attribute> |
| <name>buffer</name> |
| <value xsi:type="java:java.lang.Boolean" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">true</value> |
| </attribute> |
| <attribute> |
| <name>error-uri</name> |
| <value xsi:type="java:java.lang.String" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">cocoon:/news/CZ_weblog.rss</value> |
| </attribute> |
| </coplet-data> |
| </coplets> |
| ... |
| </pre> |
| <p>Each coplet data contains a unique id and additional configuration. A required |
| configuration is the underlying coplet base data. In the example above, |
| the <em>URICoplet</em> is used here. |
| </p> |
| <p>The above configured coplet data requires some configuration, like the |
| URI to invoke to fetch the content for this coplet. This configuration is |
| passed in the different attributes you see above. Each attribute has |
| a name and value. |
| </p> |
| <p>The set of coplet datas defines the set of available coplets a user can |
| choose from. If a user chooses to view a coplet, an instance of this coplet |
| data is created. If, e.g. the user chooses the same coplet twice, |
| two instances are created. This is useful for configurable coplets where |
| the user can choose the same coplet with different configurations. |
| </p> |
| <h3>Selected Coplets</h3> |
| <p> |
| The selected coplets are described by the set of coplet instance datas. |
| </p> |
| <pre class="code"> |
| ... |
| <coplets> |
| <coplet-instance-data id="CZ Weblog-1" name="standard"> |
| <coplet-data>CZ Weblog</coplet-data> |
| </coplet-instance-data> |
| </coplets> |
| ... |
| </pre> |
| <p> |
| The coplet instance data refers to its coplet data by specifying the |
| unique ID. The instance itself has a unique ID as well that is referenced |
| from the portal view. |
| </p> |
| <p> |
| In addition, a coplet instance data could have own configuration information. |
| </p> |
| |
| <h2>Configuring the arrangement of the defined Coplets</h2> |
| <p> |
| The portal view defines the ordering and arrangement of the coplets. This |
| view is defined in a hierarchical manner by nesting layout objects. At |
| each place, a coplet is located, a reference to a coplet instance data |
| is included. |
| </p> |
| <p> |
| The Cocoon portal provides several predefined layout elements you can use |
| for your portal view to create a nice layout: |
| </p> |
| <ul> |
| |
| <li>row - a row of items</li> |
| |
| <li>column - a column of items</li> |
| |
| <li>tab - a tab</li> |
| |
| </ul> |
| <p> |
| These are the "high-level" objects, you can use to define your |
| structure. You can nest them in any order to create a complex |
| layout. The layout is defined in an XML document as well, so let's |
| have a look at an example: |
| </p> |
| <pre class="code"> |
| ... |
| <composite-layout name="row"> |
| <item> |
| <coplet-layout name="coplet"> |
| <coplet-instance-data>Portal-Intro-1</coplet-instance-data> |
| </coplet-layout> |
| </item> |
| <item> |
| <coplet-layout name="coplet"> |
| <coplet-instance-data>Portal-Bottom-1</coplet-instance-data> |
| </coplet-layout> |
| </item> |
| </composite-layout> |
| ... |
| </pre> |
| <p> |
| In the example above, we define a row containing two coplets. This is done |
| by selecting the row layout and defining the childs (or items) of this |
| layout. In this case the items are two new layout objects, the coplet |
| layouts that can contain a coplet. The coplet layout has a reference |
| to the coplet instance data. |
| </p> |
| |
| <h2>The Rendering Process</h2> |
| <p> |
| Each layout object has a defined renderer that is used to render this |
| layout object. You can find the renderers in the cocoon.xconf. Each renderer |
| has a unique name that is used to identify this renderer. |
| </p> |
| <p> |
| A central component, the layout factory (configured in the cocoon.xconf as |
| well), contains a list of all available layout objects, like the row, |
| the column etc. The configuration for each layout object contains also |
| the corresponding renderer information. So, here is the configuration |
| which renderer will be used to render the layout object. |
| </p> |
| <p> |
| A renderer itself can be configured in various ways. The portal engine uses |
| so called aspects (don't mess them with AOP), that are used to enhance |
| to features of renderer, allowing - simplifying - a multiple inheritance |
| which is not possible in Java. Have a look at the cocoon.xconf for |
| the different renderer configurations. |
| </p> |
| |
| |
| |
| <h1>Create a new skin for your portal</h1> |
| |
| <p>This section will explain the concepts of the portal layout, |
| considering the <span class="codefrag">skins/basic/</span> skin provided with cocoon, |
| and will describe how to create a new skin by extending the |
| existing stylesheets.</p> |
| |
| <div class="note">The skin path can be changed in the portal's sitemap. There is |
| a <span class="codefrag">global-variable</span> specifying the path to the skin folder.</div> |
| |
| <p>The basic cocoon portal skin is a nice and simple example how to visualize a portal. |
| There are several elements that allow to customize the look and feel of the portal. |
| A portal with the basic skin consists of </p> |
| |
| <ul> |
| |
| <li>a <em>header</em> |
| </li> |
| |
| <li>a <em>tab row</em> |
| </li> |
| |
| <li>a <em>content section</em> containing the coplet windows</li> |
| |
| <li>and a <em>footer </em> |
| </li> |
| |
| </ul> |
| |
| <div align="center"> |
| <img class="figure" alt="Parts of the portal" src="images/portal-parts.gif" height="300" width="400"></div> |
| |
| <p>The tab row is actually a part of the content section. As well, a tab row can |
| be provided to any coplet window.</p> |
| |
| <h2>The skin's stylesheets</h2> |
| <p>If we take a look at the <span class="codefrag">skins/basic/styles</span> directory, we |
| find a number of stylesheets: |
| </p> |
| <ul> |
| |
| <li> |
| <span class="codefrag">portal-page.xsl</span>: Creates final HTML page</li> |
| |
| <li> |
| <span class="codefrag">tab.xsl</span>: layout of the tab row.</li> |
| |
| <li> |
| <span class="codefrag">window.xsl</span>: coplet window layout</li> |
| |
| <li> |
| <span class="codefrag">column.xsl</span>: layout of a column</li> |
| |
| <li> |
| <span class="codefrag">row.xsl</span>: layout of a row</li> |
| |
| <li> |
| <span class="codefrag">login-page.xsl</span>: layout of the login page</li> |
| |
| </ul> |
| <p>The <span class="codefrag">window.xsl</span> stylesheet determines the layout of a |
| coplet window. Normally, a coplet window will contain a header row with a |
| title and buttons like minimize, close, etc.</p> |
| <p>These coplet windows are arranged in rows and columns to create |
| the arrangement typical for portals. There can be several rows per column |
| and several columns in the content section. So the thinking is a little |
| different than in usual HTML tables.</p> |
| <p>The content section or content row usually has a tab row located at the top |
| and the coplet windows are arranged below. The layout of the tabs is |
| specified in the <span class="codefrag">tab.xsl</span> stylesheet.</p> |
| <p>The <span class="codefrag">portal-page.xsl</span> stylesheet encapsulates the content section |
| with the tab row and allows to define a page header and a footer. |
| This is probably the first stylesheet we want to take a closer look at. |
| </p> |
| <div class="note">The <span class="codefrag">tab.xsl</span>, <span class="codefrag">column.xsl</span>, |
| <span class="codefrag">row.xsl</span> and <span class="codefrag">window.xsl</span> stylesheets |
| are used by the portal components directly and won't be found |
| anywhere in the sitemap. The <span class="codefrag">cocoon.xconf</span> |
| defines which stylesheets will be used by the portal.</div> |
| |
| <h2>The portal-page.xsl</h2> |
| <p> |
| Here is the place to change the design of the header and footer row. |
| This stylesheet is used to construct the final HTML page, which displays |
| the portal. The code sample here displays the main template match node of the |
| stylesheet. |
| </p> |
| <pre class="code"> |
| ... |
| <xsl:template match="/"> |
| <html> |
| <head> |
| <link type="text/css" rel="stylesheet" href="page.css"/> |
| </head> |
| <body> |
| <table bgColor="#ffffff" border="0" |
| cellPadding="0" cellSpacing="0" width="100%"> |
| <tbody> |
| |
| <!-- header row --> |
| <tr> |
| <td colspan="2"> |
| <table border="2" cellPadding="0" cellSpacing="0" width="100%"> |
| <tbody> |
| <tr> |
| <td colspan="2" noWrap="" height="10" bgcolor="#DDDDDD"> |
| </td> |
| </tr> |
| <tr> |
| <td bgcolor="#CCCCCC" height="100" align="center" |
| valign="middle" width="100%"> |
| <font size="80pt">Cocoon Portal</font> |
| </td> |
| </tr> |
| <tr> |
| <td colspan="2" noWrap="" height="10" bgcolor="#DDDDDD"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| |
| <!-- content/tab row --> |
| <tr> |
| <td> |
| <xsl:apply-templates/> |
| </td> |
| </tr> |
| |
| <!-- footer row --> |
| <tr> |
| <td colspan="2"> |
| <table border="2" cellPadding="0" cellSpacing="0" width="100%"> |
| <tbody> |
| <tr> |
| <td colspan="2" noWrap="" height="10" bgcolor="#DDDDDD"> |
| <img height="1" src="sunspotdemoimg-space.gif" width="1"/> |
| </td> |
| </tr> |
| <tr> |
| <td colspan="2" noWrap="" height="30" bgcolor="#CCCCCC"> |
| <img height="1" src="sunspotdemoimg-space.gif" width="1"/> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </body> |
| </html> |
| </xsl:template> |
| ... |
| </pre> |
| |
| <h2>The tab.xsl</h2> |
| <p>From the <span class="codefrag">portal-page.xsl</span> stylesheet, we will now |
| move upwards in the XSL transformation steps and take a look at the |
| stylesheet that was processed before, the <span class="codefrag">tab.xsl</span>.</p> |
| <p>Again, this source snippet shows the main template match node of the stylesheet:</p> |
| <pre class="code">... |
| <!-- Process a tab --> |
| <xsl:template match="tab-layout"> |
| <!-- ~~~~~ Begin body table ~~~~~ --> |
| <table border="2" cellpadding="0" cellspacing="0" width="100%"> |
| <!-- ~~~~~ Begin tab row ~~~~~ --> |
| <tr> |
| <td> |
| <table summary="tab bar" border="2" cellpadding="0" |
| cellspacing="0" width="100%"> |
| <tr vAlign="top"> |
| <xsl:for-each select="named-item"> |
| <xsl:choose> |
| <xsl:when test="@selected"> |
| <!-- ~~~~~ begin selected tab ~~~~~ --> |
| <td valign="middle" bgcolor="#DDDDDD"> |
| <b> |
| <a href="{@parameter}"> |
| <font color="#000000"> |
| <xsl:value-of select="@name"/> |
| </font> |
| </a> |
| </b> |
| </td> |
| <!-- ~~~~~ end selected tab ~~~~~ --> |
| </xsl:when> |
| <xsl:otherwise> |
| <!-- ~~~~~ begin non selected tab ~~~~~ --> |
| <td valign="middle" bgcolor="#CCCCCC" > |
| <div class="tab"> |
| <a href="{@parameter}"> |
| <xsl:value-of select="@name"/> |
| </a> |
| </div> |
| </td> |
| <!-- ~~~~~ end non selected tab ~~~~~ --> |
| </xsl:otherwise> |
| </xsl:choose> |
| </xsl:for-each> |
| <!-- ~~~~~ last "blank" tab ~~~~~ --> |
| <td width="99%" bgcolor="#CCCCCC" align="right"> |
| </td> |
| </tr> |
| </table> |
| </td> |
| </tr> |
| <!-- ~~~~~ End tab row ~~~~~ --> |
| |
| <!-- ~~~~~ Begin content row ~~~~~ --> |
| <tr> |
| <td bgcolor="#FFFFFF"> |
| <xsl:apply-templates/> |
| </td> |
| </tr> |
| <!-- ~~~~~ End content row ~~~~~ --> |
| </table> |
| </xsl:template> |
| ...</pre> |
| <p>The first row that is created here contains the definition of the tabs. |
| The <span class="codefrag"><xsl:choose></span> element differentiates between the |
| currently selected tab and all other tabs. The <span class="codefrag">@selected</span> |
| attribute is generated by the portal and can be accessed as shown |
| above. As well, the portal provides the tab's <span class="codefrag">@parameter</span> |
| (usually the tab's link) and <span class="codefrag">@name</span> attributes. </p> |
| <div class="note">Depending on the configuration of the portal, it is possible |
| that tabbed areas are nested inside each other. So be careful how a tab |
| row might look in the middle of another content section.</div> |
| <p>Nice looking tabs can become pretty complex, take a look at the |
| <span class="codefrag">tab.xml</span> stylesheet in the <span class="codefrag">skins/common/</span> |
| skin to see another example.</p> |
| <p>Below the tabs, another table cell is defined that will be filled |
| with the contents of the tabbed area. This content will have been processed |
| by the <span class="codefrag">columns.xsl</span> stylesheet before - and before that by the |
| <span class="codefrag">row.xsl</span> stylesheet.</p> |
| |
| <h2>The column.xsl and row.xsl</h2> |
| <p>The <span class="codefrag">column.xsl</span> and <span class="codefrag">row.xsl</span> stylesheets |
| define the look of the tables in which the coplet windows will be placed. |
| Usually, nothing exciting happens in these stylesheets. Here is a listing of the |
| important parts, just to give a complete overview. |
| </p> |
| <p>The main template match node of the <span class="codefrag">column.xsl</span> stylesheet:</p> |
| <pre class="code">... |
| <!-- Process a Column --> |
| <xsl:template match="column-layout"> |
| |
| ... |
| |
| <table border="{$border}" cellSpacing="0" cellpadding="0" |
| width="100%"> |
| <xsl:if test="@bgcolor"> |
| <xsl:attribute name="bgcolor"> |
| <xsl:value-of select="@bgcolor" /> |
| </xsl:attribute> |
| </xsl:if> |
| <tr vAlign="top"> |
| <xsl:for-each select="item"> |
| <td> |
| <xsl:if test="@bgcolor"> |
| <xsl:attribute name="bgcolor"> |
| <xsl:value-of select="@bgcolor" /> |
| </xsl:attribute> |
| </xsl:if> |
| <xsl:if test="@width"> |
| <xsl:attribute name="width"> |
| <xsl:value-of select="@width" /> |
| </xsl:attribute> |
| </xsl:if> |
| <xsl:apply-templates /> |
| </td> |
| </xsl:for-each> |
| </tr> |
| </table> |
| </xsl:template> |
| ...</pre> |
| <p>The main template match node of the <span class="codefrag">row.xsl</span> stylesheet:</p> |
| <pre class="code">... |
| <!-- Process a row --> |
| <xsl:template match="row-layout"> |
| |
| ... |
| |
| <table border="{$border}" cellSpacing="10" width="100%"> |
| <xsl:if test="@bgcolor"> |
| <xsl:attribute name="bgcolor"> |
| <xsl:value-of select="@bgcolor" /> |
| </xsl:attribute> |
| </xsl:if> |
| <xsl:for-each select="item"> |
| <tr vAlign="top"> |
| <xsl:if test="@bgcolor"> |
| <xsl:attribute name="bgcolor"> |
| <xsl:value-of select="@bgcolor" /> |
| </xsl:attribute> |
| </xsl:if> |
| <td> |
| <xsl:apply-templates /> |
| </td> |
| </tr> |
| </xsl:for-each> |
| </table> |
| </xsl:template> |
| ...</pre> |
| |
| <h2>The window.xsl</h2> |
| <p>The <span class="codefrag">window.xsl</span> stylesheet determines the design of the coplet |
| windows and probably takes the most design effort compared to the other stylesheets. |
| A coplet window consists of a table header with the window title and a number |
| of buttons like close, minimize, maximize etc. The basic skin provides some |
| images in the <span class="codefrag">images/</span> subfolder. The rest of the window will |
| be filled with the coplet content, depending on the configuration of |
| the coplet.</p> |
| <p>A slightly more complex example can be found in the |
| <span class="codefrag">skins/common/</span> skin.</p> |
| <p>The listing below shows the main template match node:</p> |
| <pre class="code">... |
| <xsl:template match="window"> |
| |
| ... |
| |
| <table border="2" cellSpacing="0" cellpadding="0" width="100%"> |
| <tr vAlign="top"> |
| <td bgColor="{$bgColor}" valign="middle"> |
| <font> |
| <xsl:attribute name="color">#ffffff</xsl:attribute> |
| <xsl:attribute name="face">Arial</xsl:attribute> |
| <xsl:attribute name="size">2</xsl:attribute> |
| <xsl:choose> |
| <xsl:when test="@title"> |
| <b><xsl:value-of select="@title"/></b> |
| </xsl:when> |
| <xsl:otherwise> |
| <b><xsl:value-of select="title"/></b> |
| </xsl:otherwise> |
| </xsl:choose> |
| </font> |
| </td> |
| <td align="right" bgColor="{$bgColor}"> |
| <xsl:if test="fullscreen-uri"> |
| <a href="{fullscreen-uri}"> |
| <img src="customize.gif" border="0" alt="Full Screen"/> |
| </a> |
| </xsl:if> |
| <xsl:if test="maxpage-uri"> |
| <a href="{maxpage-uri}"> |
| <img src="show.gif" border="0" alt="Max Page"/> |
| </a> |
| </xsl:if> |
| <xsl:if test="maximize-uri"> |
| <a href="{maximize-uri}"> |
| <img src="maximize.gif" border="0" alt="Maximize"/> |
| </a> |
| </xsl:if> |
| <xsl:if test="minimize-uri"> |
| <a href="{minimize-uri}"> |
| <img src="minimize.gif" border="0" alt="Minimize"/> |
| </a> |
| </xsl:if> |
| <xsl:if test="remove-uri"> |
| <a href="{remove-uri}"> |
| <img src="delete.gif" border="0" alt="Delete"/> |
| </a> |
| </xsl:if> |
| </td> |
| </tr> |
| <tr> |
| <td colSpan="2"> |
| <xsl:apply-templates select="content"/> |
| </td> |
| </tr> |
| </table> |
| </xsl:template> |
| ...</pre> |
| |
| |
| |
| <h1>Further topics</h1> |
| |
| <p> |
| |
| </p> |
| |
| |
| </body> |
| </html> |