A Pen by Sean Rigney on CodePen.
Last active
August 26, 2015 16:16
-
-
Save seanr707/e2421b04b654d9726688 to your computer and use it in GitHub Desktop.
Calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<nav class="navbar navbar-default navbar-fixed-top header"> | |
<div class="container text-center"> | |
<h2>FreeCodeCamp Calculator</h2> | |
</div> | |
</nav> | |
<div class="space"></div> | |
<!-- Main section for setting up Angular --> | |
<div class="text-center" ng-app="calcApp" ng-controller="calcCtrl"> | |
<div class="calc container"> | |
<div class="display container text-center input-group"> | |
<input class="form-control" value="{{ display }}" disabled> | |
<span class="input-group-addon" ng-show="mem[1]">{{ mem[1] }}</span> | |
</div> | |
<!-- Angular generates buttons in 3 sections --> | |
<div class="buttons"> | |
<div class="row top"> | |
<button class="norm btn btn-danger" ng-repeat="item in top" ng-click="item.func(item.val)">{{ item.disp }}</button> | |
</div> | |
<div class="row main"> | |
<button class="norm col-md-1 btn btn-default text-right" ng-repeat="num in nums" ng-click="pressNum(num)" id="{{ num }}">{{ num }}</button> | |
<button class="bottom btn btn-default" ng-repeat="num in bottom" ng-click="pressNum(num)">{{ num }}</button> | |
</div> | |
<div class="side row"> | |
<button class="norm btn btn-primary" ng-repeat="item in side" ng-click="item.func(item.val)" id="{{ item.id }}">{{ item.disp }}</button> | |
</div> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Calculator Solution by Seanr707 for FreeCodeCamp | |
// Copying of this solution without credit and permission of author is not allowed | |
var calcApp = angular.module('calcApp', []); | |
calcApp.controller('calcCtrl', function($scope){ | |
$scope.nums = [ | |
7, 8, 9, | |
4, 5, 6, | |
1, 2, 3, | |
]; | |
// Seperate these for CSS sizing purposes | |
$scope.bottom = [0, '.',]; | |
// Where sum is stored | |
$scope.store = 0; | |
// Where ints turned to strings, conectated, eval() | |
// Always maxes at 3 items: [store, operand, current] -> [store, waitForOperand] | |
$scope.mem = []; | |
// Current entry we are entering | |
$scope.curr = 0; | |
// What displays in the view | |
$scope.display = 0; | |
var maxChar = 12; | |
// Changes what is displayed to users; rounds so it fits in textarea | |
$scope.update = function(type) { | |
// 'c' for current OR 's' for stored | |
if (type === 'c') { | |
$scope.display = $scope.curr; | |
} else { | |
$scope.display = $scope.store; | |
} | |
// Rounds if the number is too large | |
if ($scope.display.toString().length > maxChar) { | |
$scope.display = Math | |
.round($scope.display * Math.pow(10, maxChar)) / Math.pow(10, maxChar); | |
} | |
} | |
function opExec(mem, op) { | |
// If len < 3 then it is waiting to receive input | |
// Return first number to wait | |
if (mem.length < 3) { | |
return mem[0]; | |
} | |
// Parse var's just in case | |
mem[0] = parseFloat(mem[0]); | |
mem[2] = parseFloat(mem[2]); | |
// Perform operation | |
switch(op) { | |
case '+': | |
return mem[0] + mem[2]; | |
case '-': | |
return mem[0] - mem[2]; | |
case '*': | |
return mem[0] * mem[2]; | |
case '/': | |
return mem[0] / mem[2]; | |
} | |
} | |
// Runs when any number or decimal is pressed | |
$scope.pressNum = function(num) { | |
// Prevents overflowing textarea | |
if ($scope.curr.length >= maxChar) { | |
return; | |
} | |
// Prevents multiple decimals | |
if (num === '.' && $scope.curr.toString().match(/[^0-9|-]/g)) { | |
return; | |
} | |
// Prevents displaying as '0892' | |
if ($scope.curr === 0) { | |
$scope.curr = ''; | |
} | |
// Converts to string for easy number conectation (especially with decimal button) | |
$scope.curr = $scope.curr.toString() + num.toString(); | |
$scope.update('c'); | |
} | |
// Operand function | |
$scope.pressOp = function(op) { | |
// For changing operand in use instead of stacking them in mem | |
if ($scope.mem[1] && $scope.curr === 0) { | |
$scope.mem[1] = op; | |
return; | |
} | |
// NOTE: Used strings instead of numbers so eval can be used to | |
// parse operands unconditionally | |
// Push current entry in the memory | |
$scope.mem.push($scope.curr); | |
console.log($scope.mem); | |
// Empty the current entry | |
$scope.curr = 0; | |
// Evaluate our 3 (or 2 if first press) items in memory and move them | |
// to storage | |
$scope.store = opExec($scope.mem, $scope.mem[1]); | |
// Add stored sum and the operand to memory | |
$scope.mem = [$scope.store, op]; | |
// Updates display to stored number, so '2+3+4' would display '5' when | |
// I press '+' the second time, until '4' is pressed | |
$scope.update('s'); | |
console.log($scope.mem); | |
} | |
$scope.clear = function(type) { | |
if (type === 'ac') { | |
// Clears all memory | |
$scope.curr = 0; | |
$scope.store = 0; | |
$scope.update('c'); | |
$scope.mem = []; | |
} else { | |
// Clears current entry | |
$scope.curr = 0; | |
$scope.update('c'); | |
} | |
} | |
// NA is a null variable used to make ngRepeat usable on all entries in HTML | |
// Most functions pass a variable through, so some functions need null values | |
// So that the ngRepeat loop can be used unconditionally | |
$scope.equal = function(NA) { | |
// Pushes current to memory | |
$scope.mem.push($scope.curr); | |
// Eval's memory and moves to current, so it can be operated on | |
$scope.curr = opExec($scope.mem, $scope.mem[1]); | |
// Clears everything out | |
$scope.store = 0; | |
$scope.mem = []; | |
$scope.update('c'); | |
} | |
// Changes pos/neg value of number in current | |
$scope.chgSign = function(NA) { | |
if ($scope.curr === 0) { | |
return; | |
} | |
$scope.curr *= -1; | |
$scope.update('c'); | |
} | |
// NOTE: These objects were added last because they call on functions from above | |
// Operands on side in order | |
// IDs added so size could be changed on plus sign in CSS | |
$scope.side = { | |
multiply: { | |
id: 'mult', | |
disp: 'x', | |
val: '*', | |
func: $scope.pressOp, | |
}, | |
divide: { | |
id: 'div', | |
disp: '÷', | |
val: '/', | |
func: $scope.pressOp, | |
}, | |
minus: { | |
id: 'minus', | |
disp: '-', | |
val: '-', | |
func: $scope.pressOp, | |
}, | |
plus: { | |
id: 'plus', | |
disp: '+', | |
val: '+', | |
func: $scope.pressOp, | |
}, | |
}; | |
// Operands on top in order | |
$scope.top = { | |
ac: { | |
disp: 'AC', | |
val: 'ac', | |
func: $scope.clear, | |
}, | |
ce: { | |
disp: 'CE', | |
val: 'ce', | |
func: $scope.clear, | |
}, | |
changeSign: { | |
disp: '±', | |
val: null, | |
func: $scope.chgSign, | |
}, | |
/* Not enough room for this operand (least needed) yet | |
percent: { | |
disp: '%', | |
val: '%', | |
func: $scope.pressOp, | |
}, | |
*/ | |
equal: { | |
disp: '=', | |
val: null, | |
func: $scope.equal, | |
}, | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/2.5.1/less.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
background-image: url("http://www.publicdomainpictures.net/pictures/60000/velka/stripes-background-colorful-1376773871uk4.jpg"); | |
background-size: cover; | |
width: 100%; | |
height: 100%; | |
color: black; | |
} | |
.space { | |
height: 100px; | |
} | |
.header { | |
padding-bottom: 1%; | |
border: solid 1px grey; | |
opacity: .99; | |
} | |
.calc { | |
width: 180px; | |
height: 250px; | |
padding: 5px; | |
padding-top: 10px; | |
margin: 1% auto 0 auto; | |
background: lightgrey; | |
color: black; | |
border: solid 1px grey; | |
border-radius: 5px; | |
box-shadow: 0 2px 4px grey; | |
} | |
.display { | |
width: 150px; | |
margin 1% auto 1% auto; | |
padding: 4px; | |
} | |
.buttons { | |
width: 170px; | |
margin: 0 auto 0 auto; | |
padding: 18px; | |
text-align: center | |
} | |
.btn { | |
border-radius: 0; | |
box-shadow: 0 1px 1px grey; | |
} | |
.top { | |
width: 133px; | |
margin: 0 auto 0 auto; | |
} | |
.norm { | |
margin: 1px; | |
width: 30px; | |
padding: 3px; | |
} | |
.main { | |
width: 96px; | |
margin: 0 0 0 auto; | |
display: inline-block; | |
} | |
.row { | |
margin: 0; | |
padding: 0; | |
} | |
.bottom { | |
width: 46px; | |
margin: 1px; | |
} | |
.side { | |
width: 34px; | |
margin: 0 auto 0 -4px; | |
display: inline-block; | |
} | |
.side-btn { | |
width: 30px; | |
} | |
#plus { | |
height: 34px; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment