More articles

How to build a calculator in JavaScript

Written by
Published on

You may think you know what a calculator is. But it's not until you begin to code something that you get to see just how complex it can be. So let's get started.

0
0

Defining a calculator?

Let's start here. Because we can't build something if we don't know what it is. A calculator is a digital (or non-digital) tool or device that can perform mathematical calculations, such as addition, subtraction, multiplication, etc. The calculator accepts strings of numbers one at a time, with each moving its current decimal place position by one level. These numbers are then delimited by any mathematical operation, such as +,-, x, / and the calculator awaits for a new series of numbers. A few key features that we need to take into account:

- A calculator requires the numbers 0 - 9
- It requires standard operators (+, -, /, *)
- Needs to allow for multiple numbers to be chained together
- It requires ability to clear the buffer once we are done

Start here

Let's start by building the shape and design of the calculator itself. Essentially, a vertical rectangle with the number 0-9 spaced out evenly, with the 0 appearing somewhere at the bottom where it makes sense to fit it.

This won't be a graphical calculator as you can tell. It is a standard calculator with basic mathematical operations. And currently, it doesn't do anything.

<div class="calculator">
	<div class="screen buffer" id="screen">0</div>
<div class="screen total" id="screentotal">0</div> <div class="operators" id="operators"></div> <div class="numberpad" id="numpad"></div> </div>

Variables

Let's define a few variables before we do anything else.

var operators = ['+', '-', 'x', '/', '=', 'cl'];
var buffer = '';
var currentResult = 0;
var currentOperation = '';

operators - This array will help to build up our row of operator buttons
buffer - Keeps the current number in memory
currentResult - Updated after each operation
values - This array will hold each number in our operation

Creating the keys

The following function will create the calculator number and operator keys.

function createKeys()
{
	for(let i = 0; i < 10; i++)
	{
		let key = document.createElement('div');
		key.innerHTML = i;
		key.dataset.value = i;
		key.className = 'key';

		document.getElementById('numpad').appendChild(key);
	}

	operators.forEach(function(item){
		let key = document.createElement('div');
		key.innerHTML = item;
		key.dataset.operation = item;
		key.className = 'key';

		document.getElementById('operators').appendChild(key);
	});
}

And that will be called when the page loads.

window.addEventListener('load', createKeys);

Building the buffer

The buffer is essentially the current number that is being built up as a user clicks on the keys. And we can keep track of that in the global variable defined above.

Notice that I'm using a string to store the number. Instead of having to worry about number conversions and decimal places, I'm going to be storing the entire sequence as one string and then converting it to an integer at the very end when I am ready to perform an operation.

Click event handling

Below is the updated createKeys() function with the appropriate event handler logic added.


    function createKeys()
{
	for(let i = 0; i < 10; i++)
	{
		let key = document.createElement('div');
		key.innerHTML = i;
		key.dataset.value = i;
		key.addEventListener('click', function(e){
			// handle number click
			buffer += this.dataset.value;
		});

		document.getElementById('numpad').appendChild(key);
	}
	

The operator button clicks are more involved. The first thing that we need to do is to check that we are indeed performing one of the mathematical operations and not clearing the screen. If we are clearing the screen, we will need to reset the buffer, set the current total back to 0 and to reset all screen elements and set them back to 0.

If we are not clearing the screen, then the first thing that we need to do is to calculate the result of any numbers currently in the buffer. And the calculate function will take care of that logic for us. That function is defined down below. After our calculation, we need to clear the current buffer to make room for the new number and we set the currentOperation variable to its new value.

operators.forEach(function(item){
	let key = document.createElement('div');
        key.className = 'key';
	key.innerHTML = item;
        key.dataset.operation = item;
key.addEventListener('click', function(e){ if (this.dataset.operation == 'cl') { buffer = ''; currentResult = 0; currentOperation = ''; document.getElementById('screen').innerHTML = '0'; document.getElementById('screentotal').innerHTML = '0'; } else { calculate(); currentOperation = this.dataset.operation; buffer = ''; document.getElementById('screen').innerHTML= '0'; } });

document.getElementById('operators').appendChild(key); });

The calculate function can be defined as follows, with further explanation down below.

function calculate()
{
    switch(currentOperation) {
        case "+":
            currentResult += parseInt(buffer);
            break;

        case "-":
            currentResult -= parseInt(buffer);
            break;

        case "/":
            currentResult /= parseInt(buffer);
            break;

        case "x":
            currentResult *= parseInt(buffer);
            break;

        case "=":
            break;
        default:
            currentResult = parseInt(buffer);
        }

        document.getElementById('screentotal').innerHTML = currentResult;
}

Based on the current operation that we have selected, we are going to perform the appropriate mathematical calculation. Note the default operation essentially only happens the very first time that we select any operator. Since we only have 1 value in the buffer at this point, our currentResult is essentially the number currently in the buffer.

Once we are done calculating, we update the screentotal element and we are done.

Conclusion

This is a relatively simple calculator implementation, but covers some interesting topics in data buffering, state management, and really in just how everything, no matter how simple it seems, always has its own set of complexities.

Here is the full CSS for your copy/paste pleasure.

    
    *
{
	box-sizing: border-box;
}

.calculator { width: 500px; margin: 20px auto; padding: 10px; border-radius: 10px; background: black; color: white; box-shadow: 2px 2px 9px #aaa; position:relative; } .calculator .key { padding: 10px; font-weight: bold; text-align: center; } .calculator .numpad { padding: 10px; } .calculator .numpad > div { text-align:center; cursor:pointer; display:inline-block; width:33%; padding: 10px; } .calculator .numpad div:last-child { width:100%; } .calculator .numpad > div:hover { background:#333; color:white; } .calculator .operators { display:flex; } .calculator .operators > div{ display:inline-block; font-weight: bold; padding:10px; cursor:pointer; flex: 1 1 0; background:dodgerblue; color:white; } .screen { padding:10px; background:black; color:white; text-align:right; font-size: 18px; font-weight:bold; } .screen.buffer { position:absolute; top:0px; right:10px; font-size:11px; } .screen.total { font-size: 22px; padding:20px; }
Land your next big coding job. Search through 1000's of job listings.
X

Discussion / Comments / Questions

No messages posted yet

Add a comment

Send me your weekly newsletter filled with awesome ideas
Post comment