aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth R. Culp2011-04-26 09:54:08 -0700
committerIgor Minar2011-06-06 22:28:37 -0700
commit0a604bdb90e9dff9399bae0fb4941fe46cc7e9f9 (patch)
tree48e2725daa8d168bb9cf24c4b89e50332346c23c
parent4738d49e1c76b1762c05a21735d5eecd923aee13 (diff)
downloadangular.js-0a604bdb90e9dff9399bae0fb4941fe46cc7e9f9.tar.bz2
Tutorial files for your perusal.
-rwxr-xr-xdocs/tutorial.ngdoc87
-rwxr-xr-xdocs/tutorial.step_1.ngdoc86
-rw-r--r--docs/tutorial.step_10.ngdoc109
-rw-r--r--docs/tutorial.step_11.ngdoc113
-rwxr-xr-xdocs/tutorial.step_2.ngdoc133
-rwxr-xr-xdocs/tutorial.step_3.ngdoc104
-rwxr-xr-xdocs/tutorial.step_4.ngdoc114
-rwxr-xr-xdocs/tutorial.step_5.ngdoc109
-rwxr-xr-xdocs/tutorial.step_6.ngdoc101
-rwxr-xr-xdocs/tutorial.step_7.ngdoc159
-rwxr-xr-xdocs/tutorial.step_8.ngdoc110
-rwxr-xr-xdocs/tutorial.step_9.ngdoc95
-rw-r--r--docs/tutorial_intro.ngdoc155
13 files changed, 1475 insertions, 0 deletions
diff --git a/docs/tutorial.ngdoc b/docs/tutorial.ngdoc
new file mode 100755
index 00000000..41b53ccf
--- /dev/null
+++ b/docs/tutorial.ngdoc
@@ -0,0 +1,87 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial
+@description
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">Previous</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-0/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">Code Diff</td>
+<td id="next_step">{@link tutorial.step_1 Next}</td>
+</tr>
+</table>
+
+Welcome to the angular tutorial! Before you begin, you can check out the finished app here:
+{@link http://angular.github.com/angular-phonecat/step-11/app/ The Completed Tutorial App}. Also,
+if you missed the {@link tutorial_intro Intro to Tutorial} doc, it provides some background info,
+and describes different options you have in working through the tutorial.
+
+We'll begin the tutorial by creating a basic page, and then we'll add functionality to our app on
+each subsequent step.
+
+# Step 0
+The following sample code is our starting point. It is a static HTML page that displays next to
+nothing, but it has everything we need to proceed. You can think of this bit of code as our
+prototype template, consisting of basic HTML tags and some key angular {@link angular.directive
+directives}.
+
+__`app/index.html`:__
+<pre>
+<!doctype html>
+<html xmlns:ng="http://angularjs.org/">
+<head>
+ <meta charset="utf-8">
+ <title>my angular app</title>
+ <link rel="stylesheet" href="css/app.css"/>
+</head>
+<body>
+
+ Nothing here yet!
+
+ <script src="lib/angular/angular.js" ng:autobind></script>
+</body>
+</html>
+</pre>
+
+## Discussion:
+
+Although our app doesn't appear to do anything dynamic, note the following:
+
+* __... `xmlns:ng="http://angularjs.org"` ...__ This `xmlns` declaration for the `ng` namespace
+must be specified if you use XHTML, or if you are targeting IE older than 9 (regardless of whether
+you are using XHTML or HTML).
+
+* __`<script src="lib/angular/angular.js"` ...__ This downloads the `angular.js` bootstrap script
+and registers a callback that will be executed by the browser when the HTML is fully downloaded.
+When the callback is executed, angular looks for the {@link angular.directive.ng:autobind
+ng:autobind} attribute. If `ng:autobind` is found, it signals angular to compile and manage the
+whole page.
+
+ Note: If you elected not to download any tutorial files but still want to try out some angular
+ code on your system, you can change the relative path to the `angular.js` script in your
+ template from `./lib/angular/angular.js` to the following:
+
+ <script src="http://code.angularjs.org/angular-0.9.14.js" ng:autobind></script>
+
+ This will bootstrap angular from the angular server instead of from a local file.
+
+* To try this code out in your browser, you need to navigate to the step-0 page (you are currently
+on Step 0 of the tutorial). If your http server is running, navigate to `app/index.html`.
+Remember, this is a relative URL (see the Relative URL section in {@link tutorial_intro Intro to
+Tutorial}). The browser will display the same thing as you would see if you go to
+http://angular.github.com/angular-phonecat/step-0/app (accessible from Example at the bottom of
+the page).
+
+Now we can move on and add some content to our developing web app.
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">Previous</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-0/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">Code Diff</td>
+<td id="next_step">{@link tutorial.step_1 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_1.ngdoc b/docs/tutorial.step_1.ngdoc
new file mode 100755
index 00000000..02688f2e
--- /dev/null
+++ b/docs/tutorial.step_1.ngdoc
@@ -0,0 +1,86 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 1
+@description
+<table id="tutorial_nav">
+ <tr>
+ <td id="previous_step">{@link tutorial Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-1/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">
+{@link https://github.com/angular/angular-phonecat/commit/fa2a351f0ede1666041e407c52e4e5daf448c5f8
+Code Diff}</td>
+ <td id="next_step">{@link tutorial.step_2 Next}</td>
+ </tr>
+</table>
+
+In this step, we will add basic information about two cell phones.
+
+Note: We will usually include only the new code that we added for each step. In this and
+subsequent examples, we will leave out code from the previous step that hasn't changed, for
+example:
+
+ ...
+ <html xmlns:ng="http://angularjs.org">
+ ...
+
+Let's add the following code to `index.html`:
+
+__`app/index.html`:__
+<pre>
+<head>
+...
+ <title>Google Phone Gallery</title>
+...
+</head>
+...
+ <ul>
+ <li>
+ <span>Nexus S<span>
+ <p>
+ Fast just got faster with Nexus S.
+ </p>
+ </li>
+ <li>
+ <span>Motorola XOOM™ with Wi-Fi<span>
+ <p>
+ The Next, Next Generation tablet.
+ </p>
+ </li>
+ </ul>
+...
+</pre>
+
+## Discussion:
+
+* It's a static web page! We displayed info about two phones! Yay.
+
+* For those of you playing along at home on your own web servers, did you switch to Step 1 and
+refresh your browsers?
+
+ * __{@link tutorial_intro Using Git:}__
+
+ From your `angular-phonecat` directory, run this command:
+
+ git checkout step-1
+
+ * __{@link tutorial_intro Using Snapshots:}__
+
+ From `[install directory]/sandbox`, run this command:
+
+ ./goto_step.sh 1
+
+When you're ready, let's move on and start using some angular features to turn this static page
+into a dynamic web app.
+
+<table id="tutorial_nav">
+ <tr>
+ <td id="previous_step">{@link tutorial Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-1/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">
+{@link https://github.com/angular/angular-phonecat/commit/fa2a351f0ede1666041e407c52e4e5daf448c5f8
+Code Diff}</td>
+ <td id="next_step">{@link tutorial.step_2 Next}</td>
+ </tr>
+</table>
diff --git a/docs/tutorial.step_10.ngdoc b/docs/tutorial.step_10.ngdoc
new file mode 100644
index 00000000..a993bee1
--- /dev/null
+++ b/docs/tutorial.step_10.ngdoc
@@ -0,0 +1,109 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 10
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_9 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-10/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/abe1e13c7d9e725fdd3b811ca5ec28ea0d973aab Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_11 Next}</td>
+</tr>
+</table>
+
+In this step we will add a phone image swapping feature. We want to be able to click on a
+thumbnail image in the phone details page, and have that action change the large phone image to
+match the selection.
+
+__`app/partials/phone-detail.html`.__
+<pre>
+<img ng:src="{{mainImageUrl}}" class="phone"/>
+
+<h1>{{phone.name}}</h1>
+
+<p>{{phone.description}}</p>
+
+<ul class="phone-thumbs">
+ <li ng:repeat="img in phone.images">
+ <img ng:src="{{img}}" ng:click="setImage(img)">
+ </li>
+</ul>
+...
+</pre>
+
+__`app/js/controllers.js`.__
+<pre>
+...
+function PhoneDetailCtrl($xhr) {
+ var self = this;
+
+ $xhr('GET', 'phones/' + self.params.phoneId + '.json', function(code, response) {
+ self.phone = response;
+ self.mainImageUrl = response.images[0];
+ });
+
+ self.setImage = function(imageUrl) {
+ self.mainImageUrl = imageUrl;
+ }
+}
+
+//PhoneDetailCtrl.$inject = ['$xhr'];
+</pre>
+
+__`test/e2e/scenarios.js`.__
+<pre>
+/* jasmine-like end2end tests go here */
+...
+ describe('Phone detail view', function() {
+
+ beforeEach(function() {
+ browser().navigateTo('../../app/index.html#/phones/nexus-s');
+ });
+
+
+ it('should display nexus-s page', function() {
+ expect(binding('phone.name')).toBe('Nexus S');
+ });
+
+ it('should display "0.large" image as the main phone image', function() {
+ expect(element('img.phone').attr('src')).toBe('img/phones/nexus-s.0.jpg');
+ });
+
+
+ it('should swap main image if a thumbnail image is clicked on', function() {
+ element('.phone-thumbs li:nth-child(3) img').click();
+ expect(element('img.phone').attr('src')).toBe('img/phones/nexus-s.2.jpg');
+
+ element('.phone-thumbs li:nth-child(1) img').click();
+ expect(element('img.phone').attr('src')).toBe('img/phones/nexus-s.0.jpg');
+ });
+ });
+});
+</pre>
+
+## Discussion:
+
+Adding the phone image swapping feature is fairly straightforward:
+
+- We defined the `mainImageUrl` model variable in the details controller (`PhoneDetailCtrl`) and
+set the default value of `mainImageUrl` to the first image in the array of images.
+- We created a `setImage` controller method to change `mainImageUrl` to the image clicked on by
+the user.
+- We registered an `ng:click` handler for thumb images to use the `setImage` controller method.
+- And of course, we added e2e tests for our new feature.
+
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_9 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-10/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/abe1e13c7d9e725fdd3b811ca5ec28ea0d973aab Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_11 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_11.ngdoc b/docs/tutorial.step_11.ngdoc
new file mode 100644
index 00000000..b770caea
--- /dev/null
+++ b/docs/tutorial.step_11.ngdoc
@@ -0,0 +1,113 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 11
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_10 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-11/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/46e2bc3ff21a1385d6ef1860c5c242f8e0265379 Code
+Diff}</td>
+<td id="next_step">Next</td>
+</tr>
+</table>
+
+And so we arrive at the last step of this tutorial. Here we define a custom service that
+represents a {@link http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client
+object. Using this client object we can make requests for data in an easier way, without having
+to deal with the lower-level {@link angular.service.$xhr $xhr} APIs.
+
+__`app/index.html`.__
+<pre>
+...
+ <script src="lib/angular/angular.js" ng:autobind></script>
+ <script src="js/controllers.js"></script>
+ <script src="js/filters.js"></script>
+ <script src="js/services.js"></script>
+...
+</pre>
+
+
+__`app/js/services.js`.__ (New)
+<pre>
+ angular.service('Phone', function($resource){
+ return $resource('phones/:phoneId.json', {}, {
+ query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
+ });
+ });
+</pre>
+
+__`app/js/controllers.js`.__
+<pre>
+function PhonesCtrl($route) {
+ var self = this;
+
+ $route.when('/phones',
+ {template:'partials/phone-list.html', controller:PhoneListCtrl});
+ $route.when('/phones/:phoneId',
+ {template:'partials/phone-detail.html', controller:PhoneDetailCtrl});
+ $route.otherwise({redirectTo:'/phones'});
+
+ $route.onChange(function(){
+ self.params = $route.current.params;
+ });
+ $route.parent(this);
+}
+//PhonesCtrl.$inject = ['$route'];
+
+function PhoneListCtrl(Phone) {
+ this.orderProp = 'age';
+ this.phones = Phone.query();
+}
+//PhoneListCtrl.$inject = ['Phone'];
+
+
+function PhoneDetailCtrl(Phone) {
+ this.phone = Phone.get({phoneId:this.params.phoneId});
+}
+//PhoneDetailCtrl.$inject = ['Phone'];
+
+</pre>
+
+
+## Discussion:
+
+* We simplified our sub-controllers (`PhoneListCtrl` and `PhoneDetailCtrl`) by factoring out the
+lower-level `$xhr` service, replacing it with a new service called `Phone`. Angular's {@link
+angular.service.$resource `$resource`} service is easier to use than `$xhr` for interacting with
+data sources exposed as RESTful resources. It is also easier now to understand what the code in
+our controllers is doing.
+
+* Once again we make use of `$route's` params, this time to construct the URL passed as a
+parameter to `$resource` in our `services.js` script.
+
+There you have it! We have created a web app in a relatively short amount of time.
+
+## Closing Notes:
+
+* For more details and examples of the angular concepts we touched on in this tutorial, see the
+{@link guide Developer Guide}.
+
+* For several more examples of sample code, see the {@link cookbook Cookbook}.
+
+* When you are ready to start developing a project using angular, be sure to begin with the {@link
+https://github.com/angular/angular-seed angular seed app}.
+
+* We hope this tutorial was useful to you, and that you learned enough about angular to make you
+want to learn more. Of course, we especially hope you are inspired to go out and develop angular
+web apps of your own, and perhaps you might even be interested in {@link contribute contributing}
+to angular.
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_10 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-11/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/46e2bc3ff21a1385d6ef1860c5c242f8e0265379 Code
+Diff}</td>
+<td id="next_step">Next</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_2.ngdoc b/docs/tutorial.step_2.ngdoc
new file mode 100755
index 00000000..f78cb2aa
--- /dev/null
+++ b/docs/tutorial.step_2.ngdoc
@@ -0,0 +1,133 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 2
+@description
+<table id="tutorial_nav">
+ <tr>
+ <td id="previous_step">{@link tutorial.step_1 Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-2/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">{@link
+ https://github.com/angular/angular-phonecat/commit/02e30dd64e0e5554fbf4d442ade5b1a251f2bf56
+ Code Diff}</td>
+ <td id="next_step">{@link tutorial.step_3 Next}</td>
+ </tr>
+</table>
+
+An important feature of angular is the incorporation of the principles behind {@link
+http://en.wikipedia.org/wiki/Model–View–Controller the MVC design pattern} into client-side web
+apps. With that in mind, let's use a little angular and a little JavaScript to add Model, View,
+and Controller components to our app.
+
+Our __View__ component is constructed by angular from this template:
+
+__`app/index.html`:__
+<pre>
+...
+<body ng:controller="PhoneListCtrl">
+
+ <ul>
+ <li ng:repeat="phone in phones">
+ {{phone.name}}
+ <p>{{phone.snippet}}</p>
+ </li>
+ </ul>
+
+ <script src="lib/angular/angular.js" ng:autobind></script>
+ <script src="js/controllers.js"></script>
+</body>
+...
+</pre>
+
+Our data __Model__ (a small set of phones in object literal notation) is instantiated within our
+__Controller__ function (`PhoneListCtrl`):
+
+__`app/js/controllers.js`:__
+<pre>
+/* App Controllers */
+
+function PhoneListCtrl() {
+ this.phones = [{"name": "Nexus S",
+ "snippet": "Fast just got faster with Nexus S."},
+ {"name": "Motorola XOOM™ with Wi-Fi",
+ "snippet": "The Next, Next Generation tablet."},
+ {"name": "MOTOROLA XOOM™",
+ "snippet": "The Next, Next Generation tablet."}];
+}
+</pre>
+
+The "Angular way" urges us to test as we develop:
+
+__`test/unit/controllersSpec.js`:__
+<pre>
+/* jasmine specs for controllers go here */
+describe('PhoneCat controllers', function() {
+
+ describe('PhoneListCtrl', function(){
+
+ it('should create "phones" model with 3 phones', function() {
+ var ctrl = new PhoneListCtrl();
+ expect(ctrl.phones.length).toBe(3);
+ });
+ });
+});
+</pre>
+
+## Discussion:
+
+So what were our changes from Step 1?
+
+* __View template:__ We replaced the hard-coded phone list with the {@link
+angular.widget.@ng:repeat ng:repeat widget} and two {@link guide.expression angular expressions}
+enclosed in curly braces: `{{phone.name}}` and `{{phone.snippet}}`:
+
+ * The `ng:repeat="phone in phones"` statement in the `<li>` tag is an angular repeater. It
+ tells angular to create a `<li>` element for each phone in the phones list, using the first
+ `<li>` tag as the template.
+
+ * The curly braces around `phone.name` and `phone.snippet` are an example of {@link
+ angular.markup angular markup}. The curly braces are shorthand for the angular directive
+ {@link angular.directive.ng:bind ng:bind}. They indicate to angular that these are template
+ binding points. Binding points are locations in the template where angular constructs two-way
+ data-binding between the View and the Model. In angular, the View is a projection of the Model
+ through the HTML template.
+
+* __Controller:__ At this point, it doesn't appear as if our controller is doing very much
+controlling, but it is playing a crucial role: providing context for our data model so we can
+establish two-way data-binding between the model and the view. Note in the following how we
+connected the dots between our presentation, data, and logic components:
+
+ * The name of our controller function (in the JavaScript file `controllers.js`) matches the
+ {@link angular.directive.ng:controller ng:controller} directive in the `<body>` tag
+ (`PhoneListCtrl`).
+ * We instantiated our data within the scope of our controller function, and our template
+ binding points are located within the block bounded by the `<body
+ ng:controller="PhoneListCtrl>` tag.
+
+ So, our controller function becomes the {@link angular.scope scope} of our data model.
+ Angular uses scopes, along with the information contained in the template, data model, and
+ controller to keep the Model and View separated but in sync: any changes to the model are
+ reflected in the view; any changes that occur in the view are reflected in the model.
+
+* __Model:__ For our data model, we created a simple array of phone records, specified in object
+literal notation.
+
+* __Testing:__ Ease of testing is another cornerstone of angular's design philosophy. All we are
+doing here is showing how easy it is to create a unit test using the technology baked into
+angular. The test verifies that we have some data, and that there are 3 records in the data set.
+
+ Angular's testing stack utilizes Jasmine's Behavior-driven Development (BDD) framework. You
+ can learn about it on the {@link http://pivotal.github.com/jasmine/ Jasmine home page} and on
+ the {@link https://github.com/pivotal/jasmine/wiki Jasmine wiki}.
+
+<table id="tutorial_nav">
+ <tr>
+ <td id="previous_step">{@link tutorial.step_1 Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-2/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">{@link
+ https://github.com/angular/angular-phonecat/commit/02e30dd64e0e5554fbf4d442ade5b1a251f2bf56
+ Code Diff}</td>
+ <td id="next_step">{@link tutorial.step_3 Next}</td>
+ </tr>
+</table>
diff --git a/docs/tutorial.step_3.ngdoc b/docs/tutorial.step_3.ngdoc
new file mode 100755
index 00000000..6ebe81e8
--- /dev/null
+++ b/docs/tutorial.step_3.ngdoc
@@ -0,0 +1,104 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 3
+@description
+<table id="tutorial_nav">
+<tr>
+ <td id="previous_step">{@link tutorial.step_2 Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">{@link
+ https://github.com/angular/angular-phonecat/commit/a03815f8fb00217f5f9c1d3ef83282f79818e706 Code
+ Diff}</td>
+ <td id="next_step">{@link tutorial.step_4 Next}</td>
+</tr>
+</table>
+
+In this step, we will add full text search to our app. We will also write an end-to-end test,
+because a good end-to-end test is a good friend. It stays with your app, keeps an eye on it, and
+quickly detects regressions.
+
+__`app/index.html`:__
+<pre>
+...
+ Fulltext Search: <input name="query"/>
+
+ <ul class="phones">
+ <li ng:repeat="phone in phones.$filter(query)">
+ {{phone.name}}
+ <p>{{phone.snippet}}</p>
+ </li>
+ </ul>
+...
+</pre>
+__`test/e2e/scenarios.js`:__
+<pre>
+/* jasmine-like end2end tests go here */
+describe('PhoneCat App', function() {
+
+ describe('Phone list view', function() {
+
+ beforeEach(function() {
+ browser().navigateTo('../../app/index.html');
+ });
+
+
+ it('should filter the phone list as user types into the search box', function() {
+ expect(repeater('.phones li').count()).toBe(3);
+
+ input('query').enter('nexus');
+ expect(repeater('.phones li').count()).toBe(1);
+
+ input('query').enter('motorola');
+ expect(repeater('.phones li').count()).toBe(2);
+ });
+ });
+});
+</pre>
+
+## Discussion:
+
+We continued using the same controller that we set up in Step 2, but we added the following
+features to our app:
+
+* __Search Box:__ A standard HTML `<input>` tag combined with angular's {@link
+angular.Array.filter $filter} utility (added to the repeater) lets a user type in search criteria
+and immediately see the effects of their search on the phone list. This new code demonstrates the
+following:
+
+ * Two-way data-binding. This is one of the very nice features in angular. In this example,
+ the data that you type into the input box (named __`query`__) is immediately available as a
+ filter in the list repeater (`phone in phones.$filter(`__`query`__`)`). When the page loads,
+ angular binds the name of the input box to a variable of the same name in the data model.
+ Whenever the data Model changes, the View reflects the change, and vice versa.
+
+ * Use of `$filter` in a template. The `$filter` function is one of several built-in utility
+ functions that augment JavaScript arrays during their evaluation as angular expressions. An
+ {@link Angular.array angular array} is a JavaScript array object with additional functionality
+ added. In {@link guide.expression angular expressions}, these array utilities are available as
+ methods. (They are prefixed with a $ to avoid naming collisions.)
+
+ * How `ng:repeat` automatically shrinks and grows the number of phones in the View, via DOM
+ manipulation that is completely transparent to the developer. If you've written any DOM
+ manipulation code, this should make you happy.
+
+* __CSS:__ We added in some minimal CSS to the file we set up in Step 0: `./css/app.css`.
+
+* __Testing:__ This end-to-end test shows the following:
+
+ * Proof that the search box and the repeater are correctly wired together.
+
+ * How easy it is to write end-to-end tests. This is just a simple test, but the point here is
+ to show how easy it is to set up a functional, readable, end-to-end test.
+
+<table id="tutorial_nav">
+<tr>
+ <td id="previous_step">{@link tutorial.step_2 Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">{@link
+ https://github.com/angular/angular-phonecat/commit/a03815f8fb00217f5f9c1d3ef83282f79818e706 Code
+ Diff}</td>
+ <td id="next_step">{@link tutorial.step_4 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_4.ngdoc b/docs/tutorial.step_4.ngdoc
new file mode 100755
index 00000000..260ad38f
--- /dev/null
+++ b/docs/tutorial.step_4.ngdoc
@@ -0,0 +1,114 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 4
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_3 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-4/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/b56c91f453114347f0cb25e70b1c4fa4f1421763 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_5 Next}</td>
+</tr>
+</table>
+
+In this step, we add a feature that lets our users choose which way to order the phone list.
+
+__`app/index.html`:__
+<pre>
+...
+ <ul class="predicates">
+ <li>
+ Search: <input type="text" name="query"/>
+ </li>
+ <li>
+ Sort by:
+ <select name="orderProp">
+ <option value="name">Alphabetical</option>
+ <option value="age">Newest</option>
+ </select>
+ </li>
+ </ul>
+
+ <ul class="phones">
+ <li ng:repeat="phone in phones.$filter(query).$orderBy(orderProp)">
+ {{phone.name}}
+ <p>{{phone.snippet}}</p>
+ </li>
+ </ul>
+...
+</pre>
+
+__`app/js/controller.js`:__
+<pre>
+/* App Controllers */
+
+function PhoneListCtrl() {
+ this.phones = [{"name": "Nexus S",
+ "snippet": "Fast just got faster with Nexus S.",
+ "age": 0},
+ {"name": "Motorola XOOM™ with Wi-Fi",
+ "snippet": "The Next, Next Generation tablet.",
+ "age": 1},
+ {"name": "MOTOROLA XOOM™",
+ "snippet": "The Next, Next Generation tablet.",
+ "age": 2}];
+
+ this.orderProp = 'age';
+}
+</pre>
+
+__`test/unit/controllerSpec.js`:__
+<pre>
+/* jasmine specs for controllers go here */
+describe('PhoneCat controllers', function() {
+
+ describe('PhoneListCtrl', function(){
+ var scope, $browser, ctrl;
+
+ beforeEach(function() {
+ ctrl = new PhoneListCtrl();
+ });
+
+
+ it('should create "phones" model with 3 phones', function() {
+ expect(ctrl.phones.length).toBe(3);
+ });
+
+
+ it('should set the default value of orderProp model', function() {
+ expect(ctrl.orderProp).toBe('age');
+ });
+ });
+});
+</pre>
+
+## Discussion:
+
+To provide dynamic ordering, we employ another one of angular's "array type augmenters" and let
+the data binding do the rest of the work for us:
+
+* Like {@link angular.Array.filter $filter}, {@link angular.Array.orderBy $orderBy} is a built-in
+method available on array objects in angular expressions. In our UI template, we set up a select
+box that lets the user set the `orderProp` model variable to one of the string constants: `age` or
+`name`.
+
+* In our controller, we added a line to set the default value of `orderProp` to `age`.
+
+* Our unit test now verifies that our default ordering property is set.
+
+* Once again we added a little more CSS to improve the View.
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_3 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-4/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/b56c91f453114347f0cb25e70b1c4fa4f1421763 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_5 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_5.ngdoc b/docs/tutorial.step_5.ngdoc
new file mode 100755
index 00000000..3480e437
--- /dev/null
+++ b/docs/tutorial.step_5.ngdoc
@@ -0,0 +1,109 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 5
+@description
+<table id="tutorial_nav">
+<tr>
+ <td id="previous_step">{@link tutorial.step_4 Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-5/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">{@link
+ https://github.com/angular/angular-phonecat/commit/4f0a518557b5c7442568666b211aa79499870276 Code
+ Diff}</td>
+ <td id="next_step">{@link tutorial.step_6 Next}</td>
+</tr>
+</table>
+
+In this step, the View template remains the same but the Model and Controller change. We'll
+introduce the use of an angular {@link angular.service service}, which we will use to implement an
+`HttpXmlRequest` request to communicate with a server. Angular provides the built-in {@link
+angular.service.$xhr $xhr} service for this purpose.
+
+The addition of the `$xhr` service to our app gives us the opportunity to talk about {@link
+guide.di Dependency Injection} (DI). The use of DI is another cornerstone of the angular
+philosophy. DI helps make your web apps well structured, loosely coupled, and ultimately easier to
+test.
+
+__`app/js/controllers.js:`__
+<pre>
+/* App Controllers */
+
+function PhoneListCtrl($xhr) {
+ var self = this;
+
+ $xhr('GET', 'phones/phones.json', function(code, response) {
+ self.phones = response;
+ });
+
+ self.orderProp = 'age';
+}
+
+//PhoneListCtrl.$inject = ['$xhr'];
+</pre>
+
+__`test/unit/controllerSpec.js`:__
+<pre>
+/* jasmine specs for controllers go here */
+describe('PhoneCat controllers', function() {
+
+ describe('PhoneListCtrl', function(){
+ var scope, $browser, ctrl;
+
+ beforeEach(function() {
+ scope = angular.scope();
+ $browser = scope.$service('$browser');
+
+ $browser.xhr.expectGET('phones/phones.json').respond([{name: 'Nexus S'},
+ {name: 'Motorola DROID'}]);
+ ctrl = scope.$new(PhoneListCtrl);
+ });
+
+
+ it('should create "phones" model with 2 phones fetched from xhr', function() {
+ expect(ctrl.phones).toBeUndefined();
+ $browser.xhr.flush();
+
+ expect(ctrl.phones).toEqual([{name: 'Nexus S'},
+ {name: 'Motorola DROID'}]);
+ });
+
+
+ it('should set the default value of orderProp model', function() {
+ expect(ctrl.orderProp).toBe('age');
+ });
+ });
+});
+</pre>
+
+## Discussion:
+
+* __Services:__ {@link angular.service Services} are substitutable objects managed by angular's
+{@link guide.di DI subsystem}. Angular services simplify some of the standard operations common
+to web apps. Angular provides several built-in services (such as {@link angular.service.$xhr
+$xhr}). You can also create your own custom services.
+
+* __Dependency Injection:__ To use an angular service, you simply provide the name of the service
+as a parameter to the function in which you are using that service. Angular's {@link guide.di DI
+subsystem} recognizes the identity of the service by name, provides it for you when you need it,
+and manages any transitive dependencies the service may have (services often depend upon other
+services).
+
+* __`$xhr`:__ We moved our data set out of the controller and into the file `phones/phones.json`.
+This file serves as our data store rather than an actual server (to the browser they look the
+same). We now use the `$xhr` service to return our phone data, which you'll note is still within
+the scope of our controller function.
+
+* __Testing:__ The unit test has been expanded. It now verifies that the `$xhr` service behaves
+as expected.
+
+<table id="tutorial_nav">
+<tr>
+ <td id="previous_step">{@link tutorial.step_4 Previous}</td>
+ <td id="step_result">{@link http://angular.github.com/angular-phonecat/step-5/app Example}</td>
+ <td id="tut_home">{@link tutorial Tutorial Home}</td>
+ <td id="code_diff">{@link
+ https://github.com/angular/angular-phonecat/commit/4f0a518557b5c7442568666b211aa79499870276 Code
+ Diff}</td>
+ <td id="next_step">{@link tutorial.step_6 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_6.ngdoc b/docs/tutorial.step_6.ngdoc
new file mode 100755
index 00000000..dc7b07ed
--- /dev/null
+++ b/docs/tutorial.step_6.ngdoc
@@ -0,0 +1,101 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 6
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_5 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-6/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/2fb113a4da9b6d19e17627f351f0681befcccdc0 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_7 Next}</td>
+</tr>
+</table>
+
+In this step, we add thumbnail images, links, and a little more CSS to our app. For now, our
+links go nowhere. One step at a time; in the next step we'll implement new views that these links
+will open.
+
+__`app/index.html`:__
+<pre>
+...
+ <ul class="predicates">
+ <li>
+ Search: <input type="text" name="query"/>
+ </li>
+ <li>
+ Sort by:
+ <select name="orderProp">
+ <option value="name">Alphabetical</option>
+ <option value="age">Newest</option>
+ </select>
+ </li>
+ </ul>
+
+ <ul class="phones">
+ <li ng:repeat="phone in phones.$filter(query).$orderBy(orderProp)">
+ <a href="#/phones/{{phone.id}}">{{phone.name}}</a>
+ <a href="#/phones/{{phone.id}}" class="thumb"><img ng:src="{{phone.imageUrl}}"></a>
+ <p>{{phone.snippet}}</p>
+ </li>
+ </ul>
+...
+</pre>
+
+__`app/js/controller.js`__ (Unchanged):
+<pre>
+/* App Controllers */
+
+function PhoneListCtrl($xhr) {
+ var self = this;
+
+ $xhr('GET', 'phones/phones.json', function(code, response) {
+ self.phones = response;
+ });
+
+ self.orderProp = 'age';
+}
+
+//PhoneListCtrl.$inject = ['$xhr'];
+</pre>
+
+__`app/phones/phones.json`__ (sample snippet):
+<pre>
+ [
+ {
+ "age": 4,
+ ...
+ "carrier": "T-Mobile",
+ "id": "motorola-defy-with-motoblur",
+ "imageUrl": "http://google.com/phone/image/small/640001",
+ "name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
+ "snippet": "Are you ready for everything life throws your way?"
+ },
+ …
+ ]
+</pre>
+
+## Discussion:
+
+* Note that we're using {@link guide.expression angular expressions} enclosed in the now-familiar
+{@link angular.markup double-curly brace markup} in the href attribute values. These represent
+attribute bindings, and work the same way as the bindings we saw in previous steps.
+
+* Note also the use of the {@link angular.directive.ng:src ng:src} directive in the `<img>` tag.
+That directive prevents the browser from treating the angular `{{ exppression }}` markup
+literally, as it would do if we tried to use markup in a regular `src` attribute. Use `ng:src` to
+keep the browser from eagerly making an extra http request to an invalid location.
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_5 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-6/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/2fb113a4da9b6d19e17627f351f0681befcccdc0 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_7 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_7.ngdoc b/docs/tutorial.step_7.ngdoc
new file mode 100755
index 00000000..3b5984b4
--- /dev/null
+++ b/docs/tutorial.step_7.ngdoc
@@ -0,0 +1,159 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 7
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_6 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-7/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/43ff5d76f1c0a464da67d691418e33e6c9d8dbc8 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_8 Next}</td>
+</tr>
+</table>
+
+In this step we introduce angular's {@link angular.service.$route $route} service. This service
+is usually used in conjunction with the {@link angular.widget.ng:view ng:view} directive. The
+`$route` service makes it easy to wire together controllers, View templates, and the current URL
+location in the browser. Using this feature we can implement {@link
+http://en.wikipedia.org/wiki/Deep_linking deep linking}, which lets us utilize the browser's
+History, and Back and Forward browser navigation.
+
+We'll use {@link angular.service.$route $route} to implement two different views for our
+application: one view presents the phone listing, and the other view presents the details for a
+particular phone. We'll use {@link angular.widget.ng:view ng:view} to include one or the other of
+those views in our main layout page (`index.html`). The view presented in the layout page is based
+on which URL the user navigates to.
+
+To manage our two different views, we'll move the existing phone list controller into a
+sub-controller, add a second sub-controller to handle the phone details, and we'll create a new
+root controller to implement the routing. (We'll save the implementation of the phone details
+View for the next step.)
+
+__`app/index.html`:__
+<pre>
+<body ng:controller="PhoneCatCtrl">
+...
+
+ <ng:view></ng:view>
+...
+</pre>
+
+__`app/partials/phone-list.html`:__
+<pre>
+<ul class="predicates">
+ <li>
+ Search: <input type="text" name="query"/>
+ </li>
+ <li>
+ Sort by:
+ <select name="orderProp">
+ <option value="name">Alphabetical</option>
+ <option value="age">Newest</option>
+ </select>
+ </li>
+</ul>
+
+<ul class="phones">
+ <li ng:repeat="phone in phones.$filter(query).$orderBy(orderProp)">
+ <a href="#/phones/{{phone.id}}">{{phone.name}}</a>
+ <a href="#/phones/{{phone.id}}" class="thumb"><img ng:src="{{phone.imageUrl}}"></a>
+ <p>{{phone.snippet}}</p>
+ </li>
+</ul>
+</pre>
+
+__`app/js/controller.js`:__
+<pre>
+/* App Controllers */
+
+function PhoneCatCtrl($route) {
+ var self = this;
+
+ $route.when('/phones',
+ {template: 'partials/phone-list.html', controller: PhoneListCtrl});
+ $route.when('/phones/:phoneId',
+ {template: 'partials/phone-detail.html', controller: PhoneDetailCtrl});
+ $route.otherwise({redirectTo: '/phones'});
+
+ $route.onChange(function(){
+ self.params = $route.current.params;
+ });
+
+ $route.parent(this);
+}
+
+//PhoneCatCtrl.$inject = ['$route'];
+
+
+function PhoneListCtrl($xhr) {
+ var self = this;
+
+ $xhr('GET', 'phones/phones.json', function(code, response) {
+ self.phones = response;
+ });
+
+ self.orderProp = 'age';
+}
+
+//PhoneListCtrl.$inject = ['$xhr'];
+
+
+function PhoneDetailCtrl() {}
+</pre>
+
+## Discussion:
+
+We have many changes to discuss here in Step 7:
+
+* __The View.__ Our View template in `index.html` has been reduced down to this:
+`<ng:view></ng:view>`. It is now what we call a "layout template", because it contains
+information common for all views, including the layout of our application. The {@link
+angular.widget.ng:view ng:view} directive behaves like an "include" declaration (it's a
+specialized sibling of the {@link angular.widget.ng:include ng:include} directive) that works
+specifically with the {@link angular.service.$route $route} service. The View template associated
+with the current route definition gets included "between those tags" (there's more to it than a
+simple include, but that explanation will do for now).
+
+ * We added two new View templates:
+
+ * `app/partials/phone-list.html` for the phone list;
+
+ * `app/partials/phone-detail.html` for the phone details (just a stub for this step);
+
+* __The Controller(s).__ We now have a new root controller (`PhoneCatCtrl`) and two
+sub-controllers (`PhoneListCtrl` and `PhoneDetailCtrl`).
+
+ * __`$route.`__ The root controller's job now is to set up the `$route` configuration:
+
+ * When the fragment part of the URL in the browser ends in "/phones", `$route` grabs the
+ `phone-list.html` template, compiles it, and links it with a new scope that is controlled
+ by our `PhoneListCtrl` controller.
+
+ * When the URL ends in "/phones/:phoneId", `$route` compiles and links the
+ `phone-detail.html` template as it did with `phone-list.html`. But note the use of the
+ variable `:phoneId` in the `path` parameter of `$route.when()`: `$route` stores that
+ portion of the current URL fragment in its current parameters in a property called
+ `params.phoneId`. We made the `$route` parameters available to our sub-controllers in the
+ `$route.onChange()` function in our root controller. We will use the `phoneId` property
+ when we fetch the phone details in Step 8.
+
+ * Any other URL fragment gets redirected to `/phones`.
+
+ * __Deep Linking.__ In `$route`'s `onChange()` method, we copied {@link
+ http://en.wikipedia.org/wiki/Deep_linking deep linking} parameters to the `params` property in
+ the root scope, so we can use them in the child scopes managed by our sub-controllers.
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_6 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-7/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/43ff5d76f1c0a464da67d691418e33e6c9d8dbc8 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_8 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_8.ngdoc b/docs/tutorial.step_8.ngdoc
new file mode 100755
index 00000000..bf03fdac
--- /dev/null
+++ b/docs/tutorial.step_8.ngdoc
@@ -0,0 +1,110 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 8
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_7 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-8/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/1f91f571bdd6f1e705ebb303998afe7820ffc6d9 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_9 Next}</td>
+</tr>
+</table>
+
+In this step, we implement the Phone Details View template. Once again we will use {@link
+angular.services.$xhr $xhr} to fetch our data, and we'll flesh out the `phone-details.html` View
+template.
+
+__`app/partials/phone-details.html`:__
+<pre>
+<img ng:src="{{phone.images[0]}}" class="phone"/>
+
+<h1>{{phone.name}}</h1>
+
+<p>{{phone.description}}</p>
+
+<ul class="phone-thumbs">
+ <li ng:repeat="img in phone.images">
+ <img ng:src="{{img}}"/>
+ </li>
+</ul>
+
+<ul class="specs">
+ <li>
+ <span>Availability and Networks</span>
+ <dl>
+ <dt>Availability</dt>
+ <dd ng:repeat="availability in phone.availability">{{availability}}</dd>
+ </dl>
+ </li>
+ ...
+ <span>Additional Features</span>
+ <dd>{{phone.additionalFeatures}}</dd>
+ </li>
+</ul>
+</pre>
+
+__`app/js/controller.js`:__
+<pre>
+function PhoneCatCtrl($route) (same as Step 7)
+
+function PhoneListCtrl($xhr) (same as Step 7)
+
+function PhoneDetailCtrl($xhr) {
+ var self = this;
+
+ $xhr('GET', 'phones/' + self.params.phoneId + '.json', function(code, response) {
+ self.phone = response;
+ });
+}
+
+//PhoneDetailCtrl.$inject = ['$xhr'];
+</pre>
+
+__`app/phones/nexus-s.json`:__ (sample snippet)
+<pre>
+{
+ "additionalFeatures": "Contour Display, Near Field Communications (NFC), Three-axis gyroscope,
+ Anti-fingerprint display coating, Internet Calling support (VoIP/SIP)",
+ "android": {
+ "os": "Android 2.3",
+ "ui": "Android"
+ },
+ ...
+ "images": [
+ "img/phones/nexus-s.0.jpg",
+ "img/phones/nexus-s.1.jpg",
+ "img/phones/nexus-s.2.jpg",
+ "img/phones/nexus-s.3.jpg"
+ ],
+ "storage": {
+ "flash": "16384MB",
+ "ram": "512MB"
+ }
+}
+</pre>
+
+## Discussion:
+
+* Phone Details View Template. There is nothing fancy or new here, just note where we use the
+angular `{{ expression }}` markup and directives to project phone data from our model.
+
+* Note how we used the `$route` `params` object from the scope managed by the root controller
+(`PhoneCatCtrl`), to construct the path to the phone details requested by the user. The rest of
+this step is simply applying the previously learned concepts and angular APIs to create a large
+template that displays a lot of data about a phone.
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_7 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-8/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/1f91f571bdd6f1e705ebb303998afe7820ffc6d9 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_9 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial.step_9.ngdoc b/docs/tutorial.step_9.ngdoc
new file mode 100755
index 00000000..9fcf095d
--- /dev/null
+++ b/docs/tutorial.step_9.ngdoc
@@ -0,0 +1,95 @@
+@workInProgress
+@ngdoc overview
+@name Tutorial: Step 9
+@description
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_8 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-9/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/975d173ad0768487852387497c086f3c93fb48f6 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_10 Next}</td>
+</tr>
+</table>
+
+In this step, we have determined that the built-in angular display filters ({@link
+angular.filter.number number}, {@link angular.filter.currency currency}, {@link
+angular.filter.date date}, etc.) do not handle what we want to do, and so we get to create our own
+custom {@link angular.filter filter}.
+
+In the previous step, the details page displayed either "true" or "false" to indicate whether
+certain phone features were present or not. Our custom "checkmark" filter replaces those text
+strings with images: ✓ for "true", and ✘ for "false".
+
+Our filter code lives in `app/js/filters.js`:
+
+__`app/index.html`.__
+<pre>
+...
+ <script src="app/js/filters.js"></script>
+...
+</pre>
+
+In the phone details template, we employ our filter for angular expressions whose values are
+"true" or "false"; `{{ [phone_feature] | checkmark }}`:
+
+__`app/partials/phone-detail.html`.__
+<pre>
+<img ng:src="{{phone.images[0].large}}" class="phone"/>
+<h1>{{phone.name}}</h1>
+<p>{{phone.description}}</p>
+...
+<ul class="specs">
+ ...
+ <li>
+ <span>Connectivity</span>
+ <dl>
+ <dt>Network Support</dt>
+ <dd>{{phone.connectivity.cell}}</dd>
+ <dt>WiFi</dt>
+ <dd>{{phone.connectivity.wifi}}</dd>
+ <dt>Bluetooth</dt>
+ <dd>{{phone.connectivity.bluetooth}}</dd>
+ <dt>Infrared</dt>
+ <dd>{{phone.connectivity.infrared | checkmark}}</dd>
+ <dt>GPS</dt>
+ <dd>{{phone.connectivity.gps | checkmark}}</dd>
+ </dl>
+ </li>
+...
+</ul>
+</pre>
+
+__`app/js/filters.js`.__ (New)
+<pre>
+/* http://docs.angularjs.org/#!angular.filter */
+
+angular.filter('checkmark', function(input) {
+ return input ? '\u2713' : '\u2718';
+});
+</pre>
+
+
+## Discussion:
+
+This example shows how easy it is to roll your own filters for displaying data. As explained in
+the "Writing your own Filters" section of the {@link angular.filter angular.filter} page, you
+simply add your filter function on to the `angular.filter` object.
+
+In this example, our filter name is "checkmark"; our input is either "true" or "false", and we
+return one of two unicode characters we have chosen to represent true or false (`\u2713` and
+`\u2718`).
+
+<table id="tutorial_nav">
+<tr>
+<td id="previous_step">{@link tutorial.step_8 Previous}</td>
+<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-9/app Example}</td>
+<td id="tut_home">{@link tutorial Tutorial Home}</td>
+<td id="code_diff">{@link
+https://github.com/angular/angular-phonecat/commit/975d173ad0768487852387497c086f3c93fb48f6 Code
+Diff}</td>
+<td id="next_step">{@link tutorial.step_10 Next}</td>
+</tr>
+</table>
diff --git a/docs/tutorial_intro.ngdoc b/docs/tutorial_intro.ngdoc
new file mode 100644
index 00000000..855f545c
--- /dev/null
+++ b/docs/tutorial_intro.ngdoc
@@ -0,0 +1,155 @@
+@workInProgress
+@ngdoc overview
+@name Intro to Tutorial
+@description
+
+A great way to get introduced to angular is to work through the {@link Tutorial angular tutorial},
+which walks you through the construction of an angular web app. The app you will build in the
+tutorial is based on the {@link http://www.google.com/phone/# Google phone gallery app}.
+
+Once you set up your tutorial environment, you should be able to get through the material in less
+than a day and you'll have fun doing it. More experienced coders may be able to zip through the
+exercises in an afternoon. In any case, we promise that your time will be well spent!
+
+When you finish the tutorial you will be able to:
+
+* Create a simple dynamic application that works in any browser
+* Define the differences between angular and common JavaScript frameworks
+* Understand angular expressions
+* Understand how data binding works in angular
+* Create your own angular widgets and directives
+* Add your own tags to angular
+* Use the angular-seed project to quickly boot-strap your own projects
+* Create and run tests
+* Identify resources for learning more about angular
+
+You can work through the tutorial in any of the following ways:
+
+* <a href="#UsingGit">Using Git</a>. Use the Git Versioning System to get the files for each step.
+* <a href="#UsingSnapshots">Using Snapshots</a>. Download snapshots (files for each step of the
+tutorial) from the angular server.
+* <a href="#ReadingExamples">Reading the Examples</a>. Read through the examples, and inspect
+results and code on our server.
+
+The first two ways (Git and snapshots) give you a fuller experience, in that you can run the unit
+and end-to-end tests in addition to the tutorial app. They also give you the ability to play
+around with the code and get instant feedback in your browser. The last way (reading through the
+tutorial online) requires no setup on your machine, but you can't run the tests, and it won't be
+as easy to play around with the code.
+
+<a name="PreReqs"></a>
+# Prerequisites for Git and Snapshots
+
+To run the tutorial app and tests on your machine (using Git or the snapshots) you will need the
+following:
+
+* An http server running on your system. If you don't already have one installed, you can install
+`node.js` ({@link https://github.com/joyent/node/wiki/Installation node.js install}) or another
+http sever (such as Apache, etc.).
+* Java. This is required for running tests. Angular itself doesn't require Java.
+* A modern browser. Needed for viewing and debugging code.
+* A text editor of your choice.
+
+<a name="UsingGit"></a>
+# Using Git
+
+The following instructions are for developers who are comfortable with Git's versioning system:
+
+1. Check to be sure you have all of the <a href="#PreReqs">prerequisites</a> on your system.
+
+1. Clone the angular-phonecat repository located at {@link
+https://github.com/angular/angular-phonecat angular-phonecat} by running the following command in
+a terminal:
+
+ git clone git://github.com/angular/angular-phonecat.git
+
+ This will create a directory called `angular-phonecat`.
+
+1. In terminal, navigate to the `angular-phonecat` directory and run:
+
+ git checkout step-0
+
+ (You can run `git checkout step-[0-11]` to go to any of the steps in the tutorial).
+
+1. To see the app running in your browser, do the following:
+ * __For node.js users:__
+ 1. Run `./scripts/web-server.js` to start the web server.
+ 1. Open a browser window for the app and navigate to http://localhost:8000/app/index.html.
+ 1. Open a browser window for the tests, navigate to http://localhost:9876, and choose
+ "strict mode".
+
+ * __For other http servers:__
+ 1. Configure the server to serve the files in the `angular-phonecat` directory.
+ 1. Start the server.
+ 1. Navigate in your browser to
+ http://localhost:[*port-number*]/[*context-path*]/app/index.html.
+ 1. Navigate in your browser to http://localhost:[*port-number*]/, and choose "strict mode".
+
+<a name="UsingSnapshots"></a>
+# Using Snapshots
+
+Snapshots are the sets of files that reflect the state of the tutorial app at each step. These
+files include the HTML, CSS, and JavaScript for the app, plus Jasmine JavaScript files and Java
+libraries for the test stack. These will let you run the tutorial app and tests, without requiring
+knowledge of Git. You can download and install the snapshot files as follows:
+
+1. Check to be sure you have all of the <a href="#PreReqs">prerequisites</a> on your system.
+
+1. Navigate to [*the angular server*].
+
+1. Download and unzip [*the snapshot file*] to a suitable location.
+
+1. Change directories to [*install-dir*]/sandbox.
+
+1. Run the following command:
+ * `./goto_step.sh 0`
+
+ You have to start out at the beginning, which is Step 0. After you set up Step 0, you can skip
+ around between any steps.
+
+1. To see the app running in your browser, do the following:
+ * __For node.js users:__
+ 1. Run `./scripts/web-server.js` to run the web server.
+ 1. Open a browser window for the app and navigate to http://localhost:8000/app/index.html.
+ 1. Open a browser window for the tests, navigate to http://localhost:9876, and choose
+ "strict mode".
+
+ * __For other http servers:__
+ 1. Configure servers to serve the app and test files in the [*install-dir*]/sandbox.
+ 1. Start the server.
+ 1. Navigate in your app browser to
+ http://localhost:[*port-number*]/[*context-path*]/app/index.html.
+ 1. Navigate in your test browser to http://localhost:[*port-number*] and choose "strict
+ mode".
+
+1. To view the tutorial app at different steps, run `./goto_step.sh [0-11]` and then refresh your
+browser. For example, say you're on Step 5 of the tutorial, and you want to see the app in action:
+
+ 1. Run `goto_step.sh 5` from the command line in the `sandbox` directory.
+ 1. Refresh your app browser.
+
+<a name="ReadingExamples"></a>
+# Reading the Examples
+
+If you don't want to set up anything on your local machine, you can read through {@link Tutorial
+the tutorial} and inspect the tutorial files on our servers; doing this will give you a good idea
+of what angular does.
+
+To see the running app at each tutorial step, click the "Example" link at the top or bottom of
+each tutorial page.
+
+To view the code differences between tutorial steps, click the Code Diff link at top or bottom of
+each tutorial page. Additions are highlighted in green; deletions are highlighted in red.
+
+
+# Relative URLs
+Throughout the tutorial, we use relative URLs to refer to files hosted on our local http server.
+The absolute URL depends on your configuration. For example, if you are using the node.js server,
+`app/index.html` translates to:
+
+ http://localhost:8000/app/index.html
+
+If you are using your own http server running on port 8080 and the tutorial files are hosted at
+`/angular_tutorial`, `app/index.html` translates to:
+
+ http://localhost:8080/angular_tutorial/app/index.html