Problems with adding keyboard support to JS calculator

前端 未结 1 947
伪装坚强ぢ
伪装坚强ぢ 2021-01-25 23:49

I want to add keyboard support to my calculator. When i press operations with keyboard (i.e. +,-,* or /) js sees it as number, not as operation.

For example, when I com

相关标签:
1条回答
  • 2021-01-26 00:16

    Give this a shot. It's not got any functionality for delete key or arrow keys, but it will perhaps help move you forward more.

    <!DOCTYPE html>
    <html>
        <head>
        </head>
        <script>
          var values
          var dp
          function checkCalcKey(key) {
            switch (key) {
              case '.':
                document.getElementById('dot').click();
                break;
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
              case '+':
              case '-':
              case '/':
              case '*':
              case '=':
                document.getElementById(key).click();
                break;
            }
            return false;
          // TODO handle any of 'ArrowLeft', 'ArrowRight', 'Delete','Backspace'. I'll leave this as an exercise for you to complete!
          }
          function hardReset() {
              values = [];
              opcode = null;
              clear = true;
              reset();
          }
            
          function reset() {
            newNumber = false;
            if (opcode === null) {
               clearDisplay()
            }    
          }
            
          function clearDisplay() {
              dp = 0;
              nc = 0;
              document.getElementById('display').value = '';
          }
            
          function getValue() {
              var value;
              var s = '' + document.getElementById('display').value;
              if (s === '') {
                  value = 0;
              } else if (s.indexOf('.') === -1) {
                value = Number(s);
              } else {
                value = parseFloat(s);
              }
              return value;
          }
            
          function performMaths() {
                m = values.pop();
                v = values.pop();
                switch (opcode) {
                  case '+':
                    v += m;
                    break;
                  case '-':
                    v -= m;
                    break;
                  case '*':
                    v *= m;
                    break;
                  case '/':
                    if ( m=== 0) {
                       v = NaN;
                    } else {
                       v /= m;
                    }
                    break;
                }
                values = [v,m];
                document.getElementById('display').value = v;
          }
            
          function init() {
            clear = true;
            hardReset();
            document.querySelectorAll(".number").forEach((b) => {
               b.addEventListener('click', (e) => 
                  {
                    newNumber = true;
                    if (clear) {
                        clearDisplay();
                        clear = false;
                    }
                    nc++;
                    display=document.getElementById('display');
                    if (dp === 0) {
                       var value = (10 * Number(display.value)) + Number(e.target.textContent);
                       display.value = value;
                    } else {
                       var f = Number(e.target.textContent) / Math.pow(10,dp);
                       var value = parseFloat(display.value);
                       var value = f + value;
                       var sv = '' + value
                       sv = sv.substring(0,nc);
                       display.value = sv;
                       dp++;
                    }
                  });
             });
              
             document.getElementById('dot').addEventListener('click', () => {
                newNumber = true;
                if (dp === 0) {
                    dp++;
                    nc++;
                }
             });
              
             document.getElementById('c').addEventListener('click', () => {
                hardReset();
             });
              
             document.getElementById('ce').addEventListener('click', () => {
                reset();
             });
              
             document.querySelectorAll(".operator").forEach((b) => {
               b.addEventListener('click', (e) => 
                  {
                    clear = true;
                    if (e.target.textContent != opcode) {
                      opcode = e.target.textContent;
                    }
                    if (document.getElementById('display').value != '') {
                      if (values.length === 2) {
                          values.shift();
                      }
                     values.unshift(getValue());
                    }
                   newNumber = false;
                  });
             });
              
             document.getElementById('=').addEventListener('click', () => {
               if (values.length === 2) {
                  if (newNumber) {
                    values.pop();
                    values.push(getValue());
                  }
               } else {
                 values.push(getValue());
               }
               performMaths();
               newNumber = false;
             });
          }
            
        </script>
        <body onload="init()">
            <div class="main">
                <div id="output">
                    <input id="display" value="" onkeydown="return checkCalcKey(event.key)">
                </div>
                <button id="ce">CE</button>
                <button id="c">C</button>
                <button id="0" class="number">0</button>
                <button id="1" class="number">1</button>
                <button id="2" class="number">2</button>
                <button id="3" class="number">3</button>
                <button id="4" class="number">4</button>
                <button id="5" class="number">5</button>
                <button id="6" class="number">6</button>
                <button id="7" class="number">7</button>
                <button id="8" class="number">8</button>
                <button id="9" class="number">9</button>
                <button id="/" class="operator">/</button>
                <button id="*" class="operator">*</button>
                <button id="-" class="operator">-</button>
                <button id="+" class="operator">+</button>
                <button id="=">=</button>
                <button id="dot">.</button>
            </div>
        </body>
    </html>

    An explanation of the code:

    The getValue routine does the bulk of fixing things up, and answers the key points in your original question:

    • If a variable is being interpreted as of type string it can mess up the computation. So you can convert a variable you don't know the type of to string by combining an empty string with the variable itself.

    • There is code to check for the existence of a decimal point, then use either parseFloat or Number to cast the type of the variable (parseInt is a more verbose alternative, needing radix of 10 - for a base 10 number).

    • A couple of other key variables are:

      • dp (decimal point). It stands for the number of digits past the decimal point, so any numbers you add after are divided by 10^dp (so 1 digit after dp is n * 1/10th, 2 digits is n * 1/100th etc).
      • nc (number of characters). Sometimes you can get odd rounding errors, so things like 1.111 suddenly become 1.111000000001 or something like that, so nc is used to count digits and decimal places entered and take the left number of characters based on nc.

    There is also some funky stuff going on, mimicking a normal calculator. So that when computation goes on, you can do something like enter:

    • 5 * = to give 25..
    • Press = again and it will give you 125.

    So the last number you enter becomes like a 'sticky' constant in memory. Whenever a new value gets entered, that becomes the new 'sticky' value. So:

    • 3 * 4 = (yields 12),
    • = then yields 48 etc.

    So: - the values array is used to store both the sticky value and the total:

    • It gets re-evaluated in performMaths()
    • adjusted in operator and = event handlers.
      • the boolean newValue is set to true whenever a number is pressed, and false whenever an operation, such as +, -, /, * or = is pressed.

    checkCalcKey() is an event handler for onkeydown upon the input HTML control's. By returning false, it prevents the character you type from build input. Instead it defers to the click handler of the corresponding button and any character entry into the input control value property gets performed via that handler instead. (More info here).

    0 讨论(0)
提交回复
热议问题