Features of this Javascript Calculator :
Modern UI Design:
- Clean, material-inspired interface
- Responsive layout that works on mobile and desktop
- Smooth animations and transitions
Calculator Functionality:
- Basic operations (+, -, ×, ÷)
- Percentage calculation
- Decimal input
- Clear and delete functions
- Keyboard support
History Panel:
- Toggleable side panel showing calculation history
- Stores up to 10 most recent calculations
- Persists history using localStorage
- Click on history items to reuse results
- Clear history button
Additional Features:
- Error handling
- Responsive design
- Visual feedback for button presses
- Proper decimal handling
How to Use :
Simply copy the entire code into an HTML file Open the file in any modern browser Use either mouse clicks or keyboard to perform calculations Click the hamburger menu (≡) to view calculation history Click on history items to reuse previous results The calculator maintains state between sessions using localStorage, so your history will persist even after closing the browser.
:root {
--primary-color: #6200ee;
--primary-light: #9e47ff;
--primary-dark: #0400ba;
--secondary-color: #03dac6;
--background: #f5f5f5;
--surface: #ffffff;
--error: #b00020;
--on-primary: #ffffff;
--on-secondary: #000000;
--on-background: #000000;
--on-surface: #000000;
--on-error: #ffffff;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--background);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.calculator {
width: 100%;
max-width: 400px;
background-color: var(--surface);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
height: 700px;
}
.display {
padding: 24px;
background-color: var(--primary-color);
color: var(--on-primary);
text-align: right;
position: relative;
min-height: 120px;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.history-toggle {
position: absolute;
top: 16px;
right: 16px;
background: none;
border: none;
color: var(--on-primary);
cursor: pointer;
font-size: 1.2rem;
opacity: 0.8;
transition: opacity 0.2s;
}
.history-toggle:hover {
opacity: 1;
}
.previous-operand {
font-size: 1rem;
opacity: 0.8;
margin-bottom: 8px;
min-height: 20px;
word-break: break-all;
}
.current-operand {
font-size: 2.5rem;
font-weight: 500;
word-break: break-all;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1px;
background-color: #e0e0e0;
flex-grow: 1;
}
button {
border: none;
outline: none;
background-color: var(--surface);
font-size: 1.2rem;
padding: 20px;
cursor: pointer;
transition: all 0.2s;
position: relative;
overflow: hidden;
}
button:active {
background-color: #e0e0e0;
}
button.span-2 {
grid-column: span 2;
}
.operator {
background-color: var(--primary-light);
color: var(--on-primary);
}
.equals {
background-color: var(--primary-color);
color: var(--on-primary);
}
.clear, .delete {
background-color: #f5f5f5;
}
.history-panel {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 300px;
background-color: var(--surface);
box-shadow: -4px 0 16px rgba(0, 0, 0, 0.1);
transform: translateX(100%);
transition: transform 0.3s ease;
padding: 20px;
overflow-y: auto;
z-index: 10;
}
.history-panel.visible {
transform: translateX(0);
}
.history-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #e0e0e0;
}
.history-title {
font-size: 1.2rem;
font-weight: 500;
}
.close-history {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--on-surface);
}
.history-item {
padding: 10px 0;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
}
.history-item:hover {
background-color: #f5f5f5;
}
.history-expression {
font-size: 0.9rem;
color: #666;
}
.history-result {
font-size: 1.1rem;
font-weight: 500;
text-align: right;
}
.clear-history {
margin-top: 20px;
padding: 10px;
background-color: var(--error);
color: var(--on-error);
border: none;
border-radius: 4px;
cursor: pointer;
width: 100%;
}
@media (max-width: 768px) {
.history-panel {
width: 100%;
}
}
document.addEventListener('DOMContentLoaded', () => {
// Calculator state
let currentOperand = '0';
let previousOperand = '';
let operation = undefined;
let resetScreen = false;
let calculationHistory = JSON.parse(localStorage.getItem('calculatorHistory')) || [];
// DOM elements
const currentOperandElement = document.getElementById('currentOperand');
const previousOperandElement = document.getElementById('previousOperand');
const historyPanel = document.getElementById('historyPanel');
const historyToggle = document.getElementById('historyToggle');
const closeHistory = document.getElementById('closeHistory');
const historyItems = document.getElementById('historyItems');
const clearHistory = document.getElementById('clearHistory');
// Number buttons
const numberButtons = document.querySelectorAll('[id^="one"], [id^="two"], [id^="three"], [id^="four"], [id^="five"], [id^="six"], [id^="seven"], [id^="eight"], [id^="nine"], [id^="zero"]');
// Operation buttons
const operationButtons = document.querySelectorAll('[id^="add"], [id^="subtract"], [id^="multiply"], [id^="divide"], [id^="percent"]');
// Other buttons
const equalsButton = document.getElementById('equals');
const clearButton = document.getElementById('clear');
const deleteButton = document.getElementById('delete');
const decimalButton = document.getElementById('decimal');
// Event listeners
numberButtons.forEach(button => {
button.addEventListener('click', () => appendNumber(button.textContent));
});
operationButtons.forEach(button => {
button.addEventListener('click', () => setOperation(button.textContent));
});
equalsButton.addEventListener('click', compute);
clearButton.addEventListener('click', clear);
deleteButton.addEventListener('click', deleteNumber);
decimalButton.addEventListener('click', appendDecimal);
historyToggle.addEventListener('click', toggleHistory);
closeHistory.addEventListener('click', toggleHistory);
clearHistory.addEventListener('click', clearHistoryItems);
// Keyboard support
document.addEventListener('keydown', handleKeyboardInput);
// Functions
function appendNumber(number) {
if (currentOperand === '0' || resetScreen) {
currentOperand = number;
resetScreen = false;
} else {
currentOperand += number;
}
updateDisplay();
}
function appendDecimal() {
if (resetScreen) {
currentOperand = '0.';
resetScreen = false;
return;
}
if (currentOperand.includes('.')) return;
currentOperand += '.';
updateDisplay();
}
function deleteNumber() {
if (currentOperand.length === 1 || (currentOperand.length === 2 && currentOperand.startsWith('-'))) {
currentOperand = '0';
} else {
currentOperand = currentOperand.slice(0, -1);
}
updateDisplay();
}
function setOperation(selectedOperation) {
if (currentOperand === '') return;
if (previousOperand !== '') {
compute();
}
// Replace symbols for display
let displayOperation = selectedOperation;
if (selectedOperation === '×') displayOperation = '*';
if (selectedOperation === '÷') displayOperation = '/';
operation = displayOperation;
previousOperand = `${currentOperand} ${selectedOperation}`;
currentOperand = '';
updateDisplay();
}
function compute() {
if (previousOperand === '' || operation === undefined || resetScreen) return;
const prev = parseFloat(previousOperand);
const current = parseFloat(currentOperand);
if (isNaN(current)) return;
let computation;
switch (operation) {
case '+':
computation = prev + current;
break;
case '-':
computation = prev - current;
break;
case '*':
computation = prev * current;
break;
case '/':
computation = prev / current;
break;
case '%':
computation = prev % current;
break;
default:
return;
}
// Add to history
const historyItem = {
expression: `${previousOperand} ${currentOperand}`,
result: computation.toString()
};
calculationHistory.unshift(historyItem);
if (calculationHistory.length > 10) {
calculationHistory.pop();
}
localStorage.setItem('calculatorHistory', JSON.stringify(calculationHistory));
updateHistoryDisplay();
currentOperand = computation.toString();
operation = undefined;
previousOperand = '';
resetScreen = true;
updateDisplay();
}
function clear() {
currentOperand = '0';
previousOperand = '';
operation = undefined;
updateDisplay();
}
function updateDisplay() {
currentOperandElement.textContent = currentOperand;
previousOperandElement.textContent = previousOperand;
}
function toggleHistory() {
historyPanel.classList.toggle('visible');
if (historyPanel.classList.contains('visible')) {
updateHistoryDisplay();
}
}
function updateHistoryDisplay() {
historyItems.innerHTML = '';
calculationHistory.forEach((item, index) => {
const historyItem = document.createElement('div');
historyItem.className = 'history-item';
historyItem.innerHTML = `
${item.expression} =
${item.result}
`;
historyItem.addEventListener('click', () => {
currentOperand = item.result;
updateDisplay();
toggleHistory();
});
historyItems.appendChild(historyItem);
});
}
function clearHistoryItems() {
calculationHistory = [];
localStorage.setItem('calculatorHistory', JSON.stringify(calculationHistory));
updateHistoryDisplay();
}
function handleKeyboardInput(e) {
if (e.key >= '0' && e.key <= '9') appendNumber(e.key);
else if (e.key === '.') appendDecimal();
else if (e.key === '=' || e.key === 'Enter') compute();
else if (e.key === 'Backspace') deleteNumber();
else if (e.key === 'Escape') clear();
else if (e.key === '+' || e.key === '-' || e.key === '*' || e.key === '/') {
setOperation(e.key);
} else if (e.key === '%') setOperation('%');
}
});
Post a Comment
Thank you
Learning robo team