Пишем современный калькулятор на JavaScript

от автора

Доброго времени суток, друзья!

В этой статье мы с вами, как следует из названия, напишем простой калькулятор на современном JavaScript.

Желание написать калькулятор возникло у меня после просмотра одного туториала, посвященного созданию «simple calculator», который оказался далеко не симпл и толком ничего не умел делать.

Наш калькулятор будет true simple (42 строки кода, включая пробелы между блоками), но при этом полнофункциональным и масштабируемым.

Для расчетов будет использоваться эта замечательная библиотека (Math.js).

Без дальнейших предисловий, приступаем к делу.

Наша разметка выглядит так:

<!-- head --> <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/6.6.4/math.js"></script>  <!-- body --> <div class="calculator">     <output></output> </div> 

Здесь мы подключаем библиотеку, создаем контейнер для калькулятора и поле для вводимых символов и результата.

Подключаем стили:

* {   margin: 0;   padding: 0;   box-sizing: border-box; }  body {   height: 100vh;   background: radial-gradient(circle, skyblue, steelblue);   display: flex;   justify-content: center;   align-items: center; }  .calculator {   width: 320px;   height: 480px;   background: #eee;   border-radius: 5px;   box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.2), -2px -2px 3px rgba(0, 0, 0, 0.2); }  output {   display: flex;   justify-content: center;   align-items: center;   width: 300px;   height: 40px;   background: #fff;   margin: 10px auto;   border-radius: 5px;   font-size: 1.4em;   font-weight: bold;   box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.3),     inset -1px -1px 1px rgba(0, 0, 0, 0.3); }  .keyboard {   height: 440px;   display: flex;   flex-wrap: wrap;   justify-content: space-evenly;   align-items: flex-start; }  button {   margin: 0.5em 1em;   width: 40px;   height: 40px;   display: flex;   justify-content: center;   align-items: center;   background: none;   border: none;   cursor: pointer;   font-size: 1em;   font-weight: bold; } 

Вот что мы имеем на данный момент:

Кнопки будут генерироваться программно.

Переходим к скрипту.

Определяем поле для вывода результата и создаем контейнер для клавиатуры:

const output = document.querySelector('output')  const div = document.createElement('div') div.classList.add('keyboard') document.querySelector('.calculator').appendChild(div) 

Наша строка с символами выглядит так:

'C CE % / 7 8 9 * 4 5 6 - 1 2 3 + 0 ( ) =' 

Преобразуем данную строку в массив и создаем кнопки:

// разделителем служит пустая строка // можно было бы обойтись без пробелов, если бы у нас не было "CE" 'C CE % / 7 8 9 * 4 5 6 - 1 2 3 + 0 ( ) ='.split(' ')     // пробегаемся по массиву     // для каждого символа     // создаем кнопку с помощью строкового литерала     // записываем значение символа в атрибут "value" кнопки     .map(symbol => {         div.insertAdjacentHTML('beforeend', `<button value="${symbol}">${symbol}</button>`)     }) 

Находим созданные кнопки и добавляем к ним обработчик события «клик»:

document.querySelectorAll('button').forEach(button => {     button.addEventListener('click', function () {         // по клику вызывается функция со значением кнопки в качестве параметра         calc(this.value)     }) }) 

Мы также хотим иметь возможность вводить символы с помощью клавиатуры. Для этого нам необходимо добавить обработчик события «нажатие клавиши» к объекту «Document» или «Window», затем отфильтровать ненужные значения свойства «ключ» клавиши, например, с помощью регулярного выражения:

document.addEventListener('keydown', event => {     if ((event.key).match(/[0-9%\/*\-+\(\)=]|Backspace|Enter/)) calc(event.key) }) 

Метод «match» в данном случае играет роль фильтра: он не позволяет передавать функции «calc» аргумент, не соответствующий заданному в нем условию.

Само условие звучит так: если значением event.key является один из символов, указанных в квадратных скобках ([]; цифра от 0 до 9, знаки деления, умножения, сложения, вычитания, открывающая, закрывающая круглые скобки или знак равенства; обратная косая черта — экранирование) или (| — альтерация) Backspace, или Enter, то вызываем calc с event.key в качестве параметра, иначе ничего не делаем (Shift также успешно отбрасывается).

Наша главная (и единственная) функция «calc» выглядит следующим образом (код следует читать снизу вверх):

// функция принимает значение кнопки или ключ клавиши function calc(value) {     // если нажат знак равенства или Enter     if (value.match(/=|Enter/)) {         // пробуем выполнить операцию         try {             // вычисляем значение строки             // это возможно благодаря методу "evaluate" объекта "math"             // Math.trunc используется для округления до целого числа             output.textContent = Math.trunc(math.evaluate(output.textContent))                      // если операцию выполнить невозможно         } catch {             // сохраняем значение поля             let oldValue = output.textContent             // создаем новую переменную             let newValue = 'недопустимое выражение'             // выводим значение новой переменной в поле             output.textContent = newValue             // через полторы секунды возвращаем полю старое значение             setTimeout(() => {                 output.textContent = oldValue             }, 1500)         }              // если нажат символ "C"     } else if (value === 'C') {         // очищаем поле         output.textContent = ''          // если нажат символ "СЕ" или Backspace     } else if (value.match(/CE|Backspace/)) {         // уменьшаем строку на один символ         output.textContent = output.textContent.substring(0, output.textContent.length - 1)              // если нажата любая другая (отфильтрованная) кнопка или клавиша     } else {         // записываем ее значение в поле         output.textContent += value     } } 

В завершение, парочка слов о заявленной масштабируемости и полнофункциональности.

Метод «evaluate» (ранее «eval») и другие методы Math.js имеют очень большие возможности. Опираясь на эти возможности, мы можем легко расширить функционал нашего калькулятора, добавив в него новые символы и операторы, предусмотрев возможность работы с числами с плавающей точкой (регулируя количество знаков после запятой с помощью переключателя и метода «toFixed») и т.д.

Результат:

Код на GitHub.

Благодарю за внимание. Надеюсь, вы нашли для себя что-то полезное. Хороших выходных и счастливого кодинга.

ссылка на оригинал статьи https://habr.com/ru/post/500086/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *