0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Javascriptで電卓を作ろう 第4回 小数点を正しく入力しよう

Last updated at Posted at 2019-05-30

目次

第1回 HTMLとCSSでボタンを横並びで配置しよう

  • HTMLのマークアップ
  • CSS

第2回 四則演算をやってみよう

  • Javascriptで四則演算
  • 6)打った数字をコンソールに出力させよう。
  • 7)打った数字と記号を変数に格納しよう。
  • 8)計算結果を出力させよう。
  • 8-1)「=」を押した時の処理
  • 8-2) 計算結果と計算途中を、計算結果の画面に表示させよう。

第3回 連続で演算記号や小数点が押された場合の不具合処理

  • 最初に「+ ÷ - × =」が押せないようにする。
  • 二回連続で計算できるようにしたい。
  • Cボタン(リセットボタン)を押した時の処理
  • BS(バックスペース)ボタンを使えるようにする

第4回 小数点を正しく入力できるように改善しよう(今回の記事はここ)

  • 12.12.や12..12のように小数点を間違って入力できてしまう。
  • 電卓と同じように「.4」と入力したら0.4としたい。

第5回 演算記号を連続して押した時の不具合を直そう

第6回 バックスペースを押した時の不具合を直そう。

第7回 「4 ÷ 3 = 1.33333333333333333」の表示桁数を10桁にしたい

第8回 「電卓と同じ表示画面を目指そう

#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;
    }
  })
  
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?