calculator / index.html
namelessai's picture
Update index.html
c0ee664 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Scientific Calculator</title>
<!-- Math.js for evaluation -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/browser/math.min.js"></script>
<!-- KaTeX for rendering math -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" integrity="sha384-" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js" integrity="sha384-" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js" integrity="sha384-" crossorigin="anonymous"></script>
<style>
body {
font-family: sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #f2f2f2;
}
.calculator {
background: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
padding: 16px;
width: 360px;
}
.display {
width: 100%;
height: 48px;
font-size: 1.25rem;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
#preview {
min-height: 32px;
margin: 8px 0 12px;
padding: 4px;
background: #fafafa;
border: 1px solid #ddd;
border-radius: 4px;
}
.tabs { display: flex; margin-bottom: 8px; }
.tab {
flex: 1;
text-align: center;
padding: 8px;
cursor: pointer;
border-bottom: 2px solid transparent;
}
.tab.active { border-color: #007bff; color: #007bff; }
.buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
button { padding: 12px; font-size: 1rem; border: 1px solid #aaa; border-radius: 4px; background: #e6e6e6; cursor: pointer; transition: background 0.2s; }
button:hover { background: #d4d4d4; }
.op { background: #bbb; }
.wide { grid-column: span 2; }
</style>
</head>
<body>
<div class="calculator">
<input type="text" class="display" id="display" readonly />
<div id="preview"></div>
<div class="tabs">
<div class="tab active" data-mode="main">main</div>
<div class="tab" data-mode="abc">abc</div>
<div class="tab" data-mode="func">func</div>
<div class="tab" id="toggle-mode">RAD</div>
</div>
<div class="buttons" id="buttons-container">
<!-- main grid -->
<button data-cmd="7">7</button><button data-cmd="8">8</button><button data-cmd="9">9</button><button data-cmd="/" class="op">÷</button>
<button data-cmd="4">4</button><button data-cmd="5">5</button><button data-cmd="6">6</button><button data-cmd="*" class="op">×</button>
<button data-cmd="1">1</button><button data-cmd="2">2</button><button data-cmd="3">3</button><button data-cmd="-" class="op"></button>
<button data-cmd="0">0</button><button data-cmd=".">.</button><button data-cmd="ans">ans</button><button data-cmd="+" class="op">+</button>
<button data-cmd="%">%</button><button data-cmd="frac">a/b</button><button data-cmd="back"></button><button data-cmd="forward"></button>
<button class="wide" data-cmd="clear">C</button><button data-cmd="del">DEL</button><button class="wide" data-cmd="enter">=</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const display = document.getElementById('display');
const preview = document.getElementById('preview');
let ans = '';
let mode = 'main';
let angleMode = 'deg';
// update KaTeX preview
function updatePreview() {
try {
katex.render(display.value || ' ', preview, {throwOnError:false});
} catch {}
}
// evaluate with math.js
function evaluate(expr) {
try {
math.config({});
if (angleMode === 'deg') {
expr = expr.replace(/(sin|cos|tan)\(/g, match => `(${match}"deg", `);
}
const result = math.evaluate(expr);
ans = result.toString();
return ans;
} catch {
return 'Error';
}
}
// button logic
document.getElementById('buttons-container').addEventListener('click', e => {
if (!e.target.matches('button')) return;
const cmd = e.target.dataset.cmd;
switch (cmd) {
case 'clear': display.value = ''; break;
case 'del': display.value = display.value.slice(0, -1); break;
case 'ans': display.value += ans; break;
case 'enter': display.value = evaluate(display.value); break;
case 'frac': display.value += '/'; break;
case 'square': display.value += '^(2)'; break;
case '^': display.value += '^('; break;
case 'sqrt(': case 'nthroot(': case 'abs(': case 'sin(': case 'cos(': case 'tan(': case '(': case ')': case ',': case 'pi':
display.value += cmd === 'pi' ? 'pi' : cmd;
break;
default:
if (/^[0-9.+\-*/%^]$/.test(cmd)) display.value += cmd;
}
updatePreview();
});
// keyboard shortcuts
document.addEventListener('keydown', e => {
const k = e.key;
if (k === 'Enter') { display.value = evaluate(display.value); updatePreview(); e.preventDefault(); }
else if (k === 'Backspace') { display.value = display.value.slice(0, -1); updatePreview(); e.preventDefault(); }
else if (k === 'p') { display.value += 'pi'; updatePreview(); e.preventDefault(); }
else if (k === 's') { display.value += 'sin('; updatePreview(); e.preventDefault(); }
else if (k === 'c') { display.value += 'cos('; updatePreview(); e.preventDefault(); }
else if (k === 't') { display.value += 'tan('; updatePreview(); e.preventDefault(); }
});
// modes & toggle
const modeButtons = {
abc: [{label:'a²',cmd:'square'},{label:'a^b',cmd:'^'},{label:'|a|',cmd:'abs('},{label:'√',cmd:'sqrt('},{label:'ⁿ√',cmd:'nthroot('},{label:'π',cmd:'pi'}],
func: [{label:'sin',cmd:'sin('},{label:'cos',cmd:'cos('},{label:'tan',cmd:'tan('},{label:'(',cmd:'('},{label:')',cmd:')'},{label:',',cmd:','}]
};
function renderMode() {
const c = document.getElementById('buttons-container');
while (c.children.length > 20) c.removeChild(c.lastChild);
if (mode !== 'main') modeButtons[mode].forEach(b=>{ const btn=document.createElement('button');btn.textContent=b.label;btn.dataset.cmd=b.cmd;c.insertBefore(btn,c.firstChild); });
}
document.querySelectorAll('.tab[data-mode]').forEach(tab => tab.addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));
tab.classList.add('active'); mode=tab.dataset.mode; renderMode(); updatePreview();
}));
document.getElementById('toggle-mode').addEventListener('click', e => { angleMode = angleMode==='deg'?'rad':'deg'; e.target.textContent = angleMode.toUpperCase(); });
renderMode(); updatePreview();
});
</script>
</body>
</html>