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
28 changes: 28 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<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 id="app">
<div class="input-group">
<input type="text" id="num1" inputmode="decimal">
<select id="operator">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" id="num2" inputmode="decimal">
</div>
<div id="error-log" class="error-message"></div>
<button id="calculate-btn">подсчитать</button>
<div id="history"></div>
</div>
</body>
</html>
81 changes: 81 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const state = { history: [] };

function handleCalculation() {
const el1 = document.getElementById('num1');
const el2 = document.getElementById('num2');
const errorLog = document.getElementById('error-log');

el1.classList.remove('input-error');
el2.classList.remove('input-error');
errorLog.textContent = '';

const val1 = el1.value.replace(',', '.').trim();
const val2 = el2.value.replace(',', '.').trim();
const op = document.getElementById('operator').value;

let hasError = false;

if (!val1) { el1.classList.add('input-error'); hasError = true; }
if (!val2) { el2.classList.add('input-error'); hasError = true; }

if (hasError) {
errorLog.textContent = 'Заполните поля';
return;
}

const n1 = parseFloat(val1);
const n2 = parseFloat(val2);

if (isNaN(n1)) { el1.classList.add('input-error'); hasError = true; }
if (isNaN(n2)) { el2.classList.add('input-error'); hasError = true; }

if (op === '/' && n2 === 0) {
el2.classList.add('input-error');
errorLog.textContent = 'Деление на 0 невозможно';
return;
}

if (hasError) {
errorLog.textContent = 'Некорректные числа';
return;
}

let res;
switch (op) {
case '+': res = n1 + n2; break;
case '-': res = n1 - n2; break;
case '*': res = n1 * n2; break;
case '/': res = n1 / n2; break;
}

const formattedRes = Number.isInteger(res) ? res : parseFloat(res.toFixed(4));
state.history.push(`${val1} ${op} ${val2} = ${formattedRes}`);
renderHistory();
}

function renderHistory() {
const container = document.getElementById('history');
container.innerHTML = '';

state.history.forEach((item, index) => {
const div = document.createElement('div');
div.className = 'history-item';
const isLatest = (index === state.history.length - 1);
div.classList.add(isLatest ? 'latest' : 'old');
div.textContent = item;
container.appendChild(div);
});
container.scrollTop = container.scrollHeight;
}

document.addEventListener('DOMContentLoaded', () => {
const inputs = [document.getElementById('num1'), document.getElementById('num2')];
inputs.forEach(input => {
input.addEventListener('input', () => {
input.value = input.value.replace(/[^0-9.-]/g, '');
input.classList.remove('input-error');
});
});

document.getElementById('calculate-btn').addEventListener('click', handleCalculation);
});
116 changes: 116 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
:root {
--bg-color: #c1ffc1;
--border-color: #ff4500;
--text-color: #ff0000;
--old-text: #a57a7a;
}

* {
box-sizing: border-box;
}

body {
margin: 0;
height: 100vh;
width: 100vw;
font-family: sans-serif;
display: flex;
overflow-x: hidden;
}

#app {
position: absolute;
top: 2vh;
left: 2vw;
background-color: var(--bg-color);
padding: 20px;
border-radius: 15px;
width: clamp(300px, 40vw, 600px);
max-width: 96vw;
display: flex;
flex-direction: column;
gap: clamp(10px, 1.5vh, 20px);
align-items: center;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}

.input-group {
display: flex;
flex-direction: row;
gap: 8px;
width: 100%;
}

input, select, button {
background: transparent;
border: 1px dashed var(--border-color);
border-radius: 8px;
padding: 8px;
color: var(--text-color);
font-size: 18px;
outline: none;
transition: all 0.2s ease;
width: 100%;
}

input { flex: 2; }
select { flex: 1; width: auto; }

#history {
border: 1px dashed var(--border-color);
border-radius: 10px;
width: 100%;
height: 5.5em;
padding: 10px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--border-color) transparent;
}

#history::-webkit-scrollbar {
width: 4px;
}
#history::-webkit-scrollbar-thumb {
background-color: var(--border-color);
border-radius: 10px;
}

.history-item {
font-size: clamp(14px, 1.5vw, 20px);
font-weight: bold;
line-height: 1.2;
margin-bottom: 4px;
word-break: break-all;
}

.history-item.old { color: var(--old-text); }
.history-item.latest { color: var(--text-color); }

.input-error {
border: 2px solid #ff0000 !important;
background-color: rgba(255, 0, 0, 0.05) !important;
box-shadow: 0 0 5px rgba(255, 0, 0, 0.3);
}

@media (max-width: 500px) {
#app {
left: 2vw;
width: 96vw;
}

.input-group {
flex-direction: column;
align-items: center;
gap: 12px;
}

input, select {
flex: none;
width: 100%;
}

select {
width: 60%;
min-width: 150px;
}
}