JavaScript Calculator

Over the past few days I had so much fun building a Calculator app using JavaScript and some of its related technologies.

You can check my app here: Calculator-online .

Also, here is the GitHub repo: https://github.com/NawarYossef/calculator-app .

I realize that there are things that need improvement and that my application will always be a work in progress. Therefore, any contributions you make to improve my code are greatly appreciated.


I thought that before I talk about some of the challenges I faced throughout the project and how I overcame them, I should first list the technologies and things I learned. So here it is:

  • Bootstrap: I used it to create the calculator interface and buttons and to make a web page responsive.
  • jQuery: by using jQuery methods for event handling and collecting user inputs, I was able to manipulate DOM elements in effective ways.
  • Node.js: I used Node.js functions to write modular code and break up my application to multiple smaller files.
  • NPM: it enabled me to load third party libraries and frameworks such as lodash and Express.
  • Browserify: it was important to use a tool like Browserify in order compile Node.js code for the browser.
  • Express: I used Express to create a server and deploy my app on Heroku

Pseudocode

I realized from the beginning that my goal was not to only build a functioning program but to build an application that offers good user experience. The first thing I did was to try out some calculator apps such as the Google calculator, some android calculator on my phone and a couple of other free online apps. After the research phase, I started writing some user stories which later became a foundation for for my pseudocode:

- Initialize application
- collect Input from user
- Prevent user from entering bad expressions:
No multiple operators in a row
No multiple decimals in one number
No zero digits as first value in a number "043"
No zero digits after operator
- display input on screen
- when user clicks equal "=" sign:
convert "x" to "*" and "÷" to "/"
evaluate expression
- display result on screen
- clear screen for new operation.

Killing BUGS!!

After testing the first version of my app, I realized that there were many cases where incorrect user inputs would lead to bad math expression. So I decided to use regular expressions as my main tool to resolve these conditions.

One example is the leading zeros. I had to find a way to prevent users from entering zero digits at the beginning of a number and/or after operators. Although there were several option to resolve this issue, I decided to use regular expressions:

if (input.join("").match(/[(\-|=|+|x|\/)][0][0]/g)) {
lastInputDelete();
}

Another bug had to do with the minus operator. I had to find a way to prevent the user from entering two operators in succession (e.g.''5 +/ 3'') except when the ''-'' operator which is used to indicate a negative number (e.g. ''5 x -3''). Again, using regular expression was sufficient to resolve this issue:

if (input.join("").match(/[0-9][(x|\/)][(+|x|\/)]/g)) {
secondToLastInputDelete();
} else if (input.join("").match(/[0-9][(x|\/)][(\-)][(x|\/)]/g)) {
twoLastInputsDelete();
} else if (input.join("").match(/[0-9][(+|\-)][(x|\/)]/g)) {
secondToLastInputDelete();
} else if (input.join("").match(/[(x|\/)][(\-)][(\-|+)]/g)) {
lastInputDelete();
}

One of the trickiest bugs was related to how the JavaScript #eval() function does not parse the equal “=” operator as part of an expression and instead returns a reference error :

eval("3* 2* 2 = ")
>> Uncaught ReferenceError: Invalid left-hand side in assignment

And since the user will always enter the equal operator as the last input of an expression, I had to create a method to delete the equal sign before passing the expression to a function where the #eval() method would do its magic:

deleteEqualSign() {
let that = this
$(document).ready(function() {
$("#evaluate").click(function() {
that.lastInputDelete();
});
});
}

Code refactoring

  • After fixing several bugs in the program, it was time to refactor my code. I rewrote some functions to insure that no functions were multi-tasking and that my code is D.R.Y. Instead of using one class that does everything, I used the ES6 #class function to divide my program into two classes:
  • Calculator class: handles collecting inputs, evaluating expressions, display and reset operations.
  • Resolve class: handles validation and incorrect inputs.

One of the main issues I faced when using the #class function is the reference of #this keyword. I had to use an alias (“that”) inside jQuery functions to insure that #this is referencing the class:

displayTotal() {
let that = this
$(document).ready(function() {
$("#evaluate").click(function() {
$("#display").text(screenOutput);
// calling function to reset values for new operation
that.resetForNewOperation();
});
});
}


Deploying to Heroku

This was the most fun part of the whole experience. I first had to learn express to create a server and basic routing. This involved a short learning curve but was overall an extremely rewarding journey. I learned to use the static middleware and use #app.use() function to access the request and response objects:

app.use(express.static(..));
// middleware
app.listen(port, function(){
console.log( "server is up and running on port...")
}

Follow my coding journey here on Medium or find me on GitHub, Linkedin, and Facebook.