Javascriptで金種別計算表を作ってみた

いつも小口現金を集計するのにExcelを使っているのですが、これスマホでも使えたら便利だなと思い、JavaScriptでWebアプリを作ってみました。

最初にネットで調べて作ってみたのがこれ。


<!doctype html>
<html class="no-js" lang="ja">

<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link rel="manifest" href="site.webmanifest">
  <link rel="apple-touch-icon" href="icon.png">
  <!-- Place favicon.ico in the root directory -->

  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
    integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

  <meta name="theme-color" content="#fafafa">
</head>

<body>

  <style>
    form dl dt {
      width: 200px;
      height: 40px;
      padding: 10px 0;
      line-height: 40px;
      float: left;
    }

    form dl dd {
      padding: 10px 0;
      margin: 0;
    }

    .box {
      box-sizing: border-box;
      width: 150px;
      height: 40px;
      margin: 0;
      padding: 0 10px;
    }
  </style>

  <div class="container">
    <div class="w-60">
      <form class="kinshu">
        <dl>
          <dt>10000円:</dt>
          <dd><input type="number" name="v10000" class="box">枚</dd>

          <dt>5000円:</dt>
          <dd><input type="number" name="v5000" class="box">枚</dd>

          <dt>1000円:</dt>
          <dd><input type="number" name="v1000" class="box">枚</dd>

          <dt>500円:</dt>
          <dd><input type="number" name="v500" class="box">枚</dd>

          <dt>100円:</dt>
          <dd><input type="number" name="v100" class="box">枚</dd>

          <dt>50円:</dt>
          <dd><input type="number" name="v50" class="box">枚</dd>

          <dt>10円:</dt>
          <dd><input type="number" name="v10" class="box">枚</dd>

          <dt>5円:</dt>
          <dd><input type="number" name="v5" class="box">枚</dd>

          <dt>1円:</dt>
          <dd><input type="number" name="v1" class="box">枚</dd>
        </dl>

        <p><input type="button" class="calc-btn" onclick="calc(
          v10000.value,
          v5000.value,
          v1000.value,
          v500.value,
          v100.value,
          v50.value,
          v10.value,
          v5.value,
          v1.value
        );" value="計算"></p>

        <dt>合計:</dt>
        <dd><input type="text" id="totale_value" class="box" readonly="">円</dd>

      </form>
    </div>
  </div>

  <script>
    function calc(
      v10000, v5000, v1000, v500, v100, v50, v10, v5, v1
    ) {
      let total = document.getElementById('totale_value').value =
        Math.round(
          (10000 * v10000) + (5000 * v5000) + (1000 * v1000) + (500 * v500) + (100 * v100) + (50 * v50) + (10 * v10) + (5 * v5) + (1 * v1)
        );
    }

  </script>

</body>

</html>

一応動くんですけど、ボタンにアクションを付けてるので金種別以外の用途でつくるとなると、入力フォームの数だけボタンアクションも関数の要素も計算式も、それぞれ増やさないといけない。

でも、どうやったらいいかわからない。

ググるけどわからない。

嫌になる

やめる(最悪)

これまでだったらここでやめちゃうのですが、最近はteratailに質問することにしています。

teratail【テラテイル】|ITエンジニア特化型Q&Aサイト

https://teratail.com/

以前はわかるまで考えなきゃダメとか思っていたし、質問するのがなんだか怖くて躊躇していましたが、思い切って質問したらめちゃくちゃ親切に教えてくれて感動しました。何よりわからないところを整理しないと質問できないので、それが理解に繋がります。何も考えずに答えを見るのと、わからないところを整理して答えを見るのとでは明らかに違います。答えを頂いても動作に興味があるので、そのプログラムがどういう風に動いているのか、確認するようになりました。

テラテイルのコピーにも書かれている通り、15分考えて分からなきゃすぐ質問!したほうがいいです。

で教えていただいた正解がこれ。

<!doctype html>
<html class="no-js" lang="">

<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link rel="manifest" href="site.webmanifest">
  <link rel="apple-touch-icon" href="icon.png">
  <!-- Place favicon.ico in the root directory -->

  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
    integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

  <meta name="theme-color" content="#fafafa">
</head>

<body>

  <style>
    form dl dt {
      width: 200px;
      height: 40px;
      padding: 10px 0;
      line-height: 40px;
      float: left;
    }

    form dl dd {
      padding: 10px 0;
      margin: 0;
    }

    .box {
      box-sizing: border-box;
      width: 150px;
      height: 40px;
      margin: 0;
      padding: 0 10px;
    }
  </style>

  <div class="container">
    <div class="w-60">
      <script>
        window.addEventListener('DOMContentLoaded', () => {
          document.querySelector('.calc-btn').addEventListener('click', () => {
            const v = [...document.querySelectorAll('[data-yen]')].map(x => x.dataset["yen"] * x.value).reduce((x, y) => x + y);
            console.log([...document.querySelectorAll('[data-yen]')].map(x => x.dataset["yen"] * x.value));
            document.querySelector('#totale_value').value = v;
          });
        });
      </script>
      <form class="kinshu">
        <dl>
          <dt>10000円:</dt>
          <dd><input type="number" data-yen="10000" class="box" value="0" min="0">枚</dd>
          <dt>5000円:</dt>
          <dd><input type="number" data-yen="5000" class="box" value="0" min="0">枚</dd>
          <dt>1000円:</dt>
          <dd><input type="number" data-yen="1000" class="box" value="0" min="0">枚</dd>
          <dt>500円:</dt>
          <dd><input type="number" data-yen="500" class="box" value="0" min="0">枚</dd>
          <dt>100円:</dt>
          <dd><input type="number" data-yen="100" class="box" value="0" min="0">枚</dd>
          <dt>50円:</dt>
          <dd><input type="number" data-yen="50" class="box" value="0" min="0">枚</dd>
          <dt>10円:</dt>
          <dd><input type="number" data-yen="10" class="box" value="0" min="0">枚</dd>
          <dt>5円:</dt>
          <dd><input type="number" data-yen="5" class="box" value="0" min="0">枚</dd>
          <dt>1円:</dt>
          <dd><input type="number" data-yen="1" class="box" value="0" min="0">枚</dd>
        </dl>
        <p><input type="button" class="calc-btn" value="計算"><input type="reset" value="リセット"></p>
        <dt>合計:</dt>
        <dd><input type="text" id="totale_value" class="box" value="0" readonly>円</dd>
      </form>
    </div>
  </div>



</body>

</html>

あ~、なんとなく理解できます。要はページを読み込んだときに、ボタンをクリックしたら各input要素のデータを取得して、それぞれの入力値で乗算して合計を求めて、最後に#total_valueに入力する。ってかんじ。

リファクタリングもされててすごいんですけど、素人にはちょっと難しい。

で、ボタン要素を取得してそのボタンにイベントをつけるやり方にしてみました。

input内のボタンを<input></input>の外に出して下記に変更。

<button id="btn">計算</button>
const btn = document.getElementById('btn');

    btn.addEventListener('click', () => {
      const v = [...document.querySelectorAll('[data-yen]')].map(x => x.dataset["yen"] * x.value).reduce((x, y) => x + y);
      document.querySelector('#totale_value').value = v;
    }, false);

button要素を変数に入れてそれにイベントをつけるやり方に変更。

変数vの下にconsole.log();で処理の順序ごとに内容を確認するとさらにわかりやすいです。

addEventListenerの使い方やアロー関数の使い方も理解できました。

最初簡単に思っていた縦計だけの金種別計算表ですが、ボタンアクションにform要素の取得をつけるといろいろと応用ができそうです。

知識をインプットするだけじゃ何をやっているかわからないけれど、目的がはっきりすると知りたいこともはっきりするし理解するのも早いです。

調べながらとりあえず動くものを作って、少しずつ良くしていけばいい。最初からすごいものを作ろうとするとすぐに嫌になるので少しずつです。

Done is better than perfect.

レベルは違えど本当にそうだと思います。

この記事を書いた人

tegecat

Webや動画の製作、PCに関することを仕事にしています。また、トレイルランニングや野菜づくり、料理なども楽しんでいます。