Building a Calculator - Frontend Masters Series

Edit

This post is the first in a new series inspired by Frontend Masters. Frontend Masters is a site that provides awesome online courses for learning frontend web development. Whenever I complete a course, I will make a CodePen to apply what I've learned and a blog post to go over the details.

Course 1 - Intro To Web Development

The first course up is Intro To Web Development, where I got a refresher on basic HTML, CSS, and JavaScript. The instructor was Brian Holt (Microsoft).

The Calculator

Brian challenged students to create a simple calculator using plain HTML, CSS, and vanilla JavaScript. Here's my CodePen solution.

JavaScript

Using vanilla JavaScript to create the calculator's brain posed a few challenges. Somehow, calculators have to 'remember' previous key presses to determine what the current key press should accomplish. For example, if a user presses the number 7, then 'x', and finally 9, the calculator should return 63. However, if a user presses 7, then 7 again, they are trying to build the number 77.

There are probably purely functional ways of accomplishing this, but for simplicity's sake I created the following object and various helper functions:

const calculator = {
  firstOperand: "0",
  secondOperand: "0",
  currentOperation: null,
}

This object simply stores the firstOperand, secondOperand, and currentOperation. The rest of the app is a set of functions to build numbers, edit numbers (backspace), update the stdout, perform calculations, and reset everything.

For me, the trickiest part was determining how and when to update state in the calculator object. These are the core methods I came up with to update state:

function updateCalculatorValue(num) {
  !calculator.currentOperation ? buildOperand(num) : buildOperand(num, false)
}

function buildOperand(num, first = true) {
  if (first) {
    if (num !== "0" && calculator.firstOperand !== "0") {
      calculator.firstOperand = calculator.firstOperand.concat(num)
    } else {
      calculator.firstOperand = num
    }
    setStdout(calculator.firstOperand)
  } else {
    if (num !== "0" && calculator.secondOperand !== "0") {
      calculator.secondOperand = calculator.secondOperand.concat(num)
    } else {
      calculator.secondOperand = num
    }
    setStdout(calculator.secondOperand)
  }
}

The updateCalculatorValue and buildOperand functions work together to appropriately update the calculator object.

HTML & CSS

I challenged myself to build the calculator using just Flexbox (no Grid, SCSS, etc.). Here are some of the challenges and how I addressed them in my solution:

Centering The Calculator: I created a wrapper div with the class container. I used the tried and true display: flex, align-items: center and justify-content: center to center the calculator div vertically and horizontally on the page.

Stdout: Calculator standard outs read right to left, so I applied row-reverse to the stdout div.

Responsive Buttons: The calculator's buttons maintain their position and relative sizing across viewport sizes (laptop, mobile, etc.). I achieved this by created a flex buttons-container with flex-direction: column. Then, I nest several buttons-rows inside the container with flex: 1, which results in the flex item receiving the specified proportion of the remaining space. This results in 1 column of button rows, where most of the buttons inside each row grow responsively at the same rate.

Differently-Sized Buttons: You'll notice that the Clear button and 0 number are different sizes than the other buttons. This was accomplished by creating double and triple classes with flex set to 2, and 3 respectively.

Some Buttons Are Orange Finally, specific buttons had to be colored orange. I applied orange colors using the :last-child pseudo-element to catch the last button in each button-row.