From 4bac106603385f437942cb074ccdffae4b8d0774 Mon Sep 17 00:00:00 2001 From: CodexPremiera Date: Tue, 15 Apr 2025 00:04:11 +0800 Subject: [PATCH] build calculator with dom; use tailwind for design --- .idea/.gitignore | 8 +++ .idea/js-dom-calculator.iml | 12 ++++ .idea/modules.xml | 8 +++ .idea/vcs.xml | 6 ++ index.html | 68 +++++++++++++++++++ index.js | 127 ++++++++++++++++++++++++++++++++++++ 6 files changed, 229 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/js-dom-calculator.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 index.html create mode 100644 index.js diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/js-dom-calculator.iml b/.idea/js-dom-calculator.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/js-dom-calculator.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..0ac5a95 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..1231a97 --- /dev/null +++ b/index.html @@ -0,0 +1,68 @@ + + + + + + + + Calculator + + + +
+ +
+

JS Calculator

+
+ + +
+ +
+
+ + +
+
+ + + + +
+
+ + +
+ + + +
+ + +
+

Result:

+
+
+ +
+ + +
+

History

+
    + +
    +
    + + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..e625486 --- /dev/null +++ b/index.js @@ -0,0 +1,127 @@ +// Get DOM elements +const firstNum = document.getElementById('firstNum'); +const secondNum = document.getElementById('secondNum'); +const resultEl = document.getElementById('result'); +const historyList = document.getElementById('historyList'); +const clearHistoryBtn = document.getElementById('clear'); + +const opButtons = { + add: document.getElementById('add'), + sub: document.getElementById('sub'), + mult: document.getElementById('mult'), + div: document.getElementById('div'), +}; + +const memStore = document.getElementById('memStore'); +const memRecall = document.getElementById('memRecall'); +const memClear = document.getElementById('memClear'); + +// Global state +let history = []; +let memory = null; + +// Enable operation buttons only when both inputs are filled +function validateInputs() { + const hasValues = firstNum.value.trim() !== '' && secondNum.value.trim() !== ''; + Object.values(opButtons).forEach(btn => { + btn.disabled = !hasValues; + }); +} + +// Update button state on input +[firstNum, secondNum].forEach(input => { + input.addEventListener('input', validateInputs); +}); + +// Perform operation +function calculate(operation) { + const a = parseFloat(firstNum.value); + const b = parseFloat(secondNum.value); + if (isNaN(a) || isNaN(b)) { + resultEl.textContent = 'Result: Invalid input'; + return; + } + + let res; + let symbol; + switch (operation) { + case 'add': + res = a + b; + symbol = '+'; + break; + case 'sub': + res = a - b; + symbol = '-'; + break; + case 'mult': + res = a * b; + symbol = '*'; + break; + case 'div': + if (b === 0) { + resultEl.textContent = 'Result: Cannot divide by zero'; + return; + } + res = a / b; + symbol = '÷'; + break; + } + + resultEl.textContent = `Result: ${res}`; + const historyItem = `${a} ${symbol} ${b} = ${res}`; + history.push(historyItem); + updateHistory(); +} + +// Add click listeners to op buttons +Object.entries(opButtons).forEach(([key, btn]) => { + btn.addEventListener('click', () => calculate(key)); +}); + +// Update history list and clear history button state +function updateHistory() { + historyList.innerHTML = ''; + history.forEach(item => { + const li = document.createElement('li'); + li.textContent = item; + historyList.appendChild(li); + }); + clearHistoryBtn.disabled = history.length === 0; +} + +// Clear history +clearHistoryBtn.addEventListener('click', () => { + history = []; + updateHistory(); +}); + +// Memory buttons +memStore.addEventListener('click', () => { + const resText = resultEl.textContent; + const value = parseFloat(resText.split(': ')[1]); + if (!isNaN(value)) { + memory = value; + alert(`Memory Stored: ${memory}`); + } else { + alert('No valid result to store in memory.'); + } +}); + +memRecall.addEventListener('click', () => { + if (memory !== null) { + firstNum.value = memory; + validateInputs(); + alert(`Memory Recalled: ${memory}`); + } else { + alert('Memory is empty.'); + } +}); + +memClear.addEventListener('click', () => { + if (memory !== null) { + memory = null; + alert('Memory Cleared.'); + } else { + alert('Memory is already empty.'); + } +});