Calculator Script
class Calculator {
constructor() {
this.display = document.getElementById('display');
this.previousOperation = document.getElementById('previousOperation');
this.currentInput = '0';
this.previousInput = '';
this.operator = null;
this.waitingForOperand = false;
this.justCalculated = false;
this.initializeEventListeners();
this.initializeKeyboardSupport();
}
initializeEventListeners() {
// Button click events
document.querySelectorAll('.btn').forEach(button => {
button.addEventListener('click', (e) => {
this.createRipple(e);
this.handleButtonClick(button);
});
});
// History clear
document.querySelector('.history').addEventListener('click', () => {
this.clearHistory();
});
}
initializeKeyboardSupport() {
document.addEventListener('keydown', (e) => {
let handled = false;
if (e.key >= '0' && e.key <= '9') {
this.inputNumber(e.key);
handled = true;
} else if (e.key === '.') {
this.inputDecimal();
handled = true;
} else if (['+', '-', '*', '/'].includes(e.key)) {
const operatorMap = {
'+': '+',
'-': '-',
'*': '×',
'/': '÷'
};
this.inputOperator(operatorMap[e.key]);
handled = true;
} else if (e.key === 'Enter' || e.key === '=') {
this.calculate();
handled = true;
} else if (e.key === 'Escape') {
this.clearAll();
handled = true;
} else if (e.key === 'Backspace') {
this.backspace();
handled = true;
}
if (handled) {
e.preventDefault();
}
});
}
handleButtonClick(button) {
if (button.dataset.number) {
this.inputNumber(button.dataset.number);
} else if (button.dataset.operator) {
this.inputOperator(button.dataset.operator);
} else if (button.dataset.action) {
switch (button.dataset.action) {
case 'clear-all':
this.clearAll();
break;
case 'clear-entry':
this.clearEntry();
break;
case 'backspace':
this.backspace();
break;
case 'calculate':
this.calculate();
break;
}
}
}
inputNumber(num) {
if (this.waitingForOperand) {
this.currentInput = num;
this.waitingForOperand = false;
} else {
if (this.justCalculated) {
this.currentInput = num;
this.justCalculated = false;
this.previousOperation.textContent = '';
} else {
this.currentInput = this.currentInput === '0' ? num : this.currentInput + num;
}
}
this.updateDisplay();
}
inputDecimal() {
if (this.waitingForOperand) {
this.currentInput = '0.';
this.waitingForOperand = false;
} else if (this.currentInput.indexOf('.') === -1) {
this.currentInput += '.';
}
this.updateDisplay();
}
inputOperator(nextOperator) {
const inputValue = parseFloat(this.currentInput);
if (this.previousInput === '') {
this.previousInput = inputValue;
} else if (this.operator) {
const currentValue = this.previousInput || 0;
const newValue = this.performCalculation(currentValue, inputValue, this.operator);
if (newValue === null) return;
this.currentInput = String(newValue);
this.previousInput = newValue;
this.updateDisplay();
}
this.waitingForOperand = true;
this.operator = nextOperator;
this.justCalculated = false;
this.previousOperation.textContent = `${this.formatNumber(this.previousInput)} ${nextOperator}`;
this.updateOperatorButtons(nextOperator);
}
calculate() {
const inputValue = parseFloat(this.currentInput);
if (this.previousInput !== '' && this.operator) {
const newValue = this.performCalculation(this.previousInput, inputValue, this.operator);
if (newValue === null) return;
this.previousOperation.textContent = `${this.formatNumber(this.previousInput)} ${this.operator} ${this.formatNumber(inputValue)} =`;
this.currentInput = String(newValue);
this.previousInput = '';
this.operator = null;
this.waitingForOperand = false;
this.justCalculated = true;
this.updateDisplay();
this.animateCalculation();
this.clearOperatorButtons();
}
}
performCalculation(firstOperand, secondOperand, operator) {
let result;
switch (operator) {
case '+':
result = firstOperand + secondOperand;
break;
case '-':
result = firstOperand - secondOperand;
break;
case '×':
result = firstOperand * secondOperand;
break;
case '÷':
if (secondOperand === 0) {
this.showError('Cannot divide by zero');
return null;
}
result = firstOperand / secondOperand;
break;
default:
return null;
}
// Round to avoid floating point precision issues
return Math.round(result * 1000000000) / 1000000000;
}
clearAll() {
this.currentInput = '0';
this.previousInput = '';
this.operator = null;
this.waitingForOperand = false;
this.justCalculated = false;
this.previousOperation.textContent = '';
this.updateDisplay();
this.clearOperatorButtons();
}
clearEntry() {
this.currentInput = '0';
this.updateDisplay();
}
backspace() {
if (this.currentInput.length > 1) {
this.currentInput = this.currentInput.slice(0, -1);
} else {
this.currentInput = '0';
}
this.updateDisplay();
}
clearHistory() {
this.previousOperation.textContent = '';
document.querySelector('.history').style.animation = 'pulse 0.3s ease-in-out';
setTimeout(() => {
document.querySelector('.history').style.animation = '';
}, 300);
}
updateDisplay() {
this.display.value = this.formatNumber(this.currentInput);
// Add glow effect for large numbers
if (this.currentInput.length > 10) {
this.display.parentElement.classList.add('display-glow');
} else {
this.display.parentElement.classList.remove('display-glow');
}
}
formatNumber(num) {
const number = parseFloat(num);
if (isNaN(number)) return num;
// Format large numbers with commas
if (number >= 1000 || number <= -1000) {
return number.toLocaleString();
}
return num;
}
updateOperatorButtons(activeOperator) {
document.querySelectorAll('.btn-operator').forEach(btn => {
btn.classList.remove('active');
});
const activeButton = document.querySelector(`[data-operator="${activeOperator}"]`);
if (activeButton) {
activeButton.classList.add('active');
}
}
clearOperatorButtons() {
document.querySelectorAll('.btn-operator').forEach(btn => {
btn.classList.remove('active');
});
}
showError(message) {
this.display.value = 'Error';
this.display.parentElement.classList.add('error');
setTimeout(() => {
this.display.parentElement.classList.remove('error');
this.clearAll();
}, 1500);
}
animateCalculation() {
this.display.parentElement.classList.add('calculate');
setTimeout(() => {
this.display.parentElement.classList.remove('calculate');
}, 300);
}
createRipple(event) {
const button = event.currentTarget;
const rect = button.getBoundingClientRect();
const ripple = document.createElement('span');
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left - size / 2;
const y = event.clientY - rect.top - size / 2;
ripple.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
width: ${size}px;
height: ${size}px;
`;
ripple.classList.add('ripple');
button.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
}
}
// Initialize calculator when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new Calculator();
});
// Add some visual feedback for the calculator loading
document.addEventListener('DOMContentLoaded', () => {
const calculator = document.querySelector('.calculator');
calculator.style.opacity = '0';
calculator.style.transform = 'translateY(30px) scale(0.95)';
setTimeout(() => {
calculator.style.transition = 'all 0.6s ease-out';
calculator.style.opacity = '1';
calculator.style.transform = 'translateY(0) scale(1)';
}, 100);
});
Public Last updated: 2026-08-25 08:31:55 AM