build calculator with dom; use tailwind for design

main
CodexPremiera 3 months ago
parent f108634294
commit 4bac106603

8
.idea/.gitignore vendored

@ -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

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/js-dom-calculator.iml" filepath="$PROJECT_DIR$/.idea/js-dom-calculator.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.tailwindcss.com"></script>
<title>Calculator</title>
</head>
<body class="h-screen w-screen flex items-center justify-center">
<div class="w-2/5 flex flex-col p-10 border rounded-lg">
<!-- Header -->
<div class="h-10 my-5 flex items-center justify-center">
<h1 class="text-xl font-bold">JS Calculator</h1>
</div>
<!-- Calculator wrapper -->
<div class="w-full flex flex-col justify-center gap-4 mb-10">
<!-- Inputs and operation buttons -->
<div class="w-full flex flex-row gap-4">
<div class="flex flex-col gap-4 w-3/5">
<input id="firstNum" type="number" placeholder="First Number"
class="w-full p-2 border rounded-lg h-10" />
<input id="secondNum" type="number" placeholder="Second Number"
class="w-full p-2 border rounded-lg h-10" />
</div>
<div class="flex flex-col gap-4 w-2/5">
<button id="add" value="addition" class="w-full h-10 border rounded-lg disabled:cursor-not-allowed"
disabled>+</button>
<button id="sub" value="subtraction" class="w-full h-10 border rounded-lg disabled:cursor-not-allowed"
disabled>-</button>
<button id="mult" value="multiplication" class="w-full h-10 border rounded-lg disabled:cursor-not-allowed"
disabled>*</button>
<button id="div" value="division" class="w-full h-10 border rounded-lg disabled:cursor-not-allowed"
disabled>÷</button>
</div>
</div>
<!-- Memory buttons -->
<div class="flex items-center justify-center gap-4">
<button id="memStore" class="w-12 h-10 border rounded-lg">M+</button>
<button id="memRecall" class="w-12 h-10 border rounded-lg">MR</button>
<button id="memClear" class="w-12 h-10 border rounded-lg">MC</button>
</div>
<!-- Result -->
<div class="flex items-center justify-start">
<h3 id="result">Result: </h3>
</div>
</div>
<hr class="mb-10" />
<!-- History -->
<div class="flex flex-col">
<h3 class="font-semibold">History</h3>
<ul id="historyList" class="pl-5 pr-2 max-h-24 overflow-y-auto list-disc mt-2"></ul>
<button id="clear" class="w-28 h-10 mt-4 border rounded-lg disabled:cursor-not-allowed" disabled>
Clear History
</button>
</div>
</div>
<script src="index.js"></script>
</body>
</html>

@ -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.');
}
});
Loading…
Cancel
Save