跳至內容

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
華夏公益教科書