As a part of a study-group I did a very simple little JavaScript calculator. It's not made to look pretty.
Any ideas on how I can make the code prettier?
/*
* This is a simple JS calculator
* Made by Gemtastic 2016-05-08
*/
// Gather and set up DOM elements
var numberScreen = 'screen';
var numBtns = document.getElementsByClassName('number');
var operators = document.getElementsByClassName('operator');
// Mini statemachine of if we're in the middle of operating on a number.
var operating = false;
var operand = '';
/*
* Clears the content from the screen.
*/
function clearScreen() {
document.getElementById(numberScreen).innerHTML = "0";
resetOperating();
}
/*
* Evaluates the entered numbers with the given operator.
*/
function evaluate() {
var result;
/* If it isn't operating or the last entered is the operator
* there's no point in doing anything.
*/
if(operating && isLastEnteredNumber()){
var content = document.getElementById(numberScreen).innerHTML;
var numbers = content.split(operand);
// Parse strings to be able to operate on them.
var firstNumber = parseInt(numbers[0], 10);
var secondNumber = parseInt(numbers[1], 10);
// Switch the stored operator.
switch(operand) {
case '+':
result = firstNumber + secondNumber;
break;
case '÷':
if(firstNumber !== 0 && secondNumber !== 0) {
result = firstNumber / secondNumber;
} else {
result = 0;
}
break;
case '×':
result = firstNumber * secondNumber;
break;
case '–':
result = firstNumber - secondNumber;
break;
default:
console.log('Something went terribly wrong! ' + operand + " is not a supported operator!");
}
}
resetOperating();
document.getElementById(numberScreen).innerHTML = result || 0;
return result || 0;
}
/*
* Transforms the current input or the input's value if it's a
* full expression but not evaluated into a percentile of itself.
*/
function percent() {
var content = document.getElementById(numberScreen).innerHTML;
// Cecks if you've operated two numbers but not yet pressed '=' for evaluation
if(operating && isLastEnteredNumber()) {
var result = evaluate(); // Evaluates the screen data
if(result != '0') { // if the result isn't 0 make the transformation
content = content / 100;
} else { // if it is 0 then just append a decimal for user feedback.
content += '.0';
}
} else if (!operating && isLastEnteredNumber && content != '0') { // If you haven't started an operation an a not 0 character do the transformation
content = content / 100;
} else {
content += '.0'; // failsafe append a decimal for user feedback.
console.log('Bug in percent function! Operating: ' + operating + ', screen content:' + content); // Log, because if this happens we have a bug lulz.
}
document.getElementById(numberScreen).innerHTML = content;
resetOperating();
}
/*
* Adds a decimal to the screen number.
*/
function decimal() {
document.getElementById(numberScreen).innerHTML += ".";
}
/*
* Changes the value to be positive or negative.
*/
function editPositiveNegativeValue() {
var content = document.getElementById(numberScreen).innerHTML;
// Simple check if the first character on screen is - or not. If it is it just removes it.
if(content.charAt(0) == '-') {
content = content.slice(1);
} else {
content = "-" + content;
}
document.getElementById(numberScreen).innerHTML = content;
}
/*
* Resets the state-machine of operation to "off".
*/
function resetOperating() {
operating = false;
operand = '';
}
/*
* Checks if the last character on the screen is a number.
*/
function isLastEnteredNumber() {
var content = document.getElementById(numberScreen).innerHTML;
return !isNaN(content.charAt(content.length - 1));
}
/*
* If the screen isn't showing a simple 0 append
* to it. Else it will remplace the 0 with the
* button's number.
*/
function numberClick(event) {
var content = document.getElementById(numberScreen).innerHTML;
var btnNum = event.target.innerHTML;
if(content != "0"){
content += btnNum;
} else {
content = btnNum;
}
document.getElementById(numberScreen).innerHTML = content;
}
/*
* Called when you've pressed an operator button.
*/
function operatorClick(event) {
var operator = event.target.innerHTML;
var content = document.getElementById(numberScreen).innerHTML;
switch(operator) {
case '=':
evaluate();
break;
case 'C':
clearScreen();
break;
case '%':
percent();
break;
case '+/-':
editPositiveNegativeValue();
break;
case '.':
decimal();
break;
default:
operating = true;
operand = operator;
content += operator;
document.getElementById(numberScreen).innerHTML = content;
break;
}
}
// Set up listeners for the operands
for(var o = 0; o < operators.length; o++) {
operators[o].addEventListener('click', operatorClick, false);
}
// Set up listeners for the buttons
for(var b = 0; b < numBtns.length; b++) {
numBtns[b].addEventListener('click', numberClick, false);
}
clearScreen();
.btn {
display: inline-block;
border: 1px solid #ddd;
padding: 5px;
margin: 2px;
border-radius: 5px;
width: 1em;
text-align: center;
}
.btn:hover {
background-color: #eee;
cursor: pointer;
}
.dummy {
border: 1px solid #fff;
}
.dummy:hover {
background-color: transparent;
}
.pad {
position: absolute;
}
#screen {
display: inline-block;
margin-bottom:5px;
padding: 5px;
height: 1em;
width: 90%;
border-radius: 5px;
border: 1px solid #ddd;
text-align: right;
}
<div class="pad">
<div id="screen"></div>
<div class="row">
<div class="btn operator">C</div>
<div class="btn operator">%</div>
<div class="btn operator">+/-</div>
<div class="btn operator">÷</div>
</div>
<div class="row">
<div class="btn number">7</div>
<div class="btn number">8</div>
<div class="btn number">9</div>
<div class="btn operator">–</div>
</div>
<div class="row">
<div class="btn number">4</div>
<div class="btn number">5</div>
<div class="btn number">6</div>
<div class="btn operator">+</div>
</div>
<div class="row">
<div class="btn number">1</div>
<div class="btn number">2</div>
<div class="btn number">3</div>
<div class="btn operator">×</div>
</div>
<div class="row">
<div class="btn dummy"> </div>
<div class="btn number">0</div>
<div class="btn operator">.</div>
<div class="btn operator">=</div>
</div>
</div>
Known issues:
- Modulus (%) is not modulus as in 5%2 = 3 it turns the number on the display into a percentage.
- There's no limit to amount of numbers in the display
- It doesn't understand order of operations or many calculations at once.
5 + 56 - 2 = bork
. You have to do5 + 56 = 61 - 2 = 59
5+56-2 == 3
what now? \$\endgroup\$