Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
<title>Калькулятор</title>
</head>

<body>
<div class="box">
<div class="gridBox">
<div class="fieldWrap">
<input id="value1" type="text" class="input">
<div id="err1" class="err"></div>
</div>

<select id="operation" class="input">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>

<div class="fieldWrap">
<input id="value2" type="text" class="input">
<div id="err2" class="err"></div>
</div>
</div>

<div class="flexBox">
<button class="input btn" type="button" onclick="whenButtonClicked()">подсчитать</button>
</div>

<div id="results" class="input results">Результат</div>
</div>
</body>
</html>
104 changes: 104 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
const historyLines = [];
const HISTORY_LIMIT = 5;

function whenButtonClicked() {
clearErrors();

const a = getNumberOrShowError("value1", "err1");
const b = getNumberOrShowError("value2", "err2");
const op = document.getElementById("operation").value;

if (a === null || b === null) return;

if (op === "/" && b === 0) {
showError("value2", "err2", "Деление на 0!");
return;
}

const result = calculate(a, b, op);
const line = `${format(a)} ${op} ${format(b)} = ${format(result)}`;

addToHistory(line);
renderHistory();
}

function getNumberOrShowError(inputId, errorId) {
const text = document.getElementById(inputId).value.trim().replace(",", ".");
const num = Number(text);

if (text === "" || Number.isNaN(num)) {
showError(inputId, errorId, "Введите число");
return null;
}
return num;
}

function calculate(a, b, op) {
switch (op) {
case "+":
return a + b;

case "-":
return a - b;

case "*":
return a * b;

case "/":
return a / b;

default:
return NaN;
}
}

function format(n) {
return Number.isInteger(n) ? String(n) : String(Number(n.toFixed(4)));
}

function addToHistory(line) {
historyLines.push(line);
while (historyLines.length > HISTORY_LIMIT) historyLines.shift();
}

function renderHistory() {
const results = document.getElementById("results");

if (historyLines.length === 0) {
results.textContent = "Результат";
return;
}

results.innerHTML = "";

historyLines.forEach((line, i) => {
const row = document.createElement("div");
row.textContent = line;

const age = historyLines.length - 1 - i;
row.style.opacity = age === 0 ? "1" : String(Math.max(0.25, 0.85 - age * 0.15));

results.appendChild(row);
});
}

function showError(inputId, errorId, message) {
const input = document.getElementById(inputId);
const error = document.getElementById(errorId);

if (input) input.classList.add("input-error");
if (error) error.textContent = message;
}

function clearErrors() {
removeError("value1", "err1");
removeError("value2", "err2");
}

function removeError(inputId, errorId) {
const input = document.getElementById(inputId);
const error = document.getElementById(errorId);

if (input) input.classList.remove("input-error");
if (error) error.textContent = "";
}
66 changes: 66 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
* { box-sizing: border-box; }
body { margin: 0; font-family: Arial, sans-serif; }

.box{
background: #bfffbf;
border-radius: 10px;
padding: 18px;
max-width: 720px;
margin: 40px auto;
}

.input{
border: 1px dashed red;
border-radius: 10px;
padding: 10px 14px;
margin: 10px;
width: 100%;
background: transparent;
color: red;
font-size: 18px;
}

.gridBox{
display: grid;
grid-template-columns: 1fr 90px 1fr;
gap: 10px;
align-items: start;
}

.flexBox{
display: flex;
justify-content: center;
}

.btn{
width: 220px;
cursor: pointer;
}

.results{
min-height: 95px;
padding-top: 14px;
padding-bottom: 14px;
}

.fieldWrap{
display: flex;
flex-direction: column;
}

.err{
margin: -6px 10px 0 10px;
color: red;
font-size: 14px;
min-height: 18px;
}

.input-error{
box-shadow: 0 0 0 2px rgba(255,0,0,.35);
}

@media (max-width: 520px){
.box{ max-width: 280px; }
.gridBox{ grid-template-columns: 1fr; }
#operation{ width: 90px; justify-self: center; }
}