目次
- HTMLのマークアップ
- CSS
- Javascriptで四則演算
- 6)打った数字をコンソールに出力させよう。
- 7)打った数字と記号を変数に格納しよう。
- 8)計算結果を出力させよう。
- 8-1)「=」を押した時の処理
- 8-2) 計算結果と計算途中を、計算結果の画面に表示させよう。
- 最初に「+ ÷ - × =」が押せないようにする。
- 二回連続で計算できるようにしたい。
- Cボタン(リセットボタン)を押した時の処理
- BS(バックスペース)ボタンを使えるようにする
- 12.12.や12..12のように小数点を間違って入力できてしまう。
- 電卓と同じように「.4」と入力したら0.4としたい。
第5回 演算記号を連続して押した時の不具合を直そう(今回の記事はここ)
第7回 「4 ÷ 3 = 1.33333333333333333」の表示桁数を10桁にしたい
最初に0を連続で押せてしまう。
「3+005」や「005+2」とならないようにしたい。
- 最初state==='start
- 計算終了後state==='finish'
- 演算記号入力直後state==='calBtn'
これらの時に、前の文字が0の時は0が入力できないようにする。
また、0の入力後にstateは変更しない。
state = 'calculation'//数字を入力している状態にする。
// 0の数字ボタンを押した時
const zero = document.getElementById('zero');
zero.addEventListener('click', () => {
// - 最初state==='start
// - 計算終了後state==='finish'
// - 演算記号入力直後state==='calBtn'の時、
// 前の文字が0の時は0が入力できないようにする。
if(state==='start'||state==='finish'||state==='calBtn'){
if(output_sub.textContent.slice(-1) === '0') {
//sliceで切り出されたのは0ではなく'0'
console.log('前の文字はゼロ');
return;
}
}
if(state==='start') {
total = zero.dataset.indexId;
}else{
total += zero.dataset.indexId;
}
output_sub.textContent = total;
// state = 'calculation'//数字を入力している状態にする。
}) //click
記号ボタン(+×÷-)を連続で押せてしまい、計算ができない。
連続で四則演算記号を押した場合は、最後に押した記号ボタンが採用されるようにしたい。 )
現在のコード
//「+ ÷ - ×」ボタンを押した時
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
}
output_sub.textContent = total;
state = 'calBtn'//演算記号を入力している状態する。
mode ='integer_mode'//整数モードに戻す
}) //click
})//forEach
【変更点】
演算記号入力状態state = 'calBtn'の時に、演算記号が押したら、totalの最後の一文字(演算記号)を削除し、新たに押した演算記号をtotalに追加する。
//「+ ÷ - ×」ボタンを押した時
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
}else if(state ==='calBtn') {
// 演算記号入力状態state = 'calBtn'の時に、演算記号を押したら、totalの最後の一文字(演算記号)を削除し、新たに押した演算記号を追加する。
// →totalに、totalの最初から最後から二文字目までを代入する(最後の一文字を削除する)
total = total.slice(0, -1)
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calBtn'//演算記号を入力している状態する。
mode ='integer_mode'//整数モードに戻す
}) //click
})//forEach
演算記号を押した後に数字を二回押さないと表示されない。
例)3+4=を行いたいとき
「3」「+」「4」「4」「=」
プログラムを見ると、1-9を押した時、
else if(state === 'calculation'){
//計算中totalに打った数字を追加して、totalに代入する。
total += index.dataset.indexId;
}
となっており、計算中モードstate === 'calculation'の場合、totalni
打った数字を追加するとなっている。なので、「+」「4」ここで計算中モードに切り替わって、最後の「4」が入力されていることが原因のようだ。なので、演算記号入力状態state = 'calBtn'でも打った数字を追加できるように以下のように書き換えた。
// 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'||state === 'calBtn'){
//計算中totalに打った数字を追加して、totalに代入する。
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
}) //click
})//forEach
#残りの課題
- 最初に0を連続で押せてしまう。
- 記号ボタン(+×÷-)を連続で押せてしまい、計算ができない。(連続で押した場合は、最後に押した記号ボタンが採用されるようにしたい。 )
- 演算記号を押した後に数字を二回押さないと表示されない。
- 割り算等で小数点以下が異様に長い。
- BSで文字を消した時、小数、整数モード、記号入力モードが切り替わらない。
- 表示画面が二つある。一つで表せないか?
#今日までのコード
###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>
###CSS
.container {
width: 200px;
margin: 50px auto;
border: 2px solid black;
}
.output {
width: 200px;
height: 50px;
line-height: 50px;
text-align: right;
padding: 5px;
margin-bottom: 5px;
border:2px solid black;
box-sizing: border-box;
}
.input {
width:200px;
border: 2px solid black;
}
.row {
display: flex;
justify-content: space-between;
border: 2px solid red;
width: 200px;
}
/*rowの範囲がわかりやすいように赤の枠を作っています。*/
.num_bth, #clear, #equal_btn{
width: 60px;
height: 30px;
text-align: center;
line-height: 30px;
border-radius: 30%;
background: lightgray;
cursor: pointer;
margin: 5px;
}
###Javascript
'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';//最初の状態を定義
// 1)計算する前の最初の状態(start)
// 2)数字を入力している最中(calculation)
// 3)「+ ÷ - × =」を押した直後(calBtn)
// 4)「=」を教えて計算が終わった直後(finish)
// 変数stateに、star,calculation, calBtn, finishを代入して状態を管理します。
let mode = 'integer_mode'; //最初は整数入力モード
// 変数modeに、整数入力中integer_mode、小数入力中decimal_modeを定義します。
// 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'||state === 'calBtn'){
//計算中totalに打った数字を追加して、totalに代入する。
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
}) //click
})//forEach
// 0の数字ボタンを押した時
const zero = document.getElementById('zero');
zero.addEventListener('click', () => {
// - 最初state==='start
// - 計算終了後state==='finish'
// - 演算記号入力直後state==='calBtn'の時、
// 前の文字が0の時は0が入力できないようにする。
if(state==='start'||state==='finish'||state==='calBtn'){
if(output_sub.textContent.slice(-1) === '0') {
//sliceで切り出されたのは0ではなく'0'
console.log('前の文字はゼロ');
return;
}
}
if(state==='start') {
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(mode === 'decimal_mode'){
return; //小数点入力モードではもう一度小数点を押せない
}
//「.4」と入力したら0.4としたい。(1)+(2)で0.4となる
if(state==='start'||state==='finish') {
total = 0;//(1)最初と計算終了直後なら、0を入力
}else if(state==='calBtn'){
//これを入れないと、0.4+0.4と打つと0.4+00.4となる。
if(output_sub.textContent.slice(-1)!=='0'){
total += 0;//(1')演算記号入力直後なら、今までの計算結果に0を入力
}
}
total += point.dataset.indexId;//(2)「.」を入力
output_sub.textContent = total;
state = 'calculation'//数字を入力している状態にする。
mode = 'decimal_mode'; //小数入力モードに変更
}) //click
//「+ ÷ - ×」ボタンを押した時
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
}else if(state ==='calBtn') {
// 演算記号入力状態state = 'calBtn'の時に、演算記号を押したら、totalの最後の一文字(演算記号)を削除し、新たに押した演算記号を追加する。
// →totalに、totalの最初から最後から二文字目までを代入する(最後の一文字を削除する)
total = total.slice(0, -1)
total += index.dataset.indexId;
}
output_sub.textContent = total;
state = 'calBtn'//演算記号を入力している状態する。
mode ='integer_mode'//整数モードに戻す
}) //click
})//forEach
//イコールを押した時
const equal_btn = document.getElementById('equal_btn');
equal_btn.addEventListener('click',() =>{
console.log(eval(total));
output_total.textContent = eval(total);
state = 'finish'//計算が終わった状態にする。
mode ='integer_mode'//整数モードに戻す
});
//Cボタン(リセットボタン)を押した時の処理
const clear = document.getElementById('clear')
clear.addEventListener('click', () => {
reset();
})
//リセットを行う関数
function reset() {
total = 0;
output_sub.textContent = 0;
output_total.textContent = 0;
mode ='integer_mode'//整数モードに戻す
}
//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;
}
})
}