Compare commits

...

61 Commits

Author SHA1 Message Date
Peter Bacon Darwin 5a3504abdc docs(CHANGELOG): add changes for 1.5.0-rc.2 2016-01-28 09:51:01 +00:00
Martin Staffa 0dfc1dfebf fix(ngTouch): deprecate ngClick and disable it by default
This commit deprecates the ngClick directive from the ngTouch module.
Additionally, it disables it by default. It can be enabled in the new $touchProvider with
the $touchProvider.ngClickOverrideEnabled() method.

The directive was conceived to remove the 300ms delay
for click events on mobile browsers, by sending a synthetic click event on touchstart.
It also tried to make sure that the original click event that the browser sends after 300ms
was "busted", so that no redundant "ghost-clicks" appear.

There are various reasons why the directive is being deprecated.

- "This is an ugly, terrible hack!" (says so in the source)
- It is plagued by various bugs that are hard to fix / test for all platforms (see below)
- Simply including ngTouch activates the ngClick override, which means even if you simply want
to use ngSwipe, you may break parts of your app
- There exist alternatives for removing the 300ms delay, that can be used very well with Angular:
[FastClick](https://github.com/ftlabs/fastclick), [Tappy!](https://github.com/filamentgroup/tappy/)
(There's also hammer.js for touch events / gestures)
- The 300ms delay itself is on the way out - Chrome and Firefox for Android remove the 300ms delay
when the usual `<meta name="viewport" content="width=device-width">` is set. In IE, the
`touch-action` css property can be set to `none` or `manipulation` to remove the delay. Finally,
since iOs 8, Safari doesn't delay "slow" taps anymore. There are some caveats though, which can be
found in this excellent article on which this summary is based: http://developer.telerik.com/featured/300-ms-click-delay-ios-8/

Note that this change does not affect the `ngSwipe` directive.

Issues with interactive elements (input, a etc.) when parent element has ngClick:
Closes #4030
Closes #5307
Closes #6001
Closes #6432
Closes #7231
Closes #11358
Closes #12082
Closes #12153
Closes #12392
Closes #12545
Closes #12867
Closes #13213
Closes #13558

Other issues:
- incorrect event order
- incorrect event propagation
- ghost-clicks / failing clickbusting with corner cases
- browser specific bugs
- et al.

Closes #3296
Closes #3347
Closes #3447
Closes #3999
Closes #4428
Closes #6251
Closes #6330
Closes #7134
Closes #7935
Closes #9724
Closes #9744
Closes #9872
Closes #10211
Closes #10366
Closes #10918
Closes #11197
Closes #11261
Closes #11342
Closes #11577
Closes #12150
Closes #12317
Closes #12455
Closes #12734
Closes #13122
Closes #13272
Closes #13447

BREAKING CHANGE:

The `ngClick` override directive from the `ngTouch` module is **deprecated and disabled by default**.
This means that on touch-based devices, users might now experience a 300ms delay before a click event is fired.

If you rely on this directive, you can still enable it with the `$touchProvider.ngClickOverrideEnabled()`method:

```js
angular.module('myApp').config(function($touchProvider) {
  $touchProvider.ngClickOverrideEnabled(true);
});
```

For migration, we recommend using [FastClick](https://github.com/ftlabs/fastclick).
Also note that modern browsers remove the 300ms delay under some circumstances:
- Chrome and Firefox for Android remove the 300ms delay when the well-known `<meta name="viewport" content="width=device-width">` is set
- Internet Explorer removes the delay when  `touch-action` css property is set to `none` or `manipulation`
- Since iOs 8, Safari removes the delay on so-called "slow taps"

See this [article by Telerik](http://developer.telerik.com/featured/300-ms-click-delay-ios-8/) for more info on the topic.
Note that this change does not affect the `ngSwipe` directive.
2016-01-27 20:23:02 +01:00
Martin Staffa e9c406b246 fix($animateCss): cancel fallback timeout when animation ends normally
Previously, css animations would not cancel the timeout when the
animation ends normally (calling end explicitly / transitionEnd event).
This meant that the timeout callback fn was always called after 150% of
the animation time was over. Since the animation was already closed at this
point, it would not do any work twice, but simply remove the timer data
from the element.
This commit changes the behavior to cancel the timeout and remove the data
when it is found during animation closing.

Closes #13787
2016-01-27 19:27:34 +01:00
Matias Niemelä 79b6d55792 chore(travis): add an integration hook for the angular hubot daemon
Closes #13777
2016-01-27 17:47:33 +00:00
Georgios Kalpakas 8f94b5b277 docs(CHANGELOG): remove duplicates and fix typos
Removed some entries from `v1.5.0-beta.2` which are also included in `v1.5.0-beta.1`
and fixed some typos.

Closes #13858
2016-01-27 16:46:08 +00:00
Isaac b11120be0a docs($cookiesProvider): clarify parameters description
Fixed a grammatical mistake ("equals to"), made hyphenation consistent, fixed punctuation and
clarified the sentence structure.

Closes #13853
2016-01-27 16:30:46 +01:00
Martin Staffa bfba95ce46 docs($resource): fix an unmatched link 2016-01-27 16:30:46 +01:00
Thomas Moffett 310f80e78e docs(guide): change concepts.graffle/data.plist to fix 'World' spelling
The change is only to concepts.graffle/data.plist to fix 'World' spelling.
Another PR, #13724, already fixed the actual image.

Closes #13704
Closes #13734
2016-01-27 15:00:47 +00:00
Lucas Mirelmann acfda1022d fix($parse): Preserve expensive checks when runnning $eval inside an expression
When running an expression with expensive checks, there is a call to `$eval` or `$evalAsync`
then that expression is also evaluated using expensive checks

Closes: #13850
2016-01-27 15:30:50 +01:00
robw 04d4d93e5b docs(ngModel): add section explaining that ngModel watches by reference
The new section explains that changing only a property on an object doesn't
trigger re-rendering.

Closes #13224
Closes #13518
2016-01-27 14:24:34 +00:00
Georgios Kalpakas 8348365df9 fix($compile): properly denormalize templates when only one of the start/end symbols is different
Previously, if either of the start/end interpolation symbols remained unchanged (i.e. `{{` or `}}`),
then directive templates would not be denormalized properly. Changing only one of the start/end
symbols (but not both) is an uncommon but legitimate usecase.

Closes #13848
2016-01-26 20:16:49 +02:00
Georgios Kalpakas 16bcdcb61d docs(guide/migration): add notes for migrating from 1.4 to 1.5
Part of #13474 (includes changes up until `v1.5.0-rc.1`)
Closes #13808
2016-01-26 20:09:54 +02:00
Leo Gallucci adcfa74327 docs(guide/directives): improve Protractor test for bindings
This needs Protractor >= 1.3.0 to work.

Closes #9330
2016-01-26 15:09:02 +01:00
Michal Raczkowski d641901be6 feat($resource): add support for timeout in cancellable actions
Old behavior: actions can be either cancellable or have a numeric timeout.
When having both defined, cancellable was ignored.
With this commit: it's possible for actions to have both cancellable:true
and numeric timeout defined.

Example usage:

```js
var Post = $resource('/posts/:id', {id: '@id'}, {
  get: {
    method: 'GET',
    cancellable: true,
    timeout: 10000
  }
});

var currentPost = Post.get({id: 1});
...
// the next request can cancel the previous one
currentPost.$cancelRequest();
currentPost = Post.get({id: 2});

// any of those requests will also timeout, if the response
// doesn't come within 10 seconds
```

Closes #13824
2016-01-26 13:59:28 +02:00
Peter Bacon Darwin eae0a1121f chore(ngLocale): regenerate locales to include original localeId
Closes #13390
2016-01-26 11:27:22 +00:00
Peter Bacon Darwin 173c9063e7 style(i18n): improve indentation for readability 2016-01-26 11:27:14 +00:00
Peter Bacon Darwin b461551b81 chore(i18n): fix up i18n testing tools 2016-01-26 11:27:14 +00:00
Peter Bacon Darwin 63492a0261 feat($locale): Include original locale ID in $locale
Most systems use *IETF language tag* codes which are typically a combination
of the ISO 639 language code and ISO 3166-1 country code with an underscore
or hyphen delimiter. For example `en_US`, `en_AU`, etc.

Whilst the `$locale.id` comes close, the lowercase format makes it impossible
to transform to an IETF tag reliably. For example, it would be impossible
to deduce `en_Dsrt_US` from `en-dsrt-us`.

Closes #13390
2016-01-26 11:27:13 +00:00
Robert Reiz adb0e1746b docs(bower.json): add MIT license
Closes #13405
2016-01-26 11:03:28 +00:00
Zac Smith 3be79cd6a1 docs(tutorial): fix typo
Closes #13843
2016-01-26 11:07:58 +02:00
Martin Staffa e4c6e01791 docs($sceDelegateProvider): fix markdown errors
Closes #13360
2016-01-25 22:59:27 +01:00
Martin Staffa fb76d96009 docs(guide/interpolation): fix dangling link 2016-01-25 22:52:44 +01:00
Martin Staffa f322c4f3c3 docs(guide/directives): link to the scope property docs
Closes #12500
2016-01-25 22:52:44 +01:00
Robin Glauser 081f6ec7f2 docs(error/modulerr): add additional debugging help
This simple tip can help to diagnose the error.

Closes #12958
2016-01-25 17:07:20 +00:00
Moorzee 9bb6a30417 docs(tutorial/Tutorial): Java installation
Add step to ensure java is installed on development machine.

Closes #12938
2016-01-25 16:52:25 +00:00
marianoc84 97e97d1eb7 docs(guide/Modules): update style guide link
The linked blog post recommends John Papa's Guide.

Closes #12898
2016-01-25 16:34:16 +00:00
Lucas Galfaso 1ab4e44443 fix(dateFilter): follow the CLDR on pattern escape sequences
When there are two single quotes "''" (quotes for clarification) that are not
part of an escape sequence, then this sequence should be handled as one single
quote. See http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
second and forth examples

Closes #12839
2016-01-25 14:54:15 +00:00
Livvie Lin 99eeec358c style(src): delete whitespace and use single quotes
This change edits syntax for code consistency.

It removes whitespace to match the style of the rest of the code,
and changes double quotes to single quotes to conform with
Google's JavaScript Style Guide.

Closes #12889
2016-01-25 14:52:29 +00:00
Tobias Leugger - Vibes ce8a7525cc docs(error/unpr): add hint about using ngStrictDi
The unknown provider error often happens when code is minified and one
did not use the correct syntax that supports minification. It's
frustrating to have to hunt for a bug in minified code, so adding the
simple hint that `ngStrictDi` will tell you what is wrong in the original
code will save you quite some trouble.

Closes #12717
2016-01-25 14:40:24 +00:00
Martin Raifer 5df2e5ce29 docs(tutorial/step-7): add troubleshooting instructions
Show troubleshooting instructions as in step 11.

Closes #12715
2016-01-25 14:37:00 +00:00
Alireza Mirian ef03dfc4a4 docs($injector): fix inaccuracy in $provide.service docs
Closes #12664
Closes #12665
2016-01-25 14:33:16 +00:00
Wesley Cho 4ff9c027b0 docs(compile): improve nonassign error message
- Improve error message to mention attribute the expression errored on

Fixes #13827

Closes #13828
2016-01-24 17:17:35 +01:00
Matias Niemelä 20b8ece444 fix(ngAnimate): properly cancel-out previously running class-based animations
Prior to this fix the addition and removal of a CSS class via
ngAnimate would cause flicker effects because $animate was unable
to keep track of the CSS classes once they were applied to the
element. This fix ensures that ngAnimate always keeps a reference
to the classes in the currently running animation so that cancelling
works accordingly.

The commit also adds a test for a previously untested animation merge path.

Closes #10156
Closes #13822
2016-01-23 16:28:51 +01:00
Qingyu Zhou 6406e3b01d docs(tutorial/step_12): change "click" to "hover"
Should be "hover" not "click", since we trigger the change at "mouseenter", not "click".

Closes #13831
2016-01-23 14:21:24 +02:00
Lucas Mirelmann 234053fc9a fix(ngSanitize): Blacklist the attribute usemap
Given that the attribute `name` is blacklisted, the attribute `usemap` should be
blacklisted too.

Closes: ##13826
2016-01-22 21:16:31 +01:00
Josh Duff a277bcf0f7 refactor(equals): Cleanup equals function for readability
- Removes unnecessary nested if condition
- Simplify check when one argument is a regex

Closes: #13650
2016-01-22 20:52:38 +01:00
Peter Bacon Darwin 7985416d39 docs(CHANGELOG): fix animation grouping 2016-01-21 14:30:35 +00:00
Peter Bacon Darwin dc3013e848 docs(CHANGELOG): add release notes for 1.4.9 2016-01-21 12:42:44 +00:00
Edgar Flores 0f2926db38 docs(guide/Interpolation): fix links
The links were not working, either `{` was missing or they were in the wrong location

Closes #13809
2016-01-20 21:04:50 +01:00
Lucas Galfaso bd59335eba test(input): test for #12106
Add a test that checks that an <input> value is not set when the value is equal
to the current value

Closes #12592
2016-01-20 15:11:07 +00:00
Adrian Roselli 6aa111b333 docs(tutorial/step-6): add alt attribute to images
See http://www.ssbbartgroup.com/blog/accessible-images-using-angular/

Closes #12569
2016-01-20 14:50:53 +00:00
Martin Staffa 42b5ce99fb docs(guide/filter): clarify how to use filters in controllers
Closes #11915
2016-01-20 10:41:15 +01:00
Matias Niemelä 2cb1989d12 chore($AnimateRunner): examine the document more carefully
Some internal tests were failing because the `$document[0]` value
was null. This fix ensures that the if statement surrounding that
is more careful.
2016-01-19 13:27:38 -08:00
Martin Staffa 1137d91abd docs(ngRepeat): point out animate example, remove ng-init
Closes #9047
2016-01-19 20:09:29 +01:00
Maxime Lasserre 288e4e33c3 docs($animate): make naming consistent
In the description of the example, you use `element` to refer to the container parameter and
`listenerFn` to refer to the callback parameter.

Closes #12716
2016-01-19 20:09:29 +01:00
Daniel Herman d98c5f03a4 chore($compile): remove an unused dependency
Fixes #13791

Closes #13801
2016-01-19 20:25:36 +02:00
Peter Bacon Darwin 8d20b04f1c docs($compile): fix typo 2016-01-19 18:07:25 +00:00
Peter Bacon Darwin 56c3666fe5 feat($compile): allow required controllers to be bound to the directive controller
If directives are required through an object hash, rather than a string or array,
the required directives' controllers are bound to the current directive's controller
in much the same way as the properties are bound to using `bindToController`.

This only happens if `bindToController` is truthy.

The binding is done after the controller has been constructed and all the bindings
are guaranteed to be complete by the time the controller's `$onInit` method
is called.

This change makes it much simpler to access require controllers without the
need for manually wiring them up in link functions. In particular this
enables support for `require` in directives defined using `mod.component()`

Closes #6040
Closes #5893
Closes #13763
2016-01-19 18:07:24 +00:00
Peter Bacon Darwin cd21216ff7 feat($compile): allow require to be an object
This provides an elegant alternative to the array form of the `require`
property but also helps to support binding of `require`d controllers
to directive controllers.

Closes #8401
Closes #13763
2016-01-19 18:06:50 +00:00
Peter Bacon Darwin 3ffdf380c5 feat($compile): call $ngOnInit on directive controllers after controller construction
This enables option three of https://github.com/angular/angular.js/issues/13510#issuecomment-164140194
by allowing the creator of directive controllers using ES6 classes to have a hook
that is called when the bindings are definitely available.

Moreover this will help solve the problem of accessing `require`d controllers
from controller instances without resorting to wiring up in a `link` function.
See https://github.com/angular/angular.js/issues/5893

Closes #13763
2016-01-19 18:06:30 +00:00
Peter Bacon Darwin db5e0ffe12 fix($compile): handle boolean attributes in @ bindings
Closes #13767
Closes #13769
2016-01-19 16:35:37 +00:00
Daniel Herman 92e4801d88 perf($compile): avoid needless overhead when wrapping text nodes
This commit positively affects performance in two main ways:

1,  When wrapping text nodes in the compile step, we do not need the overhead
of the `forEach` function versus a normal for loop since we do not make
use of the closure for anything.

2.  When actually wrapping the node, we can completely bypass jqLite which
avoids several function calls and the overhead of cloning the wrapper node
which we already know to be unique.

Tests in applications show about an 83% decrease in time spent in this
specific loop.
2016-01-19 16:24:53 +00:00
thorn0 6a92e9111f docs(uppercase, lowercase): undocument these artifacts
Closes #11387
Closes #13779
2016-01-19 16:12:11 +00:00
Georgios Kalpakas ba6d37756e docs(ngModel): rename $asyncValidators error to nopromise and add missing error page
Closes #13795
2016-01-19 16:05:45 +02:00
Martin Staffa 683bd92f56 perf(ngAnimate): speed up areAnimationsAllowed check
This commit speeds up the code that checks if an element can
be animated, for the following two cases:

The checks will be sped up in cases where the animation
is disabled via $animate.enabled(element, false) on any parent element.

A minor speed-up is also included for cases where the $rootElement of the
app (the bootstrap element) is on the body or lower in the DOM tree.
2016-01-19 13:14:04 +01:00
Martin Staffa 7700e2df09 fix($animate): correctly handle $animate.pin() host elements
This commit fixes two bugs:
1) Previously, animate would assume that a found host element
was part of the $rootElement (while it's possible that it is also outside the root).

2) Previously, if a parent of the animated element was pinned to a host element, the
host would not be checked regarding animations enabled status etc.

Closes #13783
2016-01-19 13:14:04 +01:00
Martin Staffa 3fb809e412 docs($compile): correct transcludeControllers definition
Closes #13793
2016-01-19 12:08:08 +01:00
Matias Niemelä 52ea4110d3 fix(ngAnimate): ensure that animate promises resolve when the document is hidden
Prior to this fix any promise/callback chained on a call to the $animate
methods would only flush if and when the browser page is visible. This
fix ensures that a timeout will be used instead when the document
is hidden.
2016-01-17 20:00:49 +01:00
Matias Niemelä a3a7afd3aa fix(ngAnimate): do not trigger animations if the document is hidden
Prior to this fix, ngAnimate would always trigger animations even if
the browser tab or browser window was not visible. This would cause
issues with class updates / DOM operations even if elements were not
using animations. The root cause is that browsers do not flush calls to
requestAnimationFrame when browser windows / tabs are not visible.

This fix disables animations if `document.hidden` is `true`.

Closes #12842
Closes #13776
2016-01-17 20:00:41 +01:00
Martin Staffa 20bc37fbc8 chore(benchmark): improve largetable layout 2016-01-17 19:55:39 +01:00
Martin Staffa 7761b6c3b0 docs(CHANGELOG): add missing breaking changes for 1.5.0-rc.1, fix layout
- add missing component() breaking changes
- put component related feats/fixes under "component"
- move features above fixes
2016-01-17 19:26:23 +01:00
764 changed files with 3828 additions and 1689 deletions
+3 -2
View File
@@ -62,6 +62,7 @@ notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/d2120f3f2bb39a4531b2
on_success: change # options: [always|never|change] default: always
- http://104.197.9.155:8484/hubot/travis/activity #hubot-server
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
on_start: always # default: false
+288 -138
View File
@@ -1,7 +1,264 @@
<a name="1.5.0-rc.2"></a>
# 1.5.0-rc.2 controller-requisition (2016-01-28)
## Deprecation Warning
- The `ngTouch` module's `ngClick` directive has been deprecated and disabled by default. See the breaking
changes section for more information
## Bug Fixes
- **$compile:**
- properly denormalize templates when only one of the start/end symbols is different
([8348365d](https://github.com/angular/angular.js/commit/8348365df9b9e2d4c9c8d5211e3424d4b9a29767),
[#13848](https://github.com/angular/angular.js/issues/13848))
- handle boolean attributes in `@` bindings
([db5e0ffe](https://github.com/angular/angular.js/commit/db5e0ffe124ac588f01ef0fe79efebfa72f5eec7),
[#13767](https://github.com/angular/angular.js/issues/13767), [#13769](https://github.com/angular/angular.js/issues/13769))
- **$parse:** Preserve expensive checks when runnning $eval inside an expression
([acfda102](https://github.com/angular/angular.js/commit/acfda1022d23ecaea34bbc8931588a0715b3ab03))
- **dateFilter:** follow the CLDR on pattern escape sequences
([1ab4e444](https://github.com/angular/angular.js/commit/1ab4e44443716c33cd857dcb1098d20580dbb0cc),
[#12839](https://github.com/angular/angular.js/issues/12839))
- **ngAnimate:**
- cancel fallback timeout when animation ends normally
([e9c406b2](https://github.com/angular/angular.js/commit/e9c406b2464614c9784f7324d8910180c81c38a7),
[#13787](https://github.com/angular/angular.js/issues/13787))
- correctly handle `$animate.pin()` host elements
([7700e2df](https://github.com/angular/angular.js/commit/7700e2df096cf50dfdf84841cab7e2d24d2eb96d),
[#13783](https://github.com/angular/angular.js/issues/13783))
- properly cancel-out previously running class-based animations
([20b8ece4](https://github.com/angular/angular.js/commit/20b8ece444408a64ac69f7b5d45ddb3af0c418a0),
[#10156](https://github.com/angular/angular.js/issues/10156), [#13822](https://github.com/angular/angular.js/issues/13822))
- ensure that animate promises resolve when the document is hidden
([52ea4110](https://github.com/angular/angular.js/commit/52ea4110d33b7de2845a698913682a03365aa074))
- do not trigger animations if the document is hidden
([a3a7afd3](https://github.com/angular/angular.js/commit/a3a7afd3aa70d981b0210088df53fa2cf68d3a3d),
[#12842](https://github.com/angular/angular.js/issues/12842), [#13776](https://github.com/angular/angular.js/issues/13776))
- **ngSanitize:** Blacklist the attribute `usemap`
([234053fc](https://github.com/angular/angular.js/commit/234053fc9ad90e0d05be7e8359c6af66be94c094))
- **ngTouch:** deprecate ngClick and disable it by default
([0dfc1dfe](https://github.com/angular/angular.js/commit/0dfc1dfebf26af7f951f301c4e3848ac46f05d7f),
[#4030](https://github.com/angular/angular.js/issues/4030), [#5307](https://github.com/angular/angular.js/issues/5307), [#6001](https://github.com/angular/angular.js/issues/6001), [#6432](https://github.com/angular/angular.js/issues/6432), [#7231](https://github.com/angular/angular.js/issues/7231), [#11358](https://github.com/angular/angular.js/issues/11358), [#12082](https://github.com/angular/angular.js/issues/12082), [#12153](https://github.com/angular/angular.js/issues/12153), [#12392](https://github.com/angular/angular.js/issues/12392), [#12545](https://github.com/angular/angular.js/issues/12545), [#12867](https://github.com/angular/angular.js/issues/12867), [#13213](https://github.com/angular/angular.js/issues/13213), [#13558](https://github.com/angular/angular.js/issues/13558), [#3296](https://github.com/angular/angular.js/issues/3296), [#3347](https://github.com/angular/angular.js/issues/3347), [#3447](https://github.com/angular/angular.js/issues/3447), [#3999](https://github.com/angular/angular.js/issues/3999), [#4428](https://github.com/angular/angular.js/issues/4428), [#6251](https://github.com/angular/angular.js/issues/6251), [#6330](https://github.com/angular/angular.js/issues/6330), [#7134](https://github.com/angular/angular.js/issues/7134), [#7935](https://github.com/angular/angular.js/issues/7935), [#9724](https://github.com/angular/angular.js/issues/9724), [#9744](https://github.com/angular/angular.js/issues/9744), [#9872](https://github.com/angular/angular.js/issues/9872), [#10211](https://github.com/angular/angular.js/issues/10211), [#10366](https://github.com/angular/angular.js/issues/10366), [#10918](https://github.com/angular/angular.js/issues/10918), [#11197](https://github.com/angular/angular.js/issues/11197), [#11261](https://github.com/angular/angular.js/issues/11261), [#11342](https://github.com/angular/angular.js/issues/11342), [#11577](https://github.com/angular/angular.js/issues/11577), [#12150](https://github.com/angular/angular.js/issues/12150), [#12317](https://github.com/angular/angular.js/issues/12317), [#12455](https://github.com/angular/angular.js/issues/12455), [#12734](https://github.com/angular/angular.js/issues/12734), [#13122](https://github.com/angular/angular.js/issues/13122), [#13272](https://github.com/angular/angular.js/issues/13272), [#13447](https://github.com/angular/angular.js/issues/13447))
## Features
- **$compile:**
- allow required controllers to be bound to the directive controller
([56c3666f](https://github.com/angular/angular.js/commit/56c3666fe50955aa7d1c1b6159626f1c1cb34637),
[#6040](https://github.com/angular/angular.js/issues/6040), [#5893](https://github.com/angular/angular.js/issues/5893), [#13763](https://github.com/angular/angular.js/issues/13763))
- allow directive definition property `require` to be an object
([cd21216f](https://github.com/angular/angular.js/commit/cd21216ff7eb6d81fc9aa1d1ef994c3d8e046394),
[#8401](https://github.com/angular/angular.js/issues/8401), [#13763](https://github.com/angular/angular.js/issues/13763))
- call `$ngOnInit` on directive controllers after all sibling controllers have been constructed
([3ffdf380](https://github.com/angular/angular.js/commit/3ffdf380c522cbf15a4ce5a8b08d21d40d5f8859),
[#13763](https://github.com/angular/angular.js/issues/13763))
- **$locale:** include original locale ID in `$locale`
([63492a02](https://github.com/angular/angular.js/commit/63492a02614a33a50cc28f9fdd73bae731352dd5),
[#13390](https://github.com/angular/angular.js/issues/13390))
- **$resource:** add support for timeout in cancellable actions
([d641901b](https://github.com/angular/angular.js/commit/d641901be6887cdd93dc678eb514366eb759d21e),
[#13824](https://github.com/angular/angular.js/issues/13824))
## Performance Improvements
- **$compile:** avoid needless overhead when wrapping text nodes
([92e4801d](https://github.com/angular/angular.js/commit/92e4801d88fbe9b7ef719fd3d0175d85420e1cc4))
- **ngAnimate:** speed up `areAnimationsAllowed` check
([683bd92f](https://github.com/angular/angular.js/commit/683bd92f56990bf1bfeabf619d997716909ebf6b))
## Breaking Changes
- **ngTouch:** due to [0dfc1dfe](https://github.com/angular/angular.js/commit/0dfc1dfebf26af7f951f301c4e3848ac46f05d7f),
The `ngClick` override directive from the `ngTouch` module is **deprecated and disabled by default**.
This means that on touch-based devices, users might now experience a 300ms delay before a click event is fired.
If you rely on this directive, you can still enable it with the `$touchProvider.ngClickOverrideEnabled()`method:
```js
angular.module('myApp').config(function($touchProvider) {
$touchProvider.ngClickOverrideEnabled(true);
});
```
Going forward, we recommend using [FastClick](https://github.com/ftlabs/fastclick) or perhaps one of the [Angular
3rd party touch-related modules](http://ngmodules.org/tags/touch) that provide similar functionality.
Also note that modern browsers already remove the 300ms delay under some circumstances:
- Chrome and Firefox for Android remove the 300ms delay when the well-known `<meta name="viewport" content="width=device-width">` is set
- Internet Explorer removes the delay when `touch-action` css property is set to `none` or `manipulation`
- Since iOs 8, Safari removes the delay on so-called "slow taps"
See this [article by Telerik](http://developer.telerik.com/featured/300-ms-click-delay-ios-8/) for more info on the topic.
**Note that this change does not affect the `ngSwipe` directive.**
<a name="1.4.9"></a>
# 1.4.9 implicit-superannuation (2016-01-21)
## Bug Fixes
- **Animation**
- ensure that animate promises resolve when the document is hidden
([9a60408c](https://github.com/angular/angular.js/commit/9a60408c804a62a9517857bdb9a42182ab6769e3))
- do not trigger animations if the document is hidden
([09f6061a](https://github.com/angular/angular.js/commit/09f6061a8ee41cae4268e8d44d727d3bf52e22a9),
[#12842](https://github.com/angular/angular.js/issues/12842), [#13776](https://github.com/angular/angular.js/issues/13776))
- only copy over the animation options once
([2fc954d3](https://github.com/angular/angular.js/commit/2fc954d33a3a4c5d4f355be1e15a381664e02f1b),
[#13722](https://github.com/angular/angular.js/issues/13722), [#13578](https://github.com/angular/angular.js/issues/13578))
- allow event listeners on document in IE
([5ba4419e](https://github.com/angular/angular.js/commit/5ba4419e265ff34c6c23bf3533a3332c99c5f014),
[#13548](https://github.com/angular/angular.js/issues/13548), [#13696](https://github.com/angular/angular.js/issues/13696))
- allow removing classes that are added by a running animation
([6c4581fc](https://github.com/angular/angular.js/commit/6c4581fcb692b17295a41b8918c6038333e7bc3d),
[#13339](https://github.com/angular/angular.js/issues/13339), [#13380](https://github.com/angular/angular.js/issues/13380), [#13414](https://github.com/angular/angular.js/issues/13414), [#13472](https://github.com/angular/angular.js/issues/13472), [#13678](https://github.com/angular/angular.js/issues/13678))
- do not use `event.timeStamp` anymore for time tracking
([620a20d1](https://github.com/angular/angular.js/commit/620a20d1b3376d95f85004ffa494e36bb19a2e4d),
[#13494](https://github.com/angular/angular.js/issues/13494), [#13495](https://github.com/angular/angular.js/issues/13495))
- ignore children without animation data when closing them
([be01cebf](https://github.com/angular/angular.js/commit/be01cebfae9ca2383105e535820442b39a96b240),
[#11992](https://github.com/angular/angular.js/issues/11992), [#13424](https://github.com/angular/angular.js/issues/13424))
- do not alter the provided options data
([7a81e6fe](https://github.com/angular/angular.js/commit/7a81e6fe2db084172e34d509f0baad2b33a8722c),
[#13040](https://github.com/angular/angular.js/issues/13040), [#13175](https://github.com/angular/angular.js/issues/13175))
- correctly handle `$animate.pin()` host elements
([a985adfd](https://github.com/angular/angular.js/commit/a985adfdabd871f3f3f3ee59f371da50cd9611d9),
[#13783](https://github.com/angular/angular.js/issues/13783))
- allow animations when pinned element is parent element
([4cb8ac61](https://github.com/angular/angular.js/commit/4cb8ac61c7574ab4039852c358dd5946268b69fb),
[#13466](https://github.com/angular/angular.js/issues/13466))
- allow enabled children to animate on disabled parents
([6d85f24e](https://github.com/angular/angular.js/commit/6d85f24e2081d2a69c80697d90ebd45f228d9682),
[#13179](https://github.com/angular/angular.js/issues/13179), [#13695](https://github.com/angular/angular.js/issues/13695))
- correctly access `minErr`
([0c1b54f0](https://github.com/angular/angular.js/commit/0c1b54f04cf5bd7c1fe42ac49b4fbfdf35c60979))
- ensure animate runner is the same with and without animations
([937942f5](https://github.com/angular/angular.js/commit/937942f5ada6de1bdacdf0ba465f6f118c270119),
[#13205](https://github.com/angular/angular.js/issues/13205), [#13347](https://github.com/angular/angular.js/issues/13347))
- remove animation end event listeners on close
([d9157849](https://github.com/angular/angular.js/commit/d9157849df224a3a8d2e0bf03099d137f51499f6),
[#13672](https://github.com/angular/angular.js/issues/13672))
- consider options.delay value for closing timeout
([592bf516](https://github.com/angular/angular.js/commit/592bf516e50b9729e446d9aa01f4d9ebdd72d187),
[#13355](https://github.com/angular/angular.js/issues/13355), [#13363](https://github.com/angular/angular.js/issues/13363))
- **$controller:** allow identifiers containing `$`
([2563ff7b](https://github.com/angular/angular.js/commit/2563ff7ba92d84af978e7e4131253190d4d00c20),
[#13736](https://github.com/angular/angular.js/issues/13736))
- **$http:** throw if url passed is not a string
([c5bf9dae](https://github.com/angular/angular.js/commit/c5bf9daef6dfdb3e4a2942c21155a9f67d92e237),
[#12925](https://github.com/angular/angular.js/issues/12925), [#13444](https://github.com/angular/angular.js/issues/13444))
- **$parse:** handle interceptors with `undefined` expressions
([7bb2414b](https://github.com/angular/angular.js/commit/7bb2414bf6461aa45a983fd322ae875f81814cc4))
- **$resource:** don't allow using promises as `timeout` and log a warning
([47486524](https://github.com/angular/angular.js/commit/474865242c89ba3e8143f0cd52f8c292979ea730))
- **formatNumber:** cope with large and small number corner cases
([9c49eb13](https://github.com/angular/angular.js/commit/9c49eb131a6100d58c965d01fb08bcd319032229),
[#13394](https://github.com/angular/angular.js/issues/13394), [#8674](https://github.com/angular/angular.js/issues/8674), [#12709](https://github.com/angular/angular.js/issues/12709), [#8705](https://github.com/angular/angular.js/issues/8705), [#12707](https://github.com/angular/angular.js/issues/12707), [#10246](https://github.com/angular/angular.js/issues/10246), [#10252](https://github.com/angular/angular.js/issues/10252))
- **input:**
- fix URL validation being too strict
([6610ae81](https://github.com/angular/angular.js/commit/6610ae816f78ee8fc1080b93a55bf19e4ce48d3e),
[#13528](https://github.com/angular/angular.js/issues/13528), [#13544](https://github.com/angular/angular.js/issues/13544))
- add missing chars to URL validation regex
([2995b54a](https://github.com/angular/angular.js/commit/2995b54afdb9a3a2a81b0076a6ac0a9001041163),
[#13379](https://github.com/angular/angular.js/issues/13379), [#13460](https://github.com/angular/angular.js/issues/13460))
- **isArrayLike:** recognize empty instances of an Array subclass
([323f9ab7](https://github.com/angular/angular.js/commit/323f9ab73696f223c245ddefd62a769fe102615e),
[#13560](https://github.com/angular/angular.js/issues/13560), [#13708](https://github.com/angular/angular.js/issues/13708))
- **ngInclude:** do not compile template if original scope is destroyed
([9590bcf0](https://github.com/angular/angular.js/commit/9590bcf0620cd507a7795c55f9a6f4a48bfedbc1))
- **ngOptions:**
- don't skip `optgroup` elements with `value === ''`
([85e392f3](https://github.com/angular/angular.js/commit/85e392f3543ef5285c7e90e843af0ab522cb0531),
[#13487](https://github.com/angular/angular.js/issues/13487), [#13489](https://github.com/angular/angular.js/issues/13489))
- don't `$dirty` multiple select after compilation
([f163c905](https://github.com/angular/angular.js/commit/f163c90555774426ccb14752d089fc707cb4029c),
[#13211](https://github.com/angular/angular.js/issues/13211), [#13326](https://github.com/angular/angular.js/issues/13326))
- **select:** re-define `ngModelCtrl.$render` in the `select` directive's postLink function
([529b2507](https://github.com/angular/angular.js/commit/529b2507bdb4fcc22dfa0f7ab462c79fc78d1413),
[#13583](https://github.com/angular/angular.js/issues/13583), [#13583](https://github.com/angular/angular.js/issues/13583), [#13663](https://github.com/angular/angular.js/issues/13663))
## Minor Features
- **ngLocale:** add support for standalone months
([54c4041e](https://github.com/angular/angular.js/commit/54c4041ebc0cc4df70cf6996f43a6aaaf56d46bd),
[#3744](https://github.com/angular/angular.js/issues/3744), [#10247](https://github.com/angular/angular.js/issues/10247), [#12642](https://github.com/angular/angular.js/issues/12642), [#12844](https://github.com/angular/angular.js/issues/12844))
- **ngMock:** add support for `$animate.closeAndFlush()`
([512c0811](https://github.com/angular/angular.js/commit/512c08118786a419fabbd063fa17d224aba125cf))
## Performance Improvements
- **ngAnimate:** speed up `areAnimationsAllowed` check
([2d3303dd](https://github.com/angular/angular.js/commit/2d3303ddda6330c4f45b381b6b17346f6cfe2d97))
## Breaking Changes
While we do not deem the following to be a real breaking change we are highlighting it here in the
changelog to ensure that it does not surprise anyone.
- **$resource:** due to [47486524](https://github.com/angular/angular.js/commit/474865242c89ba3e8143f0cd52f8c292979ea730),
**Possible breaking change** for users who updated their code to provide a `timeout`
promise for a `$resource` request in version v1.4.8.
Up to v1.4.7 (included), using a promise as a timeout in `$resource`, would silently
fail (i.e. have no effect).
In v1.4.8, using a promise as timeout would have the (buggy) behaviour described
in https://github.com/angular/angular.js/pull/12657#issuecomment-152108887.
(I.e. it will work as expected for the first time you resolve the promise and will
cancel all subsequent requests after that - one has to re-create the resource
class. This was not documented.)
With this change, using a promise as timeout in v1.4.9 onwards is not allowed.
It will log a warning and ignore the timeout value.
If you need support for cancellable `$resource` actions, you should upgrade to
version 1.5 or higher.
<a name="1.5.0-rc.1"></a>
# 1.5.0-rc.1 quantum-fermentation (2016-01-15)
## Features
- **$compile:**
- Allow ES6 classes as controllers with `bindToController: true`
([8955cfb6](https://github.com/angular/angular.js/commit/8955cfb6462f79a32caa641ffc002f1522f08220))
- Allow ES6 classes as controllers with `bindToController: true`
([b0248b78](https://github.com/angular/angular.js/commit/b0248b7894649aa1e083698c66d01679fa66d1c1))
- **$compileProvider:** - allow registering components with the component() method
([feeb19787ca6e23e15578a4d1319f1c33853290c](https://github.com/angular/angular.js/commit/feeb19787ca6e23e15578a4d1319f1c33853290c))
- **component:**
- default controllerAs to `$ctrl`
([d91cf167](https://github.com/angular/angular.js/commit/d91cf167960d47ce38fec0d33cab6119268623f0),
[#13664](https://github.com/angular/angular.js/issues/13664), [#13710](https://github.com/angular/angular.js/issues/13710))
- disallow non-isolate scopes
([f31c5a39](https://github.com/angular/angular.js/commit/f31c5a3924629795cd9169e69b9e20efd4a9d927),
[#13710](https://github.com/angular/angular.js/issues/13710))
- allow `component()` helper to copy over custom annotations
([90975db5](https://github.com/angular/angular.js/commit/90975db5f91dfe44fa5dc4542e92c68e0d425929),
[#13741](https://github.com/angular/angular.js/issues/13741))
- **$injector:** support instantiating classes.
([8b6b4282](https://github.com/angular/angular.js/commit/8b6b42827186e5e4eb7a56f6b824c560a5058bd2))
- **ngMock:** add support for `$animate.closeAndFlush()`
([e1def1b8](https://github.com/angular/angular.js/commit/e1def1b8fe543fde09abda076d66606027f7dbeb),
[#13005](https://github.com/angular/angular.js/issues/13005), [#13576](https://github.com/angular/angular.js/issues/13576), [#13707](https://github.com/angular/angular.js/issues/13707))
- **ngMock.$componentController:** add helper to instantiate controllers for components
([dd14e0c4](https://github.com/angular/angular.js/commit/dd14e0c44d2963d217cd4eb28f1ad6e6a643d63f),
[#13683](https://github.com/angular/angular.js/issues/13683), [#13711](https://github.com/angular/angular.js/issues/13711))
## Bug Fixes
- **$animate:**
@@ -24,13 +281,19 @@
([de9777d8](https://github.com/angular/angular.js/commit/de9777d8193531472df4b57fdeb6650d7f7c1846),
[#12656](https://github.com/angular/angular.js/issues/12656), [#13333](https://github.com/angular/angular.js/issues/13333))
- **$compile:**
- Add missing variable declaration
- add missing variable declaration
([6cdbda7c](https://github.com/angular/angular.js/commit/6cdbda7cf1cfc1d49eb98d42d8e823e65bebb90d))
- Fix namespace detection for achor elements
- fix namespace detection for anchor elements
([c9e6cf9b](https://github.com/angular/angular.js/commit/c9e6cf9be0d549fba234956f7e263f40d1bb1e76))
- **$compileProvider:** remove the ability to set the `restrict` option on `component()` helper
- **component:**
- remove the ability to set the `restrict` option on `component()` helper
([25bc5318](https://github.com/angular/angular.js/commit/25bc53180248bf5e8a6467c55d913cfa38fc7a3b),
[#13741](https://github.com/angular/angular.js/issues/13741))
- use `false` as default value for `transclude` in `component()` helper
([6a47c0d7](https://github.com/angular/angular.js/commit/6a47c0d75d0c6f0bfb3b5492d1f05ec900387744),
[#13566](https://github.com/angular/angular.js/issues/13566), [#13581](https://github.com/angular/angular.js/issues/13581))
- allow passing template/templateUrl in array notation
([99d601a0](https://github.com/angular/angular.js/commit/99d601a048ac2b82e2f74ae88c96773e5d1a7258))
- **$controller:** allow identifiers containing `$`
([4e1b36c2](https://github.com/angular/angular.js/commit/4e1b36c21686ad0ca4930d1d81f77a7d9cc35851),
[#13736](https://github.com/angular/angular.js/issues/13736))
@@ -38,8 +301,6 @@
([fabc6ab5](https://github.com/angular/angular.js/commit/fabc6ab5b01dc687aa8385da067752ba34da6524))
- **$q:** make instanceof work for $q promises
([b3ef5e08](https://github.com/angular/angular.js/commit/b3ef5e08528f5f1916876032700a016448fb196a))
- **Module:** allow passing template/templateUrl in array notation
([99d601a0](https://github.com/angular/angular.js/commit/99d601a048ac2b82e2f74ae88c96773e5d1a7258))
- **copy:**
- add support for ArrayBuffer, handle multiple references to ArrayBuffer
([986647a9](https://github.com/angular/angular.js/commit/986647a968858121c1de472fc4913221dc8d339a))
@@ -54,9 +315,6 @@
- **linky:** throw error if input is not a string
([98c2db7f](https://github.com/angular/angular.js/commit/98c2db7f9c2d078a408576e722407d518c7ee10a),
[#13547](https://github.com/angular/angular.js/issues/13547), [#13693](https://github.com/angular/angular.js/issues/13693))
- **loader:** use `false` as default value for `transclude` in component helper
([6a47c0d7](https://github.com/angular/angular.js/commit/6a47c0d75d0c6f0bfb3b5492d1f05ec900387744),
[#13566](https://github.com/angular/angular.js/issues/13566), [#13581](https://github.com/angular/angular.js/issues/13581))
- **ngAnimate:**
- only copy over the animation options once
([d4fa3313](https://github.com/angular/angular.js/commit/d4fa3313088a03d15ccbf266583d6ecaa0d22241),
@@ -82,41 +340,30 @@
[#13583](https://github.com/angular/angular.js/issues/13583), [#13583](https://github.com/angular/angular.js/issues/13583), [#13663](https://github.com/angular/angular.js/issues/13663))
## Features
- **$compile:**
- Allow ES6 classes as controllers with `bindToController: true`
([8955cfb6](https://github.com/angular/angular.js/commit/8955cfb6462f79a32caa641ffc002f1522f08220))
- Allow ES6 classes as controllers with `bindToController: true`
([b0248b78](https://github.com/angular/angular.js/commit/b0248b7894649aa1e083698c66d01679fa66d1c1))
- **$compileProvider:** allow `component()` helper to copy over custom annotations
([90975db5](https://github.com/angular/angular.js/commit/90975db5f91dfe44fa5dc4542e92c68e0d425929),
[#13741](https://github.com/angular/angular.js/issues/13741))
- **$injector:** support instantiating classes.
([8b6b4282](https://github.com/angular/angular.js/commit/8b6b42827186e5e4eb7a56f6b824c560a5058bd2))
- **component:**
- default controllerAs to be $ctrl
([d91cf167](https://github.com/angular/angular.js/commit/d91cf167960d47ce38fec0d33cab6119268623f0),
[#13664](https://github.com/angular/angular.js/issues/13664), [#13710](https://github.com/angular/angular.js/issues/13710))
- disallow non-isolate scopes
([f31c5a39](https://github.com/angular/angular.js/commit/f31c5a3924629795cd9169e69b9e20efd4a9d927),
[#13710](https://github.com/angular/angular.js/issues/13710))
- **ngMock:** add support for `$animate.closeAndFlush()`
([e1def1b8](https://github.com/angular/angular.js/commit/e1def1b8fe543fde09abda076d66606027f7dbeb),
[#13005](https://github.com/angular/angular.js/issues/13005), [#13576](https://github.com/angular/angular.js/issues/13576), [#13707](https://github.com/angular/angular.js/issues/13707))
- **ngMock.$componentController:** add helper to instantiate controllers for components
([dd14e0c4](https://github.com/angular/angular.js/commit/dd14e0c44d2963d217cd4eb28f1ad6e6a643d63f),
[#13683](https://github.com/angular/angular.js/issues/13683), [#13711](https://github.com/angular/angular.js/issues/13711))
## Breaking Changes
- **$compileProvider**: due to [25bc5318](https://github.com/angular/angular.js/commit/25bc5318),
- **$component**:
*These breaking changes affect only applications updating from previous 1.5 beta / rc versions*
This release removes the ability to set the `restrict` option on directives created via the `module.component()` helper.
All components are now element directives. If you need a directive that is not an element then you must use the
- Due to [d91cf167](https://github.com/angular/angular.js/commit/d91cf167960d47ce38fec0d33cab6119268623f0),
the default `controllerAs` value for components is now `$ctrl` (previously the name of the component was used).
To migrate, either set `controllerAs` to the component name, or change the property name in your templates
to `$ctrl`
- Due to [25bc5318](https://github.com/angular/angular.js/commit/25bc5318), it is no longer possible to
set the `restrict` option on directives created via the `module.component()` helper.
All components are now element directives (`restrict: 'E'`). If you need a directive that is not an element then you must use the
`module.directive()` helper instead.
- Due to [f31c5a39](https://github.com/angular/angular.js/commit/f31c5a3924629795cd9169e69b9e20efd4a9d927),
components are now always created with `scope: {}` (isolate scope). Previously, it was also possible to create components
with `scope: true` or `scope: false`. If your components rely on this scope configuration, you will have to
create a regular directive instead.
- Due to [6a47c0d7](https://github.com/angular/angular.js/commit/6a47c0d75d0c6f0bfb3b5492d1f05ec900387744),
the `transclude` property is now `false` by default (previously `true`). If you created components that expected
transclusion then you must change your code to specify `transclude: true`.
- **linky:** due to [98c2db7f](https://github.com/angular/angular.js/commit/98c2db7f9c2d078a408576e722407d518c7ee10a),
Before this change, the filter assumed that the input (if not undefined/null) was of type 'string'
@@ -129,12 +376,6 @@ values through `linky`, you need to explicitly convert them to strings first.
Since input values could be initialized asynchronously, `undefined` or `null` will still be
returned unchanged (without throwing an error).
- **loader:** due to [6a47c0d7](https://github.com/angular/angular.js/commit/6a47c0d75d0c6f0bfb3b5492d1f05ec900387744),
Angular 1.5.0.beta.2 introduced the `module.component` helper where `transclude` was true by default.
This changes the default for `transclude` to `false`. If you created components that expected
transclusion then you must change your code to specify `transclude: true`.
<a name="1.5.0-rc.0"></a>
# 1.5.0-rc.0 oblong-panoptikum (2015-12-09)
@@ -428,57 +669,24 @@ is `$locals`.
- fix scoping of transclusion directives inside a replace directive
([1a98c0ee](https://github.com/angular/angular.js/commit/1a98c0ee346b718b9462da1abf4352a4605cbc7f),
[#12975](https://github.com/angular/angular.js/issues/12975), [#12936](https://github.com/angular/angular.js/issues/12936), [#13244](https://github.com/angular/angular.js/issues/13244))
- use createMap() for $$observe listeners when initialized from attr interpolation
([76c2491a](https://github.com/angular/angular.js/commit/76c2491a316d6b296c721227529fcb09087d369a),
[#10446](https://github.com/angular/angular.js/issues/10446))
- properly sanitize xlink:href attribute interpolation
([f33ce173](https://github.com/angular/angular.js/commit/f33ce173c90736e349cf594df717ae3ee41e0f7a),
[#12524](https://github.com/angular/angular.js/issues/12524))
- **$http:** apply `transformResponse` even when `data` is empty
([7c0731ed](https://github.com/angular/angular.js/commit/7c0731edb2f72bdf0efa186f641dab3b6aecc5d5),
[#12976](https://github.com/angular/angular.js/issues/12976), [#12979](https://github.com/angular/angular.js/issues/12979))
- **$location:** ensure `$locationChangeSuccess` fires even if URL ends with `#`
([4412fe23](https://github.com/angular/angular.js/commit/4412fe238f37f79a2017ee7b20ba089c0acd73e9),
[#12175](https://github.com/angular/angular.js/issues/12175), [#13251](https://github.com/angular/angular.js/issues/13251))
- **$parse:**
- evaluate simple expressions in interpolations only once
- **$parse:** evaluate simple expressions in interpolations only once
([1caf0b6b](https://github.com/angular/angular.js/commit/1caf0b6bee5781589e20f7a27a8c60e8b1b784f5),
[#12983](https://github.com/angular/angular.js/issues/12983), [#13002](https://github.com/angular/angular.js/issues/13002))
- fix typo in error message ("assing" -> "assign")
([70dac5ae](https://github.com/angular/angular.js/commit/70dac5ae82ffe9c6250681274905583747523b5d),
[#12940](https://github.com/angular/angular.js/issues/12940))
- block assigning to fields of a constructor
([e1f4f23f](https://github.com/angular/angular.js/commit/e1f4f23f781a79ae8a4046b21130283cec3f2917),
[#12860](https://github.com/angular/angular.js/issues/12860))
- safer conversion of computed properties to strings
([20cf7d5e](https://github.com/angular/angular.js/commit/20cf7d5e3a0af766b1929e24794859c79439351c))
- **$resource:** allow XHR request to be cancelled via a timeout promise
([4fc73466](https://github.com/angular/angular.js/commit/4fc734665e5dddef26ed30a9d4f75632cd269481),
[#12657](https://github.com/angular/angular.js/issues/12657), [#12675](https://github.com/angular/angular.js/issues/12675), [#10890](https://github.com/angular/angular.js/issues/10890), [#9332](https://github.com/angular/angular.js/issues/9332))
- **$rootScope:** prevent IE9 memory leak when destroying scopes
([8fe781fb](https://github.com/angular/angular.js/commit/8fe781fbe7c42c64eb895c28d9fd5479b037d020),
[#10706](https://github.com/angular/angular.js/issues/10706), [#11786](https://github.com/angular/angular.js/issues/11786))
- **$sanitize:**
- strip urls starting with 'unsafe:' as opposed to 'unsafe'
([a4dfa4d0](https://github.com/angular/angular.js/commit/a4dfa4d061fd2f6baf9821f0863dcce7888232ab),
[#12524](https://github.com/angular/angular.js/issues/12524))
- add mXSS protection
([bc0d8c4e](https://github.com/angular/angular.js/commit/bc0d8c4eea9a34bff5e29dd492dcdd668251be40),
[#12524](https://github.com/angular/angular.js/issues/12524))
- support void elements, fixups, remove dead code, typos
([94207f8f](https://github.com/angular/angular.js/commit/94207f8fb6ee8fe26fe18657f6b5aca6def99605),
[#12524](https://github.com/angular/angular.js/issues/12524))
- **Angular.js:** fix `isArrayLike` for unusual cases
([2c8d87e0](https://github.com/angular/angular.js/commit/2c8d87e064dca99a49ed35d1db885b1f2e40dcf4),
[#10186](https://github.com/angular/angular.js/issues/10186), [#8000](https://github.com/angular/angular.js/issues/8000), [#4855](https://github.com/angular/angular.js/issues/4855), [#4751](https://github.com/angular/angular.js/issues/4751), [#10272](https://github.com/angular/angular.js/issues/10272))
- **filters:** ensure `formatNumber` observes i18n decimal separators
([658a865c](https://github.com/angular/angular.js/commit/658a865c5b2580eed53b340e7394945cd76e2260),
[#10342](https://github.com/angular/angular.js/issues/10342), [#12850](https://github.com/angular/angular.js/issues/12850))
- **injector:** support arrow functions with no parentheses
([03726f7f](https://github.com/angular/angular.js/commit/03726f7fbd5d71c0604b8dd40e97cb2fb0fb777f),
[#12890](https://github.com/angular/angular.js/issues/12890))
- **input:** remove workaround for Firefox bug
([b366f035](https://github.com/angular/angular.js/commit/b366f0352abccfe4c4868b5a9e8c0b88659bd1ee))
- **isArrayLike:** handle jQuery objects of length 0
([773efd08](https://github.com/angular/angular.js/commit/773efd0812097a89944c889c595485a5744326f6))
- **jqLite:**
@@ -497,12 +705,6 @@ is `$locals`.
- clone elements instead of treating them like simple objects
([17715fa3](https://github.com/angular/angular.js/commit/17715fa3668b1fcabaedcd82e2e57b2a80e0a0c2),
[#12286](https://github.com/angular/angular.js/issues/12286))
- **ngAnimate:**
- ensure anchoring uses body as a container when needed
([240d5896](https://github.com/angular/angular.js/commit/240d5896ecdfac2351f9bd6147b52de52c0b7608),
[#12872](https://github.com/angular/angular.js/issues/12872))
- callback detection should only use RAF when necessary
([8b27c3f0](https://github.com/angular/angular.js/commit/8b27c3f064b34532ba99d709cadf09fc4c0cbeab))
- **ngAria:** don't add tabindex to radio and checkbox inputs
([662fb282](https://github.com/angular/angular.js/commit/662fb282c176ca00a85b6dec7af90446ea90f662),
[#12492](https://github.com/angular/angular.js/issues/12492), [#13095](https://github.com/angular/angular.js/issues/13095))
@@ -512,9 +714,6 @@ is `$locals`.
- **ngMessage:** make ngMessage compatible with ngBind
([4971ef12](https://github.com/angular/angular.js/commit/4971ef12d4c2c268cb8d26f90385dc96eba19db8),
[#8089](https://github.com/angular/angular.js/issues/8089), [#13074](https://github.com/angular/angular.js/issues/13074))
- **ngMessages:** prevent race condition with ngAnimate
([8366622b](https://github.com/angular/angular.js/commit/8366622bed009d2cad7d0cff28b9c1e48bfbd4e1),
[#12856](https://github.com/angular/angular.js/issues/12856), [#12903](https://github.com/angular/angular.js/issues/12903))
- **ngMock:** reset cache before every test
([fd83d372](https://github.com/angular/angular.js/commit/fd83d3724ad30a93254f08cb82f981eaddb5dbff),
[#13013](https://github.com/angular/angular.js/issues/13013))
@@ -525,18 +724,6 @@ is `$locals`.
- override select option registration to allow compilation of empty option
([2fcfd75a](https://github.com/angular/angular.js/commit/2fcfd75a142200e1a4b1b7ed4fb588e3befcbd57),
[#11685](https://github.com/angular/angular.js/issues/11685), [#12972](https://github.com/angular/angular.js/issues/12972), [#12968](https://github.com/angular/angular.js/issues/12968), [#13012](https://github.com/angular/angular.js/issues/13012))
- prevent frozen select ui in IE
([42c97c5d](https://github.com/angular/angular.js/commit/42c97c5db5921e9e5447fb32bdae1f48da42844f),
[#11314](https://github.com/angular/angular.js/issues/11314), [#11795](https://github.com/angular/angular.js/issues/11795))
- allow falsy values as option group identifiers
([b71d7c3f](https://github.com/angular/angular.js/commit/b71d7c3f3c04e65b02d88b33c22dd90ae3cdfc27),
[#7015](https://github.com/angular/angular.js/issues/7015), [#7024](https://github.com/angular/angular.js/issues/7024), [#12888](https://github.com/angular/angular.js/issues/12888))
- throw if ngModel is not present
([ded25187](https://github.com/angular/angular.js/commit/ded2518756d4409fdfda0d4af243f2125bea01b5),
[#7047](https://github.com/angular/angular.js/issues/7047), [#12840](https://github.com/angular/angular.js/issues/12840))
- **ngResource:** encode `&` in URL query param values
([1c97a605](https://github.com/angular/angular.js/commit/1c97a6057bc013262be761bca5e5c22224c4bbf8),
[#12201](https://github.com/angular/angular.js/issues/12201))
- **orderByFilter:** throw error if input is not array-like
([2a85a634](https://github.com/angular/angular.js/commit/2a85a634f86c84f15b411ce009a3515fca7ba580),
[#11255](https://github.com/angular/angular.js/issues/11255), [#11719](https://github.com/angular/angular.js/issues/11719))
@@ -544,24 +731,11 @@ is `$locals`.
## Features
- **$animateCss:** add support for temporary styles via `cleanupStyles`
([9f67da62](https://github.com/angular/angular.js/commit/9f67da625293441e27559ebde7503cc63408a95c),
[#12930](https://github.com/angular/angular.js/issues/12930))
- **$compile:** multiple transclusion via named slots
([a4ada8ba](https://github.com/angular/angular.js/commit/a4ada8ba9c4358273575e16778e76446ad080054),
[#4357](https://github.com/angular/angular.js/issues/4357), [#12742](https://github.com/angular/angular.js/issues/12742), [#11736](https://github.com/angular/angular.js/issues/11736), [#12934](https://github.com/angular/angular.js/issues/12934))
- **$http:** add `$xhrFactory` service to enable creation of custom xhr objects
([106f90aa](https://github.com/angular/angular.js/commit/106f90aafa0fa5a81ad7af7ffc9d1e00ab97ffef),
[#2318](https://github.com/angular/angular.js/issues/2318), [#9319](https://github.com/angular/angular.js/issues/9319), [#12159](https://github.com/angular/angular.js/issues/12159))
- **$injector:**
- Allow specifying a decorator on $injector
- **$injector:** allow specifying a decorator on $injector
([29a05984](https://github.com/angular/angular.js/commit/29a05984fe46c2c18ca51404f07c866dd92d1eec))
- add strictDi property to $injector instance
([79577c5d](https://github.com/angular/angular.js/commit/79577c5d316c7bf0204d7d1747ddc5b15bfe2955),
[#11728](https://github.com/angular/angular.js/issues/11728), [#11734](https://github.com/angular/angular.js/issues/11734))
- **$sanitize:** make svg support an opt-in
([181fc567](https://github.com/angular/angular.js/commit/181fc567d873df065f1e84af7225deb70a8d2eb9),
[#12524](https://github.com/angular/angular.js/issues/12524))
- **$templateRequest:** support configuration of $http options
([b2fc39d2](https://github.com/angular/angular.js/commit/b2fc39d2ddac64249b4f2961ee18b878a1e98251),
[#13188](https://github.com/angular/angular.js/issues/13188), [#11868](https://github.com/angular/angular.js/issues/11868), [#6860](https://github.com/angular/angular.js/issues/6860))
@@ -580,18 +754,12 @@ is `$locals`.
- invoke nested calls to `module()` immediately
([51a27c0f](https://github.com/angular/angular.js/commit/51a27c0f1ad6cd8d3e33ab0d71de22c1627c7ec3),
[#12887](https://github.com/angular/angular.js/issues/12887))
- **ngModel:** provide ng-empty and ng-not-empty CSS classes
([630280c7](https://github.com/angular/angular.js/commit/630280c7fb04a83208d09c97c2efb81be3a3db74),
[#10050](https://github.com/angular/angular.js/issues/10050), [#12848](https://github.com/angular/angular.js/issues/12848))
## Performance Improvements
- **$compile:**
- use static jquery data method to avoid creating new instances
- **$compile:** use static jquery data method to avoid creating new instances
([9b90c32f](https://github.com/angular/angular.js/commit/9b90c32f31fd56e348539674128acec6536cd846))
- lazily compile the `transclude` function
([652b83eb](https://github.com/angular/angular.js/commit/652b83eb226131d131a44453520a569202aa4aac))
- **$interpolate:** provide a simplified result for constant expressions
([cf83b4f4](https://github.com/angular/angular.js/commit/cf83b4f445d3a1fc18fc140e65e670754401d50b))
- **copy:**
@@ -607,13 +775,6 @@ is `$locals`.
## Breaking Changes
- **$sanitize:** due to [181fc567](https://github.com/angular/angular.js/commit/181fc567d873df065f1e84af7225deb70a8d2eb9),
The svg support in is now an opt-in option
Applications that depend on this option can use to turn the option back on,
but while doing so, please read the warning provided in the documentation for
information on preventing click-hijacking attacks when this option is turned on.
- **ngMessage:** due to [4971ef12](https://github.com/angular/angular.js/commit/4971ef12d4c2c268cb8d26f90385dc96eba19db8),
ngMessage is now compiled with a priority of 1, which means directives
@@ -624,14 +785,6 @@ passed the comment element created by the transclusion of ngMessage.
To restore this behavior, custom directives need to have
their priority increased to at least "1".
- **ngOptions:** due to [ded25187](https://github.com/angular/angular.js/commit/ded2518756d4409fdfda0d4af243f2125bea01b5),
`ngOptions` will now throw if `ngModel` is not present on the `select`
element. Previously, having no `ngModel` let `ngOptions` silently
fail, which could lead to hard to debug errors. The change should
therefore not affect any applications, as it simply makes the
requirement more strict and alerts the developer explicitly.
- **orderByFilter:** due to [2a85a634](https://github.com/angular/angular.js/commit/2a85a634f86c84f15b411ce009a3515fca7ba580),
Previously, an non array-like input would pass through the orderBy filter unchanged.
@@ -641,9 +794,6 @@ https://github.com/petebacondarwin/angular-toArrayFilter.
(`null` and `undefined` still pass through without an error, in order to
support asynchronous loading of resources.)
Closes #11255
Closes #11719
<a name="1.5.0-beta.1"></a>
+14 -14
View File
@@ -8,20 +8,20 @@
Large table rendered with AngularJS
</p>
<div>none: <input type="radio" ng-model="benchmarkType" value="none"></div>
<div>baseline binding: <input type="radio" ng-model="benchmarkType" value="baselineBinding"></div>
<div>baseline interpolation: <input type="radio" ng-model="benchmarkType" value="baselineInterpolation"></div>
<div>ngBind: <input type="radio" ng-model="benchmarkType" value="ngBind"></div>
<div>ngBindOnce: <input type="radio" ng-model="benchmarkType" value="ngBindOnce"></div>
<div>interpolation: <input type="radio" ng-model="benchmarkType" value="interpolation"></div>
<div>interpolation + bind-once: <input type="radio" ng-model="benchmarkType" value="bindOnceInterpolation"></div>
<div>attribute interpolation: <input type="radio" ng-model="benchmarkType" value="interpolationAttr"></div>
<div>ngBind + fnInvocation: <input type="radio" ng-model="benchmarkType" value="ngBindFn"></div>
<div>interpolation + fnInvocation: <input type="radio" ng-model="benchmarkType" value="interpolationFn"></div>
<div>ngBind + filter: <input type="radio" ng-model="benchmarkType" value="ngBindFilter"></div>
<div>interpolation + filter: <input type="radio" ng-model="benchmarkType" value="interpolationFilter"></div>
<div>ngModel (const name): <input type="radio" ng-model="benchmarkType" value="ngModelConstName"></div>
<div>ngModel (interp name): <input type="radio" ng-model="benchmarkType" value="ngModelInterpName"></div>
<div><label><input type="radio" ng-model="benchmarkType" value="none">none: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="baselineBinding">baseline binding: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="baselineInterpolation">baseline interpolation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBind">ngBind: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBindOnce">ngBindOnce: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolation">interpolation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="bindOnceInterpolation">interpolation + bind-once: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolationAttr">attribute interpolation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBindFn">ngBind + fnInvocation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolationFn">interpolation + fnInvocation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBindFilter">ngBind + filter: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolationFilter">interpolation + filter: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngModelConstName">ngModel (const name): </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngModelInterpName">ngModel (interp name): </label></div>
<ng-switch on="benchmarkType">
<baseline-binding-table ng-switch-when="baselineBinding">
+1
View File
@@ -1,5 +1,6 @@
{
"name": "AngularJS",
"license": "MIT",
"devDependencies": {
"jquery": "2.1.1",
"closure-compiler": "https://dl.google.com/closure-compiler/compiler-20140814.zip",
+4 -1
View File
@@ -6,6 +6,9 @@
This error occurs when a module fails to load due to some exception. The error
message above should provide additional context.
A common reason why the module fails to load is that you've forgotten to
include the file with the defined module or that the file couldn't be loaded.
### Using `ngRoute`
In AngularJS `1.2.0` and later, `ngRoute` has been moved to its own module.
@@ -24,4 +27,4 @@ angular.module('ng').filter('tel', function (){});
Instead create your own module and add it as a dependency to your application's top-level module.
See [#9692](https://github.com/angular/angular.js/issues/9692) and
[#7709](https://github.com/angular/angular.js/issues/7709) for more information
[#7709](https://github.com/angular/angular.js/issues/7709) for more information
+3
View File
@@ -81,3 +81,6 @@ angular.module('myModule', [])
// a scope object cannot be injected into a service.
}]);
```
If you encounter this error only with minified code, consider using `ngStrictDi` (see
{@link ng.directive:ngApp ngApp}) to provoke the error with the non-minified source.
@@ -0,0 +1,28 @@
@ngdoc error
@name ngModel:nopromise
@fullName No promise
@description
The return value of an async validator, must always be a promise. If you want to return a
non-promise value, you can convert it to a promise using {@link ng.$q#resolve `$q.resolve()`} or
{@link ng.$q#reject `$q.reject()`}.
Example:
```
.directive('asyncValidator', function($q) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
ngModel.$asyncValidators.myAsyncValidation = function(modelValue, viewValue) {
if (/* I don't need to hit the backend API */) {
return $q.resolve(); // to mark as valid or
// return $q.reject(); // to mark as invalid
} else {
// ...send a request to the backend and return a promise
}
};
}
};
})
```
+8 -3
View File
@@ -99,8 +99,13 @@ For example, the following forms are all equivalent and match the {@link ngBind}
</file>
<file name="protractor.js" type="protractor">
it('should show off bindings', function() {
expect(element(by.css('div[ng-controller="Controller"] span[ng-bind]')).getText())
.toBe('Max Karl Ernst Ludwig Planck (April 23, 1858 October 4, 1947)');
var containerElm = element(by.css('div[ng-controller="Controller"]'));
var nameBindings = containerElm.all(by.binding('name'));
expect(nameBindings.count()).toBe(5);
nameBindings.each(function(elem) {
expect(elem.getText()).toEqual('Max Karl Ernst Ludwig Planck (April 23, 1858 October 4, 1947)');
});
});
</file>
</example>
@@ -401,7 +406,7 @@ This is clearly not a great solution.
What we want to be able to do is separate the scope inside a directive from the scope
outside, and then map the outer scope to a directive's inner scope. We can do this by creating what
we call an **isolate scope**. To do this, we can use a directive's `scope` option:
we call an **isolate scope**. To do this, we can use a {@link $compile#-scope- directive's `scope`} option:
<example module="docsIsolateScopeDirective">
<file name="script.js">
+10 -5
View File
@@ -32,10 +32,13 @@ E.g. the markup `{{ 1234 | number:2 }}` formats the number 1234 with 2 decimal p
## Using filters in controllers, services, and directives
You can also use filters in controllers, services, and directives. For this, inject a dependency
with the name `<filterName>Filter` to your controller/service/directive. E.g. using the dependency
`numberFilter` will inject the number filter. The injected argument is a function that takes the
value to format as first argument and filter parameters starting with the second argument.
You can also use filters in controllers, services, and directives.
<div class="alert alert-info">
For this, inject a dependency with the name `<filterName>Filter` into your controller/service/directive.
E.g. a filter called `number` is injected by using the dependency `numberFilter`. The injected argument
is a function that takes the value to format as first argument, and filter parameters starting with the second argument.
</div>
The example below uses the filter called {@link ng.filter:filter `filter`}.
This filter reduces arrays into sub arrays based on
@@ -108,6 +111,7 @@ text upper-case.
No filter: {{greeting}}<br>
Reverse: {{greeting|reverse}}<br>
Reverse + uppercase: {{greeting|reverse:true}}<br>
Reverse, filtered in controller: {{filteredGreeting}}<br>
</div>
</file>
@@ -127,8 +131,9 @@ text upper-case.
return out;
};
})
.controller('MyController', ['$scope', function($scope) {
.controller('MyController', ['$scope', 'reverseFilter', function($scope, reverseFilter) {
$scope.greeting = 'hello';
$scope.filteredGreeting = reverseFilter($scope.greeting);
}]);
</file>
</example>
+3 -3
View File
@@ -5,7 +5,7 @@
# Interpolation and data-binding
Interpolation markup with embedded @link {guide/expressions expressions} is used by Angular to
Interpolation markup with embedded {@link guide/expression expressions} is used by Angular to
provide data-binding to text nodes and attribute values.
An example of interpolation is shown below:
@@ -43,8 +43,8 @@ interpret the attribute as present, meaning that the button would always be disa
```
For this reason, Angular provides special `ng`-prefixed directives for the following boolean attributes:
{@link ngDisabled `disabled`}, [@link ngRequired `required`}, [@link ngSelected `selected`},
{@link ngChecked `checked`}, {@link ngReadonly `readOnly`} , and [@link ngOpen `open`}.
{@link ngDisabled `disabled`}, {@link ngRequired `required`}, {@link ngSelected `selected`},
{@link ngChecked `checked`}, {@link ngReadonly `readOnly`} , and {@link ngOpen `open`}.
These directives take an expression inside the attribute, and set the corresponding boolean attribute
to true when the expression evaluates to truthy.
+150
View File
@@ -13,6 +13,156 @@ which drives many of these changes.
* Several new features, especially animations, would not be possible without a few changes.
* Finally, some outstanding bugs were best fixed by changing an existing API.
# Migrate from 1.4 to 1.5
Angular 1.5 takes a big step towards preparing developers for a smoother transition to Angular 2 in
the future. Architecturing your applications using components, making use of lifecycle hooks in
directive controllers and relying on native ES6 features (such as classes and arrow functions) are
now all possible with Angular 1.5.
This release includes numerous bug and security fixes, as well as performance improvements to core
services, directives, filters and helper functions. Existing applications can start enjoying the
benefits of such changes in `$compile`, `$parse`, `$animate`, `$animateCss`, `$sanitize`, `ngOptions`,
`currencyFilter`, `numberFilter`, `copy()` (to name but a few) without any change in code.
New features have been added to more than a dozen services, directives and filters across 7 modules.
Among them, a few stand out:
* `angular.component()`: Introducing "components", a special sort of directive that are easy to
configure and promote best practices (plus can bring Angular 1 applications closer to Angular 2's
style of architecture).
* Multi-slot transclusion: Enabling the design of more powerful and complex UI elements with a much
simpler configuration and reduced boilerplate.
* `ngAnimateSwap`: A new directive in `ngAnimate`, making it super easy to create rotating
banner-like components
* Testing helpers: New helper functions in `ngMock`, simplifying testing for animations, component
controllers and routing.
Also, notable is the improved support for ES6 features, such as classes and arrow functions. These
features are now more reliably detected and correctly handled within the core.
All this goodness doesn't come without a price, though. Below is a list of breaking changes (grouped
by module) that need to be taken into account while migrating from 1.4. Fortunately, the majority of
them should have a pretty low impact on most applications.
## Core
We tried to keep the breaking changes inside the core components to a bare minimum. Still, a few of
them were unavoidable.
### Services (`$parse`)
Due to [0ea53503](https://github.com/angular/angular.js/commit/0ea535035a3a1a992948490c3533bffb83235052),
a new special property, `$locals`, will be available for accessing the locals from an expression.
This is a breaking change, only if a `$locals` property does already exist (and needs to be
referenced) either on the `scope` or on the `locals` object. Your expressions should be changed to
access such existing properties as `this.$locals` and `$locals.$locals` respectively.
### Directives (`ngOptions`)
A fair amount of work has been put into the `ngOptions` directive, fixing bugs and corner-cases and
neutralizing browser quirks. A couple of breaking changes were made in the process:
Due to [b71d7c3f](https://github.com/angular/angular.js/commit/b71d7c3f3c04e65b02d88b33c22dd90ae3cdfc27),
falsy values (`''`, `0`, `false` and `null`) are properly recognized as option group identifiers for
options passed to `ngOptions`. Previously, all of these values were ignored and the option was not
assigned to any group. `undefined` is still interpreted as "no group".
If you have options with falsy group indentifiers that should still not be assigned to any group,
then you must filter the values before passing them to `ngOptions`, converting falsy values to
`undefined`.
Due to [ded25187](https://github.com/angular/angular.js/commit/ded2518756d4409fdfda0d4af243f2125bea01b5),
`ngOptions` now explicitly requires `ngModel` on the same element, thus an error will be thrown if
`ngModel` is not found. Previously, `ngOptions` would silently fail, which could lead to
hard-to-debug errors.
This is not expected to have any significant impact on applications, since `ngOptions` didn't work
without `ngModel` before either. The main difference is that now it will fail with a more
informative error message.
### Filters (`orderBy`)
Due to [2a85a634](https://github.com/angular/angular.js/commit/2a85a634f86c84f15b411ce009a3515fca7ba580),
passing a non-array-like value (other than `undefined` or `null`) through the `orderBy` filter will
throw an error. Previously, the input was returned unchanged, which could lead to hard-to-spot bugs
and was not consistent with other filters (e.g. `filter`).
Objects considered array-like include: arrays, array subclasses, strings, NodeLists,
jqLite/jQuery collections
## ngMessages (`ngMessage`)
Due to [4971ef12](https://github.com/angular/angular.js/commit/4971ef12d4c2c268cb8d26f90385dc96eba19db8),
the `ngMessage` directive is now compiled with a priority of 1, which means directives on the same
element as `ngMessage` with a priority lower than 1 will be applied when `ngMessage` calls its
`$transclude` function. Previously, they were applied during the initial compile phase and were
passed the comment element created by the transclusion of `ngMessage`.
If you have custom directives that relied on the previous behavior, you need to give them a priority
of 1 or greater.
## ngResource (`$resource`)
The `$resource` service underwent a minor internal refactoring to finally solve a long-standing bug
preventing requests from being cancelled using promises. Due to the nature of `$resource`'s
configuration, it was not possible to follow the `$http` convention. A new `$cancelRequest()` method
was introduced instead.
Due to [98528be3](https://github.com/angular/angular.js/commit/98528be311b48269ba0e15ba4e3e2ad9b89693a9),
using a promise as `timeout` in `$resource` is no longer supported and will log a warning. This is
hardly expected to affect the behavior of your application, since a promise as `timeout` didn't work
before either, but it will now warn you explicitly when trying to pass one.
If you need to be able to cancel pending requests, you can now use the new `$cancelRequest()` that
will be available on `$resource` instances.
## ngRoute (`ngView`)
Due to [983b0598](https://github.com/angular/angular.js/commit/983b0598121a8c5a3a51a30120e114d7e3085d4d),
a new property will be available on the scope of the route, allowing easy access to the route's
resolved values from the view's template. The default name for this property is `$resolve`. This is
a breaking change, only if a `$resolve` property is already available on the scope, in which case
the existing property will be hidden or overwritten.
To fix this, you should choose a custom name for this property, that does not collide with other
properties on the scope, by specifying the `resolveAs` property on the route.
## ngSanitize (`$sanitize`, `linky`)
The HTML sanitizer has been re-implemented using inert documents, increasing security, fixing some
corner-cases that were difficult to handle and reducing its size by about 20% (in terms of loc). In
order to make it more secure by default, a couple of breaking changes have been introduced:
Due to [181fc567](https://github.com/angular/angular.js/commit/181fc567d873df065f1e84af7225deb70a8d2eb9),
SVG support in `$sanitize` is now an opt-in feature (i.e. disabled by default), as it could make
an application vulnerable to click-hijacking attacks. If your application relies on it, you can
still turn it on with `$sanitizeProvider.enableSvg(true)`, but you extra precautions need to be
taken in order to keep your application secure. Read the documentation for more information about
the dangers and ways to mitigate them.
Due to [7a668cdd](https://github.com/angular/angular.js/commit/7a668cdd7d08a7016883eb3c671cbcd586223ae8),
the `$sanitize` service will now remove instances of the `<use>` tag from the content passed to it.
This element is used to import external SVG resources, which is a security risk as the `$sanitize`
service does not have access to the resource in order to sanitize it.
Due to [98c2db7f](https://github.com/angular/angular.js/commit/98c2db7f9c2d078a408576e722407d518c7ee10a),
passing a non-string value (other than `undefined` or `null`) through the `linky` filter will throw
an error. This is not expected to have any significant impact on applications, since the input was
always assumed to be of type 'string', so passing non-string values never worked correctly anyway.
The main difference is that now it will fail faster and with a more informative error message.
# Migrating from 1.3 to 1.4
Angular 1.4 fixes major animation issues and introduces a new API for `ngCookies`. Further, there
+2 -3
View File
@@ -75,9 +75,8 @@ that you break your application to multiple modules like this:
* And an application level module which depends on the above modules and contains any
initialization code.
We've also
[written a document](http://angularjs.blogspot.com/2014/02/an-angularjs-style-guide-and-best.html)
on how we organize large apps at Google.
You can find a community
[style guide](https://github.com/johnpapa/angular-styleguide) to help yourself when application grows.
The above is a suggestion. Tailor it to your needs.
+10
View File
@@ -246,6 +246,15 @@ npm run update-webdriver
*(You should only need to do this once.)*
You will need to have Java present on your dev machine to allow the Selenium standalone to be started.
Check if you already have java installed by opening a terminal/command line window and typing
'''
java -version
'''
If java is already installed and exists in the PATH then you will be shown the version installed,
if, however you receive a message that "java is not recognized as an internal command or external
command" you will need to install [java].
Since Protractor works by interacting with a running application, we need to start our web server:
```
@@ -280,3 +289,4 @@ Now that you have set up your local machine, let's get started with the tutorial
[bower]: http://bower.io/
[http-server]: https://github.com/nodeapps/http-server
[karma]: https://github.com/karma-runner/karma
[java]: https://www.java.com/en/download/help/download_options.xml
+1 -1
View File
@@ -43,7 +43,7 @@ __`app/index.html`:__
...
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}" alt="{{phone.name}}"></a>
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
<p>{{phone.snippet}}</p>
</li>
+12
View File
@@ -53,6 +53,18 @@ preconfigured npm to run bower install for us:
npm install
```
<div class="alert alert-warning">
**Warning:** If a new version of Angular has been released since you last ran `npm install`, then you may have a
problem with the `bower install` due to a conflict between the versions of angular.js that need to
be installed. If you get this then simply delete your `app/bower_components` folder before running
`npm install`.
</div>
<div class="alert alert-info">
**Note:** If you have bower installed globally then you can run `bower install` but for this project we have
preconfigured `npm install` to run bower for us.
</div>
## Multiple Views, Routing and Layout Template
+4 -4
View File
@@ -239,7 +239,7 @@ The name of the starting class is the name of the event that is fired (like `ent
The active class name is the same as the starting class's but with an `-active` suffix.
This two-class CSS naming convention allows the developer to craft an animation, beginning to end.
In our example above, elements are expanded from a height of **0** to **120 pixels** when they're added to the
In our example above, elements are expanded from a height of **0** to **120 pixels** when they're added to the
list and are collapsed back down to **0 pixels** before being removed from the list.
There's also a nice fade-in and fade-out effect that occurs at the same time. All of this is handled
by the CSS transition declarations at the top of the example code above.
@@ -357,10 +357,10 @@ For more on CSS animations, see the
## Animating `ngClass` with JavaScript
Let's add another animation to our application. Switching to our `phone-detail.html` page,
we see that we have a nice thumbnail swapper. By clicking on the thumbnails listed on the page,
we see that we have a nice thumbnail swapper. By hovering over the thumbnails listed on the page,
the profile phone image changes. But how can we change this around to add animations?
Let's think about it first. Basically, when you click on a thumbnail image, you're changing the
Let's think about it first. Basically, when you hover over a thumbnail image, you're changing the
state of the profile image to reflect the newly selected thumbnail image.
The best way to specify state changes within HTML is to use classes.
Much like before, how we used a CSS class to specify an animation, this time the animation will
@@ -369,7 +369,7 @@ occur whenever the CSS class itself changes.
Whenever a new phone thumbnail is selected, the state changes and the `.active` CSS class is added
to the matching profile image and the animation plays.
Let's get started and tweak our HTML code on the `phone-detail.html` page first. Notice that we
Let's get started and tweak our HTML code on the `phone-detail.html` page first. Notice that we
have changed the way we display our large image:
__`app/partials/phone-detail.html`.__
+1 -1
View File
@@ -5,7 +5,7 @@ set -e
BASE_DIR=`dirname $0`
cd $BASE_DIR
./run-tests.sh
npm run test-i18n
node src/closureSlurper.js
-6
View File
@@ -1,6 +0,0 @@
#!/bin/bash
set -e
PARENT_DIR="$(dirname "$0")"
../node_modules/.bin/jasmine-node "$PARENT_DIR"/spec/
+76 -65
View File
@@ -4,6 +4,7 @@ findLocaleId = closureI18nExtractor.findLocaleId;
extractNumberSymbols = closureI18nExtractor.extractNumberSymbols;
extractCurrencySymbols = closureI18nExtractor.extractCurrencySymbols;
extractDateTimeSymbols = closureI18nExtractor.extractDateTimeSymbols;
outputLocale = closureI18nExtractor.outputLocale;
function newTestLocaleInfo() {
@@ -72,7 +73,7 @@ describe("findLocaleId", function() {
it("should throw an error otherwise", function() {
expect(function() {
findLocaleId("str", "otherwise")
}).toThrow("unknown type in findLocaleId: otherwise");
}).toThrowError("unknown type in findLocaleId: otherwise");
});
});
@@ -131,7 +132,10 @@ describe("extractCurrencySymbols", function() {
].join('\n');
var localeInfo = {};
expect(extractCurrencySymbols(CONTENT)).toEqual({
var currencySymbols = extractCurrencySymbols(CONTENT);
expect(currencySymbols.GBP).toEqual([2, '£', 'GB£']);
expect(currencySymbols.AOA).toEqual([2, 'Kz', 'Kz']);
expect(currencySymbols).toEqual({
'GBP':[2, '£', 'GB£'],
'AOA':[2, 'Kz', 'Kz']
});
@@ -142,71 +146,71 @@ describe("extractCurrencySymbols", function() {
describe("extractDateTimeSymbols", function() {
it("should extract date time data", function() {
var CONTENT = [
"goog.i18n.DateTimeSymbols_fr_CA = {",
" ERAS: ['av. J.-C.', 'ap. J.-C.'],",
" ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],",
" NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],",
" STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',",
" 'N', 'D'],",
" MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',",
" 'août', 'septembre', 'octobre', 'novembre', 'décembre'],",
" STANDALONEMONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',",
" 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],",
" SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',",
" 'août', 'sept.', 'oct.', 'nov.', 'déc.'],",
" STANDALONESHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin',",
" 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],",
" WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',",
" 'samedi'],",
" STANDALONEWEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi',",
" 'vendredi', 'samedi'],",
" SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],",
" STANDALONESHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.',",
" 'sam.'],",
" NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],",
" STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],",
" SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],",
" QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],",
" AMPMS: ['AM', 'PM'],",
" DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'yyyy-MM-dd', 'yy-MM-dd'],",
" TIMEFORMATS: ['HH \\'h\\' mm \\'min\\' ss \\'s\\' zzzz', 'HH:mm:ss z',",
" 'HH:mm:ss', 'HH:mm'],",
" FIRSTDAYOFWEEK: 6,",
" WEEKENDRANGE: [5, 6],",
" FIRSTWEEKCUTOFFDAY: 2",
"};"
"goog.i18n.DateTimeSymbols_fr_CA = {",
" ERAS: ['av. J.-C.', 'ap. J.-C.'],",
" ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],",
" NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],",
" STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',",
" 'N', 'D'],",
" MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',",
" 'août', 'septembre', 'octobre', 'novembre', 'décembre'],",
" STANDALONEMONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',",
" 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],",
" SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',",
" 'août', 'sept.', 'oct.', 'nov.', 'déc.'],",
" STANDALONESHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin',",
" 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],",
" WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',",
" 'samedi'],",
" STANDALONEWEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi',",
" 'vendredi', 'samedi'],",
" SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],",
" STANDALONESHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.',",
" 'sam.'],",
" NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],",
" STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],",
" SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],",
" QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],",
" AMPMS: ['AM', 'PM'],",
" DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'yyyy-MM-dd', 'yy-MM-dd'],",
" TIMEFORMATS: ['HH \\'h\\' mm \\'min\\' ss \\'s\\' zzzz', 'HH:mm:ss z',",
" 'HH:mm:ss', 'HH:mm'],",
" FIRSTDAYOFWEEK: 6,",
" WEEKENDRANGE: [5, 6],",
" FIRSTWEEKCUTOFFDAY: 2",
"};"
].join('\n');
var localeInfo = {};
var expectedLocaleInfo = {
fr_CA: {
DATETIME_FORMATS: {
MONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
'octobre', 'novembre', 'décembre'],
STANDALONEMONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
'août', 'septembre', 'octobre', 'novembre', 'décembre'],
SHORTMONTH: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.',
'nov.', 'déc.'],
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
AMPMS: ['AM', 'PM'],
ERAS: ['av. J.-C.', 'ap. J.-C.'],
ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
medium: 'yyyy-MM-dd HH:mm:ss',
short: 'yy-MM-dd HH:mm',
fullDate: 'EEEE d MMMM y',
longDate: 'd MMMM y',
mediumDate: 'yyyy-MM-dd',
shortDate: 'yy-MM-dd',
mediumTime: 'HH:mm:ss',
shortTime: 'HH:mm'
}
var localeInfo = {};
var expectedLocaleInfo = {
fr_CA: {
DATETIME_FORMATS: {
MONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
'octobre', 'novembre', 'décembre'],
STANDALONEMONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
'août', 'septembre', 'octobre', 'novembre', 'décembre'],
SHORTMONTH: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.',
'nov.', 'déc.'],
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
AMPMS: ['AM', 'PM'],
ERAS: ['av. J.-C.', 'ap. J.-C.'],
ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
medium: 'yyyy-MM-dd HH:mm:ss',
short: 'yy-MM-dd HH:mm',
fullDate: 'EEEE d MMMM y',
longDate: 'd MMMM y',
mediumDate: 'yyyy-MM-dd',
shortDate: 'yy-MM-dd',
mediumTime: 'HH:mm:ss',
shortTime: 'HH:mm'
}
};
extractDateTimeSymbols(CONTENT, localeInfo);
expect(localeInfo).toEqual(expectedLocaleInfo);
})
}
};
extractDateTimeSymbols(CONTENT, localeInfo);
expect(localeInfo).toEqual(expectedLocaleInfo);
});
});
describe("pluralExtractor", function() {
@@ -272,3 +276,10 @@ describe("serializeContent", function() {
});
});
describe("outputLocale", function() {
it("should render the correct locale ids", function() {
var output = outputLocale(newTestLocaleInfo(), 'fr_CA');
expect(output).toContain('"id": "fr-ca"');
expect(output).toContain('"localeID": "fr_CA"');
});
});
+9 -7
View File
@@ -50,10 +50,10 @@ function extractNumberSymbols(content, localeInfo, currencySymbols) {
function extractCurrencySymbols(content) {
//eval script in the current context so that we get access to all the symbols
eval(content.toString());
var currencySymbols = goog.i18n.currency.CurrencyInfo;
currencySymbols.__proto__ = goog.i18n.currency.CurrencyInfoTier2;
// var currencySymbols = goog.i18n.currency.CurrencyInfo;
// currencySymbols.__proto__ = goog.i18n.currency.CurrencyInfoTier2;
return currencySymbols;
return Object.assign({}, goog.i18n.currency.CurrencyInfoTier2, goog.i18n.currency.CurrencyInfo);
}
function extractDateTimeSymbols(content, localeInfo) {
@@ -79,7 +79,7 @@ function pluralExtractor(content, localeInfo) {
goog.LOCALE = localeIds[i].match(/[^_]+/)[0];
try {
eval(contentText);
} catch(e) {
} catch (e) {
console.log("Error in eval(contentText): " + e.stack);
}
if (!goog.i18n.pluralRules.select) {
@@ -133,7 +133,7 @@ function canonicalizeForJsonStringify(unused_key, object) {
function serializeContent(localeObj) {
return JSON.stringify(localeObj, canonicalizeForJsonStringify, ' ')
.replace(new RegExp('[\\u007f-\\uffff]', 'g'), function(c) { return '\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4); })
.replace(new RegExp('[\\u007f-\\uffff]', 'g'), function(c) { return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); })
.replace(/"@@|@@"/g, '');
}
@@ -161,6 +161,7 @@ function outputLocale(localeInfo, localeID) {
if (!localeObj.DATETIME_FORMATS) {
localeObj.DATETIME_FORMATS = fallBackObj.DATETIME_FORMATS;
}
localeObj.localeID = localeID;
localeObj.id = correctedLocaleId(localeID);
var getDecimals = [
@@ -201,10 +202,11 @@ function outputLocale(localeInfo, localeID) {
DATETIME_FORMATS: localeObj.DATETIME_FORMATS,
NUMBER_FORMATS: localeObj.NUMBER_FORMATS,
pluralCat: localeObj.pluralCat,
id: localeObj.id
id: localeObj.id,
localeID: localeID
};
var content = serializeContent(localeInfo[localeID]);
var content = serializeContent(localeObj);
if (content.indexOf('getVF(') < 0) {
getVF = '';
}
@@ -2142,7 +2142,7 @@ queue}</string>
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qr
\f0\fs22 \cf2 $scope\
name='Wold'}</string>
name='World'}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
+90 -95
View File
@@ -8810,61 +8810,45 @@
}
},
"jasmine-node": {
"version": "1.14.5",
"version": "2.0.0",
"dependencies": {
"coffee-script": {
"version": "1.9.1"
},
"jasmine-growl-reporter": {
"version": "0.0.3",
"dependencies": {
"growl": {
"version": "1.7.0"
}
}
},
"requirejs": {
"version": "2.1.17"
"version": "1.7.1"
},
"walkdir": {
"version": "0.0.7"
"version": "0.0.11"
},
"underscore": {
"version": "1.8.3"
"version": "1.6.0"
},
"gaze": {
"version": "0.3.4",
"version": "0.5.2",
"dependencies": {
"minimatch": {
"version": "0.2.14",
"globule": {
"version": "0.1.0",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
"lodash": {
"version": "1.0.2"
},
"sigmund": {
"version": "1.0.0"
}
}
},
"fileset": {
"version": "0.1.5",
"dependencies": {
"glob": {
"version": "3.2.11",
"version": "3.1.21",
"dependencies": {
"inherits": {
"version": "2.0.1"
"graceful-fs": {
"version": "1.2.3"
},
"minimatch": {
"version": "0.3.0",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
},
"sigmund": {
"version": "1.0.0"
}
}
"inherits": {
"version": "1.0.2"
}
}
},
"minimatch": {
"version": "0.2.14",
"dependencies": {
"lru-cache": {
"version": "2.7.3"
},
"sigmund": {
"version": "1.0.1"
}
}
}
@@ -8874,6 +8858,17 @@
},
"mkdirp": {
"version": "0.3.5"
},
"minimist": {
"version": "0.0.8"
},
"jasmine-growl-reporter": {
"version": "0.2.1",
"dependencies": {
"growl": {
"version": "1.7.0"
}
}
}
}
},
@@ -9249,21 +9244,21 @@
}
}
},
"ansi": {
"version": "0.3.0"
},
"ansi-regex": {
"version": "2.0.0"
},
"ansi": {
"version": "0.3.0"
},
"ansi-styles": {
"version": "2.1.0"
},
"are-we-there-yet": {
"version": "1.0.4"
},
"asn1": {
"version": "0.2.3"
},
"are-we-there-yet": {
"version": "1.0.4"
},
"assert-plus": {
"version": "0.1.5"
},
@@ -9291,12 +9286,12 @@
"commander": {
"version": "2.9.0"
},
"core-util-is": {
"version": "1.0.2"
},
"cryptiles": {
"version": "2.0.5"
},
"core-util-is": {
"version": "1.0.2"
},
"dashdash": {
"version": "1.10.1"
},
@@ -9309,42 +9304,42 @@
"delayed-stream": {
"version": "1.0.0"
},
"delegates": {
"version": "0.1.0"
},
"ecc-jsbn": {
"version": "0.1.1"
},
"escape-string-regexp": {
"version": "1.0.3"
},
"delegates": {
"version": "0.1.0"
},
"extend": {
"version": "3.0.0"
},
"form-data": {
"version": "1.0.0-rc3"
},
"extsprintf": {
"version": "1.0.2"
},
"forever-agent": {
"version": "0.6.1"
},
"form-data": {
"version": "1.0.0-rc3"
},
"fstream": {
"version": "1.0.8"
},
"gauge": {
"version": "1.2.2"
},
"generate-function": {
"version": "2.0.0"
},
"generate-object-property": {
"version": "1.2.0"
},
"graceful-fs": {
"version": "4.1.2"
},
"generate-function": {
"version": "2.0.0"
},
"graceful-readlink": {
"version": "1.0.1"
},
@@ -9354,11 +9349,14 @@
"has-ansi": {
"version": "2.0.0"
},
"hawk": {
"version": "3.1.2"
},
"has-unicode": {
"version": "1.0.1"
},
"hawk": {
"version": "3.1.2"
"inherits": {
"version": "2.0.1"
},
"hoek": {
"version": "2.16.3"
@@ -9366,44 +9364,47 @@
"http-signature": {
"version": "1.1.0"
},
"inherits": {
"version": "2.0.1"
},
"ini": {
"version": "1.3.4"
},
"is-my-json-valid": {
"version": "2.12.3"
},
"is-property": {
"version": "1.0.2"
},
"is-my-json-valid": {
"version": "2.12.3"
},
"is-typedarray": {
"version": "1.0.0"
},
"isarray": {
"version": "0.0.1"
},
"jsbn": {
"version": "0.1.0"
},
"isstream": {
"version": "0.1.2"
},
"jodid25519": {
"version": "1.0.2"
},
"jsbn": {
"version": "0.1.0"
},
"json-schema": {
"version": "0.2.2"
},
"json-stringify-safe": {
"version": "5.0.1"
},
"jsprim": {
"version": "1.2.2"
},
"jsonpointer": {
"version": "2.0.0"
},
"jsprim": {
"version": "1.2.2"
"lodash.pad": {
"version": "3.1.1"
},
"lodash.padright": {
"version": "3.1.1"
},
"lodash._basetostring": {
"version": "3.0.1"
@@ -9411,24 +9412,18 @@
"lodash._createpadding": {
"version": "3.6.1"
},
"lodash.pad": {
"version": "3.1.1"
},
"lodash.padleft": {
"version": "3.1.1"
},
"lodash.padright": {
"version": "3.1.1"
"mime-db": {
"version": "1.19.0"
},
"lodash.repeat": {
"version": "3.0.1"
},
"mime-db": {
"version": "1.19.0"
},
"mime-types": {
"version": "2.1.7"
},
"lodash.padleft": {
"version": "3.1.1"
},
"minimist": {
"version": "0.0.8"
},
@@ -9438,15 +9433,15 @@
"node-uuid": {
"version": "1.4.7"
},
"npmlog": {
"version": "2.0.0"
},
"oauth-sign": {
"version": "0.8.0"
},
"once": {
"version": "1.1.1"
},
"npmlog": {
"version": "2.0.0"
},
"pinkie": {
"version": "2.0.1"
},
@@ -9462,24 +9457,24 @@
"request": {
"version": "2.67.0"
},
"semver": {
"version": "5.1.0"
},
"sntp": {
"version": "1.0.9"
},
"semver": {
"version": "5.1.0"
},
"string_decoder": {
"version": "0.10.31"
},
"stringstream": {
"version": "0.0.5"
},
"strip-ansi": {
"version": "3.0.0"
},
"strip-json-comments": {
"version": "1.0.4"
},
"strip-ansi": {
"version": "3.0.0"
},
"supports-color": {
"version": "2.0.0"
},
@@ -9495,12 +9490,12 @@
"tweetnacl": {
"version": "0.13.2"
},
"uid-number": {
"version": "0.0.3"
},
"verror": {
"version": "1.3.6"
},
"uid-number": {
"version": "0.0.3"
},
"xtend": {
"version": "4.0.1"
},
+524 -531
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -16,7 +16,8 @@
"scripts": {
"preinstall": "node scripts/npm/check-node-modules.js --purge",
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js",
"commit": "git-cz"
"commit": "git-cz",
"test-i18n": "jasmine-node i18n/spec"
},
"devDependencies": {
"angular-benchpress": "0.x.x",
@@ -51,7 +52,7 @@
"gulp-sourcemaps": "^1.2.2",
"gulp-uglify": "^1.0.1",
"gulp-util": "^3.0.1",
"jasmine-node": "~1.14.5",
"jasmine-node": "^2.0.0",
"jasmine-reporters": "~1.0.1",
"jshint-stylish": "~1.0.0",
"karma": "^0.13.19",
+1
View File
@@ -138,6 +138,7 @@
"jqLiteInheritedData": false,
"jqLiteBuildFragment": false,
"jqLiteParseHTML": false,
"jqLiteWrapNode": false,
"getBooleanAttrName": false,
"getAliasedAttrName": false,
"createEventHandler": false,
+32 -53
View File
@@ -119,29 +119,9 @@ var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
// This is used so that it's possible for internal tests to create mock ValidityStates.
var VALIDITY_STATE_PROPERTY = 'validity';
/**
* @ngdoc function
* @name angular.lowercase
* @module ng
* @kind function
*
* @description Converts the specified string to lowercase.
* @param {string} string String to be converted to lowercase.
* @returns {string} Lowercased string.
*/
var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @ngdoc function
* @name angular.uppercase
* @module ng
* @kind function
*
* @description Converts the specified string to uppercase.
* @param {string} string String to be converted to uppercase.
* @returns {string} Uppercased string.
*/
var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
@@ -161,7 +141,7 @@ var manualUppercase = function(s) {
// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
// with correct but slower alternatives.
// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
if ('i' !== 'I'.toLowerCase()) {
lowercase = manualLowercase;
uppercase = manualUppercase;
@@ -313,7 +293,7 @@ function forEachSorted(obj, iterator, context) {
* @returns {function(*, string)}
*/
function reverseParams(iteratorFn) {
return function(value, key) { iteratorFn(key, value); };
return function(value, key) {iteratorFn(key, value);};
}
/**
@@ -725,7 +705,7 @@ function isElement(node) {
* @returns {object} in the form of {key1:true, key2:true, ...}
*/
function makeMap(str) {
var obj = {}, items = str.split(","), i;
var obj = {}, items = str.split(','), i;
for (i = 0; i < items.length; i++) {
obj[items[i]] = true;
}
@@ -1001,38 +981,37 @@ function equals(o1, o2) {
if (o1 === null || o2 === null) return false;
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
if (t1 == t2) {
if (t1 == 'object') {
if (isArray(o1)) {
if (!isArray(o2)) return false;
if ((length = o1.length) == o2.length) {
for (key = 0; key < length; key++) {
if (!equals(o1[key], o2[key])) return false;
}
return true;
}
} else if (isDate(o1)) {
if (!isDate(o2)) return false;
return equals(o1.getTime(), o2.getTime());
} else if (isRegExp(o1)) {
return isRegExp(o2) ? o1.toString() == o2.toString() : false;
} else {
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
keySet = createMap();
for (key in o1) {
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
if (t1 == t2 && t1 == 'object') {
if (isArray(o1)) {
if (!isArray(o2)) return false;
if ((length = o1.length) == o2.length) {
for (key = 0; key < length; key++) {
if (!equals(o1[key], o2[key])) return false;
keySet[key] = true;
}
for (key in o2) {
if (!(key in keySet) &&
key.charAt(0) !== '$' &&
isDefined(o2[key]) &&
!isFunction(o2[key])) return false;
}
return true;
}
} else if (isDate(o1)) {
if (!isDate(o2)) return false;
return equals(o1.getTime(), o2.getTime());
} else if (isRegExp(o1)) {
if (!isRegExp(o2)) return false;
return o1.toString() == o2.toString();
} else {
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
keySet = createMap();
for (key in o1) {
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
if (!equals(o1[key], o2[key])) return false;
keySet[key] = true;
}
for (key in o2) {
if (!(key in keySet) &&
key.charAt(0) !== '$' &&
isDefined(o2[key]) &&
!isFunction(o2[key])) return false;
}
return true;
}
}
return false;
@@ -1271,7 +1250,7 @@ function startingTag(element) {
return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
elemHtml.
match(/^(<[^>]+>)/)[1].
replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});
} catch (e) {
return lowercase(elemHtml);
}
+14 -2
View File
@@ -491,8 +491,20 @@ function annotate(fn, strictDi, name) {
*
* Register a **service constructor**, which will be invoked with `new` to create the service
* instance.
* This is short for registering a service where its provider's `$get` property is the service
* constructor function that will be used to instantiate the service instance.
* This is short for registering a service where its provider's `$get` property is a factory
* function that returns an instance instantiated by the injector from the service constructor
* function.
*
* Internally it looks a bit like this:
*
* ```
* {
* $get: function() {
* return $injector.instantiate(constructor);
* }
* }
* ```
*
*
* You should use {@link auto.$provide#service $provide.service(class)} if you define your service
* as a type/class.
+11 -6
View File
@@ -254,6 +254,16 @@ function jqLiteParseHTML(html, context) {
return [];
}
function jqLiteWrapNode(node, wrapper) {
var parent = node.parentNode;
if (parent) {
parent.replaceChild(wrapper, node);
}
wrapper.appendChild(node);
}
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
var jqLiteContains = Node.prototype.contains || function(arg) {
@@ -946,12 +956,7 @@ forEach({
},
wrap: function(element, wrapNode) {
wrapNode = jqLite(wrapNode).eq(0).clone()[0];
var parent = element.parentNode;
if (parent) {
parent.replaceChild(wrapNode, element);
}
wrapNode.appendChild(element);
jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]);
},
remove: jqLiteRemove,
+2 -2
View File
@@ -329,8 +329,8 @@ var $AnimateProvider = ['$provide', function($provide) {
* // remove all the animation event listeners listening for `enter` on the given element and its children
* $animate.off('enter', container);
*
* // remove the event listener function provided by `listenerFn` that is set
* // to listen for `enter` on the given `element` as well as its children
* // remove the event listener function provided by `callback` that is set
* // to listen for `enter` on the given `container` as well as its children
* $animate.off('enter', container, callback);
* ```
*
+19 -4
View File
@@ -28,8 +28,8 @@ var $$AnimateAsyncRunFactoryProvider = function() {
};
var $$AnimateRunnerFactoryProvider = function() {
this.$get = ['$q', '$sniffer', '$$animateAsyncRun',
function($q, $sniffer, $$animateAsyncRun) {
this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {
var INITIAL_STATE = 0;
var DONE_PENDING_STATE = 1;
@@ -74,8 +74,23 @@ var $$AnimateRunnerFactoryProvider = function() {
function AnimateRunner(host) {
this.setHost(host);
var rafTick = $$animateAsyncRun();
var timeoutTick = function(fn) {
$timeout(fn, 0, false);
};
this._doneCallbacks = [];
this._runInAnimationFrame = $$animateAsyncRun();
this._tick = function(fn) {
var doc = $document[0];
// the document may not be ready or attached
// to the module for some internal tests
if (doc && doc.hidden) {
timeoutTick(fn);
} else {
rafTick(fn);
}
};
this._state = 0;
}
@@ -148,7 +163,7 @@ var $$AnimateRunnerFactoryProvider = function() {
var self = this;
if (self._state === INITIAL_STATE) {
self._state = DONE_PENDING_STATE;
self._runInAnimationFrame(function() {
self._tick(function() {
self._resolve(response);
});
}
+160 -20
View File
@@ -218,8 +218,18 @@
* definition: `controller: 'myCtrl as myAlias'`.
*
* When an isolate scope is used for a directive (see above), `bindToController: true` will
* allow a component to have its properties bound to the controller, rather than to scope. When the controller
* is instantiated, the initial values of the isolate scope bindings will be available if the controller is not an ES6 class.
* allow a component to have its properties bound to the controller, rather than to scope.
*
* After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller
* properties. You can access these bindings once they have been initialized by providing a controller method called
* `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings
* initialized.
*
* <div class="alert alert-warning">
* **Deprecation warning:** although bindings for non-ES6 class controllers are currently
* bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization
* code that relies upon bindings inside a `$onInit` method on the controller, instead.
* </div>
*
* It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.
* This will set up the scope bindings to the controller directly. Note that `scope` can still be used
@@ -255,12 +265,29 @@
* The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns
* `true` if the specified slot contains content (i.e. one or more DOM nodes).
*
* The controller can provide the following methods that act as life-cycle hooks:
* * `$onInit` - Called on each controller after all the controllers on an element have been constructed and
* had their bindings initialized (and before the pre &amp; post linking functions for the directives on
* this element). This is a good place to put initialization code for your controller.
*
* #### `require`
* Require another directive and inject its controller as the fourth argument to the linking function. The
* `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
* injected argument will be an array in corresponding order. If no such directive can be
* found, or if the directive does not have a controller, then an error is raised (unless no link function
* is specified, in which case error checking is skipped). The name can be prefixed with:
* `require` property can be a string, an array or an object:
* * a **string** containing the name of the directive to pass to the linking function
* * an **array** containing the names of directives to pass to the linking function. The argument passed to the
* linking function will be an array of controllers in the same order as the names in the `require` property
* * an **object** whose property values are the names of the directives to pass to the linking function. The argument
* passed to the linking function will also be an object with matching keys, whose values will hold the corresponding
* controllers.
*
* If the `require` property is an object and `bindToController` is truthy, then the required controllers are
* bound to the controller using the keys of the `require` property. This binding occurs after all the controllers
* have been constructed but before `$onInit` is called.
* See the {@link $compileProvider#component} helper for an example of how this can be used.
*
* If no such required directive(s) can be found, or if the directive does not have a controller, then an error is
* raised (unless no link function is specified and the required controllers are not being bound to the directive
* controller, in which case error checking is skipped). The name can be prefixed with:
*
* * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
* * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
@@ -731,8 +758,15 @@
* directives; if given, it will be passed through to the link functions of
* directives found in `element` during compilation.
* * `transcludeControllers` - an object hash with keys that map controller names
* to controller instances; if given, it will make the controllers
* available to directives.
* to a hash with the key `instance`, which maps to the controller instance;
* if given, it will make the controllers available to directives on the compileNode:
* ```
* {
* parent: {
* instance: parentControllerInstance
* }
* }
* ```
* * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
* the cloned elements; only needed for transcludes that are allowed to contain non html
* elements (e.g. SVG elements). See also the directive.controller property.
@@ -1005,6 +1039,80 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
*
* ```
*
* ### Intercomponent Communication
* Directives can require the controllers of other directives to enable communication
* between the directives. This can be achieved in a component by providing an
* object mapping for the `require` property. Here is the tab pane example built
* from components...
*
* <example module="docsTabsExample">
* <file name="script.js">
* angular.module('docsTabsExample', [])
* .component('myTabs', {
* transclude: true,
* controller: function() {
* var panes = this.panes = [];
*
* this.select = function(pane) {
* angular.forEach(panes, function(pane) {
* pane.selected = false;
* });
* pane.selected = true;
* };
*
* this.addPane = function(pane) {
* if (panes.length === 0) {
* this.select(pane);
* }
* panes.push(pane);
* };
* },
* templateUrl: 'my-tabs.html'
* })
* .component('myPane', {
* transclude: true,
* require: {tabsCtrl: '^myTabs'},
* bindings: {
* title: '@'
* },
* controller: function() {
* this.$onInit = function() {
* this.tabsCtrl.addPane(this);
* console.log(this);
* };
* },
* templateUrl: 'my-pane.html'
* });
* </file>
* <file name="index.html">
* <my-tabs>
* <my-pane title="Hello">
* <h4>Hello</h4>
* <p>Lorem ipsum dolor sit amet</p>
* </my-pane>
* <my-pane title="World">
* <h4>World</h4>
* <em>Mauris elementum elementum enim at suscipit.</em>
* <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p>
* </my-pane>
* </my-tabs>
* </file>
* <file name="my-tabs.html">
* <div class="tabbable">
* <ul class="nav nav-tabs">
* <li ng-repeat="pane in $ctrl.panes" ng-class="{active:pane.selected}">
* <a href="" ng-click="$ctrl.select(pane)">{{pane.title}}</a>
* </li>
* </ul>
* <div class="tab-content" ng-transclude></div>
* </div>
* </file>
* <file name="my-pane.html">
* <div class="tab-pane" ng-show="$ctrl.selected" ng-transclude></div>
* </file>
* </example>
*
*
* <br />
* Components are also useful as route templates (e.g. when using
* {@link ngRoute ngRoute}):
@@ -1072,7 +1180,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
transclude: options.transclude,
scope: {},
bindToController: options.bindings || {},
restrict: 'E'
restrict: 'E',
require: options.require
};
}
@@ -1182,9 +1291,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
this.$get = [
'$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
'$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
'$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',
function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
$controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
$controller, $rootScope, $sce, $animate, $$sanitizeUri) {
var SIMPLE_ATTR_NAME = /^\w/;
var specialAttrHolder = document.createElement('div');
@@ -1450,7 +1559,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var startSymbol = $interpolate.startSymbol(),
endSymbol = $interpolate.endSymbol(),
denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}')
? identity
: function denormalizeTemplate(template) {
return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
@@ -1494,13 +1603,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// modify it.
$compileNodes = jqLite($compileNodes);
}
var NOT_EMPTY = /\S+/;
// We can not compile top level text elements since text nodes can be merged and we will
// not be able to attach scope data to them, so we will wrap them in <span>
forEach($compileNodes, function(node, index) {
if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */) {
$compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
for (var i = 0, len = $compileNodes.length; i < len; i++) {
var domNode = $compileNodes[i];
if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) {
jqLiteWrapNode(domNode, $compileNodes[i] = document.createElement('span'));
}
});
}
var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext);
@@ -2280,6 +2395,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
for (var i = 0, ii = require.length; i < ii; i++) {
value[i] = getControllers(directiveName, require[i], $element, elementControllers);
}
} else if (isObject(require)) {
value = {};
forEach(require, function(controller, property) {
value[property] = getControllers(directiveName, controller, $element, elementControllers);
});
}
return value || null;
@@ -2388,6 +2508,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}
// Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
forEach(controllerDirectives, function(controllerDirective, name) {
var require = controllerDirective.require;
if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {
extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));
}
});
// Trigger the `$onInit` method on all controllers that have one
forEach(elementControllers, function(controller) {
if (isFunction(controller.instance.$onInit)) {
controller.instance.$onInit();
}
});
// PRELINKING
for (i = 0, ii = preLinkFns.length; i < ii; i++) {
linkFn = preLinkFns[i];
@@ -2956,10 +3091,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
});
attrs.$$observers[attrName].$$scope = scope;
if (isString(attrs[attrName])) {
lastValue = attrs[attrName];
if (isString(lastValue)) {
// If the attribute has been provided then we trigger an interpolation to ensure
// the value is there for use in the link fn
destination[scopeName] = $interpolate(attrs[attrName])(scope);
destination[scopeName] = $interpolate(lastValue)(scope);
} else if (isBoolean(lastValue)) {
// If the attributes is one of the BOOLEAN_ATTR then Angular will have converted
// the value to boolean rather than a string, so we special case this situation
destination[scopeName] = lastValue;
}
break;
@@ -2980,8 +3120,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// reset the change, or we will throw this exception on every $digest
lastValue = destination[scopeName] = parentGet(scope);
throw $compileMinErr('nonassign',
"Expression '{0}' used with directive '{1}' is non-assignable!",
attrs[attrName], directive.name);
"Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
attrs[attrName], attrName, directive.name);
};
lastValue = destination[scopeName] = parentGet(scope);
var parentValueWatch = function parentValueWatch(parentValue) {
+17 -1
View File
@@ -638,7 +638,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
forEach(ctrl.$asyncValidators, function(validator, name) {
var promise = validator(modelValue, viewValue);
if (!isPromiseLike(promise)) {
throw ngModelMinErr("$asyncValidators",
throw ngModelMinErr('nopromise',
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
}
setValidity(name, undefined);
@@ -937,6 +937,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* - {@link ng.directive:select select}
* - {@link ng.directive:textarea textarea}
*
* # Complex Models (objects or collections)
*
* By default, `ngModel` watches the model by reference, not value. This is important to know when
* binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the
* object or collection change, `ngModel` will not be notified and so the input will not be re-rendered.
*
* The model must be assigned an entirely new object or collection before a re-rendering will occur.
*
* Some directives have options that will cause them to use a custom `$watchCollection` on the model expression
* - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or
* if the select is given the `multiple` attribute.
*
* The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the
* first level of the object (or only changing the properties of an item in the collection if it's an array) will still
* not trigger a re-rendering of the model.
*
* # CSS classes
* The following CSS classes are added and removed on the associated input/select/textarea element
* depending on the validity of the model.
+24 -17
View File
@@ -170,6 +170,8 @@
*
* **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
*
* See the example below for defining CSS animations with ngRepeat.
*
* @element ANY
* @scope
* @priority 1000
@@ -222,22 +224,11 @@
* For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
*
* @example
* This example initializes the scope to a list of names and
* then uses `ngRepeat` to display every person:
<example module="ngAnimate" deps="angular-animate.js" animations="true">
* This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed
* results by name. New (entering) and removed (leaving) items are animated.
<example module="ngRepeat" name="ngRepeat" deps="angular-animate.js" animations="true">
<file name="index.html">
<div ng-init="friends = [
{name:'John', age:25, gender:'boy'},
{name:'Jessie', age:30, gender:'girl'},
{name:'Johanna', age:28, gender:'girl'},
{name:'Joy', age:15, gender:'girl'},
{name:'Mary', age:28, gender:'girl'},
{name:'Peter', age:95, gender:'boy'},
{name:'Sebastian', age:50, gender:'boy'},
{name:'Erika', age:27, gender:'girl'},
{name:'Patrick', age:40, gender:'boy'},
{name:'Samantha', age:60, gender:'girl'}
]">
<div ng-controller="repeatController">
I have {{friends.length}} friends. They are:
<input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
<ul class="example-animate-container">
@@ -250,6 +241,22 @@
</ul>
</div>
</file>
<file name="script.js">
angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
$scope.friends = [
{name:'John', age:25, gender:'boy'},
{name:'Jessie', age:30, gender:'girl'},
{name:'Johanna', age:28, gender:'girl'},
{name:'Joy', age:15, gender:'girl'},
{name:'Mary', age:28, gender:'girl'},
{name:'Peter', age:95, gender:'boy'},
{name:'Sebastian', age:50, gender:'boy'},
{name:'Erika', age:27, gender:'girl'},
{name:'Patrick', age:40, gender:'boy'},
{name:'Samantha', age:60, gender:'girl'}
];
});
</file>
<file name="animations.css">
.example-animate-container {
background:white;
@@ -260,7 +267,7 @@
}
.animate-repeat {
line-height:40px;
line-height:30px;
list-style:none;
box-sizing:border-box;
}
@@ -282,7 +289,7 @@
.animate-repeat.ng-move.ng-move-active,
.animate-repeat.ng-enter.ng-enter-active {
opacity:1;
max-height:40px;
max-height:30px;
}
</file>
<file name="protractor.js" type="protractor">
+1 -1
View File
@@ -613,7 +613,7 @@ function dateFilter($locale) {
forEach(parts, function(value) {
fn = DATE_FORMATS[value];
text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
: value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
: value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
});
return text;
+37 -2
View File
@@ -1757,10 +1757,19 @@ function $ParseProvider() {
csp: noUnsafeEval,
expensiveChecks: true
};
var runningChecksEnabled = false;
return function $parse(exp, interceptorFn, expensiveChecks) {
$parse.$$runningExpensiveChecks = function() {
return runningChecksEnabled;
};
return $parse;
function $parse(exp, interceptorFn, expensiveChecks) {
var parsedExpression, oneTime, cacheKey;
expensiveChecks = expensiveChecks || runningChecksEnabled;
switch (typeof exp) {
case 'string':
exp = exp.trim();
@@ -1786,6 +1795,9 @@ function $ParseProvider() {
} else if (parsedExpression.inputs) {
parsedExpression.$$watchDelegate = inputsWatchDelegate;
}
if (expensiveChecks) {
parsedExpression = expensiveChecksInterceptor(parsedExpression);
}
cache[cacheKey] = parsedExpression;
}
return addInterceptor(parsedExpression, interceptorFn);
@@ -1796,7 +1808,30 @@ function $ParseProvider() {
default:
return addInterceptor(noop, interceptorFn);
}
};
}
function expensiveChecksInterceptor(fn) {
if (!fn) return fn;
expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate;
expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign);
expensiveCheckFn.constant = fn.constant;
expensiveCheckFn.literal = fn.literal;
for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) {
fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]);
}
return expensiveCheckFn;
function expensiveCheckFn(scope, locals, assign, inputs) {
var expensiveCheckOldValue = runningChecksEnabled;
runningChecksEnabled = true;
try {
return fn(scope, locals, assign, inputs);
} finally {
runningChecksEnabled = expensiveCheckOldValue;
}
}
}
function expressionInputDirtyCheck(newValue, oldValueOfValue) {
+2 -1
View File
@@ -998,7 +998,7 @@ function $RootScopeProvider() {
});
}
asyncQueue.push({scope: this, expression: expr, locals: locals});
asyncQueue.push({scope: this, expression: $parse(expr), locals: locals});
},
$$postDigest: function(fn) {
@@ -1090,6 +1090,7 @@ function $RootScopeProvider() {
$applyAsync: function(expr) {
var scope = this;
expr && applyAsyncQueue.push($applyAsyncExpression);
expr = $parse(expr);
scheduleApplyAsync();
function $applyAsyncExpression() {
+15 -13
View File
@@ -144,13 +144,15 @@ function $SceDelegateProvider() {
* @kind function
*
* @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
*
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
*
* Note: **an empty whitelist array will block all URLs**!
* <div class="alert alert-warning">
* **Note:** an empty whitelist array will block all URLs!
* </div>
*
* @return {Array} the currently set whitelist array.
*
@@ -173,17 +175,17 @@ function $SceDelegateProvider() {
* @kind function
*
* @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
*
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
*
* The typical usage for the blacklist is to **block
* [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
* these would otherwise be trusted but actually return content from the redirected domain.
* The typical usage for the blacklist is to **block
* [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
* these would otherwise be trusted but actually return content from the redirected domain.
*
* Finally, **the blacklist overrides the whitelist** and has the final say.
* Finally, **the blacklist overrides the whitelist** and has the final say.
*
* @return {Array} the currently set blacklist array.
*
+1 -1
View File
@@ -49,7 +49,7 @@
"assertArg": false,
"isPromiseLike": false,
"mergeClasses": false,
"mergeAnimationOptions": false,
"mergeAnimationDetails": false,
"prepareAnimationOptions": false,
"applyAnimationStyles": false,
"applyAnimationFromStyles": false,
+7
View File
@@ -756,6 +756,13 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
element.off(events.join(' '), onAnimationProgress);
}
//Cancel the fallback closing timeout and remove the timer data
var animationTimerData = element.data(ANIMATE_TIMER_KEY);
if (animationTimerData) {
$timeout.cancel(animationTimerData[0].timer);
element.removeData(ANIMATE_TIMER_KEY);
}
// if the preparation function fails then the promise is not setup
if (runner) {
runner.complete(!rejected);
+54 -41
View File
@@ -42,22 +42,21 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
});
}
function hasAnimationClasses(options, and) {
options = options || {};
var a = (options.addClass || '').length > 0;
var b = (options.removeClass || '').length > 0;
function hasAnimationClasses(animation, and) {
var a = (animation.addClass || '').length > 0;
var b = (animation.removeClass || '').length > 0;
return and ? a && b : a || b;
}
rules.join.push(function(element, newAnimation, currentAnimation) {
// if the new animation is class-based then we can just tack that on
return !newAnimation.structural && hasAnimationClasses(newAnimation.options);
return !newAnimation.structural && hasAnimationClasses(newAnimation);
});
rules.skip.push(function(element, newAnimation, currentAnimation) {
// there is no need to animate anything if no classes are being added and
// there is no structural animation that will be triggered
return !newAnimation.structural && !hasAnimationClasses(newAnimation.options);
return !newAnimation.structural && !hasAnimationClasses(newAnimation);
});
rules.skip.push(function(element, newAnimation, currentAnimation) {
@@ -83,19 +82,17 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
});
rules.cancel.push(function(element, newAnimation, currentAnimation) {
var nA = newAnimation.options.addClass;
var nR = newAnimation.options.removeClass;
var cA = currentAnimation.options.addClass;
var cR = currentAnimation.options.removeClass;
var nA = newAnimation.addClass;
var nR = newAnimation.removeClass;
var cA = currentAnimation.addClass;
var cR = currentAnimation.removeClass;
// early detection to save the global CPU shortage :)
if ((isUndefined(nA) && isUndefined(nR)) || (isUndefined(cA) && isUndefined(cR))) {
return false;
}
return (hasMatchingClasses(nA, cR)) || (hasMatchingClasses(nR, cA));
return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA);
});
this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
@@ -167,8 +164,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
function normalizeAnimationOptions(element, options) {
return mergeAnimationOptions(element, options, {});
function normalizeAnimationDetails(element, animation) {
return mergeAnimationDetails(element, animation, {});
}
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
@@ -337,7 +334,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
// this is a hard disable of all animations for the application or on
// the element itself, therefore there is no need to continue further
// past this point if not enabled
var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node);
// Animations are also disabled if the document is currently hidden (page is not visible
// to the user), because browsers slow down or do not flush calls to requestAnimationFrame
var skipAnimations = !animationsEnabled || $document[0].hidden || disabledElementsLookup.get(node);
var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
var hasExistingAnimation = !!existingAnimation.state;
@@ -360,6 +359,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
structural: isStructural,
element: element,
event: event,
addClass: options.addClass,
removeClass: options.removeClass,
close: close,
options: options,
runner: runner
@@ -372,11 +373,10 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
close();
return runner;
} else {
mergeAnimationOptions(element, existingAnimation.options, options);
mergeAnimationDetails(element, existingAnimation, newAnimation);
return existingAnimation.runner;
}
}
var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation);
if (cancelAnimationFlag) {
if (existingAnimation.state === RUNNING_STATE) {
@@ -391,7 +391,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
existingAnimation.close();
} else {
// this will merge the new animation options into existing animation options
mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
mergeAnimationDetails(element, existingAnimation, newAnimation);
return existingAnimation.runner;
}
} else {
@@ -401,12 +402,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation);
if (joinAnimationFlag) {
if (existingAnimation.state === RUNNING_STATE) {
normalizeAnimationOptions(element, options);
normalizeAnimationDetails(element, newAnimation);
} else {
applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
event = newAnimation.event = existingAnimation.event;
options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
options = mergeAnimationDetails(element, existingAnimation, newAnimation);
//we return the same runner since only the option values of this animation will
//be fed into the `existingAnimation`.
@@ -417,7 +418,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
} else {
// normalization in this case means that it removes redundant CSS classes that
// already exist (addClass) or do not exist (removeClass) on the element
normalizeAnimationOptions(element, options);
normalizeAnimationDetails(element, newAnimation);
}
// when the options are merged and cleaned up we may end up not having to do
@@ -427,7 +428,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
if (!isValidAnimation) {
// animate (from/to) can be quickly checked first, otherwise we check if any classes are present
isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0)
|| hasAnimationClasses(newAnimation.options);
|| hasAnimationClasses(newAnimation);
}
if (!isValidAnimation) {
@@ -457,7 +458,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
var isValidAnimation = parentElement.length > 0
&& (animationDetails.event === 'animate'
|| animationDetails.structural
|| hasAnimationClasses(animationDetails.options));
|| hasAnimationClasses(animationDetails));
// this means that the previous animation was cancelled
// even if the follow-up animation is the same event
@@ -489,7 +490,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
// this combined multiple class to addClass / removeClass into a setClass event
// so long as a structural event did not take over the animation
event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true)
event = !animationDetails.structural && hasAnimationClasses(animationDetails, true)
? 'setClass'
: animationDetails.event;
@@ -569,6 +570,13 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB);
}
/**
* This fn returns false if any of the following is true:
* a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
* b) a parent element has an ongoing structural animation, and animateChildren is false
* c) the element is not a child of the body
* d) the element is not a child of the $rootElement
*/
function areAnimationsAllowed(element, parentElement, event) {
var bodyElement = jqLite($document[0].body);
var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML';
@@ -602,10 +610,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
if (!parentAnimationDetected) {
var parentElementDisabled = disabledElementsLookup.get(parentNode);
// disable animations if the user hasn't explicitly enabled animations on the
// current element
if (parentElementDisabled === true && elementDisabled !== false) {
// disable animations if the user hasn't explicitly enabled animations on the
// current element
elementDisabled = true;
// element is disabled via parent element, no need to check anything else
break;
} else if (parentElementDisabled === false) {
elementDisabled = false;
}
@@ -622,25 +632,28 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
// there is no need to continue traversing at this point
if (parentAnimationDetected && animateChildren === false) break;
if (!rootElementDetected) {
// angular doesn't want to attempt to animate elements outside of the application
// therefore we need to ensure that the rootElement is an ancestor of the current element
rootElementDetected = isMatchingElement(parentElement, $rootElement);
if (!rootElementDetected) {
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
if (parentHost) {
parentElement = parentHost;
rootElementDetected = true;
}
}
}
if (!bodyElementDetected) {
// we also need to ensure that the element is or will be apart of the body element
// we also need to ensure that the element is or will be a part of the body element
// otherwise it is pointless to even issue an animation to be rendered
bodyElementDetected = isMatchingElement(parentElement, bodyElement);
}
if (bodyElementDetected && rootElementDetected) {
// If both body and root have been found, any other checks are pointless,
// as no animation data should live outside the application
break;
}
if (!rootElementDetected) {
// If no rootElement is detected, check if the parentElement is pinned to another element
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
if (parentHost) {
// The pin target element becomes the next parent element
parentElement = parentHost;
continue;
}
}
parentElement = parentElement.parent();
}
+7 -1
View File
@@ -218,7 +218,10 @@ function applyAnimationToStyles(element, options) {
}
}
function mergeAnimationOptions(element, target, newOptions) {
function mergeAnimationDetails(element, oldAnimation, newAnimation) {
var target = oldAnimation.options || {};
var newOptions = newAnimation.options || {};
var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || '');
var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || '');
var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove);
@@ -250,6 +253,9 @@ function mergeAnimationOptions(element, target, newOptions) {
target.removeClass = null;
}
oldAnimation.addClass = target.addClass;
oldAnimation.removeClass = target.removeClass;
return target;
}
+7 -6
View File
@@ -34,16 +34,17 @@ angular.module('ngCookies', ['ng']).
* The object may have following properties:
*
* - **path** - `{string}` - The cookie will be available only for this path and its
* sub-paths. By default, this would be the URL that appears in your base tag.
* sub-paths. By default, this is the URL that appears in your `<base>` tag.
* - **domain** - `{string}` - The cookie will be available only for this domain and
* its sub-domains. For obvious security reasons the user agent will not accept the
* cookie if the current domain is not a sub domain or equals to the requested domain.
* its sub-domains. For security reasons the user agent will not accept the cookie
* if the current domain is not a sub-domain of this domain or equal to it.
* - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
* or a Date object indicating the exact date/time this cookie will expire.
* - **secure** - `{boolean}` - The cookie will be available only in secured connection.
* - **secure** - `{boolean}` - If `true`, then the cookie will only be available through a
* secured connection.
*
* Note: by default the address that appears in your `<base>` tag will be used as path.
* This is important so that cookies will be visible for all routes in case html5mode is enabled
* Note: By default, the address that appears in your `<base>` tag will be used as the path.
* This is important so that cookies will be visible for all routes when html5mode is enabled.
*
**/
var defaults = this.defaults = {};
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "af-na",
"localeID": "af_NA",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "af-za",
"localeID": "af_ZA",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "af",
"localeID": "af",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "agq-cm",
"localeID": "agq_CM",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "agq",
"localeID": "agq",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "ak-gh",
"localeID": "ak_GH",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "ak",
"localeID": "ak",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "am-et",
"localeID": "am_ET",
"pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "am",
"localeID": "am",
"pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-001",
"localeID": "ar_001",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-ae",
"localeID": "ar_AE",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-bh",
"localeID": "ar_BH",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-dj",
"localeID": "ar_DJ",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-dz",
"localeID": "ar_DZ",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-eg",
"localeID": "ar_EG",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-eh",
"localeID": "ar_EH",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-er",
"localeID": "ar_ER",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-il",
"localeID": "ar_IL",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-iq",
"localeID": "ar_IQ",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-jo",
"localeID": "ar_JO",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-km",
"localeID": "ar_KM",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-kw",
"localeID": "ar_KW",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-lb",
"localeID": "ar_LB",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-ly",
"localeID": "ar_LY",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-ma",
"localeID": "ar_MA",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-mr",
"localeID": "ar_MR",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-om",
"localeID": "ar_OM",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-ps",
"localeID": "ar_PS",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-qa",
"localeID": "ar_QA",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-sa",
"localeID": "ar_SA",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-sd",
"localeID": "ar_SD",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-so",
"localeID": "ar_SO",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-ss",
"localeID": "ar_SS",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-sy",
"localeID": "ar_SY",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-td",
"localeID": "ar_TD",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-tn",
"localeID": "ar_TN",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar-ye",
"localeID": "ar_YE",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "ar",
"localeID": "ar",
"pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "as-in",
"localeID": "as_IN",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "as",
"localeID": "as",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "asa-tz",
"localeID": "asa_TZ",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "asa",
"localeID": "asa",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "ast-es",
"localeID": "ast_ES",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "ast",
"localeID": "ast",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "az-cyrl-az",
"localeID": "az_Cyrl_AZ",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "az-cyrl",
"localeID": "az_Cyrl",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "az-latn-az",
"localeID": "az_Latn_AZ",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "az-latn",
"localeID": "az_Latn",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "az",
"localeID": "az",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "bas-cm",
"localeID": "bas_CM",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "bas",
"localeID": "bas",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "be-by",
"localeID": "be_BY",
"pluralCat": function(n, opt_precision) { if (n % 10 == 1 && n % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (n % 10 == 0 || n % 10 >= 5 && n % 10 <= 9 || n % 100 >= 11 && n % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "be",
"localeID": "be",
"pluralCat": function(n, opt_precision) { if (n % 10 == 1 && n % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (n % 10 == 0 || n % 10 >= 5 && n % 10 <= 9 || n % 100 >= 11 && n % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "bem-zm",
"localeID": "bem_ZM",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "bem",
"localeID": "bem",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "bez-tz",
"localeID": "bez_TZ",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -137,6 +137,7 @@ $provide.value("$locale", {
]
},
"id": "bez",
"localeID": "bez",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+1
View File
@@ -119,6 +119,7 @@ $provide.value("$locale", {
]
},
"id": "bg-bg",
"localeID": "bg_BG",
"pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);

Some files were not shown because too many files have changed in this diff Show More