目次
- HTMLのマークアップ
- CSS
- Javascriptで四則演算
- 6)打った数字をコンソールに出力させよう。
- 7)打った数字と記号を変数に格納しよう。
- 8)計算結果を出力させよう。
- 8-1)「=」を押した時の処理
- 8-2) 計算結果と計算途中を、計算結果の画面に表示させよう。
- 最初に「+ ÷ - × =」が押せないようにする。
- 二回連続で計算できるようにしたい。
- Cボタン(リセットボタン)を押した時の処理
- BS(バックスペース)ボタンを使えるようにする
第4回 小数点を正しく入力できるように改善しよう(今回の記事はここ)
- 12.12.や12..12のように小数点を間違って入力できてしまう。
- 電卓と同じように「.4」と入力したら0.4としたい。
第7回 「4 ÷ 3 = 1.33333333333333333」の表示桁数を10桁にしたい
#12.12.や12..12のような正しくない小数は入力できないようにする。
###対処法
整数入力中、小数入力中を変数(mode)で定義します。
modeという変数を用意して、integer_mode、decimal_modeを代入して状態を管理します。
a)整数入力中(integer_mode)
- 「.」小数点を押すことができる。
b)小数入力中(decimal_mode)
- 「+ ÷ - ×」が押されるまでは、「.」小数点を押すことができない。(12.12.4や12..12とならないようにしたい)
これらを踏まえて、このこのように書いていきます。
小数点を押したら、
- 小数入力中mode==='demimal_mode'とする。
- このmodeでは、小数点は押せないようにする。
「+ ÷ - ×」、「=」「C」を押したら、
- 整数入力中mode==='integer_mode'に戻す。
'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'){
//計算中totalに打った数字を追加して、totalに代入する。
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(mode === 'decimal_mode'){
return;
}
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', () => {
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'//演算記号を入力している状態する。
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;
}
})
}
#電卓と同じように「.4」と入力したら0.4としたい。
【条件】
①
- 最初state==='start
- 計算終了後state==='finish'
の時に小数点が押されたらtotal=0とした後に
total = 0 + .とする。
②
- 演算記号入力直後state==='calBtn'
の時に小終点が押されたら
total += 0とした後に
total = total + .とする。
こうすることで「.」の前に0を挿入できる。
// 「.」小数点ボタンを押した時
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
残りの課題
- 最初に0を連続で押せてしまう。
- 記号ボタン(+×÷-)を連続で押せてしまい、計算ができない。(連続で押した場合は、最後に押した記号ボタンが採用されるようにしたい。 )
- 12.12.や12..12のように小数点を正しくなく入力できてしまう。 - 割り算等で小数点以下が異様に長い。
- 電卓と同じように「.4」と入力したら0.4としたい。 - 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'){
//計算中totalに打った数字を追加して、totalに代入する。
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(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
}
console.log(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;
}
})
}