Skip to content

Instantly share code, notes, and snippets.

@longnt80
Last active June 13, 2017 01:08
Show Gist options
  • Save longnt80/1cc0a7852a351c984bf1132e755c2b52 to your computer and use it in GitHub Desktop.
Save longnt80/1cc0a7852a351c984bf1132e755c2b52 to your computer and use it in GitHub Desktop.
JavaScript Calculator
<div class="container">
<div class="title">Calculator</div>
<div class="input-box">
<div class="ans"></div>
<div class="input"></div>
</div>
<div class="button-box">
<div class="row">
<button value="ac">AC</button>
<button value="ce">CE</button>
</div>
<div class="row">
<button value="7">7</button>
<button value="8">8</button>
<button value="9">9</button>
<button value="÷">÷</button>
</div>
<div class="row">
<button value="4">4</button>
<button value="5">5</button>
<button value="6">6</button>
<button value="x">x</button>
</div>
<div class="row">
<button value="1">1</button>
<button value="2">2</button>
<button value="3">3</button>
<button value="-">-</button>
</div>
<div class="row">
<button value=".">.</button>
<button value="0">0</button>
<button class="result" value="=">=</button>
<button value="+">+</button>
</div>
</div>
</div>
$(document).ready(function(){
var ans = "";
var input = "";
var holder = [];
// Function to round the decimal, avoid floating point error (**I didn't write this**)
Number.prototype.roundTo = function(x, base) {
var pow = Math.pow(base || 10, x);
return +(Math.round(this * pow) / pow);
};
// Function to calculate the math in an array. Ex: ["3","+","2"]
function parser(arr) {
var temp;
for (var i = 1; i < arr.length; i+=2) {
var reg = /[\-\+]/;
if (arr.length === 1 ) {
return arr;
}
else if (arr[i].match(reg) && arr.join('').indexOf('x') < 0 && arr.join('').indexOf('÷') < 0 ) {
if ( arr[i] === "+" ) {
temp = parseFloat(arr[i-1]) + parseFloat(arr[i+1]);
arr.splice(i-1,3, temp.roundTo(10).toString() );
parser(arr);
}
else if ( arr[i] === "-" ) {
temp = parseFloat(arr[i-1]) - parseFloat(arr[i+1]);
arr.splice(i-1,3, temp.roundTo(10).toString() );
parser(arr);
}
}
else if (arr[i] === "x" ) {
temp = parseFloat(arr[i-1]) * parseFloat(arr[i+1]);
arr.splice(i-1,3, temp.roundTo(10).toString() );
parser(arr);
}
else if (arr[i] === "÷" ) {
temp = parseFloat(arr[i-1]) / parseFloat(arr[i+1]);
arr.splice(i-1,3, temp.roundTo(10).toString() );
parser(arr);
}
}
}
var typeDigit = /\d/g;
var typeMath = /x\b|[\÷\-\+]\B/g;
var typeDot = /\./g;
$('.input').html("0");
$('.ans').html("0");
$('button').on('click',function(){
var val = $(this).val();
var lastDigit = input.charAt(input.length-1);
var isSolve = val.match(/\=/g);
var isDot = val.match(typeDot);
var isMath = val.match(typeMath);
var isRedo = val.match(/ac|ce/g);
var isDigit = val.match(typeDigit);
var previousVal = holder[holder.length-1];
// Input is a digit 0-9
if ( isDigit ) {
if ( ans.length > 0 ) {
ans = "";
input = "";
holder = [];
if ( val == 0 ) {
$('.input').html("0");
$('.ans').html("0");
input = val;
}
else {
input = val;
}
}
else if ( input.length === 1 && input == 0 ) {
input = val;
}
else if ( input.match(typeMath) ) {
// Dealing with negative sign
if ( (input.length === 1 && input === "-" && holder.length === 0) || ( previousVal.length === 1 && previousVal.match(typeMath)) ) {
input += val;
}
else {
holder.push(input);
input = val;
}
}
else {
input += val;
}
}
// Input is the dot
if ( isDot ) {
if ( input.match(typeMath) ) {
if ( (input.length === 1 && input === "-" && holder.length === 0) || ( previousVal.length === 1 && previousVal.match(typeMath)) ) {
input += "0" + val;
}
else {
holder.push(input);
input = "0" + val;
}
}
else if ( input.length === 0 ) {
if ( ans.length > 0 ) {
ans = "";
input = "";
holder = [];
input = "0" + val;
}
input = "0" + val;
}
else if ( input.length > 0 && input.indexOf(val) > 0 ) {
return;
}
else {
input += val;
}
}
// Input is math signs
if ( isMath ) {
if ( input.length === 0 ) {
if ( ans.length === 0 ) {
if ( val === "-" ) {
input = val;
}
else {
return;
}
}
else if ( ans.length > 0 ){
if ( holder[0] === "Infinity" || holder[0] === "-Infinity" || holder[0] === "NaN" ) {
if ( val === "-" ) {
ans = "";
holder = [];
input = val;
}
else {
return;
}
}
else {
ans = "";
input = val;
}
}
}
// Dealing with negative sign
else if ( (lastDigit === ".") || (input === "-" && previousVal.match(typeMath)) ) {
return;
}
// Dealing with negative sign
else if ( input.match(typeMath) && val != "-" ) {
input = val;
}
else if ( input.match(typeMath) && val === "-" ) {
holder.push(input);
input = val;
}
else {
holder.push(parseFloat(input).toString());
input = val;
}
}
// Input is the cancel buttons: AC or CE
if ( val === "ac" ) {
ans = "";
input = "";
holder = [];
}
if ( val === "ce" ) {
if ( ans.length > 0 ) {
ans = "";
input = "";
holder = [];
}
else if ( input.match(typeMath) ) {
input = holder.pop();
}
else if ( input.length === 1 ) {
if ( holder.length === 0 ) {
input = "";
}
else {
input = holder.pop();
}
}
else {
input = input.slice(0, input.length-1);
}
}
// Click the "=" button
if ( isSolve ) {
if ( holder.length <= 1 ) {
return;
}
else if ( input.match(typeDigit) ) {
holder.push(parseFloat(input).toString());
}
else if ( input === "-" && lastDigit.match(typeMath) ) {
holder.pop();
}
ans = holder.slice().join('');
parser(holder);
input = "";
if ( holder[0] === "Infinity" || holder[0] === "-Infinity" || holder[0] === "NaN" ) {
$('.ans').html(ans + "=");
$('.input').html("Should not divided by 0!<br><a target=\"_blank\" href=\"https://goo.gl/F2B4MB\">Learn more</a>");
}
else {
$('.ans').html(ans + "=");
$('.input').html(holder.join(''));
}
}
lastDigit = input.charAt(input.length-1); // Updating lastDigit AFTER the input is being updated above
console.log(val,input,input.length,lastDigit,holder,ans.length); // For debugging
if ( input.length === 0 && holder.length === 0 ) {
$('.input').html("0");
}
else if ( input.length > 0 ) {
$('.input').html(input);
}
if ( holder.length === 0 ) {
$('.ans').html("0");
}
else if ( holder.length > 0 && input.length > 0 ) {
$('.ans').html(holder.join(''));
}
console.log( $('.input').text().length ); // For debugging
if ( $('.input').text().length > 15 ) {
$('.input').addClass('expanded');
}
else {
$('.input').removeClass('expanded');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
* {
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
}
.container {
width: 300px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
border: 1px solid gray;
border-radius: 10px;
text-align: center;
background-color: GhostWhite;
.title {
margin: 10px;
text-align: left;
color: lightgrey;
}
.input-box {
width: 280px;
margin: 0 auto;
border: 1px solid gray;
border-radius: 3px;
background-color: honeydew;
text-align: right;
padding: 5px 10px;
overflow: hidden;
.input,.ans {
float: right;
clear: both;
overflow: hidden;
}
.input {
font-size: 30px;
font-weight: bold;
height: 45px;
}
.input.expanded {
font-size: 16px;
word-wrap: break-word;
word-break: break-all;
width: 100%;
}
.ans {
font-size: 14px;
height: 21px;
}
a {
color: coral;
}
}
.button-box {
width: 280px;
margin: 20px auto;
.row {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
align-content: center;
button {
font-weight: bold;
font-size: 20px;
width: 22%;
background-color: Silver;
border: none;
margin: 5px 11px 5px 0;
height: 40px;
line-height: 40px;
box-shadow: 0 3px #999;
border-radius: 3px;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&[value="="] {
background-color: coral;
}
}
button:active {
transform: translateY(2px);
box-shadow: 0 1px #999;
}
button:focus {
outline: none;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment