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