XForms/仪表盘构建器
您希望一个表单可以布局单个页面仪表盘。在这种情况下,仪表盘由一组“Portlets”组成,每个 Portlet 都有独立的内容。
我们的仪表盘构建器将控制一个仪表盘库。每个仪表盘都有一个名称、布局信息以及在仪表盘中呈现的一系列 Portlet。在我们的示例中,仪表盘最多可以包含 36 个 Portlet,但最佳实践通常包含 7 个 Portlet,加上或减去一到两个。
我们的仪表盘布局将采用三种类型之一
- 行方向,其中同一行中的所有 Portlet 具有相同的高度
- 列方向,其中同一列中的所有 Portlet 共享相同的宽度
- 网格方向,其中所有 Portlet 必须包含在规则的网格结构中
该工具将允许用户创建一个新仪表盘并为其命名。然后,用户选择三种布局类型之一。每种布局类型都允许用户指定每行或每列的属性,例如使用像素的绝对宽度/高度或宽度/高度的相对高度/宽度百分比。请注意,为了允许仪表盘调整大小以适应不同的屏幕尺寸,应使用相对大小。
在每行、每列或每个网格中,用户可以指定一组 Portlet,然后为每个 Portlet 指定一些参数。
当用户保存仪表盘时,它将保存一个 XML 实例文档,其中包含仪表盘布局的规范。可以使用 XQuery 或 XSLT 将此布局转换为 CSS 文件,该文件在每次显示仪表盘时加载。
-
行
-
列
-
网格
此表单仅应在选择行布局或网格布局时显示行高度规范。类似地,只有在选择列布局或网格布局时才会显示列宽度。
以下代码提供了此逻辑。
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<title>Demonstration of relevant fields.</title>
<xf:model>
<xf:instance id="my-data" xmlns="">
<data>
<DashboardLayoutCode>row</DashboardLayoutCode>
</data>
</xf:instance>
<xf:instance id="views" xmlns="">
<data>
<row-info />
<col-info />
</data>
</xf:instance>
<xf:bind nodeset="instance('views')/row-info" relevant="instance('my-data')/DashboardLayoutCode!='col' " />
<xf:bind nodeset="instance('views')/col-info" relevant="instance('my-data')/DashboardLayoutCode!='row'" />
</xf:model>
<body>
<p>Demonstration of relevant fields. Grid layouts require both rows and columns to be specified.</p>
<xf:select1 ref="instance('my-data')/DashboardLayoutCode">
<xf:label>Enter Layout Type: </xf:label>
<xf:item>
<xf:label>Row</xf:label>
<xf:value>row</xf:value>
</xf:item>
<xf:item>
<xf:label>Col</xf:label>
<xf:value>col</xf:value>
</xf:item>
<xf:item>
<xf:label>Grid</xf:label>
<xf:value>grid</xf:value>
</xf:item>
</xf:select1>
<br />
<xf:group ref="instance('views')/row-info">
<h1>Row</h1>
</xf:group>
<xf:group ref="instance('views')/col-info">
<h1>Col</h1>
</xf:group>
</body>
</html>
注意:正在开发中!
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>Form Title</title>
<style type="text/css">
@namespace xf url("http://www.w3.org/2002/xforms");
body {font-family:Helvetica, sans-serif;}
/* This line ensures all the separate input controls appear on their own lines */
xf|input, xf|select, xf|select1, xf|textarea {display:block; margin:5px 0;}
/* Makes the labels right aligned in a 170px wide column that floats to the left of the input controls. */
xf|input > xf|label, xf|select > xf|label, xf|select1 > xf|label, xf|textarea > xf|label, xf|output > xf|label
{text-align:right; padding-right:10px; width:170px; float:left; text-align:right; font-weight: bold;}
.DashboardDescriptionText textarea {
width: 400px;
height: 8em;
font-family:Helvetica, sans-serif;
}
/* anything marked as a cell is inside a table */
.cell * {display: inline; padding: 1px 1px;}
/* set to column widths in the portlet table */
.PortletID {width: 10px;}
.PortletRow {width: 10px;}
.RowPlacement {width: 10px;}
.PortletHeight {width: 10px;}
.PortletWidth {width: 10px;}
</style>
<xf:model>
<xf:instance id="my-dash" xmlns="">
<DashboardDocument>
<DashboardID>123</DashboardID>
<DashboardName>Sample Dashboard</DashboardName>
<DashboardDescriptionText>A full description of the </DashboardDescriptionText>
<DashboardKeywords>test, example, sample</DashboardKeywords>
<DashboardLayoutCode>row</DashboardLayoutCode>
<DashboardRowCount>3</DashboardRowCount>
<DashboardColumnCount>4</DashboardColumnCount>
<Rows>
<Row>
<RowHeight>20%</RowHeight>
</Row>
<Row>
<RowHeight>50%</RowHeight>
</Row>
<Row>
<RowHeight>30%</RowHeight>
</Row>
</Rows>
<Portlets>
<Portlet>
<PortletID>1</PortletID>
<PortletName>Portlet1</PortletName>
<RowPlacement>1</RowPlacement>
<PortletWidth>25%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>2</PortletID>
<PortletName>Portlet2</PortletName>
<RowPlacement>1</RowPlacement>
<PortletWidth>25%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>3</PortletID>
<PortletName>Portlet3</PortletName>
<RowPlacement>1</RowPlacement>
<PortletWidth>25%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>4</PortletID>
<PortletName>Portlet4</PortletName>
<RowPlacement>1</RowPlacement>
<PortletWidth>25%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>5</PortletID>
<PortletName>Portlet5</PortletName>
<RowPlacement>2</RowPlacement>
<PortletWidth>33%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>6</PortletID>
<PortletName>Portlet3</PortletName>
<RowPlacement>2</RowPlacement>
<PortletWidth>33%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>7</PortletID>
<PortletName>Portlet3</PortletName>
<RowPlacement>2</RowPlacement>
<PortletWidth>33%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>8</PortletID>
<PortletName>Portlet3</PortletName>
<RowPlacement>3</RowPlacement>
<PortletWidth>33%</PortletWidth>
<PortletHeight />
</Portlet>
<Portlet>
<PortletID>9</PortletID>
<PortletName>Portlet3</PortletName>
<RowPlacement>3</RowPlacement>
<PortletWidth>33%</PortletWidth>
<PortletHeight />
</Portlet>
</Portlets>
</DashboardDocument>
</xf:instance>
<!-- used to select the number of rows and columns -->
<xf:instance id="layout-items" xmlns="">
<data>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
</data>
</xf:instance>
<!-- named views that are conditionally relevent based on the rules -->
<xf:instance id="views" xmlns="">
<data>
<row-view />
<col-view />
</data>
</xf:instance>
<!-- the rules on how to display the views -->
<!-- if we have a row or grid oriented display get the number of rows -->
<xf:bind id="row-view" nodeset="instance('views')/row-view" relevant="instance('my-dash')/DashboardLayoutCode='row' | instance('my-dash')/DashboardLayoutCode='grid'" />
<!-- if we have a column or grid oriented display get the number of columns -->
<xf:bind id="col-view" nodeset="instance('views')/col-view" relevant="instance('my-dash')/DashboardLayoutCode='col' | instance('my-dash')/DashboardLayoutCode='grid'" />
</xf:model>
</head>
<body>
<xf:output ref="DashboardID">
<xf:label>Dashboard ID:</xf:label>
</xf:output>
<xf:input ref="DashboardName">
<xf:label>Dashboard Name</xf:label>
<xf:hint>A short name under 50 characters.</xf:hint>
</xf:input>
<xf:textarea ref="DashboardDescriptionText" class="DashboardDescriptionText">
<xf:label>Description:</xf:label>
<xf:hint>Full description text. Used for searching for dashboards.</xf:hint>
</xf:textarea>
<xf:input ref="DashboardKeywords">
<xf:label>Keywords:</xf:label>
<xf:hint>Use comma to separate keywords.</xf:hint>
</xf:input>
<xf:select1 ref="DashboardLayoutCode">
<xf:label>Layout Style:</xf:label>
<xf:item>
<xf:label>Row</xf:label>
<xf:value>row</xf:value>
</xf:item>
<xf:item>
<xf:label>Column</xf:label>
<xf:value>col</xf:value>
</xf:item>
<xf:item>
<xf:label>Grid</xf:label>
<xf:value>grid</xf:value>
</xf:item>
</xf:select1>
<xf:group ref="instance('views')/row-view">
<xf:group ref="instance('my-dash')">
<xf:select1 ref="DashboardRowCount">
<xf:label>Number of Rows: </xf:label>
<xf:itemset nodeset="instance('layout-items')/item">
<xf:item>
<xf:label ref="." />
<xf:value ref="." />
</xf:item>
</xf:itemset>
</xf:select1>
</xf:group>
</xf:group>
<xf:group ref="instance('views')/col-view">
<xf:group ref="instance('my-dash')">
<xf:select1 ref="DashboardColumnCount">
<xf:label>Number of Columns: </xf:label>
<xf:itemset nodeset="instance('layout-items')/item">
<xf:item>
<xf:label ref="." />
<xf:value ref="." />
</xf:item>
</xf:itemset>
</xf:select1>
</xf:group>
</xf:group>
<table>
<thead>
<tr>
<th class="cell PortletID">ID</th>
<th class="cell PortletName">Name</th>
<th class="cell RowPlacement">Placement</th>
<th class="cell PortletHeight">Height</th>
<th class="cell PortletWidth">Width</th>
</tr>
</thead>
</table>
<xf:repeat nodeset="instance('my-dash')/Portlets/Portlet">
<span class="cell PortletID">
<xf:input ref="PortletID"/>
</span>
<span class="cell PortletName">
<xf:input ref="PortletName"/>
</span>
<span class="cell RowPlacement">
<xf:input ref="RowPlacement"/>
</span>
<span class="cell PortletHeight">
<xf:input ref="PortletHeight"/>
</span>
<span class="cell PortletWidth">
<xf:input ref="PortletWidth"/>
</span>
</xf:repeat>
</body>
</html>
仪表盘是 Web 门户中常见的特性。为了实现互操作性,每个 Portlet 的内容可以通过在 JSR-168 规范中指定的 CSS 标签来指定。JSR-168 旨在与 OASIS 远程 Portlet 的 Web 服务 标准保持一致。
要了解创建 Portlet 的人机工程学最佳实践,请参阅 Stephen Few 的优秀著作 信息仪表盘设计。有关使用哪些指标的优秀参考资料,请参阅 Wayne W. Erickson 的著作 性能仪表盘。Richardson 等人的著作 使用开源工具进行门户开发 中也讨论了门户标准。