目次
- HTMLのマークアップ
- CSS
- Javascriptで四則演算
- 6)打った数字をコンソールに出力させよう。
- 7)打った数字と記号を変数に格納しよう。
- 8)計算結果を出力させよう。
- 8-1)「=」を押した時の処理
- 8-2) 計算結果と計算途中を、計算結果の画面に表示させよう。
第3回 連続で演算記号や小数点が押された場合の不具合処理(今回の記事はここ)
- 最初に「+ ÷ - × =」が押せないようにする。
- 二回連続で計算できるようにしたい。
- Cボタン(リセットボタン)を押した時の処理
- BS(バックスペース)ボタンを使えるようにする
- 12.12.や12..12のように小数点を間違って入力できてしまう。
- 電卓と同じように「.4」と入力したら0.4としたい。
第7回 「4 ÷ 3 = 1.33333333333333333」の表示桁数を10桁にしたい
前回作成した電卓について、以下のような点を改善したいと思います。
前回の記事
- 最初に「+ ÷ - = .」が押せてしまう。
- 最初に0を連続で押せてしまう(00.4や00043となってしまう)
- 記号ボタン(+×÷-)を連続で押せてしまい、計算ができない。(連続で押した場合は、最後に押した記号ボタンが採用されるようにしたい。
) - 一度計算をやると、次の計算をするときに、ブラウザを読み込みなおさないといけない(Cボタンを使えるようにしよう)
- 前回の計算結果を利用して、次の計算を行いたい。
- 12.12.や12..12のように間違った小数を入力できてしまう。
- 電卓と同じように「.4」と入力したら0.4としたい。
- 一度間違えると、全てやり直し(BSボタンを使えるようにしたい)
- 割り算等で小数点以下が異様に長い。
#対処法1)
これらに対応するため、状態を定義します。
1)計算する前の最初の状態(start)
2)数字を入力している最中(calculation)
3)「+ ÷ - × =」を押した直後(calBtn)
4)「=」を教えて計算が終わった直後(finish)
stateという変数を用意して、star,calculation, calBtn, finishを代入して状態を管理します。
1)計算する前の最初の状態(start)
- 「+ ÷ - × =」が押せないようにする。
- 0を連続で押された時に、1つだけ入力するようにしたい。
2)数字を入力している最中(calculation)
- どのボタンも押せる
3)「+ ÷ - ×」を押した直後(calBtn)
- 「+ ÷ - ×」を連続で押した場合、最後に押されたボタンを採用するようにしたい。
- 0を連続で押された時に、1つだけ入力するようにしたい。
4)「=」を教えて計算が終わった直後(finish)
- 「=」を押せないようにしたい。
- 次に数字が押された場合、前の計算結果はリセットして、計算をやり直す。
- 次に「+ ÷ - ×」を押した場合、前回の計算結果を利用して続けて計算する。
#対処法2)
これとは別に整数入力中、小数入力中を別の変数で定義します。
modeという変数を用意して、integer_mode、decimal_modeを代入して状態を管理します。
a)整数入力中(integer_mode)
-「.」小数点を押すことができる。
b)小数入力中(decimal_mode)
- 「+ ÷ - ×」が押されるまでは、「.」小数点を押すことができない。(12.12.4や12..12とならないようにしたい)
#HTMLの変更
現在は、0,1,2,3,4,5,6,7,8,9,+,-,,/全てが同じclass="num_bth"となっているが、状態管理するにあたり、「0」「1-9」「+,-,,/」「.(point)」を別の変数で管理することにします。
「0」 id="zero"
「1-9 class="one_nine"
「+,-,*,/」class="cal"
「. (point)」 id="point"
HTML変更後
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>電卓</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class = "container">
<!-- 計算結果を出力する場所-->
<div id = "output_total" class="output ">0</div>
<!-- 計算過程を出力する -->
<div id = "output_sub" class="output active">0</div>
<!-- ボタンを配置する場所-->
<div class = 'input'>
<section class = 'row'>
<div id = "clear">C</div>
<div class = "num_bth"></div>
<div class = "num_bth" id="bs">BS</div>
<div class = "num_bth cal" data-index-id= '/'>÷</div>
</section>
<section class = 'row'>
<div class = "num_bth one_nine " data-index-id = 9 >9</div>
<div class = "num_bth one_nine " data-index-id = 8 >8</div>
<div class = "num_bth one_nine " data-index-id = 7 >7</div>
<div class = "num_bth cal" data-index-id = '*'>×</div>
</section>
<section class = 'row'>
<div class = "num_bth one_nine " data-index-id = 6 >6</div>
<div class = "num_bth one_nine " data-index-id = 5 >5</div>
<div class = "num_bth one_nine " data-index-id = 4 >4</div>
<div class = "num_bth cal" data-index-id = '-'>-</div>
</section>
<section class = 'row'>
<div class = "num_bth one_nine " data-index-id = 3 >3</div>
<div class = "num_bth one_nine" data-index-id = 2 >2</div>
<div class = "num_bth one_nine" data-index-id = 1 >1</div>
<div class = "num_bth cal" data-index-id = '+'>+</div>
</section>
<section class = 'row'>
<div class = "num_bth" data-index-id = 00 >00</div>
<div class = "num_bth" id="zero" data-index-id = 0 >0</div>
<div class = "num_bth" id="point" data-index-id = . >.</div>
<div id = 'equal_btn'>=</div>
</section>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
#JavascriptをHTMLに合わせて、「0」「1-9」「+,-,*,/」「.(point)」が押せるように以下のように変更
'use strict'
{
const num_bth = document.querySelectorAll('.num_bth');
let output_sub = document.getElementById('output_sub');//計算結果を表示する場所
const output_total = document.getElementById('output_total');//計算過程を表示する場所
let total = 0;//計算式を表す変数
let state = 'start';//最初の状態を定義
let mode = 'integer_mode'; //最初は整数入力モード
// 1-9の数字ボタンを押した時
const one_nine = document.querySelectorAll('.one_nine');
one_nine.forEach(index => {
index.addEventListener('click', () => {
console.log(index.dataset.indexId)
if(total === 0) {
total = index.dataset.indexId;
}else{
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
}) //click
})//forEach
// 0の数字ボタンを押した時
const zero = document.getElementById('zero');
zero.addEventListener('click', () => {
console.log(zero.dataset.indexId)
if(total === 0) {
total = zero.dataset.indexId;
}else{
total += zero.dataset.indexId;
}
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
}) //click
// 「.」小数点ボタンを押した時
const point = document.getElementById('point');
point.addEventListener('click', () => {
console.log(point.dataset.indexId)
if(total === 0) {
total = point.dataset.indexId;
}else{
total += point.dataset.indexId;
}
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
mode = 'decimal_mode'; //小数入力モードに変更
}) //click
//「+ ÷ - ×」ボタンを押した時
const cal = document.querySelectorAll('.cal');
cal.forEach(index => {
index.addEventListener('click', () => {
console.log(index.dataset.indexId)
if(total === 0) {
total = index.dataset.indexId;
}else{
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calBtn'//演算記号を入力している状態する。
}) //click
})//forEach
//イコールを押した時
const equal_btn = document.getElementById('equal_btn');
equal_btn.addEventListener('click',() =>{
console.log(eval(total));
output_total.textContent = eval(total);
});
}
#最初に「+ ÷ - × =」が押せないようにする。
最初の状態の時state==='start'に演算記号が押せないようにしたい。
if(state === 'start') {
return;
}
returnとし、以下の処理が行われないようにすればよい。
//「+ ÷ - ×」ボタンを押した時
const cal = document.querySelectorAll('.cal');
cal.forEach(index => {
index.addEventListener('click', () => {
if(state === 'start') {
return;
}
console.log(index.dataset.indexId)
if(total === 0) {
total = index.dataset.indexId;
}else{
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calBtn'//演算記号を入力している状態する。
}) //click
})//forEach
#二回連続で計算できるようにしたい。
「2 × 3 = 6」「6 + 2 = 8」を連続して計算しようとするとこうなってしまう
電卓の機能として以下のようにしたい。
- 計算後に数字を押した場合:前回の結果はリセットして計算しなおす。
- 計算後に演算記号を押した場合:前回の計算結果にを再度利用して計算を続ける。
というわけで、数字を押した時、記号を押した時の各stateごとの処理は以下の通り。
数字を押した時
- 最初(state==="start"):
- totalに打った数字を代入する
- stateをcalculationに変える
- 計算後(state==="finish")
- リセット処理後に、totalに打った数字を代入する
- stateを計算中(calculation)に変える
- 計算中(state==="calculation")
- totalに打った数字を追加して、totalに代入する。
// 1-9の数字ボタンを押した時
const one_nine = document.querySelectorAll('.one_nine');
one_nine.forEach(index => {
index.addEventListener('click', () => {
if(state === 'start') {
//最初totalに打った数字を代入する
total = index.dataset.indexId;
}else if(state === 'finish') {
//計算後、リセット処理後に、totalに打った数字を代入する
reset();
total = index.dataset.indexId;
}else if(state === 'calculation'){
//計算中totalに打った数字を追加して、totalに代入する。
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
}) //click
})//forEach
//リセットを行う関数
function reset() {
total = 0;
output_sub.textContent = 0;
output_total.textContent = 0;
}
記号を押した時
- 最初(state="start"):
- 記号は押せないようにする
- 計算後(state="finish")
- 前の計算結果をtotal に代入して計算しなおす。
- 計算過程表示画面に前の計算結果を表示させる。
- 計算結果表示画面を"0"を表示させる。
- stateを演算記号を押した後(calBtn)に変える
- 計算中(state="calculation")
- totalに打った記号を追加し、totalに代入する。
-
- stateを演算記号を押した後(calBtn)に変える
//「+ ÷ - ×」ボタンを押した時
const cal = document.querySelectorAll('.cal');
cal.forEach(index => {
index.addEventListener('click', () => {
if(state === 'start') {
return;//最初記号は押せない
}else if(state === 'calculation'){
total += index.dataset.indexId;//計算中はtotalに打った記号を追加し、totalに代入する。
}else if(state === 'finish'){
//計算後は前の計算結果をtotal に代入して計算しなおす。
total = output_total.textContent;
total += index.dataset.indexId;
output_total.textContent = 0
}
console.log(index.dataset.indexId)
output_sub.textContent = total;
state = 'calBtn'//演算記号を入力している状態する。
}) //click
})//forEach
#Cボタン(リセットボタン)を押した時の処理
//Cボタン(リセットボタン)を押した時の処理
const clear = document.getElementById('clear')
clear.addEventListener('click', () => {
reset();
})
//リセットを行う関数
function reset() {
total = 0;
output_sub.textContent = 0;
output_total.textContent = 0;
}
#BS(バックスペース)ボタンを使えるようにする
- 計算終了後(state === "finish") はBSを押せない。
- それ以外の時は、最初から最後から二文字目までをtotalに代入(最後の一文字を除きtotalに代入する)
slice関数
str.slice(0, -1) は、文字列から 0 番目の文字から最後から 2 番目の文字までを取り出します。
String.prototype.slice()
//BSボタン(バックスペース)を押した時の処理
const bs = document.getElementById('bs')
bs.addEventListener('click', () => {
console.log('BS')
if(state ==="finish") {
return;//計算後は、bsを押せない。
}else{
// 一文字目から、最後から二文字目までをtotalに代入(最後の一文字を除きtotalに代入する)
total = output_sub.textContent.slice(0, -1);
output_sub.textContent = total;
}
})
#残りの課題 次回へ
- 最初に「+ ÷ - = .」が押せてしまう。
- 最初に0を連続で押せてしまう(00.4や00043となってしまう)
- 記号ボタン(+×÷-)を連続で押せてしまい、計算ができない。(連続で押した場合は、最後に押した記号ボタンが採用されるようにしたい。
- 一度計算をやると、次の計算をするときに、ブラウザを読み込みなおさないといけない(Cボタンを使えるようにしよう)
- 前回の計算結果を利用して、次の計算を行いたい。 - 12.12.や12..12のように間違った小数を入力できてしまう。
- 電卓と同じように「.4」と入力したら0.4としたい。
- 一度間違えると、全てやり直し(BSボタンを使えるようにしたい) - 割り算等で小数点以下が異様に長い。