Moje zdjęcie
Software Craftsman's Blog by Marcin Pieciukiewicz
Java and Scala development

Monday, August 26, 2013

Writing a simplified JSON parser in Clojure

Today I want to write a step by step example of creating a parser for JSON. What is extraordinary, I'll use a Clojure to do that. This is because I have to learn Clojure for my current job and I think parsing problem is very good for this, due it's complexity and usefulness.

What is Clojure? Basically it is a programming language that is a dialect of another language called Lisp. And it is targeted for Java Virtual Machine. Here is some minor description from clojure.org:

Clojure is predominantly a functional programming language, and features a rich set of immutable, persistent data structures.

For those that aren't familiar with Clojure this article might be too difficult, because Clojure has a tremendously different syntax than ie. Java or Scala. In that case it would be better to start with some other tutorial that covers Clojure basics or with some book, ie. "Practical Clojure". I found that book to be a very good, easy to read and a comprehensive introduction to the language.

Enough introduction, let's go to our parser problem.

Define parser requirements
We want to write a JSON parser. Why JSON? I've chosen it because of a couple of reasons. First it is very popular in many commercial usages (ie. RESTful services or NoSQL databases), on the second hand it has very simple syntax so it will be good for training.

JSON syntax is defined on a page www.json.org. So basically in JSON we could have 6 different value types:
  1. Object - wrapped in curly brackets, properties separated by commas and values separated from properties names separated with colon. ie. {name:"Marcin", surname:"Pieciukiewicz"}
  2. Array - wrapped in square brackets, values separated with commas, ie. ["dog","cat","cow"]
  3. String - sequence of characters wrapped in double quotes, ie. "dog"
  4. Number
  5. Boolean - true or false
  6. Null - null
For our purpose I would like to make some simplifications to the syntax, so we could focus on general parsing problems:
  1. No white characters are allowed (outside a string)
  2. Number can be non negative integer only
  3. String cannot contain double quotes and escape character won't be supported, so "\" will be treated as normal character
  4. Parsed JSON is always correct
All those simplifications are introduced so our parser could be simple enough to well fit in this article.

Parsing based on sequence traversing
Clojure provides us with a powerful sequence mechanism and we will use it to traverse through a JSON string. You can imagine that we want to have a cursor over a JSON string that will be used to read subsequent characters, and it will only move forward (from the beginning of the json string, to the end).
To do so we'll have to utilize two commands:
(first some-string)
and
(rest some-string)
first command simply returns first element from the given sequence, and rest command returns a sequence of the elements after the first element. We'll use this commands extensively mainly in recursive operations. It's important to notice that first and rest functions work on sequence passed as parameter, in our case this functions implicitly converts passed string into a sequence.

To understand better how we'll utilize those functions this is a simple example of printing every character from stream in separate line:
(defn print-in-lines [text]
  (if (not (empty? text))
    (do
      (println (first text))
      (recur (rest text)))))
This function first checks if given text is not empty and, if so, it prints out the first character of text and then calls itself recursively with text parameter stripped of the first character.

Detect element type
Because our parser will traverse json string only once we need to detect what kind of element is going to be next. To do that we'll define a set of functions that will check the first character from json sequence and compare it with a character from JSON syntax. Ie. we want to be able to detect beginning of an object. To do so we'll define is-object-opening? function:
(defn is-object-opening? [json] (= \{ (first json)))
As you can see (which might be hard in Clojure ;)) this function takes a json sequence and checks if it's first character is an opening curly bracket “{“. And in the end it returns boolean value. Also we would like to know when this object ends, so let's define function to detect closing curly bracket:
(defn is-object-ending? [json] (= \} (first json)))
This is very simple, so let's define this kind of functions for array and string detection:
(defn is-array-opening? [json] (= \[ (first json)))
(defn is-array-ending? [json] (= \] (first json)))

(defn is-string-opening? [json] (= \" (first json)))
(defn is-string-ending? [json] (= \" (first json)))
Also we'll need to detect integers, boolean values and nulls. To do that we'll assume that integer value starts with a digit from 0 to 9, boolean value starts with lowercase 't' (for true) or lowercase 'f' (for false), and null starts with lowercase 'n'. Now we can define functions that will detect those values:
(defn is-boolean-opening? [json] (or (= \t (first json)) (= \f (first json))))

(defn is-null-opening? [json] (= \n (first json)))

(defn is-digit? [json]
  (and
    (>= (int (first json)) (int \0))
    (<= (int (first json)) (int \9))))

(defn non-digit? [json]
  (not (is-digit? json)))
As you can see I haven't defined functions that detects the end of boolean or null value. That is because we exactly know what values can start with 't', 'f' or 'n' and in particular how long they are. And we'll use this knowledge later.
For integers instead of creating is-integer-opening? and is-integer-ending? I've created more generally named functions that do exactly the same thing.

Parsing primitive values - number, string, boolean and null
When we know what is going to be next in the sequence we want to parse it. We'll start with a basic types, object and array we'll leave for later.
So we need to create a function for each type that will return a parsed value, and, evenly important, a new sequence that is pointing just after parsed value. You can think about it as returning new cursor position in json text.

Parsing string.
String parsing is about reading our json stream until we occur double quote symbol. We'll do that recursively (tail-recursive). What is important, we assume that json sequence passed to this function doesn't start with opening double quote, because it was "consumed" when we checked value type. This is parse-string function implementation (in first call string is initialized to an empty string ""):
(defn parse-string [json string]
  (if (is-string-ending? json)
    [string (rest json)]
    (recur (rest json) (str string (first json)))))
As you can see we check first character of json to see if we should finish parsing. If so we return string (which is our accumulator of read value) and the remaining json sequence. We've used rest function to skip closing double quote character. Otherwise, if we haven't found double quote, we remove first character of passed sequence and concatenate current string value with first character in current sequence and make a recursive call to parse-string function.

Parsing number.
Number parsing is very similar to string parsing. We simply read subsequent character until it's not a digit, and meanwhile we increase an accumulated value (in first call number have to be initialized to zero):
(defn char-to-number [character]
  (- (int character) (int \0)))

(defn parse-number [json number]
  (if (non-digit? json)
    [number json]
    (recur (rest json) (+ (char-to-number (first json)) (* number 10)))))
To convert a digit character into corresponding numerical value I've created char-to-number function that simply casts character into ASCII integer value and calculate difference between that value and integer value of '0' character.

Parsing boolean.
To parse a boolean we'll just have to check the first letter. If it is 't' the value is 'true', if the first letter is 'f' the boolean value is 'false'. Now implementation of parser function is very simple:
(defn parse-boolean [json]
  (if (= \t (first json))
     [true (drop 4 json)]
     [false (drop 5 json)]
    )
  )
We don't have to detect where the value string ends because we know that true is 4 characters long, and false is 5 characters long, so we'll just drop corresponding number of characters from json sequence.
To be clear, we could do that because we assumed that json we are parsing is correct.

Parsing null.
Parsing null value is even simpler than parsing a boolean value. Because we'll call our parse-null function after we detected null value, we'll only need to skip 4 characters from json sequence and return nil:
(defn parse-null [json]
    [nil (drop 4 json)]
  )
Call a parse function for a detected type
Now we have to combine our detection of element type with proper parse function. To do that we'll create parse-value function (because everything is a value ;)):
(declare parse-object parse-array)

(defn parse-value [json]
  (cond
    (is-digit? json) (parse-number json 0)
    (is-boolean-opening? json) (parse-boolean json)
    (is-null-opening? json) (parse-null json)
    (is-string-opening? json) (parse-string (rest json) "")
    (is-object-opening? json) (parse-object (rest json) {})
    (is-array-opening? json) (parse-array (rest json) [])
    :else (println "Incorrect character?")))
Also we've declared parse-object and parse-array functions, so parse-value function would compile. We'll implement those functions later.

Parse array
Array parsing will be a little more complex. Basically we need to read elements separated by comma character, until we occur closing square bracket “]” that is closing the array. We'll do that by recursively calling our array-parse function and in each run it will read one element of the array. This is the implementation:
(defn drop-comma-if-first [json]
  (if (= \, (first json))
    (rest json)
    json))

(defn parse-array [json array]
  (if (is-array-ending? json)
    [array (rest json)]
    (let
      [value-result (parse-value (drop-comma-if-first json))
       value (nth value-result 0)
       rest-json (nth value-result 1)]
      (recur rest-json (conj array value)))))
As you can see we simply stop the recursion when the first element of json stream is “]” character (is-array-ending? function). If not, we have to read element value and to do that we'll use parse-value function. There is also drop-colon-if-first function used - it simply skips the first colon in json sequence if it is present, this is the case when we want to read second or subsequent element from array and we need to skip separator.

Also in parse-array function we use let statement so we can acquire result of parse-value function that is a vector containing parsed value, and also the new json stream that points just after parsed value. After that we simply call parse-array function recursively with new json stream and array with added value we've just parsed (we've used conj function to do that).

Parse object
Object parsing is very similar to array parsing, with the difference that we also need to parse the key name of the value. To do that we have to introduce a method that will be responsible for parsing of that key:
(defn parse-property-name [json name]
  (if (= \: (first json))
    [name json]
    (recur (rest json)
           (str name (first json)))))
It works alike parse-string function, but instead of looking for double quote it is looking after colon to check if the name has ended. Next, let's look at the implementation of parse-object function:
(defn parse-object [json object]
  (if (is-object-ending? json)
    [object (rest json)]; rest to skip closing '}'
    (let
      [property-name-result (parse-property-name (drop-comma-if-first json) "")
       property-name (nth property-name-result 0)
       value-json (rest (nth property-name-result 1))
       value-result (parse-value value-json)
       value (nth value-result 0)
       rest-json (nth value-result 1)]
      (recur rest-json (assoc object property-name value)))))
As you can see it has very similar construction to parse-array function. In let statement it calls parse-property-name function, remembers it's result, then calls parse-value function. Also it uses assoc function to add new property to constructed object.

Main parser function
The last thing to do is to create a main function that can be access point to our parser:
(defn parse-json [json]
  (nth (parse-value json) 0))
It simply calls parse-value function and from it's result extracts first element which is a parsed element. That's all.

Summary
I hope that this example showed that Clojure is a good way to solve more complex problems, such as string parsing. It might not be a best language to do so, but it is not a great struggle to work with it either. For sure Clojure will force you to think differently than Java and this might be it's greatest advantage.

Source code with full solution is available on gist.github.com: json_parser.clj.

Wednesday, August 21, 2013

Scalatra - How to setup with Maven and Jetty

Recently I was inspired by a colleague to dig into AngularJS and Scalatra web application stack, so today I'll continue with first steps in digging into Scalatra.

Description from www.scalatra.org:
Scalatra is a simple, accessible and free web micro-framework.
It combines the power of the JVM with the beauty and brevity of Scala, helping you quickly build high-performance web sites and APIs.

And when you look at examples you can get feeling that this might be a great framework to help you develop your applications quickly:
package com.example.app
import org.scalatra._

class HelloWorldApp extends ScalatraFilter {
  get("/") {
    <h1>Hello, {params("name")}</h1>
  }
}

So let's start playing with it by creating a sample project that will use Maven as the build tool and a Jetty server as our application's container.

1. Define build process and application dependencies
To start we need to create main pom.xml file required by maven. It will be placed in the main directory we've created for our project.
First we need to configure it to properly compile Scala language sources. I have described this process in article Maven configuration example for Scala. So you should follow instructions from that article.

When this is done we'll add support for Scalatra. To do that we'll need to include org.scalatra:scalatra dependency in pom.xml. Also let's include library org.scalatra:scalatra-specs2 that will add support for writing tests in the future. So add this part of code inside <dependencies> tag (To be clear, I've used a Scalatra dependencies prepared for Scala 2.10, this is the reason for weird suffixes in artrifactId):
<!-- Scalatra -->
<dependency>
    <groupId>org.scalatra</groupId>
    <artifactId>scalatra_2.10</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.scalatra</groupId>
    <artifactId>scalatra-specs2_2.10</artifactId>
    <version>2.2.0</version>
    <scope>test</scope>
</dependency>

Also Scalatra requires that Java Servlet API 2.5 be available during application compilation, so we'll add it in provided scope:

<!-- Servlet API -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

That will be all to support Scalatra in our application, now let's add Jetty so we'll be able to run our application without any external application server. This only requires to add a plugin inside a <build> -> <plugins> tag:
<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.0.2.v20130417</version>
</plugin>
Now the configuration of our build process is complete. To summarize this is my complete pom.xml for this example:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>pl.marpiec</groupId>
    <artifactId>scalatratest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>war</packaging>

    <properties>
        <scala.lang.version>2.10.1</scala.lang.version>
        <scala.maven.version>2.10.1</scala.maven.version>
        <scalatra.version>2.2.0</scalatra.version>
        <jetty.version>9.0.2.v20130417</jetty.version>
    </properties>

    <repositories>
        <repository>
            <id>scala-tools.org</id>
            <name>Scala-tools Maven2 Repository</name>
            <url>https://oss.sonatype.org/content/groups/scala-tools/</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>scala-tools.org</id>
            <name>Scala-tools Maven2 Repository</name>
            <url>https://oss.sonatype.org/content/groups/scala-tools/</url>
        </pluginRepository>
    </pluginRepositories>


    <dependencies>
        <!-- Scala -->
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>${scala.lang.version}</version>
        </dependency>

        <!-- Scalatra -->
        <dependency>
            <groupId>org.scalatra</groupId>
            <artifactId>scalatra_2.10</artifactId>
            <version>${scalatra.version}</version>
        </dependency>
        <dependency>
            <groupId>org.scalatra</groupId>
            <artifactId>scalatra-specs2_2.10</artifactId>
            <version>${scalatra.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>${scala.maven.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>${jetty.version}</version>
            </plugin>
        </plugins>
    </build>
</project>

2. Configure web application by web.xml file
To be able to run our web application we need to create a standard Java web application description file, web.xml. Let's create this file inside [Project Dir]\src\main\webapp\WEB-INF\ directory. It's content is very simple:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <context-param>
        <param-name>org.scalatra.LifeCycle</param-name>
        <param-value>pl.marpiec.scalatratest.servlets.ScalatraBootstrap</param-value>
    </context-param>
    <listener>
        <listener-class>org.scalatra.servlet.ScalatraListener</listener-class>
    </listener>
</web-app>
This will tell an application's server (Jetty in our case) that it have to call a ScalatraListener when application starts. Also context parameter org.scalatra.LifeCycle points to the ScalatraBootstrap class that will be used by our application. This parameter is not required, but without it you will have to put ScalaBootstrap class in root package, and that would be ugly. Also, you probably want to change the package name that is used to be align with your project ;).

3. Create your first Scalatra servlet
So now let's create our first servlet that will send simple responses for GET requests. This servlet might look like this:
package pl.marpiec.scalatratest.servlets

import org.scalatra.ScalatraServlet

/**
 * @author Marcin Pieciukiewicz
 */
class MainServlet extends ScalatraServlet {
  get("/") {
    <html>
      Hello to scalatra
    </html>
  }

  get("/json-page") {
    "<json-response>Hello to scalatra</json-resonse>"
  }
}
As you can see this servlet will send an html response for the request of root application address, and it will send string containing json if /json-page is requested.

4. Create ScalatraBootstrap class
The last thing to do is to create a class mentioned earlier: ScalatraBootstrap, and then bind our servlet with proper URL path:

package pl.marpiec.scalatratest.servlets

import org.scalatra._
import javax.servlet.ServletContext

class ScalatraBootstrap extends LifeCycle {
  override def init(context: ServletContext) {
    context.mount(new MainServlet, "/*")
  }
}

This class is basicly starting point for scalatra configuration. In our case we've just added our server to be mapped for all url suffixes.

And now our sample application is complete.

5. Test application
To test this application we have to run it on servlet container, and as it was mentioned earlier we'll use Jetty runned as Maven plugin. So to start our server with our application just run:
mvn jetty:run
After a while a Jetty server will be running and listening on port 8080 on localhost. So just check the responses under http://localhost:8080:


And http://localhost:8080/json-page:







Sunday, August 18, 2013

AngularJS example - simple calculator

Recently my attention was focused on a very interesting JavaScript framework named AngularJS. It is a framework created by Google to augment creation of rich browser-based application. In this article I would like to present an example of application created with AngularJS that will use some of the features provided by this framework. Of course I've just began to learn AngularJS so this article contains examples of basic concepts used by AngularJS.

1. Application concept
Our application will be a very simple calculator, that provides the four basic mathematical operations, and it will work on integer numbers. The expected layout should be like that:



2. Download AngularJS framework
AngularJS framework is distributed as a single JavaScript file and can be acquired on the angularjs.org page. Just choose stable and mininified version of the file. It will be named angular.min.js. When I was writing this article the stable version was 1.0.7.

3. Create an application's structure
Our application will be organized in this directory structure:
Calculator             Main project directory
|--lib                      
|  |--js                    JavaScript 3rd party libraries
|--app
   |--js                    JavaScript application source files
   |--style                 CSS files
   |--view                  HTML files
When the application's structure is created, then we copy downloaded angular.min.js file into Calculator/lib/js directory.
Then let's create basic source files that will define our application. We'll need three of them:
  • Calculator/index.html - root view layer file of our application
  • Calculator/app/js/app.js - main source file, will put logic in this file
  • Calculator/app/style/default.css - main cascading style file

4. Create AngularJS application
In next step we'll create an html skeleton for our application that will define basic html properties and include our source files. So the content of index.html should look like that:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html ng-app="calculatorApplication">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script src="lib/js/angular.min.js" type="text/javascript"></script>
    <script src="app/js/app.js" type="text/javascript"></script>
    <link href="app/style/default.css" rel="stylesheet" type="text/css">
</head>
<body>

<div ng-view></div>

</body>
</html>
Beside the standard html header there are two elements that are specific to AngularJS application:
  • <html ng-app="calculatorApplication"> 
  • It tells AngularJS that everything inside html tag is an AngularJS controlled application. And it is a module called "calculatorApplication".
  • <div ng-view></div>
  • This ng-view attribute points to the element that will be a container, where AngularJS will put created view.
As you can see a framework extends a standard HTML with its' own attributes that can be interpreted by AngularJS internals.

After creating HTML structure of our application we have to add some behavior. We'll do that by editing app.js file and adding there this part of code:
var app = angular.module("calculatorApplication", []);
This construct will create AngularJS module called calculatorApplication. Empty square brackets stands for empty list of dependencies that our application will require.
In the next step we would like to define some basic behavior for our application. Basically we want our application to have a home page that will have a welcome message and a link to our calculator.
That page should look like that:

As you can see the url for this page have an interesting #/home suffix. Basically it is an address of our application subpage. This is a standard way to define subpages in AngularJS. Now we would like to bind this /home suffix with some content. So let's add a controller definition of this page by changing app.js content into this:
var app = angular.module("calculatorApplication", []).config(function ($routeProvider) {
    $routeProvider.when("/home", {
        templateUrl: "app/view/home.html",
        controller: "HomeController"
    });

    $routeProvider.otherwise({
        redirectTo: "/home"
    });
});

app.controller("HomeController", function () {
});
A few things are happening in this part of code. First we've called config method and passed a function that will configure our application. This function takes a parameter $routeProvider which is responsible for binding url address (ie. /home suffix) with a proper behavior. In our case we want it to use a home.html template for the view and HomeController when there is /home suffix present. In any other case we want our application to redirect to that address. Also we've defined a controller that is called HomeController with no specific behavior.
The last thing we need to do is to create a template for our home page. So create a file Calculator/app/view/home.html and put this content inside it:
<div>
    <div>
        This is home page:
    </div>
    <div>
        You can go to <a href="#/calculator">Calculator</a>.
    </div>
</div>
As you can see it is very simple html code that will display a message and a link to the calculator page (the page we havn't created yet).

5. First try out of an application
Now you can try to run this application. You can do this in two ways:
  • Deploy it on http server and go to url of index.html file
  • Open index.html directly from your file system
For now, the latter one will be an easier solution ;)

Attention!
Because of security reasons some browsers can block a javascript to access local files through AJAX request. This is the case at least for a Chrome and an Internet Explorer. I don't know the solution for an IE but if you want to test it in a Chrome you have to run the browser with --allow-file-access-from-files parameter as stated on this stackoverflow question. It should not be the case if you deploy your application in http server.
For a Firefox browser our application should work flawlessly.

6. Add calculator page
To add a calculator to our application first we need to create an html template that will define ours calculator's view. We'll put it inside Calculator/app/view/calculator.html file:
<div class="calculator">
    <div class="display">0</div>
    <div class="digitsKeyboard">
        <div class="digitKey">1</div>
        <div class="digitKey">2</div>
        <div class="digitKey">3</div>
        <div class="digitKey">4</div>
        <div class="digitKey">5</div>
        <div class="digitKey">6</div>
        <div class="digitKey">7</div>
        <div class="digitKey">8</div>
        <div class="digitKey">9</div>
        <div class="digitKey">0</div>
        <div class="equalSignKey">=</div>
    </div>
    <div class="operationsKeyboard">
        <div class="operationKey">/</div>
        <div class="operationKey">*</div>
        <div class="operationKey">+</div>
        <div class="operationKey">-</div>
    </div>
</div>
So basically in our calculator we'll have a display, a keyboard with digit keys and an equal sign key, and a keyboard with possible mathematical operations. We also have to provide a stylesheet for our calculator so it can look properly. So put this CSS inside Calculator/app/style/default.css file:
.calculator {
    display: inline-block;
    background-color: black;
    height: 240px;
    width: 208px;
    overflow: hidden;
}

.display {
    background-color: #DDDDDD;
    border: 1px solid black;
    font-family: monospace;
    font-size: 27px;
    font-weight: bold;
    height: 30px;
    padding: 0 4px;
    text-align: right;
    width: 198px;
    overflow: hidden;
}

.digitsKeyboard {
    overflow: hidden;
    width: 156px;
    float: left;
}

.digitKey {
    width: 50px;
    height:50px;
    background-color: #AABBCC;
}

.equalSignKey {
    width: 102px;
    height: 50px;
    background-color: #AACCBB;
}

.operationsKeyboard {
    overflow: hidden;
    width: 52px;
    height:208px;
    float: left;
}

.operationKey {
    width: 50px;
    height:50px;
    background-color: #CCAABB;
}

.digitKey, .equalSignKey, .operationKey {
    cursor: pointer;
    font-family: monospace;
    font-size: 33px;
    border: 1px solid black;
    line-height: 50px;
    text-align: center;
    float: left;
}

.digitKey:hover, .equalSignKey:hover, .operationKey:hover {
    opacity: 0.8;
}
.digitKey:active, .equalSignKey:active, .operationKey:active {
    opacity: 0.7;
}

The last thing we have to do is to map a /calculator address in our application. So we need to add a calculator page to $routeProvider in exactly the same way we've defined a home page. So add this inside Calculator/app/js/app.js file:
$routeProvider.when("/calculator", {
    templateUrl: "app/view/calculator.html",
    controller: "CalculatorController"
}); 
And also define new empty controller for Calculator:
app.controller("CalculatorController", function () {
});
Now you can try to access calculator page in your browser. Just open the index.html file and click on the calculator link. Then you should see a calculator on the screen.

7. Define calculator constants
Now we'll add some juice to our CalculatorController. To do that let's start by changing the factory function declaration for the controller:
app.controller("CalculatorController", function ($scope) {
});
As you can see we've added a $scope parameter to a function definition. It is an object where our application state is held. For our purpose you just need to know that you can define any field inside the $scope object and it will be accessible in other places in an application.

So let us start with defining a keys of calculator with the required properties by putting this code inside controller's function.
$scope.digitKeys = [
    {label: "1", value: 1}, {label: "2", value: 2}, {label: "3", value: 3},
    {label: "4", value: 4}, {label: "5", value: 5}, {label: "6", value: 6},
    {label: "7", value: 7}, {label: "8", value: 8}, {label: "9", value: 9},
    {label: "0", value: 0}
];
We'll use digitKeys field to define an array of objects that represent every digit key in calculator keyboard. Every key has a label property that will be displayed on given key and a value that will be used for computation.
$scope.equalSignKey = {label: "="};
Here we only need a label for equal sign key. This code is placed here only to be consistent with other keys definitions. Other solution would be just to place equal sign directly inside html file.
$scope.operationKeys = [
    {label: "/", operation: function (a, b) {return a / b}},
    {label: "*", operation: function (a, b) {return a * b}},
    {label: "+", operation: function (a, b) {return a + b}},
    {label: "-", operation: function (a, b) {return a - b}}
];
And the last set of keys are the mathematical operation keys. As you can see we put the operation function inside every object, so that will give us easy access to them, when we'll want to call it.

8. Make calculator rendered dynamically
When we defined our buttons in CalculatorController we can use them to simplify our html template and generate buttons dynamically. Let's start with the easiest case of equal sign key:
<div class="equalSignKey">
    {{ equalSignKey.label }}
</div>
In this case we used {{ }} placeholder to tell AngularJS that we want to put equalSignKey.label value in this place. Angular will look for that value within the $scope object and it will bind it with a corresponding part of an html file.

We'll do similar thing with digit buttons, but we'll use an AngularJS directive named ng-repeat that allow us to iterate over array elements and repeat an html tag for every element in array:
<div class="digitKey" ng-repeat="key in digitKeys">
    {{ key.label }}
</div>
In this case AngularJS iterates over $scope.digitKeys array and puts current element inside a key variable. That way we don't have to repeat html code for every key.

We'll do exactly the same operation for operations keys:
<div class="operationKey" ng-repeat="key in operationKeys">
     {{ key.label }}
</div>
So the resulting calculator.html file should look like that:
<div class="calculator">
    <div class="display">0</div>
    <div class="keyboard">
        <div class="digitKey" ng-repeat="key in digitKeys">
            {{ key.label }}
        </div>
        <div class="equalSignKey" ng-click="compute()">
            {{ equalSignKey.label }}
        </div>
    </div>
    <div class="operations">
        <div class="operationKey" ng-repeat="key in operationKeys">
            {{ key.label }}
        </div>
    </div>
</div>

Now you can test the application to check if it still displays properly.

9. Add calculator behavior
Now we want to make our calculator to behave as real calculator so we'll need to define a variables that will hold a current calculator state. We'll need 5 of those:
  • displayValue - current value displayed on calculator screen
  • valueA - first (left) value that will be used for computation
  • valueB - second (right) value that will be used for computation
  • selectedOperation - which mathematical operation was chosen by the user
  • clearValue - should value displayed on screen be cleared after new digit pressed?
So let's define them and initialize them with default values. Add this code inside a CalculatorController:
$scope.displayValue = 0;
$scope.valueA = 0;
$scope.valueB = 0;
$scope.selectedOperation = null;
$scope.clearValue = true;

10. Bind displayValue variable with view
As we now have a variable displayValue, we would like it to be displayed in our calculator. And in this place best of AngularJS comes in. To do that just put a {{ displayValue }} placeholder inside a calculator.html changing <div class="display">0</div> so it will look like this:
<div class="display">{{ displayValue }}</div>
That's all!
Now AngularJS we'll do it's tricks to ensure that value displayed on page is equal to the value of the variable. If you change the variable value, then automatically the value displayed on the page will be changed to be the same as the variable.
And that's not all, imagine if display would be editable input field, then when user would input some value inside it, then automatically the value of the binded variable would be changed as well. So it works both ways and it's hugely simplifies development of an application.

11. Add behavior to calculator's buttons
We have all parts of our calculator in place, so now it's time to add a behavior to it. So the main idea is to bind a buttons with correct behavior. To do this with AngularJS we'll use ng-click directive. So let's change the calculator.html template:

<div class="calculator">
    <div class="display">{{ displayValue }}</div>
    <div class="digitsKeyboard">
        <div class="digitKey" ng-repeat="key in digitKeys" 
                ng-click="digitClicked(key.value)">
            {{ key.label }}
        </div>
        <div class="equalSignKey" ng-click="compute()">
            {{ equalSignKey.label }}
        </div>
    </div>
    <div class="operationsKeyboard">
        <div class="operationKey" ng-repeat="key in operationKeys" 
                ng-click="operationClicked(key.operation)">
            {{ key.label }}
        </div>
    </div>
</div>

In this part of code we've added three ng-click directives that contains simple JavaScript function calls:
  • For a digit key: ng-click="digitClicked(key.value)"
  • For an operation key: operationClicked(key.operation)"
  • For an equal sign key: ng-click="compute()"
As you can see we could pass a data defined earlier in AngularJS variables in the same way as we've passed them earlier into {{ }} blocks. The main idea for those changes is to call a corresponding function after clicking on a button.

Now let's define those three functions inside CalculatorController. It is important to notice that those functions have to be defined as a part of $scope object:
  • Function to handle digit button click:
$scope.digitClicked = function (digit) {
    if ($scope.clearValue) {
        $scope.displayValue = digit;
        $scope.clearValue = false;
    } else {
        $scope.displayValue = $scope.displayValue * 10 + digit;
    }
    $scope.valueB = $scope.displayValue
};
After user clicks a digit button, we want to update displayed value by replacing displayed value with digit, or by increasing displayed value by that digit (it's simple, just scale previous value by the factor of 10 and then add clicked digit). Also we need to remember displayed value as second value for the mathematical operation.
  • Function to handle operation button click:
$scope.operationClicked = function (operation) {
    $scope.selectedOperation = operation;
    $scope.valueA = $scope.displayValue;
    $scope.valueB = $scope.displayValue;
    $scope.clearValue = true;
};
When user clicks operation button we simply want to remember clicked operation, and assign currently displayed value as both values for mathematical operation. Also we need to set clearValue flag, so when user clicks on digit button, the displayed value will be replaced by selected digit, not increased by it.
  • Function to handle equal sign button click:
$scope.compute = function () {
    if($scope.selectedOperation != null) {
        $scope.displayValue = Math.floor(
                       $scope.selectedOperation($scope.valueA, $scope.valueB));
        $scope.clearValue = true;
        $scope.valueA = $scope.displayValue;
    }
}
The last function main responsibility is to calculate a result if an operation is selected (assigned to $scope.selectedOperation field). It is done by simple call of remembered function. Also clearValue flag is set and a computation result is remembered as first value of new operation.

Summary
This is all, now we have a fully functional calculator for internet browsers.
As you can see AngularJS is an easy to use (at least for an online calculator) and quite powerful framework for JavaScript application development. It brings a new way to bind an application state with html based view layer, that greatly simplifies creation of JavaScript applications.

The complete source code of this calculator is available at github.com.