JavaScript #7:電卓に履歴機能を追加する

公開:2026.05.09(土) 03:04

電卓に履歴機能を追加する

JavaScript #6:自作の処理を別ファイルにする」で作成した電卓に計算履歴を表示する機能を追加してみる。

追加する機能:
・計算するたびに、結果を history という配列(リスト)に追加
・配列の中身を、HTMLのリスト(
    など)として画面に表示

    1. index.html修正内容
    ・履歴を表示する領域 id=history-container 追加
    ・履歴を表示する ulノード id=history-list 追加
    ・履歴をクリアするボタン id=clear-history 追加
    <div id="history-container">
      <h3>計算機能</h3>
      <ul id="history-list"></ul>
      <button id="clear-history">履歴をクリア</button>
    </div>
    2. main.js修正内容
    ・履歴を格納するための historyData配列 を追加
    ・"="の処理で historyData配列 へ値の追加と liノードの追加
    // 履歴を表示するulノード
    const historyList = document.getElementById('history-list');
    
    // 履歴を格納するための historyData配列 を追加
    let historyData = [];
     :
    // "="の処理で historyData配列 へ値の追加と liノードの追加
    const expression = display.value;
    const result = calculate(display.value);
    
    if (result !== 'Error') {
        historyData.unshift(`${expression} = ${result}`);
        renderHistory();
    }
    display.value = result;
    
    ・履歴をクリアする id=clear-history ボタンと処理を追加
    // 履歴をクリアするボタン
    const clearHistoryBtn = document.getElementById('clear-history');
    
    // 履歴クリア処理
    function renderHistory() {
        historyList.innerHTML = '';
    
        historyData.forEach(item => {
            const li = document.createElement('li');
            li.textContent = item;
            historyList.appendChild(li);
        });
    }
    
    //  履歴をクリアボタンにイベント登録
    clearHistoryBtn.addEventListener('click', () => {
        historyData = [];
        renderHistory();
    });

    3. style.css修正内容
    履歴クリア用のスタイルを追加
    #history-container {
        margin-top: 20px;
        background: white;
        padding: 15px;
        border-radius: 10px;
        width: 300px;
        box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    }
    
    #history-list {
        list-style: none; /* 点を消す */
        padding: 0;
        max-height: 200px; /* 長くなったらスクロール */
        overflow-y: auto;
    }
    
    #history-list li {
        padding: 8px;
        border-bottom: 1px solid #eee;
        font-family: monospace;
    }
    
    #clear-history {
        margin-top: 10px;
        width: 100%;
        background-color: #ff4444;
        color: white;
        border: none;
        padding: 5px;
        cursor: pointer;
        border-radius: 4px;
    }

参考(全体ソース)

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Vite 電卓</title>
  </head>
  <body>
    <div id="app">
      <!-- ここに電卓のHTMLを貼り付けます -->
      <div id="calculator">
          <input type="text" id="display" readonly>
          <div class="buttons">
              <button>7</button><button>8</button><button>9</button><button>/</button>
              <button>4</button><button>5</button><button>6</button><button>*</button>
              <button>1</button><button>2</button><button>3</button><button>-</button>
              <button>0</button>
              <button>C</button>
              <button>=</button>
              <button>+</button>
          </div>
      </div>
      <div id="history-container">
        <h3>計算機能</h3>
        <ul id="history-list"></ul>
        <button id="clear-history">履歴をクリア</button>
      </div>
    </div>
    <script type="module" src="./src/main.js"></script>
  </body>
</html>

2. main.js
import './style.css'
import { calculate, clearDisplay } from './calculatorLogic.js'
 
const display = document.getElementById('display');
const buttons = document.querySelectorAll('#calculator .buttons button');
// 履歴を表示するulノード
const historyList = document.getElementById('history-list');
// 履歴をクリアするボタン
const clearHistoryBtn = document.getElementById('clear-history');

// 履歴を格納するための historyData配列 を追加
let historyData = [];

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.textContent;
 
        if (value === 'C') {
            display.value = clearDisplay();
        } else if (value === '=') {
            // "="の処理で historyData配列 へ値の追加と liノードの追加
            const expression = display.value;
            const result = calculate(display.value);

            if (result !== 'Error') {
                historyData.unshift(`${expression} = ${result}`);
                renderHistory();
            }
            display.value = result;
        } else {
            display.value += value;
        }
    });
});

// 履歴クリア処理
function renderHistory() {
    historyList.innerHTML = '';

    historyData.forEach(item => {
        const li = document.createElement('li');
        li.textContent = item;
        historyList.appendChild(li);
    });
}

//  履歴をクリアボタンにイベント登録
clearHistoryBtn.addEventListener('click', () => {
    historyData = [];
    renderHistory();
});

3. style.css
body {
    display: flex;
    justify-content: center; /* 横方向の中央 */
    align-items: center;    /* 縦方向の中央 */
    height: 100vh;         /* 画面いっぱいの高さ */
    background-color: #f0f0f0;
    margin: 0;
}
 
#calculator {
    background-color: #333;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.3);
}
 
/* 表示画面のスタイル */
#display {
    width: 100%;
    height: 50px;
    font-size: 24px;
    text-align: right;
    margin-bottom: 10px;
    padding: 10px;
    box-sizing: border-box; /* パディングを含めたサイズ計算 */
    border: none;
    border-radius: 5px;
}
.buttons {
    display: grid;
    /* 4つの列を同じ幅(1fr)で作る */
    grid-template-columns: repeat(4, 1fr); 
    /* ボタン同士の隙間 */
    gap: 10px;
}
 
button {
    padding: 20px;
    font-size: 18px;
    cursor: pointer;
    border: none;
    border-radius: 5px;
    background-color: #eee;
    transition: background-color 0.2s; /* ホバー時のアニメーション */
}
 
/* マウスが乗った時 */
button:hover {
    background-color: #ddd;
}
 
/* 計算ボタンなどの色を変える(お好みで) */
button:nth-child(4n) {
    background-color: #ff9500;
    color: white;
}
.wide {
    grid-column: span 2;
}

#history-container {
    margin-top: 20px;
    background: white;
    padding: 15px;
    border-radius: 10px;
    width: 300px;
    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}

#history-list {
    list-style: none; /* 点を消す */
    padding: 0;
    max-height: 200px; /* 長くなったらスクロール */
    overflow-y: auto;
}

#history-list li {
    padding: 8px;
    border-bottom: 1px solid #eee;
    font-family: monospace;
}

#clear-history {
    margin-top: 10px;
    width: 100%;
    background-color: #ff4444;
    color: white;
    border: none;
    padding: 5px;
    cursor: pointer;
    border-radius: 4px;
}

"JavaScript 学習"

0 件のコメント:

その他の記事