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
36 changes: 36 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Калькулятор</title>
<link rel="stylesheet" href="resources/style.css">
</head>
<body>
<div class="calculator-container">
<div class="calculator">
<div class="input-row">
<input type="text" id="operand1" class="calc-input" placeholder="Первый операнд">

<select id="operator" class="calc-select">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>

<input type="text" id="operand2" class="calc-input" placeholder="Второй операнд">
</div>

<div class="button-row">
<button id="calculate-btn" class="calc-button">подсчитать</button>
</div>

<div id="result-field" class="result-field">
</div>
</div>
</div>

<script src="resources/script.js"></script>
</body>
</html>
171 changes: 171 additions & 0 deletions resources/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
document.addEventListener('DOMContentLoaded', function() {

const operand1Input = document.getElementById('operand1');
const operand2Input = document.getElementById('operand2');
const operatorSelect = document.getElementById('operator');
const calculateBtn = document.getElementById('calculate-btn');
const resultField = document.getElementById('result-field');

let history = [];

// Функция для замены запятой на точку
function normalizeNumber(value) {
return value.replace(',', '.');
}

function isValidNumber(value) {
if (value === '' || value === null || value === undefined) {
return false;
}
const normalizedValue = normalizeNumber(value);
return !isNaN(parseFloat(normalizedValue)) && isFinite(normalizedValue);
}

// Функция для удаления класса ошибки у полей
function removeErrors() {
operand1Input.classList.remove('error-input');
operand2Input.classList.remove('error-input');

// Удаляем существующие сообщения об ошибках
const existingErrors = document.querySelectorAll('.error-message');
existingErrors.forEach(error => error.remove());
}

function showError(message) {
const errorDiv = document.createElement('div');
errorDiv.className = 'error-message';
errorDiv.textContent = message;
resultField.parentNode.insertBefore(errorDiv, resultField.nextSibling);
}

function calculate() {
removeErrors();

const val1 = operand1Input.value.trim();
const val2 = operand2Input.value.trim();
const operator = operatorSelect.value;

let hasError = false;

if (!isValidNumber(val1)) {
operand1Input.classList.add('error-input');
hasError = true;
}

if (!isValidNumber(val2)) {
operand2Input.classList.add('error-input');
hasError = true;
}

if (hasError) {
showError('Пожалуйста, введите корректные числа (используйте цифры, точку или запятую)');
return;
}

const num1 = parseFloat(normalizeNumber(val1));
const num2 = parseFloat(normalizeNumber(val2));

if (operator === '/' && num2 === 0) {
operand2Input.classList.add('error-input');
showError('Деление на ноль невозможно');
return;
}

let result;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
default:
result = 'Ошибка';
}

// Форматируем результат (ограничиваем до 10 знаков после запятой)
if (typeof result === 'number') {
result = parseFloat(result.toFixed(10));
}

const exampleString = `${val1} ${operator} ${val2} = ${result}`;

history.push(exampleString);

// Оставляем только последние 2 примера
if (history.length > 2) {
history.shift();
}

displayResults();
}

function displayResults() {
resultField.innerHTML = '';

if (history.length === 0) {
return;
}

// Отображаем предыдущий результат (если есть)
if (history.length === 2) {
const prevDiv = document.createElement('div');
prevDiv.className = 'previous-result';
prevDiv.textContent = history[0];
resultField.appendChild(prevDiv);
}

// Отображаем текущий результат
const currentDiv = document.createElement('div');
currentDiv.className = 'current-result';
currentDiv.textContent = history[history.length - 1];
resultField.appendChild(currentDiv);
}

// Функция для валидации ввода в реальном времени
function validateInput(input) {
input.addEventListener('input', function() {
// Разрешаем цифры, точку, запятую и знак минус в начале
const value = this.value;
const lastChar = value[value.length - 1];

if (value.length > 0) {
// Проверяем, что последний символ допустим
if (!/^[\d\.,\-]$/.test(lastChar)) {
this.value = value.slice(0, -1);
}

// Проверяем, что минус может быть только в начале
if (lastChar === '-' && value.indexOf('-') !== value.lastIndexOf('-')) {
this.value = value.slice(0, -1);
}
}
});

// Убираем ошибку при начале ввода
input.addEventListener('focus', function() {
this.classList.remove('error-input');
const existingErrors = document.querySelectorAll('.error-message');
existingErrors.forEach(error => error.remove());
});
}

validateInput(operand1Input);
validateInput(operand2Input);

// Обработчик для кнопки подсчета
calculateBtn.addEventListener('click', calculate);

// Обработчик для клавиши Enter
document.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
calculate();
}
});
});
133 changes: 133 additions & 0 deletions resources/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font-family: Arial, sans-serif;
min-height: 100vh;
display: flex;
background-color: #f0f0f0;
}

.calculator-container {
width: 70%;
margin: 20px;
}

.calculator {
background-color: #BAFFC2;
padding: 20px;
border-radius: 10px;
width: 100%;
}

.calc-input,
.calc-select,
.calc-button,
.result-field {
background-color: #BAFFC2;
border: 1px dashed #ff0000;
border-radius: 10px;
color: #ff0100;
font-size: 16px;
}

.calc-input {
flex: 1;
min-width: 150px;
padding: 10px 15px;
}

.calc-input::placeholder {
color: rgba(255, 1, 0, 0.5);
}

.calc-select {
width: 80px;
padding: 8px 5px;
text-align: left;
}

.calc-select option {
background-color: #BAFFC2;
color: #FF0100;
}

.calc-button {
padding: 5px 20px;
font-size: 16px;
cursor: pointer;
width: auto;
display: inline-block;
transition: background-color 0.3s;
}

.calc-button:hover {
background-color: rgba(255, 1, 0, 0.1);
}

.result-field {
padding: 15px;
min-height: 80px;
font-size: 18px;
display: flex;
flex-direction: column;
gap: 5px;
}

.current-result {
color: #ff0100;
}

.previous-result {
color: rgba(255, 1, 0, 0.3);
}

.error-input {
border-style: solid;
background-color: rgba(255, 1, 0, 0.05);
}

.error-message {
color: #ff0100;
font-size: 14px;
margin-top: 5px;
font-style: italic;
}

.input-row {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 20px;
align-items: center;
}

.button-row {
display: flex;
justify-content: center;
margin-bottom: 20px;
}

@media (max-width: 768px) {
.calculator-container {
width: 90%;
}

.calc-input {
min-width: 100%;
}

.input-row {
flex-direction: column;
align-items: stretch;
}

.calc-select {
width: 80px;
max-width: 200px;
align-self: center;
}
}