Basic JavaScript Calculator

Basic JavaScript Calculator

Hi Everyone, hope you all are doing well.

In this article, we are going to make a simple basic calculator using JavaScript. Our calculator will perform the basic mathematical operations: addition, subtraction, multiplication and division. To better understand this tutorial, it would be good if you have some knowledge of basic HTML, CSS and JavaScript. But anyways I will try to simplify all the stuff as best as I can.

Designing our Calculator.

‌ Let's start with making a structure for our calculator for that we will need our friend HTML.

The way I am going to design my calculator is just how i did it, if you want you can make it your way. Note:- I am not going to explain how HTML and CSS works in detail, if you want to learn about HTML and CSS first, you can go check these tutorials for HTML and CSS

‌ What I like to do is create a div container and write all the content inside of it. So, inside the body tag let's create our first div with a class "calculator".

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="style.css" />
        <title>Calculator</title>
    </head>
    <body>
        <div class="calculator">

        </div>
    </body>
</html>

Now that we have created our parent div, it's time to work on the calculator itself. I've divided the calculator into 2 parts one is output and the second the number pad which contains all the numbers and operators.

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="style.css" />
        <title>Calculator</title>
    </head>
    <body>
        <div class="calculator">
            <div class="output">

            </div>
            <div class="numpad">

            </div>
        </div>
    </body>
</html>

Now we have created the structure for our calculator it's time to add all the buttons and text field to display output. For the output I have again gone with div, I've created two div elements one with id "tempOut" which will store and display the temporary output at every step, and the second div with id "numbers" will store and display the current number entered by the user.

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="style.css" />
        <title>Calculator</title>
    </head>
    <body>
        <div class="calculator">
            <div class="output">
                <div id="tempOut">0</div>
                <div id="numbers">0</div>
            </div>
            <div class="numpad">

            </div>
        </div>
    </body>
</html>

Okay, the last section for the HTML part is creating our buttons what we will do here is divide the numpad section into 5 rows with 4 buttons in each row.

There are 4 buttons in each row except the first one, in the first row the clear button is expanded to take 2 columns so there are 3 buttons in the first row and 4 in the others.

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="style.css" />
        <title>Calculator</title>
    </head>
    <body>
        <div class="calculator">
            <div class="output">
                <div id="tempOut">0</div>
                <div id="numbers">0</div>
            </div>
            <div class="numpad">
                <div class="row row-1">
                    <button class="col col-1" id="clear">CLEAR</button>
                    <button class="col col-3" id="del">DEL</button>
                    <button class="col col-4 op">+</button>
                </div>
                <div class="row row-2">
                    <button class="col col-1 num">1</button>
                    <button class="col col-2 num">2</button>
                    <button class="col col-3 num">3</button>
                    <button class="col col-4 op">-</button>
                </div>
                <div class="row row-3">
                    <button class="col col-1 num">4</button>
                    <button class="col col-2 num">5</button>
                    <button class="col col-3 num">6</button>
                    <button class="col col-4 op">×</button>
                </div>
                <div class="row row-4">
                    <button class="col col-1 num">7</button>
                    <button class="col col-2 num">8</button>
                    <button class="col col-3 num">9</button>
                    <button class="col col-4 op">÷</button>
                </div>
                <div class="row row-5">
                    <button class="col col-1 num">0</button>
                    <button class="col col-2 num">.</button>
                    <button class="col col-3 num">00</button>
                    <button class="col col-4" id="eq">&equals;</button>
                </div>
            </div>
            </div>
        </div>
    </body>
</html>

So, we are finally done with HTML but if you see the output of just the above HTML you won't be impressed. This is what you'll see by just using the above HTML code.

This is what you'll see by just using the above HTML code.

Screenshot (457).png ‌ Although we can work with this only without any problem but let's make it a little nicer by adding some styling to it.

Now I am just going to provide you with the CSS I used, and if you want you can change it.

body {
    background-color: rgb(0, 218, 145);
}

.calculator {
    background: gainsboro;
    display: grid;
    border: 10px solid black;
    border-radius: 10px;
    height: 550px;
    width: fit-content;
    margin: auto;
    padding: 10px;
    align-self: center;
}

.output {
    background: rgb(255, 255, 255);
    border-radius: 10px;
    height: 5.5rem;
    font-size: 3rem;
    text-align: end;
    margin-bottom: 1rem;
    padding: 1rem;
}

#tempOut {
    font-style: oblique;
    color: gray;
    font-size: 50%;
    margin-bottom: 1rem;
}

.numpad {
    display: grid;
}

.row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
}

.col {
    font-size: 1.5rem;
    font-weight: 900;
    border: solid black;
    border-radius: 10px;
    margin: 1px;
    text-align: center;
    padding: 1rem 2rem;
}

.row-1 > .col-1 {
    grid-column: 1 / span 2;
}

.col:hover {
    background-color: rgba(12, 12, 12, 0.3);
    cursor: pointer;
}

‌ If you decided to use the above CSS, you must see something like this in your browser:

Screenshot (456).png ‌ So, we are finally done with designing the calculator and it's time to use the lovely JavaScript and make this calculator functional.

So let's start by creating some variables and selecting some DOM elements.

let currNumber = "";
let currAns = 0;
let currOp = "";
let countOperator = 0;
const inputNumber = document.getElementById("numbers");
const tempOutput = document.getElementById("tempOut");
const numpad = document.querySelectorAll(".num");
const allOperators = document.querySelectorAll(".op");
const equal = document.getElementById("eq");

Now let's understand the above code line by line

So, currNumber will be used to store the number entered by the user which we will use later in the calculations, then we have currAns, which will as the name suggests store the current answer as in the answer calculated at every step (if there are multiple operations). currOp will be used to store the operator entered by the user and countOperator will be used to let the program know that we have to start calculating as soon as user presses the second operator (or equals button, in that there is no use of countOperator variable)

In the next 5 lines we select the HTML elements from our HTML file. And to select the HTML elements I have used two functions document.getElementById() and document.querySelectorAll() before going ahead with understanding the variables lets just take a moment and understand what are these functions and what are they used for.

getElementById: document.getElementById() method returns the element that has the ID attribute with the specified value. An ID should be unique within a page. However, if more than one element with the specified ID exists, the getElementById() method returns the first element in the source code.

querySelectorAll: document.querySelectorAll() method returns all elements in the document that matches a specified CSS selector(s), as a static NodeList object. The NodeList object represents a collection of nodes. The nodes can be accessed by index numbers (The index starts at 0) which means we can use forEach loop to access the elements in the NodeList object.

‌ inputNumber selects and stores the element from HTML document which have an id of "numbers" we will use it to display the numbers entered by user. Similarly tempOutput selects and stores the element which has an id of "tempOut", we will use this to display the temporary output with the operator as we go on with multiple operations. Then we store all the numbers in our numpad (with class name "num") as a NodeList into numpad. Similarly, we store all the operators (class name ".op") in allOperators. Then at the end equal selects the element with id "eq" that is the equals button.

Now that we are done with all the variables let's create some event listeners.

I will be showing you the specific event listeners with the function that they call, but when you write it all the functions should be declared before all the events are defined. I'll share the complete sorted code at the end of this tutorial.

1. Getting numbers from numpad

numpad.forEach((num) => {
    num.addEventListener("click", getNumberFromNumpad);
});

‌ we have used forEach loop on the NodeList stored in numpad to and added an event listener which will run a function named 'getNumberFromNumpad' every time a number is clicked. Now let's write that function

addEventListener: ‌ ‌The addEventListener() method attaches an event handler to the specified element. ‌ ‌When using the addEventListener() method, the JavaScript is separated from the HTML markup, for better readability and allows us to add event listeners even when we do not control the HTML markup. ‌

const getNumberFromNumpad = (e) => {
    if (tempOutput.textContent.includes("=")) {
        tempOutput.textContent = "";
        inputNumber.textContent = e.target.textContent;
        countOperator = 0;
        currAns = 0;
    } else {
        inputNumber.textContent === "0" || inputNumber.textContent === ""
            ? (inputNumber.textContent = e.target.textContent)
            : (inputNumber.textContent += e.target.textContent);
    }
};

Now, this function receives an event as an argument (whenever a function is called by an event listener it by default receives an event as an argument) that's why we have a parameter named e to store that event and use it inside our function. Then we check that if the user has already pressed the "=" button and is starting a new calculation in that case we make everything go back to the default state, and if the "=" button is not yet pressed then we use something called a ternary or conditional operator in JavaScript to check if the user is entering the first digit of a number or is entering nth digit of a number and accordingly change the display number. For e.g, by default there is a 0 displayed as a number in our calculator, now as soon as the user types any number, say 5, 5 will replace the 0 and after that, if the user tries to add more digits to the same number say 6 then 6 will just be added next to it and displayed as 56

Read more about ternary operator here.

2. Getting the operator

allOperators.forEach((op) => {
    op.addEventListener("click", currentOperator);
});

As we applied the event listener to all the numbers, we do the same for all the operators and then call the function named currentOperator to store the current operator, calculate and display the temporary result. Now let's see the implementation of the function.

const currentOperator = (e) => {
    countOperator += 1;
    currNumber = Number(inputNumber.textContent);
    currOp = e.target.textContent;
    if (countOperator <= 1) tempOutput.textContent = `${currNumber} ${currOp}`;
    else {
        calcAnswer();
        tempOutput.textContent = `${currAns} ${currOp}`;
    }
    inputNumber.textContent = "";
};

‌ Now, remember we created a variable called countOperator this is where it will come handy, we will increment the countOperator by 1 every time any operator is clicked, we will store the operator and the number entered by the user into currOp and currNumber respectively so that we can display the temporary result in our tempOutput section. Then we check if countOperator is greater than 1 or not, if it is not greater than 1 then we simply update the tempOutput's text to display the number stored in currNumber with the operator stored in currOp, but if the countOperator is greater than 1 then we call a function named "calcAnswer" (we will create it in some time) and update the tempOutput's text content to display the current answer with the current operator. and then at the end, we update inputNumber to be empty so that the user can write the next number to complete the calculation.

To update the text in tempOutput we have used a property called textContent which is available to every HTML element. If you want you can read about it in detail here. Also, to update the text we have used something called string literals which are written inside `` and lets us use variables inside and display their values as and in a string. All we need to do in order to write variables inside a string literal is $ and then write the variable name inside {} for example ${myVariable}

3. Calculating and displaying the final result

equal.addEventListener("click", function () {
    currNumber = Number(inputNumber.textContent);
    calcAnswer();
    tempOutput.textContent += " " + currNumber + " =";
    inputNumber.textContent = currAns;
});

As equal was not a NodeList and simply a single button element we have directly added an event listener to it. and also as there were just 4 lines of code, instead of writing a function expression I wrote a function inside of the addEventListener() method. It's also good as now you know that we can also define a function inside of the addEventListener() method. So, on the equal button click, we store the number entered in the currNumber and then we call the calcAnswer() to calculate our final result after which we simply update our tempOutput section to display the previous text in the tempOutput section along with the current number and the "=" sign and then finally display the final result in the inputNumber.

Writing the logic for calculation.

Now let's write the calcAnswer function that we are going to use for all of our calculation.

const calcAnswer = function () {
    switch (tempOutput.textContent.slice(-1)) {
        case "+":
            if (currAns == 0) {
                currAns =
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    ) + currNumber;
            } else {
                currAns += currNumber;
            }
            break;
        case "-":
            if (currAns == 0) {
                currAns =
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    ) - currNumber;
            } else {
                currAns -= currNumber;
            }
            break;
        case "×":
            if (currAns == 0) {
                currAns =
                    currNumber *
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    );
            } else {
                currAns *= currNumber;
            }
            break;
        case "÷":
            if (currAns == 0) {
                currAns =
                    currNumber /
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    );
            } else {
                currAns /= currNumber;
            }
            break;

        default:
            break;
    }
};

We are going to use the switch statement to perform the calculations according to the operator entered. The switch statement lets us pass a variable and then create different cases for it and only run the case which matches the value stored in the variable.

Now, what I will do here is I'll only explain one case because the rest are exactly the same the only difference would be the operation.

So, we are tempOutput.textContent.slice(-1) to the switch statement which basically gets the last digit that is the operator that we have displayed in our tempOutput section and then let's see the first case inside of our switch statement.

the first case inside of the switch statement is "+", that is if the user has pressed the "+" button then this case will be executed. Now inside this, we first check that if we have previously calculated any result by checking that if currAns is 0 or not, if the currAns is 0, then we simply take the number from the tempOutput section and add it to the currNumber that is the current number entered by the user, but if the currAns is not 0, in that case, we simply add the currNumber to currAns.

‌ To get the number and operator from tempOutput section we have used something called slice() method, Now let us take a quick look at the slice() method

Syntax: string.slice(start, end) The slice() method extracts parts of a string and returns the extracted parts in a new string. The start and end parameters are used to specify the part of the string we want to extract. Parameter Values for slice()

start: The start parameter is required. It is the position where to begin the extraction (First character is at position 0).

end: The end parameter is optional. It is the position (up to, but not including) where to end the extraction. If omitted, slice() selects all characters from the start-position to the end of the string ‌

Clear and Del events

Now Clear button is given to clear the entire screen while the del button is given to work as backspace and delete a single digit at a time.

Let's make these button functional and complete our calculator.

document.getElementById("clear").addEventListener("click", function () {
    inputNumber.textContent = "0";
    tempOutput.textContent = "0";
    currAns = 0;
    countOperator = 0;
});

document.getElementById("del").addEventListener("click", function () {
    inputNumber.textContent = inputNumber.textContent.slice(0, -1);
    if (inputNumber.textContent === "") {
        inputNumber.textContent = "0";
    }
});

Well, there is not much that we have done here, for the clear button we have simply made everything back to the default values. And for the del button we used the slice() method to delete the last digit every time the del button is pressed and if the user deletes the entire number then we simple write 0 in place of that

Complete JavaScript Code

"use strict";

// VARIABLES
let currNumber = "";
let currAns = 0;
let currOp = "";
let countOperator = 0;
const inputNumber = document.getElementById("numbers");
const tempOutput = document.getElementById("tempOut");
const numpad = document.querySelectorAll(".num");
const allOperators = document.querySelectorAll(".op");
const equal = document.getElementById("eq");

// FUNCTIONS
const getNumberFromNumpad = (e) => {
    if (tempOutput.textContent.includes("=")) {
        tempOutput.textContent = "";
        inputNumber.textContent = e.target.textContent;
        countOperator = 0;
        currAns = 0;
    } else {
        inputNumber.textContent === "0" || inputNumber.textContent === ""
            ? (inputNumber.textContent = e.target.textContent)
            : (inputNumber.textContent += e.target.textContent);
    }
};

const calcAnswer = function () {
    switch (tempOutput.textContent.slice(-1)) {
        case "+":
            if (currAns == 0) {
                currAns =
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    ) + currNumber;
            } else {
                currAns += currNumber;
            }
            break;
        case "-":
            if (currAns == 0) {
                currAns =
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    ) - currNumber;
            } else {
                currAns -= currNumber;
            }
            break;
        case "×":
            if (currAns == 0) {
                currAns =
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    ) * currNumber;
            } else {
                currAns *= currNumber;
            }
            break;
        case "÷":
            if (currAns == 0) {
                currAns =
                    Number(
                        tempOutput.textContent.slice(
                            0,
                            tempOutput.textContent.indexOf(" ")
                        )
                    ) / currNumber;
            } else {
                currAns /= currNumber;
            }
            break;

        default:
            break;
    }
};

const currentOperator = (e) => {
    countOperator += 1;
    currNumber = Number(inputNumber.textContent);
    currOp = e.target.textContent;
    if (countOperator <= 1) tempOutput.textContent = `${currNumber} ${currOp}`;
    else {
        calcAnswer();
        tempOutput.textContent = `${currAns} ${currOp}`;
    }
    inputNumber.textContent = "";
};

// EVENTS
numpad.forEach((num) => {
    num.addEventListener("click", getNumberFromNumpad);
});

allOperators.forEach((op) => {
    op.addEventListener("click", currentOperator);
});

equal.addEventListener("click", function () {
    currNumber = Number(inputNumber.textContent);
    calcAnswer();
    tempOutput.textContent += " " + currNumber + " =";
    inputNumber.textContent = currAns;
});

document.getElementById("clear").addEventListener("click", function () {
    inputNumber.textContent = "0";
    tempOutput.textContent = "0";
    currAns = 0;
    countOperator = 0;
});

document.getElementById("del").addEventListener("click", function () {
    inputNumber.textContent = inputNumber.textContent.slice(0, -1);
    if (inputNumber.textContent === "") {
        inputNumber.textContent = "0";
    }
});

Get the complete Code with HTML and CSS form here.

Conclusion

So we are finally done with our calculator, Congratulations on creating this calculator now as I already said this is how I made it you can definitely change it and make it in your own way if you want and just look at my code for help.

I hope this tutorial helped you in any way. And Thank you for taking you time to read this tutorial and best of luck.