跳至内容

XForms/计算器

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

计算器是网络应用程序的经典示例之一。

<html
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xf="http://www.w3.org/2002/xforms"
  xmlns:ev="http://www.w3.org/2001/xml-events">
  <head>
   <!-- Licensed by the w3c.org under the GPL2 -->
   <title>Calculator Sample</title>
   <xf:model>
     <xf:instance>
      <equation xmlns="">
        <display>0</display>
        <displaybuffer>0</displaybuffer>
        <first>0</first>
        <second>0</second>
        <memory>0</memory>
        <result />
      </equation>
     </xf:instance>
   </xf:model>
   <style type="text/css">
   table {
     border: thin outset;
   }
   td {
     border: thin inset;
   }
   .display {
     text-align: right;
   }
 </style>
  </head>
  <body>
   <p>A simple calculator</p>
   <table>
     <tr>
      <td colspan="6" class="display">
        <xf:output ref="/equation/display" />
      </td>
     </tr>
     <tr>
      <td>
        <xf:output ref="/equation/memory">
         <xf:label>M:</xf:label>
        </xf:output>
      </td>
      <td />
      <td />
      <td />
      <td colspan="2">
        <xf:trigger>
         <xf:label>Clear</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/first" value="0" />
           <xf:setvalue ref="/equation/second" value="0" />
           <xf:setvalue ref="/equation/result" value="0" />
           <xf:setvalue ref="/equation/display" value="0" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
           <xf:toggle case="add" />
         </xf:action>
        </xf:trigger>
      </td>
     </tr>
     <tr>
      <td>
        <xf:trigger>
         <xf:label>MC</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/memory" value="0" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>7</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 7" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>8</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 8" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>9</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 9" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>/</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/first" value="/equation/display" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
           <xf:toggle case="divide" />
         </xf:action>
        </xf:trigger>
      </td>
      <td />
     </tr>
     <tr>
      <td>
        <xf:trigger>
         <xf:label>MR</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/display" value="/equation/memory" />
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/memory" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>4</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 4" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>5</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 5" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>6</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 6" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>*</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/first" value="/equation/display" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
           <xf:toggle case="multiply" />
         </xf:action>
        </xf:trigger>
      </td>
     </tr>
     <tr>
      <td>
        <xf:trigger>
         <xf:label>MS</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/memory" value="/equation/display" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>1</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 1" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>2</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 2" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>3</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 3" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>-</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/first" value="/equation/display" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
           <xf:toggle case="subtract" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>1/x</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/display" value="1 div /equation/display" />
         </xf:action>
        </xf:trigger>
      </td>
     </tr>
     <tr>
      <td>
        <xf:trigger>
         <xf:label>M+</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/memory" value="/equation/memory + /equation/display" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>0</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10" />
           <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:trigger>
         <xf:label>+/-</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/display" value="/equation/display * -1" />
         </xf:action>
        </xf:trigger>
      </td>
      <td />
      <td>
        <xf:trigger>
         <xf:label>+</xf:label>
         <xf:action ev:event="DOMActivate">
           <xf:setvalue ref="/equation/first" value="/equation/display" />
           <xf:setvalue ref="/equation/displaybuffer" value="0" />
           <xf:toggle case="add" />
         </xf:action>
        </xf:trigger>
      </td>
      <td>
        <xf:switch>
         <xf:case id="add" selected="true">
           <xf:trigger>
            <xf:label>=</xf:label>
            <xf:action ev:event="DOMActivate">
              <xf:setvalue ref="/equation/second" value="/equation/displaybuffer" />
              <xf:setvalue ref="/equation/result" value="/equation/first + /equation/second" />
              <xf:setvalue ref="/equation/display" value="/equation/result" />
              <xf:setvalue ref="/equation/displaybuffer" value="0" />
            </xf:action>
           </xf:trigger>
         </xf:case>
         <xf:case id="subtract">
           <xf:trigger>
            <xf:label>=</xf:label>
            <xf:action ev:event="DOMActivate">
              <xf:setvalue ref="/equation/second" value="/equation/displaybuffer" />
              <xf:setvalue ref="/equation/result" value="/equation/first - /equation/second" />
              <xf:setvalue ref="/equation/display" value="/equation/result" />
              <xf:setvalue ref="/equation/displaybuffer" value="0" />
            </xf:action>
           </xf:trigger>
         </xf:case>
         <xf:case id="multiply">
           <xf:trigger>
            <xf:label>=</xf:label>
            <xf:action ev:event="DOMActivate">
              <xf:setvalue ref="/equation/second" value="/equation/displaybuffer" />
              <xf:setvalue ref="/equation/result" value="/equation/first * /equation/second" />
              <xf:setvalue ref="/equation/display" value="/equation/result" />
              <xf:setvalue ref="/equation/displaybuffer" value="0" />
            </xf:action>
           </xf:trigger>
         </xf:case>
         <xf:case id="divide">
           <xf:trigger>
            <xf:label>=</xf:label>
            <xf:action ev:event="DOMActivate">
              <xf:setvalue ref="/equation/second" value="/equation/displaybuffer" />
              <xf:setvalue ref="/equation/result" value="/equation/first div /equation/second" />
              <xf:setvalue ref="/equation/display" value="/equation/result" />
              <xf:setvalue ref="/equation/displaybuffer" value="0" />
            </xf:action>
           </xf:trigger>
         </xf:case>
        </xf:switch>
      </td>
     </tr>
   </table>
  </body>
</html>

计算器程序大约有 300 行代码。但大部分代码只是说明当按钮被按下时应该执行什么操作。

计算器的模型非常简单,只有五个变量:

  • display - 可见的显示
  • displaybuffer - 一个不可见的辅助显示
  • first - 第一个运算符
  • second - 第二个运算符
  • memory - 由内存功能使用

以下是“5”按钮的触发器

<td>
  <xf:trigger>
   <xf:label>5</xf:label>
     <xf:action ev:event="DOMActivate">
       <xf:setvalue ref="/equation/displaybuffer" value="/equation/displaybuffer * 10 + 5" />
       <xf:setvalue ref="/equation/display" value="/equation/displaybuffer" />
     </xf:action>
  </xf:trigger>
</td>

触发器的动作只是做两件事:

  1. 将显示缓冲区的值乘以 10(将数字向左移一位),然后加上 5。
  2. 将显示缓冲区的值复制到显示屏。

也有科学计算器,但它们的结构类似。

比较 JavaScript 版本和 XForms 版本很有趣。JavaScript 版本更短,但 JavaScript 可以利用一些可用的工具。

参考资料

[编辑 | 编辑源代码]

Hixie 的自然对数

下一页: 犯罪档案 | 上一页: 发票管理
首页: XForms
华夏公益教科书