OOP Basic Calculator

by manototh

HTML

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OOP Basic Calculator</title>
  <link rel="stylesheet" href="style.css" />
  <script src="main.js" defer="defer"></script>
</head>

<body>
  <div id="calculator1" class="calculator-wrapper">
    <div class="calculator-container">
      <div class="calculator-row">
        <div class="calculator-element-wrapper calculator-display">
          <div class="calculator-element-container">
            <div class="calculator-element-content"></div>
          </div>
        </div>
      </div>
      <div class="calculator-row">
        <div class="calculator-element-wrapper calculator-button">
          <div class="calculator-element-container">
            <div class="calculator-element-content">AC</div>
          </div>
        </div>
        <div class="calculator-element-wrapper calculator-button">
          <div class="calculator-element-container">
            <div class="calculator-element-content">C</div>
          </div>
        </div>
        <div class="calculator-element-wrapper calculator-button">
          <div class="calculator-element-container">
            <div class="calculator-element-content">()</div>
          </div>
        </div>
        <div class="calculator-element-wrapper calculator-button">
          <div class="calculator-element-container">
            <div class="calculator-element-content">/</div>
          </div>
        </div>
      </div>
      <div class="calculator-row">
        <div class="calculator-element-wrapper calculator-button">
          <div class="calculator-element-container">
            <div class="calculator-element-content">7</div>
          </div>
        </div>
        <div class="calculator-element-wrapper calculator-button">
          <div class="calculator-element-container">
            <div class="calculator-element-content">8</div>
          </div>
        </div>
 ...

CSS

@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,600;0,700;0,800;1,300;1,400;1,600;1,700;1,800&display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.calculator-wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  font-size: 16px;
  font-family: Open Sans;
}

.calculator-container {
  width: 691px;
  height: 568px;
  display: flex;
  flex-direction: column;
  border-radius: 1em;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  border: 1px solid #e0e0e0;
}

.calculator-row {
  width: 100%;
  height: calc(100% / 6);
  display: flex;
}

.calculator-element-wrapper {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
}

.calculator-element-wrapper.calculator-display {
  width: 100%;
}

.calculator-element-wrapper.calculator-button,
.calculator-element-wrapper.calculator-logo-button {
  width: calc(100% / 4);
  cursor: pointer;
}

.calculator-element-container {
  padding: 10px;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  border-radius: 10em;
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .2), 0 2px 10px 0 rgba(0, 0, 0, .1);
  color: #4f4f4f;
  border-color: #fbfbfb;
}

.calculator-button .calculator-element-container:hover,
.calculator-button .calculator-element-container:focus,
.calculator-logo-button .calculator-element-container:hover,
.calculator-logo-button .calculator-element-container:focus {
  background-color: #e8e8e8;
}

.calculator-button .calculator-element-container:active,
.calculator-logo-button .calculator-element-container:active {
  background-color: #c8c8c8;
}

.calculator-button .calculator-element-container:hover,
.calculator-button .calculator-element-container:focus,
.calculator-button .calculator-element-container:active,
.calculator-logo-button .calculator-element-container:hover,
.calculator-logo-button...

JavaScript

'use strict';

// Reactor pattern
class Event {
    constructor(name) {
        this.name = name;
        this.callbacks = [];
    }
}

Event.prototype.registerCallback = function (callback) {
    this.callbacks.push(callback);
}

class Reactor {
    constructor() {
        this.events = {};
    }
}

Reactor.prototype.registerEvent = function (eventName) {
    this.events[eventName] = new Event(eventName);
};

Reactor.prototype.dispatchEvent = function (eventName, eventArgs) {
    this.events[eventName].callbacks.forEach(function (callback) { callback(eventArgs); });
};

Reactor.prototype.addEventListener = function (eventName, callback) {
    this.events[eventName].registerCallback(callback);
};


// Core calculator functionality
class CalculatorCore {
    constructor() {
        this.input = "";
        this._reactor = new Reactor();
        this._reactor.registerEvent("calc");
    }
}

CalculatorCore.prototype.addEventListener = function (eventName, callback) {
    this._reactor.addEventListener(eventName, callback);
}

CalculatorCore.prototype.calculate = function () {
    let result = NaN;
    try {
        result = eval(this.input).toString();
    } catch (e) {
        if (e instanceof SyntaxError) {
            console.error(e);
        } else {
            throw e;
        }
    }

    this._reactor.dispatchEvent("calc", result);
}

CalculatorCore.prototype.setInput = function (input) {
    this.input = input;
}

CalculatorCore.prototype.getInput = function () {
    return this.input;
}

// Calculator UI options
class CalculatorUIOptions {
    constructor(calculatorSelector, calculatorBackgroundColor, buttonBackgroundColor, displayBackgroundColor, textColor) {
        this.calculatorSelector = calculatorSelector;
        this.calculatorBackgroundColor = typeof (calculatorBackgroundColor) === "string" ? calculatorBackgroundColor : "";
        this.buttonBackgroundColor = typeof (buttonBackgroundColor) === "string" ? buttonBackgroundColor : "";
       ...