跳转到内容

XForms/仪表盘构建器

来自维基教科书,开放世界开放书籍

您希望一个表单可以布局单个页面仪表盘。在这种情况下,仪表盘由一组“Portlets”组成,每个 Portlet 都有独立的内容。

我们的仪表盘构建器将控制一个仪表盘库。每个仪表盘都有一个名称、布局信息以及在仪表盘中呈现的一系列 Portlet。在我们的示例中,仪表盘最多可以包含 36 个 Portlet,但最佳实践通常包含 7 个 Portlet,加上或减去一到两个。

应用程序设计

[编辑 | 编辑源代码]

我们的仪表盘布局将采用三种类型之一

  1. 行方向,其中同一行中的所有 Portlet 具有相同的高度
  2. 列方向,其中同一列中的所有 Portlet 共享相同的宽度
  3. 网格方向,其中所有 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 等人的著作 使用开源工具进行门户开发 中也讨论了门户标准。

下一页: URL 重写器 | 上一页: 应用程序构建器
首页: XForms
华夏公益教科书