Compare commits

..

33 Commits

Author SHA1 Message Date
Brian Ford 47a55ca767 docs(changelog): release notes for 1.3.8 prophetic-narwhal 2014-12-19 13:22:00 -08:00
sandeep 3d78bf3fa8 docs(guide/index): add book Responsive Web Design with AngularJS
This book explores the AngularJS features that can help a developer for building a responsive application.

Merçi beaucoup~

Closes #10513
2014-12-18 23:58:21 -05:00
Brian Ford 6e80d0ad54 docs(guide/$location): improve formatting 2014-12-18 15:01:51 -08:00
Ben Nelson ae637acdfb docs(api/index): grammar is important and so should you
I changed the word "into" to "within".
Original description underneath ngAnimate reads: "Use ngAnimate to enable animation features into your application".
I changed the text to read: "Use ngAnimate to enable animation features within your application".
The change in wording makes the description read better and gives it a more professional feel.

Closes #10517
2014-12-18 13:49:01 -05:00
Pawel Kozlowski 661f6d9ecf fix(orderBy): compare timestamps when sorting date objects
Fixes #10512
Closes #10516
2014-12-18 19:41:25 +01:00
Olivier Giulieri 56a7abd38f docs(guide): fix typo
Closes #10511
2014-12-18 18:43:30 +01:00
olexme 7d70dcdab1 docs($animate): fix misleading $animate.cancel example
The given example is wrong, you can't cancel the promise returned by "then"
since it is not the one originally tracked by "addClass".

Closes #10498
2014-12-17 20:14:22 +00:00
Todd Skinner 9e6161e579 docs($httpBackend): correct grammar
Closes #10496
2014-12-17 11:15:20 +00:00
Georgios Kalpakas bd28c74c1d fix(filterFilter): make $ match properties on deeper levels as well
Closes #10401
2014-12-17 10:17:07 +01:00
kwypchlo cd77c089ba perf(limitTo): replace for loop with slice 2014-12-16 22:43:46 +01:00
kwypchlo 83f88c1818 refactor(orderBy): remove unneeded function wrapping 2014-12-16 22:42:13 +01:00
Georgios Kalpakas fb2c585897 fix(filterFilter): let expression object {$: '...'} also match primitive items
Closes #10428
2014-12-16 22:40:34 +01:00
Kevin Primat bdbe4fd34a docs(Angular): improve sentence flow
Closes #10482
2014-12-16 19:04:05 +01:00
Kevin Primat 0b4e150aa5 docs(Angular): fix punctuation
Closes #10481
2014-12-16 19:02:02 +01:00
Jack Kingsman e091bb7dbb docs(error/badcfg): add missing "but"
Sentence meaning was unclear; added what I assumed should have been a "but"

Closes #10473
2014-12-16 14:31:24 +00:00
marmalade b62c858499 docs(guide/Scopes): fix capitalization
This sentence should begin with a capital 'R', not a lower case one.

Closes #10472
2014-12-16 14:29:53 +00:00
Chi Kei Chan 4a18274670 docs(guide/E2E Testing): add '-' to 'end-to-end'
Closes #10458
2014-12-16 14:28:45 +00:00
Zachary Lopez e3bf1ed217 docs(angular.identity): add @param and @returns tags
Closes #10457
2014-12-16 14:26:29 +00:00
Chi Kei Chan a5f037d033 docs($templateRequest): fix run-on sentence
The description of $templateRequest contains a run-on sentence that makes it confusing to understand.

ORGINAL: If the HTTP request fails or the response data of the HTTP request is empty then a `$compile` error will be thrown (the exception can be thwarted by setting the 2nd parameter of the function to true).

NEW: If the HTTP request fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted by setting the 2nd parameter of the function to true).

Closes #10456
2014-12-16 14:25:18 +00:00
Alexander Tseung 25152bb218 docs(tutorial/index): improve capitalization
Improve capitalization in acronyms for better clarity.
2014-12-16 14:21:27 +00:00
Aleksey Bobyr 24eb528b05 docs(guide/expression): update diff list between JavaScript and Angular expressions
add paragraphs about function declaration, comma and void operators and
RegExp to the diff list in the beginning of articule

Closes #10418
Closes #10452
2014-12-16 14:21:01 +00:00
thorn0 d161cc6b25 docs(select): improve formatting and wording
The part about using `select as` and `track by` together was hard to read.
And it wasn't clear what happens if they're used together.

Closes #10409
2014-12-16 14:18:51 +00:00
Jesús Rodríguez Rodríguez d604f941e8 fix(CHANGELOG): missing version number for 1.2.28
Well, the version number was missing there.
2014-12-16 12:44:07 +01:00
Peter Bacon Darwin 85758ce3af docs(CHANGELOG): remove reverted commit 2014-12-16 07:56:13 +00:00
Caitlin Potter 924e68c7d5 fix(ngAria): trigger digest on ng-click via keypress, pass $event to expression
Minor improvement to ng-click directive from ngAria. Now, if bindings are updated
during the click handler, the DOM will be updated as well. Additionally, the $event
object is passed in to the expression via locals, as is done for core event directives.

Closes #10442
Closes #10443
Closes #10447
2014-12-15 20:47:53 -05:00
Peter Bacon Darwin f297aa5d0a chore(CHANGELOG): update with changes for 1.2.28 2014-12-15 22:14:51 +00:00
Brenard Cubacub 337ce67612 docs(API Reference): fix punctuation
Closes #10453
2014-12-15 21:27:29 +01:00
Todd Skinner 8b56c08327 docs(angular.copy): fix grammar
Closes #10459
2014-12-15 21:24:53 +01:00
Peter Bacon Darwin 32eec67023 chore(CHANGELOG): update with v1.3.7 changes 2014-12-15 19:21:28 +00:00
Georgios Kalpakas fd1528a6c8 chore(CHANGELOG): add breaking change note for #9757 2014-12-15 18:48:06 +00:00
Chi Kei Chan 6cb5fbf5ef docs(error/badname): fix grammatical error
Closes #10460
2014-12-15 19:07:58 +01:00
Alexander Tseung f6644c720e docs(tutorial/step_08): fix capitalization
Closes #10466
2014-12-15 19:05:05 +01:00
Chi Kei Chan 0d9aafba3b docs(angular.fromJson): replace the word "Thingy"
Replace the word "thingy" with "JSON string" to specify what thingy means.

Closes #10468
2014-12-15 19:03:06 +01:00
23 changed files with 363 additions and 116 deletions
+129 -2
View File
@@ -1,3 +1,102 @@
<a name="1.3.8"></a>
# 1.3.8 prophetic-narwhal (2014-12-19)
## Bug Fixes
- **filterFilter:**
- make `$` match properties on deeper levels as well
([bd28c74c](https://github.com/angular/angular.js/commit/bd28c74c1d91c477a86f10fe36576cba0249e6ef),
[#10401](https://github.com/angular/angular.js/issues/10401))
- let expression object `{$: '...'}` also match primitive items
([fb2c5858](https://github.com/angular/angular.js/commit/fb2c58589758744c0eef8c2ead3dbcf27a5cf200),
[#10428](https://github.com/angular/angular.js/issues/10428))
- **ngAria:** trigger digest on `ng-click` via keypress, pass `$event` to expression
([924e68c7](https://github.com/angular/angular.js/commit/924e68c7d522a1086969f3583d0ce87e59110bc5),
[#10442](https://github.com/angular/angular.js/issues/10442), [#10443](https://github.com/angular/angular.js/issues/10443), [#10447](https://github.com/angular/angular.js/issues/10447))
- **orderBy:** compare timestamps when sorting date objects
([661f6d9e](https://github.com/angular/angular.js/commit/661f6d9ecf1459ce3b2794c3cde373e17ae83972),
[#10512](https://github.com/angular/angular.js/issues/10512), [#10516](https://github.com/angular/angular.js/issues/10516))
## Performance Improvements
- **limitTo:** replace for loop with slice
([cd77c089](https://github.com/angular/angular.js/commit/cd77c089ba2f4b94ccc74f32f0ffa9fb70851c02))
<a name="1.3.7"></a>
# 1.3.7 leaky-obstruction (2014-12-15)
## Bug Fixes
- **$compile:** use `createMap()` for `$$observe` listeners when initialized from attr interpolation
([8e28bb4c](https://github.com/angular/angular.js/commit/8e28bb4c2f6d015dfe1cec7755f1ca9b0ecef1f8))
- **$http:**
- only parse as JSON when opening/closing brackets match
([b9bdbe61](https://github.com/angular/angular.js/commit/b9bdbe615cc4070d2233ff06830a4c6fb1217cda),
[#10349](https://github.com/angular/angular.js/issues/10349), [#10357](https://github.com/angular/angular.js/issues/10357))
- don't convert FormData objects to JSON
([40258838](https://github.com/angular/angular.js/commit/40258838031604feecb862afdc6f1f503d80ce4a),
[#10373](https://github.com/angular/angular.js/issues/10373))
- **$parse:** a chain of field accessors should use a single `getterFn`
([c90ad968](https://github.com/angular/angular.js/commit/c90ad96808be350526516626205c3a7d1da79024))
- **ngRepeat:** allow extra whitespaces in `(key,value)` part of micro-syntax
([ef640cbc](https://github.com/angular/angular.js/commit/ef640cbc2af5794c987e75472c12e63a59590044),
[#6827](https://github.com/angular/angular.js/issues/6827), [#6833](https://github.com/angular/angular.js/issues/6833))
- **orderBy:** do not try to call `valueOf`/`toString` on `null`
([a097aa95](https://github.com/angular/angular.js/commit/a097aa95b7c78beab6d1b7d521c25f7d9d7843d9),
[#10385](https://github.com/angular/angular.js/issues/10385), [#10386](https://github.com/angular/angular.js/issues/10386))
## Features
- **$compile:** add support for `ng-attr` with camelCased attributes
([d8e37078](https://github.com/angular/angular.js/commit/d8e37078600089839f82f0e84022f1087e1fd3f2),
[#9845](https://github.com/angular/angular.js/issues/9845), [#10194](https://github.com/angular/angular.js/issues/10194))
- **$http:** pass response status code to data transform functions
([1b740974](https://github.com/angular/angular.js/commit/1b740974f5eb373bed04071d51f908ced7c5a8e5),
[#10324](https://github.com/angular/angular.js/issues/10324), [#6734](https://github.com/angular/angular.js/issues/6734), [#10440](https://github.com/angular/angular.js/issues/10440))
- **$rootScope:** allow passing `locals` argument to `$evalAsync`
([9b96cea4](https://github.com/angular/angular.js/commit/9b96cea462676d123e1b2dd852aedbe3da8fa4a0),
[#10390](https://github.com/angular/angular.js/issues/10390))
## Performance Improvements
- **$compile:** only re-`$interpolate` attribute values at link time if changed since compile
([9ae0c01c](https://github.com/angular/angular.js/commit/9ae0c01c2bcaff2f3906eec574f9c6ed8abde14a))
## Breaking Changes
- **orderBy:** due to [a097aa95](https://github.com/angular/angular.js/commit/a097aa95b7c78beab6d1b7d521c25f7d9d7843d9),
Previously, if either value being compared in the orderBy comparator was null or undefined, the
order would, incorrectly, not change. Now, this order behaves more like Array.prototype.sort, which
by default pushes `null` behind objects, due to `n` occurring after `[` (the first characters of their
stringified forms) in ASCII / Unicode. If `toString` is customized, or does not exist, the
behaviour is undefined.
<a name="1.2.28"></a>
# 1.2.28 finnish-disembarkation (2014-12-15)
## Bug Fixes
- **$route:** fix redirection with optional/eager params
([1b9e408d](https://github.com/angular/angular.js/commit/1b9e408ddbe48a6d3db27f501515d6efad01f42d),
[#9742](https://github.com/angular/angular.js/issues/9742), [#10202](https://github.com/angular/angular.js/issues/10202))
- **linky:** encode double quotes when serializing email addresses
([929dd15b](https://github.com/angular/angular.js/commit/929dd15b9b65034350f18abe6c56a8d956f4b978),
[#8945](https://github.com/angular/angular.js/issues/8945), [#8964](https://github.com/angular/angular.js/issues/8964), [#5946](https://github.com/angular/angular.js/issues/5946), [#10090](https://github.com/angular/angular.js/issues/10090), [#9256](https://github.com/angular/angular.js/issues/9256))
<a name="1.3.6"></a>
# 1.3.6 robofunky-danceblaster (2014-12-08)
@@ -17,7 +116,7 @@
- strip off empty hash segments when comparing
([e93710fe](https://github.com/angular/angular.js/commit/e93710fe0e4fb05ceee59a04f290692a5bec5d20),
[#9635](https://github.com/angular/angular.js/issues/9635))
- **$parse:**
- **$parse:**
- fix operators associativity
([ed1243ff](https://github.com/angular/angular.js/commit/ed1243ffc7c2cb4bd5b4dece597597db8eb08e34))
- follow JavaScript context for unbound functions
@@ -81,7 +180,7 @@
## Breaking Changes
- **$location:** due to [2dc34a96](https://github.com/angular/angular.js/commit/2dc34a969956eea680be4c8d9f800556d110996a),
We no longer throw an `ihshprfx` error if the URL after the base path
contains only a hash fragment. Previously, if the base URL was `http://abc.com/base/`
@@ -96,6 +195,34 @@ and hashPrfix are set up as above, then `http://abc.com/base/other/path` does no
throw an error but just ignores the extra path: `http://abc.com/base`.
- **filterFilter:** due to [a75537d4](https://github.com/angular/angular.js/commit/a75537d461c92e3455e372ff5005bf0cad2d2e95),
Named properties in the expression object will only match against properties on the **same level**.
Previously, named string properties would match against properties on the same level **or deeper**.
Before:
```js
arr = filterFilter([{level1: {level2: 'test'}}], {level1: 'test'}); // arr.length -> 1
```
After:
```js
arr = filterFilter([{level1: {level2: 'test'}}], {level1: 'test'}); // arr.length -> 0
```
In order to match deeper nested properties, you have to either match the depth level of the
property or use the special `$` key (which still matches properties on the same level
**or deeper**). E.g.:
```js
// Both examples below have `arr.length === 1`
arr = filterFilter([{level1: {level2: 'test'}}], {level1: {level2: 'test'}});
arr = filterFilter([{level1: {level2: 'test'}}], {$: 'test'});
```
<a name="1.3.5"></a>
# 1.3.5 cybernetic-mercantilism (2014-12-01)
+2 -2
View File
@@ -128,7 +128,7 @@ Use ngRoute to enable URL routing to your application. The ngRoute module suppor
## {@link ngAnimate ngAnimate}
Use ngAnimate to enable animation features into your application. Various core ng directives will provide
Use ngAnimate to enable animation features within your application. Various core ng directives will provide
animation hooks into your application when ngAnimate is included. Animations are defined by using CSS transitions/animations
or JavaScript callbacks.
@@ -273,7 +273,7 @@ Use ngSanitize to securely parse and manipulate HTML data in your application.
## {@link ngMock ngMock}
Use ngMock to inject and mock modules, factories, services and providers within your unit tests
Use ngMock to inject and mock modules, factories, services and providers within your unit tests.
<div class="alert alert-info">Include the **angular-mocks.js** file into your test runner for this to work.</div>
+1 -1
View File
@@ -3,7 +3,7 @@
@fullName Response does not match configured parameter
@description
This error occurs when the {@link ngResource.$resource `$resource`} service expects a response that can be deserialized as an array, receives an object, or vice versa.
This error occurs when the {@link ngResource.$resource `$resource`} service expects a response that can be deserialized as an array but receives an object, or vice versa.
By default, all resource actions expect objects, except `query` which expects arrays.
To resolve this error, make sure your `$resource` configuration matches the actual format of the data returned from the server.
+1 -1
View File
@@ -3,6 +3,6 @@
@fullName Bad `hasOwnProperty` Name
@description
Occurs when you try to use the name `hasOwnProperty` in a context where it is not allow.
Occurs when you try to use the name `hasOwnProperty` in a context where it is not allowed.
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
and allowing such a name would break lookups on this object.
+7 -7
View File
@@ -5,9 +5,9 @@
# What does it do?
The `$location` service parses the URL in the browser address bar (based on the [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL available to
your application. Changes to the URL in the address bar are reflected into $location service and
changes to $location are reflected into the browser address bar.
The `$location` service parses the URL in the browser address bar (based on [`window.location`](https://developer.mozilla.org/en/window.location)) and makes the URL available to
your application. Changes to the URL in the address bar are reflected into the `$location` service and
changes to `$location` are reflected into the browser address bar.
**The $location service:**
@@ -21,7 +21,7 @@ changes to $location are reflected into the browser address bar.
- Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
## Comparing $location to window.location
## Comparing `$location` to `window.location`
<table class="table">
<thead>
@@ -68,7 +68,7 @@ changes to $location are reflected into the browser address bar.
</tbody>
</table>
## When should I use $location?
## When should I use `$location`?
Any time your application needs to react to a change in the current URL or if you want to change
the current URL in the browser.
@@ -85,7 +85,7 @@ others customizing the configuration can enable new features.
Once the `$location` service is instantiated, you can interact with it via jQuery-style getter and
setter methods that allow you to get or change the current URL in the browser.
## $location service configuration
## `$location` service configuration
To configure the `$location` service, retrieve the
{@link ng.$locationProvider $locationProvider} and set the parameters as follows:
@@ -835,7 +835,7 @@ angular.module('locationExample', [])
# Related API
* {@link ng.$location $location API}
* {@link ng.$location `$location` API}
+4 -4
View File
@@ -6,7 +6,7 @@
# E2E Testing
<div class="alert alert-danger">
**Note:** In the past, end to end testing could be done with a deprecated tool called
**Note:** In the past, end-to-end testing could be done with a deprecated tool called
[Angular Scenario Runner](http://code.angularjs.org/1.2.16/docs/guide/e2e-testing). That tool
is now in maintenance mode.
</div>
@@ -14,7 +14,7 @@ is now in maintenance mode.
As applications grow in size and complexity, it becomes unrealistic to rely on manual testing to
verify the correctness of new features, catch bugs and notice regressions. Unit tests
are the first line of defense for catching bugs, but sometimes issues come up with integration
between components which can't be captured in a unit test. End to end tests are made to find
between components which can't be captured in a unit test. End-to-end tests are made to find
these problems.
We have built [Protractor](https://github.com/angular/protractor), an end
@@ -23,7 +23,7 @@ Angular application.
## Using Protractor
Protractor is a [Node.js](http://nodejs.org) program, and runs end to end tests that are also
Protractor is a [Node.js](http://nodejs.org) program, and runs end-to-end tests that are also
written in JavaScript and run with node. Protractor uses [WebDriver](https://code.google.com/p/selenium/wiki/GettingStarted)
to control browsers and simulate user actions.
@@ -77,7 +77,7 @@ filter the list of items.
## Example
See the [angular-seed](https://github.com/angular/angular-seed) project for more examples, or look
at the embedded examples in the Angular documentation (For example, {@link $http $http}
has an end to end test in the example under the `protractor.js` tag).
has an end-to-end test in the example under the `protractor.js` tag).
## Caveats
+13 -5
View File
@@ -26,8 +26,16 @@ Angular expressions are like JavaScript expressions with the following differenc
* **Forgiving:** In JavaScript, trying to evaluate undefined properties generates `ReferenceError`
or `TypeError`. In Angular, expression evaluation is forgiving to `undefined` and `null`.
* **No Control Flow Statements:** you cannot use the following in an Angular expression:
* **No Control Flow Statements:** You cannot use the following in an Angular expression:
conditionals, loops, or exceptions.
* **No Function Declarations:** You cannot declare functions in an Angular expression,
even inside `ng-init` directive.
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
in an Angular expression.
* **No Comma And Void Operators:** You cannot use `,` or `void` in an Angular expression.
* **Filters:** You can use {@link guide/filter filters} within expressions to format data before
displaying it.
@@ -164,11 +172,11 @@ expression. The reason behind this is core to the Angular philosophy that applic
be in controllers, not the views. If you need a real conditional, loop, or to throw from a view
expression, delegate to a JavaScript method instead.
## No RegExp creation with literal notation
## No function declarations or RegExp creation with literal notation
You can't create regular expressions from within AngularJS expressions. This is to avoid complex
model transformation logic inside templates. Such logic is better placed in a controller or in a dedicated
filter where it can be tested properly.
You can't declare functions or create regular expressions from within AngularJS expressions. This is
to avoid complex model transformation logic inside templates. Such logic is better placed in a
controller or in a dedicated filter where it can be tested properly.
## `$event`
+1
View File
@@ -109,6 +109,7 @@ This is a short list of libraries with specific support and documentation for wo
* [ng-book: The Complete Book on AngularJS](http://ng-book.com/) by Ari Lerner
* [AngularJS : Novice to Ninja](http://www.amazon.in/AngularJS-Novice-Ninja-Sandeep-Panda/dp/0992279453) by Sandeep Panda
* [AngularJS UI Development](http://www.amazon.com/AngularJS-UI-Development-Amit-Ghart-ebook/dp/B00OXVAK7A) by Amit Gharat and Matthias Nehlsen
* [Responsive Web Design with AngularJS](http://www.amazon.com/Responsive-Design-AngularJS-Sandeep-Kumar/dp/178439842X) by Sandeep Kumar Patel
###Videos:
* [egghead.io](http://egghead.io/)
+1 -1
View File
@@ -177,7 +177,7 @@ for example, only a portion of the view needs to be controlled by Angular.
To examine the scope in the debugger:
1. right click on the element of interest in your browser and select 'inspect element'. You
1. Right click on the element of interest in your browser and select 'inspect element'. You
should see the browser debugger with the element you clicked on highlighted.
2. The debugger allows you to access the currently selected element in the console as `$0`
+3 -3
View File
@@ -16,8 +16,8 @@ about the phones in the catalog.
## Data
Note that the `phones.json` file contains unique ids and image urls for each of the phones. The
urls point to the `app/img/phones/` directory.
Note that the `phones.json` file contains unique IDs and image URLs for each of the phones. The
URLs point to the `app/img/phones/` directory.
__`app/phones/phones.json`__ (sample snippet):
@@ -59,7 +59,7 @@ the element attribute.
We also added phone images next to each record using an image tag with the {@link
ng.directive:ngSrc ngSrc} directive. That directive prevents the
browser from treating the Angular `{{ expression }}` markup literally, and initiating a request to
invalid url `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had only
invalid URL `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had only
specified an attribute binding in a regular `src` attribute (`<img src="{{phone.imageUrl}}">`).
Using the `ngSrc` directive prevents the browser from making an http request to an invalid location.
+2 -2
View File
@@ -20,7 +20,7 @@ fleshed out the `phone-detail.html` view template.
## Data
In addition to `phones.json`, the `app/phones/` directory also contains one json file for each
In addition to `phones.json`, the `app/phones/` directory also contains one JSON file for each
phone:
__`app/phones/nexus-s.json`:__ (sample snippet)
@@ -53,7 +53,7 @@ show this data in the phone detail view.
## Controller
We'll expand the `PhoneDetailCtrl` by using the `$http` service to fetch the json files. This works
We'll expand the `PhoneDetailCtrl` by using the `$http` service to fetch the JSON files. This works
the same way as the phone list controller.
__`app/js/controllers.js`:__
+6 -4
View File
@@ -401,6 +401,8 @@ noop.$inject = [];
return (transformationFn || angular.identity)(value);
};
```
* @param {*} value to be returned.
* @returns {*} the value passed in.
*/
function identity($) {return $;}
identity.$inject = [];
@@ -655,7 +657,7 @@ function arrayRemove(array, value) {
* Creates a deep copy of `source`, which should be an object or an array.
*
* * If no destination is supplied, a copy of the object or array is created.
* * If a destination is provided, all of its elements (for array) or properties (for objects)
* * If a destination is provided, all of its elements (for arrays) or properties (for objects)
* are deleted and then all elements/properties from the source are copied to it.
* * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
* * If `source` is identical to 'destination' an exception will be thrown.
@@ -993,7 +995,7 @@ function toJson(obj, pretty) {
* Deserializes a JSON string.
*
* @param {string} json JSON string to deserialize.
* @returns {Object|Array|string|number} Deserialized thingy.
* @returns {Object|Array|string|number} Deserialized JSON string.
*/
function fromJson(json) {
return isString(json)
@@ -1166,7 +1168,7 @@ function getNgAttribute(element, ngAttr) {
* {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
*
* You can specify an **AngularJS module** to be used as the root module for the application. This
* module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
* module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
* should contain the application code needed or have dependencies on other modules that will
* contain the code. See {@link angular.module} for more information.
*
@@ -1174,7 +1176,7 @@ function getNgAttribute(element, ngAttr) {
* document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
* would not be resolved to `3`.
*
* `ngApp` is the easiest, and most common, way to bootstrap an application.
* `ngApp` is the easiest, and most common way to bootstrap an application.
*
<example module="ngAppDemo">
<file name="index.html">
+45 -21
View File
@@ -13,14 +13,15 @@ var ngOptionsMinErr = minErr('ngOptions');
*
* The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
* elements for the `<select>` element using the array or object obtained by evaluating the
* `ngOptions` comprehension_expression.
* `ngOptions` comprehension expression.
*
* In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
* similar result. However, the `ngOptions` provides some benefits such as reducing memory and
* similar result. However, `ngOptions` provides some benefits such as reducing memory and
* increasing speed by not creating a new scope for each repeated instance, as well as providing
* more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions` should be
* used when the `select` model needs to be bound to a non-string value. This is because an option
* element can only be bound to string values at present.
* more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
* comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
* to a non-string value. This is because an option element can only be bound to string values at
* present.
*
* When an item in the `<select>` menu is selected, the array element or object property
* represented by the selected option will be bound to the model identified by the `ngModel`
@@ -35,28 +36,51 @@ var ngOptionsMinErr = minErr('ngOptions');
* array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
* </div>
*
* ## `select as`
* ## `select` **`as`**
*
* Using `select as` will bind the result of the `select as` expression to the model, but
* Using `select` **`as`** will bind the result of the `select` expression to the model, but
* the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
* or property name (for object data sources) of the value within the collection. If a `track by` expression
* or property name (for object data sources) of the value within the collection. If a **`track by`** expression
* is used, the result of that expression will be set as the value of the `option` and `select` elements.
*
* ### `select as` with `track by`
*
* Using `select as` together with `track by` is not recommended. Reasoning:
* ### `select` **`as`** and **`track by`**
*
* <div class="alert alert-warning">
* Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
* </div>
*
* Consider the following example:
*
* ```html
* <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
* ```
*
* ```js
* $scope.values = [{
* id: 1,
* label: 'aLabel',
* subItem: { name: 'aSubItem' }
* }, {
* id: 2,
* label: 'bLabel',
* subItem: { name: 'bSubItem' }
* }];
*
* $scope.selected = { name: 'aSubItem' };
* ```
*
* With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
* of the data source (to `item` in this example). To calculate whether an element is selected, we do the
* following:
*
* 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
* 2. Apply **`track by`** to the already selected value in `ngModel`.
* In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
* value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
* a wrong object, the selected element can't be found, `<select>` is always reset to the "not
* selected" option.
*
* - Example: &lt;select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"&gt;
* values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}],
* $scope.selected = {name: 'aSubItem'};
* - track by is always applied to `value`, with the purpose of preserving the selection,
* (to `item` in this case)
* - to calculate whether an item is selected we do the following:
* 1. apply `track by` to the values in the array, e.g.
* In the example: [1,2]
* 2. apply `track by` to the already selected value in `ngModel`:
* In the example: this is not possible, as `track by` refers to `item.id`, but the selected
* value from `ngModel` is `{name: aSubItem}`.
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
+26 -15
View File
@@ -14,19 +14,26 @@
*
* Can be one of:
*
* - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
* the contents of the `array`. All strings or objects with string properties in `array` that contain this string
* will be returned. The predicate can be negated by prefixing the string with `!`.
* - `string`: The string is used for matching against the contents of the `array`. All strings or
* objects with string properties in `array` that match this string will be returned. This also
* applies to nested object properties.
* The predicate can be negated by prefixing the string with `!`.
*
* - `Object`: A pattern object can be used to filter specific properties on objects contained
* by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
* which have property `name` containing "M" and property `phone` containing "1". A special
* property name `$` can be used (as in `{$:"text"}`) to accept a match against any
* property of the object. That's equivalent to the simple substring match with a `string`
* as described above. The predicate can be negated by prefixing the string with `!`.
* For Example `{name: "!M"}` predicate will return an array of items which have property `name`
* property of the object or its nested object properties. That's equivalent to the simple
* substring match with a `string` as described above. The predicate can be negated by prefixing
* the string with `!`.
* For example `{name: "!M"}` predicate will return an array of items which have property `name`
* not containing "M".
*
* Note that a named property will match properties on the same level only, while the special
* `$` property will match properties on the same level or deeper. E.g. an array item like
* `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
* **will** be matched by `{$: 'John'}`.
*
* - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
* function is called for each element of `array`. The final result is an array of those
* elements that the predicate returned true for.
@@ -39,10 +46,10 @@
*
* - `function(actual, expected)`:
* The function will be given the object value and the predicate value to compare and
* should return true if the item should be included in filtered result.
* should return true if both values should be considered equal.
*
* - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
* this is essentially strict comparison of expected and actual.
* - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
* This is essentially strict comparison of expected and actual.
*
* - `false|undefined`: A short hand for a function which will look for a substring match in case
* insensitive way.
@@ -145,6 +152,7 @@ function filterFilter() {
// Helper functions for `filterFilter`
function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
var predicateFn;
if (comparator === true) {
@@ -163,13 +171,16 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
}
predicateFn = function(item) {
if (shouldMatchPrimitives && !isObject(item)) {
return deepCompare(item, expression.$, comparator, false);
}
return deepCompare(item, expression, comparator, matchAgainstAnyProp);
};
return predicateFn;
}
function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
var actualType = typeof actual;
var expectedType = typeof expected;
@@ -188,11 +199,11 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
var key;
if (matchAgainstAnyProp) {
for (key in actual) {
if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
return true;
}
}
return false;
return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
} else if (expectedType === 'object') {
for (key in expected) {
var expectedVal = expected[key];
@@ -200,9 +211,9 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
continue;
}
var keyIsDollar = key === '$';
var actualVal = keyIsDollar ? actual : actual[key];
if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar)) {
var matchAnyProperty = key === '$';
var actualVal = matchAnyProperty ? actual : actual[key];
if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
return false;
}
}
+5 -7
View File
@@ -106,8 +106,7 @@ function limitToFilter() {
}
}
var out = [],
i, n;
var i, n;
// if abs(limit) exceeds maximum length, trim it
if (limit > input.length)
@@ -119,14 +118,13 @@ function limitToFilter() {
i = 0;
n = limit;
} else {
// zero and NaN check on limit - return empty array
if (!limit) return [];
i = input.length + limit;
n = input.length;
}
for (; i < n; i++) {
out.push(input[i]);
}
return out;
return input.slice(i, n);
};
}
+5 -7
View File
@@ -130,9 +130,7 @@ function orderByFilter($parse) {
}
if (predicate === '') {
// Effectively no predicate was passed so we compare identity
return reverseComparator(function(a, b) {
return compare(a, b);
}, descending);
return reverseComparator(compare, descending);
}
get = $parse(predicate);
if (get.constant) {
@@ -174,14 +172,14 @@ function orderByFilter($parse) {
function objectToString(value) {
if (value === null) return 'null';
if (typeof value.toString === 'function') {
value = value.toString();
if (isPrimitive(value)) return value;
}
if (typeof value.valueOf === 'function') {
value = value.valueOf();
if (isPrimitive(value)) return value;
}
if (typeof value.toString === 'function') {
value = value.toString();
if (isPrimitive(value)) return value;
}
return '';
}
+1 -1
View File
@@ -9,7 +9,7 @@ var $compileMinErr = minErr('$compile');
* @description
* The `$templateRequest` service downloads the provided template using `$http` and, upon success,
* stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
* of the HTTP request is empty then a `$compile` error will be thrown (the exception can be thwarted
* of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
* by setting the 2nd parameter of the function to true).
*
* @param {string} tpl The HTTP request template URL
+2 -1
View File
@@ -833,7 +833,8 @@ angular.module('ngAnimate', ['ng'])
* promise that was returned when the animation was started.
*
* ```js
* var promise = $animate.addClass(element, 'super-long-animation').then(function() {
* var promise = $animate.addClass(element, 'super-long-animation');
* promise.then(function() {
* //this will still be called even if cancelled
* });
*
+19 -12
View File
@@ -297,21 +297,28 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
}
};
})
.directive('ngClick',['$aria', function($aria) {
.directive('ngClick',['$aria', '$parse', function($aria, $parse) {
return {
restrict: 'A',
link: function(scope, elem, attr) {
if ($aria.config('tabindex') && !elem.attr('tabindex')) {
elem.attr('tabindex', 0);
}
compile: function(elem, attr) {
var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
return function(scope, elem, attr) {
if ($aria.config('tabindex') && !elem.attr('tabindex')) {
elem.attr('tabindex', 0);
}
if ($aria.config('bindKeypress') && !elem.attr('ng-keypress')) {
elem.on('keypress', function(event) {
if (event.keyCode === 32 || event.keyCode === 13) {
scope.$eval(attr.ngClick);
}
});
}
if ($aria.config('bindKeypress') && !attr.ngKeypress) {
elem.on('keypress', function(event) {
if (event.keyCode === 32 || event.keyCode === 13) {
scope.$apply(callback);
}
function callback() {
fn(scope, { $event: event });
}
});
}
};
}
};
}])
+14 -14
View File
@@ -1276,7 +1276,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1290,7 +1290,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1304,7 +1304,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1320,7 +1320,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1336,7 +1336,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1349,7 +1349,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
*
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1370,7 +1370,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* is in JSON format.
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current expectation.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*
@@ -1405,7 +1405,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled. See #expect for more info.
*/
@@ -1419,7 +1419,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1433,7 +1433,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1450,7 +1450,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1467,7 +1467,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1484,7 +1484,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
@@ -1497,7 +1497,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
*
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
* and returns true if the url match the current definition.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
+49 -6
View File
@@ -65,6 +65,33 @@ describe('Filter: filter', function() {
});
it('should match primitive array values against top-level `$` property in object expression',
function() {
var items, expr;
items = ['something', 'something else', 'another thing'];
expr = {$: 'some'};
expect(filter(items, expr).length).toBe(2);
expect(filter(items, expr)).toEqual([items[0], items[1]]);
items = [{val: 'something'}, {val: 'something else'}, {val: 'another thing'}];
expr = {$: 'some'};
expect(filter(items, expr).length).toBe(2);
expect(filter(items, expr)).toEqual([items[0], items[1]]);
items = [123, 456, 789];
expr = {$: 1};
expect(filter(items, expr).length).toBe(1);
expect(filter(items, expr)).toEqual([items[0]]);
items = [true, false, 'true'];
expr = {$: true, ignored: 'false'};
expect(filter(items, expr).length).toBe(2);
expect(filter(items, expr)).toEqual([items[0], items[2]]);
}
);
it('should take object as predicate', function() {
var items = [{first: 'misko', last: 'hevery'},
{first: 'adam', last: 'abrons'}];
@@ -136,14 +163,30 @@ describe('Filter: filter', function() {
});
it('should respect the depth level of a "$" property', function() {
var items = [{person: {name: 'Annet', email: 'annet@example.com'}},
{person: {name: 'Billy', email: 'me@billy.com'}},
{person: {name: 'Joan', email: {home: 'me@joan.com', work: 'joan@example.net'}}}];
var expr = {person: {$: 'net'}};
it('should match named properties only against named properties on the same level', function() {
var expr = {person: {name: 'John'}};
var items = [{person: 'John'}, // No match (1 level higher)
{person: {name: 'John'}}, // Match (same level)
{person: {name: {first: 'John', last: 'Doe'}}}]; // No match (1 level deeper)
expect(filter(items, expr).length).toBe(1);
expect(filter(items, expr)).toEqual([items[0]]);
expect(filter(items, expr)).toEqual([items[1]]);
});
it('should match any properties on same or deeper level for given "$" property', function() {
var items = [{level1: 'test', foo1: 'bar1'},
{level1: {level2: 'test', foo2:'bar2'}, foo1: 'bar1'},
{level1: {level2: {level3: 'test', foo3: 'bar3'}, foo2: 'bar2'}, foo1: 'bar1'}];
expect(filter(items, {$: 'ES'}).length).toBe(3);
expect(filter(items, {$: 'ES'})).toEqual([items[0], items[1], items[2]]);
expect(filter(items, {level1: {$: 'ES'}}).length).toBe(2);
expect(filter(items, {level1: {$: 'ES'}})).toEqual([items[1], items[2]]);
expect(filter(items, {level1: {level2: {$: 'ES'}}}).length).toBe(1);
expect(filter(items, {level1: {level2: {$: 'ES'}}})).toEqual([items[2]]);
});
+10
View File
@@ -79,6 +79,16 @@ describe('Filter: orderBy', function() {
{ a:new Date('01/01/2014'), b:3 }]);
});
it('should compare timestamps when sorting dates', function() {
expect(orderBy([
new Date('01/01/2015'),
new Date('01/01/2014')
])).toEqualData([
new Date('01/01/2014'),
new Date('01/01/2015')
]);
});
it('should use function', function() {
expect(
+17
View File
@@ -509,6 +509,23 @@ describe('$aria', function() {
expect(clickFn).not.toHaveBeenCalled();
expect(keypressFn).toHaveBeenCalled();
});
it('should update bindings when keypress handled', function() {
compileInput('<div ng-click="text = \'clicked!\'">{{text}}</div>');
expect(element.text()).toBe('');
spyOn(scope.$root, '$digest').andCallThrough();
element.triggerHandler({ type: 'keypress', keyCode: 13 });
expect(element.text()).toBe('clicked!');
expect(scope.$root.$digest).toHaveBeenCalledOnce();
});
it('should pass $event to ng-click handler as local', function() {
compileInput('<div ng-click="event = $event">{{event.type}}' +
'{{event.keyCode}}</div>');
expect(element.text()).toBe('');
element.triggerHandler({ type: 'keypress', keyCode: 13 });
expect(element.text()).toBe('keypress13');
});
});
describe('actions when bindKeypress set to false', function() {