JavaScriptで簡単な電卓アプリを作ってみた

以下のサイトを参考にしました
[イヌでもわかるJavascript講座 - 電卓](http://cya.sakura.ne.jp/java/calc.htm)

制作したアプリ
[Document](https://atlansien.github.io/Calculator-made-with-javascript.io/)
Github
[GitHub - atlansien/Calculator-made-with-javascript.io](https://github.com/atlansien/Calculator-made-with-javascript.io)
制作時間:3日(７時間)

今回参考にしたサイトの電卓はあくまで基本的な四則演算ができるだけのプログラムで、個人的に思っている電卓とは違っていました。
なので、今回は個人的に改良したい点を一つずつ考えながら実装していきました。

---

## ソースコード

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

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <section id="frame">
      <p class="logo">Electronic Calculator</p>
      <div id="screen">0</div>
      <div class="horizontal">
        <a class="btn number ac" onclick="allCrear()">AC</a>
        <a class="btn number" onclick="inverted()">+/-</a>
        <a class="btn number" onclick="percent()">%</a>
        <a class="btn number" onclick="calclation('/')">÷</a>
      </div>
      <div class="horizontal">
        <a class="btn number" onclick="inputValue(7)">7</a>
        <a class="btn number" onclick="inputValue(8)">8</a>
        <a class="btn number" onclick="inputValue(9)">9</a>
        <a class="btn number" onclick="calclation('*')">×</a>
      </div>
      <div class="horizontal">
        <a class="btn number" onclick="inputValue(4)">4</a>
        <a class="btn number" onclick="inputValue(5)">5</a>
        <a class="btn number" onclick="inputValue(6)">6</a>
        <a class="btn number" onclick="calclation('-')">-</a>
      </div>
      <div class="horizontal">
        <a class="btn number" onclick="inputValue(1)">1</a>
        <a class="btn number" onclick="inputValue(2)">2</a>
        <a class="btn number" onclick="inputValue(3)">3</a>
        <a class="btn number" onclick="calclation('+')">+</a>
      </div>
      <div class="horizontal">
        <a class="btn zero" onclick="inputValue(0)">0</a>
        <a class="btn number" onclick="inputDot('.')">.</a>
        <a class="btn number" onclick="calclation('=')">=</a>
      </div>
    </section>
    <script src="js/main.js"></script>
  </body>
</html>

```
</div></details>

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

```css
body {
  margin: 100px auto;
  text-align: center;
  background-color: #ffedc6;
  font-family: 'Comic Sans MS';
}

#frame {
    margin: 0 auto;
    padding : 10px 0;
    width: 350px;
    background-color: #cdeeaa;
    border : 2px solid #000;
    box-shadow: 0 0 20px gray;
    border-radius: 30px;
}

#screen {
  margin: 0 auto;
  text-align: right;
  line-height: 60px;
  letter-spacing : 5px;
  width: 300px;
  height: 60px;
  background-color: #D1E0C1;
  border: 2px solid #000;
  border-radius: 10px;
  font-size: 2rem;
}

.horizontal a {
  display: inline-block;
  margin: 10px 5px;
}

.btn {
  height: 60px;
  line-height: 60px;
  background-color: #96dae4;
  text-align: center;
  border-radius: 10px;
  border: 2px solid #000;
  transition: 0.1s;
}

.btn:hover {
  cursor: pointer;
  box-shadow: 0 0 8px gray;
}

.btn:active {
  box-shadow: inset 0 0 8px #000;
}

.zero {
  width: 135px;
}

.number {
  width: 60px;
}

.ac {
    background-color: rgb(243, 97, 72);
}
```
</div></details>

<details><summary>JavaScript</summary><div>

```javascript
let symbol = "+";
let total = "";
let currentValue = "";
let flag = 0; // 数字 = 0, 演算子 = 1

const screen = document.getElementById("screen");

// 数字を入力
const inputValue = data => {
  if (currentValue.length <= 8) { // 入力できる最大文字数
    flag = 0;
    currentValue += data;
    screen.textContent = currentValue;
  }
};

// 文字列から.を見つけ、入力を制限する
const inputDot = data => {
  if (!currentValue.includes(".")) {
    currentValue += data;
    screen.textContent = currentValue;
  }
};

// プラスマイナスの反転
const inverted = () => {
  if (currentValue === "") { // 合計の数字を反転
    total = -total;
    screen.textContent = total;
  } else { // 入力した数字を反転
    currentValue = -currentValue;
    screen.textContent = currentValue;
  }
};

// 計算をする
const calclation = data => {
  if (flag === 0 && data !== "=") { // =以外の記号を押した
    flag = 1;

    let formula = total + symbol + currentValue;
    total = eval(formula);

    symbol = data;
    currentValue = "";
    screen.textContent = total;

  } else if (flag === 1 && data === "=") { // =を２回以上連打した
    let formula = total + symbol + total;
    total = eval(formula);

    currentValue = "";
    screen.textContent = total;

  } else if (data === "=") { // =を一回押した
    flag = 1;

    let formula = total + symbol + currentValue;
    total = eval(formula);

    currentValue = "";
    screen.textContent = total;

  } else { // =を押した後数字を入力せず記号を押した
    symbol = data;
  }
};

const percent = () => {
  if(symbol === "+" || symbol === "-") { // 足し算、引き算の場合の動作
   let formula = currentValue / 100;
   formula = total * formula;
   currentValue = eval(formula);
   
   screen.textContent = currentValue;
 }else { // それ以外(数字のみ、掛け算、割り算の動作)
   let formula = currentValue / 100;
   currentValue = eval(formula);

   screen.textContent = currentValue;
 }
};


// ACを押した場合の動作
const allCrear = () => {
  symbol = "+";
  total = "";
  currentValue = "";
  flag = 0;
  screen.textContent = "0";
};


```
</div></details>

---

## 改良、変更した点

### ドット（.）が何回でも打てる

ドットが何度でも打てると数字としておかしくなるので`indexOf`を使って文字内にすでにドットが存在する場合二重入力不可能にしました。
しかしその後`includes`を知り、こちらの方が現在の環境的に適したコードだと思ったので変更しました。

```js:indexOf
if(currentValue.indexOf('.') < 0)
```

```js:includes
if(!currentValue.includes('.'))
```

### inputタグを使いたくない

直接入力できるようにしたくなかったのでので、今回は`div`内に数字を表示させるようにしました。
あとあと考えると、別にinputで`disable="disable"`を使えばよかったかなと思いましたがまあ作れたのでOKということで。

### 入力する文字数の制限がない

`length`を使用して指定の文字数以上になったら入力できないようしました。
ここは今回使わなかった`input`を使った場合`maxlength`で制限できるところですね。

### イコールを連打した際に合計の数字同士の計算結果が出るようにしたい

flagと押下した時の演算子をif文で判別する事で計算することができるようになりました。

### プラマイ反転がない

単項演算子を使うことで反転できるようにしました

### %計算がない

この%計算はメーカーによって動作が変わるようで、今回は手近にあったiPhoneの電卓機能を参考にして作ってみました。


## 終わりに
まだ実装しきれていない機能はいくつかありますが(C/ACの切り替え)制作の期限を定めていたのでこの状態でアップロードしました。
今回は参考のプログラムを元に修正するだけでしたが、実際0からアプリを作る際も期限を意識しないといけないので、簡単なアプリでもいいからいくつか作ってみて自分がどれくらいの時間で物を作れるのか把握できるようになっていった方がいいかのな？とは思いました。

電卓アプリは、簡単に作れる部分と、少し頭をひねらないといけない部分があるので、プログラミング初学者が作ってみるのに最適なアプリです。みなさんもぜひ作ってはいかがでしょうか。