Update latest docs content from gdocs

This commit is contained in:
Vojta Jina 2011-06-07 23:13:44 +02:00 committed by Igor Minar
parent e670a812fa
commit e0ee3a0726
8 changed files with 119 additions and 131 deletions

View file

@ -9,80 +9,80 @@ detection, and preventing invalid form submission.
<doc:example> <doc:example>
<doc:source> <doc:source>
<script> <script>
UserForm.$inject = ['$invalidWidgets']; UserForm.$inject = ['$invalidWidgets'];
function UserForm($invalidWidgets){ function UserForm($invalidWidgets){
this.$invalidWidgets = $invalidWidgets; this.$invalidWidgets = $invalidWidgets;
this.state = /^\w\w$/; this.state = /^\w\w$/;
this.zip = /^\d\d\d\d\d$/; this.zip = /^\d\d\d\d\d$/;
this.master = { this.master = {
name: 'John Smith', name: 'John Smith',
address:{ address:{
line1: '123 Main St.', line1: '123 Main St.',
city:'Anytown', city:'Anytown',
state:'AA', state:'AA',
zip:'12345' zip:'12345'
}, },
contacts:[ contacts:[
{type:'phone', value:'1(234) 555-1212'} {type:'phone', value:'1(234) 555-1212'}
] ]
}; };
this.cancel(); this.cancel();
} }
UserForm.prototype = { UserForm.prototype = {
cancel: function(){ cancel: function(){
this.form = angular.copy(this.master); this.form = angular.copy(this.master);
}, },
save: function(){ save: function(){
this.master = this.form; this.master = this.form;
this.cancel(); this.cancel();
} }
}; };
</script> </script>
<div ng:controller="UserForm"> <div ng:controller="UserForm">
<label>Name:</label><br/> <label>Name:</label><br/>
<input type="text" name="form.name" ng:required/> <br/><br/> <input type="text" name="form.name" ng:required/> <br/><br/>
<label>Address:</label><br/> <label>Address:</label><br/>
<input type="text" name="form.address.line1" size="33" ng:required/> <br/> <input type="text" name="form.address.line1" size="33" ng:required/> <br/>
<input type="text" name="form.address.city" size="12" ng:required/>, <input type="text" name="form.address.city" size="12" ng:required/>,
<input type="text" name="form.address.state" size="2" ng:required ng:validate="regexp:state"/> <input type="text" name="form.address.state" size="2" ng:required ng:validate="regexp:state"/>
<input type="text" name="form.address.zip" size="5" ng:required <input type="text" name="form.address.zip" size="5" ng:required
ng:validate="regexp:zip"/><br/><br/> ng:validate="regexp:zip"/><br/><br/>
<label>Phone:</label> <label>Contacts:</label>
[ <a href="" ng:click="form.contacts.$add()">add</a> ] [ <a href="" ng:click="form.contacts.$add()">add</a> ]
<div ng:repeat="contact in form.contacts"> <div ng:repeat="contact in form.contacts">
<select name="contact.type"> <select name="contact.type">
<option>email</option> <option>email</option>
<option>phone</option> <option>phone</option>
<option>pager</option> <option>pager</option>
<option>IM</option> <option>IM</option>
</select> </select>
<input type="text" name="contact.value" ng:required/> <input type="text" name="contact.value" ng:required/>
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ] [ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
</div> </div>
<button ng:click="cancel()" disabled="{{master.$equals(form)}}">Cancel</button> <button ng:click="cancel()" disabled="{{master.$equals(form)}}">Cancel</button>
<button ng:click="save()" disabled="{{$invalidWidgets.visible() || <button ng:click="save()" disabled="{{$invalidWidgets.visible() ||
master.$equals(form)}}">Save</button> master.$equals(form)}}">Save</button>
<hr/> <hr/>
Debug View: Debug View:
<pre>form={{form}} <pre>form={{form}}
master={{master}}</pre> master={{master}}</pre>
</div> </div>
</doc:source> </doc:source>
<doc:scenario> <doc:scenario>
it('should enable save button', function(){ it('should enable save button', function(){
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy(); expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter(''); input('form.name').enter('');
@ -100,7 +100,7 @@ master.$equals(form)}}">Save</button>
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy(); expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
expect(element(':input[name=form.name]').val()).toEqual('John Smith'); expect(element(':input[name=form.name]').val()).toEqual('John Smith');
}); });
</doc:scenario> </doc:scenario>
</doc:example> </doc:example>
@ -109,15 +109,10 @@ master.$equals(form)}}">Save</button>
#Things to notice #Things to notice
* Cancel & save buttons are only enabled if the form is dirty -- there is something to cancel or * Cancel & save buttons are only enabled if the form is dirty there is something to cancel or
save. save.
* Save button is only enabled if there are no validation errors on the form. * Save button is only enabled if there are no validation errors on the form.
* Cancel reverts the form changes back to original state. * Cancel reverts the form changes back to original state.
* Save updates the internal model of the form. * Save updates the internal model of the form.
* Debug view shows the two models. One presented to the user form and the other being the pristine * Debug view shows the two models. One presented to the user form and the other being the pristine
copy master. copy master.

View file

@ -43,7 +43,7 @@ to retrieve Buzz activity and comments.
<img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/> <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a> <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
<a href="" ng:click="expandReplies(item)" style="float: right;"> <a href="" ng:click="expandReplies(item)" style="float: right;">
Expand replies: {{item.links.replies.count}} Expand replies: {{item.links.replies[0].count}}
</a> </a>
</h1> </h1>
{{item.object.content | html}} {{item.object.content | html}}

View file

@ -78,27 +78,19 @@ ng:validate="regexp:zip"/><br/><br/>
it('should validate zip', function(){ it('should validate zip', function(){
expect(using('.example').element(':input[name=user.address.zip]').attr('className')) expect(using('.example').element(':input[name=user.address.zip]').attr('className'))
.not().toMatch(/ng-validation-error/) .not().toMatch(/ng-validation-error/);
using('.example').input('user.address.zip').enter('abc'); using('.example').input('user.address.zip').enter('abc');
expect(using('.example').element(':input[name=user.address.zip]').attr('className')) expect(using('.example').element(':input[name=user.address.zip]').attr('className'))
.toMatch(/ng-validation-error/) .toMatch(/ng-validation-error/);
}); });
it('should validate state', function(){ it('should validate state', function(){
expect(using('.example').element(':input[name=user.address.state]').attr('className')) expect(using('.example').element(':input[name=user.address.state]').attr('className'))
.not().toMatch(/ng-validation-error/) .not().toMatch(/ng-validation-error/);
using('.example').input('user.address.state').enter('XXX'); using('.example').input('user.address.state').enter('XXX');
expect(using('.example').element(':input[name=user.address.state]').attr('className')) expect(using('.example').element(':input[name=user.address.state]').attr('className'))
.toMatch(/ng-validation-error/) .toMatch(/ng-validation-error/);
}); });
</doc:scenario> </doc:scenario>
</doc:example> </doc:example>

View file

@ -17,7 +17,7 @@ no connection between the controller and the view.
<doc:example> <doc:example>
<doc:source> <doc:source>
<script> <script>
function TicTacToeCntl($location){ function TicTacToeCntl($location){
this.$location = $location; this.$location = $location;
@ -34,8 +34,8 @@ no connection between the controller and the view.
} }
TicTacToeCntl.prototype = { TicTacToeCntl.prototype = {
dropPiece: function(row, col) { dropPiece: function(row, col) {
if (!this.winner && !this.board) { if (!this.winner && !this.board[row][col]) {
this.board = this.nextMove; this.board[row][col] = this.nextMove;
this.nextMove = this.nextMove == 'X' ? 'O' : 'X'; this.nextMove = this.nextMove == 'X' ? 'O' : 'X';
this.setUrl(); this.setUrl();
} }
@ -51,15 +51,15 @@ no connection between the controller and the view.
this.setUrl(); this.setUrl();
}, },
grade: function(){ grade: function(){
var b = this.board; var b = this.board;
this.winner = this.winner =
row(0) || row(1) || row(2) || row(0) || row(1) || row(2) ||
col(0) || col(1) || col(2) || col(0) || col(1) || col(2) ||
diagonal(-1) || diagonal(1); diagonal(-1) || diagonal(1);
function row(r) { return same(b, b, b);} function row(row) { return same(b[row][0], b[row][1], b[row][2]);}
function col(c) { return same(b, b, b);} function col(col) { return same(b[0][col], b[1][col], b[2][col]);}
function diagonal(i) { return same(b[1-i], b, b[1+i]);} function diagonal(i) { return same(b[0][1-i], b[1][1], b[2][1+i]);}
function same(a, b, c) { return (a==b && b==c) ? a : '';}; function same(a, b, c) { return (a==b && b==c) ? a : '';};
}, },
setUrl: function(){ setUrl: function(){
var rows = []; var rows = [];
@ -68,12 +68,12 @@ no connection between the controller and the view.
}); });
this.$location.hashSearch.board = rows.join(';') + '/' + this.nextMove; this.$location.hashSearch.board = rows.join(';') + '/' + this.nextMove;
}, },
readUrl: function(scope, value) { readUrl: function(value) {
if (value) { if (value) {
value = value.split('/'); value = value.split('/');
this.nextMove = value; this.nextMove = value[1];
angular.forEach(value.split(';'), function(row, i){ angular.forEach(value[0].split(';'), function(row, col){
this.board = row.split(','); this.board[col] = row.split(',');
}, this); }, this);
this.grade(); this.grade();
} else { } else {
@ -82,36 +82,38 @@ no connection between the controller and the view.
} }
}; };
</script> </script>
<h3>Tic-Tac-Toe</h3> <h3>Tic-Tac-Toe</h3>
<div ng:controller="TicTacToeCntl"> <div ng:controller="TicTacToeCntl">
Next Player: {{nextMove}} Next Player: {{nextMove}}
<div class="winner" ng:show="winner">Player {{winner}} has won!</div> <div class="winner" ng:show="winner">Player {{winner}} has won!</div>
<table class="board"> <table class="board">
<tr ng:repeat="row in board" style="height:15px;"> <tr ng:repeat="row in board" style="height:15px;">
<td ng:repeat="cell in row" ng:style="cellStyle" <td ng:repeat="cell in row" ng:style="cellStyle"
ng:click="dropPiece($parent.$index, $index)">{{cell}}</td> ng:click="dropPiece($parent.$index, $index)">{{cell}}</td>
</tr> </tr>
</table> </table>
<button ng:click="reset()">reset board</button> <button ng:click="reset()">reset board</button>
</div> </div>
</doc:source> </doc:source>
<doc:scenario> <doc:scenario>
it('should play a game', function(){ it('should play a game', function(){
piece(1, 1); piece(1, 1);
expect(binding('nextMove')).toEqual('O'); expect(binding('nextMove')).toEqual('O');
piece(3, 1); piece(3, 1);
expect(binding('nextMove')).toEqual('X'); expect(binding('nextMove')).toEqual('X');
piece(1, 2); piece(1, 2);
piece(3, 2); piece(3, 2);
piece(1, 3); piece(1, 3);
expect(element('.winner').text()).toEqual('Player X has won!'); expect(element('.winner').text()).toEqual('Player X has won!');
}); });
function piece(row, col) { function piece(row, col) {
element('.board tr:nth-child('+row+') td:nth-child('+col+')').click(); element('.board tr:nth-child('+row+') td:nth-child('+col+')').click();
} }
</doc:scenario> </doc:scenario>
</doc:example> </doc:example>
@ -123,13 +125,12 @@ no connection between the controller and the view.
* The controller is defined in JavaScript and has no reference to the rendering logic. * The controller is defined in JavaScript and has no reference to the rendering logic.
* The controller is instantiated by <angular/> and injected into the view. * The controller is instantiated by <angular/> and injected into the view.
* The controller can be instantiated in isolation (without a view) and the code will still execute. * The controller can be instantiated in isolation (without a view) and the code will still execute.
This makes it very testable. This makes it very testable.
* The HTML view is a projection of the model. In the above example, the model is stored in the * The HTML view is a projection of the model. In the above example, the model is stored in the
board variable. board variable.
* All of the controller's properties (such as board and nextMove) are available to the view. * All of the controller's properties (such as board and nextMove) are available to the view.
* Changing the model changes the view. * Changing the model changes the view.
* The view can call any controller function. * The view can call any controller function.
* In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's * In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's
hash so the browser's back button will undo game steps. See deep-linking. This example calls hash so the browser's back button will undo game steps. See deep-linking. This example calls {@link
{@link api/angular.scope.$watch $watch()} to set up a listener that invokes `readUrl()` when api/angular.scope.$watch $watch()} to set up a listener that invokes `readUrl()` when needed.
needed.

View file

@ -180,7 +180,7 @@ The unit test now verifies that the default ordering property is set.
We used Jasmine's API to extract the controller construction into a `beforeEach` block, which is We used Jasmine's API to extract the controller construction into a `beforeEach` block, which is
shared by all tests in the nearest `describe` block. shared by all tests in the parent `describe` block.
To run the unit tests, once again execute the `./scripts/test.sh` script and you should see the To run the unit tests, once again execute the `./scripts/test.sh` script and you should see the
@ -205,7 +205,7 @@ __`test/e2e/scenarios.js`:__
function() { function() {
// let's narrow the dataset to make the test assertions shorter // narrow the dataset to make the test assertions shorter
input('query').enter('tablet'); input('query').enter('tablet');

View file

@ -111,7 +111,7 @@ our model into the view.
__`app/partials/phone-details.html`:__ __`app/partials/phone-details.html`:__
<pre> <pre>
<img ng:src="{{phone.images}}" class="phone"/> <img ng:src="{{phone.images[0]}}" class="phone"/>
<h1>{{phone.name}}</h1> <h1>{{phone.name}}</h1>

View file

@ -42,7 +42,7 @@ function PhoneDetailCtrl($xhr) {
$xhr('GET', 'phones/' + self.params.phoneId + '.json', function(code, response) { $xhr('GET', 'phones/' + self.params.phoneId + '.json', function(code, response) {
self.phone = response; self.phone = response;
self.mainImageUrl = response.images; self.mainImageUrl = response.images[0];
}); });

View file

@ -102,7 +102,7 @@ function PhoneDetailCtrl(Phone_) {
self.phone = Phone_.get({phoneId: self.params.phoneId}, function(phone) { self.phone = Phone_.get({phoneId: self.params.phoneId}, function(phone) {
self.mainImageUrl = phone.images; self.mainImageUrl = phone.images[0];
}); });