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

#計算機を作る

##今回作る機能
###ボタン切り替え機能
1.演算子入力をボタン切り替え機能を使って、計算する。
2.演算子入力した後で、別の演算子を入力するとその演算子を使った計算に切り替わるようにする。
3.CLEARボタン押すことで、リセットできる。

押した演算子ボタンの計算行いたかったので計算の関数を多少改変した。

今回の記事では、どのボタンを押したか分かりやすく、ボタンの背景色をピンクにしている。

苦戦したのは、CLEARボタンを押すことで演算子ボタンを初期化する機能。

[getElementsByClassNameで指定したクラスを全部消す](https://cre8cre8.com/javascript/remove-classes-with-pure-javascript.htm)

上記のサイトで解決することができた。

##完成物

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="raimumk2" data-slug-hash="QWyRvjr" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="QWyRvjr">
  <span>See the Pen <a href="https://codepen.io/raimumk2/pen/QWyRvjr">
  QWyRvjr</a> by ライム (<a href="https://codepen.io/raimumk2">@raimumk2</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

##サンプルコード

<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 id="equal" onclick="calc('=')">=</button>
      </div>
      
      <div id="symbol-btns">
        <button class="symbol-btn" onclick="calc('/')">/</button>
        <button class="symbol-btn" onclick="calc('*')">*</button>
        <button class="symbol-btn" onclick="calc('-')">-</button>
        <button class="symbol-btn" 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;
  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;
}

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

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

.active {
  background-color: pink;
}
```
</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 (flag === 0 && data !== "=") {
    flag = 1;
    
    var formula = total + operator + currentValue;
    total = eval(formula);
    
    operator = data;
    currentValue = '';
    show.textContent = total;
    console.log(operator); //確認用
  } 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(operator);
  }
};

//ボタン切り替え機能の関数

var btns = document.getElementsByClassName('symbol-btn');
for (var i = btns.length - 1; i >= 0; i--) {
  btnAction(btns[i],i);
}

function btnAction(btnDOM, btnId) {
  btnDOM.addEventListener('click', function() {
    this.classList.add('active');

    for(var i = btns.length - 1; i >= 0; i--) {
      if(btnId !== i) {
        if(btns[i].classList.contains('active')) {
          btns[i].classList.remove('active');
        }
      }
    }
  });
}

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

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

function resetBackColor() {
  [].forEach.call(btns, function(e) {
    e.classList.remove('active');
  });
}

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

</div></details>


###該当するコード

```js:caluculate.js
//ボタン切り替え機能の関数
var btns = document.getElementsByClassName('symbol-btn');
for (var i = btns.length - 1; i >= 0; i--) {
  btnAction(btns[i],i);
}

function btnAction(btnDOM, btnId) {
  btnDOM.addEventListener('click', function() {
    this.classList.add('active');

    for(var i = btns.length - 1; i >= 0; i--) {
      if(btnId !== i) {
        if(btns[i].classList.contains('active')) {
          btns[i].classList.remove('active');
        }
      }
    }
  });
}

//計算の関数
var calc = data => {
  if (flag === 0 && data !== "=") {
    flag = 1;
    
    var formula = total + operator + currentValue;
    total = eval(formula);
    
    operator = data;
    currentValue = '';
    show.textContent = total;
    console.log(operator); //確認用
  } 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(operator);
  }
};
```

```js:caluculate.js
//CLEARボタンを押すことでクラスを取り除く関数
function resetBackColor() {
  [].forEach.call(btns, function(e) {
    e.classList.remove('active');
  });
}

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


##参考サイト
###js関連
[jQuery日本語リファレンス](http://semooh.jp/jquery/)

[qiita:jQuery classの追加・削除](https://qiita.com/Scheme/items/300739f6da6a95e58306)

[qiita:すっきり書きたい JavaScriptの条件分岐](https://qiita.com/taiju_suzuki/items/e2bf11fcf1645623235f)

[qiita:JS イベントまとめ](https://qiita.com/hththt/items/aefbcc6eb191588dadff)

[【jQuery入門】removeClass()でクラスを削除する方法まとめ！](https://www.sejuku.net/blog/54936)

[getElementsByClassNameで指定したクラスを全部消す](https://cre8cre8.com/javascript/remove-classes-with-pure-javascript.htm)

###エラー関連

[Uncaught Type Error: Cannot read property 'columns' of undefinedについて](https://teratail.com/questions/33448)

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

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

リストに追加する機能自体は、自分の記事からコピペして、今のコードに合うように書き換える。

リスト自体の配置やスタイルをどう当てるかが課題。

計算結果リストの編集機能は、主に削除さえできればと思っている。