javascriptを使って簡単な計算機を作るpart5 入門者向け

#計算機を作る

##今回作る機能
・クリアボタンと小数点ボタンの追加
・クリアボタンでテキストボックスの値をリセットする機能
・入力できる文字列や文字数などの制限

これらの機能実装するにあたり、スタイルの変更を行った。

##ボタンの追加とスタイルの変更
(スクリーンショット)
<img width="380" alt="スクリーンショット 2020-07-21 12.24.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662094/f6489150-03cc-fa45-018c-7678a90e5b27.png">

CLEARボタンで、テキストボックス内の値をリセットすることができる。

RECORDボタンは、今後追加するであろう計算結果をリストに追加するためのボタンを前もって配置しておいた。


##入力できる文字列や文字数などの制限
###意図しない文字列
(制限済み)・最初に記号ボタンが押せてしまう
(+ - * / . =)

(制限済み)・記号ボタンを連続で押せてしまう

(制限済み)・0を連続で押せてしまう
(00.1など）
100とは打てるようにしたいので工夫が必要

(制限済み)・小数点は一つまで打てるようにしたい
(0.1.0などは計算機としては変なので）

(実装済み)・記号ボタンも一つまで
記号ボタンの括りを
(+ - * / . =)
↓
(+ - * /)(.)(=)に変更する必要がありそう。

###文字数に関して
(制限済み)・テキストボックスの表示範囲外に文字を打てないようにしたい
(文字数をテキストボックス範囲内に収まるように)

(制限済み)・「1÷3」などの計算で、小数点以下の桁が長くなるとテキストボックスの表示範囲外に飛び出してしまう。

##サンプルコード

<details><summary>HTML</summary><div>

```html:caluculate.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/caluculate.css">
  <title>計算機</title>
</head>
<body>
  <div class="caluculate">
    <div class="wrapper">
      <div id="number-text">0</div>
    </div>
    <div class="other-btns">
      <button id="clear-btn">CLEAR</button>
      <button id="record-btn" onclick="record()">RECORD</button>
    </div>
    <div id="btns">
      <div id="num-btns">
        <button onclick="number(7)">7</button>
        <button onclick="number(8)">8</button>
        <button onclick="number(9)">9</button>
        <button onclick="number(4)">4</button>
        <button onclick="number(5)">5</button>
        <button onclick="number(6)">6</button>
        <button onclick="number(1)">1</button>
        <button onclick="number(2)">2</button>
        <button onclick="number(3)">3</button>
        <button id="zero" onclick="zero(0)">0</button>
        <button name="point" onclick="point('.')">.</button>
        <button name="equal" onclick="calc('=')">=</button>
      </div>
      
      <div id="symbol-btns">
        <button name="symbol" onclick="calc('/')">/</button>
        <button name="symbol" onclick="calc('*')">*</button>
        <button name="symbol" onclick="calc('-')">-</button>
        <button name="symbol" onclick="calc('+')">+</button>
      </div>
    </div>
  </div>

  <script src="js/caluculate.js"></script>
</body>
</html>
```

</div></details>

<details><summary>CSS</summary><div>

```css:caluculate.css
* {
  margin: 0;
  padding: 0;
}

.caluculate {
  margin: 100px auto;
}

.wrapper {
  width: 300px;
  margin: 0 auto;
}

.wrapper > #number-text {
  width: 285px;
  height: 54px;
  line-height: 54px;
  margin-left: 5px;
  margin-bottom: 5px;
  /* padding: 4px; */
  font-size: 48px;
  border: 1px solid black;
  /* 右から左へ入力するためのスタイル */
  text-align: right;
}

.other-btns {
  margin: 0 auto;
  width: 300px;
}

#clear-btn {
  width: 135px;
  margin-left: 5px;
  font-size: 24px;
  /* 上下のズレを直すためのスタイル */
  vertical-align: middle;
}

#record-btn {
  width: 135px;
  font-size: 24px;
  margin-left: 13px;
  /* 上下のズレを直すためのスタイル */
  vertical-align: middle;
}

#btns {
  width: 300px;
  display: flex;
  margin: auto;
}

button {
  width: 65px;
  height: 57px;
}

#num-btns {
  margin: 5px;
}

#num-btns > button {
  margin-bottom: 5px;
  font-size: 24px;
}

/* #num-btns > button:last-child {
  width: 136px;
} */

#symbol-btns {
  height: 228px;
  display: flex;
  flex-direction: column;
  display: inline-block;
  margin-top: 5px;
}

#symbol-btns > button {
  margin-bottom: 5px;
  height: 57px;
  font-size: 24px;
  text-align: center;
}
```

</div></details>

<details><summary>Javascript</summary><div>

```js:caluculate.js
var show = document.getElementById('number-text');
var total = ''; //現在の式
var operator = ''; //演算子
var currentValue = ''; //現在の値
var flag = 0; //ボタンが押されたあとに効かなくする※flag(フラグ)を立てる。最初は0を代入。

//数字入力の関数
var number = data => { //押されたボタンの値 data()をアロー関数にしている
  if (currentValue.length <= 8) {
    flag = 0;
    currentValue += data;
    show.textContent = currentValue;
    console.log(show.textContent); //確認用
  }
};

//0についての関数
var zero = data => {
  if(currentValue === '0') {
    return; //最初の文字が0のとき0を押せなくする
  } else if (currentValue.length <= 8){
    flag = 0;
    currentValue += data;
    show.textContent = currentValue;
    console.log(show.textContent);
  }
}

//小数点(.)の関数
var point = data => {
  if (currentValue === '') {
    return; //最初に小数点を押せなくする
  } else if (!currentValue.includes('.')) {
    currentValue += data;
    show.textContent = currentValue;
  }
}

//計算の関数(内部的に計算をするも含む)
var calc = data => {
  if (currentValue === '') {
    return; //最初に演算子を押せなくする
  }else if (flag === 0 && data !== "=") {
    flag = 1;

    var formula = total + operator + currentValue;
    total = eval(formula);

    operator = data;
    currentValue = '';
    show.textContent = total;
  } else if (flag === 1 && data === "=") {
    var formula = total + operator + total;
    total = limitNum(eval(formula));

    currentValue = "";
    show.textContent = total;
  } else if (data === "=") {
    flag = 1;

    var formula = total + operator + currentValue;
    total = limitNum(eval(formula));

    currentValue = "";
    show.textContent = total;
  } else {
    operator = data;
  }
  console.log(show.textContent);
};

//小数点以下の桁数を揃える関数
function limitNum(num) {
  return Math.round(num*10000000)/10000000;
}

//CLEARボタンの関数
function reset() {
  operator = '';
  total = '';
  currentValue = '';
  flag = 0;
  show.textContent = '0';
};

var clear = document.getElementById('clear-btn')
clear.addEventListener('click', () => {
  reset();
});
```

</div></details>


##参考サイト
###計算機の作り方など

[JavaScriptで簡単な電卓アプリを作ってみた](https://qiita.com/atlansien/items/6f6433b1e1971a69112d)

[Javascriptで電卓を作ろう　第3回　連続で演算記号や小数点が押された場合の処理](https://qiita.com/rikimaru914/items/8df2124165afd036b922)

###CSS関連

[cssで要素を横並びにする方法まとめ](https://qiita.com/katsunory/items/99a417f4e1a763477a09)

[ボタンやフォームの上下位置がずれたとき 他](https://woshidan.hatenablog.com/entry/2013/12/30/042143)

###制限機能に関して
[JavaScript アロー関数を説明するよ](https://qiita.com/may88seiji/items/4a49c7c78b55d75d693b)

[【JavaScript】アロー関数式を学ぶついでにthisも復習する話](https://qiita.com/mejileben/items/69e5facdb60781927929)

[jQueryのdata()で属性を取得・設定・変更する方法まとめ！](https://www.sejuku.net/blog/38263)

[MDN:Array.prototype.includes()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)

[MDN:eval()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval)

[JavaScriptでeval関数の使い方とリスクとは【初心者向け】](https://techacademy.jp/magazine/15038)

[JavaScript初歩知識3 アラート確認&flag(flagを立ててボタンを制御するの部分)](https://qiita.com/astrix-sho-2091372/items/d0c96833b3b397550ecf)

[Javascriptで電卓を作ろう　第7回「4 ÷ 3 = 1.33333333333333333」の表示桁数を10桁にしたい](https://qiita.com/rikimaru914/items/c3f23aa65f4be780d6ff)

[MDN:Math.round()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/round)

[【JavaScript】桁指定して四捨五入・切り上げ・切り捨て](https://qiita.com/nagito25/items/0293bc317067d9e6c560)

##残りの今後の構想
・記号入力は、ボタン切り替え機能を使って計算したい。要は、iphoneの電卓を想定

テキストボックスには記号は入力せず、内部的に入力する。
記号に文字数を使うと、長い桁になったときに足りなくなるし、見辛そうなので。
（テキストボックス表示例：「1」→(+ボタンを押す)→「1」→(=ボタンを押す)→「2」）

7/25追記:機能自体は実装できたので、どの演算子ボタンを押したか分かりやすくするためのCSSを書く。

・計算結果をリストに追加していく機能
（複数の計算があったとき用のメモ代わり）
RECORDボタン押してリストに追加する。

・計算結果リストの編集ができる機能
(作れそうなら作ってみる)

###感想など
今回の機能を実装するにあたって、参考サイトのコードを最初は全然読めなかったけど、一つ一つのコードを、単語の意味やどんな意図で使われているかを調べることで少しずつ前に進めることができた。

コードをそのままコピペとはやらずに、コードの意味を一つ一つ理解してから次に進むってやっているので、かなり時間をかけてしまっているのは問題点。

参考にしたコードを組み合わせることで思い通りの結果を得られることも学んだ。

手を動かすことで学べるを初めて実感したかもしれない。
行動する前から諦めては何もできないことも実感した。

今後の構想の内容を実装しながら、次何作るか考えておかねば。