ダッシュで奪取

元SIerだけどWebエンジニアになりたい!

【JavaScript】計算機に数値が入力できるようにした


GW、足りない睡眠時間を補ったり映画を観たり、たくさん休んで回復しました。今日から再開するぞ!

前回は見た目だけで何もできませんでしたが、数値ボタンで数値入力されるようにしました。
サンプルページ

目次

  1. やりたいこと
  2. 全体像
  3. HTML
  4. JavaScript
  5. ひとこと

1.やりたいこと

  • 計算機の見た目はできたので、各ボタンに処理を入れていく
  • 数値ボタンを押すと、数値が入力される
  • 数値は、3桁ごとにカンマ区切りで表示させる
  • 表示可能な桁数をオーバーしたら、それ以上入力できないようにする

2. 全体像

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" type="text/css" href="css/style_calc.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="format-detection" content="telephone=no, email=no, address=no"/>
    <title>けいさんき</title>
  </head>
  <body>
    <div class="container">
      <div class="calculator">
        <div class="display"><span id="display_text">0</span></div>
        <div class="button">
          <button type="button" class="action_btn" onclick="pushBtnFnc('ac');">AC</button>
          <button type="button" class="action_btn" onclick="pushBtnFnc('signChange')">+/-</button>
          <button type="button" class="action_btn" onclick="pushBtnFnc('percent')">%</button>
          <button type="button" class="symbol_btn" onclick="pushBtnFnc('div')">÷</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(7);">7</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(8);">8</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(9);">9</button>
          <button type="button" class="symbol_btn" onclick="pushBtnFnc('mul')">×</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(4);">4</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(5);">5</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(6);">6</button>
          <button type="button" class="symbol_btn" onclick="pushBtnFnc('sub')"></button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(1);">1</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(2);">2</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc(3);">3</button>
          <button type="button" class="symbol_btn" onclick="pushBtnFnc('add')"></button>
          <button type="button" class="number_btn long_btn" onclick="pushBtnFnc(0);">0</button>
          <button type="button" class="number_btn" onclick="pushBtnFnc('.');">.</button>
          <button type="button" class="symbol_btn" onclick="pushBtnFnc('equ')"></button>
        </div>
      </div>
    </div>
    <script type="text/javascript" src="js/20190505_calc.js"></script>
  </body>
</html>

JavaScript

// 画面の値を取得するための変数
var target = document.getElementById("display_text");
var displayNum = "";

// ボタン振り分け処理
function pushBtnFnc(key) {
  if (!isNaN(key)) {
    numberBtnFnc(key);
  } else {
    actionBtnFnc(key);
  }
}

// ACボタン等の処理
function actionBtnFnc(key) {
  if (key == "ac") {
    // ACボタンが押されたら、画面表示を0にする(クリア)
    displayNum = "0";
    setCalc(displayNum);
  }
}

// 数字ボタンの処理
function numberBtnFnc(num) {
  // 12桁目の入力は受け付けない(ここで終了)
  if (displayNum.length == 11) {
    return;
  }

  // 0しか入力されていなかった場合、入力値で置き換える
  if (displayNum == "0") {
    displayNum = num;
  } else {
    displayNum += String(num);
  }

  setCalc(displayNum);
}

// 計算結果を画面に表示する
function setCalc(displayNum) {
  target.innerText = Number(displayNum).toLocaleString();
}

3. HTML

<button type="button" class="action_btn" onclick="pushBtnFnc('ac');">AC</button>

onclickで、クリック時の処理を指定しています。
ボタンクリック時にはどのボタンでも共通でpushBtnFncを実行し、引数で数値ボタンの処理、+ボタンの処理等を判定・分岐させるようにしました。

<script type="text/javascript" src="js/20190505_calc.js"></script>

上記のpushBtnFncはどこにいるのかというと、js/20190505_calc.jsの中に記述されています。
body部の最後でjsファイルを読み込んで、js/20190505_calc.js内の処理を使えるようにします。

※画面上の項目(計算機の結果表示部分)を使用しているため、最下部で読み込んでいます。
cssのようにhead部で読み込むと、画面のhtml部分を読み込む前にjs/20190505_calc.jsが実行されてしまうため、うまく動かないです…

4. JavaScript

// 画面の値を取得するための変数
var target = document.getElementById("display_text");
var displayNum = "";

共通部分なので、関数の外に書いています。
document.getElementById(ID名)で、IDが一致した要素を取得。

ボタン振り分け処理

// ボタン振り分け処理
function pushBtnFnc(key) {
  if (!isNaN(key)) {
    numberBtnFnc(key);
  } else {
    actionBtnFnc(key);
  }
}

全てのボタンで、まずこの関数に飛びます。
isNaN(値)は、値が数値であればFALSE・数値でなければTRUEを返します。

なんとなく分かりにくいので、否定条件の!を追加しました。
数値であればTRUE(numberBtnFnc)、数値でなければFALSE(actionBtnFnc)側の分岐に入ります。

ACボタン等の処理

// ACボタン等の処理
function actionBtnFnc(key) {
  if (key == "ac") {
    // ACボタンが押されたら、画面表示を0にする(クリア)
    displayNum = "0";
    setCalc(displayNum);
  }
}

今回は数値入力部分のみ作るつもりでいましたが…リセットしたくなる度にページをリロードするのも面倒なので、ACボタンの処理だけ動くようにしています。

setCalcの処理は後述…

数字ボタンの処理

// 数字ボタンの処理
function numberBtnFnc(num) {
  // 12桁目の入力は受け付けない(ここで終了)
  if (displayNum.length == 11) {
    return;
  }

  // 0しか入力されていなかった場合、入力値で置き換える
  if (displayNum == "0") {
    displayNum = num;
  } else {
    displayNum += String(num);
  }

  setCalc(displayNum);
}
12桁目の入力は受け付けない(ここで終了)

画面上、カンマ込みで11桁まで表示できそうだったので11を最大桁数としました。 値.lengthで値の桁数を取得できるので、11桁であればreturnで処理を抜けています。

実際の計算機だと、e表示でたくさんの桁数を扱えたりするのですが、今回は練習でそこまで対応する予定はないので、取りあえず入力不可(ボタンを押しても何もせず終了)に…

0しか入力されていなかった場合、入力値で置き換える

0が入力されている時に1が押されたら、画面には「1」と表示したいです。
1が入力されている時に1が押されたら、画面には「11」と表示したいです。

そのため、入力値が0か0以外かで分岐させています。

String(数値)で文字列に変換している理由ですが、変換しておかないと数値同士の足し算が行われてしまうためです…(1が入力されている時に1を押すと、画面には「2」が表示されるようになってしまう)

計算結果を画面に表示する

// 計算結果を画面に表示する
function setCalc(displayNum) {
  target.innerText = Number(displayNum).toLocaleString();
}

共通部分なので、別関数に書きました。 数値.toLocaleString()で、数値を3桁ごとにカンマ区切りした状態で文字列変換してくれます。

対応していないブラウザもあるとのことですが、Chrome・Safariで問題ないことを確認できたため、大丈夫かな…と思い取りあえずこれで。
ちゃんと書くなら、正規表現でreplaceですね…

5. ひとこと

まだまだ中身空っぽに等しい状態ですが、ちょっとでも動くとやっぱり嬉しいものです。

数値入力だけで結構時間がかかってしまったので、普段何気なく使っている電卓ですが、しれっと結構複雑なことやってるんだな…と思いました。

次は簡単な計算ができるように!したい!