fix(repo): remove stray calculator artifact
This commit is contained in:
parent
024b9c481c
commit
e215c09af0
3 changed files with 0 additions and 493 deletions
|
|
@ -1,44 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
|
||||||
<meta name="theme-color" content="#1a1a2e" />
|
|
||||||
<title>Калькулятор</title>
|
|
||||||
<link rel="stylesheet" href="style.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app">
|
|
||||||
<div id="display" role="status" aria-live="polite" aria-label="Результат">
|
|
||||||
<div id="expression" aria-hidden="true"></div>
|
|
||||||
<div id="result">0</div>
|
|
||||||
</div>
|
|
||||||
<div id="buttons">
|
|
||||||
<button type="button" data-action="clear" aria-label="Очистить">C</button>
|
|
||||||
<button type="button" data-action="sign" aria-label="Сменить знак">±</button>
|
|
||||||
<button type="button" data-action="backspace" aria-label="Удалить символ">⌫</button>
|
|
||||||
<button type="button" data-action="operator" data-value="/" aria-label="Разделить">÷</button>
|
|
||||||
|
|
||||||
<button type="button" data-action="digit" data-value="7">7</button>
|
|
||||||
<button type="button" data-action="digit" data-value="8">8</button>
|
|
||||||
<button type="button" data-action="digit" data-value="9">9</button>
|
|
||||||
<button type="button" data-action="operator" data-value="*" aria-label="Умножить">×</button>
|
|
||||||
|
|
||||||
<button type="button" data-action="digit" data-value="4">4</button>
|
|
||||||
<button type="button" data-action="digit" data-value="5">5</button>
|
|
||||||
<button type="button" data-action="digit" data-value="6">6</button>
|
|
||||||
<button type="button" data-action="operator" data-value="-" aria-label="Вычесть">−</button>
|
|
||||||
|
|
||||||
<button type="button" data-action="digit" data-value="1">1</button>
|
|
||||||
<button type="button" data-action="digit" data-value="2">2</button>
|
|
||||||
<button type="button" data-action="digit" data-value="3">3</button>
|
|
||||||
<button type="button" data-action="operator" data-value="+" aria-label="Сложить">+</button>
|
|
||||||
|
|
||||||
<button type="button" data-action="digit" data-value="0" id="btn-zero">0</button>
|
|
||||||
<button type="button" data-action="decimal" aria-label="Десятичная точка">.</button>
|
|
||||||
<button type="button" data-action="equals" aria-label="Равно">=</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="script.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
213
2227/script.js
213
2227/script.js
|
|
@ -1,213 +0,0 @@
|
||||||
const MAX_DIGITS = 15;
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
currentValue: "0",
|
|
||||||
previousValue: null,
|
|
||||||
operator: null,
|
|
||||||
shouldResetDisplay: false,
|
|
||||||
isError: false,
|
|
||||||
lastOperand: null,
|
|
||||||
lastOperator: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expressionEl = document.getElementById("expression");
|
|
||||||
const resultEl = document.getElementById("result");
|
|
||||||
|
|
||||||
function formatNumber(str) {
|
|
||||||
if (str === "Error") return str;
|
|
||||||
if (str === "Infinity" || str === "-Infinity") return "Error";
|
|
||||||
if (str === "NaN") return "Error";
|
|
||||||
const num = parseFloat(str);
|
|
||||||
if (!isFinite(num)) return "Error";
|
|
||||||
if (Number.isInteger(num) && Math.abs(num) < 1e15) {
|
|
||||||
return String(num);
|
|
||||||
}
|
|
||||||
const fixed = num.toPrecision(12);
|
|
||||||
return String(parseFloat(fixed));
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateDisplay() {
|
|
||||||
if (state.isError) {
|
|
||||||
resultEl.textContent = "Error";
|
|
||||||
resultEl.style.color = "#e94560";
|
|
||||||
} else {
|
|
||||||
resultEl.textContent = state.currentValue;
|
|
||||||
resultEl.style.color = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearError() {
|
|
||||||
if (state.isError) {
|
|
||||||
state.isError = false;
|
|
||||||
state.currentValue = "0";
|
|
||||||
state.previousValue = null;
|
|
||||||
state.operator = null;
|
|
||||||
state.lastOperand = null;
|
|
||||||
state.lastOperator = null;
|
|
||||||
state.shouldResetDisplay = false;
|
|
||||||
expressionEl.textContent = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendDigit(digit) {
|
|
||||||
clearError();
|
|
||||||
if (state.shouldResetDisplay) {
|
|
||||||
state.currentValue = digit;
|
|
||||||
state.shouldResetDisplay = false;
|
|
||||||
} else {
|
|
||||||
if (digit === "0" && state.currentValue === "0") return;
|
|
||||||
state.currentValue = state.currentValue === "0" ? digit : state.currentValue + digit;
|
|
||||||
}
|
|
||||||
state.currentValue = state.currentValue.slice(0, MAX_DIGITS);
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDecimal() {
|
|
||||||
clearError();
|
|
||||||
if (state.shouldResetDisplay) {
|
|
||||||
state.currentValue = "0.";
|
|
||||||
state.shouldResetDisplay = false;
|
|
||||||
updateDisplay();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!state.currentValue.includes(".")) {
|
|
||||||
state.currentValue += ".";
|
|
||||||
}
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBackspace() {
|
|
||||||
clearError();
|
|
||||||
if (state.shouldResetDisplay) return;
|
|
||||||
if (state.currentValue.length <= 1 || (state.currentValue.length === 2 && state.currentValue.startsWith("-"))) {
|
|
||||||
state.currentValue = "0";
|
|
||||||
} else {
|
|
||||||
state.currentValue = state.currentValue.slice(0, -1);
|
|
||||||
}
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleOperator(op) {
|
|
||||||
clearError();
|
|
||||||
const current = parseFloat(state.currentValue);
|
|
||||||
if (state.operator && !state.shouldResetDisplay) {
|
|
||||||
compute();
|
|
||||||
}
|
|
||||||
state.previousValue = current;
|
|
||||||
state.operator = op;
|
|
||||||
state.shouldResetDisplay = true;
|
|
||||||
expressionEl.textContent = `${formatNumber(String(current))} ${op}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function compute() {
|
|
||||||
const prev = state.previousValue;
|
|
||||||
const current = parseFloat(state.currentValue);
|
|
||||||
if (prev === null) return;
|
|
||||||
|
|
||||||
let result;
|
|
||||||
switch (state.operator) {
|
|
||||||
case "+": result = prev + current; break;
|
|
||||||
case "-": result = prev - current; break;
|
|
||||||
case "*": result = prev * current; break;
|
|
||||||
case "/":
|
|
||||||
if (current === 0) {
|
|
||||||
state.isError = true;
|
|
||||||
state.currentValue = "Error";
|
|
||||||
state.operator = null;
|
|
||||||
state.previousValue = null;
|
|
||||||
updateDisplay();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result = prev / current;
|
|
||||||
break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.lastOperand = current;
|
|
||||||
state.lastOperator = state.operator;
|
|
||||||
state.currentValue = formatNumber(String(result));
|
|
||||||
state.operator = null;
|
|
||||||
state.previousValue = null;
|
|
||||||
state.shouldResetDisplay = true;
|
|
||||||
expressionEl.textContent = "";
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEquals() {
|
|
||||||
clearError();
|
|
||||||
if (state.operator) {
|
|
||||||
compute();
|
|
||||||
} else if (state.lastOperator !== null && state.lastOperand !== null) {
|
|
||||||
state.previousValue = parseFloat(state.currentValue);
|
|
||||||
state.operator = state.lastOperator;
|
|
||||||
compute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleClear() {
|
|
||||||
state.currentValue = "0";
|
|
||||||
state.previousValue = null;
|
|
||||||
state.operator = null;
|
|
||||||
state.lastOperand = null;
|
|
||||||
state.lastOperator = null;
|
|
||||||
state.shouldResetDisplay = false;
|
|
||||||
state.isError = false;
|
|
||||||
expressionEl.textContent = "";
|
|
||||||
resultEl.style.color = "";
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSign() {
|
|
||||||
if (state.isError) return;
|
|
||||||
if (state.shouldResetDisplay) return;
|
|
||||||
state.currentValue = String(-parseFloat(state.currentValue));
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlePercent() {
|
|
||||||
if (state.isError) return;
|
|
||||||
const num = parseFloat(state.currentValue);
|
|
||||||
if (state.operator && state.previousValue !== null) {
|
|
||||||
const adjusted = state.previousValue * (num / 100);
|
|
||||||
state.currentValue = formatNumber(String(adjusted));
|
|
||||||
} else {
|
|
||||||
state.currentValue = formatNumber(String(num / 100));
|
|
||||||
}
|
|
||||||
updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("buttons").addEventListener("click", (e) => {
|
|
||||||
const btn = e.target.closest("button");
|
|
||||||
if (!btn) return;
|
|
||||||
|
|
||||||
const action = btn.dataset.action;
|
|
||||||
switch (action) {
|
|
||||||
case "digit": appendDigit(btn.dataset.value); break;
|
|
||||||
case "decimal": handleDecimal(); break;
|
|
||||||
case "backspace": handleBackspace(); break;
|
|
||||||
case "operator": handleOperator(btn.dataset.value); break;
|
|
||||||
case "equals": handleEquals(); break;
|
|
||||||
case "clear": handleClear(); break;
|
|
||||||
case "sign": handleSign(); break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener("keydown", (e) => {
|
|
||||||
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
||||||
if (e.key >= "0" && e.key <= "9") {
|
|
||||||
appendDigit(e.key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (e.key) {
|
|
||||||
case ".": handleDecimal(); break;
|
|
||||||
case "Backspace": handleBackspace(); break;
|
|
||||||
case "Delete": handleClear(); break;
|
|
||||||
case "Escape": handleClear(); break;
|
|
||||||
case "Enter":
|
|
||||||
case "=": handleEquals(); break;
|
|
||||||
case "+": handleOperator("+"); break;
|
|
||||||
case "-": handleOperator("-"); break;
|
|
||||||
case "*": handleOperator("*"); break;
|
|
||||||
case "/": handleOperator("/"); break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
236
2227/style.css
236
2227/style.css
|
|
@ -1,236 +0,0 @@
|
||||||
*, *::before, *::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
background: #1a1a2e;
|
|
||||||
padding: 16px;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Calculator container ---- */
|
|
||||||
#app {
|
|
||||||
width: clamp(260px, 90vw, 360px);
|
|
||||||
background: #16213e;
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: clamp(14px, 4vw, 24px);
|
|
||||||
box-shadow:
|
|
||||||
0 8px 32px rgba(0, 0, 0, 0.35),
|
|
||||||
0 2px 8px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Display ---- */
|
|
||||||
#display {
|
|
||||||
background: #0f3460;
|
|
||||||
border-radius: 14px;
|
|
||||||
padding: clamp(12px, 3vw, 20px);
|
|
||||||
margin-bottom: clamp(12px, 3vw, 18px);
|
|
||||||
min-height: 90px;
|
|
||||||
text-align: right;
|
|
||||||
color: #e0e0e0;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#expression {
|
|
||||||
font-size: clamp(12px, 3.5vw, 15px);
|
|
||||||
color: #8fa8c8;
|
|
||||||
min-height: 22px;
|
|
||||||
word-break: break-all;
|
|
||||||
line-height: 1.4;
|
|
||||||
transition: color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#result {
|
|
||||||
font-size: clamp(26px, 8vw, 36px);
|
|
||||||
font-weight: 300;
|
|
||||||
min-height: 44px;
|
|
||||||
word-break: break-all;
|
|
||||||
line-height: 1.2;
|
|
||||||
letter-spacing: -0.02em;
|
|
||||||
transition: color 0.15s;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Button grid ---- */
|
|
||||||
#buttons {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: clamp(6px, 1.8vw, 10px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Base button ---- */
|
|
||||||
button {
|
|
||||||
font-size: clamp(17px, 5vw, 22px);
|
|
||||||
padding: clamp(12px, 3.5vw, 18px) 0;
|
|
||||||
border: none;
|
|
||||||
border-radius: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
background: #1a1a40;
|
|
||||||
color: #e0e0e0;
|
|
||||||
font-weight: 400;
|
|
||||||
transition:
|
|
||||||
background 0.15s ease,
|
|
||||||
transform 0.1s ease,
|
|
||||||
box-shadow 0.15s ease;
|
|
||||||
outline: none;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ripple-like highlight on tap */
|
|
||||||
button::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background: radial-gradient(circle at center, rgba(255,255,255,0.12) 0%, transparent 70%);
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:active::after {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hover */
|
|
||||||
button:hover {
|
|
||||||
background: #262655;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active press */
|
|
||||||
button:active {
|
|
||||||
transform: scale(0.94);
|
|
||||||
background: #2e2e65;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Keyboard focus ring */
|
|
||||||
button:focus-visible {
|
|
||||||
box-shadow: 0 0 0 3px rgba(83, 52, 131, 0.6);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Function keys (C, +/-, backspace) ---- */
|
|
||||||
[data-action="clear"],
|
|
||||||
[data-action="sign"],
|
|
||||||
[data-action="backspace"] {
|
|
||||||
background: #0f3460;
|
|
||||||
color: #8fbceb;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action="clear"]:hover,
|
|
||||||
[data-action="sign"]:hover,
|
|
||||||
[data-action="backspace"]:hover {
|
|
||||||
background: #154178;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action="clear"]:active,
|
|
||||||
[data-action="sign"]:active,
|
|
||||||
[data-action="backspace"]:active {
|
|
||||||
background: #1b4f8f;
|
|
||||||
transform: scale(0.94);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Operator keys ---- */
|
|
||||||
[data-action="operator"] {
|
|
||||||
background: #533483;
|
|
||||||
color: #d9c4f0;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action="operator"]:hover {
|
|
||||||
background: #6544a3;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action="operator"]:active {
|
|
||||||
background: #7654b3;
|
|
||||||
transform: scale(0.94);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Equals key ---- */
|
|
||||||
[data-action="equals"] {
|
|
||||||
background: linear-gradient(135deg, #e94560, #d63251);
|
|
||||||
color: #fff;
|
|
||||||
font-weight: 600;
|
|
||||||
box-shadow: 0 3px 12px rgba(233, 69, 96, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action="equals"]:hover {
|
|
||||||
background: linear-gradient(135deg, #f05575, #e04060);
|
|
||||||
box-shadow: 0 4px 16px rgba(233, 69, 96, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action="equals"]:active {
|
|
||||||
background: linear-gradient(135deg, #ff6585, #f05070);
|
|
||||||
transform: scale(0.94);
|
|
||||||
box-shadow: 0 2px 8px rgba(233, 69, 96, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Zero button span ---- */
|
|
||||||
#btn-zero {
|
|
||||||
grid-column: span 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Responsive: narrow screens ---- */
|
|
||||||
@media (max-width: 320px) {
|
|
||||||
#app {
|
|
||||||
border-radius: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#display {
|
|
||||||
border-radius: 10px;
|
|
||||||
min-height: 76px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Responsive: wider desktop ---- */
|
|
||||||
@media (min-width: 600px) {
|
|
||||||
#app {
|
|
||||||
width: 360px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
padding: 20px 0;
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#result {
|
|
||||||
font-size: 38px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#expression {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Reduced motion preference ---- */
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
button {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button::after {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#expression, #result {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue