A simple calculator with AngularJS

AngularJs is a javascript based framework to create powerful and dynamic web applications.With the help of AngularJs we can extend the capabilities of HTML and use functions like Data-binding, MVC architecture and much more.

Angular Calc

Below is a simple example of a calculator built with AngularJs, I have tried to use as much as minimal code possible.The main functionlity used is data-binding and calling operating functions using directive.

View Demo


<body ng-app="myApp">
 <form class="calc" ng-controller="MyCtrl">
 <p class="calc-display">
 <input type="text" name="output" id="res" value="{{output}}" class="calc-display-input">
 </p>
 <p class="operators">
 <button type="button" class="calc-button calc-button-red calc-button-big" ng-click='operate("/")' >÷</button>
 <button type="button" class="calc-button calc-button-red calc-button-big" ng-click='operate("*")' >x</button>
 <button type="button" class="calc-button calc-button-red calc-button-big" ng-click='operate("-")' >-</button>
 <button type="button" class="calc-button calc-button-red calc-button-big" ng-click='operate("+")' >+</button>
 </p>
 <p class="calc-row">
 <button type="button" class="calc-button" ng-click="updateOutput($index)" ng-repeat="n in [0,1,2,3,4,5,6,7,8,9]">{{n}}</button>
 <button type="button" class="calc-button" ng-click="updateOutput('.')">.</button>
 <button type="button" class="calc-button" ng-click='output = 0'>C</button>
 
 </p>
 <p class="calc-row"><button type="button" class="calc-button calc-button-yellow calc-button-big" ng-click="equal()">=</button></p>
 </form>
</body>

So I have used ng-repeat for the numbers and I have bind a function to them which will pass the value using $index to output function.For the operators I have used a common function as well and I am passing just the operator.

The clear button just resets the output variable to zero.now lets the AngularJs code.


var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
 $scope.output = "0";
 $scope.inOperation = false;
 $scope.num1 = 0;
 
 $scope.updateOutput = function(btn) {
 if($scope.output == "0") {
 $scope.output = btn;
 } else {
 $scope.output += String(btn);
 }
 };

 $scope.operate = function(op) {
 if($scope.output && !$scope.inOperation){
 $scope.num1 = $scope.output;
 $scope.output += op;
 $scope.inOperation = true;
 }else if($scope.output.length > $scope.num1.length+1){
 $scope.output = eval($scope.output);
 $scope.output += op;
 } 
 };

 $scope.equal = function() {
 if($scope.output.length > $scope.num1.length+1){
 $scope.output = eval($scope.output);
 $scope.num1 = $scope.output;
 }else{
 $scope.output = $scope.num1;
 }
 };
 
}
myApp.controller('MyCtrl', MyCtrl);

The code is pretty simple , I have used a output variable initialized to zero , then inOpertaion to specify the state of operation and finally num1 to store the first number.

The updateoutput function displays the number on the calc screen.The operate function evaluates the string based on the conditions and so the equal function does.

Finally below is the css code for making it look like a calculator.



html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
  display: block;
}

body {
  line-height: 1;
}

ol, ul {
  list-style: none;
}

blockquote, q {
  quotes: none;
}

blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

.about {
  margin: 70px auto 40px;
  padding: 8px;
  width: 260px;
  font: 10px/18px 'Lucida Grande', Arial, sans-serif;
  color: #bbb;
  text-align: center;
  text-shadow: 0 -1px rgba(0, 0, 0, 0.3);
  background: #383838;
  background: rgba(34, 34, 34, 0.8);
  border-radius: 4px;
  background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3));
  background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3));
  background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3));
  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3));
  -webkit-box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2), 0 0 6px rgba(0, 0, 0, 0.4);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2), 0 0 6px rgba(0, 0, 0, 0.4);
}
.about a {
  color: #eee;
  text-decoration: none;
  border-radius: 2px;
  -webkit-transition: background 0.1s;
  -moz-transition: background 0.1s;
  -o-transition: background 0.1s;
  transition: background 0.1s;
}
.about a:hover {
  text-decoration: none;
  background: #555;
  background: rgba(255, 255, 255, 0.15);
}

.about-links {
  height: 30px;
}
.about-links > a {
  float: left;
  width: 50%;
  line-height: 30px;
  font-size: 12px;
}

.about-author {
  margin-top: 5px;
}
.about-author > a {
  padding: 1px 3px;
  margin: 0 -1px;
}

input, button {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

::-moz-focus-inner {
  padding: 0;
  border: 0;
}

body {
  font: 12px/20px 'Lucida Grande', Tahoma, Verdana, sans-serif;
  color: #404040;
  background: #d8e5e5;
}

.calc {
  margin: 50px auto;
  padding: 15px;
  width: 320px;
  background: #3d4543;
  border: 1px solid #222;
  border-radius: 4px;
  background-image: -webkit-linear-gradient(top, #3d4543, #2f2a2f);
  background-image: -moz-linear-gradient(top, #3d4543, #2f2a2f);
  background-image: -o-linear-gradient(top, #3d4543, #2f2a2f);
  background-image: linear-gradient(to bottom, #3d4543, #2f2a2f);
  -webkit-box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1), 0 0 4px rgba(0, 0, 0, 0.5);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1), 0 0 4px rgba(0, 0, 0, 0.5);
}

.calc-display {
  margin: 0 0 20px;
  padding: 3px;
  background: #222;
  border-radius: 3px;
  -webkit-box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.calc-display-input {
  display: block;
  width: 100%;
  height: 35px;
  padding: 0 8px;
  font: 26px/35px UbuntuMono, monospace;
  color: #444;
  text-align: right;
  background: #bccd95;
  background-clip: padding-box;
  /* Don't let the background bleed outside the border */
  border: 1px solid #222;
  border-radius: 2px;
  background-image: -webkit-linear-gradient(top, #bccd95, #e0f5b1);
  background-image: -moz-linear-gradient(top, #bccd95, #e0f5b1);
  background-image: -o-linear-gradient(top, #bccd95, #e0f5b1);
  background-image: linear-gradient(to bottom, #bccd95, #e0f5b1);
  -webkit-box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.12);
}

.calc-row , .operators {
  margin-top: 7px;
  zoom: 1;
}
.calc-row:before, .calc-row:after, .operators:after, .operators:before {
  content: '';
  display: table;
  clear: both;
}


.calc-button {
  float: left;
  padding: 0;
  margin: 0 0 0 7px;
  width: 74px;
  font: 15px/35px UbuntuMono, monospace;
  color: white;
  text-align: center;
  text-decoration: none;
  text-shadow: 0 1px rgba(0, 0, 0, 0.4);
  background: #313131;
  background-clip: padding-box !important;
  /* !important because FF overrides the value on :active */
  border: 0;
  /* IE 8 fix */
  border: 1px solid rgba(0, 0, 0, 0.8);
  border-radius: 3px;
  cursor: pointer;
  background-image: -webkit-linear-gradient(top, #313131, #1c1c1c);
  background-image: -moz-linear-gradient(top, #313131, #1c1c1c);
  background-image: -o-linear-gradient(top, #313131, #1c1c1c);
  background-image: linear-gradient(to bottom, #313131, #1c1c1c);
  -webkit-box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 1px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 1px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.calc-row .calc-button {
  width: 101px;
  margin-bottom: 10px;
}
.calc-row .calc-button:nth-child(3n+1){
  margin-left: 0px;
}
.calc-button:first-child {
  margin-left: 0;
}
.calc-button:active {
  background: #282828;
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.6), 0 1px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.6), 0 1px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.05);
}

.calc-button-gray {
  background: #6f6f6f;
  background-image: -webkit-linear-gradient(top, #6f6f6f, #515151);
  background-image: -moz-linear-gradient(top, #6f6f6f, #515151);
  background-image: -o-linear-gradient(top, #6f6f6f, #515151);
  background-image: linear-gradient(to bottom, #6f6f6f, #515151);
}
.calc-button-gray:active {
  background: #555;
}

.calc-button-red {
  background: #ff4561;
  background-image: -webkit-linear-gradient(top, #ff7286, #ff4561);
  background-image: -moz-linear-gradient(top, #ff7286, #ff4561);
  background-image: -o-linear-gradient(top, #ff7286, #ff4561);
  background-image: linear-gradient(to bottom, #ff7286, #ff4561);
}
.calc-button-red:active {
  background: #ff4561;
}

.calc-button-yellow {
  background: #ffa70c;
  background-image: -webkit-linear-gradient(top, #ffb935, #ffa70c);
  background-image: -moz-linear-gradient(top, #ffb935, #ffa70c);
  background-image: -o-linear-gradient(top, #ffb935, #ffa70c);
  background-image: linear-gradient(to bottom, #ffb935, #ffa70c);
  width: 100% !important;
}
.calc-button-yellow:active {
  background: #ffa70c;
}

.calc-button-big {
  font-size: 16px;
}

.lt-ie8 .calc-display-input {
  width: 152px;
}

/* border-box fix */
.lt-ie7 .calc-row {
  margin-left: -7px;
}

/* first-child fix */