build calculator with dom; use tailwind for design
parent
f108634294
commit
4bac106603
@ -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…
Reference in New Issue