IOS8 Calculator _ANGULARJS based on ANGULARJS implementation

Source: Internet
Author: User

Objective

First of all, create the basic project of ANGULARJS, it is best to use the scaffolding tool yeoman directly generated, if not the environment, of course, can also download the Angularjs file to introduce the project.

Detailed examples

Main.js is the project's main JS file, all of the JS are written in this file, initialization, the file's JS code as follows

Angular
 . Module (' Calculatorapp ', [
 ' nganimate ',
 ' ngcookies ',
 ' Ngresource ',
 ' Ngroute
 ', ' Ngsanitize ',
 ' Ngtouch '
 ])
 . Controller (' Mainctrl ', function ($scope) {
 $scope. result= "";
 $scope. data={
  "1": ["AC", "+ +", "%", ""],
  "2": ["7", "8", "9", "X"],
  "3": ["4", "5", "6", "-"],
  "4": ["1", "2", "3", "+"],
  "5": ["0", ".", "="]
 }
 );

Result is a two-way binding that displays the results of the operation, and data is the number and symbol on the calculator keyboard.

All CSS code related to this project is as follows:

*{margin:0;
padding:0;
 } body {padding-top:20px;
padding-bottom:20px;
 } h1{Text-align:center;
Color: #3385ff;
 }. main{margin:20px Auto;
 border:1px solid #202020;
 Border-bottom:none;
 width:60%;
height:600px;
 }. result{Display:block;
 width:100%;
 height:30%;
 Background: #202020;
 Box-sizing:border-box;
 Border:none;
 padding:0;
 margin:0;
 Resize:none;
 Color: #fff;
 font-size:80px;
 Text-align:right;
 line-height:270px;
 Overflow:hidden;

Background-clip:border-box;
 }. row{height:14%;
 Background: #d7d8da;
 Box-sizing:border-box;
 border-bottom:1px solid #202020;
Overflow:hidden;
 }. col{height:100%;
 Box-sizing:border-box;
 border-right:1px solid #202020;
 Float:left;
 Color: #202020;
 font-size:28px;
 Text-align:center;
line-height:83px;
 }. normal{width:25%; end-no{width:25%;
 Border-right:none;
 Background: #f78e11;

Color: #fff;
 }. zero{width:50%; history{background: #3385ff;
 Color: #fff;
 font-size:22px; Text-aLign:center; }

Then the layout of the HTML is as follows:

<body ng-app= "Calculatorapp" >
 
 

The P tag for class history is used to display input records, which means that all of the keys you press are displayed above for easy viewing of the results, history as an array below the current scope, which is explained later. Here, a textarea is used as the display screen for calculating results, mainly to use bidirectional binding features. At the same time generate a calculator each key and interface elements are through the data object cycle has been generated, the showClass method is a method below the scope to get the irregular interface display elements of the class attribute, explained later, the showResult method is the key response to the Main method, All of our press responses to the keys are in this way and will be explained in detail later.

The Showclass method code is as follows:

  Display Calculator style
 $scope. Showclass=function (index,a) {
  if (a==0) {return
   "zero";
  }
  return index==3| | a== "=" "?" End-no ": normal";
 

This method is primarily for special handling of the last column in each row to be shown as orange and to occupy two cells for the key that displays 0.

So far, the calculator interface has been fully implemented

The effect chart is as follows:

The following needs to implement the response to the key, the key includes the number key, operator key, AC key, each button press will have a different corresponding and the key is a link between the

In order to make the code easy to explain, the method of Showresult the code of the method is given by piecewise.

First, there are several variables to be added for control and storage.

 The stack of the number used for calculation
 $scope. num=[];
 $scope. history=[];
  The operator stack that accepts input
 $scope. opt=[];
  The calculator calculates
 the result $scope. result= "";
 Indicates whether you want to start the display again, true to not display again, false indicates that you want to empty the current output to display the digital
 $scope again. flag=true;
 Indicates whether the operator can be entered again or false $scope if it can be true
 . Isopt=true;

The NUM array is actually a stack, used to receive the user input numbers, the specific usage will explain later, the history array for the user entered all the keys, each press let the button on the symbol or number into the stack, and then use the binding real-time display in the interface. An opt array is another stack that is used to receive the operator entered by the user. The concrete usage will explain later, flag is a sign, true indicates that the number that is pressed while the number is being pressed is part of the current display number and needs to be shown after it, such as the current interface showing 12, and then 3 to determine the flag, and if true, display 123, Otherwise, empty the interface, the direct display of 3.ISOPT is another flag, primarily to prevent users from entering the process of illegal input to the operator, such as the user entered the 1+2+, when the loss is here, the following input should be a number, but the user entered an operator, by judging this flag, Allows the calculator to ignore this illegal operator, leaving the input still 1+2+.

The following code fragment gives the complete code to connect them.

$scope. Init=function () {
  $scope. num=[];
  $scope. opt=[];
  $scope. history=[];
  $scope. Flag = true;
  $scope. isopt=true;

 } ;
 $scope. Showresult=function (a) {
  $scope. History.push (a);
  var reg=/\d/ig,regdot=/\./ig,regabs=/\//ig;
  If you click on a number if
  (Reg.test (a)) {
   //Eliminate Frozen
   if ($scope. isopt==false) {
    $scope. Isopt=true
   }

   if ($scope. result!= 0 && $scope. Flag && $scope. Result!= "error") {
    $scope. result + A;
   }
   else {
    $scope. result = A;
    $scope. Flag = true;
   }

  }

initThe method is used to initialize some variables and flags to return them to their original state. The showResult method is to show the main method that the interface responds to user actions, the above code is an if branch of the method that, if input is a number, if the input to the operator has been frozen (the input operator is not currently allowed, the input will be ignored), then when the number is entered, the freeze state is untied So that the next time the operator is entered, the operator stack is entered. If the currently displayed result is not empty and the number that is now pressed is part of the currently displayed number and no error occurs, the result is that the current number is currently being pressed at the end of the current display number, otherwise the display will be displayed again, and the next number to be displayed will be shown after the number.

JS Code (connected)

 If you click on AC
  else if (a== "AC") {
   $scope. result=0;
   $scope. Init ();
  

If you click on AC, it represents initialization, letting the display result be 0 and emptying all states.

JS Code (connected)

 If you clicked on a decimal point
  else if (a== ".") {
   if ($scope. result!= "" &&!regdot.test ($scope. Result)) {
    $scope. Result+=a
   }}
  }

If you click on a decimal point, let this decimal number be connected to the end of the current display if the current display is not empty and the current display does not have a decimal point in the result.

JS Code (connected)

 If you click on a fetch back operator
  else if (Regabs.test (a)) {
   if ($scope. result>0) {
    $scope. result= "-" + $scope. Result;
   }
   else{
    $scope. Result=math.abs ($scope. result);
   }
  }

If you click on a reverse operation, the current display result is reversed

JS Code (connected)

 If you click a percent
  else if (a== "%") {
   $scope. result= $scope. Format (number ($scope. result)/100);

  

If you click on a percent semicolon, the current display result is divided by 100 and then shown, here is a format function

The code is as follows:

 Formatted result output
  $scope. format=function (num) {
  var regnum=/.{ 10,}/ig;
   if (Regnum.test (num)) {
    if (/\./.test (num)) {return
     num.toexponential (3);
    }
    else{return
     num.toexponential ();
    }
   else{return
    num
   }
  }

Its main function is that iOS8 's own calculator does not display infinitely many digits, if more than 10 digits (including a decimal point) are used, the scientific calculation method is applied to show that, in order to be simple, the display result with a decimal point and more than 10 digits is calculated using scientific calculation, so that it retains the 3-bit display after the decimal point.

JS code (Showresult partially connected)

 If you click on an operator and the current display result is not NULL and error
  else if ($scope. Checkoperator (a) && $scope. result!= "" &&$ scope.result!= "Error" && $scope. isopt) {
   $scope. flag=false;
   $scope. Num.push ($scope. result);
   $scope. Operation (a);
   Once you click the operator once, you need to ignore the
   $scope. Isopt=false
  }

This branch is one of the most complex branches, which means that if you enter an operator, the operation will be performed. To get into this branch, you need to first set the flag to false, which means that the next time you enter a number, you re-enter the number instead of the current display result input.

Then, to get the currently displayed number first into the digital stack as the number being calculated, the operation method is the method of operation, because this time you have clicked on an operator, so the next time you click on it, ignore the operator and set the isopt to False.

The operation code is as follows

//Compare the precedence of the currently entered operator and Operation Fu top operator//if the stack top operator has a small priority, the current operator is put into the stack and is not computed,//otherwise the stack top operator is out of stack, and the digital stack is continuously out of the stack two elements, into
  Row evaluates//then pushes the current operator into the stack.
    $scope. Operation=function (current) {//If the operator stack is empty, directly into the stack if (! $scope. opt.length) {$scope. Opt.push (!).
   Return
   } var Operator,right,left;
   var lastopt= $scope. opt[$scope. opt.length-1];
   If the current operator precedence is greater than the last operator, only stack if ($scope. ISPRI (current,lastopt)) {$scope. Opt.push
     else{operator= $scope. Opt.pop ();
     right= $scope. Num.pop ();
     left= $scope. Num.pop ();
     $scope. Calculate (Left,operator,right);
    $scope. Operation (current); 
}
  };

The method accepts the currently entered operator as a parameter, and its core idea is that an operator is currently received, and if the operator stack is empty, the current operator is pushed into the stack, and then there is no need to do anything about it. If the current operator stack is not empty, the stack top element of the current operator stack is ejected, giving the currently received operator and the stack top operator precedence (multiplication and division priority is greater than plus minus, and the top operator priority is higher in the case of the same priority, because the stack is first entered). The Ispri method is used to judge the priority, receives two parameters, the first is the currently received operator, the second is the stack-top operator for the stack, and if the current operator has a higher priority according to the preceding rules, the operator is put directly into the stack. If the current operator priority is less than the stack top operator, then you need to compute and change the calculator's display, and then pop up the two elements of the counting stack, respectively, as the two operands of the operation, and then eject the stack top element of the operator stack as the operator of this operation. Calling the Calculate method for operations

The method code is as follows

 Responsible for calculating the result function
  $scope. Calculate=function (left,operator,right) {
   switch (operator) {case
    "+":
     $ Scope.result = $scope. Format (number (left) + number (right);
     $scope. Num.push ($scope. result);
     break;
    Case "-":
     $scope. result = $scope. Format (number (left)-number (right));
     $scope. Num.push ($scope. result);
     break;
    Case "x":
     $scope. result = $scope. Format (number (left) * Number (right));
     $scope. Num.push ($scope. result);
     break;
    Case "A":
     if (right==0) {
      $scope. result= "Error";
      $scope. Init ();
     else{
      $scope. result = $scope. Format (number (left)/number (right);
      $scope. Num.push ($scope. result);
     break;
    Default:break;
   }
  ;

This method accepts three parameters, the left operand, the middle operator and the right-hand operation number, changes the result display results after the subtraction method operation and calculates the result into the stack into the operand stack, where it is necessary to note that if the operation is division and the divisor is 0, an error occurs, displays the error, clears all States, otherwise normal operation.

After the completion of an operation, the operator stack and the state of the digital stack will be changed, and the current value of the key is not in the stack, so repeat the above process for priority comparison in the operation, is actually a recursive process, Until the operator stack is empty or the current operator has a higher precedence than the stack top operator of the operators stack. The Ispri method is used to determine operator precedence.

The code is as follows:

 Determines whether the current operator has precedence over last, and returns true
  //or False
  $scope. Ispri=function (current,last) {if
   (current==last) { return
    false;
   }
   else {
    if (current== "x" | | current== ""] {
     if (last== "x" | | last== "=") {return
      false;
     }
     else{return
      true;
     }
    }
    else{return
     false;}}
  ;

The rules of judgment are described earlier.

In addition, there checkOperator is a way to determine whether the input symbol is subtraction arithmetic symbol

The code is as follows:

 Determines whether the current symbol is an operational symbol
  $scope. Checkoperator=function (opt) {
   if (opt== "+" | | opt== "-" | | opt== "X" | | opt== "") {return
    true;
   }
   return false;
  }

Returns true if it is, otherwise returns false.

So far, there's also a branch with an input equal number that doesn't

Its code is as follows (Showresult method)

 If clicking is equal number
  else if (a== "=" && $scope. result!= "" && $scope. result!= "Error") {
   $scope. flag= false;
   $scope. Num.push ($scope. result);
   while ($scope. opt.length!=0) {
    var operator= $scope. Opt.pop ();
    var right= $scope. Num.pop ();
    var left= $scope. Num.pop ();
    $scope. Calculate (Left,operator,right);
   }
  }
 ;

If you enter an equals number, first set the flag to false, allowing the interface to be displayed again the next time you enter a number, and the current displayed number as the operand into the stack. Then it is necessary to continue the stack operation until the operator stack is empty to be able to stop.

Summarize

The above is the implementation of the main code and process, because the branch code more and all the branches are not able to detail, so the Showresult method is separated, may look not too adapt. Due to the haste of writing and not spending too much time to test, there may be some bugs, welcome to point out. At the same time because the level is limited, perhaps this method is not the best, welcome to a better program to Exchange learning ~ ~ above is the entire content of this article, I hope that everyone's study or work to bring certain help.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.