my-calculator / index.html
lior007's picture
Add 1 files
a2859c9 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Professional Scientific Calculator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300;400;500;700&display=swap');
body {
font-family: 'Roboto Mono', monospace;
}
.calculator {
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
.display {
min-height: 120px;
word-break: break-all;
}
.btn {
transition: all 0.1s ease;
transform-origin: center;
}
.btn:active {
transform: scale(0.95);
}
.btn-operator {
background-color: #3b82f6;
color: white;
}
.btn-operator:hover {
background-color: #2563eb;
}
.btn-function {
background-color: #10b981;
color: white;
}
.btn-function:hover {
background-color: #059669;
}
.btn-equals {
background-color: #f59e0b;
color: white;
}
.btn-equals:hover {
background-color: #d97706;
}
.btn-clear {
background-color: #ef4444;
color: white;
}
.btn-clear:hover {
background-color: #dc2626;
}
.btn-secondary {
background-color: #4b5563;
color: white;
}
.btn-secondary:hover {
background-color: #374151;
}
.btn-number {
background-color: #1f2937;
color: white;
}
.btn-number:hover {
background-color: #111827;
}
.history-item:hover {
background-color: #f3f4f6;
cursor: pointer;
}
.tab-active {
border-bottom: 3px solid #3b82f6;
font-weight: 500;
}
.scientific-panel {
transition: all 0.3s ease;
}
.angle-unit {
background-color: #e5e7eb;
color: #1f2937;
}
.angle-unit.active {
background-color: #3b82f6;
color: white;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-4">
<div class="calculator w-full max-w-md bg-white rounded-2xl overflow-hidden shadow-xl">
<!-- Calculator header with tabs -->
<div class="flex border-b">
<div class="tab tab-active py-3 px-6 text-center flex-1 cursor-pointer" data-tab="basic">
<i class="fas fa-calculator mr-2"></i> Basic
</div>
<div class="tab py-3 px-6 text-center flex-1 cursor-pointer" data-tab="scientific">
<i class="fas fa-square-root-alt mr-2"></i> Scientific
</div>
<div class="tab py-3 px-6 text-center flex-1 cursor-pointer" data-tab="history">
<i class="fas fa-history mr-2"></i> History
</div>
</div>
<!-- Display area -->
<div class="display p-4 bg-gray-50 text-right">
<div id="expression" class="text-gray-500 text-lg min-h-6 overflow-x-auto whitespace-nowrap"></div>
<div id="result" class="text-3xl font-semibold mt-2 overflow-x-auto whitespace-nowrap">0</div>
</div>
<!-- Angle unit selector -->
<div class="scientific-panel hidden px-4 py-2 bg-gray-100 flex justify-center space-x-2">
<button class="angle-unit active px-3 py-1 rounded-full text-sm" data-unit="deg">DEG</button>
<button class="angle-unit px-3 py-1 rounded-full text-sm" data-unit="rad">RAD</button>
<button class="angle-unit px-3 py-1 rounded-full text-sm" data-unit="grad">GRAD</button>
</div>
<!-- Calculator buttons -->
<div class="grid grid-cols-5 gap-1 p-2">
<!-- Row 1 -->
<button class="btn btn-clear col-span-2 py-4 rounded" data-action="clear">AC</button>
<button class="btn btn-clear py-4 rounded" data-action="backspace">
<i class="fas fa-backspace"></i>
</button>
<button class="btn btn-secondary py-4 rounded" data-action="percentage">%</button>
<button class="btn btn-operator py-4 rounded" data-action="divide">÷</button>
<!-- Row 2 -->
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="sin">sin</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="cos">cos</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="tan">tan</button>
<button class="btn btn-secondary py-4 rounded" data-action="power">x^y</button>
<button class="btn btn-operator py-4 rounded" data-action="multiply">×</button>
<!-- Row 3 -->
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="asin">sin⁻¹</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="acos">cos⁻¹</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="atan">tan⁻¹</button>
<button class="btn btn-secondary py-4 rounded" data-action="square"></button>
<button class="btn btn-operator py-4 rounded" data-action="subtract"></button>
<!-- Row 4 -->
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="log">log</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="ln">ln</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="factorial">x!</button>
<button class="btn btn-secondary py-4 rounded" data-action="sqrt"></button>
<button class="btn btn-operator py-4 rounded" data-action="add">+</button>
<!-- Row 5 -->
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="pi">π</button>
<button class="btn btn-function py-4 rounded scientific-btn hidden" data-action="e">e</button>
<button class="btn btn-secondary py-4 rounded" data-action="decimal">.</button>
<button class="btn btn-number py-4 rounded col-span-2" data-action="equals">=</button>
<!-- Row 6 (Numbers) -->
<button class="btn btn-number py-4 rounded" data-number="7">7</button>
<button class="btn btn-number py-4 rounded" data-number="8">8</button>
<button class="btn btn-number py-4 rounded" data-number="9">9</button>
<button class="btn btn-number py-4 rounded" data-number="4">4</button>
<button class="btn btn-number py-4 rounded" data-number="5">5</button>
<button class="btn btn-number py-4 rounded" data-number="6">6</button>
<button class="btn btn-number py-4 rounded" data-number="1">1</button>
<button class="btn btn-number py-4 rounded" data-number="2">2</button>
<button class="btn btn-number py-4 rounded" data-number="3">3</button>
<button class="btn btn-number py-4 rounded" data-number="0">0</button>
<button class="btn btn-number py-4 rounded" data-action="sign">±</button>
</div>
<!-- History panel (hidden by default) -->
<div id="history-panel" class="hidden max-h-64 overflow-y-auto p-4 border-t">
<div class="text-center text-gray-500 mb-2">Calculation History</div>
<div id="history-list"></div>
</div>
</div>
<script>
// DOM elements
const resultElement = document.getElementById('result');
const expressionElement = document.getElementById('expression');
const historyList = document.getElementById('history-list');
const tabs = document.querySelectorAll('.tab');
const scientificPanel = document.querySelector('.scientific-panel');
const scientificButtons = document.querySelectorAll('.scientific-btn');
const historyPanel = document.getElementById('history-panel');
const angleUnitButtons = document.querySelectorAll('.angle-unit');
// Calculator state
let currentInput = '0';
let previousInput = '';
let operation = null;
let resetInput = false;
let angleMode = 'deg'; // deg, rad, grad
let calculationHistory = [];
// Initialize calculator
updateDisplay();
// Event listeners for number buttons
document.querySelectorAll('[data-number]').forEach(button => {
button.addEventListener('click', () => {
appendNumber(button.getAttribute('data-number'));
});
});
// Event listeners for operation buttons
document.querySelectorAll('[data-action]').forEach(button => {
button.addEventListener('click', () => {
const action = button.getAttribute('data-action');
switch(action) {
case 'add':
case 'subtract':
case 'multiply':
case 'divide':
chooseOperation(action);
break;
case 'equals':
compute();
break;
case 'clear':
clear();
break;
case 'backspace':
backspace();
break;
case 'decimal':
appendDecimal();
break;
case 'sign':
toggleSign();
break;
case 'percentage':
percentage();
break;
case 'square':
square();
break;
case 'sqrt':
squareRoot();
break;
case 'power':
power();
break;
case 'sin':
sin();
break;
case 'cos':
cos();
break;
case 'tan':
tan();
break;
case 'asin':
asin();
break;
case 'acos':
acos();
break;
case 'atan':
atan();
break;
case 'log':
log();
break;
case 'ln':
ln();
break;
case 'factorial':
factorial();
break;
case 'pi':
appendPi();
break;
case 'e':
appendE();
break;
}
});
});
// Tab switching
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const tabName = tab.getAttribute('data-tab');
// Update active tab
tabs.forEach(t => t.classList.remove('tab-active'));
tab.classList.add('tab-active');
// Show/hide panels
if (tabName === 'scientific') {
scientificPanel.classList.remove('hidden');
scientificButtons.forEach(btn => btn.classList.remove('hidden'));
historyPanel.classList.add('hidden');
} else if (tabName === 'history') {
scientificPanel.classList.add('hidden');
scientificButtons.forEach(btn => btn.classList.add('hidden'));
historyPanel.classList.remove('hidden');
renderHistory();
} else {
scientificPanel.classList.add('hidden');
scientificButtons.forEach(btn => btn.classList.add('hidden'));
historyPanel.classList.add('hidden');
}
});
});
// Angle unit selection
angleUnitButtons.forEach(button => {
button.addEventListener('click', () => {
angleUnitButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
angleMode = button.getAttribute('data-unit');
});
});
// Keyboard support
document.addEventListener('keydown', (e) => {
if (e.key >= '0' && e.key <= '9') {
appendNumber(e.key);
} else if (e.key === '.') {
appendDecimal();
} else if (e.key === '+') {
chooseOperation('add');
} else if (e.key === '-') {
chooseOperation('subtract');
} else if (e.key === '*') {
chooseOperation('multiply');
} else if (e.key === '/') {
chooseOperation('divide');
} else if (e.key === 'Enter' || e.key === '=') {
compute();
} else if (e.key === 'Escape') {
clear();
} else if (e.key === 'Backspace') {
backspace();
} else if (e.key === '%') {
percentage();
} else if (e.key === '^') {
power();
}
});
// Calculator functions
function appendNumber(number) {
if (currentInput === '0' || resetInput) {
currentInput = number;
resetInput = false;
} else {
currentInput += number;
}
updateDisplay();
}
function appendDecimal() {
if (resetInput) {
currentInput = '0.';
resetInput = false;
return;
}
if (currentInput.indexOf('.') === -1) {
currentInput += '.';
}
updateDisplay();
}
function toggleSign() {
currentInput = (parseFloat(currentInput) * -1).toString();
updateDisplay();
}
function clear() {
currentInput = '0';
previousInput = '';
operation = null;
updateDisplay();
}
function backspace() {
if (currentInput.length === 1 || (currentInput.length === 2 && currentInput.startsWith('-'))) {
currentInput = '0';
} else {
currentInput = currentInput.slice(0, -1);
}
updateDisplay();
}
function chooseOperation(op) {
if (currentInput === '0' && previousInput !== '') {
operation = op;
return;
}
if (previousInput === '') {
previousInput = currentInput;
} else if (operation) {
const result = computeOperation(previousInput, currentInput, operation);
previousInput = result.toString();
}
operation = op;
currentInput = '0';
updateDisplay();
}
function compute() {
if (operation === null || previousInput === '') return;
const result = computeOperation(previousInput, currentInput, operation);
// Add to history
const historyEntry = {
expression: `${previousInput} ${getOperationSymbol(operation)} ${currentInput}`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
operation = null;
previousInput = '';
resetInput = true;
updateDisplay();
}
function computeOperation(num1, num2, op) {
const n1 = parseFloat(num1);
const n2 = parseFloat(num2);
switch(op) {
case 'add': return n1 + n2;
case 'subtract': return n1 - n2;
case 'multiply': return n1 * n2;
case 'divide': return n1 / n2;
default: return n2;
}
}
function percentage() {
currentInput = (parseFloat(currentInput) / 100).toString();
updateDisplay();
}
function square() {
const num = parseFloat(currentInput);
const result = num * num;
// Add to history
const historyEntry = {
expression: `${num}²`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function squareRoot() {
const num = parseFloat(currentInput);
const result = Math.sqrt(num);
// Add to history
const historyEntry = {
expression: `√${num}`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function power() {
previousInput = currentInput;
currentInput = '0';
operation = 'power';
expressionElement.textContent = `${previousInput}^`;
resultElement.textContent = currentInput;
}
function sin() {
let num = parseFloat(currentInput);
// Convert to radians if needed
if (angleMode === 'deg') {
num = degToRad(num);
} else if (angleMode === 'grad') {
num = gradToRad(num);
}
const result = Math.sin(num);
// Add to history
const historyEntry = {
expression: `sin(${currentInput}${angleMode})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function cos() {
let num = parseFloat(currentInput);
// Convert to radians if needed
if (angleMode === 'deg') {
num = degToRad(num);
} else if (angleMode === 'grad') {
num = gradToRad(num);
}
const result = Math.cos(num);
// Add to history
const historyEntry = {
expression: `cos(${currentInput}${angleMode})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function tan() {
let num = parseFloat(currentInput);
// Convert to radians if needed
if (angleMode === 'deg') {
num = degToRad(num);
} else if (angleMode === 'grad') {
num = gradToRad(num);
}
const result = Math.tan(num);
// Add to history
const historyEntry = {
expression: `tan(${currentInput}${angleMode})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function asin() {
let num = parseFloat(currentInput);
let result = Math.asin(num);
// Convert from radians if needed
if (angleMode === 'deg') {
result = radToDeg(result);
} else if (angleMode === 'grad') {
result = radToGrad(result);
}
// Add to history
const historyEntry = {
expression: `sin⁻¹(${currentInput})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function acos() {
let num = parseFloat(currentInput);
let result = Math.acos(num);
// Convert from radians if needed
if (angleMode === 'deg') {
result = radToDeg(result);
} else if (angleMode === 'grad') {
result = radToGrad(result);
}
// Add to history
const historyEntry = {
expression: `cos⁻¹(${currentInput})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function atan() {
let num = parseFloat(currentInput);
let result = Math.atan(num);
// Convert from radians if needed
if (angleMode === 'deg') {
result = radToDeg(result);
} else if (angleMode === 'grad') {
result = radToGrad(result);
}
// Add to history
const historyEntry = {
expression: `tan⁻¹(${currentInput})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function log() {
const num = parseFloat(currentInput);
const result = Math.log10(num);
// Add to history
const historyEntry = {
expression: `log(${currentInput})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function ln() {
const num = parseFloat(currentInput);
const result = Math.log(num);
// Add to history
const historyEntry = {
expression: `ln(${currentInput})`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function factorial() {
const num = parseInt(currentInput);
let result = 1;
for (let i = 2; i <= num; i++) {
result *= i;
}
// Add to history
const historyEntry = {
expression: `${currentInput}!`,
result: result
};
calculationHistory.unshift(historyEntry);
currentInput = result.toString();
updateDisplay();
}
function appendPi() {
if (currentInput === '0' || resetInput) {
currentInput = Math.PI.toString();
resetInput = false;
} else {
currentInput += Math.PI.toString();
}
updateDisplay();
}
function appendE() {
if (currentInput === '0' || resetInput) {
currentInput = Math.E.toString();
resetInput = false;
} else {
currentInput += Math.E.toString();
}
updateDisplay();
}
// Helper functions
function updateDisplay() {
resultElement.textContent = currentInput;
if (operation !== null) {
expressionElement.textContent = `${previousInput} ${getOperationSymbol(operation)}`;
} else {
expressionElement.textContent = '';
}
}
function getOperationSymbol(op) {
switch(op) {
case 'add': return '+';
case 'subtract': return '−';
case 'multiply': return '×';
case 'divide': return '÷';
case 'power': return '^';
default: return '';
}
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
function radToDeg(radians) {
return radians * 180 / Math.PI;
}
function gradToRad(grads) {
return grads * Math.PI / 200;
}
function radToGrad(radians) {
return radians * 200 / Math.PI;
}
function renderHistory() {
historyList.innerHTML = '';
if (calculationHistory.length === 0) {
historyList.innerHTML = '<div class="text-center text-gray-400 py-4">No history yet</div>';
return;
}
calculationHistory.forEach((item, index) => {
const historyItem = document.createElement('div');
historyItem.className = 'history-item p-2 border-b hover:bg-gray-50';
historyItem.innerHTML = `
<div class="text-sm text-gray-500">${item.expression}</div>
<div class="text-right font-semibold">${item.result}</div>
`;
historyItem.addEventListener('click', () => {
currentInput = item.result.toString();
updateDisplay();
});
historyList.appendChild(historyItem);
});
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=lior007/my-clock" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>