Compare commits

...

291 Commits

Author SHA1 Message Date
Georgios Kalpakas 19ecdb54bf fix(ngJq): properly detect when ng-jq is empty
Previously, even when `ng-jq` was empty (which should force the use of
jqLite), Angular tried to find jQuery on `window['']`. If it didn't find
anything there, it would fall back to jqLite (as expected).

Nonetheless, trying to access `window['']` calls `getElementById('')`,
which issues a warning in Firefox (maybe others).

This fix properly detects when `ng-jq` is empty and avoids trying to
access `window['']`.

Fixes #12741
2015-09-14 22:43:55 +02:00
Peter Bacon Darwin 30aa3eff4c chore(scripts/publish): get dist-tag from package.json
Closes #12722
2015-09-14 21:29:16 +01:00
Peter Bacon Darwin 8d39bd8abf fix($browser): handle async updates to location
Both browser reloads and iOS 9 bugs cause the window.location to report
a different href that which we have just set. The change does not become
available until the next tick.

This change generalises previous work to deal with reloads to deal with
the iOS 9 bug in the UIWebView component.

Closes #12241
Closes #12819
2015-09-14 21:27:46 +01:00
Matias Niemelä 472d076cca fix(ngAnimateMock): $animate.flush should work for looping animations 2015-09-14 13:02:46 -07:00
Arliang 1ae0be13c2 docs(CHANGELOG): fix typo
Closes #12837
2015-09-14 11:11:25 +03:00
toastman 159efdd429 docs($httpBackend): fix typo/mismatch
There is an mismatch for status in controller and test.
In controller $scope.status = 'ERROR!' and in test we
expect($rootScope.status).toBe('Failed...') so the test will fail;

Closes #12834
2015-09-13 22:18:07 +02:00
Martin Staffa 4755a35b7d test(input): clarify a test's description and expectations
The test ensures that when the trueValue is a string, the required error
is removed, not that the model is set to the trueValue.
2015-09-13 19:23:31 +02:00
Lucas Galfaso b2f8b0b875 fix($parse): throw error when accessing a restricted property indirectly
When accessing an instance thru a computed member and the property is an array,
then also check the string value of the array.

Closes #12833
2015-09-13 16:30:58 +01:00
lucastetreault 24cd70058d refactor(*): use isDefined and isUndefined consistently
Fix any place that compares with `undefined` to use `isUndefined` and `isDefined` instead.

Closes #4365
Closes #12831
2015-09-12 17:17:11 +01:00
indrimuska e46ab43422 docs($interpolate): add missing bracket in first example
Closes #12824
2015-09-11 15:00:15 +03:00
Georgios Kalpakas 8a62a8c7f0 docs(ngInit): fix typo ("unnecesary" --> "unnecessary")
Closes #12810
2015-09-11 14:54:16 +03:00
Georgios Kalpakas b6c2f8b854 docs(CONTRIBUTING.md): mention gitter community
Closes #12782
2015-09-11 14:46:33 +03:00
Martin Staffa 00ee090f4f docs(ngMessageFormat): convert plnkr to internal example
Fixes #12801
2015-09-10 00:12:32 +02:00
Georgios Kalpakas 544001f5a3 fix(input): ignore min/max if they are empty on all input types
When the min/max attributes are empty (i.e. `attrs.min/max === ''`), there
should be no min/max validation applied (i.e. all values should be valid
wrt min/max). This works correctly for `input[number]`, but not for date
input family (`input[date/datetime-local/time/week/month]`).

In the case on `input[number]`, an empty string for `attrs.min/max` is
translated to `undefined` for `minVal/maxVal` and a check for
`isUndefined(minVal/maxVal)` ensures that no min/max validation takes
place.
For the data input family, an empty string for `attrs.min/max` is
translated to `NaN` (by `parseDate()`), so an additional check (for
`isNaN(minVal/maxVal)`) is required.

Fixes #12363

Closes #12785
2015-09-09 15:31:33 +03:00
Peter Bacon Darwin 7175d0d0e3 docs(ngRepeat): make ngInit note a bit clearer
Closes #5623
2015-09-09 13:27:05 +01:00
Peter Bacon Darwin 010d9b6853 docs(ngInit): relaxed the warning notice 2015-09-09 13:15:02 +01:00
Peter Bacon Darwin 122ab074ca fix(angular.copy): support copying XML nodes
Closes #5429
Closes #12786
2015-09-09 13:10:03 +01:00
Peter Bacon Darwin e22bf9ac78 docs(indexPage): update Case Studies link to new site 2015-09-09 11:52:01 +01:00
Akshay Agarwal 324cb6b358 docs(angular.version): fix summary description
Fix summary description of `angular.version`.
The property description is best kept for the detailed page.

Closes #12790
2015-09-08 23:26:53 +03:00
Martin Staffa 80a2176e20 docs($compile): clarify scope types and controllerAs
Closes #12537
Closes #12758
2015-09-08 11:52:01 +01:00
Peter Bacon Darwin 681affef59 style($rootScope): remove trailing whitespace 2015-09-07 22:23:44 +01:00
kwypchlo 0ca8b1df20 fix(toDebugString): change replacement string
As discussed in #10085, the original replacement string can be treated
as html when displayed by the browser so it replaces it with '...' string.

Closes #10103
2015-09-07 22:23:43 +01:00
HeberLZ 20fb626b78 fix(rootScope): add support for watchCollection to watch an object which does not inherit from Object
Closes #9964
2015-09-07 22:08:02 +01:00
HeberLZ 7ea2c7f36e fix(ngRepeat): add support to iterate an object's properties even if it does not inherit from Object
Closes #9964
2015-09-07 22:06:41 +01:00
Bernie Telles 912cbdd468 docs($rootScope): explain why watchExpression should be idempotent
This attempts to clarify the rationale. The previous sentence was a bit ambiguous.

Closes #9963
2015-09-07 21:37:50 +01:00
Jason Bedard 0202663e93 perf(Angular): only create new collection in getBlockNodes if the block has changed
Closes #9899
2015-09-07 21:34:22 +01:00
=Florian Bernstein 159bbf11ac docs($compile): improve documentation on directive $scope usage
Add information about the behavior of several directives, especially of
their scopes when applied on a single element.

Closes #5761
Closes #9727
2015-09-07 21:05:34 +01:00
Peter Bacon Darwin 9d2cc8341c test($http): remove use of deprecated success and error calls in tests 2015-09-07 14:43:33 +01:00
Pawel Kozlowski 38520a1a73 fix($http): propagate status -1 for timed out requests
Fixes #4491
Closes #8756
2015-09-07 14:30:26 +01:00
Izhaki 470eb37d29 docs(guide/directive): clarification on the 'matches' terminology
Closes #8120
2015-09-07 12:19:09 +01:00
Peter Bacon Darwin 4baf25b3ce test(ng-options): add tests for option element with no value attribute
See #6519
2015-09-07 12:01:34 +01:00
Peter Bacon Darwin eb193686a5 test(select): add tests for option element with no value attribute
See #6519
2015-09-07 12:01:33 +01:00
Peter Bacon Darwin 4bebe7830b test(ngOptions): fix typo 2015-09-07 12:01:33 +01:00
Georgios Kalpakas 146cbf7eaa style(ngAria): make JSCS happy again 2015-09-07 12:54:38 +03:00
Marcy Sutton b8e356191f doc(ngAria): update the accessibility guide
Closes #12262
2015-09-07 12:16:36 +03:00
marcysutton f48244ce5e fix(ngAria): clean up tabindex usage
* Do not put tabindex on native controls using ng-model or ng-click
* Uses a single nodeBlacklist to limit which elements receive support

Closes #11500
2015-09-07 12:13:46 +03:00
thorn0 ebba426c0c docs($compile): clarify 'sharing' controllers
The current wording may make the reader erroneously think that one controller
can belong to multiple directives.

Closes #12768
2015-09-06 11:36:52 +03:00
Martin Staffa aa11dfc162 style(formSpec): fix indentation 2015-09-04 11:42:52 +02:00
Martin Staffa c6110e8b08 fix(form, ngModel): correctly notify parent form when children are added
Test that re-added controls propagate validity changes to the parent form.

Ensure that when a form / control that was removed and then attached
to a different parent, is renamed / deleted, the new parent will
be notified of the change.

Document that dynamic adding / removing of controls may require manually
propagating the current state of the control to the parent form.
2015-09-04 11:42:51 +02:00
Martin Staffa 290b5049c2 fix(ngModel): remove reference to parentForm from removed control
This fixes cases where the control gets removed, but the control's
element stays in the DOM.
Previously, if the removed control's validity changed, a reference to
it would again be stored on its former parent form.

Fixes #12263
2015-09-04 11:42:51 +02:00
Martin Staffa f8a07dd9fe refactor(form, ngModel): streamline how controls are added to parent forms
This delegates setting the control's parentForm to the parentForm's
$addControl method. This way, the model controller saves one instance
of looking up the parentForm controller. The form controller keeps two
lookups (one for its own ctrl, one for the optional parent).

This also fixes adding the parentForm in the following case:
- a control is removed from a parent, but its corresponding DOM
element is not destroyed
- the control is then re-added to the form

Before the fix, the control's parentForm was only set once during
controller initialization, so the the parentForm would not be set on
the control in that specific case.
2015-09-04 11:42:51 +02:00
Georgios Kalpakas 6f39f10827 fix($httpBackend): send null when post-data is undefined
IE11 (and maybe others) converts an `undefined` argument to `xhr.send()` to
string (`'undefined'`) for certain request methods (e.g. DELETE). This
causes the request to appear having a body, when it shouldn't.

Fixes #12141
Fixes #12739

Closes
2015-09-03 14:08:16 +03:00
Peter Bacon Darwin c3a654b7c8 fix($animate): invalid CSS class names should not break subsequent elements
The postDigest handler was not being added if the first element in
to modify the CSS classes contained invalid CSS class names. This meant
that subsequent valid CSS class changes were not being handled since we
were not then adding the handler for those correct cases.

Closes #12674
Closes #12725
2015-09-02 12:45:11 +01:00
Peter Bacon Darwin e7293daf2a refactor($animate): move CSS class update functions out of closure 2015-09-02 12:34:08 +01:00
Mike c71d414a95 docs(doc_widgets.css): remove dead link
This removes a dead link (https://bitbucket.org/alexg/syntaxhighlighter/issues/177/superfluous-vertical-scrollbars-in-chrome)
which linked to an issue on Bitbucket that no longer exists due to
the project moving to GitHub.

Closes #12710
2015-09-01 23:45:46 +02:00
Martin Staffa 06d4e18cda docs(faq): clarify browser support
Closes #12728
2015-09-01 23:37:00 +02:00
Tim Whitbeck 966e01cf26 docs(input): mention ngMin and ngMax for all date input types
Closes #11636
Closes #12244
2015-09-01 23:29:40 +02:00
Lucas Galfaso 67afd9dc63 docs(CHANGELOG): Add breaking change notice for issue 12506
Closes #12705
2015-09-01 22:14:38 +02:00
Martin Staffa 4175860af1 docs(ngModel): improve the $setViewValue documentation
- reorder the paragraphs to highlight more important info
- clarify what can / should be passed to the method,
and what to (not) expect from it
- clarify when the method will trigger a digest

Closes #12713
Closes #11121
Closes #12498
2015-09-01 19:38:11 +02:00
Martin Staffa 6fb90bda9a docs(guide/Directives): clarify what compile means
Closes #11908
2015-09-01 18:06:23 +02:00
Nabil Kadimi 770dd2dcfd docs(misc/Downloading): use the latest stable
Closes #12534
2015-09-01 17:59:21 +02:00
Martin Staffa 0ff7bba2e3 test(select): clean up and improve the option directive tests
- add tests to ensure options with interpolated text are added / updated
- refactor tests for interpolated option values to use the
standard compile helper defined in the spec file.
- rephrase some test descriptions for clarity

Closes #12580
2015-08-31 23:54:13 +02:00
Martin Staffa 82b0929e4e fix(select): update option if interpolated value attribute changes
This is for options added without ngOptions.
Previously, an option with an interpolated value attribute would
not be updated if the binding changed, i.e. the select controller would
not recognize the changed option. Now the value attribute will
be observed if it contains an interpolation.

Closes #12005
Closes #12582
2015-08-31 23:18:19 +02:00
Lucas Galfaso 7d2c6eeef8 fix($parse): assign returns the new value
The `.assign` function returns the new value.
The version with csp enabled already has this behavior.

Closes #12675
Closes #12708
2015-08-31 22:40:23 +02:00
Ron Fenolio 6d8c1950a0 style(guide/Conceptual Overview): clean up conceptual table overview.
Clean up the conceptual overview table to make it cleaner and easier
to look at.

Closes #12620
2015-08-31 21:55:56 +02:00
Rex Salisbury 1a5ea22079 docs(guide/Forms): replace form with user
Referring to the `user` as `form` in the previews is confusing,
since it makes it seem as though the data being displayed is attached
to the `form` object, when the `form` object is separate.

Closes #12687
2015-08-31 21:15:01 +02:00
Joakim Blomskøld 4f9eb2c6e4 docs(form): add info about pending prop and class
Closes #12704
2015-08-31 21:11:03 +02:00
Martin Staffa 43769fb676 fix(ngModel): let aliased validator directives work on any element
`ng(Pattern|Minlength|Maxlength)` directives will now validate the
`ngModel` when on an element that is not an `input` or
a `textarea`. Previously, only their HTML5 counterparts worked on
every element.

This is because the three validators were extracted
into  separate directives (see 26d91b653a
and 1be9bb9d35), whereas the aliased
attribute handling assumes the validators will only exist on
`input|textarea` (see d9b90d7c10 and
25541c1f87).

Since `ngMin` and `ngMax` are also aliased attributes, this means
observers of `min` and `max` will be fired if `ngMin` and `ngMax`
change. This will happen on any element, even if it does not have
an `ngModel`. However, since min/max validators are only ever added
as part of the `input[number|textarea]` types, even if the element
has an `ngModel`, no validators will be added.

Finally the commit also tests that `ng-required` works on any element,
although that validator worked on all elements before this fix.

Fixes #12158
Closes #12658
2015-08-31 20:52:06 +02:00
Ziyu Wang 170cd96646 fix(docs): fix typo "Hasbang"
Closes #12712
2015-08-31 10:27:13 +02:00
Matias Niemelä 1d18e60ef7 docs(CHANGELOG): add changes for 1.4.5 2015-08-28 12:06:35 -07:00
Matias Niemelä ea8016c4c8 fix(ngAnimate): use requestAnimationFrame to space out child animations
This reverts the previous behaviour of using foreced reflows to deal
with preparation classes in favour of a system that uses
requestAnimationFrame (RAF).

Closes #12669
Closes #12594
Closes #12655
Closes #12631
Closes #12612
Closes #12187
2015-08-27 16:56:18 -07:00
Matias Niemelä c3d5e33e18 fix($animate): $animate.enabled(false) should disable animations on $animateCss as well
Closes #12696
Closes #12685
2015-08-27 16:29:33 -07:00
Matias Niemelä 2f6b6fb7a1 fix($animateCss): do not throw errors when a closing timeout is fired on a removed element
Closes #12650
2015-08-27 14:07:59 -07:00
Lucas Galfaso ea2518fcea test($parse): fix csp setup
Run the parse interpreter for csp enabled tests
2015-08-26 23:24:02 +02:00
grsmvg 7e67e525a5 docs(jqLite): document unsupported event object as parameter in off()/unbind()
Closes #12291
2015-08-25 15:34:19 +03:00
Martin Staffa 0e001084ff fix(ngModel): validate pattern against the viewValue
Since the HTML5 pattern validation constraint validates the input value,
we should also validate against the viewValue. While this worked in
core up to Angular 1.2, in 1.3, we changed not only validation,
but the way `input[date]` and `input[number]` are handled - they parse
their input values into `Date` and `Number` respectively, which cannot
be validated by a regex.

Fixes #12344

BREAKING CHANGE:

The `ngPattern` and `pattern` directives will validate the regex
against the `viewValue` of `ngModel`, i.e. the value of the model
before the $parsers are applied. Previously, the modelValue
(the result of the $parsers) was validated.

This fixes issues where `input[date]` and `input[number]` cannot
be validated because the viewValue string is parsed into
`Date` and `Number` respectively (starting with Angular 1.3).
It also brings the directives in line with HTML5 constraint
validation, which validates against the input value.

This change is unlikely to cause applications to fail, because even
in Angular 1.2, the value that was validated by pattern could have
been manipulated by the $parsers, as all validation was done
inside this pipeline.

If you rely on the pattern being validated against the modelValue,
you must create your own validator directive that overwrites
the built-in pattern validator:

```
.directive('patternModelOverwrite', function patternModelOverwriteDirective() {
  return {
    restrict: 'A',
    require: '?ngModel',
    priority: 1,
    compile: function() {
      var regexp, patternExp;

      return {
        pre: function(scope, elm, attr, ctrl) {
          if (!ctrl) return;

          attr.$observe('pattern', function(regex) {
            /**
             * The built-in directive will call our overwritten validator
             * (see below). We just need to update the regex.
             * The preLink fn guaranetees our observer is called first.
             */
            if (isString(regex) && regex.length > 0) {
              regex = new RegExp('^' + regex + '$');
            }

            if (regex && !regex.test) {
              //The built-in validator will throw at this point
              return;
            }

            regexp = regex || undefined;
          });

        },
        post: function(scope, elm, attr, ctrl) {
          if (!ctrl) return;

          regexp, patternExp = attr.ngPattern || attr.pattern;

          //The postLink fn guarantees we overwrite the built-in pattern validator
          ctrl.$validators.pattern = function(value) {
            return ctrl.$isEmpty(value) ||
              isUndefined(regexp) ||
              regexp.test(value);
          };
        }
      };
    }
  };
});
```
2015-08-24 17:01:20 +02:00
Peter Bacon Darwin 85e3203918 chore(npm-shrinkwrap): update to dgeni-packages 0.10.19
See https://github.com/angular/dgeni-packages/commit/313a7c3832
2015-08-23 21:40:11 -04:00
Martin Staffa f95bc42cee docs(ngAnimate): fix typo
Closes #12521
2015-08-21 12:30:02 +02:00
Martin Staffa 9080d2c53c doc(ngMock.$controller): correct controller name in bindToController example
Closes #12550
2015-08-21 11:35:10 +02:00
Matias Niemelä 728f7e2a85 docs(ngAnimate): staggering example should contain duration:0s property
As of 1.4.4 this property needs to always be in the CSS code

Related #12594
Closes #12637
2015-08-20 20:54:31 +02:00
Matias Niemelä 5f704065a7 docs(ngShow): simplify the CSS transition code
The animation example contains unnecessarily complex CSS animation
code in it and the conventions are off.

Related #12631
2015-08-20 20:47:56 +02:00
Matias Niemelä 64631bf2e6 docs(ngAnimate): remove -webkit-transition properties
This property is no longer mandatory by browsers.
2015-08-20 20:47:55 +02:00
Karl Svartholm aa35b243f8 docs(ngAnimate): remove extraneous "then"
To improve readability

Closes #12634
2015-08-20 20:44:42 +02:00
Gabriel Monteagudo 1cc9c9ca9d fix($animateCss): fix parse errors on older Android WebViews
Errors are caused by reserved keywords 'finally' and 'catch'

Closes #12610
2015-08-20 20:39:41 +02:00
Matias Niemelä dc48aadd26 fix(ngAnimate): only buffer rAF requests within the animation runners
Closes #12280
2015-08-19 10:40:37 -07:00
Matias Niemelä ebce2f7253 revert: fix(core): ensure that multiple requests to requestAnimationFrame are buffered 2015-08-19 10:39:47 -07:00
Matias Niemelä d0e50fdcd0 docs(CHANGELOG): add changes for 1.3.18 2015-08-19 01:10:06 -07:00
Matias Niemelä d88167318d fix($animateCss): properly handle cancellation timeouts for follow-up animations
Prior to this fix if `$animateCss` was called multiple on the same
element with new animation data then the preceeding fallback timout
would cause the animation to cancel midway. This fix ensures that
`$animateCss` can be triggered multiple times and only when the final
timeout has passed then all animations will be closed.

Closes #12490
Closes #12359
2015-08-17 21:02:39 -07:00
Sreenivasan K 0a75a3db6e fix($animateCss): ensure failed animations clear the internal cache
Closes #12214
Closes #12518
Closes #12381
2015-08-17 16:06:25 -07:00
Lucas Galfaso b643f0d322 fix(ngResources): support IPv6 URLs
Do not confuse IPv6 URLs domains and resource parameters.

Closes #12512
Closes #12532
2015-08-16 12:36:56 +02:00
Martin Staffa 01dd588a28 docs(select): tweak description and add examples
- Change some wordings to make them more understandable
- Reorder the paragraphs so they can be read more easily as a coherent text
- Add examples for static single / multiple selects, and non-selected option
- Add example for select with repeated options
- Remove form-related info from ngOptions select (doesn't apply)
2015-08-15 18:32:50 +02:00
Meli 3d6dc3fe31 docs(select): explain how to set default value
Setting the default value in a select is a real trap for beginners, questions about how to do this on StackExchange have been view more than 40000 times in the last year.  This changes updates the documentation to make it clearer.

Closes #12546
2015-08-15 18:32:49 +02:00
Matias Niemelä 0c81e9fd25 fix($animateCss): the transitions options delay value should be applied before class application
When `options.delay` is passed into `$animateCss`the delay style would be
applied after the add/remove CSS classes are evaluated (for transitions).
At this point it is too late for the delay to be picked up (this
functionality however does work with keyfarme animations).

This patch ensures that the provided `options.delay` value is
applied before the CSS classes are applied to the element.

Closes #12584
2015-08-14 13:58:38 -07:00
Elvio Cavalcante 5df80e1854 docs(tutorial): fix test issue
Unnecessary split. The url returns a string without the hash,
resulting in an undefined value and making the test fails.

Matches the phonecat app more closely, too.

Closes #12590
2015-08-14 15:12:39 -04:00
David Czech ba9fb82f18 docs($animate): remove redundant 'animate' in link
Closes #12568
2015-08-14 12:08:32 +02:00
Martin Staffa b497f3e47f docs(CHANGELOG): add changes for 1.4.4 2015-08-13 11:15:10 -07:00
Matias Niemelä 39b634e50a feat(ngAnimate): expose a core version of $animateCss
A core version of `$animateCss` can now be injected when
ngAnimate is not present. This core version doesn't trigger any
animations in any way. All that it does is apply the provided from
and/or to styles as well as the addClass and removeClass values.

The motivation for this feature is to allow for directives to activate
animations automatically when ngAnimate is included without the need to
use `$animate`.

Closes #12509
Closes #12570
2015-08-13 10:49:59 -07:00
Matias Niemelä cf28c1a276 chore: rename angular.bind to angular.bind.js
Some internal tests were failing since `.bind` is a JS file which
is expected to have a `.js` file name suffix.
2015-08-12 13:11:48 -07:00
sreeramu 92e41ac904 fix($animate): leave animation callback should not overridden by follow-up animation
Closes #12271
Closes #12249
Closes #12161
2015-08-12 11:59:54 -07:00
Matias Niemelä d33cedda16 fix(ngAnimate): always apply a preparation reflow for CSS-based animations
It's unpredictable sometimes to ensure that a browser triggers a reflow
for an animation. Prior to this patch, reflows would be applied
carefully in between parent/child DOM structure, but that doesn't seem
to be enough for animations that contain complex CSS styling rules.

Closes #12553
Closes #12554
Closes #12267
Closes #12554
2015-08-12 10:20:18 +02:00
Lucas Galfaso 6838c97945 perf($q): small $q performance optimization
Only generate a new promise when `then` receives some non-undefined parameter

Closes #12535
2015-08-11 23:37:46 +02:00
Ilya Mochalov f827a8e050 docs($interval): cancel() ignores falsy parameter
Closes #12552
2015-08-11 16:57:01 -04:00
Luke Waite a844138060 docs($sce): correct typo
Fix markdown quotation of a `;` so that it is properly rendered in the docs.
Makes it more consistent with the other codeblocked characters in the
list.

Closes #12549
2015-08-11 10:50:21 -04:00
Caitlin Potter 8ae9e94ecb style(loader): make jscs happy 2015-08-11 10:43:49 -04:00
Frank 1bd451d082 docs(angular.module): simplify wording+improve grammar
A suggestion on the wording of retrieving a moudle

Closes #12543
2015-08-11 10:42:44 -04:00
arm1n c11a7d676f fix(ngOptions): allow empty option selection with multiple attribute
Fixes #12511
Closes #12541
2015-08-10 22:13:48 +02:00
Lucas Galfaso 0827e88e21 style(jscs): fix whitespace 2015-08-09 13:03:48 +02:00
Lucas Galfaso 1363cbd6b4 style(jshint): fix jshint warning 2015-08-09 12:40:28 +02:00
Lucas Galfaso 44a96a4c14 fix($injector): Allows ES6 function syntax
Closes #12424
Closes #12425
2015-08-09 12:20:31 +02:00
Lucas Galfaso 1cf10ab810 chore(saucelabs): Upgrade Chrome and Firefox to the latest versions
Closes #12430
2015-08-09 12:19:38 +02:00
Lucas Galfaso ed3a33a063 feat(orderBy): Stable sort the input
Stable sort the input array

Closes #12408
Fixes #12405
2015-08-08 22:33:53 +02:00
Martin Staffa a268c29fb0 fix(ngModel): correct minErr usage for correct doc creation
Remove the `new` from the minErr assignment, so the closure compiler
can detect the errors correctly. Also removes the leading $ from the
variable name to be consistent with the Angular.js file.

Closes #12386
Closes #12416
2015-08-08 17:57:23 +02:00
Martin Staffa adb286389c docs(form): explain why the empty-string setter is created 2015-08-07 19:28:11 +02:00
Lucas Galfaso 94533e5706 refactor(form): remove the use of the private setter function
Remove the private `setter` function from $parse
Replace the `setter` from the `form` directive with $parse

Closes #12483
2015-08-07 14:47:09 +02:00
Rouven Weßling 99d2c46a16 refactor(): remove more bits and pieces related to Internet Explorer 8
Closes #12407
2015-08-07 14:29:55 +02:00
Yun Liu 929ec6ba5a style($http): fix typo in useLegacyPromise var
Closes #12515
2015-08-07 14:13:25 +02:00
luanshixia 39ff3332a3 fix(ngSanitize): escape the wide char quote marks in a regex in linky.js
Escape the wide char quote marks in a regex in linky.js

Closes #11609
2015-08-06 23:09:22 +02:00
Ryan Hendry 4c92a3ccc7 style(ngAnimate): add missing semi-colon
Adding missing semi-colon which is breaking minification

Closes #12513
2015-08-06 22:30:18 +02:00
Steve Mao dc0b856e9c docs(CONTRIBUTING): correct spelling and grammar
Summary:
  - Use properly capitalized GitHub brand name
  - Correctly negate two clauses using "nor" (caitp feels this may confuse
non-english speakers and need to be revised, but hopefully not)
  - Correctly end sentence with period

Closes #12497
2015-08-04 09:24:03 -04:00
Martin Staffa bb281f85e7 docs(.Scope): correct link to scope guide 2015-08-03 22:09:45 +02:00
Martin Staffa 496e08a605 docs($rootScope.Scope): remove obsolete line, and link to guide
The removed line pointed to a removed example. Re-adding the example
would have been of questionable value, as it introduced several
concepts without context. It's therefore better to link to the guide,
which provides a better introduction.

Closes #12167
2015-08-03 21:55:40 +02:00
Eric Adams 548a1348d9 docs(guide/Dependency Injection): fix angular.injector arguments list
The original file included a code sample using `angular.injector(['myModule', 'ng'])`,
which appears to be incorrect when trying to retrieve anything attached to `myModule`.
Reversing the args fixes this.

Closes #12292
2015-08-03 21:07:48 +02:00
Derk Vedelaar 9845570be8 docs(tutorial/7 - Routing): update angular version
The versions are updated in the angular-phonecat repo, but not in
the documentation. This change syncs the version numbers.

Closes #12396
2015-08-03 21:02:53 +02:00
Satish Maurya 35d35e6a7e docs(guide/Forms): display scope form / master data in examples
It will be good to have the binding results in the CSS classes /
binding to form / control state example, similar to the Simple Form
example.

Closes #12326
2015-08-03 20:56:25 +02:00
Martin Probst 5abf593e6b fix(injector): check that modulesToLoad isArray.
When users accidentally just pass a single string, e.g.
`angular.injector('myModule')`, this change give them a better error message.

Currently Angular just reports that the module with the name 'm' is missing,
as it's iterating through all characters in the string, instead of all strings
in the module.

Closes #12285
2015-08-03 10:18:19 +02:00
ArchmageInc 9efe60f294 docs($q): add $q.when and $q.resolve callback arguments
Closes #12372
2015-08-03 10:13:37 +02:00
Jacob Carter 8553b56e97 docs(ngOptions): close select element
Close select element in html example to stop errors occurring for copy/paste users

Closes #12384
2015-08-03 10:12:12 +02:00
Rouven Weßling a8f7e9cfde feat($httpProvider): add 'useLegacyPromiseExtensions' configuration
The legacy methods, `success` and `error`, have been deprecated.

Set this to `false` to cause `$http` to throw an error if these methods are
used in the application.

For now it defaults to `true`. In a future release we will remove these
methods altogether.

DEPRECATION NOTICE:

The legacy methods 'success' and 'error' on promises returned by $http
are now deprecated.

Closes #12112
Closes #10508
2015-08-01 20:34:30 +01:00
Lucas Galfaso 7b8a16b238 refactor($locale): use en-us as generic built-in locale
Previously there was a custom built en-us locale that was included with
angular.js. This made likely that it would get out of sync with the real
en-us locale that is generated from the closure library.

This change removes that custom one and uses the generated one instead.
This also has the benefit of preventing the unwanted caught error on trying
to load `ngLocale` during angular bootstrap.

Closes #12462
Closes #12444
Closes #12134
Closes #8174
2015-07-31 22:07:27 +02:00
Steven d2695b04a7 docs(guide): Facebook was mispelled as Faceb0ok
Fixes typo :>

Closes #12470
2015-07-30 19:45:39 -04:00
Peter Bacon Darwin 6f3b8622ad fix($compile): don't trigger $observer if initial value is undefined
Closes #12383
Closes #12464
2015-07-30 23:23:08 +01:00
Strikeskids 97ac7634df docs($rootScope.Scope): improve clarity describing $watch with no listener
The previous explanation in parentheses created a bit of confusion because the documentation stated to leave off the `listener`, but then said "be prepared for multiple calls to your listener". The new explanation clarifies that it is indeed the `watchExpression` that will be executed multiple times.

Closes #12429
2015-07-30 15:22:40 -04:00
Laisky.Cai ef3846a7a6 docs(guide/expression): replace tt by code
Replaces <tt> elements with <code> in expressions guide. Looks identical
in Chromium

Closes #12437
2015-07-30 12:50:34 -04:00
patyatka 93985804a9 docs($compile): fix typo
Closes #12443
2015-07-30 12:32:42 -04:00
Caitlin Potter 533d9b7670 fix($compile): ignore optional =-bound properties with empty value
Previously, optional empty '='-bound expressions were ignored ---
erroneously they stopped being ignored, and no tests were caused to
fail for this reason. This change restores the original ignoring
behaviour while still preventing other errors fixed by 8a1eb16

Closes #12144
Closes #12259
Closes #12290
2015-07-29 16:58:18 +01:00
Matias Niemelä 0d6fc2dce5 fix(ngAnimate): ensure that only string-based addClass/removeClass values are applied
Related #11268
Closes #12458
Closes #12459
2015-07-29 14:07:10 +01:00
Peter Bacon Darwin addb1ae37d test(guide/expression): we must tell protractor to wait for the alert appear
This is a better solution than f91eb0e9ec
2015-07-28 14:41:01 +01:00
Jochen Niebuhr f13852c179 fix(Angular): allow unescaped = signs in values in parseKeyValue
In some cases people will not follow all URL standards and may have
unescaped = characters in their GET parameter values. Currently $location
will not parse them correctly dropping everything after the unescaped =.

This change includes all characters after the first `=` up to the next `&`.

Closes #12351
2015-07-27 22:30:28 +01:00
Peter Bacon Darwin 5298672411 fix(ng/$locale): by default put negative sign before currency symbol
It seems that the case where the negative sign goes between the currency
symbol and the numeric value is actually the special case and that locales
that require this have it built in. So we should default to having the
negative sign before the symbol.

See http://cldr.unicode.org/translation/number-patterns and
http://unicode.org/cldr/trac/ticket/5674

Closes #10158
2015-07-27 22:21:28 +01:00
Peter Bacon Darwin 058d462fa7 revert: refactor($locale): use en-us as generic built-in locale
This reverts commit 70ce425e6a.

There are internal projects in Google that generate their own version
of angular.js and so this commit caused those projects to break.

We are going to look into a more satisfactory way of getting this change
in.
2015-07-27 22:00:14 +01:00
Peter Bacon Darwin f91eb0e9ec test(expression): add sleep(100) to protractor spec that uses alert
In Chrome, if two alert boxes pop up, without enough time between them,
Protractor (or possibly ChromeDriver) sometimes fails to recognize the
second alert.
2015-07-27 21:53:14 +01:00
Matias Niemelä 861636c625 fix($animate): make sure to run a post-digest reflow for parentless animations
Closes #12400
Closes #12401
2015-07-27 16:21:50 -04:00
Lucas Galfaso e7423168fb fix(input): Firefox validation trigger
Do not trigger Firefox validation on form initialization.
- Do not set a value to an <input> field if the field already has the same value

Closes #12102
2015-07-26 19:40:05 +02:00
Martin Staffa 4bcf6c17c8 docs(ngOptions): remove obsolete trkslct error page
Closes #12417
2015-07-26 19:35:56 +02:00
Blake Johnston d506b8a9df docs($compile): pluralize DOM element
Previous description includes singular `collection of DOM element`. Current change revises `element` to be plural.

Closes #12431
2015-07-26 19:34:14 +02:00
Lucas Galfaso e0cf496f3c fix($rootScope): don't clear phase if $apply is re-entered
We cannot re-enter a `$apply` block while already in a `$apply` or `$digest`
phase.

Before this change such an invalid call to `$apply` was incorrectly clearing
the phase, which meant that a second invalid `$apply` call was being allowed.

Closes #12174
2015-07-25 20:44:08 +01:00
Sreenivasan K a5221f320a fix(merge): regExp should not be treated as a objects when merging.
angular.merge({ key: /regexp/ }) now works the way you'd expect it to.

Horray!

Closes #12419
Closes #12409
2015-07-24 09:00:31 -04:00
Lucas Galfaso 18a2e4fbfc fix(httpParamSerializerJQLike): Follow jQuery for index of arrays of objects
Follow jQuery when serializing arrays that contain objects

Close #12393
Close #12398
2015-07-23 23:05:20 +02:00
Matias Niemelä 32d3cbb3aa fix(ngAnimate): ensure that parent class-based animations are never closed by their children
This fix ensures that a structural child animation will never close a
parent class based early so that the CSS classes for the child are ready
for it to perform its CSS animation. The reasoning for the past for this
was because their is a one frame delay before the classes were applied.
If a parent and a child animation happen at the same time then the
animations may not be picked up for the element since the CSS classes
may not have been applied yet.

This fix ensures that parent CSS classes are applied in a synchronous
manner without the need to run a one RAF wait. The solution to this was
to apply the preparation classes during the pre-digest phase and then
apply the CSS classes right after with a forced reflow paint.

BREAKING CHANGE: CSS classes added/removed by ngAnimate are now applied
synchronously once the first digest has passed.

The previous behavior involved ngAnimate having to wait for one
requestAnimationFrame before CSS classes were added/removed. The CSS classes
are now applied directly after the first digest that is triggered after
`$animate.addClass`, `$animate.removeClass` or `$animate.setClass` is
called. If any of your code relies on waiting for one frame before
checking for CSS classes on the element then please change this
behavior. If a parent class-based animation, however, is run through a
JavaScript animation which triggers an animation for `beforeAddClass`
and/or `beforeRemoveClass` then the CSS classes will not be applied
in time for the children (and the parent class-based animation will not
be cancelled by any child animations).

Closes #11975
Closes #12276
2015-07-20 14:21:59 -07:00
Matias Niemelä acc53ce6ad revert: fix(ngAnimate): ensure nested class-based animations are spaced out with a RAF 2015-07-20 14:21:53 -07:00
Matias Niemelä 0f6d37ead5 chore(ngAnimate): skip adding the preparation classes when options.$$skipPreparationClasses is present 2015-07-20 14:21:43 -07:00
Matias Niemelä 11695ca6e2 fix($animateCss): make sure that skipBlocking avoids the pre-emptive transition-delay styling 2015-07-20 14:21:35 -07:00
ColinFletch cce084ee89 docs(guide/Controllers): Syntax adjustments.
Closes #12379
2015-07-19 17:39:53 +02:00
Jesse Mandel d935c245c0 docs(guide/module): fixed link to blog post
Closes #12165
Closes #12250
2015-07-19 16:41:55 +02:00
Matthew Hill b871b98a57 docs(filter.js): documents second parameter to .register
Closes #12378
2015-07-19 14:49:30 +02:00
Lucas Galfaso 1cb6bd4944 chore(angularFiles.js): Remove deleted file 2015-07-18 12:04:03 +02:00
bluepnume 3abb3fefe6 fix($q): Use extend to avoid overwriting prototype
Use `extend` on `Promise.prototype` and `Deferred.prototype`, to avoid having to
manually set `constructor` on the overwritten prototypes.

Closes #10697
2015-07-18 11:42:42 +02:00
Lucas Galfaso 8ed682941a chore(asyncCallback): Remove dead code
Closes #12371
2015-07-18 11:13:23 +02:00
Olen Davis 44ce9c8288 fix(ngAnimate): allow animations on body and root elements
Closes #11956
Closes #12245
2015-07-17 11:30:06 -07:00
Matias Niemelä 2ff1b09ab7 chore: replace jqLite($document[0].body) with $$body 2015-07-17 11:29:54 -07:00
Matias Niemelä 976cd036da chore(core): introduce $$body service
This patch makes it easier to gain access to document.body
via the injector.
2015-07-17 11:29:48 -07:00
sreeramu 21d6db382d fix($animate): ensure that class-based animations are properly applied when cancelled
Instead of merging existing animation option to new animation options we can
merge in reverse and utilize old animation runner.

Closes #12266
Closes #12007
2015-07-17 11:24:31 -07:00
Matias Niemelä fc7d2d2737 chore($$forceReflow): create service for issuing reflows in animations 2015-07-17 09:42:47 -07:00
Matias Niemelä c77b607e61 chore(mocks): remove $$animateReflow from triggerReflow()
This service was removed when 1.4.0 was released, but the mock
code still stubs it.
2015-07-17 09:42:47 -07:00
jbnizet ec22d2276e docs(CHANGELOG): fix release date of 1.4.3 version
Closes #12356
2015-07-17 10:44:03 +03:00
Matias Niemelä 344dffbc54 docs($animateCss): add missing options flag to animation example
Closes #12202
2015-07-16 14:33:57 -07:00
startswithaj 7db5f361b0 fix(ngAnimate): $timeout without invokeApply
This change calls $timeout with the invokeApply
parameter set to false which stops ngAnimate
from invoking its changes inside an $apply block

Closes #12281
Closes #12282
2015-07-16 14:29:40 -07:00
shoja d494a69ef6 docs($sce): correct typos
Line 548: Remove duplicate 'not' and clarify wording
Line 556: Remove period within parenthetical statement
Line 560: Clarify wording
Line 570: Capitalize 'E.g.' at the start of a sentence

Closes #12252
2015-07-16 22:28:32 +02:00
Ashish Dasnurkar 91212d9440 docs($cookiesProvider): fixed a typo
"This is *import* so that cookies will be visible" should be "This is *important* so that cookies will be visible"

Closes #12264
2015-07-16 22:27:02 +02:00
Nabil Kadimi b661887072 docs(guide/Dependency Injection): minor punctuation fixes
Closes #12268
2015-07-16 22:25:18 +02:00
Mohamed Samy 60b7b003fd docs(tutorial/7 - Routing): fix matching in test
It is corrected in github, but not in the angular.org site.
Copied it from https://github.com/angular/angular-phonecat/compare/step-6...step-7

Closes #12314
2015-07-16 22:20:01 +02:00
Andrew Passanisi 6ba5404406 docs(error/ctrlfmt): fixed a small typo in ctrl error message
Closes #12320
2015-07-16 22:18:08 +02:00
Peter Bacon Darwin 2b68136a20 chore(ngLocale): regenerate locales
This regeneration takes into account the changes due to:

* update to closure library 27.0.1
* fix to default position of negative sign in currency formats

Closes #12307
Closes #12362
2015-07-16 19:20:11 +01:00
Peter Bacon Darwin dc49b4d952 chore(i18n): update closure library 2015-07-16 19:20:11 +01:00
Peter Bacon Darwin 96f2e3bef5 fix(i18n): by default put negative sign before currency symbol
It seems that the case where the negative sign goes between the currency
symbol and the numeric value is actually the special case and that locales
that require this have it built in. So we should default to having the
negative sign before the symbol.

See http://cldr.unicode.org/translation/number-patterns and
http://unicode.org/cldr/trac/ticket/5674

Closes #10158
2015-07-16 19:20:11 +01:00
Peter Bacon Darwin 70ce425e6a refactor($locale): use en-us as generic built-in locale
Previously there was a custom built en-us locale that was included with
angular.js. This made likely that it would get out of sync with the real
en-us locale that is generated from the closure library.

This change removes that custom one and uses the generated one instead.
This also has the benefit of preventing the unwanted caught error on trying
to load `ngLocale` during angular bootstrap.

Closes #12134
Closes #8174
2015-07-16 19:19:39 +01:00
Peter Bacon Darwin 9e492c358c fix($location): don't crash if navigating outside the app base
Previously, if you navigate outside of the Angular application, say be clicking
the back button, the $location service would try to handle the url change
and error due to the URL not being valid for the application.

This fixes that issue by ensuring that a reload happens when you navigate
to a URL that is not within the application.

Closes #11667
2015-07-16 18:46:13 +01:00
Peter Bacon Darwin 92c7ce5bec refactor($location): compute appBaseNoFile only once 2015-07-16 18:46:13 +01:00
Peter Bacon Darwin 618356e481 fix(ngCsp): allow CSP to be configurable
There are two different features in Angular that can break CSP rules:
use of `eval` to execute a string as JavaScript and dynamic injection of
CSS style rules into the DOM.

This change allows us to configure which of these features should be turned
off to allow a more fine grained set of CSP rules to be supported.

Closes #11933
Closes #8459
Closes #12346
2015-07-16 12:26:24 +01:00
Peter Bacon Darwin 1f4aa47193 docs(migration): clarify non-numeric matching
Closes #12350
2015-07-15 13:52:56 +01:00
Peter Bacon Darwin 528cedaa0c docs(CHANGELOG): Remove redundant items from 1.4.3 changes
The update to the change log for the 1.4.3 release accidentally included
a number of changes from previous releases.
2015-07-15 12:34:46 +01:00
Matias Niemelä 1622182737 docs(CHANGELOG): add changes for 1.4.3 2015-07-14 18:26:10 -07:00
Matias Niemelä 36efe6c1a2 test($animateCss): avoid unnecessary checking for transition-timing-function
There is no need to check for this in the test and it adds complexity
for linux-based browsers.
2015-07-14 14:07:50 -07:00
Matias Niemelä 5081982e30 test($animateCss): ensure that transitionStyle by itself doesn't trigger anything
Using `transitionStyle` without any other properties does not trigger an
animation so we could have a test to assert that it doesn't do that.
2015-07-14 13:45:11 -07:00
Matias Niemelä 97d79eec80 fix($animateCss): ensure animations execute if only a keyframeStyle is provided
`$animateCss` is a fan of transition animations, but it turns out that
if only a keyframeStyle is provided into the animation upon constrution
then it will quit because it assumes that nothing will be animated
(since no classes or styles are being applied). This patch ensures that
a keyframe style can solely be applied to an animation triggered with
`$animateCss`.

```js
// this will now work as expected
$animateCss(element, { keyframeStyle: '1s rotate' }).start();
```

Closes #12124
Closes #12340
2015-07-14 13:45:03 -07:00
Matias Niemelä e4aeae0c73 fix(ngAnimate): ensure that orphaned elements do not throw errors when animated
This fix ensures that both `$animateCss` and `$animate` swallow the error
when an animation takes place in the sitation that the element is removed
from the parent element sometime before or during the preparation stages of the
animation.

Closes #11975
Closes #12338
2015-07-14 21:06:55 +01:00
Dominic Watson 7202bfafcd docs(ngAnimate) - Correct keyframe to keyframeStyle 2015-07-14 10:42:05 -07:00
Steve Mao 4cef752985 docs(CONTRIBUTING): state what is mandatory or optional
Closes #12032
2015-07-13 13:24:52 +01:00
Steve Mao d38f6ff401 docs(CONTRIBUTING): how to write a breaking change
Closes #12032
2015-07-13 13:24:44 +01:00
Steve Mao 8f6dac9536 docs(CONTRIBUTING): revert is a modifier
EG: https://github.com/angular/angular.js/commit/462f444b06ae5cad3ccb761b1dba7131df01a655

Closes #12032
2015-07-13 13:24:34 +01:00
Peter Bacon Darwin de5b8dc781 docs(guide/controller): add a line about controller as 2015-07-13 13:22:01 +01:00
Peter Bacon Darwin 41834e6f4a docs(guide/controller): add a line about controller as 2015-07-13 13:18:29 +01:00
niteshthakur dbb42b5c85 docs(guide/controller): clarify that controllers are defined **by** a constructor function
A controller is a instantiated object created **from** a constructor function.
It was not accurate to describe a Controller **as** a constructor function.

Closes #11888
2015-07-13 13:18:29 +01:00
Peter Bacon Darwin f012374f12 docs($routeChangeSuccess): note that resolve values are available on current route
Closes #11413
2015-07-13 13:10:47 +01:00
Rouven Weßling 14e0b9c352 refactor(ngCsp): use document.head
The `head` property is available from IE9 onwards.

Closes #11905
2015-07-13 09:37:03 +01:00
Jerry Orta 9ea52d818b fix(loader): define isFunction
Closes: #12299
Closes: #12287
2015-07-10 22:54:58 +02:00
Martin Staffa d518a64d93 docs(CHANGELOG): add changes for 1.4.2 2015-07-06 22:19:53 +02:00
Wesley Cho fe0af2c073 chore(animate): remove dead code
- Remove unused `$$asyncCallback`

Fixes #12251
Closes #12254
2015-07-02 22:57:00 +02:00
marcysutton 1f5e42e882 feat(ngAria): add option to disable role=button
Closes #11580
Closes #12234
2015-07-02 14:36:49 +03:00
Jeff Cross d193c3a25c revert: "fix($compile): do not write @-bound properties if attribute is not present"
This reverts commit 8a1eb1625c.

This commit broke the tabs component on the material project,
which caused internal breakages. Will open a separate issue to
look into the issue.
2015-07-01 22:12:03 -07:00
Raphael Jamet 4da1cc3b81 refactor($templateRequest): Remove useless dependencies in tests 2015-07-01 12:15:00 -07:00
Raphael Jamet 6de08216e7 docs($templateRequest): update the description with caching changes
The previous changes to $templateRequest were not documented, they now are.
2015-07-01 12:15:00 -07:00
Raphael Jamet 3c6e8ce044 refactor($templateRequest): move $sce checks and trust the cache
Move all the calls to $sce.getTrustedUrl inside $templateRequest, and
also trust the contents of the cache. This allows prefetching templates
and to bypass the checks on things where they make no sense, like
templates specified in script tags.

Closes #12219
Closes #12220
Closes #12240
2015-07-01 12:14:42 -07:00
Peter Bacon Darwin e51024ed54 docs(ngAnimate): fix typos 2015-06-30 13:19:52 +01:00
Chris Bosco 04f1ebd470 docs(guide/Migrating): $animate.on/off example updated to match docs
Closes #12212
2015-06-30 03:05:05 +01:00
Bart Verkoeijen 2e63ab734a docs(guide/Migrating): add breaking change for 1.4 regarding controller constructors.
If you previously returned a object from a controller constructor function,
it would not be bound to the scope. As of 1.4 it does, and can cause
unexpected objects as the scope.

Closes #12227
2015-06-30 02:59:46 +01:00
Georgios Kalpakas 6333d65b76 fix($compile): throw error when requestng new and isolate scopes (async)
While directives are not allowed to request both a new (normal) and an
isolate scope on the same element, the relevant check was not performed
correctly when the directive requesting the isolate scope had a lower
priority and specified a `templateUrl`.
In that case, the check was deferred until the template was fetched, but
the info about other directives requesting a new (normal) scope was not
properly preserved (in `previousCompileContext`).

This commit fixes this, so now an error is thrown (as expected).

Fixes #12215
Closes #12217
2015-06-28 11:33:06 +03:00
Yichao Wang 1ce5d216c7 docs(ngAnimate): fix typos in JS and CSS selector
Closes #12203
2015-06-25 12:42:17 +03:00
Georgios Kalpakas 28c166939e test($compile): test default value for optional attribute with new scope
Related to #12151
Closes #12194
2015-06-24 10:25:55 +02:00
Peter Bacon Darwin 14638f4a60 fix(ngOptions): only watch numeric properties of an array
It turns out that the options that are displayed are more constrained than
just whether the property starts with a $ character.
If the values collection is array-like then we only display the options that
are identified by numerical properties - it's an array right?

So this commit aligns `getWatchables` with `getOptions`.

See #12010
2015-06-23 17:47:34 -07:00
Peter Bacon Darwin 0c1fbdd242 chore(doc-gen): update to dgeni-packages 0.10.17
Make proper use of the new `git` package in dgeni-packages
2015-06-23 04:41:45 -07:00
Martin Staffa 33f7f26558 docs(ngChecked): note that it shouldn't be used with ngModel
Closes #11106
2015-06-22 23:39:08 +02:00
Martin Staffa e27eed3ca4 docs(ngCookies): improve deprecation notice 2015-06-22 23:37:50 +02:00
Gabriel Monteagudo 6cbbd96647 fix(merge): treat dates as atomic values instead of objects.
Makes angular.merge copy dates correctly.

Closes #11720

Closes #11720
2015-06-22 21:21:09 +02:00
Phil Brown d0cb69348e docs($http): set correct link to XMLHttpRequest.responseType
The link to MDN XMLHttpRequest.responseType was incorrect.

Closes #12183
2015-06-22 18:51:46 +02:00
Jandalf f15f8df2b4 docs($httpProvider): typo fix
fix a typo:
default.cache -> defaults.cache
2015-06-21 14:07:13 +02:00
Peter Bacon Darwin e7662ebc31 docs(directives): add multiElement tag to appropriate directives
Closes #11104
2015-06-21 01:52:01 +01:00
Peter Bacon Darwin 8ceed4faf3 chore(dependencies): update to dgeni-packages 0.10.15
Closes #11104
Closes #11418
2015-06-21 01:51:31 +01:00
Tsuyoshi Yoshizawa 6903b5ec4c fix($location): allow navigating outside the original base URL
Previously, if you navigated outside of the current base URL angular
crashed with a `Cannot call method 'charAt' of undefined` error.

Closes #11302
Closes #4776
2015-06-19 18:40:28 +01:00
Peter Bacon Darwin 48e1f5605e fix(orderBy): ensure correct ordering with arrays of objects and no predicate
By refactoring to use a Schwartzian transform, we can ensure that objects
with no custom `toString` or `toValue` methods are just ordered using
their position in the original collection.

Closes #11866
Closes #11312
Closes #4282
2015-06-18 08:36:16 +01:00
Peter Bacon Darwin c5a3d8fc5f refact(filter): move hasCustomToString into shared namespace to be reused 2015-06-18 08:33:28 +01:00
Martin Staffa c61149213b docs(CHANGELOG): fix position for some entries in 1.4.1 2015-06-17 23:57:54 +02:00
Stéphane Campinas ad7200e2c2 docs(tutorial/Tutorial): add missing word
Closes #12147
2015-06-17 21:19:02 +02:00
Alfonso Presa bea74c0f56 docs(ngTouch): Document event parameter for $swipe handlers
Document that the event handlers provided by $swipe do receive the raw
event as their last parameter.

Closes #11983

Closes #12149
2015-06-17 21:17:33 +02:00
Martin Staffa bacc3b7e0e docs(tutorial): make docTutorialReset use a button
It's confusing to have it look like a link that goes to the homepage

Closes #1473
2015-06-17 21:14:39 +02:00
Caitlin Potter 8a1eb1625c fix($compile): do not write @-bound properties if attribute is not present
Shadows only when attributes are non-optional and not own properties,
only stores the observed '@' values when they are indeed strings.

Partial revert of 6339d30d1379689da5eec9647a953f64821f8b0

Closes #12151
Closes #12144
2015-06-17 17:40:12 +01:00
Peter Bacon Darwin ed27e0ea6a docs(CHANGELOG): fix typo 2015-06-17 14:35:25 +01:00
Peter Bacon Darwin f81ff3beb0 fix($browser): prevent infinite digest if changing hash when there is no hashPrefix
The `window.location.hash' setter will strip of a single leading hash character
if it exists from the fragment  before joining the fragment value to the href
with a new hash character.

This meant that if we want the fragment to lead with a hash character, we
must do `window.location.hash = '##test'` to ensure that the first hash
character in the fragment is not lost.

The `$location.hash` setter works differently and assumes that the value
passed is the the full fragment, i.e. it does not attempt to strip off a
single leading hash character.

Previously, if you called, `$location.hash('#test')`, the leading hash was
being stripped and the resulting url fragment did not contain this hash:
`$location.hash()`, then became 'test' rather than `#test`, which led to
an infinite digest.

Closes #10423
Closes #12145
2015-06-17 14:01:20 +01:00
Martin Staffa 720012eab6 docs(resource): clarify success callback arguments
Closes #7730
2015-06-16 19:50:42 +02:00
Kent C. Dodds 3adfe5bda9 docs(guide/Unit Testing): add variable declaration to $filter test
The $filter example never declares `$filter` and therefore would add
`$filter` to the global namespace. Add variable declaration.

Closes #12129
2015-06-16 19:12:10 +02:00
Martin Staffa dc0467879d docs(input[radio]): clarify difference between value and ngValue
Closes #7971
2015-06-16 19:11:11 +02:00
Peter Bacon Darwin 528d7f9568 docs(CHANGELOG): add 1.4.1 changes 2015-06-16 14:52:17 +01:00
Georgios Kalpakas 636ce70e47 style(forms): fix indentation in example 2015-06-16 15:34:02 +03:00
Nir Noy 5f5ee0f880 docs(forms): remove redundant call to $scope.$apply()
As of Angular 1.3 `$setViewValue` already calls `$apply` and triggers a
digest cycle, so now there is no need wrapping the `$setViewValue`
function call with `$apply`, which will just trigger an additional digest
cycle.
2015-06-16 13:20:57 +03:00
Thomas Landauer 46b7cf7464 docs(filter): document third argument of predicate function 2015-06-15 20:50:59 +02:00
Martin Staffa 860edee65b docs(changelog): fix typo
Closes #12085
2015-06-15 20:45:28 +02:00
Caitlin Potter ebd0fbba8f fix(forms): parse exponential notation in numberInputType parser
Support parsing numbers in exponential notation, which Number.prototype.toString() returns
for sufficiently high numbers.

Closes #12121
Closes #12122
2015-06-15 08:46:47 -04:00
Rouven Weßling 093416f60f chore(npm): add the license to package.json
This removes a warning when executing npm install.

Closes #12111
2015-06-15 14:17:56 +03:00
Martin Staffa 0400dc9c2a docs($http): expand the param serializer docs
Closes #11745
Closes #12064
2015-06-14 13:36:37 +02:00
Lucas Galfaso 71fc3f4fa0 fix($parse): set null reference properties to undefined
When there is an expression of the form
* true && a.b.c
* true && a()
* true && a()()
* false || a.b.c
* false || a()
* false || a()()

where `a == null`

Closes #12099
2015-06-13 12:38:57 +02:00
Martin Staffa 8caf1802e0 fix(compile): assign ctrl return values correctly for multiple directives
Fixes #12029
Closes #12036
2015-06-12 21:41:55 +02:00
Peter Bacon Darwin 91b602263b fix($location): do not get caught in infinite digest in IE9
Thanks to @hamfastgamgee for getting this fix in place.

Closes #11439
Closes #11675
Closes #11935
Closes #12083
2015-06-12 14:35:46 +01:00
Lucas Galfaso 0934b76b72 fix(ngModel): form validation when there is an Object.prototype enumerable value
When adding an Object.prototype enumerable property, this should not be confused
as a form error

Closes #12066
2015-06-11 23:25:08 +02:00
Caitlin Potter 571bee7b2f test($location): ensure mock window can be wrapped by jqLite
Fixin da build

Closes #12086
2015-06-11 12:04:56 -04:00
Peter Bacon Darwin 11055132bf test($locationSpec): refactor and clean up tests 2015-06-11 14:29:13 +01:00
Peter Bacon Darwin 0898b1240b test($logSpec): don't pollute the global namespace with helpers 2015-06-11 13:29:15 +01:00
Conny Sjöblom 8dc09e6dab fix(linky): allow case insensitive scheme detection
Closes #12073
Closes #12073
2015-06-10 14:38:55 +01:00
Lucas Galfaso 799353c75d fix($sanitize): dont not remove tab index property
Closes #8371
Closes #5853
2015-06-10 11:48:00 +02:00
David Link ffac747e84 docs(tutorial/Tutorial): clarify what npm install does
If the reader does not cd into angular-phonecat subdirectory,
npm install will not work.
This comment helps newbies understand npm install is dependent
on a custom project.json file.

Closes #12040
2015-06-09 21:41:12 +02:00
Martin Staffa 998340de7f docs(select): correct workaround for numeric option bc 2015-06-09 21:35:59 +02:00
Georgios Kalpakas 559313652e test($compile): fix test
The fixed test is supposed to test a fix for an IE11 bug/peculiarity that
arises when using a specifically configured MutationObserver on the page
(see #11781 for more info).
The configuration contained a typo (`sublist` instead of `subtree`), which
effectively failed to set up the MutationObserver in a way that would make
the IE11 bug appear.

Closes #12061
2015-06-09 18:29:26 +03:00
Martin Staffa a69251ab55 docs(select): add note about breaking change with numeric values
Closes #12052
2015-06-08 21:15:14 +02:00
David Anderton 7e5248a33f docs(orderBy): correctly is not the right word
The use of correctly implies that Angular is doing something incorrect, however it is that we expect a number passed as a string to be sorted as a number. Angular does not do what we are expecting, although it responds correctly to what we have actually asked - sorting based on the string representation of a number.

Closes #12046
2015-06-08 21:15:10 +02:00
Martin Staffa c210ff5eae docs($compile): correct what gets passed to ctrl argument
Closes #11903
2015-06-08 21:15:07 +02:00
Jason Bedard 9efb0d5ee9 perf($compile): avoid jquery data calls when there is no data 2015-06-08 12:16:09 +02:00
Jason Bedard 0e622f7b5b fix(copy): do not copy the same object twice 2015-06-08 12:12:56 +02:00
Martin Staffa 071be60927 docs($animateCss): fix a dangling link 2015-06-06 14:45:01 +02:00
Martin Staffa a25aa5b577 docs(input[number]): mention incompatibility with allowInvalid
Closes #11390
2015-06-06 14:44:56 +02:00
Josh Sherick df9c720d08 docs(tutorial/step0): display list correctly
Two bullet points were indented causing the entire lines
to be formatted as code by markdown.
Decreased indentation level by one, as it seems this was not the intention.

Closes #12035
2015-06-06 14:44:52 +02:00
Will Fong 4fe141f794 docs(tutorial/index): add a "next step" sentence
All the other pages have a "continue to next page" link
at the bottom of the page. Keeps a nice reading flow.

Closes #12038
2015-06-06 14:44:28 +02:00
Lucas Galfaso f3b1d0b723 fix($compile): workaround for IE11 MutationObserver
IE11 MutationObserver breaks consecutive text nodes into several text nodes.
This patch merges consecutive text nodes into a single node before
looking for interpolations.

Closes #11781
2015-06-06 11:26:40 +02:00
qbzzt 288225b080 docs(ngClass): add class 'has-error' to demonstrate hyphen use
Modify the example, to show that, when using `ngClass`'s map syntax,
hyphenated classes (e.h. such as those used by Bootstrap) must be enclosed
in quotes.

Closes #12027
2015-06-06 01:34:31 +03:00
Matias Niemelä e967abcd30 docs(CHANGELOG): add changes for 1.3.16 2015-06-05 13:40:38 -07:00
Igor Minar 2c3cd8126c docs(http): add info about unique cookies and XSRF protection on shared domains
Closes #12028
2015-06-04 22:15:55 -07:00
Martin Staffa 41385f0afc docs(*): improve accessibility of links
Closes #7932
2015-06-04 23:00:43 +02:00
Martin Staffa 500b0f6cdb docs(guide/expressions): include filters in one-time binding examples
Closes #8776
2015-06-04 23:00:40 +02:00
Allan Bogh 40b27280ab docs(ngAria): clarify which module to include for ngAria
Closes #11802
2015-06-04 23:00:37 +02:00
Kevin Huang b73c64e2fb docs(guide/Conceptual Overview): remove text from in-page anchor tags
The in-page anchor tags that serve as bookmarks for information about views and models have
visible text content that unintentionally makes them seem like clickable links navigating to
other parts of the page or to entirely different pages.

Closes #11450
2015-06-04 23:00:34 +02:00
fahdsheikh 2f5d42ec72 docs(changelog): fixed grammatical error
Changed "a animation" to "an animation" for grammatical consistency

Closes #11672
2015-06-04 23:00:31 +02:00
Georgios Kalpakas 25d731e9b0 docs(orderBy): fix JSCS trailing whitespace error 2015-06-04 10:55:07 +03:00
Robert Jenks 15da7cc3dc docs(orderBy): improve sorting behaviour and move logic into the controller
Improve the sorting behaviour in the 2nd example: Clicking on an unsorted
column sorts in ascending order, while clicking on a sorted column sorts
in descending order. Also, add a simple sort indicator.

Closes #11981
2015-06-04 10:11:16 +03:00
Peter Bacon Darwin 34a6da24c1 fix(ngOptions): do not watch properties starting with $
Expressions that compute labels and track by values for ngOptions were
being called for properties, that start with $ even though those properties
were being ignored as options.

Closes #11930
Closes #12010
2015-06-04 06:28:00 +01:00
Georgios Kalpakas ebaa0f5985 fix(ngAria): update aria-valuemin/max when min/max change
As a result of thi fix, `ngMin/Max` also set `aria-valuemin/max` on
"range"-shaped elements.

Fixes #11770

Closes #11774
2015-06-03 21:23:38 +02:00
Dominick bb15d414c6 docs(guide/Modules): simple grammar fix
the module consist of… --> the module consists of…

Closes #11843
2015-06-03 21:07:46 +02:00
Dominick f056036a4a docs(guide/security): remove errant word
Closes #11870
2015-06-03 21:06:44 +02:00
Dominick a055762027 docs(guide/i18n): grammar fix
contraction "it's" --> possessive "its"
2015-06-03 21:06:19 +02:00
Dominick 82d38e4453 docs(guide/Using $location): format parameter name
Format parameter name as code. (It's used elsewhere in this doc page in code examples, as code itself.)
2015-06-03 21:04:13 +02:00
Steve Mao 6a743f0b5b docs(ngModelOptions): make object notation style consistent
There is a space before and after `{` and `}` for most of the objects throughout the docs.

Closes #11871
2015-06-03 21:03:16 +02:00
shoja 31f6f76291 docs($httpBackend): correct typo
docs($httpBackend): correct typo

Correct "send" to "sent".

Closes #11876
2015-06-03 21:02:50 +02:00
David Eriksson a2b5a5ed5f docs($cookiesProvider): escape HTML
Escape the "base" HTML element so it will be displayed in the online documentation.

Closes #11897
2015-06-03 21:01:47 +02:00
Boris Cherny 1d41e8a975 docs(ngRepeat): document that track by must be the last expression
this is a point of confusion that's not well documented. see #5520

Closes #11934
2015-06-03 20:57:56 +02:00
Pascal Precht 01182dfbb8 docs(ngMessages): fixes logical bug
The paragraph below this changes says:

"Then the `required` message will be displayed first."

`required` needs to be `true` to match that sentence.

Closes #12009
2015-06-03 19:59:26 +02:00
Yuriy Bash e17f85cc5b docs(ngMessages): fix spelling error
Closes #12019
2015-06-03 19:56:51 +02:00
Steven Easter d7dc14dc0c fix(ngOptions): use reference check only when not using trackBy
Change the check on changed value for ngOptions to ensure that a reference check is only done
when trackBy is not used.  Previously, if trackBy was being used but the values of the objects were
equal a reference check was then used which would cause the check to be true if the objects had
different memory references but the values were equal.  This can cause issues with forms being
marked dirty when the value of the model as not actually changed.

Closes #11936
Closes #11996
2015-06-02 12:37:33 +01:00
Henry Zhu 578fa019b3 chore(jscs): remove .jscs.json.todo, rename config to .jscsrc
Closes #11993
2015-06-02 10:29:54 +01:00
Michal Miszczyszyn 3c9096efb4 test(ngAria): test that aria-hidden/disabled are always "true" or "false"
Previously, when using ngAria with the ng-hide directive,
and the value passed to ng-hide was not boolean,
the aria-hidden attribute was set to this non-boolean value.

Closes #11865
Closes #11998
2015-06-01 23:13:22 +02:00
Fred Sauer 59273354b5 fix(ngAria): ensure boolean values for aria-hidden and aria-disabled
aria-hidden should mirror the boolean representation of their ng-*
counterpart (ng-show, ng-hide) instead of their actual value. Same
applies to aria-disabled and ng-disabled

Closes #11365
2015-06-01 23:13:21 +02:00
Xavier Haniquaut f67204794e docs(migration): fix minor typo
Closes #11994
2015-06-01 21:51:47 +01:00
Wenhua Zhao b6389eedda chore(injector): avoid invoking noop 2015-06-01 11:48:36 +02:00
Ran Ding a6339d30d1 fix($compile): exception when using "watch" as isolated scope binding variable in Firefox
Fix on all binding modes: '=', '@' and '&' as well as optional cases
Throw exception when user define 'hasOwnProperty' in binding.

Closes #11627
2015-06-01 11:36:18 +02:00
Vladimir Lugovsky 351fe4b79c feat($compile): show module name during multidir error
Show module name if possible when multidir error happens.

Closes #11775
2015-06-01 11:08:27 +02:00
Lucas Galfaso d19504a179 fix($parse): set null reference properties to undefined
When there is an expression of the form `true && a.b` and where `a == null`, then set
the value of `true && a.b` to `undefined`.

Closes #11959
2015-06-01 11:03:12 +02:00
Jeff Lee e5e871fe1a docs(ngAnimate): fix typo
Closes #11957
2015-06-01 08:03:20 +01:00
Ron Tsui 90fa884f94 docs(README): improve unusual phrasing
Closes #11958
2015-06-01 08:01:26 +01:00
Yi EungJun 80b9018f29 docs(guide/Directives): use more standard data-ng-model in example
Use data-ng-model instead of data-ng:model which is accepted for legacy reason.
The next "Normalization" section is saying:

> Best Practice: Prefer using the dash-delimited format (e.g. ng-bind for
> ngBind). If you want to use an HTML validating tool, you can instead use the
> data-prefixed version (e.g. data-ng-bind for ngBind). The other forms
> shown above are accepted for legacy reasons but we advise you to avoid
> them.

Closes #11960
2015-06-01 07:59:05 +01:00
Daniel f6ac226c8b docs(numberFilter): update to match handling of null and undefined
This changed in 2ae10f67fc, where null and
undefined are passed through.

Closes #11963
2015-06-01 07:55:37 +01:00
Michael Watts 2d22380873 docs(guide/Scopes): capitalisation of word scope
Closes #11970
2015-06-01 07:50:12 +01:00
Peter Bacon Darwin 7c49d9986f docs(README.closure.md): clarify sentence
Closes #11979
2015-06-01 07:48:21 +01:00
pholly 209f4f3e0f docs(guide/Expressions): added special case for one-time binding of object literals under Value stabilization algorithm
One time binding of object literals are treated differently than simple expressions. Added a link to Ben Nadel's article describing how object literals's keys are checked for undefined.

Closes #11982
2015-06-01 07:42:22 +01:00
Tero Parviainen 5d68c763e2 refactor($compile): remove unused elementTransclusion argument
Remove the unused elementTransclusion argument from createBoundTranscludeFn.
Also remove the nodeLinkFn.elementTranscludeOnThisElement attribute, which
becomes unnecessary.

Closes #9962
Closes #11985
2015-06-01 07:36:36 +01:00
Ryan Dale 3ef529806f feat($q): $q.resolve as an alias for $q.when
New "when" alias "resolve" to maintain naming consistency with ES6.

Closes #11944
Closes #11987
2015-06-01 07:31:51 +01:00
651 changed files with 10548 additions and 7281 deletions
-15
View File
@@ -1,15 +0,0 @@
// This is an incomplete TODO list of checks we want to start enforcing
//
// The goal is to enable these checks one by one by moving them to .jscs.json along with commits
// that correct the existing code base issues and make the new check pass.
{
"validateParameterSeparator": ", ", // Re-assert this rule when JSCS allows multiple spaces
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
"disallowImplicitTypeConversion": ["string"],
"disallowMultipleLineBreaks": true,
"validateJSDoc": {
"checkParamNames": true,
"requireParamTypes": true
}
}
View File
+519 -2
View File
@@ -1,3 +1,494 @@
<a name="1.4.5"></a>
# 1.4.5 permanent-internship (2015-08-28)
## Bug Fixes
- **$animate:** `$animate.enabled(false)` should disable animations on $animateCss as well
([c3d5e33e](https://github.com/angular/angular.js/commit/c3d5e33e18bd9e423e2d0678e85564fad1dba99f),
[#12696](https://github.com/angular/angular.js/issues/12696), [#12685](https://github.com/angular/angular.js/issues/12685))
- **$animateCss:**
- do not throw errors when a closing timeout is fired on a removed element
([2f6b6fb7](https://github.com/angular/angular.js/commit/2f6b6fb7a1dee0ff97c5d2959b927347eeda6e8b),
[#12650](https://github.com/angular/angular.js/issues/12650))
- fix parse errors on older Android WebViews
([1cc9c9ca](https://github.com/angular/angular.js/commit/1cc9c9ca9d9698356ea541517b3d06ce6556c01d),
[#12610](https://github.com/angular/angular.js/issues/12610))
- properly handle cancellation timeouts for follow-up animations
([d8816731](https://github.com/angular/angular.js/commit/d88167318d1c69f0dbd2101c05955eb450c34fd5),
[#12490](https://github.com/angular/angular.js/issues/12490), [#12359](https://github.com/angular/angular.js/issues/12359))
- ensure failed animations clear the internal cache
([0a75a3db](https://github.com/angular/angular.js/commit/0a75a3db6ef265389c8c955981c2fe67bb4f7769),
[#12214](https://github.com/angular/angular.js/issues/12214), [#12518](https://github.com/angular/angular.js/issues/12518), [#12381](https://github.com/angular/angular.js/issues/12381))
- the transitions options delay value should be applied before class application
([0c81e9fd](https://github.com/angular/angular.js/commit/0c81e9fd25285dd757db98d458919776a1fb62fc),
[#12584](https://github.com/angular/angular.js/issues/12584))
- **ngAnimate:**
- use requestAnimationFrame to space out child animations
([ea8016c4](https://github.com/angular/angular.js/commit/ea8016c4c8f55bc021549f342618ed869998e335),
[#12669](https://github.com/angular/angular.js/issues/12669), [#12594](https://github.com/angular/angular.js/issues/12594), [#12655](https://github.com/angular/angular.js/issues/12655), [#12631](https://github.com/angular/angular.js/issues/12631), [#12612](https://github.com/angular/angular.js/issues/12612), [#12187](https://github.com/angular/angular.js/issues/12187))
- only buffer rAF requests within the animation runners
([dc48aadd](https://github.com/angular/angular.js/commit/dc48aadd26bbf1797c1c408f63ffde99d67414a9),
[#12280](https://github.com/angular/angular.js/issues/12280))
- **ngModel:** validate pattern against the viewValue
([0e001084](https://github.com/angular/angular.js/commit/0e001084ffff8674efad289d37cb16cc4e46b50a),
[#12344](https://github.com/angular/angular.js/issues/12344))
- **ngResources:** support IPv6 URLs
([b643f0d3](https://github.com/angular/angular.js/commit/b643f0d3223a627ef813f0777524e25d2dd95371),
[#12512](https://github.com/angular/angular.js/issues/12512), [#12532](https://github.com/angular/angular.js/issues/12532))
## Breaking Changes
- **ngModel:** due to [0e001084](https://github.com/angular/angular.js/commit/0e001084ffff8674efad289d37cb16cc4e46b50a),
The `ngPattern` and `pattern` directives will validate the regex
against the `viewValue` of `ngModel`, i.e. the value of the model
before the $parsers are applied. Previously, the modelValue
(the result of the $parsers) was validated.
This fixes issues where `input[date]` and `input[number]` cannot
be validated because the viewValue string is parsed into
`Date` and `Number` respectively (starting with Angular 1.3).
It also brings the directives in line with HTML5 constraint
validation, which validates against the input value.
This change is unlikely to cause applications to fail, because even
in Angular 1.2, the value that was validated by pattern could have
been manipulated by the $parsers, as all validation was done
inside this pipeline.
If you rely on the pattern being validated against the modelValue,
you must create your own validator directive that overwrites
the built-in pattern validator:
```js
.directive('patternModelOverwrite', function patternModelOverwriteDirective() {
return {
restrict: 'A',
require: '?ngModel',
priority: 1,
compile: function() {
var regexp, patternExp;
return {
pre: function(scope, elm, attr, ctrl) {
if (!ctrl) return;
attr.$observe('pattern', function(regex) {
/**
* The built-in directive will call our overwritten validator
* (see below). We just need to update the regex.
* The preLink fn guaranetees our observer is called first.
*/
if (isString(regex) && regex.length > 0) {
regex = new RegExp('^' + regex + '$');
}
if (regex && !regex.test) {
//The built-in validator will throw at this point
return;
}
regexp = regex || undefined;
});
},
post: function(scope, elm, attr, ctrl) {
if (!ctrl) return;
regexp, patternExp = attr.ngPattern || attr.pattern;
//The postLink fn guarantees we overwrite the built-in pattern validator
ctrl.$validators.pattern = function(value) {
return ctrl.$isEmpty(value) ||
isUndefined(regexp) ||
regexp.test(value);
};
}
};
}
};
});
```
<a name="1.3.18"></a>
# 1.3.18 collective-penmanship (2015-08-18)
## Bug Fixes
- **$animate:**
- clear class animations cache if animation is not started
([2c03a357](https://github.com/angular/angular.js/commit/2c03a3574336ed814d020cf7ba36cee5b87e65b5),
[#12604](https://github.com/angular/angular.js/issues/12604), [#12603](https://github.com/angular/angular.js/issues/12603))
- do not throw errors if element is removed before animation starts
([6b72598b](https://github.com/angular/angular.js/commit/6b72598b87022e1dd96bddc4451e007ef0601579),
[#10205](https://github.com/angular/angular.js/issues/10205))
- **ngModel:** correct minErr usage for correct doc creation
([64a142b5](https://github.com/angular/angular.js/commit/64a142b58ed0a0e3896d82f3f9ce35373548d0ff),
[#12386](https://github.com/angular/angular.js/issues/12386), [#12416](https://github.com/angular/angular.js/issues/12416))
<a name="1.4.4"></a>
# 1.4.4 pylon-requirement (2015-08-13)
## Bug Fixes
- **$animate:**
- leave animation callback should not overridden by follow-up animation
([92e41ac9](https://github.com/angular/angular.js/commit/92e41ac904b7d16e96fd31a49ac2ae15d606a665),
[#12271](https://github.com/angular/angular.js/issues/12271), [#12249](https://github.com/angular/angular.js/issues/12249), [#12161](https://github.com/angular/angular.js/issues/12161))
- make sure to run a post-digest reflow for parentless animations
([861636c6](https://github.com/angular/angular.js/commit/861636c62542252a54fb2d2fa8ea9e17eefee120),
[#12400](https://github.com/angular/angular.js/issues/12400), [#12401](https://github.com/angular/angular.js/issues/12401))
- ensure that class-based animations are properly applied when cancelled
([21d6db38](https://github.com/angular/angular.js/commit/21d6db382d8f3540fb0bb7280570fba8d88d9843),
[#12266](https://github.com/angular/angular.js/issues/12266), [#12007](https://github.com/angular/angular.js/issues/12007))
- **$animateCss:** make sure that `skipBlocking` avoids the pre-emptive transition-delay styling
([11695ca6](https://github.com/angular/angular.js/commit/11695ca6e2ce5b21bb944ee0de80892203155cbb))
- **$compile:**
- don't trigger $observer if initial value is `undefined`
([6f3b8622](https://github.com/angular/angular.js/commit/6f3b8622adce2006df5cf7eed4bf9262539004bd),
[#12383](https://github.com/angular/angular.js/issues/12383), [#12464](https://github.com/angular/angular.js/issues/12464))
- ignore optional =-bound properties with empty value
([533d9b76](https://github.com/angular/angular.js/commit/533d9b76704368ba9700ab08589118abca9f598c),
[#12144](https://github.com/angular/angular.js/issues/12144), [#12259](https://github.com/angular/angular.js/issues/12259), [#12290](https://github.com/angular/angular.js/issues/12290))
- **$injector:** Allows ES6 function syntax
([44a96a4c](https://github.com/angular/angular.js/commit/44a96a4c140873d9fd8484d870af83a0bb9acabd),
[#12424](https://github.com/angular/angular.js/issues/12424), [#12425](https://github.com/angular/angular.js/issues/12425))
- **$location:** don't crash if navigating outside the app base
([9e492c35](https://github.com/angular/angular.js/commit/9e492c358c19549696577c86c2c61b93f50ab356),
[#11667](https://github.com/angular/angular.js/issues/11667))
- **$q:** Use extend to avoid overwriting prototype
([3abb3fef](https://github.com/angular/angular.js/commit/3abb3fefe653df2a4cb730cface0049939c18efd),
[#10697](https://github.com/angular/angular.js/issues/10697))
- **$rootScope:** don't clear phase if $apply is re-entered
([e0cf496f](https://github.com/angular/angular.js/commit/e0cf496f3cd6835db91546438def5bca1b6db4df),
[#12174](https://github.com/angular/angular.js/issues/12174))
- **Angular:** allow unescaped `=` signs in values in `parseKeyValue`
([f13852c1](https://github.com/angular/angular.js/commit/f13852c179ffd9ec18b7a94df27dec39eb5f19fc),
[#12351](https://github.com/angular/angular.js/issues/12351))
- **httpParamSerializerJQLike:** Follow jQuery for index of arrays of objects
([18a2e4fb](https://github.com/angular/angular.js/commit/18a2e4fbfc44216c31bbcdf7705ca87c53e6f1fa))
- **i18n:** by default put negative sign before currency symbol
([96f2e3be](https://github.com/angular/angular.js/commit/96f2e3bef5fc310edb2f6ed1addbcb7e1c1e71c2),
[#10158](https://github.com/angular/angular.js/issues/10158))
- **injector:** check that modulesToLoad isArray.
([5abf593e](https://github.com/angular/angular.js/commit/5abf593e6b3535cc836c99db4018a4e2fc2dbc3b),
[#12285](https://github.com/angular/angular.js/issues/12285))
- **input:** Firefox validation trigger
([e7423168](https://github.com/angular/angular.js/commit/e7423168fbf439a8798fdbbffb57955c272c2d74),
[#12102](https://github.com/angular/angular.js/issues/12102))
- **merge:** regExp should not be treated as a objects when merging.
([a5221f32](https://github.com/angular/angular.js/commit/a5221f320a8c1644354003c0e78201add44f11e6),
[#12419](https://github.com/angular/angular.js/issues/12419), [#12409](https://github.com/angular/angular.js/issues/12409))
- **ng/$locale:** by default put negative sign before currency symbol
([52986724](https://github.com/angular/angular.js/commit/5298672411cd7f5870e12185845cc2e9e3fe6949),
[#10158](https://github.com/angular/angular.js/issues/10158))
- **ngAnimate:**
- always apply a preparation reflow for CSS-based animations
([d33cedda](https://github.com/angular/angular.js/commit/d33cedda1624114d7e97a97b79705685c6cc40a2),
[#12553](https://github.com/angular/angular.js/issues/12553), [#12554](https://github.com/angular/angular.js/issues/12554), [#12267](https://github.com/angular/angular.js/issues/12267), [#12554](https://github.com/angular/angular.js/issues/12554))
- ensure that only string-based addClass/removeClass values are applied
([0d6fc2dc](https://github.com/angular/angular.js/commit/0d6fc2dce57ac60dfebba6eefb571ef9afcd2189),
[#12458](https://github.com/angular/angular.js/issues/12458), [#12459](https://github.com/angular/angular.js/issues/12459))
- ensure that parent class-based animations are never closed by their children
([32d3cbb3](https://github.com/angular/angular.js/commit/32d3cbb3aadf71492102f9318fcac570fb60bef8),
[#11975](https://github.com/angular/angular.js/issues/11975), [#12276](https://github.com/angular/angular.js/issues/12276))
- allow animations on body and root elements
([44ce9c82](https://github.com/angular/angular.js/commit/44ce9c8288fc6c12043567027271a09bd0594d74),
[#11956](https://github.com/angular/angular.js/issues/11956), [#12245](https://github.com/angular/angular.js/issues/12245))
- $timeout without invokeApply
([7db5f361](https://github.com/angular/angular.js/commit/7db5f361b0097a79255b90b26b5d700decf22f37),
[#12281](https://github.com/angular/angular.js/issues/12281), [#12282](https://github.com/angular/angular.js/issues/12282))
- **ngCsp:** allow CSP to be configurable
([618356e4](https://github.com/angular/angular.js/commit/618356e481fcfeac74bfc9086332e25062fd8133),
[#11933](https://github.com/angular/angular.js/issues/11933), [#8459](https://github.com/angular/angular.js/issues/8459), [#12346](https://github.com/angular/angular.js/issues/12346))
- **ngModel:** correct minErr usage for correct doc creation
([a268c29f](https://github.com/angular/angular.js/commit/a268c29fb019858155dac6692f351b64d43bb61c),
[#12386](https://github.com/angular/angular.js/issues/12386), [#12416](https://github.com/angular/angular.js/issues/12416))
- **ngOptions:** allow empty option selection with multiple attribute
([c11a7d67](https://github.com/angular/angular.js/commit/c11a7d676f21c39916243b13eeaf47f44b40c8eb),
[#12511](https://github.com/angular/angular.js/issues/12511), [#12541](https://github.com/angular/angular.js/issues/12541))
- **ngSanitize:** escape the wide char quote marks in a regex in linky.js
([39ff3332](https://github.com/angular/angular.js/commit/39ff3332a31b2db09e615ecea07634708cb46d7b),
[#11609](https://github.com/angular/angular.js/issues/11609))
## Features
- **$animateCss:** expose a core version of `$animateCss`
([39b634e5](https://github.com/angular/angular.js/commit/39b634e50a9ed140649d4be119a291debe527d55),
[#12509](https://github.com/angular/angular.js/issues/12509))
- **$httpProvider:** add 'useLegacyPromiseExtensions' configuration
([a8f7e9cf](https://github.com/angular/angular.js/commit/a8f7e9cfde82ed7eaba3a868d8acafdf57f2d76f),
[#12112](https://github.com/angular/angular.js/issues/12112), [#10508](https://github.com/angular/angular.js/issues/10508))
- **orderBy:** Stable sort the input
([ed3a33a0](https://github.com/angular/angular.js/commit/ed3a33a063f09d7ca356d15c278d95ad82e680a0),
[#12408](https://github.com/angular/angular.js/issues/12408), [#12405](https://github.com/angular/angular.js/issues/12405))
## Performance Improvements
- **$q:** small $q performance optimization
([6838c979](https://github.com/angular/angular.js/commit/6838c979451c109d959a15035177ccee715ccf19),
[#12535](https://github.com/angular/angular.js/issues/12535))
## Breaking Changes
- **ngAnimate:** due to [32d3cbb3](https://github.com/angular/angular.js/commit/32d3cbb3aadf71492102f9318fcac570fb60bef8),
CSS classes added/removed by ngAnimate are now applied synchronously once the first digest has passed.
The previous behavior involved ngAnimate having to wait for one
requestAnimationFrame before CSS classes were added/removed. The CSS classes
are now applied directly after the first digest that is triggered after
`$animate.addClass`, `$animate.removeClass` or `$animate.setClass` is
called. If any of your code relies on waiting for one frame before
checking for CSS classes on the element then please change this
behavior. If a parent class-based animation, however, is run through a
JavaScript animation which triggers an animation for `beforeAddClass`
and/or `beforeRemoveClass` then the CSS classes will not be applied
in time for the children (and the parent class-based animation will not
be cancelled by any child animations).
- **$q** due to [6838c979](https://github.com/angular/angular.js/commit/6838c979451c109d959a15035177ccee715ccf19),
When writing tests, there is no need to call `$timeout.flush()` to resolve a call to `$q.when` with a value.
The previous behavior involved creating an extra promise that needed to be resolved. This is no longer needed when
`$q.when` is called with a value. In the case that the test is not aware if `$q.when` is called with a value or
another promise, it is possible to replace `$timeout.flush();` with `$timeout.flush(0);`.
```js
describe('$q.when', function() {
it('should not need a call to $timeout.flush() to resolve already resolved promises',
inject(function($q, $timeout) {
$q.when('foo');
// In Angular 1.4.3 a call to `$timeout.flush();` was needed
$timeout.verifyNoPendingTasks();
}));
it('should accept $timeout.flush(0) when not sure if $q.when was called with a value or a promise',
inject(function($q, $timeout) {
$q.when('foo');
$timeout.flush(0);
$timeout.verifyNoPendingTasks();
}));
it('should need a call to $timeout.flush() to resolve $q.when when called with a promise',
inject(function($q, $timeout) {
$q.when($q.when('foo'));
$timeout.flush();
$timeout.verifyNoPendingTasks();
}));
});
```
<a name="1.4.3"></a>
# 1.4.3 foam-acceleration (2015-07-15)
## Bug Fixes
- **$animateCss:** ensure animations execute if only a keyframeStyle is provided
([97d79eec](https://github.com/angular/angular.js/commit/97d79eec80092f5fae3336c23aa881a72436de55),
[#12124](https://github.com/angular/angular.js/issues/12124), [#12340](https://github.com/angular/angular.js/issues/12340))
- **loader:** define isFunction
([9ea52d81](https://github.com/angular/angular.js/commit/9ea52d818bcd2fb3ea8ccc85bf47f9fd5af68843))
- **ngAnimate:** ensure that orphaned elements do not throw errors when animated
([e4aeae0c](https://github.com/angular/angular.js/commit/e4aeae0c7303b94135e6df20e6c5e25f2aa0f586),
[#11975](https://github.com/angular/angular.js/issues/11975), [#12338](https://github.com/angular/angular.js/issues/12338))
<a name="1.4.2"></a>
# 1.4.2 nebular-readjustment (2015-07-06)
## Bug Fixes
- **$browser:** prevent infinite digest if changing hash when there is no hashPrefix
([f81ff3be](https://github.com/angular/angular.js/commit/f81ff3beb0c9d19d494c5878086fb57476442b8b),
[#10423](https://github.com/angular/angular.js/issues/10423), [#12145](https://github.com/angular/angular.js/issues/12145))
- **$compile:**
- throw error when requestng new and isolate scopes (async)
([6333d65b](https://github.com/angular/angular.js/commit/6333d65b76e0796cfbab8a2953af0c8014dba2e1),
[#12215](https://github.com/angular/angular.js/issues/12215), [#12217](https://github.com/angular/angular.js/issues/12217))
- **$location:** allow navigating outside the original base URL
([6903b5ec](https://github.com/angular/angular.js/commit/6903b5ec4c04ed6b7c80ef7d638c48639ccdc4bb),
[#11302](https://github.com/angular/angular.js/issues/11302), [#4776](https://github.com/angular/angular.js/issues/4776))
- **merge:** treat dates as atomic values instead of objects.
([6cbbd966](https://github.com/angular/angular.js/commit/6cbbd966479448591f819cbf904e0a3b757613dc),
[#11720](https://github.com/angular/angular.js/issues/11720), [#11720](https://github.com/angular/angular.js/issues/11720))
- **ngOptions:** only watch numeric properties of an array
([14638f4a](https://github.com/angular/angular.js/commit/14638f4a60053b085565e597fc74bd31cf0d372b))
- **orderBy:** ensure correct ordering with arrays of objects and no predicate
([48e1f560](https://github.com/angular/angular.js/commit/48e1f5605edd32a63318fd78f5165c7d1f1a20f9),
[#11866](https://github.com/angular/angular.js/issues/11866), [#11312](https://github.com/angular/angular.js/issues/11312), [#4282](https://github.com/angular/angular.js/issues/4282))
## Features
- **ngAria:** add option to disable role=button
([1f5e42e8](https://github.com/angular/angular.js/commit/1f5e42e8821217026ef36a46d36f84d7cd32830a),
[#11580](https://github.com/angular/angular.js/issues/11580), [#12234](https://github.com/angular/angular.js/issues/12234))
<a name="1.3.17"></a>
# 1.3.17 tsktskskly-euouae (2015-07-06)
## Bug Fixes
- **$browser:** prevent infinite digest if changing hash when there is no hashPrefix
([61a3fb67](https://github.com/angular/angular.js/commit/61a3fb676a186e22564fb0181c17647b35ca4e5e),
[#10423](https://github.com/angular/angular.js/issues/10423), [#12145](https://github.com/angular/angular.js/issues/12145))
- **$location:**
- allow navigating outside the original base URL
([0bb57d53](https://github.com/angular/angular.js/commit/0bb57d538f25a1b6f20025d87a451c39671b59aa),
[#11302](https://github.com/angular/angular.js/issues/11302), [#4776](https://github.com/angular/angular.js/issues/4776))
- do not get caught in infinite digest in IE9
([f486ebe8](https://github.com/angular/angular.js/commit/f486ebe80b6d7854d3eb9029f14d94299cf493cb),
[#11439](https://github.com/angular/angular.js/issues/11439), [#11675](https://github.com/angular/angular.js/issues/11675), [#11935](https://github.com/angular/angular.js/issues/11935), [#12083](https://github.com/angular/angular.js/issues/12083))
- **linky:** allow case insensitive scheme detection
([6b28aef1](https://github.com/angular/angular.js/commit/6b28aef1c537bfb2da21820d6ca154344efe266e),
[#12073](https://github.com/angular/angular.js/issues/12073), [#12074](https://github.com/angular/angular.js/issues/12074))
<a name="1.4.1"></a>
# 1.4.1 hyperionic-illumination (2015-06-16)
## Bug Fixes
- **$compile:**
- workaround for IE11 MutationObserver
([f3b1d0b7](https://github.com/angular/angular.js/commit/f3b1d0b723298a5f8ea21d0704405649cce1b5fc),
[#11781](https://github.com/angular/angular.js/issues/11781))
- prevent exception when using `watch` as isolated scope binding property in Firefox
([a6339d30](https://github.com/angular/angular.js/commit/a6339d30d1379689da5eec9647a953f64821f8b0),
[#11627](https://github.com/angular/angular.js/issues/11627))
- assign controller return values correctly for multiple directives
([8caf1802](https://github.com/angular/angular.js/commit/8caf1802e0e93389dec626ef35e04a302aa6c39d),
[#12029](https://github.com/angular/angular.js/issues/12029), [#12036](https://github.com/angular/angular.js/issues/12036))
- **$location:** do not get caught in infinite digest in IE9 when redirecting in `$locationChangeSuccess`
([91b60226](https://github.com/angular/angular.js/commit/91b602263b96b6fce1331208462e18eb647f4d60),
[#11439](https://github.com/angular/angular.js/issues/11439), [#11675](https://github.com/angular/angular.js/issues/11675), [#11935](https://github.com/angular/angular.js/issues/11935), [#12083](https://github.com/angular/angular.js/issues/12083))
- **$parse:** set null reference properties to `undefined`
([71fc3f4f](https://github.com/angular/angular.js/commit/71fc3f4fa0cd12eff335d57efed7c033554749f4),
[#12099](https://github.com/angular/angular.js/issues/12099))
([d19504a1](https://github.com/angular/angular.js/commit/d19504a179355d7801d59a8db0285a1322e04601),
[#11959](https://github.com/angular/angular.js/issues/11959))
- **$sanitize:** do not remove `tabindex` attribute
([799353c7](https://github.com/angular/angular.js/commit/799353c75de28e6fbf52dac6e0721e85b578575a),
[#8371](https://github.com/angular/angular.js/issues/8371), [#5853](https://github.com/angular/angular.js/issues/5853))
- **copy:** do not copy the same object twice
([0e622f7b](https://github.com/angular/angular.js/commit/0e622f7b5bc3d5d0ab0fbc1a1bc69404bd7216d5))
- **forms:** parse exponential notation in `numberInputType` directive
([ebd0fbba](https://github.com/angular/angular.js/commit/ebd0fbba8ff90bee0cd016d574643d56a7f81ed0),
[#12121](https://github.com/angular/angular.js/issues/12121), [#12122](https://github.com/angular/angular.js/issues/12122))
- **linky:** allow case insensitive scheme detection
([8dc09e6d](https://github.com/angular/angular.js/commit/8dc09e6dabb84c2c611cdc9e40adfac989648200),
[#12073](https://github.com/angular/angular.js/issues/12073), [#12073](https://github.com/angular/angular.js/issues/12073))
- **ngAria:**
- update `aria-valuemin/max` when `min/max` change
([ebaa0f59](https://github.com/angular/angular.js/commit/ebaa0f598501702ae64d59ada0ae492eaf0e2db6),
[#11770](https://github.com/angular/angular.js/issues/11770), [#11774](https://github.com/angular/angular.js/issues/11774))
- ensure boolean values for aria-hidden and aria-disabled
([59273354](https://github.com/angular/angular.js/commit/59273354b57dd8d1ad2cd2f4740ffa8923e480f9),
[#11365](https://github.com/angular/angular.js/issues/11365))
- **ngModel:** ignore Object.prototype properties on the form validation object
([0934b76b](https://github.com/angular/angular.js/commit/0934b76b72cec86093414834ac4cb7f0946b651d),
[#12066](https://github.com/angular/angular.js/issues/12066))
- **ngOptions:**
- do not watch properties starting with $
([34a6da24](https://github.com/angular/angular.js/commit/34a6da24c17356d4ffc70aec3f621a140a9a61ab),
[#11930](https://github.com/angular/angular.js/issues/11930), [#12010](https://github.com/angular/angular.js/issues/12010))
- use reference check only when not using trackBy
([d7dc14dc](https://github.com/angular/angular.js/commit/d7dc14dc0cdeb9c187d227e19acc8aca7df9d740),
[#11936](https://github.com/angular/angular.js/issues/11936), [#11996](https://github.com/angular/angular.js/issues/11996))
## Features
- **$compile:** show module name during `multidir` error
([351fe4b7](https://github.com/angular/angular.js/commit/351fe4b79c50a45a11af2fcd2aa7b6fd3b70058d),
[#11775](https://github.com/angular/angular.js/issues/11775))
- **$q:** $q.resolve as an alias for $q.when
([3ef52980](https://github.com/angular/angular.js/commit/3ef529806fef28b41ca4af86a330f39a95699cf6),
[#11944](https://github.com/angular/angular.js/issues/11944), [#11987](https://github.com/angular/angular.js/issues/11987))
## Performance Improvements
- **$compile:** avoid jquery data calls when there is no data
([9efb0d5e](https://github.com/angular/angular.js/commit/9efb0d5ee961b57c8fc144a3138a15955e4010e2))
<a name="1.3.16"></a>
# 1.3.16 cookie-oatmealification (2015-06-05)
## Bug Fixes
- **$compile:** throw error on invalid directive name
([634e4671](https://github.com/angular/angular.js/commit/634e467172efa696eb32ef8942ffbedeecbd030e),
[#11281](https://github.com/angular/angular.js/issues/11281), [#11109](https://github.com/angular/angular.js/issues/11109))
- **$cookies:** update $cookies to prevent duplicate cookie writes and play nice with external code
([706a93ab](https://github.com/angular/angular.js/commit/706a93ab6960e3474698ccf9a8048b3c32e567c6),
[#11490](https://github.com/angular/angular.js/issues/11490), [#11515](https://github.com/angular/angular.js/issues/11515))
- **$http:** throw error if `success` and `error` methods do not receive a function
([731e1f65](https://github.com/angular/angular.js/commit/731e1f6534ab7fd1e053b8d7a25c902fcd934fea),
[#11330](https://github.com/angular/angular.js/issues/11330), [#11333](https://github.com/angular/angular.js/issues/11333))
- **core:** ensure that multiple requests to requestAnimationFrame are buffered
([0adc0364](https://github.com/angular/angular.js/commit/0adc0364265b06c567ccc8e90a7f09cc46f235b2),
[#11791](https://github.com/angular/angular.js/issues/11791))
- **filterFilter:** fix matching against `null`/`undefined`
([9dd0fe35](https://github.com/angular/angular.js/commit/9dd0fe35d1027e59b84b2396abee00d8683f3b50),
[#11573](https://github.com/angular/angular.js/issues/11573), [#11617](https://github.com/angular/angular.js/issues/11617))
- **jqLite:**
- check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
([647f3f55](https://github.com/angular/angular.js/commit/647f3f55eb7100a255272f7277f0f962de234a32),
[#11508](https://github.com/angular/angular.js/issues/11508))
- attr should ignore comment, text and attribute nodes
([181e5ebc](https://github.com/angular/angular.js/commit/181e5ebc3fce5312feacaeace4fcad0d32f4d73c))
- **ngAnimate:**
- ensure that minified repaint code isn't removed
([d5c99ea4](https://github.com/angular/angular.js/commit/d5c99ea42b834343fd0362cfc572f47e7536ccfb),
[#9936](https://github.com/angular/angular.js/issues/9936))
- **ngAria:** handle elements with role="checkbox/menuitemcheckbox"
([1c282af5](https://github.com/angular/angular.js/commit/1c282af5abc205d4aac37c05c5cb725d71747134),
[#11317](https://github.com/angular/angular.js/issues/11317), [#11321](https://github.com/angular/angular.js/issues/11321))
- **ngModel:** allow setting model to NaN when asyncValidator is present
([b64519fe](https://github.com/angular/angular.js/commit/b64519fea7f1a5ec75e32c4b71b012b827314153),
[#11315](https://github.com/angular/angular.js/issues/11315), [#11411](https://github.com/angular/angular.js/issues/11411))
- **ngTouch:**
- check undefined tagName for SVG event target
([7560a8d2](https://github.com/angular/angular.js/commit/7560a8d2d65955ddb60ede9d586502f4e3cbd062))
- register touches properly when jQuery is used
([40441f6d](https://github.com/angular/angular.js/commit/40441f6dfc5ebd5cdc679c269c4639238f5351eb),
[#4001](https://github.com/angular/angular.js/issues/4001), [#8584](https://github.com/angular/angular.js/issues/8584), [#10797](https://github.com/angular/angular.js/issues/10797), [#11488](https://github.com/angular/angular.js/issues/11488))
- **select:** prevent unknown option being added to select when bound to null property
([9e3f82bb](https://github.com/angular/angular.js/commit/9e3f82bbaf83cad7bb3121db756099b0880562e6),
[#11872](https://github.com/angular/angular.js/issues/11872), [#11875](https://github.com/angular/angular.js/issues/11875))
## Features
- **travis:** run unit tests on iOS 8
([1f650871](https://github.com/angular/angular.js/commit/1f650871266b88b3dab4a894a839a82ac9a06b69),
[#11479](https://github.com/angular/angular.js/issues/11479))
<a name="1.4.0"></a>
# 1.4.0 jaracimrman-existence (2015-05-26)
@@ -374,7 +865,7 @@ To get the desired behaviour you need to iterate using the object form of the `n
## Breaking Changes
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
JavaSript and CSS animations can no longer be run in
JavaScript and CSS animations can no longer be run in
parallel. With earlier versions of ngAnimate, both CSS and JS animations
would be run together when multiple animations were detected. This
feature has now been removed, however, the same effect, with even more
@@ -420,7 +911,7 @@ $animate.off(element, 'enter', fn);
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
There is no need to call `$scope.$apply` or
`$scope.$digest` inside of a animation promise callback anymore
`$scope.$digest` inside of an animation promise callback anymore
since the promise is resolved within a digest automatically (but a
digest is not run unless the promise is chained).
@@ -1153,7 +1644,33 @@ But in practice this is not what people want and so this change iterates over pr
in the order they are returned by Object.keys(obj), which is almost always the order
in which the properties were defined.
- **select:** due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
the `select` directive will now use strict comparison of the `ngModel` scope value against `option`
values to determine which option is selected. This means `Number` scope values will not be matched
against numeric option strings.
In Angular 1.3.x, setting `scope.x = 200` would select the `option` with the value 200 in the following `select`:
```
<select ng-model="x">
<option value="100">100</option>
<option value="200">200</option>
</select>
```
In Angular 1.4.x, the 'unknown option' will be selected.
To remedy this, you can simply initialize the model as a string: `scope.x = '200'`, or if you want to
keep the model as a `Number`, you can do the conversion via `$formatters` and `$parsers` on `ngModel`:
```js
ngModelCtrl.$parsers.push(function(value) {
return parseInt(value, 10); // Convert option value to number
});
ngModelCtrl.$formatters.push(function(value) {
return value.toString(); // Convert scope value to string
});
```
<a name="1.3.9"></a>
# 1.3.9 multidimensional-awareness (2015-01-13)
+11 -4
View File
@@ -19,7 +19,7 @@ Help us keep Angular open and inclusive. Please read and follow our [Code of Con
## <a name="question"></a> Got a Question or Problem?
If you have questions about how to use AngularJS, please direct these to the [Google Group][groups]
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc].
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc] and [Gitter][gitter].
## <a name="issue"></a> Found an Issue?
If you find a bug in the source code or a mistake in the documentation, you can help us by
@@ -199,8 +199,13 @@ format that includes a **type**, a **scope** and a **subject**:
<footer>
```
The **header** is mandatory and the **scope** of the header is optional.
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
to read on github as well as in various git tools.
to read on GitHub as well as in various git tools.
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
### Type
Must be one of the following:
@@ -210,7 +215,7 @@ Must be one of the following:
* **docs**: Documentation only changes
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
semi-colons, etc)
* **refactor**: A code change that neither fixes a bug or adds a feature
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **perf**: A code change that improves performance
* **test**: Adding missing tests
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
@@ -228,13 +233,14 @@ The subject contains succinct description of the change:
* no dot (.) at the end
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes"
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
A detailed explanation can be found in this [document][commit-message-format].
@@ -262,6 +268,7 @@ You can find out more detailed information about contributing in the
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[dev-doc]: https://docs.angularjs.org/guide
[github]: https://github.com/angular/angular.js
[gitter]: https://gitter.im/angular/angular.js
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
+7 -3
View File
@@ -115,7 +115,7 @@ module.exports = function(grunt) {
files: { src: 'test/**/*.js' },
},
ng: {
files: { src: files['angularSrc'] },
files: { src: files['angularSrc'].concat('!src/angular.bind.js') },
},
ngAnimate: {
files: { src: 'src/ngAnimate/**/*.js' },
@@ -156,9 +156,13 @@ module.exports = function(grunt) {
},
jscs: {
src: ['src/**/*.js', 'test/**/*.js'],
src: [
'src/**/*.js',
'test/**/*.js',
'!src/angular.bind.js' // we ignore this file since contains an early return statement
],
options: {
config: ".jscs.json"
config: ".jscsrc"
}
},
+2 -2
View File
@@ -1,8 +1,8 @@
Using AngularJS with the Closure Compiler
=========================================
The Closure Compiler project contains externs definitions for AngularJS
JavaScript in its `contrib/externs` directory.
The Closure Compiler project contains definitions for the AngularJS JavaScript
in its `contrib/externs` directory.
The definitions contain externs for use with the Closure compiler (aka
JSCompiler). Passing these files to the --externs parameter of a compiler
+1 -1
View File
@@ -10,7 +10,7 @@ the browser how to do dependency injection and inversion of control.
Oh yeah and it helps with server-side communication, taming async callbacks with promises and
deferreds. It also makes client-side navigation and deeplinking with hashbang urls or HTML5 pushState a
piece of cake. The best of all: it makes development fun!
piece of cake. Best of all?? It makes development fun!
* Web site: http://angularjs.org
* Tutorial: http://docs.angularjs.org/tutorial
+11 -6
View File
@@ -14,13 +14,14 @@ var angularFiles = {
'src/ng/anchorScroll.js',
'src/ng/animate.js',
'src/ng/asyncCallback.js',
'src/ng/animateCss.js',
'src/ng/browser.js',
'src/ng/cacheFactory.js',
'src/ng/compile.js',
'src/ng/controller.js',
'src/ng/document.js',
'src/ng/exceptionHandler.js',
'src/ng/forceReflow.js',
'src/ng/http.js',
'src/ng/httpBackend.js',
'src/ng/interpolate.js',
@@ -76,7 +77,10 @@ var angularFiles = {
'src/ng/directive/script.js',
'src/ng/directive/select.js',
'src/ng/directive/style.js',
'src/ng/directive/validators.js'
'src/ng/directive/validators.js',
'src/angular.bind.js',
'src/publishExternalApis.js',
'src/ngLocale/angular-locale_en-us.js'
],
'angularLoader': [
@@ -88,6 +92,7 @@ var angularFiles = {
'angularModules': {
'ngAnimate': [
'src/ngAnimate/shared.js',
'src/ngAnimate/body.js',
'src/ngAnimate/rafScheduler.js',
'src/ngAnimate/animateChildrenDirective.js',
'src/ngAnimate/animateCss.js',
@@ -179,7 +184,6 @@ var angularFiles = {
'bower_components/jquery/dist/jquery.js',
'test/jquery_remove.js',
'@angularSrc',
'src/publishExternalApis.js',
'@angularSrcModules',
'@angularScenario',
'@angularTest'
@@ -188,7 +192,8 @@ var angularFiles = {
'karmaExclude': [
'test/jquery_alias.js',
'src/angular-bootstrap.js',
'src/ngScenario/angular-bootstrap.js'
'src/ngScenario/angular-bootstrap.js',
'src/angular.bind.js'
],
'karmaScenario': [
@@ -215,7 +220,6 @@ var angularFiles = {
'bower_components/jquery/dist/jquery.js',
'test/jquery_alias.js',
'@angularSrc',
'src/publishExternalApis.js',
'@angularSrcModules',
'@angularScenario',
'@angularTest'
@@ -224,7 +228,8 @@ var angularFiles = {
'karmaJqueryExclude': [
'src/angular-bootstrap.js',
'src/ngScenario/angular-bootstrap.js',
'test/jquery_remove.js'
'test/jquery_remove.js',
'src/angular.bind.js'
]
};
+1 -1
View File
@@ -56,7 +56,7 @@ li.doc-example-live {
}
div.syntaxhighlighter {
padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars http://is.gd/gSMgC */
padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars */
}
/* TABS - tutorial environment navigation */
+2 -2
View File
@@ -35,7 +35,7 @@ angular.module('tutorials', [])
'step': '@docTutorialReset'
},
template:
'<p><a href="" ng-click="show=!show;$event.stopPropagation()">Workspace Reset Instructions ➤</a></p>\n' +
'<p><button class="btn" ng-click="show=!show">Workspace Reset Instructions ➤</button></p>\n' +
'<div class="alert alert-info" ng-show="show">\n' +
' <p>Reset the workspace to step {{step}}.</p>' +
' <p><pre>git checkout -f step-{{step}}</pre></p>\n' +
@@ -43,7 +43,7 @@ angular.module('tutorials', [])
'<a href="http://angular.github.io/angular-phonecat/step-{{step}}/app">Step {{step}} Live Demo</a>.</p>\n' +
'</div>\n' +
'<p>The most important changes are listed below. You can see the full diff on ' +
'<a ng-href="https://github.com/angular/angular-phonecat/compare/step-{{step ? (step - 1): \'0~1\'}}...step-{{step}}">GitHub</a>\n' +
'<a ng-href="https://github.com/angular/angular-phonecat/compare/step-{{step ? (step - 1): \'0~1\'}}...step-{{step}}" title="See diff on Github">GitHub</a>\n' +
'</p>'
};
});
+3 -4
View File
@@ -10,14 +10,14 @@ var Package = require('dgeni').Package;
module.exports = new Package('angularjs', [
require('dgeni-packages/ngdoc'),
require('dgeni-packages/nunjucks'),
require('dgeni-packages/examples')
require('dgeni-packages/examples'),
require('dgeni-packages/git')
])
.factory(require('./services/errorNamespaceMap'))
.factory(require('./services/getMinerrInfo'))
.factory(require('./services/getVersion'))
.factory(require('./services/gitData'))
.factory(require('./services/deployments/debug'))
.factory(require('./services/deployments/default'))
@@ -26,7 +26,6 @@ module.exports = new Package('angularjs', [
.factory(require('./inline-tag-defs/type'))
.processor(require('./processors/error-docs'))
.processor(require('./processors/index-page'))
.processor(require('./processors/keywords'))
@@ -43,7 +42,7 @@ module.exports = new Package('angularjs', [
readFilesProcessor.basePath = path.resolve(__dirname,'../..');
readFilesProcessor.sourceFiles = [
{ include: 'src/**/*.js', basePath: 'src' },
{ include: 'src/**/*.js', exclude: 'src/angular.bind.js', basePath: 'src' },
{ include: 'docs/content/**/*.ngdoc', basePath: 'docs/content' }
];
-16
View File
@@ -1,16 +0,0 @@
"use strict";
var versionInfo = require('../../../lib/versions/version-info');
/**
* @dgService gitData
* @description
* Information from the local git repository
*/
module.exports = function gitData() {
return {
version: versionInfo.currentVersion,
versions: versionInfo.previousVersions,
info: versionInfo.gitRepoInfo
};
};
@@ -76,7 +76,7 @@
<div class="row">
<div class="col-md-9 header-branding">
<a class="brand navbar-brand" href="http://angularjs.org">
<img width="117" height="30" class="logo" ng-src="img/angularjs-for-header-only.svg">
<img width="117" height="30" class="logo" alt="Link to Angular JS Homepage" ng-src="img/angularjs-for-header-only.svg">
</a>
<ul class="nav navbar-nav">
<li class="divider-vertical"></li>
@@ -90,7 +90,7 @@
<li class="disabled"><a href="http://angularjs.org/">Why AngularJS?</a></li>
<li><a href="http://www.youtube.com/user/angularjs">Watch</a></li>
<li><a href="tutorial">Tutorial</a></li>
<li><a href="http://builtwith.angularjs.org/">Case Studies</a></li>
<li><a href="https://www.madewithangular.com/">Case Studies</a></li>
<li><a href="https://github.com/angular/angular-seed">Seed App project template</a></li>
<li><a href="misc/faq">FAQ</a></li>
</ul>
@@ -223,7 +223,7 @@
Super-powered by Google ©2010-2015
( <a id="version"
ng-href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md#{{versionNumber}}"
ng-bind-template="v{{version}}">
ng-bind-template="v{{version}}" title="Changelog of this version of Angular JS">
</a>
)
</p>
+1 -1
View File
@@ -11,7 +11,7 @@ Supported formats:
1. `__name__`
2. `__name__ as __identifier__`
N'either `__name__` or `__identifier__` may contain spaces.
Neither `__name__` or `__identifier__` may contain spaces.
Example of incorrect usage that leads to this error:
```html
+45
View File
@@ -0,0 +1,45 @@
@ngdoc error
@name $http:legacy
@fullName The `success` and `error` methods on the promise returned from `$http` have been disabled.
@description
This error occurs when the legacy promise extensions (`success` and `error`)
{@link $httpProvider#useLegacyPromiseExtensions legacy `$http` promise extensions} have been disabled.
To resolve this error, either turn on the legacy extensions by adding
`$httpProvider.useLegacyPromiseExtensions(true);` to your application's configuration; or refactor you
use of `$http` to use `.then()` rather than `.success()` and `.error()`.
For example if you code looked like this:
```js
// Simple GET request example :
$http.get('/someUrl').
success(function(data, status, headers, config) {
// This callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
```
then you would change it to look like:
```js
// Simple GET request example :
$http.get('/someUrl').
then(function(response) {
// (The response object contains the data, status, headers and config properties)
// This callback will be called asynchronously
// when the response is available.
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
```
For more information, see the
{@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`}
documentation.
@@ -1,33 +0,0 @@
@ngdoc error
@name ngOptions:trkslct
@fullName Comprehension expression cannot contain both `select as` and `track by` expressions.
@description
NOTE: This error was introduced in 1.3.0-rc.5, and was removed for 1.3.0-rc.6 in order to
not break existing apps.
This error occurs when 'ngOptions' is passed a comprehension expression that contains both a
`select as` expression and a `track by` expression. These two expressions are fundamentally
incompatible.
* Example of bad expression: `<select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">`
`values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}]`,
`$scope.selected = {name: 'aSubItem'};`
* track by is always applied to `value`, with purpose to preserve the selection,
(to `item` in this case)
* To calculate whether an item is selected, `ngOptions` does the following:
1. apply `track by` to the values in the array:
In the example: [1,2]
2. apply `track by` to the already selected value in `ngModel`:
In the example: this is not possible, as `track by` refers to `item.id`, but the selected
value from `ngModel` is `{name: aSubItem}`.
Here's an example of how to make this example work by using `track by` without `select as`:
```
<select ng-model="selected" ng-options="item.label for item in values track by item.id">
```
Note: This would store the whole `item` as the model to `scope.selected` instead of `item.subItem`.
For more information on valid expression syntax, see 'ngOptions' in {@link ng.directive:select select} directive docs.
+2 -2
View File
@@ -301,7 +301,7 @@ it('should show example', inject(
### Fallback for legacy browsers
For browsers that support the HTML5 history API, `$location` uses the HTML5 history API to write
path and search. If the history API is not supported by a browser, `$location` supplies a Hasbang
path and search. If the history API is not supported by a browser, `$location` supplies a Hashbang
URL. This frees you from having to worry about whether the browser viewing your app supports the
history API or not; the `$location` service makes this transparent to you.
@@ -693,7 +693,7 @@ A path should always begin with forward slash (`/`); the `$location.path()` sett
forward slash if it is missing.
Note that the `!` prefix in the hashbang mode is not part of `$location.path()`; it is actually
hashPrefix.
`hashPrefix`.
## Crawling your app
+30 -67
View File
@@ -23,9 +23,9 @@ angular.module('myApp', ['ngAria'])...
###Using ngAria
Most of what ngAria does is only visible "under the hood". To see the module in action, once you've
added it as a dependency, you can test a few things:
* Using your favorite element inspector, look for ngAria attributes in your own code.
* Using your favorite element inspector, look for attributes added by ngAria in your own code.
* Test using your keyboard to ensure `tabindex` is used correctly.
* Fire up a screen reader such as VoiceOver to listen for ARIA support.
* Fire up a screen reader such as VoiceOver or NVDA to check for ARIA support.
[Helpful screen reader tips.](http://webaim.org/articles/screenreader_testing/)
##Supported directives
@@ -41,8 +41,8 @@ Currently, ngAria interfaces with the following directives:
<h2 id="ngmodel">ngModel</h2>
Most of ngAria's heavy lifting happens in the {@link ngModel ngModel}
directive. For elements using ngModel, special attention is paid by ngAria if that element also
Much of ngAria's heavy lifting happens in the {@link ngModel ngModel}
directive. For elements using ngModel, special attention is paid by ngAria if that element also
has a role or type of `checkbox`, `radio`, `range` or `textbox`.
For those elements using ngModel, ngAria will dynamically bind and update the following ARIA
@@ -134,10 +134,8 @@ attributes (if they have not been explicitly specified by the developer):
ngAria will also add `tabIndex`, ensuring custom elements with these roles will be reachable from
the keyboard. It is still up to **you** as a developer to **ensure custom controls will be
operable** from the keybard. Think of `ng-click` on a `<div>` or `<md-checkbox>`: you still need
to bind `ng-keypress` to make it fully operable from the keyboard. As a rule, any time you create
a widget involving user interaction, be sure to test it with your keyboard and at least one mobile
and desktop screen reader (preferably more).
accessible**. As a rule, any time you create a widget involving user interaction, be sure to test
it with your keyboard and at least one mobile and desktop screen reader.
<h2 id="ngdisabled">ngDisabled</h2>
@@ -160,7 +158,7 @@ Becomes:
```
>You can check whether a control is legitimately disabled for a screen reader by visiting
[chrome://accessibility](chrome://accessibility).
[chrome://accessibility](chrome://accessibility) and inspecting [the accessibility tree](http://www.paciellogroup.com/blog/2015/01/the-browser-accessibility-tree/).
<h2 id="ngshow">ngShow</h2>
@@ -210,16 +208,25 @@ The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redun
`display: none`. See explanation for {@link guide/accessibility#ngshow ngShow} when overriding the default CSS.
<h2><span id="ngclick">ngClick</span> and <span id="ngdblclick">ngDblclick</span></h2>
If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` if it isn't there
already.
If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` to any element not in
a node blacklist:
To fix widespread accessibility problems with `ng-click` on div elements, ngAria will dynamically
bind keypress by default as long as the element isn't an anchor, button, input or textarea.
You can turn this functionality on or off with the `bindKeypress` configuration option. ngAria
will also add the `button` role to communicate to users of assistive technologies.
* Button
* Anchor
* Input
* Textarea
* Select
* Details/Summary
For `ng-dblclick`, you must still manually add `ng-keypress` and role to non-interactive elements such
as `div` or `taco-button` to enable keyboard access.
To fix widespread accessibility problems with `ng-click` on `div` elements, ngAria will
dynamically bind a keypress event by default as long as the element isn't in the node blacklist.
You can turn this functionality on or off with the `bindKeypress` configuration option.
ngAria will also add the `button` role to communicate to users of assistive technologies. This can
be disabled with the `bindRoleForClick` configuration option.
For `ng-dblclick`, you must still manually add `ng-keypress` and a role to non-interactive elements
such as `div` or `taco-button` to enable keyboard access.
<h3>Example</h3>
```html
@@ -260,62 +267,18 @@ The attribute magic of ngAria may not work for every scenario. To disable indivi
you can use the {@link ngAria.$ariaProvider#config config} method. Just keep in mind this will
tell ngAria to ignore the attribute globally.
<example module="ngAria_ngDisabledExample" deps="angular-aria.js">
<example module="ngAria_ngClickExample" deps="angular-aria.js">
<file name="index.html">
<style>
[role=checkbox] {
cursor: pointer;
display: inline-block;
}
[role=checkbox] .icon:before {
content: '\2610';
display: inline-block;
font-size: 2em;
line-height: 1;
vertical-align: middle;
speak: none;
}
[role=checkbox].active .icon:before {
content: '\2611';
}
</style>
<form ng-controller="formsController">
<div ng-model="someModel" show-attrs>
Div with ngModel and aria-invalid disabled
<div ng-click="someFunction" show-attrs>
&lt;div&gt; with ng-click and bindRoleForClick, tabindex set to false
</div>
<div role="checkbox" ng-model="checked" ng-class="{active: checked}"
aria-label="Custom Checkbox" ng-click="toggleCheckbox()" some-checkbox show-attrs>
<span class="icon" aria-hidden="true"></span>
Custom Checkbox for comparison
</div>
</form>
<script>
angular.module('ngAria_ngDisabledExample', ['ngAria'], function config($ariaProvider) {
angular.module('ngAria_ngClickExample', ['ngAria'], function config($ariaProvider) {
$ariaProvider.config({
ariaInvalid: false,
tabindex: true
bindRoleForClick: false,
tabindex: false
});
})
.controller('formsController', function($scope){
$scope.checked = false;
$scope.toggleCheckbox = function(){
$scope.checked = !$scope.checked;
}
})
.directive('someCheckbox', function(){
return {
restrict: 'A',
link: function($scope, $el, $attrs) {
$el.on('keypress', function(event){
event.preventDefault();
if(event.keyCode === 32 || event.keyCode === 13){
$scope.toggleCheckbox();
$scope.$apply();
}
});
}
}
})
.directive('showAttrs', function() {
return function(scope, el, attrs) {
var pre = document.createElement('pre');
+18 -18
View File
@@ -8,22 +8,22 @@
This section briefly touches on all of the important parts of AngularJS using a simple example.
For a more in-depth explanation, see the {@link tutorial/ tutorial}.
| Concept | Description |
|------------------|------------------------------------------|
|{@link concepts#template Template} | HTML with additional markup |
|{@link concepts#directive Directives} | extend HTML with custom attributes and elements |
|{@link concepts#model Model} | the data shown to the user in the view and with which the user interacts |
|{@link concepts#scope Scope} | context where the model is stored so that controllers, directives and expressions can access it |
|{@link concepts#expression Expressions} | access variables and functions from the scope |
|{@link concepts#compiler Compiler} | parses the template and instantiates directives and expressions |
|{@link concepts#filter Filter} | formats the value of an expression for display to the user |
|{@link concepts#view View} | what the user sees (the DOM) |
|{@link concepts#databinding Data Binding} | sync data between the model and the view |
|{@link concepts#controller Controller} | the business logic behind views |
|{@link concepts#di Dependency Injection} | Creates and wires objects and functions |
|{@link concepts#injector Injector} | dependency injection container |
|{@link concepts#module Module} | a container for the different parts of an app including controllers, services, filters, directives which configures the Injector |
|{@link concepts#service Service} | reusable business logic independent of views |
| Concept | Description |
|--------------------------------------------|--------------------------------------------------------------------------|
|{@link concepts#template Template} | HTML with additional markup |
|{@link concepts#directive Directives} | extend HTML with custom attributes and elements |
|{@link concepts#model Model} | the data shown to the user in the view and with which the user interacts |
|{@link concepts#scope Scope} | context where the model is stored so that controllers, directives and expressions can access it |
|{@link concepts#expression Expressions} | access variables and functions from the scope |
|{@link concepts#compiler Compiler} | parses the template and instantiates directives and expressions |
|{@link concepts#filter Filter} | formats the value of an expression for display to the user |
|{@link concepts#view View} | what the user sees (the DOM) |
|{@link concepts#databinding Data Binding} | sync data between the model and the view |
|{@link concepts#controller Controller} | the business logic behind views |
|{@link concepts#di Dependency Injection} | Creates and wires objects and functions |
|{@link concepts#injector Injector} | dependency injection container |
|{@link concepts#module Module} | a container for the different parts of an app including controllers, services, filters, directives which configures the Injector |
|{@link concepts#service Service} | reusable business logic independent of views |
## A first example: Data binding
@@ -57,7 +57,7 @@ Try out the Live Preview above, and then let's walk through the example and desc
This looks like normal HTML, with some new markup. In Angular, a file like this is called a
<a name="template">{@link templates template}</a>. When Angular starts your application, it parses and
processes this new markup from the template using the <a name="compiler">{@link compiler compiler}</a>.
The loaded, transformed and rendered DOM is then called the <a name="view">view</a>.
The loaded, transformed and rendered DOM is then called the <a name="view"></a>*view*.
The first kind of new markup are the <a name="directive">{@link directive directives}</a>.
They apply special behavior to attributes or elements in the HTML. In the example above we use the
@@ -79,7 +79,7 @@ An <a name="expression">{@link expression expression}</a> in a template is a Jav
to read and write variables. Note that those variables are not global variables.
Just like variables in a JavaScript function live in a scope,
Angular provides a <a name="scope">{@link scope scope}</a> for the variables accessible to expressions.
The values that are stored in variables on the scope are referred to as the <a name="model">model</a>
The values that are stored in variables on the scope are referred to as the <a name="model"></a>*model*
in the rest of the documentation.
Applied to the example above, the markup directs Angular to "take the data we got from the input widgets
and multiply them together".
+9 -6
View File
@@ -5,13 +5,16 @@
# Understanding Controllers
In Angular, a Controller is a JavaScript **constructor function** that is used to augment the
In Angular, a Controller is defined by a JavaScript **constructor function** that is used to augment the
{@link scope Angular Scope}.
When a Controller is attached to the DOM via the {@link ng.directive:ngController ng-controller}
directive, Angular will instantiate a new Controller object, using the specified Controller's
**constructor function**. A new **child scope** will be available as an injectable parameter to the
Controller's constructor function as `$scope`.
**constructor function**. A new **child scope** will be created and made available as an injectable
parameter to the Controller's constructor function as `$scope`.
If the controller has been attached using the `controller as` syntax then the controller instance will
be assigned to a property on the new scope.
Use controllers to:
@@ -106,7 +109,7 @@ needed for a single view.
The most common way to keep Controllers slim is by encapsulating work that doesn't belong to
controllers into services and then using these services in Controllers via dependency injection.
This is discussed in the {@link di Dependency Injection} {@link services
This is discussed in the {@link di Dependency Injection} and {@link services
Services} sections of this guide.
@@ -162,7 +165,7 @@ scope is augmented (managed) by the `SpicyController` Controller.
starts with capital letter and ends with "Controller".
- Assigning a property to `$scope` creates or updates the model.
- Controller methods can be created through direct assignment to scope (see the `chiliSpicy` method)
- The Controller methods and properties are available in the template (for the `<div>` element and
- The Controller methods and properties are available in the template (for both the `<div>` element and
its children).
## Spicy Arguments Example
@@ -302,7 +305,7 @@ describe('myController function', function() {
```
If you need to test a nested Controller you need to create the same scope hierarchy
If you need to test a nested Controller you must create the same scope hierarchy
in your test that exists in the DOM:
```js
+3 -3
View File
@@ -163,8 +163,8 @@ someModule.controller('MyController', function($scope, greeter) {
});
```
Given a function the injector can infer the names of the services to inject by examining the
function declaration and extracting the parameter names. In the above example `$scope`, and
Given a function, the injector can infer the names of the services to inject by examining the
function declaration and extracting the parameter names. In the above example, `$scope` and
`greeter` are two services which need to be injected into the function.
One advantage of this approach is that there's no array of names to keep in sync with the
@@ -293,7 +293,7 @@ Create a new injector that can provide components defined in our `myModule` modu
`greeter` service from the injector. (This is usually done automatically by angular bootstrap).
```js
var injector = angular.injector(['myModule', 'ng']);
var injector = angular.injector(['ng', 'myModule']);
var greeter = injector.get('greeter');
```
+17 -6
View File
@@ -19,8 +19,9 @@ how to implement them.
## What are Directives?
At a high level, directives are markers on a DOM element (such as an attribute, element
name, comment or CSS class) that tell AngularJS's **HTML compiler** ({@link ng.$compile `$compile`}) to
attach a specified behavior to that DOM element or even transform the DOM element and its children.
name, comment or CSS class) that tell AngularJS's **HTML compiler** ({@link ng.$compile `$compile`})
to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform
the DOM element and its children.
Angular comes with a set of these directives built-in, like `ngBind`, `ngModel`, and `ngClass`.
Much like you create controllers and services, you can create your own directives for Angular to use.
@@ -30,7 +31,7 @@ When Angular {@link guide/bootstrap bootstraps} your application, the
<div class="alert alert-info">
**What does it mean to "compile" an HTML template?**
For AngularJS, "compilation" means attaching event listeners to the HTML to make it interactive.
For AngularJS, "compilation" means attaching directives to the HTML to make it interactive.
The reason we use the term "compile" is that the recursive process of attaching directives
mirrors the process of compiling source code in
[compiled programming languages](http://en.wikipedia.org/wiki/Compiled_languages).
@@ -42,16 +43,26 @@ mirrors the process of compiling source code in
Before we can write a directive, we need to know how Angular's {@link guide/compiler HTML compiler}
determines when to use a given directive.
In the following example, we say that the `<input>` element **matches** the `ngModel` directive.
Similar to the terminology used when an [element **matches** a selector]
(https://developer.mozilla.org/en-US/docs/Web/API/Element.matches), we say an element **matches** a
directive when the directive is part of its declaration.
In the following example, we say that the `<input>` element **matches** the `ngModel` directive
```html
<input ng-model="foo">
```
The following also **matches** `ngModel`:
The following `<input>` element also **matches** `ngModel`:
```html
<input data-ng:model="foo">
<input data-ng-model="foo">
```
And the following <person> element **matches** the `person` directive:
```html
<person>{{name}}</person>
```
### Normalization
+17 -11
View File
@@ -28,13 +28,13 @@ Angular expressions are like JavaScript expressions with the following differenc
* **No Control Flow Statements:** You cannot use the following in an Angular expression:
conditionals, loops, or exceptions.
* **No Function Declarations:** You cannot declare functions in an Angular expression,
even inside `ng-init` directive.
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
in an Angular expression.
* **No Comma And Void Operators:** You cannot use `,` or `void` in an Angular expression.
* **Filters:** You can use {@link guide/filter filters} within expressions to format data before
@@ -70,7 +70,7 @@ You can try evaluating different expressions here:
<ul>
<li ng-repeat="expr in exprs track by $index">
[ <a href="" ng-click="removeExp($index)">X</a> ]
<tt>{{expr}}</tt> => <span ng-bind="$parent.$eval(expr)"></span>
<code>{{expr}}</code> => <span ng-bind="$parent.$eval(expr)"></span>
</li>
</ul>
</div>
@@ -141,6 +141,9 @@ provide mockable access to globals.
}
element(by.css('[ng-click="greet()"]')).click();
// We need to give the browser time to display the alert
browser.wait(protractor.ExpectedConditions.alertIsPresent(), 1000);
var alertDialog = browser.switchTo().alert();
expect(alertDialog.getText()).toEqual('Hello World');
@@ -175,7 +178,7 @@ expression, delegate to a JavaScript method instead.
## No function declarations or RegExp creation with literal notation
You can't declare functions or create regular expressions from within AngularJS expressions. This is
to avoid complex model transformation logic inside templates. Such logic is better placed in a
to avoid complex model transformation logic inside templates. Such logic is better placed in a
controller or in a dedicated filter where it can be tested properly.
## `$event`
@@ -303,19 +306,23 @@ then the expression is not fulfilled and will remain watched.
keep dirty-checking the watch in the future digest loops by following the same
algorithm starting from step 1
#### Special case for object literals
Unlike simple values, object-literals are watched until every key is defined.
See http://www.bennadel.com/blog/2760-one-time-data-bindings-for-object-literal-expressions-in-angularjs-1-3.htm
### How to benefit from one-time binding
If the expression will not change once set, it is a candidate for one-time binding.
If the expression will not change once set, it is a candidate for one-time binding.
Here are three example cases.
When interpolating text or attributes:
```html
<div name="attr: {{::color}}">text: {{::name}}</div>
<div name="attr: {{::color}}">text: {{::name | uppercase}}</div>
```
When using a directive with bidirectional binding and the parameters will not change:
When using a directive with bidirectional binding and parameters that will not change:
```js
someModule.directive('someDirective', function() {
@@ -338,7 +345,6 @@ When using a directive that takes an expression:
```html
<ul>
<li ng-repeat="item in ::items">{{item.name}};</li>
<li ng-repeat="item in ::items | orderBy:'name'">{{item.name}};</li>
</ul>
```
+6 -4
View File
@@ -33,7 +33,7 @@ for other directives to augment its behavior.
<input type="button" ng-click="reset()" value="Reset" />
<input type="submit" ng-click="update(user)" value="Save" />
</form>
<pre>form = {{user | json}}</pre>
<pre>user = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
@@ -95,6 +95,8 @@ and failing to satisfy its validity.
<input type="button" ng-click="reset()" value="Reset" />
<input type="submit" ng-click="update(user)" value="Save" />
</form>
<pre>user = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<style type="text/css">
@@ -183,6 +185,8 @@ didn't interact with a control
<input type="button" ng-click="reset(form)" value="Reset" />
<input type="submit" ng-click="update(user)" value="Save" />
</form>
<pre>user = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
</file>
@@ -491,9 +495,7 @@ The following example shows how to add two-way data-binding to contentEditable e
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.on('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
ctrl.$setViewValue(elm.html());
});
// model -> view
+91 -5
View File
@@ -156,8 +156,94 @@ The syntax extension is based on a subset of the ICU MessageFormat syntax that c
gender selections. Please refer to the links in the “Further Reading” section at the bottom of this
section.
You may find it helpful to play with our [Plnkr Example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview)
as you read the examples below.
You may find it helpful to play with the following example as you read the explanations below:
<example name="message-format-example" module="messageFormatExample" deps="angular-message-format.js">
<file name="index.html">
<div ng-controller="ckCtrl">
<b>Set number of recipients</b>
<button ng-click="setNumRecipients(0)">None</button>
<button ng-click="setNumRecipients(1)">One</button>
<button ng-click="setNumRecipients(2)">Two</button>
<button ng-click="setNumRecipients(3)">Three</button>
<br><br>
<b>Sender's</b> name: <input ng-model="sender.name"> &nbsp;&nbsp;
<br><br><b>Recipients</b><br>
<div ng-repeat="recipient in recipients">
Name: <input ng-model="recipient.name"> &nbsp;&nbsp;
Gender: <button ng-click="setGender(recipient, 'male')">male</button>
<button ng-click="setGender(recipient, 'female')">female</button>
<button ng-click="setGender(recipient, 'other')">other</button>
</div>
<br><br><b>Message</b><br>
{{recipients.length, plural, offset:1
=0 {You ({{sender.name}}) gave no gifts}
=1 { {{ recipients[0].gender, select,
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) a gift.}
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) a gift.}
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) a gift.}
}}
}
one { {{ recipients[0].gender, select,
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) and one other person a gift.}
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) and one other person a gift.}
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) and one other person a gift.}
}}
}
other {You ({{sender.name}}) gave {{recipients.length}} people gifts. }
}}
<br><br><b>In an attribute</b><br>
<div attrib="{{recipients.length, plural, offset:1
=0 {You ({{sender.name}}) gave no gifts}
=1 { {{ recipients[0].gender, select,
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) a gift.}
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) a gift.}
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) a gift.}
}}
}
one { {{ recipients[0].gender, select,
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) and one other person a gift.}
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) and one other person a gift.}
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) and one other person a gift.}
}}
}
other {You ({{sender.name}}) gave {{recipients.length}} people gifts. }
}}">
This div has an attribute interpolated with messageformat. Use the DOM inspector to check it out.
</div>
</div>
</file>
<file name="app.js">
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
angular.module('messageFormatExample', ['ngMessageFormat'])
.controller('ckCtrl', function ($scope, $injector, $parse) {
var people = [ new Person("Alice", "female"),
new Person("Bob", "male"),
new Person("Charlie", "male") ];
$scope.sender = new Person("Harry Potter", "male");
$scope.recipients = people.slice();
$scope.setNumRecipients = function(n) {
n = n > people.length ? people.length : n;
$scope.recipients = people.slice(0, n);
};
$scope.setGender = function(person, gender) {
person.gender = gender;
};
});
</file>
</example>
### Plural Syntax
@@ -305,7 +391,7 @@ matching is **case-sensitive**.
#### Selection Keywords
Selection keywords are simple words like "male" and "female". The keyword, "other", and it's
Selection keywords are simple words like "male" and "female". The keyword, "other", and its
corresponding message are required while others are optional. It is used when the Angular
expression does not match (case-insensitively) any of the other keywords specified.
@@ -333,9 +419,9 @@ allows you to nest plural and gender expressions in any order.
Please note that if these are intended to reach a translator and be translated, it is recommended
that the messages appear as a whole and not be split up.
### More complex example that demonstrates nesting
### Demonstration of nesting
This is taken from the [plunker example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview) linked to earlier.
This is taken from the above example.
```text
{{recipients.length, plural, offset:1
+1 -1
View File
@@ -53,7 +53,7 @@ In Angular applications, you move the job of filling page templates with data fr
## Specific Topics
* **Login: **[Google example](https://developers.google.com/+/photohunt/python), [AngularJS Faceb0ok library](https://github.com/pc035860/angular-easyfb), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
* **Login: **[Google example](https://developers.google.com/+/photohunt/python), [AngularJS Facebook library](https://github.com/pc035860/angular-easyfb), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
* **Mobile:** [Angular on Mobile Guide](http://www.ng-newsletter.com/posts/angular-on-mobile.html), [PhoneGap](http://devgirl.org/2013/06/10/quick-start-guide-phonegap-and-angularjs/)
* **Other Languages:** [CoffeeScript](http://www.coffeescriptlove.com/2013/08/angularjs-and-coffeescript-tutorials.html), [Dart](https://github.com/angular/angular.dart.tutorial/wiki)
* **Realtime: **[Socket.io](http://www.creativebloq.com/javascript/angularjs-collaboration-board-socketio-2132885), [OmniBinder](https://github.com/jeffbcross/omnibinder)
+40 -6
View File
@@ -43,7 +43,7 @@ Animations in 1.4 have been refactored internally, but the API has stayed much t
some breaking changes that need to be addressed when upgrading to 1.4.
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
JavaSript and CSS animations can no longer be run in
JavaScript and CSS animations can no longer be run in
parallel. With earlier versions of ngAnimate, both CSS and JS animations
would be run together when multiple animations were detected. This
feature has been removed, however, the same effect, with even more
@@ -88,10 +88,10 @@ element.on('$animate:before', function(e, data) {
element.off('$animate:before', fn);
// 1.4+
$animate.on(element, 'enter', function(data) {
$animate.on('enter', element, function(data) {
//...
});
$animate.off(element, 'enter', fn);
$animate.off('enter', element, fn);
```
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
@@ -136,7 +136,7 @@ class based animations (animations triggered via ngClass) in order to ensure tha
## Forms (`ngMessages`, `ngOptions`)
## Forms (`ngMessages`, `ngOptions`, `select`)
### ngMessages
The ngMessages module has also been subject to an internal refactor to allow it to be more flexible
@@ -178,8 +178,8 @@ have been fixed. The breaking changes are comparatively minor and should not aff
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
when `ngOptions` renders the option values within the DOM, the resulting HTML code is different.
Normally this should not affect your application at all, however, if your code relies on inspecting
the value property of `<option>` elements (that `ngOptions` generates) then be sure to [read the details]
(https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef).
the value property of `<option>` elements (that `ngOptions` generates) then be sure
to [read the details](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef).
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
when iterating over an object's properties using the `(key, value) in obj` syntax
@@ -190,6 +190,37 @@ in the order they are returned by Object.keys(obj), which is almost always the o
in which the properties were defined.
### select
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
the `select` directive will now use strict comparison of the `ngModel` scope value against `option`
values to determine which option is selected. This means non-string scope values (such as `Number` or `Boolean`)
will not be matched against equivalent option strings (such as the strings `"123"`, `"true"` or `"false"`).
In Angular 1.3.x, setting `scope.x = 200` would select the option with the value 200 in the following `select`:
```
<select ng-model="x">
<option value="100">100</option>
<option value="200">200</option>
</select>
```
In Angular 1.4.x, the 'unknown option' will be selected.
To remedy this, you can initialize the model as a string: `scope.x = '200'`, or if you want to
keep the model as a `Number`, you can do the conversion via `$formatters` and `$parsers` on `ngModel`:
```js
ngModelCtrl.$parsers.push(function(value) {
return parseInt(value, 10); // Convert option value to number
});
ngModelCtrl.$formatters.push(function(value) {
return value.toString(); // Convert scope value to string
});
```
## Templating (`ngRepeat`, `$compile`)
### ngRepeat
@@ -217,6 +248,9 @@ Due to [6a38dbfd](https://github.com/angular/angular.js/commit/6a38dbfd3c34c8f9e
previously, '&' expressions would always set up a function in the isolate scope. Now, if the binding
is marked as optional and the attribute is not specified, no function will be added to the isolate scope.
Due to [62d514b](https://github.com/angular/angular.js/commit/62d514b06937cc7dd86e973ea11165c88343b42d),
returning an object from a controller constructor function will now override the scope. Views that use the
controllerAs method will no longer get the this reference, but the returned object.
## Cookies (`ngCookies`)
+2 -2
View File
@@ -76,7 +76,7 @@ that you break your application to multiple modules like this:
initialization code.
We've also
[written a document](http://blog.angularjs.org/2014/02/an-angularjs-style-guide-and-best.html)
[written a document](http://angularjs.blogspot.com/2014/02/an-angularjs-style-guide-and-best.html)
on how we organize large apps at Google.
The above is a suggestion. Tailor it to your needs.
@@ -140,7 +140,7 @@ The above is a suggestion. Tailor it to your needs.
# Module Loading & Dependencies
A module is a collection of configuration and run blocks which get applied to the application
during the bootstrap process. In its simplest form the module consist of a collection of two kinds
during the bootstrap process. In its simplest form the module consists of a collection of two kinds
of blocks:
1. **Configuration blocks** - get executed during the provider registrations and configuration
+1 -1
View File
@@ -5,7 +5,7 @@
# What are Scopes?
{@link ng.$rootScope.Scope scope} is an object that refers to the application
{@link ng.$rootScope.Scope Scope} is an object that refers to the application
model. It is an execution context for {@link expression expressions}. Scopes are
arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can
watch {@link guide/expression expressions} and propagate events.
+1 -1
View File
@@ -39,7 +39,7 @@ In general, we recommend against this because it can create unintended XSS vecto
However, it's ok to mix server-side templating in the bootstrap template (`index.html`) as long
as user input cannot be used on the server to output html that would then be processed by Angular
in a way that would cause allow for arbitrary code execution.
in a way that would allow for arbitrary code execution.
For instance, you can use server-side templating to dynamically generate CSS, URLs, etc, but not
for generating templates that are bootstrapped/compiled by Angular.
+3 -1
View File
@@ -261,8 +261,10 @@ myModule.filter('length', function() {
describe('length filter', function() {
var $filter;
beforeEach(inject(function(_$filter_){
$filter= _$filter_;
$filter = _$filter_;
}));
it('returns 0 when given null', function() {
+2 -2
View File
@@ -15,14 +15,14 @@ development.
production.
To point your code to an angular script on the Google CDN server, use the following template. This
example points to the minified version 1.3.14:
example points to the minified version 1.4.5:
```
<!doctype html>
<html ng-app>
<head>
<title>My Angular App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
</head>
<body>
</body>
+10 -4
View File
@@ -86,9 +86,15 @@ Yes. See instructions in {@link downloading}.
### What browsers does Angular work with?
We run our extensive test suite against the following browsers: Safari, Chrome, Firefox, Opera 15,
IE9 and mobile browsers (Android, Chrome Mobile, iOS Safari). See {@link guide/ie Internet
Explorer Compatibility} for more details on supporting legacy IE browsers.
We run our extensive test suite against the following browsers: the latest versions of Chrome,
Firefox, Safari, and Safari for iOs, as well as Internet Explorer versions 9-11. See {@link guide/ie
Internet Explorer Compatibility} for more details on supporting legacy IE browsers.
If a browser is untested, it doesn't mean it won't work; for example, older Android (2.3.x)
is supported in the sense that we avoid the dot notation for reserved words as property names,
but we don't actively test changes against it. You can also expect browsers to work that share
a large part of their codebase with a browser we test, such as Opera > version 12
(uses the Blink engine), or the various Firefox derivatives.
### What's Angular's performance like?
@@ -194,7 +200,7 @@ Conditionally showing and hiding things using jQuery is a common pattern in othe
`ng-show` (and `ng-hide`) conditionally show and hide elements based on boolean expressions.
Describe the conditions for showing and hiding an element in terms of `$scope` variables:
<div ng-show="!loggedIn">Click <a href="#/login">here</a> to log in</div>
<div ng-show="!loggedIn"><a href="#/login">Click here to log in</a></div>
Note also the counterpart `ng-hide` and similar `ng-disabled`.
Note especially the powerful `ng-switch` that should be used instead of several mutually exclusive `ng-show`s.
+4 -2
View File
@@ -129,7 +129,8 @@ Once you have Node.js installed on your machine you can download the tool depend
npm install
```
This command will download the following tools, into the `node_modules` directory:
This command reads angular-phonecat's `package.json` file and downloads the following tools
into the `node_modules` directory:
- [Bower][bower] - client-side code package manager
- [Http-Server][http-server] - simple local static web server
@@ -198,7 +199,7 @@ http://localhost:8000/app/index.html
<div class="alert alert-info">
To serve the web app on a different ip address or port, edit the "start" script within package.json.
You can `-a` to set the address and `-p` to set the port.
You can use `-a` to set the address and `-p` to set the port.
</div>
### Running Unit Tests
@@ -270,6 +271,7 @@ It is good to run the end to end tests whenever you make changes to the HTML vie
that the application as a whole is executing correctly. It is very common to run End to End tests
before pushing a new commit of changes to a remote repository.
Now that you have set up your local machine, let's get started with the tutorial: {@link step_00 Step 0 - Bootstrapping}
[git]: http://git-scm.com/
[node]: http://nodejs.org/
+13 -13
View File
@@ -31,7 +31,7 @@ npm install
To see the app running in a browser, open a *separate* terminal/command line tab or window, then
run `npm start` to start the web server. Now, open a browser window for the app and navigate to
<a href="http://localhost:8000/app/" target="_blank">`http://localhost:8000/app/`</a>
<a href="http://localhost:8000/app/" target="_blank" title="Open app on localhost">`http://localhost:8000/app/`</a>
Note that if you already ran the master branch app prior to checking out step-0, you may see the cached
master version of the app in your browser window at this point. Just hit refresh to re-load the page.
@@ -91,22 +91,22 @@ being the element on which the `ngApp` directive was defined.
Nothing here {{'yet' + '!'}}
This line demonstrates two core features of Angular's templating capabilities:
This line demonstrates two core features of Angular's templating capabilities:
* a binding, denoted by double-curlies `{{ }}`
* a simple expression `'yet' + '!'` used in this binding.
* a binding, denoted by double-curlies `{{ }}`
* a simple expression `'yet' + '!'` used in this binding.
The binding tells Angular that it should evaluate an expression and insert the result into the
DOM in place of the binding. Rather than a one-time insert, as we'll see in the next steps, a
binding will result in efficient continuous updates whenever the result of the expression
evaluation changes.
The binding tells Angular that it should evaluate an expression and insert the result into the
DOM in place of the binding. Rather than a one-time insert, as we'll see in the next steps, a
binding will result in efficient continuous updates whenever the result of the expression
evaluation changes.
{@link guide/expression Angular expression} is a JavaScript-like code snippet that is
evaluated by Angular in the context of the current model scope, rather than within the scope of
the global context (`window`).
{@link guide/expression Angular expression} is a JavaScript-like code snippet that is
evaluated by Angular in the context of the current model scope, rather than within the scope of
the global context (`window`).
As expected, once this template is processed by Angular, the html page contains the text:
"Nothing here yet!".
As expected, once this template is processed by Angular, the html page contains the text:
"Nothing here yet!".
## Bootstrapping AngularJS apps
+1 -1
View File
@@ -75,7 +75,7 @@ __`test/e2e/scenarios.js`__:
query.sendKeys('nexus');
element.all(by.css('.phones li a')).first().click();
browser.getLocationAbsUrl().then(function(url) {
expect(url.split('#')[1]).toBe('/phones/nexus-s');
expect(url).toBe('/phones/nexus-s');
});
});
...
+7 -7
View File
@@ -33,17 +33,17 @@ We are using [Bower][bower] to install client-side dependencies. This step upda
"license": "MIT",
"private": true,
"dependencies": {
"angular": "~1.3.0",
"angular-mocks": "~1.3.0",
"jquery": "2.1.1",
"angular": "1.4.x",
"angular-mocks": "1.4.x",
"jquery": "~2.1.1",
"bootstrap": "~3.1.1",
"angular-route": "~1.3.0"
"angular-route": "~1.4.0"
}
}
```
The new dependency `"angular-route": "~1.3.0"` tells bower to install a version of the
angular-route component that is compatible with version 1.3.x. We must tell bower to download
The new dependency `"angular-route": "~1.4.0"` tells bower to install a version of the
angular-route component that is compatible with version 1.4.x. We must tell bower to download
and install this dependency.
If you have bower installed globally, then you can run `bower install` but for this project, we have
@@ -313,7 +313,7 @@ to various URLs and verify that the correct view was rendered.
it('should redirect index.html to index.html#/phones', function() {
browser.get('app/index.html');
browser.getLocationAbsUrl().then(function(url) {
expect(url.split('#')[1]).toBe('/phones');
expect(url).toEqual('/phones');
});
});
+3 -2
View File
@@ -21,6 +21,7 @@ var outputFolder = '../build/docs';
var bowerFolder = 'bower_components';
var src = 'app/src/**/*.js';
var ignoredFiles = '!src/angular.bind.js';
var assets = 'app/assets/**/*';
@@ -50,7 +51,7 @@ gulp.task('build-app', function() {
var minFile = 'docs.min.js';
var folder = outputFolder + '/js/';
return gulp.src(src)
return gulp.src([src, ignoredFiles])
.pipe(sourcemaps.init())
.pipe(concat(file))
.pipe(gulp.dest(folder))
@@ -107,5 +108,5 @@ gulp.task('jshint', ['doc-gen'], function() {
gulp.task('default', ['assets', 'doc-gen', 'build-app', 'jshint']);
gulp.task('watch', function() {
gulp.watch([src, assets], ['assets', 'build-app']);
gulp.watch([src, ignoredFiles, assets], ['assets', 'build-app']);
});
+5 -2
View File
@@ -303,8 +303,8 @@ goog.i18n.currency.CurrencyInfo = {
'KRW': [0, '\u20A9', 'KR₩'],
'LKR': [2, 'Rs', 'SLRs'],
'LTL': [2, 'Lt', 'Lt'],
'LVL': [2, 'Ls', 'Ls'],
'MNT': [0, '\u20AE', 'MN₮'],
'MVR': [2, 'Rf', 'MVR'],
'MXN': [2, '$', 'Mex$'],
'MYR': [2, 'RM', 'RM'],
'NOK': [50, 'kr', 'NOkr'],
@@ -339,6 +339,7 @@ goog.i18n.currency.CurrencyInfo = {
goog.i18n.currency.CurrencyInfoTier2 = {
'AFN': [48, 'Af.', 'AFN'],
'AMD': [0, 'Dram', 'dram'],
'ANG': [2, 'NAf.', 'ANG'],
'AOA': [2, 'Kz', 'Kz'],
'ARS': [2, '$', 'AR$'],
'AWG': [2, 'Afl.', 'Afl.'],
@@ -414,6 +415,7 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'SLL': [0, 'SLL', 'SLL'],
'SOS': [0, 'SOS', 'SOS'],
'SRD': [2, '$', 'SR$'],
'SSP': [2, '£', 'SSP'],
'STD': [0, 'Db', 'Db'],
'SYP': [0, '£', 'SY£'],
'SZL': [2, 'SZL', 'SZL'],
@@ -430,5 +432,6 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'XCD': [2, '$', 'EC$'],
'XOF': [0, 'CFA', 'CFA'],
'XPF': [0, 'FCFP', 'FCFP'],
'ZMK': [0, 'ZMK', 'ZMK']
'ZMW': [0, 'ZMW', 'ZMW'],
'ZWD': [0, '$', 'Z$']
};
+305 -54
View File
@@ -17,7 +17,7 @@
*
* This file is autogenerated by script. See
* http://go/generate_datetime_constants.py using --for_closure
* File generated from CLDR ver. 26
* File generated from CLDR ver. 27.0.1
*
* To reduce the file size (which may cause issues in some JS
* developing environments), this file will only contain locales
@@ -36,9 +36,11 @@ goog.provide('goog.i18n.DateTimeSymbols_af');
goog.provide('goog.i18n.DateTimeSymbols_am');
goog.provide('goog.i18n.DateTimeSymbols_ar');
goog.provide('goog.i18n.DateTimeSymbols_az');
goog.provide('goog.i18n.DateTimeSymbols_be');
goog.provide('goog.i18n.DateTimeSymbols_bg');
goog.provide('goog.i18n.DateTimeSymbols_bn');
goog.provide('goog.i18n.DateTimeSymbols_br');
goog.provide('goog.i18n.DateTimeSymbols_bs');
goog.provide('goog.i18n.DateTimeSymbols_ca');
goog.provide('goog.i18n.DateTimeSymbols_chr');
goog.provide('goog.i18n.DateTimeSymbols_cs');
@@ -50,6 +52,7 @@ goog.provide('goog.i18n.DateTimeSymbols_de_CH');
goog.provide('goog.i18n.DateTimeSymbols_el');
goog.provide('goog.i18n.DateTimeSymbols_en');
goog.provide('goog.i18n.DateTimeSymbols_en_AU');
goog.provide('goog.i18n.DateTimeSymbols_en_CA');
goog.provide('goog.i18n.DateTimeSymbols_en_GB');
goog.provide('goog.i18n.DateTimeSymbols_en_IE');
goog.provide('goog.i18n.DateTimeSymbols_en_IN');
@@ -60,6 +63,8 @@ goog.provide('goog.i18n.DateTimeSymbols_en_ZA');
goog.provide('goog.i18n.DateTimeSymbols_es');
goog.provide('goog.i18n.DateTimeSymbols_es_419');
goog.provide('goog.i18n.DateTimeSymbols_es_ES');
goog.provide('goog.i18n.DateTimeSymbols_es_MX');
goog.provide('goog.i18n.DateTimeSymbols_es_US');
goog.provide('goog.i18n.DateTimeSymbols_et');
goog.provide('goog.i18n.DateTimeSymbols_eu');
goog.provide('goog.i18n.DateTimeSymbols_fa');
@@ -118,6 +123,7 @@ goog.provide('goog.i18n.DateTimeSymbols_sk');
goog.provide('goog.i18n.DateTimeSymbols_sl');
goog.provide('goog.i18n.DateTimeSymbols_sq');
goog.provide('goog.i18n.DateTimeSymbols_sr');
goog.provide('goog.i18n.DateTimeSymbols_sr_Latn');
goog.provide('goog.i18n.DateTimeSymbols_sv');
goog.provide('goog.i18n.DateTimeSymbols_sw');
goog.provide('goog.i18n.DateTimeSymbols_ta');
@@ -343,6 +349,52 @@ goog.i18n.DateTimeSymbols_az = {
};
/**
* Date/time formatting symbols for locale be.
*/
goog.i18n.DateTimeSymbols_be = {
ERAS: ['да н.э.', 'н.э.'],
ERANAMES: ['да н.э.', 'н.э.'],
NARROWMONTHS: ['с', 'л', 'с', 'к', 'м', 'ч', 'л', 'ж', 'в', 'к',
'л', 'с'],
STANDALONENARROWMONTHS: ['с', 'л', 'с', 'к', 'м', 'ч', 'л', 'ж', 'в',
'к', 'л', 'с'],
MONTHS: ['студзеня', 'лютага', 'сакавіка',
'красавіка', 'мая', 'чэрвеня', 'ліпеня',
'жніўня', 'верасня', 'кастрычніка',
'лістапада', 'снежня'],
STANDALONEMONTHS: ['студзень', 'люты', 'сакавік',
'красавік', 'май', 'чэрвень', 'ліпень',
'жнівень', 'верасень', 'кастрычнік',
'лістапад', 'снежань'],
SHORTMONTHS: ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр',
'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
STANDALONESHORTMONTHS: ['сту', 'лют', 'сак', 'кра', 'май',
'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
WEEKDAYS: ['нядзеля', 'панядзелак', 'аўторак',
'серада', 'чацвер', 'пятніца', 'субота'],
STANDALONEWEEKDAYS: ['нядзеля', 'панядзелак',
'аўторак', 'серада', 'чацвер', 'пятніца',
'субота'],
SHORTWEEKDAYS: ['нд', 'пн', 'аў', 'ср', 'чц', 'пт', 'сб'],
STANDALONESHORTWEEKDAYS: ['нд', 'пн', 'аў', 'ср', 'чц', 'пт',
'сб'],
NARROWWEEKDAYS: ['н', 'п', 'а', 'с', 'ч', 'п', 'с'],
STANDALONENARROWWEEKDAYS: ['н', 'п', 'а', 'с', 'ч', 'п', 'с'],
SHORTQUARTERS: ['1-шы кв.', '2-гі кв.', '3-ці кв.',
'4-ты кв.'],
QUARTERS: ['1-шы квартал', '2-гі квартал',
'3-ці квартал', '4-ты квартал'],
AMPMS: ['да палудня', 'пасля палудня'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd.M.y', 'd.M.yy'],
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 6
};
/**
* Date/time formatting symbols for locale bg.
*/
@@ -439,16 +491,10 @@ goog.i18n.DateTimeSymbols_bn = {
NARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ', 'শু', 'শ'],
STANDALONENARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ',
'শু', 'শ'],
SHORTQUARTERS: [
'প্র. ত্রৈ. এক. চতুর্থাংশ',
'দ্বি.ত্রৈ.এক. চতুর্থাংশ',
'তৃ.ত্রৈ.এক.চতুর্থাংশ',
'চ.ত্রৈ.এক চতুর্থাংশ'],
QUARTERS: [
'প্রথম ত্রৈমাসিকের এক চতুর্থাংশ',
'দ্বিতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
'তৃতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
'চতুর্থ ত্রৈমাসিকের এক চতুর্থাংশ'],
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['ত্রৈমাসিক', 'ষাণ্মাসিক',
'তৃতীয় চতুর্থাংশ',
'চতুর্থ ত্রৈমাসিক'],
AMPMS: ['am', 'pm'],
DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
@@ -497,6 +543,44 @@ goog.i18n.DateTimeSymbols_br = {
};
/**
* Date/time formatting symbols for locale bs.
*/
goog.i18n.DateTimeSymbols_bs = {
ERAS: ['p. n. e.', 'n. e.'],
ERANAMES: ['Prije nove ere', 'Nove ere'],
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: ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli',
'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'juni',
'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep',
'okt', 'nov', 'dec'],
STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
'aug', 'sep', 'okt', 'nov', 'dec'],
WEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak',
'petak', 'subota'],
STANDALONEWEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda',
'četvrtak', 'petak', 'subota'],
SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Č', 'P', 'S'],
STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
QUARTERS: ['Prvi kvartal', 'Drugi kvartal', 'Treći kvartal',
'Četvrti kvartal'],
AMPMS: ['prije podne', 'popodne'],
DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd. MMM. y.', 'dd.MM.yy.'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} \'u\' {0}', '{1} \'u\' {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 6
};
/**
* Date/time formatting symbols for locale ca.
*/
@@ -507,8 +591,9 @@ goog.i18n.DateTimeSymbols_ca = {
'NV', 'DS'],
STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
'ST', 'OC', 'NV', 'DS'],
MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
MONTHS: ['de gener', 'de febrer', 'de març', 'dabril', 'de maig',
'de juny', 'de juliol', 'dagost', 'de setembre', 'doctubre',
'de novembre', 'de desembre'],
STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
@@ -609,7 +694,7 @@ goog.i18n.DateTimeSymbols_cs = {
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1. čtvrtletí', '2. čtvrtletí', '3. čtvrtletí',
'4. čtvrtletí'],
AMPMS: ['AM', 'PM'],
AMPMS: ['dopoledne', 'odpoledne'],
DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. M. y', 'dd.MM.yy'],
TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
@@ -684,7 +769,7 @@ goog.i18n.DateTimeSymbols_da = {
SHORTQUARTERS: ['1. kvt.', '2. kvt.', '3. kvt.', '4. kvt.'],
QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'dd/MM/y', 'dd/MM/yy'],
DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd/MM/y'],
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
@@ -758,7 +843,7 @@ goog.i18n.DateTimeSymbols_de_AT = {
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
AMPMS: ['vorm.', 'nachm.'],
DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'dd. MMM y', 'dd.MM.yy'],
DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
FIRSTDAYOFWEEK: 0,
@@ -882,10 +967,47 @@ goog.i18n.DateTimeSymbols_en_AU = {
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['am', 'pm'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/y'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 5
};
/**
* Date/time formatting symbols for locale en_CA.
*/
goog.i18n.DateTimeSymbols_en_CA = {
ERAS: ['BC', 'AD'],
ERANAMES: ['Before Christ', 'Anno Domini'],
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: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
'August', 'September', 'October', 'November', 'December'],
STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'],
SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'],
STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday'],
STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday'],
SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'y-MM-dd'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 5
@@ -919,7 +1041,7 @@ goog.i18n.DateTimeSymbols_en_GB = {
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['am', 'pm'],
AMPMS: ['a.m.', 'p.m.'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
@@ -958,7 +1080,7 @@ goog.i18n.DateTimeSymbols_en_IE = {
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['a.m.', 'p.m.'],
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
@@ -993,7 +1115,7 @@ goog.i18n.DateTimeSymbols_en_IN = {
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['am', 'pm'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
@@ -1030,7 +1152,7 @@ goog.i18n.DateTimeSymbols_en_SG = {
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['am', 'pm'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
@@ -1074,7 +1196,7 @@ goog.i18n.DateTimeSymbols_en_ZA = {
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y/MM/dd'],
DATEFORMATS: ['EEEE, dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y/MM/dd'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
FIRSTDAYOFWEEK: 6,
@@ -1088,7 +1210,7 @@ goog.i18n.DateTimeSymbols_en_ZA = {
*/
goog.i18n.DateTimeSymbols_es = {
ERAS: ['a. C.', 'd. C.'],
ERANAMES: ['antes de Cristo', 'anno Dómini'],
ERANAMES: ['antes de Cristo', 'después de Cristo'],
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
'N', 'D'],
@@ -1114,7 +1236,7 @@ goog.i18n.DateTimeSymbols_es = {
'4.º trimestre'],
AMPMS: ['a. m.', 'p. m.'],
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
'd \'de\' MMM \'de\' y', 'd/M/yy'],
'd MMM y', 'd/M/yy'],
TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
@@ -1129,17 +1251,17 @@ goog.i18n.DateTimeSymbols_es = {
goog.i18n.DateTimeSymbols_es_419 = {
ERAS: ['a. C.', 'd. C.'],
ERANAMES: ['antes de Cristo', 'después de Cristo'],
NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
'N', 'D'],
MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
'set.', 'oct.', 'nov.', 'dic.'],
'sept.', 'oct.', 'nov.', 'dic.'],
STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
'sábado'],
STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
@@ -1149,12 +1271,12 @@ goog.i18n.DateTimeSymbols_es_419 = {
'Sáb.'],
NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
'4.º trimestre'],
AMPMS: ['a. m.', 'p. m.'],
AMPMS: ['a. m.', 'p. m.'],
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
'd \'de\' MMM \'de\' y', 'd/M/yy'],
'd MMM y', 'd/M/yy'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
@@ -1169,6 +1291,86 @@ goog.i18n.DateTimeSymbols_es_419 = {
goog.i18n.DateTimeSymbols_es_ES = goog.i18n.DateTimeSymbols_es;
/**
* Date/time formatting symbols for locale es_MX.
*/
goog.i18n.DateTimeSymbols_es_MX = {
ERAS: ['a. C.', 'd. C.'],
ERANAMES: ['antes de Cristo', 'después de Cristo'],
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
'N', 'D'],
MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
SHORTMONTHS: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep',
'oct', 'nov', 'dic'],
STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
'sábado'],
STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
'Viernes', 'Sábado'],
SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
'Sáb.'],
NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
SHORTQUARTERS: ['1er. trim.', '2º. trim.', '3er. trim.', '4º trim.'],
QUARTERS: ['1er. trimestre', '2º. trimestre', '3er. trimestre',
'4º trimestre'],
AMPMS: ['a.m.', 'p.m.'],
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
'dd/MM/y', 'dd/MM/yy'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 5
};
/**
* Date/time formatting symbols for locale es_US.
*/
goog.i18n.DateTimeSymbols_es_US = {
ERAS: ['a. C.', 'd. C.'],
ERANAMES: ['antes de Cristo', 'después de Cristo'],
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
'N', 'D'],
MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
'sept.', 'oct.', 'nov.', 'dic.'],
STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
'sábado'],
STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
'Viernes', 'Sábado'],
SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
'Sáb.'],
NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
'4.º trimestre'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
'd MMM y', 'd/M/yy'],
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 5
};
/**
* Date/time formatting symbols for locale et.
*/
@@ -1327,7 +1529,8 @@ goog.i18n.DateTimeSymbols_fi = {
AMPMS: ['ap.', 'ip.'],
DATEFORMATS: ['cccc d. MMMM y', 'd. MMMM y', 'd.M.y', 'd.M.y'],
TIMEFORMATS: ['H.mm.ss zzzz', 'H.mm.ss z', 'H.mm.ss', 'H.mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
DATETIMEFORMATS: ['{1} \'klo\' {0}', '{1} \'klo\' {0}', '{1} \'klo\' {0}',
'{1} {0}'],
FIRSTDAYOFWEEK: 0,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 3
@@ -1440,10 +1643,9 @@ goog.i18n.DateTimeSymbols_fr_CA = {
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', 'y-MM-dd', 'yy-MM-dd'],
TIMEFORMATS: ['HH \'h\' mm \'min\' ss \'s\' zzzz', 'HH:mm:ss z', 'HH:mm:ss',
'HH:mm'],
DATETIMEFORMATS: ['{1} \'à\' {0}', '{1} \'à\' {0}', '{1} {0}', '{1} {0}'],
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'yy-MM-dd'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 5
@@ -1697,7 +1899,7 @@ goog.i18n.DateTimeSymbols_he = {
QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
AMPMS: ['לפנה״צ', 'אחה״צ'],
DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
'{1}, {0}'],
FIRSTDAYOFWEEK: 6,
@@ -2073,7 +2275,7 @@ goog.i18n.DateTimeSymbols_iw = {
QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
AMPMS: ['לפנה״צ', 'אחה״צ'],
DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
'{1}, {0}'],
FIRSTDAYOFWEEK: 6,
@@ -2941,7 +3143,7 @@ goog.i18n.DateTimeSymbols_my = {
'တတိယ သုံးလပတ်',
'စတုတ္ထ သုံးလပတ်'],
AMPMS: ['နံနက်', 'ညနေ'],
DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
DATEFORMATS: ['EEEE dd MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1}မှာ {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 6,
@@ -2999,7 +3201,7 @@ goog.i18n.DateTimeSymbols_ne = {
STANDALONENARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७',
'८', '९', '१०', '११', '१२'],
MONTHS: ['जनवरी', 'फेब्रुअरी', 'मार्च',
'अप्रिल', 'म', 'जुन', 'जुलाई',
'अप्रिल', 'म', 'जुन', 'जुलाई',
'अगस्ट', 'सेप्टेम्बर',
'अक्टोबर', 'नोभेम्बर',
'डिसेम्बर'],
@@ -3019,10 +3221,10 @@ goog.i18n.DateTimeSymbols_ne = {
'अक्टोबर', 'नोभेम्बर',
'डिसेम्बर'],
WEEKDAYS: ['आइतबार', 'सोमबार',
'मङ्गलबार', 'बुधबार', 'बिहबार',
'मङ्गलबार', 'बुधबार', 'बिहिबार',
'शुक्रबार', 'शनिबार'],
STANDALONEWEEKDAYS: ['आइतबार', 'सोमबार',
'मङ्गलबार', 'बुधबार', 'बिहबार',
'मङ्गलबार', 'बुधबार', 'बिहिबार',
'शुक्रबार', 'शनिबार'],
SHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल', 'बुध',
'बिही', 'शुक्र', 'शनि'],
@@ -3036,8 +3238,7 @@ goog.i18n.DateTimeSymbols_ne = {
'चौथो सत्र'],
QUARTERS: ['पहिलो सत्र', 'दोस्रो सत्र',
'तेस्रो सत्र', 'चौथो सत्र'],
AMPMS: ['पूर्व मध्यान्ह',
'उत्तर मध्यान्ह'],
AMPMS: ['पूर्वाह्न', 'अपराह्न'],
DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
@@ -3265,7 +3466,7 @@ goog.i18n.DateTimeSymbols_pl = {
SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
QUARTERS: ['I kwartał', 'II kwartał', 'III kwartał', 'IV kwartał'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'dd.MM.y', 'dd.MM.y'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
FIRSTDAYOFWEEK: 0,
@@ -3330,12 +3531,12 @@ goog.i18n.DateTimeSymbols_pt_PT = {
'N', 'D'],
MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
STANDALONEMONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
'out', 'nov', 'dez'],
STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
'Ago', 'Set', 'Out', 'Nov', 'Dez'],
STANDALONESHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul',
'ago', 'set', 'out', 'nov', 'dez'],
WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
'quinta-feira', 'sexta-feira', 'sábado'],
STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
@@ -3570,7 +3771,7 @@ goog.i18n.DateTimeSymbols_sl = {
'4. četrtletje'],
AMPMS: ['dop.', 'pop.'],
DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'd. MMM y', 'd. MM. yy'],
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
WEEKENDRANGE: [5, 6],
@@ -3661,6 +3862,44 @@ goog.i18n.DateTimeSymbols_sr = {
};
/**
* Date/time formatting symbols for locale sr_Latn.
*/
goog.i18n.DateTimeSymbols_sr_Latn = {
ERAS: ['p. n. e.', 'n. e.'],
ERANAMES: ['Pre nove ere', 'Nove ere'],
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: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust',
'septembar', 'oktobar', 'novembar', 'decembar'],
STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul',
'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep',
'okt', 'nov', 'dec'],
STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
'avg', 'sep', 'okt', 'nov', 'dec'],
WEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak',
'subota'],
STANDALONEWEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak',
'petak', 'subota'],
SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
NARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
QUARTERS: ['Prvo tromesečje', 'Drugo tromesečje', 'Treće tromesečje',
'Četvrto tromesečje'],
AMPMS: ['pre podne', 'po podne'],
DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd.MM.y.', 'd.M.yy.'],
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 0,
WEEKENDRANGE: [5, 6],
FIRSTWEEKCUTOFFDAY: 6
};
/**
* Date/time formatting symbols for locale sv.
*/
@@ -3726,7 +3965,7 @@ goog.i18n.DateTimeSymbols_sw = {
'Alhamisi', 'Ijumaa', 'Jumamosi'],
NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
SHORTQUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
QUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
AMPMS: ['AM', 'PM'],
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
@@ -4189,7 +4428,7 @@ goog.i18n.DateTimeSymbols_zh = {
QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
AMPMS: ['上午', '下午'],
DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'yy/M/d'],
TIMEFORMATS: ['zzzzah:mm:ss', 'zah:mm:ss', 'ah:mm:ss', 'ah:mm'],
TIMEFORMATS: ['zzzz ah:mm:ss', 'z ah:mm:ss', 'ah:mm:ss', 'ah:mm'],
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
FIRSTDAYOFWEEK: 6,
WEEKENDRANGE: [5, 6],
@@ -4330,12 +4569,16 @@ if (goog.LOCALE == 'af') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar;
} else if (goog.LOCALE == 'az') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az;
} else if (goog.LOCALE == 'be') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_be;
} else if (goog.LOCALE == 'bg') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bg;
} else if (goog.LOCALE == 'bn') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bn;
} else if (goog.LOCALE == 'br') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_br;
} else if (goog.LOCALE == 'bs') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs;
} else if (goog.LOCALE == 'ca') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca;
} else if (goog.LOCALE == 'chr') {
@@ -4358,6 +4601,8 @@ if (goog.LOCALE == 'af') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
} else if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_AU;
} else if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CA;
} else if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GB;
} else if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
@@ -4376,6 +4621,10 @@ if (goog.LOCALE == 'af') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_419;
} else if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es;
} else if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_MX;
} else if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_US;
} else if (goog.LOCALE == 'et') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_et;
} else if (goog.LOCALE == 'eu') {
@@ -4492,6 +4741,8 @@ if (goog.LOCALE == 'af') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sq;
} else if (goog.LOCALE == 'sr') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr;
} else if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn;
} else if (goog.LOCALE == 'sv') {
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv;
} else if (goog.LOCALE == 'sw') {
File diff suppressed because it is too large Load Diff
+351 -2
View File
@@ -18,7 +18,7 @@
* This file is autogenerated by script:
* http://go/generate_number_constants.py
* using the --for_closure flag.
* File generated from CLDR ver. 26
* File generated from CLDR ver. 27.0.1
*
* To reduce the file size (which may cause issues in some JS
* developing environments), this file will only contain locales
@@ -41,14 +41,21 @@ goog.provide('goog.i18n.NumberFormatSymbols_am');
goog.provide('goog.i18n.NumberFormatSymbols_am_ET');
goog.provide('goog.i18n.NumberFormatSymbols_ar');
goog.provide('goog.i18n.NumberFormatSymbols_ar_001');
goog.provide('goog.i18n.NumberFormatSymbols_ar_EG');
goog.provide('goog.i18n.NumberFormatSymbols_az');
goog.provide('goog.i18n.NumberFormatSymbols_az_Latn');
goog.provide('goog.i18n.NumberFormatSymbols_az_Latn_AZ');
goog.provide('goog.i18n.NumberFormatSymbols_be');
goog.provide('goog.i18n.NumberFormatSymbols_be_BY');
goog.provide('goog.i18n.NumberFormatSymbols_bg');
goog.provide('goog.i18n.NumberFormatSymbols_bg_BG');
goog.provide('goog.i18n.NumberFormatSymbols_bn');
goog.provide('goog.i18n.NumberFormatSymbols_bn_BD');
goog.provide('goog.i18n.NumberFormatSymbols_br');
goog.provide('goog.i18n.NumberFormatSymbols_br_FR');
goog.provide('goog.i18n.NumberFormatSymbols_bs');
goog.provide('goog.i18n.NumberFormatSymbols_bs_Latn');
goog.provide('goog.i18n.NumberFormatSymbols_bs_Latn_BA');
goog.provide('goog.i18n.NumberFormatSymbols_ca');
goog.provide('goog.i18n.NumberFormatSymbols_ca_AD');
goog.provide('goog.i18n.NumberFormatSymbols_ca_ES');
@@ -71,11 +78,13 @@ goog.provide('goog.i18n.NumberFormatSymbols_de_CH');
goog.provide('goog.i18n.NumberFormatSymbols_de_DE');
goog.provide('goog.i18n.NumberFormatSymbols_de_LU');
goog.provide('goog.i18n.NumberFormatSymbols_el');
goog.provide('goog.i18n.NumberFormatSymbols_el_CY');
goog.provide('goog.i18n.NumberFormatSymbols_el_GR');
goog.provide('goog.i18n.NumberFormatSymbols_en');
goog.provide('goog.i18n.NumberFormatSymbols_en_001');
goog.provide('goog.i18n.NumberFormatSymbols_en_AS');
goog.provide('goog.i18n.NumberFormatSymbols_en_AU');
goog.provide('goog.i18n.NumberFormatSymbols_en_CA');
goog.provide('goog.i18n.NumberFormatSymbols_en_DG');
goog.provide('goog.i18n.NumberFormatSymbols_en_FM');
goog.provide('goog.i18n.NumberFormatSymbols_en_GB');
@@ -100,6 +109,8 @@ goog.provide('goog.i18n.NumberFormatSymbols_es_419');
goog.provide('goog.i18n.NumberFormatSymbols_es_EA');
goog.provide('goog.i18n.NumberFormatSymbols_es_ES');
goog.provide('goog.i18n.NumberFormatSymbols_es_IC');
goog.provide('goog.i18n.NumberFormatSymbols_es_MX');
goog.provide('goog.i18n.NumberFormatSymbols_es_US');
goog.provide('goog.i18n.NumberFormatSymbols_et');
goog.provide('goog.i18n.NumberFormatSymbols_et_EE');
goog.provide('goog.i18n.NumberFormatSymbols_eu');
@@ -157,6 +168,7 @@ goog.provide('goog.i18n.NumberFormatSymbols_ja_JP');
goog.provide('goog.i18n.NumberFormatSymbols_ka');
goog.provide('goog.i18n.NumberFormatSymbols_ka_GE');
goog.provide('goog.i18n.NumberFormatSymbols_kk');
goog.provide('goog.i18n.NumberFormatSymbols_kk_Cyrl');
goog.provide('goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ');
goog.provide('goog.i18n.NumberFormatSymbols_km');
goog.provide('goog.i18n.NumberFormatSymbols_km_KH');
@@ -165,6 +177,7 @@ goog.provide('goog.i18n.NumberFormatSymbols_kn_IN');
goog.provide('goog.i18n.NumberFormatSymbols_ko');
goog.provide('goog.i18n.NumberFormatSymbols_ko_KR');
goog.provide('goog.i18n.NumberFormatSymbols_ky');
goog.provide('goog.i18n.NumberFormatSymbols_ky_Cyrl');
goog.provide('goog.i18n.NumberFormatSymbols_ky_Cyrl_KG');
goog.provide('goog.i18n.NumberFormatSymbols_ln');
goog.provide('goog.i18n.NumberFormatSymbols_ln_CD');
@@ -179,10 +192,12 @@ goog.provide('goog.i18n.NumberFormatSymbols_mk_MK');
goog.provide('goog.i18n.NumberFormatSymbols_ml');
goog.provide('goog.i18n.NumberFormatSymbols_ml_IN');
goog.provide('goog.i18n.NumberFormatSymbols_mn');
goog.provide('goog.i18n.NumberFormatSymbols_mn_Cyrl');
goog.provide('goog.i18n.NumberFormatSymbols_mn_Cyrl_MN');
goog.provide('goog.i18n.NumberFormatSymbols_mr');
goog.provide('goog.i18n.NumberFormatSymbols_mr_IN');
goog.provide('goog.i18n.NumberFormatSymbols_ms');
goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn');
goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn_MY');
goog.provide('goog.i18n.NumberFormatSymbols_mt');
goog.provide('goog.i18n.NumberFormatSymbols_mt_MT');
@@ -200,6 +215,7 @@ goog.provide('goog.i18n.NumberFormatSymbols_no_NO');
goog.provide('goog.i18n.NumberFormatSymbols_or');
goog.provide('goog.i18n.NumberFormatSymbols_or_IN');
goog.provide('goog.i18n.NumberFormatSymbols_pa');
goog.provide('goog.i18n.NumberFormatSymbols_pa_Guru');
goog.provide('goog.i18n.NumberFormatSymbols_pa_Guru_IN');
goog.provide('goog.i18n.NumberFormatSymbols_pl');
goog.provide('goog.i18n.NumberFormatSymbols_pl_PL');
@@ -219,7 +235,10 @@ goog.provide('goog.i18n.NumberFormatSymbols_sl_SI');
goog.provide('goog.i18n.NumberFormatSymbols_sq');
goog.provide('goog.i18n.NumberFormatSymbols_sq_AL');
goog.provide('goog.i18n.NumberFormatSymbols_sr');
goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl');
goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl_RS');
goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn');
goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn_RS');
goog.provide('goog.i18n.NumberFormatSymbols_sv');
goog.provide('goog.i18n.NumberFormatSymbols_sv_SE');
goog.provide('goog.i18n.NumberFormatSymbols_sw');
@@ -238,12 +257,14 @@ goog.provide('goog.i18n.NumberFormatSymbols_uk_UA');
goog.provide('goog.i18n.NumberFormatSymbols_ur');
goog.provide('goog.i18n.NumberFormatSymbols_ur_PK');
goog.provide('goog.i18n.NumberFormatSymbols_uz');
goog.provide('goog.i18n.NumberFormatSymbols_uz_Latn');
goog.provide('goog.i18n.NumberFormatSymbols_uz_Latn_UZ');
goog.provide('goog.i18n.NumberFormatSymbols_vi');
goog.provide('goog.i18n.NumberFormatSymbols_vi_VN');
goog.provide('goog.i18n.NumberFormatSymbols_zh');
goog.provide('goog.i18n.NumberFormatSymbols_zh_CN');
goog.provide('goog.i18n.NumberFormatSymbols_zh_HK');
goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans');
goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans_CN');
goog.provide('goog.i18n.NumberFormatSymbols_zh_TW');
goog.provide('goog.i18n.NumberFormatSymbols_zu');
@@ -340,6 +361,13 @@ goog.i18n.NumberFormatSymbols_ar = {
goog.i18n.NumberFormatSymbols_ar_001 = goog.i18n.NumberFormatSymbols_ar;
/**
* Number formatting symbols for locale ar_EG.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_ar_EG = goog.i18n.NumberFormatSymbols_ar;
/**
* Number formatting symbols for locale az.
* @enum {string}
@@ -363,6 +391,13 @@ goog.i18n.NumberFormatSymbols_az = {
};
/**
* Number formatting symbols for locale az_Latn.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_az_Latn = goog.i18n.NumberFormatSymbols_az;
/**
* Number formatting symbols for locale az_Latn_AZ.
* @enum {string}
@@ -370,6 +405,36 @@ goog.i18n.NumberFormatSymbols_az = {
goog.i18n.NumberFormatSymbols_az_Latn_AZ = goog.i18n.NumberFormatSymbols_az;
/**
* Number formatting symbols for locale be.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_be = {
DECIMAL_SEP: ',',
GROUP_SEP: '\u00A0',
PERCENT: '%',
ZERO_DIGIT: '0',
PLUS_SIGN: '+',
MINUS_SIGN: '-',
EXP_SYMBOL: 'E',
PERMILL: '\u2030',
INFINITY: '\u221E',
NAN: 'NaN',
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0%',
CURRENCY_PATTERN: '\u00A4#,##0.00',
DEF_CURRENCY_CODE: 'BYR'
};
/**
* Number formatting symbols for locale be_BY.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_be_BY = goog.i18n.NumberFormatSymbols_be;
/**
* Number formatting symbols for locale bg.
* @enum {string}
@@ -460,6 +525,43 @@ goog.i18n.NumberFormatSymbols_br = {
goog.i18n.NumberFormatSymbols_br_FR = goog.i18n.NumberFormatSymbols_br;
/**
* Number formatting symbols for locale bs.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_bs = {
DECIMAL_SEP: ',',
GROUP_SEP: '.',
PERCENT: '%',
ZERO_DIGIT: '0',
PLUS_SIGN: '+',
MINUS_SIGN: '-',
EXP_SYMBOL: 'E',
PERMILL: '\u2030',
INFINITY: '\u221E',
NAN: 'NaN',
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0%',
CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
DEF_CURRENCY_CODE: 'BAM'
};
/**
* Number formatting symbols for locale bs_Latn.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_bs_Latn = goog.i18n.NumberFormatSymbols_bs;
/**
* Number formatting symbols for locale bs_Latn_BA.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_bs_Latn_BA = goog.i18n.NumberFormatSymbols_bs;
/**
* Number formatting symbols for locale ca.
* @enum {string}
@@ -758,6 +860,13 @@ goog.i18n.NumberFormatSymbols_el = {
};
/**
* Number formatting symbols for locale el_CY.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_el_CY = goog.i18n.NumberFormatSymbols_el;
/**
* Number formatting symbols for locale el_GR.
* @enum {string}
@@ -825,6 +934,29 @@ goog.i18n.NumberFormatSymbols_en_AU = {
};
/**
* Number formatting symbols for locale en_CA.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_en_CA = {
DECIMAL_SEP: '.',
GROUP_SEP: ',',
PERCENT: '%',
ZERO_DIGIT: '0',
PLUS_SIGN: '+',
MINUS_SIGN: '-',
EXP_SYMBOL: 'E',
PERMILL: '\u2030',
INFINITY: '\u221E',
NAN: 'NaN',
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0%',
CURRENCY_PATTERN: '\u00A4#,##0.00',
DEF_CURRENCY_CODE: 'CAD'
};
/**
* Number formatting symbols for locale en_DG.
* @enum {string}
@@ -1105,6 +1237,52 @@ goog.i18n.NumberFormatSymbols_es_ES = goog.i18n.NumberFormatSymbols_es;
goog.i18n.NumberFormatSymbols_es_IC = goog.i18n.NumberFormatSymbols_es;
/**
* Number formatting symbols for locale es_MX.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_es_MX = {
DECIMAL_SEP: '.',
GROUP_SEP: ',',
PERCENT: '%',
ZERO_DIGIT: '0',
PLUS_SIGN: '+',
MINUS_SIGN: '-',
EXP_SYMBOL: 'E',
PERMILL: '\u2030',
INFINITY: '\u221E',
NAN: 'NaN',
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0%',
CURRENCY_PATTERN: '\u00A4#,##0.00',
DEF_CURRENCY_CODE: 'MXN'
};
/**
* Number formatting symbols for locale es_US.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_es_US = {
DECIMAL_SEP: '.',
GROUP_SEP: ',',
PERCENT: '%',
ZERO_DIGIT: '0',
PLUS_SIGN: '+',
MINUS_SIGN: '-',
EXP_SYMBOL: 'E',
PERMILL: '\u2030',
INFINITY: '\u221E',
NAN: 'NaN',
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0\u00A0%',
CURRENCY_PATTERN: '\u00A4#,##0.00',
DEF_CURRENCY_CODE: 'USD'
};
/**
* Number formatting symbols for locale et.
* @enum {string}
@@ -1905,6 +2083,13 @@ goog.i18n.NumberFormatSymbols_kk = {
};
/**
* Number formatting symbols for locale kk_Cyrl.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_kk_Cyrl = goog.i18n.NumberFormatSymbols_kk;
/**
* Number formatting symbols for locale kk_Cyrl_KZ.
* @enum {string}
@@ -2025,6 +2210,13 @@ goog.i18n.NumberFormatSymbols_ky = {
};
/**
* Number formatting symbols for locale ky_Cyrl.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_ky_Cyrl = goog.i18n.NumberFormatSymbols_ky;
/**
* Number formatting symbols for locale ky_Cyrl_KG.
* @enum {string}
@@ -2236,6 +2428,13 @@ goog.i18n.NumberFormatSymbols_mn = {
};
/**
* Number formatting symbols for locale mn_Cyrl.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_mn_Cyrl = goog.i18n.NumberFormatSymbols_mn;
/**
* Number formatting symbols for locale mn_Cyrl_MN.
* @enum {string}
@@ -2296,6 +2495,13 @@ goog.i18n.NumberFormatSymbols_ms = {
};
/**
* Number formatting symbols for locale ms_Latn.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_ms_Latn = goog.i18n.NumberFormatSymbols_ms;
/**
* Number formatting symbols for locale ms_Latn_MY.
* @enum {string}
@@ -2449,7 +2655,7 @@ goog.i18n.NumberFormatSymbols_nl = {
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0%',
CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0-#,##0.00',
DEF_CURRENCY_CODE: 'EUR'
};
@@ -2544,6 +2750,13 @@ goog.i18n.NumberFormatSymbols_pa = {
};
/**
* Number formatting symbols for locale pa_Guru.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_pa_Guru = goog.i18n.NumberFormatSymbols_pa;
/**
* Number formatting symbols for locale pa_Guru_IN.
* @enum {string}
@@ -2837,6 +3050,13 @@ goog.i18n.NumberFormatSymbols_sr = {
};
/**
* Number formatting symbols for locale sr_Cyrl.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_sr_Cyrl = goog.i18n.NumberFormatSymbols_sr;
/**
* Number formatting symbols for locale sr_Cyrl_RS.
* @enum {string}
@@ -2844,6 +3064,37 @@ goog.i18n.NumberFormatSymbols_sr = {
goog.i18n.NumberFormatSymbols_sr_Cyrl_RS = goog.i18n.NumberFormatSymbols_sr;
/**
* Number formatting symbols for locale sr_Latn.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_sr_Latn = {
DECIMAL_SEP: ',',
GROUP_SEP: '.',
PERCENT: '%',
ZERO_DIGIT: '0',
PLUS_SIGN: '+',
MINUS_SIGN: '-',
EXP_SYMBOL: 'E',
PERMILL: '\u2030',
INFINITY: '\u221E',
NAN: 'NaN',
DECIMAL_PATTERN: '#,##0.###',
SCIENTIFIC_PATTERN: '#E0',
PERCENT_PATTERN: '#,##0%',
CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
DEF_CURRENCY_CODE: 'RSD'
};
/**
* Number formatting symbols for locale sr_Latn_RS.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_sr_Latn_RS =
goog.i18n.NumberFormatSymbols_sr_Latn;
/**
* Number formatting symbols for locale sv.
* @enum {string}
@@ -3130,6 +3381,13 @@ goog.i18n.NumberFormatSymbols_uz = {
};
/**
* Number formatting symbols for locale uz_Latn.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_uz_Latn = goog.i18n.NumberFormatSymbols_uz;
/**
* Number formatting symbols for locale uz_Latn_UZ.
* @enum {string}
@@ -3220,6 +3478,13 @@ goog.i18n.NumberFormatSymbols_zh_HK = {
};
/**
* Number formatting symbols for locale zh_Hans.
* @enum {string}
*/
goog.i18n.NumberFormatSymbols_zh_Hans = goog.i18n.NumberFormatSymbols_zh;
/**
* Number formatting symbols for locale zh_Hans_CN.
* @enum {string}
@@ -3309,14 +3574,30 @@ if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar;
}
if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar;
}
if (goog.LOCALE == 'az') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
}
if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
}
if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
}
if (goog.LOCALE == 'be') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_be;
}
if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_be;
}
if (goog.LOCALE == 'bg') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bg;
}
@@ -3341,6 +3622,18 @@ if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_br;
}
if (goog.LOCALE == 'bs') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
}
if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
}
if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
}
if (goog.LOCALE == 'ca') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
}
@@ -3429,6 +3722,10 @@ if (goog.LOCALE == 'el') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
}
if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
}
if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
}
@@ -3449,6 +3746,10 @@ if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_AU;
}
if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CA;
}
if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
}
@@ -3545,6 +3846,14 @@ if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es;
}
if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_MX;
}
if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_US;
}
if (goog.LOCALE == 'et') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_et;
}
@@ -3773,6 +4082,10 @@ if (goog.LOCALE == 'kk') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
}
if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
}
if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
}
@@ -3805,6 +4118,10 @@ if (goog.LOCALE == 'ky') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
}
if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
}
if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
}
@@ -3861,6 +4178,10 @@ if (goog.LOCALE == 'mn') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
}
if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
}
if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
}
@@ -3877,6 +4198,10 @@ if (goog.LOCALE == 'ms') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
}
if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
}
if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
}
@@ -3945,6 +4270,10 @@ if (goog.LOCALE == 'pa') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
}
if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
}
if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
}
@@ -4021,10 +4350,22 @@ if (goog.LOCALE == 'sr') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
}
if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
}
if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
}
if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn;
}
if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn;
}
if (goog.LOCALE == 'sv') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sv;
}
@@ -4097,6 +4438,10 @@ if (goog.LOCALE == 'uz') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
}
if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
}
if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
}
@@ -4121,6 +4466,10 @@ if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_HK;
}
if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
}
if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
}
File diff suppressed because it is too large Load Diff
+19 -1
View File
@@ -17,7 +17,7 @@
*
* This file is autogenerated by script:
* http://go/generate_pluralrules.py
* File generated from CLDR ver. 26
* File generated from CLDR ver. 27.0.1
*
* Before check in, this file could have been manually edited. This is to
* incorporate changes before we could fix CLDR. All manual modification must be
@@ -821,6 +821,9 @@ if (goog.LOCALE == 'ar') {
if (goog.LOCALE == 'az') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
}
if (goog.LOCALE == 'be') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.beSelect_;
}
if (goog.LOCALE == 'bg') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
}
@@ -830,6 +833,9 @@ if (goog.LOCALE == 'bn') {
if (goog.LOCALE == 'br') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.brSelect_;
}
if (goog.LOCALE == 'bs') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
}
if (goog.LOCALE == 'ca') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
}
@@ -863,6 +869,9 @@ if (goog.LOCALE == 'en') {
if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
}
if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
}
if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
}
@@ -890,6 +899,12 @@ if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
}
if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
}
if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
}
if (goog.LOCALE == 'et') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
}
@@ -1070,6 +1085,9 @@ if (goog.LOCALE == 'sq') {
if (goog.LOCALE == 'sr') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
}
if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
}
if (goog.LOCALE == 'sv') {
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
}
+3 -3
View File
@@ -38,16 +38,16 @@ describe('parsePattern', function() {
parseAndExpect('#,##,##0.00\u00A4', '', '-', '\u00A4', '\u00A4', 1, 2, 2, 2, 3);
parseAndExpect('#,##,##0.00\u00A4;(#,##,##0.00\u00A4)',
'', '(', '\u00A4', '\u00A4)', 1, 2, 2, 2, 3);
parseAndExpect('\u00A4#,##0.00', '\u00A4', '\u00A4-', '', '', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4#,##0.00', '\u00A4', '-\u00A4', '', '', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4#,##0.00;(\u00A4#,##0.00)',
'\u00A4', '(\u00A4', '', ')', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4#,##0.00;\u00A4-#,##0.00',
'\u00A4', '\u00A4-', '', '', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4 #,##0.00', '\u00A4 ', '\u00A4 -', '', '', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4 #,##0.00', '\u00A4 ', '-\u00A4 ', '', '', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4 #,##0.00;\u00A4-#,##0.00',
'\u00A4 ', '\u00A4-', '', '', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4 #,##0.00;\u00A4 #,##0.00-',
'\u00A4 ', '\u00A4 ', '', '-', 1, 2, 2, 3, 3);
parseAndExpect('\u00A4 #,##,##0.00', '\u00A4 ', '\u00A4 -', '', '', 1, 2, 2, 2, 3);
parseAndExpect('\u00A4 #,##,##0.00', '\u00A4 ', '-\u00A4 ', '', '', 1, 2, 2, 2, 3);
});
});
+1 -1
View File
@@ -56,7 +56,7 @@ function parsePattern(pattern) {
p.negSuf = negative.substr(pos + trunkLen).replace(/\'/g, '');
} else {
// hardcoded '-' sign is fine as all locale use '-' as MINUS_SIGN. (\u2212 is the same as '-')
p.negPre = p.posPre + '-';
p.negPre = '-' + p.posPre;
p.negSuf = p.posSuf;
}
+5 -3
View File
@@ -17,7 +17,9 @@ module.exports = function(config, specificOptions) {
testName: specificOptions.testName || 'AngularJS',
startConnect: true,
options: {
'selenium-version': '2.41.0'
// We need selenium version +2.46 for Firefox 39 and the last selenium version for OS X is 2.45.
// TODO: Uncomment when there is a selenium 2.46 available for OS X.
// 'selenium-version': '2.46.0'
}
},
@@ -35,12 +37,12 @@ module.exports = function(config, specificOptions) {
'SL_Chrome': {
base: 'SauceLabs',
browserName: 'chrome',
version: '39'
version: '43'
},
'SL_Firefox': {
base: 'SauceLabs',
browserName: 'firefox',
version: '31'
version: '39'
},
'SL_Safari': {
base: 'SauceLabs',
+1 -1
View File
@@ -116,7 +116,7 @@ module.exports = {
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/\r?\n/g, '\\n');
js = "!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>');";
js = "!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type=\"text/css\">" + css + "</style>');";
state.js.push(js);
return state;
@@ -4,6 +4,8 @@
var isFunction = function isFunction(value){return typeof value == 'function';};
var isPromiseLike = function isPromiseLike(obj) {return obj && isFunction(obj.then);};
var isObject = function isObject(value){return value != null && typeof value === 'object';};
var isUndefined = function isUndefined(value) {return typeof value === 'undefined';};
var minErr = function minErr (module, constructor) {
return function (){
var ErrorConstructor = constructor || Error;
@@ -11,6 +13,20 @@ var minErr = function minErr (module, constructor) {
};
};
var extend = function extend(dst) {
for (var i = 1, ii = arguments.length; i < ii; i++) {
var obj = arguments[i];
if (obj) {
var keys = Object.keys(obj);
for (var j = 0, jj = keys.length; j < jj; j++) {
var key = keys[j];
dst[key] = obj[key];
}
}
}
return dst;
};
var $q = qFactory(process.nextTick, function noopExceptionHandler() {});
exports.resolved = $q.resolve;
+23 -17
View File
@@ -2284,7 +2284,7 @@
"version": "0.6.1",
"dependencies": {
"wordwrap": {
"version": "0.0.2"
"version": "0.0.3"
},
"minimist": {
"version": "0.0.10"
@@ -2385,10 +2385,10 @@
}
},
"dgeni-packages": {
"version": "0.10.13",
"version": "0.10.19",
"dependencies": {
"catharsis": {
"version": "0.8.6",
"version": "0.8.7",
"dependencies": {
"underscore-contrib": {
"version": "0.3.0",
@@ -2404,10 +2404,10 @@
"version": "2.3.0",
"dependencies": {
"camel-case": {
"version": "1.1.1"
"version": "1.1.2"
},
"constant-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"dot-case": {
"version": "1.1.1"
@@ -2428,7 +2428,7 @@
"version": "1.1.1"
},
"pascal-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"path-case": {
"version": "1.1.1"
@@ -2440,10 +2440,10 @@
"version": "1.1.1"
},
"swap-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"title-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"upper-case": {
"version": "1.1.2"
@@ -2468,7 +2468,7 @@
}
},
"htmlparser2": {
"version": "3.8.2",
"version": "3.8.3",
"dependencies": {
"domhandler": {
"version": "2.3.0"
@@ -2518,21 +2518,21 @@
"version": "0.3.0",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
"version": "2.6.5"
},
"sigmund": {
"version": "1.0.0"
"version": "1.0.1"
}
}
},
"nunjucks": {
"version": "1.2.0",
"version": "1.3.4",
"dependencies": {
"optimist": {
"version": "0.6.1",
"dependencies": {
"wordwrap": {
"version": "0.0.2"
"version": "0.0.3"
},
"minimist": {
"version": "0.0.10"
@@ -2552,10 +2552,10 @@
"version": "0.2.14",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
"version": "2.6.5"
},
"sigmund": {
"version": "1.0.0"
"version": "1.0.1"
}
}
},
@@ -2582,10 +2582,10 @@
"version": "0.1.6"
},
"fsevents": {
"version": "0.3.5",
"version": "0.3.8",
"dependencies": {
"nan": {
"version": "1.5.3"
"version": "2.0.5"
}
}
}
@@ -2621,6 +2621,12 @@
}
}
},
"semver": {
"version": "4.3.6"
},
"shelljs": {
"version": "0.5.3"
},
"winston": {
"version": "0.7.3",
"dependencies": {
+242 -231
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -1,7 +1,9 @@
{
"name": "angularjs",
"license": "MIT",
"branchVersion": "^1.4.0-beta.0",
"branchPattern": "1.4.*",
"distTag": "latest",
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
+4 -13
View File
@@ -95,19 +95,10 @@ function publish {
# don't publish every build to npm
if [ "${NEW_VERSION/+sha}" = "$NEW_VERSION" ] ; then
if [ "${NEW_VERSION/-}" = "$NEW_VERSION" ] ; then
if [[ $NEW_VERSION =~ ^1\.2\.[0-9]+$ ]] ; then
# publish 1.2.x releases with the appropriate tag
# this ensures that `npm install` by default will not grab `1.2.x` releases
npm publish --tag=old
else
# publish releases as "latest"
npm publish
fi
else
# publish prerelease builds with the beta tag
npm publish --tag=beta
fi
# get the npm dist-tag from a custom property (distTag) in package.json
DIST_TAG=$(readJsonProp "package.json" "distTag")
echo "-- Publishing to npm as $DIST_TAG"
npm publish --tag=$DIST_TAG
fi
cd $SCRIPT_DIR
+1 -3
View File
@@ -55,6 +55,7 @@
"isBlob": false,
"isBoolean": false,
"isPromiseLike": false,
"hasCustomToString": false,
"trim": false,
"escapeForRegexp": false,
"isElement": false,
@@ -162,9 +163,6 @@
/* ng/compile.js */
"directiveNormalize": false,
/* ng/parse.js */
"setter": false,
/* ng/directive/directives.js */
"ngDirective": false,
+87 -54
View File
@@ -352,8 +352,14 @@ function baseExtend(dst, objs, deep) {
var src = obj[key];
if (deep && isObject(src)) {
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
baseExtend(dst[key], [src], true);
if (isDate(src)) {
dst[key] = new Date(src.valueOf());
} else if (isRegExp(src)) {
dst[key] = new RegExp(src);
} else {
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
baseExtend(dst[key], [src], true);
}
} else {
dst[key] = src;
}
@@ -464,6 +470,11 @@ identity.$inject = [];
function valueFn(value) {return function() {return value;};}
function hasCustomToString(obj) {
return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
}
/**
* @ngdoc function
* @name angular.isUndefined
@@ -795,9 +806,18 @@ function copy(source, destination, stackSource, stackDest) {
if (!destination) {
destination = source;
if (source) {
if (isObject(source)) {
var index;
if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
return stackDest[index];
}
// TypedArray, Date and RegExp have specific copy functionality and must be
// pushed onto the stack before returning.
// Array and other objects create the base object and recurse to copy child
// objects. The array/object will be pushed onto the stack when recursed.
if (isArray(source)) {
destination = copy(source, [], stackSource, stackDest);
return copy(source, [], stackSource, stackDest);
} else if (isTypedArray(source)) {
destination = new source.constructor(source);
} else if (isDate(source)) {
@@ -805,9 +825,16 @@ function copy(source, destination, stackSource, stackDest) {
} else if (isRegExp(source)) {
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
destination.lastIndex = source.lastIndex;
} else if (isObject(source)) {
} else if (isFunction(source.cloneNode)) {
destination = source.cloneNode(true);
} else {
var emptyObject = Object.create(getPrototypeOf(source));
destination = copy(source, emptyObject, stackSource, stackDest);
return copy(source, emptyObject, stackSource, stackDest);
}
if (stackDest) {
stackSource.push(source);
stackDest.push(destination);
}
}
} else {
@@ -818,9 +845,6 @@ function copy(source, destination, stackSource, stackDest) {
stackDest = stackDest || [];
if (isObject(source)) {
var index = stackSource.indexOf(source);
if (index !== -1) return stackDest[index];
stackSource.push(source);
stackDest.push(destination);
}
@@ -829,12 +853,7 @@ function copy(source, destination, stackSource, stackDest) {
if (isArray(source)) {
destination.length = 0;
for (var i = 0; i < source.length; i++) {
result = copy(source[i], null, stackSource, stackDest);
if (isObject(source[i])) {
stackSource.push(source[i]);
stackDest.push(result);
}
destination.push(result);
destination.push(copy(source[i], null, stackSource, stackDest));
}
} else {
var h = destination.$$hashKey;
@@ -848,20 +867,20 @@ function copy(source, destination, stackSource, stackDest) {
if (isBlankObject(source)) {
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
for (key in source) {
putValue(key, source[key], destination, stackSource, stackDest);
destination[key] = copy(source[key], null, stackSource, stackDest);
}
} else if (source && typeof source.hasOwnProperty === 'function') {
// Slow path, which must rely on hasOwnProperty
for (key in source) {
if (source.hasOwnProperty(key)) {
putValue(key, source[key], destination, stackSource, stackDest);
destination[key] = copy(source[key], null, stackSource, stackDest);
}
}
} else {
// Slowest path --- hasOwnProperty can't be called as a method
for (key in source) {
if (hasOwnProperty.call(source, key)) {
putValue(key, source[key], destination, stackSource, stackDest);
destination[key] = copy(source[key], null, stackSource, stackDest);
}
}
}
@@ -869,16 +888,6 @@ function copy(source, destination, stackSource, stackDest) {
}
}
return destination;
function putValue(key, val, destination, stackSource, stackDest) {
// No context allocation, trivial outer scope, easily inlined
var result = copy(val, null, stackSource, stackDest);
if (isObject(val)) {
stackSource.push(val);
stackDest.push(result);
}
destination[key] = result;
}
}
/**
@@ -968,7 +977,7 @@ function equals(o1, o2) {
for (key in o2) {
if (!(key in keySet) &&
key.charAt(0) !== '$' &&
o2[key] !== undefined &&
isDefined(o2[key]) &&
!isFunction(o2[key])) return false;
}
return true;
@@ -979,22 +988,39 @@ function equals(o1, o2) {
}
var csp = function() {
if (isDefined(csp.isActive_)) return csp.isActive_;
if (!isDefined(csp.rules)) {
var active = !!(document.querySelector('[ng-csp]') ||
document.querySelector('[data-ng-csp]'));
if (!active) {
var ngCspElement = (document.querySelector('[ng-csp]') ||
document.querySelector('[data-ng-csp]'));
if (ngCspElement) {
var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
ngCspElement.getAttribute('data-ng-csp');
csp.rules = {
noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
};
} else {
csp.rules = {
noUnsafeEval: noUnsafeEval(),
noInlineStyle: false
};
}
}
return csp.rules;
function noUnsafeEval() {
try {
/* jshint -W031, -W054 */
new Function('');
/* jshint +W031, +W054 */
return false;
} catch (e) {
active = true;
return true;
}
}
return (csp.isActive_ = active);
};
/**
@@ -1226,13 +1252,19 @@ function tryDecodeURIComponent(value) {
* @returns {Object.<string,boolean|Array>}
*/
function parseKeyValue(/**string*/keyValue) {
var obj = {}, key_value, key;
var obj = {};
forEach((keyValue || "").split('&'), function(keyValue) {
var splitPoint, key, val;
if (keyValue) {
key_value = keyValue.replace(/\+/g,'%20').split('=');
key = tryDecodeURIComponent(key_value[0]);
key = keyValue = keyValue.replace(/\+/g,'%20');
splitPoint = keyValue.indexOf('=');
if (splitPoint !== -1) {
key = keyValue.substring(0, splitPoint);
val = keyValue.substring(splitPoint + 1);
}
key = tryDecodeURIComponent(key);
if (isDefined(key)) {
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
val = isDefined(val) ? tryDecodeURIComponent(val) : true;
if (!hasOwnProperty.call(obj, key)) {
obj[key] = val;
} else if (isArray(obj[key])) {
@@ -1641,10 +1673,9 @@ function bindJQuery() {
// bind to jQuery if present;
var jqName = jq();
jQuery = window.jQuery; // use default jQuery.
if (isDefined(jqName)) { // `ngJq` present
jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
}
jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
!jqName ? undefined : // use jqLite
window[jqName]; // use jQuery specified by `ngJq`
// Use jQuery if it exists with proper functionality, otherwise default to us.
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
@@ -1749,22 +1780,24 @@ function getter(obj, path, bindFnToScope) {
/**
* Return the DOM siblings between the first and last node in the given array.
* @param {Array} array like object
* @returns {jqLite} jqLite collection containing the nodes
* @returns {Array} the inputted object or a jqLite collection containing the nodes
*/
function getBlockNodes(nodes) {
// TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
// collection, otherwise update the original collection.
// TODO(perf): update `nodes` instead of creating a new object?
var node = nodes[0];
var endNode = nodes[nodes.length - 1];
var blockNodes = [node];
var blockNodes;
do {
node = node.nextSibling;
if (!node) break;
blockNodes.push(node);
} while (node !== endNode);
for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
if (blockNodes || nodes[i] !== node) {
if (!blockNodes) {
blockNodes = jqLite(slice.call(nodes, 0, i));
}
blockNodes.push(node);
}
}
return jqLite(blockNodes);
return blockNodes || nodes;
}
+7 -11
View File
@@ -3,7 +3,6 @@
/* global angularModule: true,
version: true,
$LocaleProvider,
$CompileProvider,
htmlAnchorDirective,
@@ -20,7 +19,6 @@
ngClassDirective,
ngClassEvenDirective,
ngClassOddDirective,
ngCspDirective,
ngCloakDirective,
ngControllerDirective,
ngFormDirective,
@@ -57,6 +55,7 @@
$AnchorScrollProvider,
$AnimateProvider,
$CoreAnimateCssProvider,
$$CoreAnimateQueueProvider,
$$CoreAnimateRunnerProvider,
$BrowserProvider,
@@ -65,6 +64,7 @@
$DocumentProvider,
$ExceptionHandlerProvider,
$FilterProvider,
$$ForceReflowProvider,
$InterpolateProvider,
$IntervalProvider,
$$HashMapProvider,
@@ -87,7 +87,6 @@
$$TestabilityProvider,
$TimeoutProvider,
$$RAFProvider,
$$AsyncCallbackProvider,
$WindowProvider,
$$jqLiteProvider,
$$CookieReaderProvider
@@ -99,8 +98,9 @@
* @name angular.version
* @module ng
* @description
* An object that contains information about the current AngularJS version. This object has the
* following properties:
* An object that contains information about the current AngularJS version.
*
* This object has the following properties:
*
* - `full` `{string}` Full version string, such as "0.9.18".
* - `major` `{number}` Major version number, such as "0".
@@ -152,11 +152,6 @@ function publishExternalAPI(angular) {
});
angularModule = setupModuleLoader(window);
try {
angularModule('ngLocale');
} catch (e) {
angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
}
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
@@ -219,6 +214,7 @@ function publishExternalAPI(angular) {
$provide.provider({
$anchorScroll: $AnchorScrollProvider,
$animate: $AnimateProvider,
$animateCss: $CoreAnimateCssProvider,
$$animateQueue: $$CoreAnimateQueueProvider,
$$AnimateRunner: $$CoreAnimateRunnerProvider,
$browser: $BrowserProvider,
@@ -227,6 +223,7 @@ function publishExternalAPI(angular) {
$document: $DocumentProvider,
$exceptionHandler: $ExceptionHandlerProvider,
$filter: $FilterProvider,
$$forceReflow: $$ForceReflowProvider,
$interpolate: $InterpolateProvider,
$interval: $IntervalProvider,
$http: $HttpProvider,
@@ -248,7 +245,6 @@ function publishExternalAPI(angular) {
$timeout: $TimeoutProvider,
$window: $WindowProvider,
$$rAF: $$RAFProvider,
$$asyncCallback: $$AsyncCallbackProvider,
$$jqLite: $$jqLiteProvider,
$$HashMap: $$HashMapProvider,
$$cookieReader: $$CookieReaderProvider
+10
View File
@@ -0,0 +1,10 @@
if (window.angular.bootstrap) {
//AngularJS is already loaded, so we can return here...
console.log('WARNING: Tried to load angular more than once.');
return;
}
//try to bind to jquery now so that one can write jqLite(document).ready()
//but we will rebind on bootstrap again.
bindJQuery();
-12
View File
@@ -1,15 +1,3 @@
if (window.angular.bootstrap) {
//AngularJS is already loaded, so we can return here...
console.log('WARNING: Tried to load angular more than once.');
return;
}
//try to bind to jquery now so that one can write jqLite(document).ready()
//but we will rebind on bootstrap again.
bindJQuery();
publishExternalAPI(angular);
jqLite(document).ready(function() {
angularInit(document, bootstrap);
});
+3 -2
View File
@@ -62,7 +62,7 @@
* Implicit module which gets automatically added to each {@link auto.$injector $injector}.
*/
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
@@ -645,7 +645,7 @@ function createInjector(modulesToLoad, strictDi) {
}));
forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
return instanceInjector;
@@ -718,6 +718,7 @@ function createInjector(modulesToLoad, strictDi) {
// Module Loading
////////////////////////////////////
function loadModules(modulesToLoad) {
assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
var runBlocks = [], moduleFn;
forEach(modulesToLoad, function(module) {
if (loadedModules.get(module)) return;
+16 -9
View File
@@ -65,7 +65,7 @@
* - [`html()`](http://api.jquery.com/html/)
* - [`next()`](http://api.jquery.com/next/) - Does not support selectors
* - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
* - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
* - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
* - [`prepend()`](http://api.jquery.com/prepend/)
@@ -79,7 +79,7 @@
* - [`text()`](http://api.jquery.com/text/)
* - [`toggleClass()`](http://api.jquery.com/toggleClass/)
* - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
* - [`val()`](http://api.jquery.com/val/)
* - [`wrap()`](http://api.jquery.com/wrap/)
*
@@ -182,6 +182,13 @@ function jqLiteAcceptsData(node) {
return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
}
function jqLiteHasData(node) {
for (var key in jqCache[node.ng339]) {
return true;
}
return false;
}
function jqLiteBuildFragment(html, context) {
var tmp, tag, wrap,
fragment = context.createDocumentFragment(),
@@ -443,7 +450,7 @@ function jqLiteInheritedData(element, name, value) {
while (element) {
for (var i = 0, ii = names.length; i < ii; i++) {
if ((value = jqLite.data(element, names[i])) !== undefined) return value;
if (isDefined(value = jqLite.data(element, names[i]))) return value;
}
// If dealing with a document fragment node with a host element, and no parent, use the host
@@ -549,14 +556,14 @@ function getBooleanAttrName(element, name) {
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
}
function getAliasedAttrName(element, name) {
var nodeName = element.nodeName;
return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
function getAliasedAttrName(name) {
return ALIASED_ATTR[name];
}
forEach({
data: jqLiteData,
removeData: jqLiteRemoveData
removeData: jqLiteRemoveData,
hasData: jqLiteHasData
}, function(fn, name) {
JQLite[name] = fn;
});
@@ -687,7 +694,7 @@ forEach({
// in a way that survives minification.
// jqLiteEmpty takes no arguments but is a setter.
if (fn !== jqLiteEmpty &&
(((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
(isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
if (isObject(arg1)) {
// we are a write, but the object properties are the key/values
@@ -708,7 +715,7 @@ forEach({
// TODO: do we still need this?
var value = fn.$dv;
// Only if we have $dv do we iterate over all, otherwise it is just the first element.
var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
for (var j = 0; j < jj; j++) {
var nodeValue = fn(this[j], arg1, arg2);
value = value ? value + nodeValue : nodeValue;
+23 -10
View File
@@ -38,8 +38,8 @@ function setupModuleLoader(window) {
* All modules (angular core or 3rd party) that should be available to an application must be
* registered using this mechanism.
*
* When passed two or more arguments, a new module is created. If passed only one argument, an
* existing module (the name passed as the first argument to `module`) is retrieved.
* Passing one argument retrieves an existing {@link angular.Module},
* whereas passing more than one argument creates a new {@link angular.Module}
*
*
* # Module
@@ -146,7 +146,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#provider $provide.provider()}.
*/
provider: invokeLater('$provide', 'provider'),
provider: invokeLaterAndSetModuleName('$provide', 'provider'),
/**
* @ngdoc method
@@ -157,7 +157,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#factory $provide.factory()}.
*/
factory: invokeLater('$provide', 'factory'),
factory: invokeLaterAndSetModuleName('$provide', 'factory'),
/**
* @ngdoc method
@@ -168,7 +168,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#service $provide.service()}.
*/
service: invokeLater('$provide', 'service'),
service: invokeLaterAndSetModuleName('$provide', 'service'),
/**
* @ngdoc method
@@ -203,7 +203,7 @@ function setupModuleLoader(window) {
* @description
* See {@link auto.$provide#decorator $provide.decorator()}.
*/
decorator: invokeLater('$provide', 'decorator'),
decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
/**
* @ngdoc method
@@ -237,7 +237,7 @@ function setupModuleLoader(window) {
* See {@link ng.$animateProvider#register $animateProvider.register()} and
* {@link ngAnimate ngAnimate module} for more information.
*/
animation: invokeLater('$animateProvider', 'register'),
animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
/**
* @ngdoc method
@@ -255,7 +255,7 @@ function setupModuleLoader(window) {
* (`myapp_subsection_filterx`).
* </div>
*/
filter: invokeLater('$filterProvider', 'register'),
filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
/**
* @ngdoc method
@@ -267,7 +267,7 @@ function setupModuleLoader(window) {
* @description
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
*/
controller: invokeLater('$controllerProvider', 'register'),
controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
/**
* @ngdoc method
@@ -280,7 +280,7 @@ function setupModuleLoader(window) {
* @description
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
directive: invokeLater('$compileProvider', 'directive'),
directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
/**
* @ngdoc method
@@ -330,6 +330,19 @@ function setupModuleLoader(window) {
return moduleInstance;
};
}
/**
* @param {string} provider
* @param {string} method
* @returns {angular.Module}
*/
function invokeLaterAndSetModuleName(provider, method) {
return function(recipeName, factoryFunction) {
if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
invokeQueue.push([provider, method, arguments]);
return moduleInstance;
};
}
});
};
});
+1
View File
@@ -5,3 +5,4 @@
*/
'use strict';
(function() {
function isFunction(value) {return typeof value === 'function';};
+51 -46
View File
@@ -105,61 +105,66 @@ var $$CoreAnimateQueueProvider = function() {
}
};
function addRemoveClassesPostDigest(element, add, remove) {
var data = postDigestQueue.get(element);
var classVal;
if (!data) {
postDigestQueue.put(element, data = {});
postDigestElements.push(element);
}
if (add) {
forEach(add.split(' '), function(className) {
function updateData(data, classes, value) {
var changed = false;
if (classes) {
classes = isString(classes) ? classes.split(' ') :
isArray(classes) ? classes : [];
forEach(classes, function(className) {
if (className) {
data[className] = true;
changed = true;
data[className] = value;
}
});
}
return changed;
}
if (remove) {
forEach(remove.split(' '), function(className) {
if (className) {
data[className] = false;
}
});
}
if (postDigestElements.length > 1) return;
$rootScope.$$postDigest(function() {
forEach(postDigestElements, function(element) {
var data = postDigestQueue.get(element);
if (data) {
var existing = splitClasses(element.attr('class'));
var toAdd = '';
var toRemove = '';
forEach(data, function(status, className) {
var hasClass = !!existing[className];
if (status !== hasClass) {
if (status) {
toAdd += (toAdd.length ? ' ' : '') + className;
} else {
toRemove += (toRemove.length ? ' ' : '') + className;
}
function handleCSSClassChanges() {
forEach(postDigestElements, function(element) {
var data = postDigestQueue.get(element);
if (data) {
var existing = splitClasses(element.attr('class'));
var toAdd = '';
var toRemove = '';
forEach(data, function(status, className) {
var hasClass = !!existing[className];
if (status !== hasClass) {
if (status) {
toAdd += (toAdd.length ? ' ' : '') + className;
} else {
toRemove += (toRemove.length ? ' ' : '') + className;
}
});
}
});
forEach(element, function(elm) {
toAdd && jqLiteAddClass(elm, toAdd);
toRemove && jqLiteRemoveClass(elm, toRemove);
});
postDigestQueue.remove(element);
}
});
postDigestElements.length = 0;
forEach(element, function(elm) {
toAdd && jqLiteAddClass(elm, toAdd);
toRemove && jqLiteRemoveClass(elm, toRemove);
});
postDigestQueue.remove(element);
}
});
postDigestElements.length = 0;
}
function addRemoveClassesPostDigest(element, add, remove) {
var data = postDigestQueue.get(element) || {};
var classesAdded = updateData(data, add, true);
var classesRemoved = updateData(data, remove, false);
if (classesAdded || classesRemoved) {
postDigestQueue.put(element, data);
postDigestElements.push(element);
if (postDigestElements.length === 1) {
$rootScope.$$postDigest(handleCSSClassChanges);
}
}
}
}];
};
+84
View File
@@ -0,0 +1,84 @@
'use strict';
/**
* @ngdoc service
* @name $animateCss
* @kind object
*
* @description
* This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
* then the `$animateCss` service will actually perform animations.
*
* Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
*/
var $CoreAnimateCssProvider = function() {
this.$get = ['$$rAF', '$q', function($$rAF, $q) {
var RAFPromise = function() {};
RAFPromise.prototype = {
done: function(cancel) {
this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
},
end: function() {
this.done();
},
cancel: function() {
this.done(true);
},
getPromise: function() {
if (!this.defer) {
this.defer = $q.defer();
}
return this.defer.promise;
},
then: function(f1,f2) {
return this.getPromise().then(f1,f2);
},
'catch': function(f1) {
return this.getPromise()['catch'](f1);
},
'finally': function(f1) {
return this.getPromise()['finally'](f1);
}
};
return function(element, options) {
if (options.from) {
element.css(options.from);
options.from = null;
}
var closed, runner = new RAFPromise();
return {
start: run,
end: run
};
function run() {
$$rAF(function() {
close();
if (!closed) {
runner.done();
}
closed = true;
});
return runner;
}
function close() {
if (options.addClass) {
element.addClass(options.addClass);
options.addClass = null;
}
if (options.removeClass) {
element.removeClass(options.removeClass);
options.removeClass = null;
}
if (options.to) {
element.css(options.to);
options.to = null;
}
}
};
}];
};
-11
View File
@@ -1,11 +0,0 @@
'use strict';
function $$AsyncCallbackProvider() {
this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
return $$rAF.supported
? function(fn) { return $$rAF(fn); }
: function(fn) {
return $timeout(fn, 0, false);
};
}];
}
+12 -7
View File
@@ -63,7 +63,7 @@ function Browser(window, document, $log, $sniffer) {
function getHash(url) {
var index = url.indexOf('#');
return index === -1 ? '' : url.substr(index + 1);
return index === -1 ? '' : url.substr(index);
}
/**
@@ -87,7 +87,7 @@ function Browser(window, document, $log, $sniffer) {
var cachedState, lastHistoryState,
lastBrowserUrl = location.href,
baseElement = document.find('base'),
reloadLocation = null;
pendingLocation = null;
cacheState();
lastHistoryState = cachedState;
@@ -147,8 +147,8 @@ function Browser(window, document, $log, $sniffer) {
// Do the assignment again so that those two variables are referentially identical.
lastHistoryState = cachedState;
} else {
if (!sameBase) {
reloadLocation = url;
if (!sameBase || pendingLocation) {
pendingLocation = url;
}
if (replace) {
location.replace(url);
@@ -157,14 +157,18 @@ function Browser(window, document, $log, $sniffer) {
} else {
location.hash = getHash(url);
}
if (location.href !== url) {
pendingLocation = url;
}
}
return self;
// getter
} else {
// - reloadLocation is needed as browsers don't allow to read out
// the new location.href if a reload happened.
// - pendingLocation is needed as browsers don't allow to read out
// the new location.href if a reload happened or if there is a bug like in iOS 9 (see
// https://openradar.appspot.com/22186109).
// - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
return reloadLocation || location.href.replace(/%27/g,"'");
return pendingLocation || location.href.replace(/%27/g,"'");
}
};
@@ -186,6 +190,7 @@ function Browser(window, document, $log, $sniffer) {
urlChangeInit = false;
function cacheStateAndFireUrlChange() {
pendingLocation = null;
cacheState();
fireUrlChange();
}
+2 -2
View File
@@ -67,10 +67,10 @@
$scope.keys = [];
$scope.cache = $cacheFactory('cacheId');
$scope.put = function(key, value) {
if ($scope.cache.get(key) === undefined) {
if (isUndefined($scope.cache.get(key))) {
$scope.keys.push(key);
}
$scope.cache.put(key, value === undefined ? null : value);
$scope.cache.put(key, isUndefined(value) ? null : value);
};
}]);
</file>
+105 -56
View File
@@ -146,18 +146,24 @@
* and other directives used in the directive's template will also be excluded from execution.
*
* #### `scope`
* **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
* same element request a new scope, only one new scope is created. The new scope rule does not
* apply for the root of the template since the root of the template always gets a new scope.
* The scope property can be `true`, an object or a falsy value:
*
* **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
* normal scope in that it does not prototypically inherit from the parent scope. This is useful
* when creating reusable components, which should not accidentally read or modify data in the
* parent scope.
* * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
*
* The 'isolate' scope takes an object hash which defines a set of local scope properties
* derived from the parent scope. These local properties are useful for aliasing values for
* templates. Locals definition is a hash of local scope property to its source:
* * **`true`:** A new child scope that prototypically inherits from its parent will be created for
* the directive's element. If multiple directives on the same element request a new scope,
* only one new scope is created. The new scope rule does not apply for the root of the template
* since the root of the template always gets a new scope.
*
* * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
* 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
* scope. This is useful when creating reusable components, which should not accidentally read or modify
* data in the parent scope.
*
* The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
* directive's element. These local properties are useful for aliasing values for templates. The keys in
* the object hash map to the name of the property on the isolate scope; the values define how the property
* is bound to the parent scope, via matching attributes on the directive's element:
*
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
* always a string since DOM attributes are strings. If no `attr` name is specified then the
@@ -190,6 +196,20 @@
* For example, if the expression is `increment(amount)` then we can specify the amount value
* by calling the `localFn` as `localFn({amount: 22})`.
*
* In general it's possible to apply more than one directive to one element, but there might be limitations
* depending on the type of scope required by the directives. The following points will help explain these limitations.
* For simplicity only two directives are taken into account, but it is also applicable for several directives:
*
* * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
* * **child scope** + **no scope** => Both directives will share one single child scope
* * **child scope** + **child scope** => Both directives will share one single child scope
* * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use
* its parent's scope
* * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
* be applied to the same element.
* * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives
* cannot be applied to the same element.
*
*
* #### `bindToController`
* When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
@@ -198,7 +218,7 @@
*
* #### `controller`
* Controller constructor function. The controller is instantiated before the
* pre-linking phase and it is shared with other directives (see
* pre-linking phase and can be accessed by other directives (see
* `require` attribute). This allows the directives to communicate with each other and augment
* each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
*
@@ -238,9 +258,10 @@
*
* #### `controllerAs`
* Identifier name for a reference to the controller in the directive's scope.
* This allows the controller to be referenced from the directive template. The directive
* needs to define a scope for this configuration to be used. Useful in the case when
* directive is used as component.
* This allows the controller to be referenced from the directive template. This is especially
* useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
* to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
* `controllerAs` reference might overwrite a property that already exists on the parent scope.
*
*
* #### `restrict`
@@ -399,13 +420,16 @@
* * `controller` - the directive's required controller instance(s) - Instances are shared
* among all directives, which allows the directives to use the controllers as a communication
* channel. The exact value depends on the directive's `require` property:
* * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
* * `string`: the controller instance
* * `array`: array of controller instances
* * no controller(s) required: `undefined`
*
* If a required controller cannot be found, and it is optional, the instance is `null`,
* otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
*
* Note that you can also require the directive's own controller - it will be made available like
* any other controller.
*
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
* This is the same as the `$transclude`
* parameter of directive controllers, see there for details.
@@ -430,7 +454,7 @@
*
* ### Transclusion
*
* Transclusion is the process of extracting a collection of DOM element from one part of the DOM and
* Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
* copying them to another part of the DOM, while maintaining their connection to the original AngularJS
* scope from where they were taken.
*
@@ -852,6 +876,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (isObject(bindings.isolateScope)) {
directive.$$isolateBindings = bindings.isolateScope;
}
directive.$$moduleName = directiveFactory.$$moduleName;
directives.push(directive);
} catch (e) {
$exceptionHandler(e);
@@ -1073,7 +1098,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var node = this.$$element[0],
booleanKey = getBooleanAttrName(node, key),
aliasedKey = getAliasedAttrName(node, key),
aliasedKey = getAliasedAttrName(key),
observer = key,
nodeName;
@@ -1140,7 +1165,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
if (writeAttr !== false) {
if (value === null || value === undefined) {
if (value === null || isUndefined(value)) {
this.$$element.removeAttr(attrName);
} else {
this.$$element.attr(attrName, value);
@@ -1184,7 +1209,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
listeners.push(fn);
$rootScope.$evalAsync(function() {
if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {
// no one registered attribute interpolation function, so lets call it manually
fn(attrs[key]);
}
@@ -1423,8 +1448,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (nodeLinkFn.transcludeOnThisElement) {
childBoundTranscludeFn = createBoundTranscludeFn(
scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
nodeLinkFn.elementTranscludeOnThisElement);
scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
} else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
childBoundTranscludeFn = parentBoundTranscludeFn;
@@ -1446,7 +1470,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
@@ -1545,6 +1569,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
break;
case NODE_TYPE_TEXT: /* Text Node */
if (msie === 11) {
// Workaround for #11781
while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {
node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
node.parentNode.removeChild(node.nextSibling);
}
}
addTextInterpolateDirective(directives, node.nodeValue);
break;
case NODE_TYPE_COMMENT: /* Comment */
@@ -1644,7 +1675,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
previousCompileContext = previousCompileContext || {};
var terminalPriority = -Number.MAX_VALUE,
newScopeDirective,
newScopeDirective = previousCompileContext.newScopeDirective,
controllerDirectives = previousCompileContext.controllerDirectives,
newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
templateDirective = previousCompileContext.templateDirective,
@@ -1810,6 +1841,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
controllerDirectives: controllerDirectives,
newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
newIsolateScopeDirective: newIsolateScopeDirective,
templateDirective: templateDirective,
nonTlbTranscludeDirective: nonTlbTranscludeDirective
@@ -1837,7 +1869,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;
nodeLinkFn.templateOnThisElement = hasTemplate;
nodeLinkFn.transclude = childTranscludeFn;
@@ -1998,9 +2029,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
for (i in elementControllers) {
controller = elementControllers[i];
var controllerResult = controller();
if (controllerResult !== controller.instance) {
// If the controller constructor has a return value, overwrite the instance
// from setupControllers and update the element data
controller.instance = controllerResult;
$element.data('$' + directive.name + 'Controller', controllerResult);
$element.data('$' + i + 'Controller', controllerResult);
if (controller === controllerForBindings) {
// Remove and re-install bindToController bindings
thisLinkFn.$$destroyBindings();
@@ -2097,7 +2131,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
i = 0, ii = directives.length; i < ii; i++) {
try {
directive = directives[i];
if ((maxPriority === undefined || maxPriority > directive.priority) &&
if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
directive.restrict.indexOf(location) != -1) {
if (startAttrName) {
directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
@@ -2192,7 +2226,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$compileNode.empty();
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
$templateRequest(templateUrl)
.then(function(content) {
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
@@ -2300,11 +2334,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return a.index - b.index;
}
function assertNoDuplicate(what, previousDirective, directive, element) {
function wrapModuleNameIfDefined(moduleName) {
return moduleName ?
(' (module: ' + moduleName + ')') :
'';
}
if (previousDirective) {
throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
previousDirective.name, directive.name, what, startingTag(element));
throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',
previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),
directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));
}
}
@@ -2485,26 +2526,28 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var fragment = document.createDocumentFragment();
fragment.appendChild(firstElementToRemove);
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
// data here because there's no public interface in jQuery to do that and copying over
// event listeners (which is the main use of private data) wouldn't work anyway.
jqLite(newNode).data(jqLite(firstElementToRemove).data());
if (jqLite.hasData(firstElementToRemove)) {
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
// data here because there's no public interface in jQuery to do that and copying over
// event listeners (which is the main use of private data) wouldn't work anyway.
jqLite(newNode).data(jqLite(firstElementToRemove).data());
// Remove data of the replaced element. We cannot just call .remove()
// on the element it since that would deallocate scope that is needed
// for the new node. Instead, remove the data "manually".
if (!jQuery) {
delete jqLite.cache[firstElementToRemove[jqLite.expando]];
} else {
// jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
// the replaced element. The cleanData version monkey-patched by Angular would cause
// the scope to be trashed and we do need the very same scope to work with the new
// element. However, we cannot just cache the non-patched version and use it here as
// that would break if another library patches the method after Angular does (one
// example is jQuery UI). Instead, set a flag indicating scope destroying should be
// skipped this one time.
skipDestroyOnNextJQueryCleanData = true;
jQuery.cleanData([firstElementToRemove]);
// Remove data of the replaced element. We cannot just call .remove()
// on the element it since that would deallocate scope that is needed
// for the new node. Instead, remove the data "manually".
if (!jQuery) {
delete jqLite.cache[firstElementToRemove[jqLite.expando]];
} else {
// jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
// the replaced element. The cleanData version monkey-patched by Angular would cause
// the scope to be trashed and we do need the very same scope to work with the new
// element. However, we cannot just cache the non-patched version and use it here as
// that would break if another library patches the method after Angular does (one
// example is jQuery UI). Instead, set a flag indicating scope destroying should be
// skipped this one time.
skipDestroyOnNextJQueryCleanData = true;
jQuery.cleanData([firstElementToRemove]);
}
}
for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
@@ -2548,11 +2591,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
switch (mode) {
case '@':
if (!optional && !hasOwnProperty.call(attrs, attrName)) {
destination[scopeName] = attrs[attrName] = void 0;
}
attrs.$observe(attrName, function(value) {
destination[scopeName] = value;
if (isString(value)) {
destination[scopeName] = value;
}
});
attrs.$$observers[attrName].$$scope = scope;
if (attrs[attrName]) {
if (isString(attrs[attrName])) {
// 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);
@@ -2560,9 +2608,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
break;
case '=':
if (optional && !attrs[attrName]) {
return;
if (!hasOwnProperty.call(attrs, attrName)) {
if (optional) break;
attrs[attrName] = void 0;
}
if (optional && !attrs[attrName]) break;
parentGet = $parse(attrs[attrName]);
if (parentGet.literal) {
compare = equals;
@@ -2603,9 +2654,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
case '&':
// Don't assign Object.prototype method to scope
if (!attrs.hasOwnProperty(attrName) && optional) break;
parentGet = $parse(attrs[attrName]);
parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
// Don't assign noop to destination if expression is not valid
if (parentGet === noop && optional) break;
+1 -1
View File
@@ -39,7 +39,7 @@ function $$CookieReader($document) {
// the first value that is seen for a cookie is the most
// specific one. values for the same cookie name that
// follow are for less specific paths.
if (lastCookies[name] === undefined) {
if (isUndefined(lastCookies[name])) {
lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
}
}
+8 -1
View File
@@ -206,6 +206,13 @@
* @priority 100
*
* @description
* Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
*
* Note that this directive should not be used together with {@link ngModel `ngModel`},
* as this can lead to unexpected behavior.
*
* ### Why do we need `ngChecked`?
*
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as checked. (Their presence means true and their absence means false.)
* If we put an Angular interpolation expression into such an attribute then the
@@ -230,7 +237,7 @@
*
* @element INPUT
* @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
* then special attribute "checked" will be set on the element
* then the `checked` attribute will be set on the element
*/
+53 -21
View File
@@ -25,6 +25,7 @@ function nullFormRenameControl(control, name) {
* @property {boolean} $dirty True if user has already interacted with the form.
* @property {boolean} $valid True if all of the containing forms and controls are valid.
* @property {boolean} $invalid True if at least one containing control or form is invalid.
* @property {boolean} $pending True if at least one containing control or form is pending.
* @property {boolean} $submitted True if user has submitted the form even if its invalid.
*
* @property {Object} $error Is an object hash, containing references to controls or
@@ -64,8 +65,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
var form = this,
controls = [];
var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
// init state
form.$error = {};
form.$$success = {};
@@ -76,8 +75,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
form.$valid = true;
form.$invalid = false;
form.$submitted = false;
parentForm.$addControl(form);
form.$$parentForm = nullFormCtrl;
/**
* @ngdoc method
@@ -116,11 +114,23 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
/**
* @ngdoc method
* @name form.FormController#$addControl
* @param {object} control control object, either a {@link form.FormController} or an
* {@link ngModel.NgModelController}
*
* @description
* Register a control with the form.
* Register a control with the form. Input elements using ngModelController do this automatically
* when they are linked.
*
* Input elements using ngModelController do this automatically when they are linked.
* Note that the current state of the control will not be reflected on the new parent form. This
* is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
* state.
*
* However, if the method is used programmatically, for example by adding dynamically created controls,
* or controls that have been previously removed without destroying their corresponding DOM element,
* it's the developers responsiblity to make sure the current state propagates to the parent form.
*
* For example, if an input control is added that is already `$dirty` and has `$error` properties,
* calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
*/
form.$addControl = function(control) {
// Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
@@ -131,6 +141,8 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
if (control.$name) {
form[control.$name] = control;
}
control.$$parentForm = form;
};
// Private API: rename a form control
@@ -147,11 +159,18 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
/**
* @ngdoc method
* @name form.FormController#$removeControl
* @param {object} control control object, either a {@link form.FormController} or an
* {@link ngModel.NgModelController}
*
* @description
* Deregister a control from the form.
*
* Input elements using ngModelController do this automatically when they are destroyed.
*
* Note that only the removed control's validation state (`$errors`etc.) will be removed from the
* form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
* different from case to case. For example, removing the only `$dirty` control from a form may or
* may not mean that the form is still `$dirty`.
*/
form.$removeControl = function(control) {
if (control.$name && form[control.$name] === control) {
@@ -168,6 +187,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
});
arrayRemove(controls, control);
control.$$parentForm = nullFormCtrl;
};
@@ -204,7 +224,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
delete object[property];
}
},
parentForm: parentForm,
$animate: $animate
});
@@ -223,7 +242,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
$animate.addClass(element, DIRTY_CLASS);
form.$dirty = true;
form.$pristine = false;
parentForm.$setDirty();
form.$$parentForm.$setDirty();
};
/**
@@ -279,7 +298,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
form.$setSubmitted = function() {
$animate.addClass(element, SUBMITTED_CLASS);
form.$submitted = true;
parentForm.$setSubmitted();
form.$$parentForm.$setSubmitted();
};
}
@@ -329,6 +348,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
* # CSS classes
* - `ng-valid` is set if the form is valid.
* - `ng-invalid` is set if the form is invalid.
* - `ng-pending` is set if the form is pending.
* - `ng-pristine` is set if the form is pristine.
* - `ng-dirty` is set if the form is dirty.
* - `ng-submitted` is set if the form was submitted.
@@ -404,7 +424,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
</script>
<style>
.my-form {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
background: transparent;
}
@@ -449,10 +468,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
* related scope, under this name.
*/
var formDirectiveFactory = function(isNgForm) {
return ['$timeout', function($timeout) {
return ['$timeout', '$parse', function($timeout, $parse) {
var formDirective = {
name: 'form',
restrict: isNgForm ? 'EAC' : 'E',
require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
controller: FormController,
compile: function ngFormCompile(formElement, attr) {
// Setup initial state of the control
@@ -461,7 +481,9 @@ var formDirectiveFactory = function(isNgForm) {
var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
return {
pre: function ngFormPreLink(scope, formElement, attr, controller) {
pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
var controller = ctrls[0];
// if `action` attr is not present on the form, prevent the default action (submission)
if (!('action' in attr)) {
// we can't use jq events because if a form is destroyed during submission the default
@@ -490,22 +512,24 @@ var formDirectiveFactory = function(isNgForm) {
});
}
var parentFormCtrl = controller.$$parentForm;
var parentFormCtrl = ctrls[1] || controller.$$parentForm;
parentFormCtrl.$addControl(controller);
var setter = nameAttr ? getSetter(controller.$name) : noop;
if (nameAttr) {
setter(scope, controller.$name, controller, controller.$name);
setter(scope, controller);
attr.$observe(nameAttr, function(newValue) {
if (controller.$name === newValue) return;
setter(scope, controller.$name, undefined, controller.$name);
parentFormCtrl.$$renameControl(controller, newValue);
setter(scope, controller.$name, controller, controller.$name);
setter(scope, undefined);
controller.$$parentForm.$$renameControl(controller, newValue);
setter = getSetter(controller.$name);
setter(scope, controller);
});
}
formElement.on('$destroy', function() {
parentFormCtrl.$removeControl(controller);
if (nameAttr) {
setter(scope, attr[nameAttr], undefined, controller.$name);
}
controller.$$parentForm.$removeControl(controller);
setter(scope, undefined);
extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
});
}
@@ -514,6 +538,14 @@ var formDirectiveFactory = function(isNgForm) {
};
return formDirective;
function getSetter(expression) {
if (expression === '') {
//create an assignable expression, so forms with an empty name can be renamed later
return $parse('this[""]').assign;
}
return $parse(expression).assign || noop;
}
}];
};
+86 -28
View File
@@ -6,14 +6,14 @@
DIRTY_CLASS: false,
UNTOUCHED_CLASS: false,
TOUCHED_CLASS: false,
$ngModelMinErr: false,
ngModelMinErr: false,
*/
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
@@ -138,9 +138,17 @@ var inputType = {
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
* valid ISO date string (yyyy-MM-dd).
* valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
* (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
* constraint validation.
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
* a valid ISO date string (yyyy-MM-dd).
* a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
* (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
* constraint validation.
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -232,10 +240,18 @@ var inputType = {
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
* valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
* a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
* This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
* inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
* Note that `min` will also add native HTML5 constraint validation.
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
* This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
* inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
* Note that `max` will also add native HTML5 constraint validation.
* @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
* @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -328,10 +344,18 @@ var inputType = {
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
* valid ISO time format (HH:mm:ss).
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
* valid ISO time format (HH:mm:ss).
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
* This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
* attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
* native HTML5 constraint validation.
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
* This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
* attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
* native HTML5 constraint validation.
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
* `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
* `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -423,10 +447,18 @@ var inputType = {
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
* valid ISO week format (yyyy-W##).
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
* a valid ISO week format (yyyy-W##).
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
* This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
* attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
* native HTML5 constraint validation.
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
* This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
* attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
* native HTML5 constraint validation.
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -520,10 +552,19 @@ var inputType = {
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
* a valid ISO month format (yyyy-MM).
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
* be a valid ISO month format (yyyy-MM).
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
* This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
* attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
* native HTML5 constraint validation.
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
* This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
* attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
* native HTML5 constraint validation.
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
@@ -612,6 +653,16 @@ var inputType = {
* error docs for more information and an example of how to convert your model if necessary.
* </div>
*
* ## Issues with HTML5 constraint validation
*
* In browsers that follow the
* [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),
* `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.
* If a non-number is entered in the input, the browser will report the value as an empty string,
* which means the view / model values in `ngModel` and subsequently the scope value
* will also be an empty string.
*
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
@@ -903,12 +954,15 @@ var inputType = {
* HTML radio button.
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string} value The value to which the expression should be set when selected.
* @param {string} value The value to which the `ngModel` expression should be set when selected.
* Note that `value` only supports `string` values, i.e. the scope model needs to be a string,
* too. Use `ngValue` if you need complex models (`number`, `object`, ...).
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
* @param {string} ngValue Angular expression which sets the value to which the expression should
* be set when selected.
* @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio
* is selected. Should be used instead of the `value` attribute if you need
* a non-string `ngModel` (`boolean`, `array`, ...).
*
* @example
<example name="radio-input-directive" module="radioExample">
@@ -1115,7 +1169,11 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
element.on('change', listener);
ctrl.$render = function() {
element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
// Workaround for Firefox validation #12102.
var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;
if (element.val() !== value) {
element.val(value);
}
};
}
@@ -1226,7 +1284,7 @@ function createDateInputType(type, regexp, parseDate, format) {
ctrl.$formatters.push(function(value) {
if (value && !isDate(value)) {
throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
}
if (isValidDate(value)) {
previousDate = value;
@@ -1268,7 +1326,7 @@ function createDateInputType(type, regexp, parseDate, format) {
}
function parseObservedDateValue(val) {
return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
}
};
}
@@ -1302,7 +1360,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
ctrl.$formatters.push(function(value) {
if (!ctrl.$isEmpty(value)) {
if (!isNumber(value)) {
throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
}
value = value.toString();
}
@@ -1395,7 +1453,7 @@ function parseConstantExpr($parse, context, name, expression, fallback) {
if (isDefined(expression)) {
parseFn = $parse(expression);
if (!parseFn.constant) {
throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +
throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
'`{1}`.', name, expression);
}
return parseFn(context);
+2 -2
View File
@@ -60,7 +60,7 @@ var ngBindDirective = ['$compile', function($compile) {
$compile.$$addBindingInfo(element, attr.ngBind);
element = element[0];
scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
element.textContent = value === undefined ? '' : value;
element.textContent = isUndefined(value) ? '' : value;
});
};
}
@@ -128,7 +128,7 @@ var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate
$compile.$$addBindingInfo(element, interpolateFn.expressions);
element = element[0];
attr.$observe('ngBindTemplate', function(value) {
element.textContent = value === undefined ? '' : value;
element.textContent = isUndefined(value) ? '' : value;
});
};
}
+8 -5
View File
@@ -162,7 +162,7 @@ function classDirective(name, selector) {
* @example Example that demonstrates basic bindings via ngClass directive.
<example>
<file name="index.html">
<p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
<p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p>
<label>
<input type="checkbox" ng-model="deleted">
deleted (apply "strike" class)
@@ -173,7 +173,7 @@ function classDirective(name, selector) {
</label><br>
<label>
<input type="checkbox" ng-model="error">
error (apply "red" class)
error (apply "has-error" class)
</label>
<hr>
<p ng-class="style">Using String Syntax</p>
@@ -202,6 +202,10 @@ function classDirective(name, selector) {
.red {
color: red;
}
.has-error {
color: red;
background-color: yellow;
}
.orange {
color: orange;
}
@@ -212,13 +216,13 @@ function classDirective(name, selector) {
it('should let you toggle the class', function() {
expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
expect(ps.first().getAttribute('class')).not.toMatch(/red/);
expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);
element(by.model('important')).click();
expect(ps.first().getAttribute('class')).toMatch(/bold/);
element(by.model('error')).click();
expect(ps.first().getAttribute('class')).toMatch(/red/);
expect(ps.first().getAttribute('class')).toMatch(/has-error/);
});
it('should let you toggle string example', function() {
@@ -258,7 +262,6 @@ function classDirective(name, selector) {
</file>
<file name="style.css">
.base-class {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}
+47 -17
View File
@@ -6,27 +6,29 @@
*
* @element html
* @description
* Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
*
* Angular has some features that can break certain
* [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.
*
* If you intend to implement these rules then you must tell Angular not to use these features.
*
* This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
*
* CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
* For Angular to be CSP compatible there are only two things that we need to do differently:
*
* - don't use `Function` constructor to generate optimized value getters
* - don't inject custom stylesheet into the document
* The following rules affect Angular:
*
* AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
* directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
* evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
* be raised.
* * `unsafe-eval`: this rule forbids apps to use `eval` or `Function(string)` generated functions
* (among other things). Angular makes use of this in the {@link $parse} service to provide a 30%
* increase in the speed of evaluating Angular expressions.
*
* CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
* includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
* To make those directives work in CSP mode, include the `angular-csp.css` manually.
* * `unsafe-inline`: this rule forbids apps from inject custom styles into the document. Angular
* makes use of this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}).
* To make these directives work when a CSP rule is blocking inline styles, you must link to the
* `angular-csp.css` in your HTML manually.
*
* Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
* autodetection however triggers a CSP error to be logged in the console:
* If you do not provide `ngCsp` then Angular tries to autodetect if CSP is blocking unsafe-eval
* and automatically deactivates this feature in the {@link $parse} service. This autodetection,
* however, triggers a CSP error to be logged in the console:
*
* ```
* Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
@@ -35,11 +37,39 @@
* ```
*
* This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
* directive on the root element of the application or on the `angular.js` script tag, whichever
* appears first in the html document.
* directive on an element of the HTML document that appears before the `<script>` tag that loads
* the `angular.js` file.
*
* *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
*
* You can specify which of the CSP related Angular features should be deactivated by providing
* a value for the `ng-csp` attribute. The options are as follows:
*
* * no-inline-style: this stops Angular from injecting CSS styles into the DOM
*
* * no-unsafe-eval: this stops Angular from optimising $parse with unsafe eval of strings
*
* You can use these values in the following combinations:
*
*
* * No declaration means that Angular will assume that you can do inline styles, but it will do
* a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous versions
* of Angular.
*
* * A simple `ng-csp` (or `data-ng-csp`) attribute will tell Angular to deactivate both inline
* styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous versions
* of Angular.
*
* * Specifying only `no-unsafe-eval` tells Angular that we must not use eval, but that we can inject
* inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
*
* * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
* run eval - no automcatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
*
* * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
* styles nor use eval, which is the same as an empty: ng-csp.
* E.g.`<body ng-csp="no-inline-style;no-unsafe-eval">`
*
* @example
* This example shows how to apply the `ngCsp` directive to the `html` tag.
```html
@@ -171,4 +201,4 @@
// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
// bootstrap the system (before $parse is instantiated), for this reason we just have
// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
// the csp() fn that looks for the `ng-csp` attribute anywhere in the current doc
+1 -1
View File
@@ -4,6 +4,7 @@
* @ngdoc directive
* @name ngIf
* @restrict A
* @multiElement
*
* @description
* The `ngIf` directive removes or recreates a portion of the DOM tree based on an
@@ -60,7 +61,6 @@
}
.animate-if.ng-enter, .animate-if.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}
+3 -4
View File
@@ -85,7 +85,6 @@
}
.slide-animate.ng-enter, .slide-animate.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
position:absolute;
@@ -178,8 +177,8 @@
* @param {Object} angularEvent Synthetic event object.
* @param {String} src URL of content to load.
*/
var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',
function($templateRequest, $anchorScroll, $animate, $sce) {
var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
function($templateRequest, $anchorScroll, $animate) {
return {
restrict: 'ECA',
priority: 400,
@@ -215,7 +214,7 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce
}
};
scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
scope.$watch(srcExp, function ngIncludeWatchAction(src) {
var afterAnimation = function() {
if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
$anchorScroll();
+9 -7
View File
@@ -10,16 +10,18 @@
* current scope.
*
* <div class="alert alert-danger">
* The only appropriate use of `ngInit` is for aliasing special properties of
* {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
* should use {@link guide/controller controllers} rather than `ngInit`
* to initialize values on a scope.
* This directive can be abused to add unnecessary amounts of logic into your templates.
* There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
* {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
* server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
* rather than `ngInit` to initialize values on a scope.
* </div>
*
* <div class="alert alert-warning">
* **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
* sure you have parenthesis for correct precedence:
* **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
* sure you have parentheses to ensure correct operator precedence:
* <pre class="prettyprint">
* `<div ng-init="test1 = (data | orderBy:'name')"></div>`
* `<div ng-init="test1 = ($index | toString)"></div>`
* </pre>
* </div>
*
+47 -40
View File
@@ -16,8 +16,7 @@ var VALID_CLASS = 'ng-valid',
TOUCHED_CLASS = 'ng-touched',
PENDING_CLASS = 'ng-pending';
var $ngModelMinErr = new minErr('ngModel');
var ngModelMinErr = minErr('ngModel');
/**
* @ngdoc type
@@ -237,7 +236,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
this.$$success = {}; // keep valid keys here
this.$pending = undefined; // keep pending keys here
this.$name = $interpolate($attr.name || '', false)($scope);
this.$$parentForm = nullFormCtrl;
var parsedNgModel = $parse($attr.ngModel),
parsedNgModelAssign = parsedNgModel.assign,
@@ -268,7 +267,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
}
};
} else if (!parsedNgModel.assign) {
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
$attr.ngModel, startingTag($element));
}
};
@@ -317,8 +316,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
return isUndefined(value) || value === '' || value === null || value !== value;
};
var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
currentValidationRunId = 0;
var currentValidationRunId = 0;
/**
* @ngdoc method
@@ -351,7 +349,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
unset: function(object, property) {
delete object[property];
},
parentForm: parentForm,
$animate: $animate
});
@@ -389,7 +386,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
ctrl.$pristine = false;
$animate.removeClass($element, PRISTINE_CLASS);
$animate.addClass($element, DIRTY_CLASS);
parentForm.$setDirty();
ctrl.$$parentForm.$setDirty();
};
/**
@@ -559,7 +556,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
function processParseErrors() {
var errorKey = ctrl.$$parserName || 'parse';
if (parserValid === undefined) {
if (isUndefined(parserValid)) {
setValidity(errorKey, null);
} else {
if (!parserValid) {
@@ -599,7 +596,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("$asyncValidators",
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
}
setValidity(name, undefined);
@@ -729,37 +726,47 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* @description
* Update the view value.
*
* This method should be called when an input directive want to change the view value; typically,
* this is done from within a DOM event handler.
* This method should be called when a control wants to change the view value; typically,
* this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
* directive calls it when the value of the input changes and {@link ng.directive:select select}
* calls it when an option is selected.
*
* For example {@link ng.directive:input input} calls it when the value of the input changes and
* {@link ng.directive:select select} calls it when an option is selected.
*
* If the new `value` is an object (rather than a string or a number), we should make a copy of the
* object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
* watch of objects, it only looks for a change of identity. If you only change the property of
* the object then ngModel will not realise that the object has changed and will not invoke the
* `$parsers` and `$validators` pipelines.
*
* For this reason, you should not change properties of the copy once it has been passed to
* `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
*
* When this method is called, the new `value` will be staged for committing through the `$parsers`
* When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
* and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
* value sent directly for processing, finally to be applied to `$modelValue` and then the
* **expression** specified in the `ng-model` attribute.
*
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
* **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
* in the `$viewChangeListeners` list, are called.
*
* In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
* and the `default` trigger is not listed, all those actions will remain pending until one of the
* `updateOn` events is triggered on the DOM element.
* All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
* directive is used with a custom debounce for this particular event.
* Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
* is specified, once the timer runs out.
*
* Note that calling this function does not trigger a `$digest`.
* When used with standard inputs, the view value will always be a string (which is in some cases
* parsed into another type, such as a `Date` object for `input[date]`.)
* However, custom controls might also pass objects to this method. In this case, we should make
* a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
* perform a deep watch of objects, it only looks for a change of identity. If you only change
* the property of the object then ngModel will not realise that the object has changed and
* will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
* not change properties of the copy once it has been passed to `$setViewValue`.
* Otherwise you may cause the model value on the scope to change incorrectly.
*
* @param {string} value Value from the view.
* <div class="alert alert-info">
* In any case, the value passed to the method should always reflect the current value
* of the control. For example, if you are calling `$setViewValue` for an input element,
* you should pass the input DOM value. Otherwise, the control and the scope model become
* out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
* the control's DOM value in any way. If we want to change the control's DOM value
* programmatically, we should update the `ngModel` scope expression. Its new value will be
* picked up by the model controller, which will run it through the `$formatters`, `$render` it
* to update the DOM, and finally call `$validate` on it.
* </div>
*
* @param {*} value value from the view.
* @param {string} trigger Event that triggered the update.
*/
this.$setViewValue = function(value, trigger) {
@@ -936,7 +943,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
</script>
<style>
.my-input {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
background: transparent;
}
@@ -1023,7 +1029,7 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
return {
pre: function ngModelPreLink(scope, element, attr, ctrls) {
var modelCtrl = ctrls[0],
formCtrl = ctrls[1] || nullFormCtrl;
formCtrl = ctrls[1] || modelCtrl.$$parentForm;
modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
@@ -1032,12 +1038,12 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
attr.$observe('name', function(newValue) {
if (modelCtrl.$name !== newValue) {
formCtrl.$$renameControl(modelCtrl, newValue);
modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
}
});
scope.$on('$destroy', function() {
formCtrl.$removeControl(modelCtrl);
modelCtrl.$$parentForm.$removeControl(modelCtrl);
});
},
post: function ngModelPostLink(scope, element, attr, ctrls) {
@@ -1101,7 +1107,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
* - `debounce`: integer value which contains the debounce model update value in milliseconds. A
* value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
* custom value for each event. For example:
* `ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
* `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"`
* - `allowInvalid`: boolean value which indicates that the model can be set with values that did
* not validate correctly instead of the default behavior of setting the model to undefined.
* - `getterSetter`: boolean value which determines whether or not to treat functions bound to
@@ -1236,7 +1242,7 @@ var ngModelOptionsDirective = function() {
var that = this;
this.$options = copy($scope.$eval($attrs.ngModelOptions));
// Allow adding/overriding bound events
if (this.$options.updateOn !== undefined) {
if (isDefined(this.$options.updateOn)) {
this.$options.updateOnDefault = false;
// extract "default" pseudo-event from list of events that can trigger a model update
this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
@@ -1259,7 +1265,6 @@ function addSetValidityMethod(context) {
classCache = {},
set = context.set,
unset = context.unset,
parentForm = context.parentForm,
$animate = context.$animate;
classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
@@ -1267,7 +1272,7 @@ function addSetValidityMethod(context) {
ctrl.$setValidity = setValidity;
function setValidity(validationErrorKey, state, controller) {
if (state === undefined) {
if (isUndefined(state)) {
createAndSet('$pending', validationErrorKey, controller);
} else {
unsetAndCleanup('$pending', validationErrorKey, controller);
@@ -1311,7 +1316,7 @@ function addSetValidityMethod(context) {
}
toggleValidationCss(validationErrorKey, combinedState);
parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
}
function createAndSet(name, value, controller) {
@@ -1351,7 +1356,9 @@ function addSetValidityMethod(context) {
function isObjectEmpty(obj) {
if (obj) {
for (var prop in obj) {
return false;
if (obj.hasOwnProperty(prop)) {
return false;
}
}
}
return true;
+32 -25
View File
@@ -64,7 +64,7 @@ var ngOptionsMinErr = minErr('ngOptions');
* Consider the following example:
*
* ```html
* <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
* <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"></select>
* ```
*
* ```js
@@ -292,19 +292,41 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
this.disabled = disabled;
}
function getOptionValuesKeys(optionValues) {
var optionValuesKeys;
if (!keyName && isArrayLike(optionValues)) {
optionValuesKeys = optionValues;
} else {
// if object, extract keys, in enumeration order, unsorted
optionValuesKeys = [];
for (var itemKey in optionValues) {
if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
optionValuesKeys.push(itemKey);
}
}
}
return optionValuesKeys;
}
return {
trackBy: trackBy,
getTrackByValue: getTrackByValue,
getWatchables: $parse(valuesFn, function(values) {
getWatchables: $parse(valuesFn, function(optionValues) {
// Create a collection of things that we would like to watch (watchedArray)
// so that they can all be watched using a single $watchCollection
// that only runs the handler once if anything changes
var watchedArray = [];
values = values || [];
optionValues = optionValues || [];
Object.keys(values).forEach(function getWatchable(key) {
var locals = getLocals(values[key], key);
var selectValue = getTrackByValueFn(values[key], locals);
var optionValuesKeys = getOptionValuesKeys(optionValues);
var optionValuesLength = optionValuesKeys.length;
for (var index = 0; index < optionValuesLength; index++) {
var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
var value = optionValues[key];
var locals = getLocals(optionValues[key], key);
var selectValue = getTrackByValueFn(optionValues[key], locals);
watchedArray.push(selectValue);
// Only need to watch the displayFn if there is a specific label expression
@@ -318,7 +340,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
var disableWhen = disableWhenFn(scope, locals);
watchedArray.push(disableWhen);
}
});
}
return watchedArray;
}),
@@ -330,21 +352,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// The option values were already computed in the `getWatchables` fn,
// which must have been called to trigger `getOptions`
var optionValues = valuesFn(scope) || [];
var optionValuesKeys;
if (!keyName && isArrayLike(optionValues)) {
optionValuesKeys = optionValues;
} else {
// if object, extract keys, in enumeration order, unsorted
optionValuesKeys = [];
for (var itemKey in optionValues) {
if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
optionValuesKeys.push(itemKey);
}
}
}
var optionValuesKeys = getOptionValuesKeys(optionValues);
var optionValuesLength = optionValuesKeys.length;
for (var index = 0; index < optionValuesLength; index++) {
@@ -518,7 +526,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
forEach(selectedValues, function(value) {
var option = options.selectValueMap[value];
if (!option.disabled) selections.push(options.getViewValueFromOption(option));
if (option && !option.disabled) selections.push(options.getViewValueFromOption(option));
});
return selections;
@@ -706,8 +714,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// Check to see if the value has changed due to the update to the options
if (!ngModelCtrl.$isEmpty(previousValue)) {
var nextValue = selectCtrl.readValue();
if (ngOptions.trackBy && !equals(previousValue, nextValue) ||
previousValue !== nextValue) {
if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
ngModelCtrl.$setViewValue(nextValue);
ngModelCtrl.$render();
}
+18 -6
View File
@@ -3,6 +3,7 @@
/**
* @ngdoc directive
* @name ngRepeat
* @multiElement
*
* @description
* The `ngRepeat` directive instantiates a template once per item from a collection. Each template
@@ -20,8 +21,10 @@
* | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
* | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
*
* Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
* This may be useful when, for instance, nesting ngRepeats.
* <div class="alert alert-info">
* Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
* This may be useful when, for instance, nesting ngRepeats.
* </div>
*
*
* # Iterating over object properties
@@ -97,6 +100,15 @@
* </div>
* ```
*
* <div class="alert alert-warning">
* **Note:** `track by` must always be the last expression:
* </div>
* ```
* <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
* {{model.name}}
* </div>
* ```
*
* # Special repeat start and end points
* To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
* the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
@@ -168,8 +180,9 @@
* which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
* is specified, ng-repeat associates elements by identity. It is an error to have
* more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
* mapped to the same DOM element, which is not possible.) If filters are used in the expression, they should be
* applied before the tracking expression.
* mapped to the same DOM element, which is not possible.)
*
* Note that the tracking expression must come last, after any filters, and the alias expression.
*
* For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
* will be associated by item identity in the array.
@@ -245,7 +258,6 @@
.animate-repeat.ng-move,
.animate-repeat.ng-enter,
.animate-repeat.ng-leave {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
}
@@ -417,7 +429,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
// if object, extract keys, in enumeration order, unsorted
collectionKeys = [];
for (var itemKey in collection) {
if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
collectionKeys.push(itemKey);
}
}
+3 -4
View File
@@ -5,6 +5,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
/**
* @ngdoc directive
* @name ngShow
* @multiElement
*
* @description
* The `ngShow` directive shows or hides the given HTML element based on the expression
@@ -124,9 +125,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
background: white;
}
.animate-show.ng-hide-add.ng-hide-add-active,
.animate-show.ng-hide-remove.ng-hide-remove-active {
-webkit-transition: all linear 0.5s;
.animate-show.ng-hide-add, .animate-show.ng-hide-remove {
transition: all linear 0.5s;
}
@@ -180,6 +179,7 @@ var ngShowDirective = ['$animate', function($animate) {
/**
* @ngdoc directive
* @name ngHide
* @multiElement
*
* @description
* The `ngHide` directive shows or hides the given HTML element based on the expression
@@ -282,7 +282,6 @@ var ngShowDirective = ['$animate', function($animate) {
</file>
<file name="animations.css">
.animate-hide {
-webkit-transition: all linear 0.5s;
transition: all linear 0.5s;
line-height: 20px;
opacity: 1;
-1
View File
@@ -91,7 +91,6 @@
}
.animate-switch.ng-animate {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
position:absolute;
+173 -25
View File
@@ -108,31 +108,162 @@ var SelectController =
* @description
* HTML `SELECT` element with angular data-binding.
*
* In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
* ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits such as reducing
* memory and increasing speed by not creating a new scope for each repeated instance, as well as providing
* more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
* comprehension expression.
* The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
* between the scope and the `<select>` control (including setting default values).
* Ìt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
* {@link ngOptions `ngOptions`} directives.
*
* When an item in the `<select>` menu is selected, the array element or object property
* represented by the selected option will be bound to the model identified by the `ngModel`
* directive.
* When an item in the `<select>` menu is selected, the value of the selected option will be bound
* to the model identified by the `ngModel` directive. With static or repeated options, this is
* the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
* If you want dynamic value attributes, you can use interpolation inside the value attribute.
*
* If the viewValue contains a value that doesn't match any of the options then the control
* will automatically add an "unknown" option, which it then removes when this is resolved.
* <div class="alert alert-warning">
* Note that the value of a `select` directive used without `ngOptions` is always a string.
* When the model needs to be bound to a non-string value, you must either explictly convert it
* using a directive (see example below) or use `ngOptions` to specify the set of options.
* This is because an option element can only be bound to string values at present.
* </div>
*
* If the viewValue of `ngModel` does not match any of the options, then the control
* will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
*
* Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
* be nested into the `<select>` element. This element will then represent the `null` or "not selected"
* option. See example below for demonstration.
*
* <div class="alert alert-info">
* The value of a `select` directive used without `ngOptions` is always a string.
* When the model needs to be bound to a non-string value, you must either explictly convert it
* using a directive (see example below) or use `ngOptions` to specify the set of options.
* This is because an option element can only be bound to string values at present.
* In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
* ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
* more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
* comprehension expression, and additionally in reducing memory and increasing speed by not creating
* a new scope for each repeated instance.
* </div>
*
* ### Example (binding `select` to a non-string value)
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} required Sets `required` validation error key if the value is not entered.
* @param {string=} ngRequired Adds required attribute and required validation constraint to
* the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
* when you want to data-bind to the required attribute.
* @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
* interaction with the select element.
* @param {string=} ngOptions sets the options that the select is populated with and defines what is
* set on the model on selection. See {@link ngOptions `ngOptions`}.
*
* @example
* ### Simple `select` elements with static options
*
* <example name="static-select" module="staticSelect">
* <file name="index.html">
* <div ng-controller="ExampleController">
* <form name="myForm">
* <label for="singleSelect"> Single select: </label><br>
* <select name="singleSelect" ng-model="data.singleSelect">
* <option value="option-1">Option 1</option>
* <option value="option-2">Option 2</option>
* </select><br>
*
* <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
* <select name="singleSelect" ng-model="data.singleSelect">
* <option value="">---Please select---</option> <!-- not selected / blank option -->
* <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
* <option value="option-2">Option 2</option>
* </select><br>
* <button ng-click="forceUnknownOption()">Force unknown option</button><br>
* <tt>singleSelect = {{data.singleSelect}}</tt>
*
* <hr>
* <label for="multipleSelect"> Multiple select: </label><br>
* <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
* <option value="option-1">Option 1</option>
* <option value="option-2">Option 2</option>
* <option value="option-3">Option 3</option>
* </select><br>
* <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
* </form>
* </div>
* </file>
* <file name="app.js">
* angular.module('staticSelect', [])
* .controller('ExampleController', ['$scope', function($scope) {
* $scope.data = {
* singleSelect: null,
* multipleSelect: [],
* option1: 'option-1',
* };
*
* $scope.forceUnknownOption = function() {
* $scope.data.singleSelect = 'nonsense';
* };
* }]);
* </file>
*</example>
*
* ### Using `ngRepeat` to generate `select` options
* <example name="ngrepeat-select" module="ngrepeatSelect">
* <file name="index.html">
* <div ng-controller="ExampleController">
* <form name="myForm">
* <label for="repeatSelect"> Repeat select: </label>
* <select name="repeatSelect" ng-model="data.repeatSelect">
* <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
* </select>
* </form>
* <hr>
* <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
* </div>
* </file>
* <file name="app.js">
* angular.module('ngrepeatSelect', [])
* .controller('ExampleController', ['$scope', function($scope) {
* $scope.data = {
* singleSelect: null,
* availableOptions: [
* {id: '1', name: 'Option A'},
* {id: '2', name: 'Option B'},
* {id: '3', name: 'Option C'}
* ],
* };
* }]);
* </file>
*</example>
*
*
* ### Using `select` with `ngOptions` and setting a default value
* See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.
*
* <example name="select-with-default-values" module="defaultValueSelect">
* <file name="index.html">
* <div ng-controller="ExampleController">
* <form name="myForm">
* <label for="mySelect">Make a choice:</label>
* <select name="mySelect" id="mySelect"
* ng-options="option.name for option in data.availableOptions track by option.id"
* ng-model="data.selectedOption"></select>
* </form>
* <hr>
* <tt>option = {{data.selectedOption}}</tt><br/>
* </div>
* </file>
* <file name="app.js">
* angular.module('defaultValueSelect', [])
* .controller('ExampleController', ['$scope', function($scope) {
* $scope.data = {
* availableOptions: [
* {id: '1', name: 'Option A'},
* {id: '2', name: 'Option B'},
* {id: '3', name: 'Option C'}
* ],
* selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
* };
* }]);
* </file>
*</example>
*
*
* ### Binding `select` to a non-string value via `ngModel` parsing / formatting
*
* <example name="select-with-non-string-options" module="nonStringSelect">
* <file name="index.html">
@@ -270,9 +401,12 @@ var optionDirective = ['$interpolate', function($interpolate) {
priority: 100,
compile: function(element, attr) {
// If the value attribute is not defined then we fall back to the
// text content of the option element, which may be interpolated
if (isUndefined(attr.value)) {
if (isDefined(attr.value)) {
// If the value attribute is defined, check if it contains an interpolation
var valueInterpolated = $interpolate(attr.value, true);
} else {
// If the value attribute is not defined then we fall back to the
// text content of the option element, which may be interpolated
var interpolateFn = $interpolate(element.text(), true);
if (!interpolateFn) {
attr.$set('value', element.text());
@@ -288,24 +422,38 @@ var optionDirective = ['$interpolate', function($interpolate) {
selectCtrl = parent.data(selectCtrlName) ||
parent.parent().data(selectCtrlName); // in case we are in optgroup
function addOption(optionValue) {
selectCtrl.addOption(optionValue, element);
selectCtrl.ngModelCtrl.$render();
chromeHack(element);
}
// Only update trigger option updates if this is an option within a `select`
// that also has `ngModel` attached
if (selectCtrl && selectCtrl.ngModelCtrl) {
if (interpolateFn) {
if (valueInterpolated) {
// The value attribute is interpolated
var oldVal;
attr.$observe('value', function valueAttributeObserveAction(newVal) {
if (isDefined(oldVal)) {
selectCtrl.removeOption(oldVal);
}
oldVal = newVal;
addOption(newVal);
});
} else if (interpolateFn) {
// The text content is interpolated
scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
attr.$set('value', newVal);
if (oldVal !== newVal) {
selectCtrl.removeOption(oldVal);
}
selectCtrl.addOption(newVal, element);
selectCtrl.ngModelCtrl.$render();
chromeHack(element);
addOption(newVal);
});
} else {
selectCtrl.addOption(attr.value, element);
selectCtrl.ngModelCtrl.$render();
chromeHack(element);
// The value attribute is static
addOption(attr.value);
}
element.on('$destroy', function() {
+3 -2
View File
@@ -43,8 +43,9 @@ var patternDirective = function() {
ctrl.$validate();
});
ctrl.$validators.pattern = function(value) {
return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);
ctrl.$validators.pattern = function(modelValue, viewValue) {
// HTML5 pattern constraint validates the input value, so we validate the viewValue
return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
};
}
};
+1
View File
@@ -115,6 +115,7 @@ function $FilterProvider($provide) {
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
* (`myapp_subsection_filterx`).
* </div>
* @param {Function} factory If the first argument was a string, a factory function for the filter to be registered.
* @returns {Object} Registered filter instance, or if a map of filters was provided then a map
* of the registered filter instances.
*/
+5 -7
View File
@@ -34,9 +34,11 @@
* `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
* **will** be matched by `{$: 'John'}`.
*
* - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
* function is called for each element of `array`. The final result is an array of those
* elements that the predicate returned true for.
* - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.
* The function is called for each element of the array, with the element, its index, and
* the entire array itself as arguments.
*
* The final result is an array of those elements that the predicate returned true for.
*
* @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
* determining if the expected value (from the filter expression) and actual value (from
@@ -161,10 +163,6 @@ function filterFilter() {
};
}
function hasCustomToString(obj) {
return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
}
// Helper functions for `filterFilter`
function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
+5 -4
View File
@@ -45,9 +45,9 @@
}
element(by.model('amount')).clear();
element(by.model('amount')).sendKeys('-1234');
expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');
expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');
expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00');
expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00');
expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234');
});
</file>
</example>
@@ -80,9 +80,10 @@ function currencyFilter($locale) {
* @description
* Formats a number as text.
*
* If the input is null or undefined, it will just be returned.
* If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
* If the input is not a number an empty string is returned.
*
* If the input is an infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
*
* @param {number|string} number Number to format.
* @param {(number|string)=} fractionSize Number of decimal places to round the number to.
+133 -82
View File
@@ -8,7 +8,7 @@
* @description
* Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
* for strings and numerically for numbers. Note: if you notice numbers are not being sorted
* correctly, make sure they are actually being saved as numbers and not strings.
* as expected, make sure they are actually being saved as numbers and not strings.
*
* @param {Array} array The array to sort.
* @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
@@ -83,19 +83,40 @@
{name:'Mike', phone:'555-4321', age:21},
{name:'Adam', phone:'555-5678', age:35},
{name:'Julie', phone:'555-8765', age:29}];
$scope.predicate = '-age';
$scope.predicate = 'age';
$scope.reverse = true;
$scope.order = function(predicate) {
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
$scope.predicate = predicate;
};
}]);
</script>
<style type="text/css">
.sortorder:after {
content: '\25b2';
}
.sortorder.reverse:after {
content: '\25bc';
}
</style>
<div ng-controller="ExampleController">
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
<hr/>
[ <a href="" ng-click="predicate=''">unsorted</a> ]
<table class="friend">
<tr>
<th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
(<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
<th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
<th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
<th>
<a href="" ng-click="order('name')">Name</a>
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
</th>
<th>
<a href="" ng-click="order('phone')">Phone Number</a>
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
</th>
<th>
<a href="" ng-click="order('age')">Age</a>
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
</th>
</tr>
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
<td>{{friend.name}}</td>
@@ -155,88 +176,118 @@
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse) {
return function(array, sortPredicate, reverseOrder) {
if (!(isArrayLike(array))) return array;
sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];
if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
if (sortPredicate.length === 0) { sortPredicate = ['+']; }
sortPredicate = sortPredicate.map(function(predicate) {
var descending = false, get = predicate || identity;
if (isString(predicate)) {
if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
descending = predicate.charAt(0) == '-';
predicate = predicate.substring(1);
}
if (predicate === '') {
// Effectively no predicate was passed so we compare identity
return reverseComparator(compare, descending);
}
get = $parse(predicate);
if (get.constant) {
var key = get();
return reverseComparator(function(a, b) {
return compare(a[key], b[key]);
}, descending);
}
}
return reverseComparator(function(a, b) {
return compare(get(a),get(b));
}, descending);
});
return slice.call(array).sort(reverseComparator(comparator, reverseOrder));
function comparator(o1, o2) {
for (var i = 0; i < sortPredicate.length; i++) {
var comp = sortPredicate[i](o1, o2);
if (comp !== 0) return comp;
}
return 0;
}
function reverseComparator(comp, descending) {
return descending
? function(a, b) {return comp(b,a);}
: comp;
var predicates = processPredicates(sortPredicate, reverseOrder);
// Add a predicate at the end that evaluates to the element index. This makes the
// sort stable as it works as a tie-breaker when all the input predicates cannot
// distinguish between two elements.
predicates.push({ get: function() { return {}; }, descending: reverseOrder ? -1 : 1});
// The next three lines are a version of a Swartzian Transform idiom from Perl
// (sometimes called the Decorate-Sort-Undecorate idiom)
// See https://en.wikipedia.org/wiki/Schwartzian_transform
var compareValues = Array.prototype.map.call(array, getComparisonObject);
compareValues.sort(doComparison);
array = compareValues.map(function(item) { return item.value; });
return array;
function getComparisonObject(value, index) {
return {
value: value,
predicateValues: predicates.map(function(predicate) {
return getPredicateValue(predicate.get(value), index);
})
};
}
function isPrimitive(value) {
switch (typeof value) {
case 'number': /* falls through */
case 'boolean': /* falls through */
case 'string':
return true;
default:
return false;
}
}
function objectToString(value) {
if (value === null) return 'null';
if (typeof value.valueOf === 'function') {
value = value.valueOf();
if (isPrimitive(value)) return value;
}
if (typeof value.toString === 'function') {
value = value.toString();
if (isPrimitive(value)) return value;
}
return '';
}
function compare(v1, v2) {
var t1 = typeof v1;
var t2 = typeof v2;
if (t1 === t2 && t1 === "object") {
v1 = objectToString(v1);
v2 = objectToString(v2);
}
if (t1 === t2) {
if (t1 === "string") {
v1 = v1.toLowerCase();
v2 = v2.toLowerCase();
}
if (v1 === v2) return 0;
return v1 < v2 ? -1 : 1;
} else {
return t1 < t2 ? -1 : 1;
function doComparison(v1, v2) {
var result = 0;
for (var index=0, length = predicates.length; index < length; ++index) {
result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending;
if (result) break;
}
return result;
}
};
function processPredicates(sortPredicate, reverseOrder) {
reverseOrder = reverseOrder ? -1 : 1;
return sortPredicate.map(function(predicate) {
var descending = 1, get = identity;
if (isFunction(predicate)) {
get = predicate;
} else if (isString(predicate)) {
if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
descending = predicate.charAt(0) == '-' ? -1 : 1;
predicate = predicate.substring(1);
}
if (predicate !== '') {
get = $parse(predicate);
if (get.constant) {
var key = get();
get = function(value) { return value[key]; };
}
}
}
return { get: get, descending: descending * reverseOrder };
});
}
function isPrimitive(value) {
switch (typeof value) {
case 'number': /* falls through */
case 'boolean': /* falls through */
case 'string':
return true;
default:
return false;
}
}
function objectValue(value, index) {
// If `valueOf` is a valid function use that
if (typeof value.valueOf === 'function') {
value = value.valueOf();
if (isPrimitive(value)) return value;
}
// If `toString` is a valid function and not the one from `Object.prototype` use that
if (hasCustomToString(value)) {
value = value.toString();
if (isPrimitive(value)) return value;
}
// We have a basic object so we use the position of the object in the collection
return index;
}
function getPredicateValue(value, index) {
var type = typeof value;
if (value === null) {
type = 'string';
value = 'null';
} else if (type === 'string') {
value = value.toLowerCase();
} else if (type === 'object') {
value = objectValue(value, index);
}
return { value: value, type: type };
}
function compare(v1, v2) {
var result = 0;
if (v1.type === v2.type) {
if (v1.value !== v2.value) {
result = v1.value < v2.value ? -1 : 1;
}
} else {
result = v1.type < v2.type ? -1 : 1;
}
return result;
}
}
+24
View File
@@ -0,0 +1,24 @@
'use strict';
var $$ForceReflowProvider = function() {
this.$get = ['$document', function($document) {
return function(domNode) {
//the line below will force the browser to perform a repaint so
//that all the animated elements within the animation frame will
//be properly updated and drawn on screen. This is required to
//ensure that the preparation animation is properly flushed so that
//the active state picks up from there. DO NOT REMOVE THIS LINE.
//DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH
//WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
//WILL TAKE YEARS AWAY FROM YOUR LIFE.
if (domNode) {
if (!domNode.nodeType && domNode instanceof jqLite) {
domNode = domNode[0];
}
} else {
domNode = $document[0].body;
}
return domNode.offsetWidth + 1;
};
}];
};
+145 -68
View File
@@ -8,6 +8,12 @@ var JSON_ENDS = {
'{': /}$/
};
var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
var $httpMinErr = minErr('$http');
var $httpMinErrLegacyFn = function(method) {
return function() {
throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method);
};
};
function serializeValue(v) {
if (isObject(v)) {
@@ -23,13 +29,17 @@ function $HttpParamSerializerProvider() {
* @name $httpParamSerializer
* @description
*
* Default $http params serializer that converts objects to a part of a request URL
* Default {@link $http `$http`} params serializer that converts objects to strings
* according to the following rules:
*
* * `{'foo': 'bar'}` results in `foo=bar`
* * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
* * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
* * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
*
* Note that serializer will sort the request parameters alphabetically.
* */
this.$get = function() {
return function ngParamSerializer(params) {
if (!params) return '';
@@ -56,7 +66,43 @@ function $HttpParamSerializerJQLikeProvider() {
* @name $httpParamSerializerJQLike
* @description
*
* Alternative $http params serializer that follows jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
* Alternative {@link $http `$http`} params serializer that follows
* jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
* The serializer will also sort the params alphabetically.
*
* To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:
*
* ```js
* $http({
* url: myUrl,
* method: 'GET',
* params: myParams,
* paramSerializer: '$httpParamSerializerJQLike'
* });
* ```
*
* It is also possible to set it as the default `paramSerializer` in the
* {@link $httpProvider#defaults `$httpProvider`}.
*
* Additionally, you can inject the serializer and use it explicitly, for example to serialize
* form data for submission:
*
* ```js
* .controller(function($http, $httpParamSerializerJQLike) {
* //...
*
* $http({
* url: myUrl,
* method: 'POST',
* data: $httpParamSerializerJQLike(myData),
* headers: {
* 'Content-Type': 'application/x-www-form-urlencoded'
* }
* });
*
* });
* ```
*
* */
this.$get = function() {
return function jQueryLikeParamSerializer(params) {
@@ -68,8 +114,8 @@ function $HttpParamSerializerJQLikeProvider() {
function serialize(toSerialize, prefix, topLevel) {
if (toSerialize === null || isUndefined(toSerialize)) return;
if (isArray(toSerialize)) {
forEach(toSerialize, function(value) {
serialize(value, prefix + '[]');
forEach(toSerialize, function(value, index) {
serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
});
} else if (isObject(toSerialize) && !isDate(toSerialize)) {
forEachSorted(toSerialize, function(value, key) {
@@ -213,7 +259,7 @@ function $HttpProvider() {
*
* - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
* that will provide the cache for all requests who set their `cache` property to `true`.
* If you set the `default.cache = false` then only requests that specify their own custom
* If you set the `defaults.cache = false` then only requests that specify their own custom
* cache object will be cached. See {@link $http#caching $http Caching} for more information.
*
* - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
@@ -230,10 +276,11 @@ function $HttpProvider() {
* - **`defaults.headers.put`**
* - **`defaults.headers.patch`**
*
* - **`defaults.paramSerializer`** - {string|function(Object<string,string>):string} - A function used to prepare string representation
* of request parameters (specified as an object).
* If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
* Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
*
* - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
* used to the prepare string representation of request parameters (specified as an object).
* If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
* Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
*
**/
var defaults = this.defaults = {
@@ -289,6 +336,30 @@ function $HttpProvider() {
return useApplyAsync;
};
var useLegacyPromise = true;
/**
* @ngdoc method
* @name $httpProvider#useLegacyPromiseExtensions
* @description
*
* Configure `$http` service to return promises without the shorthand methods `success` and `error`.
* This should be used to make sure that applications work without these methods.
*
* Defaults to false. If no value is specified, returns the current configured value.
*
* @param {boolean=} value If true, `$http` will return a normal promise without the `success` and `error` methods.
*
* @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
* otherwise, returns the current configured value.
**/
this.useLegacyPromiseExtensions = function(value) {
if (isDefined(value)) {
useLegacyPromise = !!value;
return this;
}
return useLegacyPromise;
};
/**
* @ngdoc property
* @name $httpProvider#interceptors
@@ -355,17 +426,15 @@ function $HttpProvider() {
*
* ## General usage
* The `$http` service is a function which takes a single argument a configuration object
* that is used to generate an HTTP request and returns a {@link ng.$q promise}
* with two $http specific methods: `success` and `error`.
* that is used to generate an HTTP request and returns a {@link ng.$q promise}.
*
* ```js
* // Simple GET request example :
* $http.get('/someUrl').
* success(function(data, status, headers, config) {
* then(function(response) {
* // this callback will be called asynchronously
* // when the response is available
* }).
* error(function(data, status, headers, config) {
* }, function(response) {
* // called asynchronously if an error occurs
* // or server returns response with an error status.
* });
@@ -374,21 +443,23 @@ function $HttpProvider() {
* ```js
* // Simple POST request example (passing data) :
* $http.post('/someUrl', {msg:'hello word!'}).
* success(function(data, status, headers, config) {
* then(function(response) {
* // this callback will be called asynchronously
* // when the response is available
* }).
* error(function(data, status, headers, config) {
* }, function(response) {
* // called asynchronously if an error occurs
* // or server returns response with an error status.
* });
* ```
*
* The response object has these properties:
*
* Since the returned value of calling the $http function is a `promise`, you can also use
* the `then` method to register callbacks, and these callbacks will receive a single argument
* an object representing the response. See the API signature and type info below for more
* details.
* - **data** `{string|Object}` The response body transformed with the transform
* functions.
* - **status** `{number}` HTTP status code of the response.
* - **headers** `{function([headerName])}` Header getter function.
* - **config** `{Object}` The configuration object that was used to generate the request.
* - **statusText** `{string}` HTTP status text of the response.
*
* A response status code between 200 and 299 is considered a success status and
* will result in the success callback being called. Note that if the response is a redirect,
@@ -412,8 +483,8 @@ function $HttpProvider() {
* request data must be passed in for POST/PUT requests.
*
* ```js
* $http.get('/someUrl').success(successCallback);
* $http.post('/someUrl', data).success(successCallback);
* $http.get('/someUrl').then(successCallback);
* $http.post('/someUrl', data).then(successCallback);
* ```
*
* Complete list of shortcut methods:
@@ -427,6 +498,14 @@ function $HttpProvider() {
* - {@link ng.$http#patch $http.patch}
*
*
* ## Deprecation Notice
* <div class="alert alert-danger">
* The `$http` legacy promise methods `success` and `error` have been deprecated.
* Use the standard `then` method instead.
* If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to
* `false` then these methods will throw {@link $http:legacy `$http/legacy`} error.
* </div>
*
* ## Setting HTTP Headers
*
* The $http service will automatically add certain HTTP headers to all requests. These defaults
@@ -470,7 +549,7 @@ function $HttpProvider() {
* data: { test: 'test' }
* }
*
* $http(req).success(function(){...}).error(function(){...});
* $http(req).then(function(){...}, function(){...});
* ```
*
* ## Transforming Requests and Responses
@@ -699,15 +778,16 @@ function $HttpProvider() {
* properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
* or the per-request config object.
*
* In order to prevent collisions in environments where multiple Angular apps share the
* same domain or subdomain, we recommend that each application uses unique cookie name.
*
* @param {object} config Object describing the request to be made and how it should be
* processed. The object has following properties:
*
* - **method** `{string}` HTTP method (e.g. 'GET', 'POST', etc)
* - **url** `{string}` Absolute or relative URL of the resource that is being requested.
* - **params** `{Object.<string|Object>}` Map of strings or objects which will be turned
* to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
* JSONified.
* - **params** `{Object.<string|Object>}` Map of strings or objects which will be serialized
* with the `paramSerializer` and appended as GET parameters.
* - **data** `{string|Object}` Data to be sent as the request message data.
* - **headers** `{Object}` Map of strings or functions which return strings representing
* HTTP headers to send to the server. If the return value of a function is null, the
@@ -725,10 +805,14 @@ function $HttpProvider() {
* transform function or an array of such functions. The transform function takes the http
* response body, headers and status and returns its transformed (typically deserialized) version.
* See {@link ng.$http#overriding-the-default-transformations-per-request
* Overriding the Default Transformations}
* - **paramSerializer** - {string|function(Object<string,string>):string} - A function used to prepare string representation
* of request parameters (specified as an object).
* Is specified as string, it is interpreted as function registered in with the {$injector}.
* Overriding the Default TransformationjqLiks}
* - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to
* prepare the string representation of request parameters (specified as an object).
* If specified as string, it is interpreted as function registered with the
* {@link $injector $injector}, which means you can create your own serializer
* by registering it as a {@link auto.$provide#service service}.
* The default serializer is the {@link $httpParamSerializer $httpParamSerializer};
* alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}
* - **cache** `{boolean|Cache}` If true, a default $http cache will be used to cache the
* GET request, otherwise if a cache instance built with
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
@@ -739,22 +823,11 @@ function $HttpProvider() {
* XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
* for more information.
* - **responseType** - `{string}` - see
* [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
* [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
*
* @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
* standard `then` method and two http specific methods: `success` and `error`. The `then`
* method takes two arguments a success and an error callback which will be called with a
* response object. The `success` and `error` methods take a single argument - a function that
* will be called when the request succeeds or fails respectively. The arguments passed into
* these functions are destructured representation of the response object passed into the
* `then` method. The response object has these properties:
* @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object
* when the request succeeds or fails.
*
* - **data** `{string|Object}` The response body transformed with the transform
* functions.
* - **status** `{number}` HTTP status code of the response.
* - **headers** `{function([headerName])}` Header getter function.
* - **config** `{Object}` The configuration object that was used to generate the request.
* - **statusText** `{string}` HTTP status text of the response.
*
* @property {Array.<Object>} pendingRequests Array of config objects for currently pending
* requests. This is primarily meant to be used for debugging purposes.
@@ -796,13 +869,12 @@ function $HttpProvider() {
$scope.response = null;
$http({method: $scope.method, url: $scope.url, cache: $templateCache}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
}).
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
then(function(response) {
$scope.status = response.status;
$scope.data = response.data;
}, function(response) {
$scope.data = response.data || "Request failed";
$scope.status = response.status;
});
};
@@ -907,23 +979,28 @@ function $HttpProvider() {
promise = promise.then(thenFn, rejectFn);
}
promise.success = function(fn) {
assertArgFn(fn, 'fn');
if (useLegacyPromise) {
promise.success = function(fn) {
assertArgFn(fn, 'fn');
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
promise.error = function(fn) {
assertArgFn(fn, 'fn');
promise.error = function(fn) {
assertArgFn(fn, 'fn');
promise.then(null, function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
promise.then(null, function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
} else {
promise.success = $httpMinErrLegacyFn('success');
promise.error = $httpMinErrLegacyFn('error');
}
return promise;
@@ -1212,8 +1289,8 @@ function $HttpProvider() {
* Resolves the raw $http promise.
*/
function resolvePromise(response, status, headers, statusText) {
// normalize internal statuses to 0
status = Math.max(status, 0);
//status: HTTP response status code, 0, -1 (aborted by timeout / promise)
status = status >= -1 ? status : 0;
(isSuccess(status) ? deferred.resolve : deferred.reject)({
data: response,
+3 -3
View File
@@ -58,7 +58,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
xhr.onload = function requestLoaded() {
var statusText = xhr.statusText || '';
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// responseText is the old-school way of retrieving response (supported by IE9)
// response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
var response = ('response' in xhr) ? xhr.response : xhr.responseText;
@@ -109,7 +109,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
}
}
xhr.send(post);
xhr.send(isUndefined(post) ? null : post);
}
if (timeout > 0) {
@@ -126,7 +126,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
function completeRequest(callback, status, response, headersString, statusText) {
// cancel timeout and subsequent timeout promise resolution
if (timeoutId !== undefined) {
if (isDefined(timeoutId)) {
$browserDefer.cancel(timeoutId);
}
jsonpDone = xhr = null;
+1 -1
View File
@@ -139,7 +139,7 @@ function $InterpolateProvider() {
* ```js
* var $interpolate = ...; // injected
* var exp = $interpolate('Hello {{name | uppercase}}!');
* expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
* expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');
* ```
*
* `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
+1 -1
View File
@@ -174,7 +174,7 @@ function $IntervalProvider() {
* @description
* Cancels a task associated with the `promise`.
*
* @param {promise} promise returned by the `$interval` function.
* @param {Promise=} promise returned by the `$interval` function.
* @returns {boolean} Returns `true` if the task was successfully canceled.
*/
interval.cancel = function(promise) {
-68
View File
@@ -10,72 +10,4 @@
*
* * `id` `{string}` locale id formatted as `languageId-countryId` (e.g. `en-us`)
*/
function $LocaleProvider() {
this.$get = function() {
return {
id: 'en-us',
NUMBER_FORMATS: {
DECIMAL_SEP: '.',
GROUP_SEP: ',',
PATTERNS: [
{ // Decimal Pattern
minInt: 1,
minFrac: 0,
maxFrac: 3,
posPre: '',
posSuf: '',
negPre: '-',
negSuf: '',
gSize: 3,
lgSize: 3
},{ //Currency Pattern
minInt: 1,
minFrac: 2,
maxFrac: 2,
posPre: '\u00A4',
posSuf: '',
negPre: '(\u00A4',
negSuf: ')',
gSize: 3,
lgSize: 3
}
],
CURRENCY_SYM: '$'
},
DATETIME_FORMATS: {
MONTH:
'January,February,March,April,May,June,July,August,September,October,November,December'
.split(','),
SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
AMPMS: ['AM','PM'],
medium: 'MMM d, y h:mm:ss a',
'short': 'M/d/yy h:mm a',
fullDate: 'EEEE, MMMM d, y',
longDate: 'MMMM d, y',
mediumDate: 'MMM d, y',
shortDate: 'M/d/yy',
mediumTime: 'h:mm:ss a',
shortTime: 'h:mm a',
ERANAMES: [
"Before Christ",
"Anno Domini"
],
ERAS: [
"BC",
"AD"
]
},
pluralCat: function(num) {
if (num === 1) {
return 'one';
}
return 'other';
}
};
};
}
+30 -14
View File
@@ -89,12 +89,12 @@ function serverBase(url) {
*
* @constructor
* @param {string} appBase application base URL
* @param {string} appBaseNoFile application base URL stripped of any filename
* @param {string} basePrefix url path prefix
*/
function LocationHtml5Url(appBase, basePrefix) {
function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
this.$$html5 = true;
basePrefix = basePrefix || '';
var appBaseNoFile = stripFile(appBase);
parseAbsoluteUrl(appBase, this);
@@ -141,14 +141,14 @@ function LocationHtml5Url(appBase, basePrefix) {
var appUrl, prevAppUrl;
var rewrittenUrl;
if ((appUrl = beginsWith(appBase, url)) !== undefined) {
if (isDefined(appUrl = beginsWith(appBase, url))) {
prevAppUrl = appUrl;
if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
} else {
rewrittenUrl = appBase + prevAppUrl;
}
} else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
} else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
rewrittenUrl = appBaseNoFile + appUrl;
} else if (appBaseNoFile == url + '/') {
rewrittenUrl = appBaseNoFile;
@@ -168,10 +168,10 @@ function LocationHtml5Url(appBase, basePrefix) {
*
* @constructor
* @param {string} appBase application base URL
* @param {string} appBaseNoFile application base URL stripped of any filename
* @param {string} hashPrefix hashbang prefix
*/
function LocationHashbangUrl(appBase, hashPrefix) {
var appBaseNoFile = stripFile(appBase);
function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
parseAbsoluteUrl(appBase, this);
@@ -185,7 +185,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
var withoutHashUrl;
if (withoutBaseUrl.charAt(0) === '#') {
if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
// The rest of the url starts with a hash so we have
// got either a hashbang path or a plain hash fragment
@@ -199,7 +199,15 @@ function LocationHashbangUrl(appBase, hashPrefix) {
// There was no hashbang path nor hash fragment:
// If we are in HTML5 mode we use what is left as the path;
// Otherwise we ignore what is left
withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
if (this.$$html5) {
withoutHashUrl = withoutBaseUrl;
} else {
withoutHashUrl = '';
if (isUndefined(withoutBaseUrl)) {
appBase = url;
this.replace();
}
}
}
parseAppUrl(withoutHashUrl, this);
@@ -272,14 +280,13 @@ function LocationHashbangUrl(appBase, hashPrefix) {
*
* @constructor
* @param {string} appBase application base URL
* @param {string} appBaseNoFile application base URL stripped of any filename
* @param {string} hashPrefix hashbang prefix
*/
function LocationHashbangInHtml5Url(appBase, hashPrefix) {
function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
this.$$html5 = true;
LocationHashbangUrl.apply(this, arguments);
var appBaseNoFile = stripFile(appBase);
this.$$parseLinkUrl = function(url, relHref) {
if (relHref && relHref[0] === '#') {
// special case for links to hash fragments:
@@ -309,7 +316,7 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
// include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
// include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
this.$$absUrl = appBase + hashPrefix + this.$$url;
};
@@ -818,7 +825,9 @@ function $LocationProvider() {
appBase = stripHash(initialUrl);
LocationMode = LocationHashbangUrl;
}
$location = new LocationMode(appBase, '#' + hashPrefix);
var appBaseNoFile = stripFile(appBase);
$location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
$location.$$parseLinkUrl(initialUrl, initialUrl);
$location.$$state = $browser.state();
@@ -898,6 +907,13 @@ function $LocationProvider() {
// update $location when $browser url changes
$browser.onUrlChange(function(newUrl, newState) {
if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
// If we are navigating outside of the app then force a reload
$window.location.href = newUrl;
return;
}
$rootScope.$evalAsync(function() {
var oldUrl = $location.absUrl();
var oldState = $location.$$state;
+20 -28
View File
@@ -38,6 +38,15 @@ var $parseMinErr = minErr('$parse');
function ensureSafeMemberName(name, fullExpression) {
// From the JavaScript docs:
// Property names must be strings. This means that non-string objects cannot be used
// as keys in an object. Any non-string object, including a number, is typecasted
// into a string via the toString method.
//
// So, to ensure that we are checking the same `name` that JavaScript would use,
// we cast it to a string, if possible
name = (isObject(name) && name.toString) ? name.toString() : name;
if (name === "__defineGetter__" || name === "__defineSetter__"
|| name === "__lookupGetter__" || name === "__lookupSetter__"
|| name === "__proto__") {
@@ -774,6 +783,7 @@ ASTCompiler.prototype = {
this.state.computing = 'assign';
var result = this.nextId();
this.recurse(assignable, result);
this.return_(result);
extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
}
var toWatch = getInputs(ast.body);
@@ -982,8 +992,10 @@ ASTCompiler.prototype = {
nameId.name = ast.property.name;
}
}
recursionFn(intoId);
}, function() {
self.assign(intoId, 'undefined');
});
recursionFn(intoId);
}, !!create);
break;
case AST.CallExpression:
@@ -1021,8 +1033,10 @@ ASTCompiler.prototype = {
}
expression = self.ensureSafeObject(expression);
self.assign(intoId, expression);
recursionFn(intoId);
}, function() {
self.assign(intoId, 'undefined');
});
recursionFn(intoId);
});
}
break;
@@ -1606,29 +1620,6 @@ Parser.prototype = {
}
};
//////////////////////////////////////////////////
// Parser helper functions
//////////////////////////////////////////////////
function setter(obj, path, setValue, fullExp) {
ensureSafeObject(obj, fullExp);
var element = path.split('.'), key;
for (var i = 0; element.length > 1; i++) {
key = ensureSafeMemberName(element.shift(), fullExp);
var propertyObj = ensureSafeObject(obj[key], fullExp);
if (!propertyObj) {
propertyObj = {};
obj[key] = propertyObj;
}
obj = propertyObj;
}
key = ensureSafeMemberName(element.shift(), fullExp);
ensureSafeObject(obj[key], fullExp);
obj[key] = setValue;
return setValue;
}
var getterFnCacheDefault = createMap();
var getterFnCacheExpensive = createMap();
@@ -1697,13 +1688,14 @@ function $ParseProvider() {
var cacheDefault = createMap();
var cacheExpensive = createMap();
this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
this.$get = ['$filter', function($filter) {
var noUnsafeEval = csp().noUnsafeEval;
var $parseOptions = {
csp: $sniffer.csp,
csp: noUnsafeEval,
expensiveChecks: false
},
$parseOptionsExpensive = {
csp: $sniffer.csp,
csp: noUnsafeEval,
expensiveChecks: true
};
+27 -4
View File
@@ -272,8 +272,11 @@ function qFactory(nextTick, exceptionHandler) {
this.$$state = { status: 0 };
}
Promise.prototype = {
extend(Promise.prototype, {
then: function(onFulfilled, onRejected, progressBack) {
if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
return this;
}
var result = new Deferred();
this.$$state.pending = this.$$state.pending || [];
@@ -294,7 +297,7 @@ function qFactory(nextTick, exceptionHandler) {
return handleCallback(error, false, callback);
}, progressBack);
}
};
});
//Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
function simpleBind(context, fn) {
@@ -341,7 +344,7 @@ function qFactory(nextTick, exceptionHandler) {
this.notify = simpleBind(this, this.notify);
}
Deferred.prototype = {
extend(Deferred.prototype, {
resolve: function(val) {
if (this.promise.$$state.status) return;
if (val === this.promise) {
@@ -404,7 +407,7 @@ function qFactory(nextTick, exceptionHandler) {
});
}
}
};
});
/**
* @ngdoc method
@@ -487,6 +490,9 @@ function qFactory(nextTick, exceptionHandler) {
* the promise comes from a source that can't be trusted.
*
* @param {*} value Value or a promise
* @param {Function=} successCallback
* @param {Function=} errorCallback
* @param {Function=} progressCallback
* @returns {Promise} Returns a promise of the passed value or promise
*/
@@ -497,6 +503,22 @@ function qFactory(nextTick, exceptionHandler) {
return result.promise.then(callback, errback, progressBack);
};
/**
* @ngdoc method
* @name $q#resolve
* @kind function
*
* @description
* Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.
*
* @param {*} value Value or a promise
* @param {Function=} successCallback
* @param {Function=} errorCallback
* @param {Function=} progressCallback
* @returns {Promise} Returns a promise of the passed value or promise
*/
var resolve = when;
/**
* @ngdoc method
* @name $q#all
@@ -565,6 +587,7 @@ function qFactory(nextTick, exceptionHandler) {
$Q.defer = defer;
$Q.reject = reject;
$Q.when = when;
$Q.resolve = resolve;
$Q.all = all;
return $Q;
+3 -41
View File
@@ -10,7 +10,7 @@ function $$RAFProvider() { //rAF
$window.webkitCancelRequestAnimationFrame;
var rafSupported = !!requestAnimationFrame;
var rafFn = rafSupported
var raf = rafSupported
? function(fn) {
var id = requestAnimationFrame(fn);
return function() {
@@ -24,46 +24,8 @@ function $$RAFProvider() { //rAF
};
};
queueFn.supported = rafSupported;
raf.supported = rafSupported;
var cancelLastRAF;
var taskCount = 0;
var taskQueue = [];
return queueFn;
function flush() {
for (var i = 0; i < taskQueue.length; i++) {
var task = taskQueue[i];
if (task) {
taskQueue[i] = null;
task();
}
}
taskCount = taskQueue.length = 0;
}
function queueFn(asyncFn) {
var index = taskQueue.length;
taskCount++;
taskQueue.push(asyncFn);
if (index === 0) {
cancelLastRAF = rafFn(flush);
}
return function cancelQueueFn() {
if (index >= 0) {
taskQueue[index] = null;
index = null;
if (--taskCount === 0 && cancelLastRAF) {
cancelLastRAF();
cancelLastRAF = null;
taskQueue.length = 0;
}
}
};
}
return raf;
}];
}
+16 -16
View File
@@ -109,12 +109,9 @@ function $RootScopeProvider() {
* A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
* {@link auto.$injector $injector}. Child scopes are created using the
* {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
* compiled HTML template is executed.)
* compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
* an in-depth introduction and usage examples.
*
* Here is a simple scope snippet to show how you can interact with the scope.
* ```html
* <file src="./test/ng/rootScopeSpec.js" tag="docs1" />
* ```
*
* # Inheritance
* A scope can inherit from a parent scope, as in this example:
@@ -256,10 +253,10 @@ function $RootScopeProvider() {
* Registers a `listener` callback to be executed whenever the `watchExpression` changes.
*
* - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
* $digest()} and should return the value that will be watched. (Since
* {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
* `watchExpression` can execute multiple times per
* {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
* $digest()} and should return the value that will be watched. (`watchExpression` should not change
* its value when executed multiple times with the same input because it may be executed multiple
* times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be
* [idempotent](http://en.wikipedia.org/wiki/Idempotence).
* - The `listener` is called only when the value from the current `watchExpression` and the
* previous call to `watchExpression` are not equal (with the exception of the initial run,
* see below). Inequality is determined according to reference inequality,
@@ -276,9 +273,9 @@ function $RootScopeProvider() {
*
*
* If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
* you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
* can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
* change is detected, be prepared for multiple calls to your listener.)
* you can register a `watchExpression` function with no `listener`. (Be prepared for
* multiple calls to your `watchExpression` because it will execute multiple times in a
* single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
*
* After a watcher is registered with the scope, the `listener` fn is called asynchronously
* (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
@@ -608,7 +605,7 @@ function $RootScopeProvider() {
// copy the items to oldValue and look for changes.
newLength = 0;
for (key in newValue) {
if (newValue.hasOwnProperty(key)) {
if (hasOwnProperty.call(newValue, key)) {
newLength++;
newItem = newValue[key];
oldItem = oldValue[key];
@@ -630,7 +627,7 @@ function $RootScopeProvider() {
// we used to have more keys, need to find them and destroy them.
changeDetected++;
for (key in oldValue) {
if (!newValue.hasOwnProperty(key)) {
if (!hasOwnProperty.call(newValue, key)) {
oldLength--;
delete oldValue[key];
}
@@ -1040,11 +1037,14 @@ function $RootScopeProvider() {
$apply: function(expr) {
try {
beginPhase('$apply');
return this.$eval(expr);
try {
return this.$eval(expr);
} finally {
clearPhase();
}
} catch (e) {
$exceptionHandler(e);
} finally {
clearPhase();
try {
$rootScope.$digest();
} catch (e) {

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