Compare commits

...

222 Commits

Author SHA1 Message Date
Peter Bacon Darwin b879223cf3 fix(input): ensure that hidden input values are correct after history.back
Due to the nature of some browser's PageCache/BFCache, returning to an Angular
app sometimes causes `input[hidden]` elements to retain the last value
that was stored before the page was navigated away from previously.

This is particularly problematic if the input has an interpolated value.
E.g. `<input type="hidden" value="{{ 1 + 2 }}">` since when the browser
returns, instead of the original interpolation template, the HTML contains
the previous value `<input type="hidden" value="3">`.

This commit instructs the browser not to attempt to reinstate the previous
value when navigating back in history by setting `autocomplete="off"` on
the hidden input element element.
2016-10-10 22:22:30 +01:00
Georgios Kalpakas bba6004147 docs(ngModel): rename $asyncValidators error to nopromise and add missing error page
Closes #13795
2016-01-19 16:11:44 +02:00
Matias Niemelä d386b7ae4b fix(ngAnimate): do not use event.timeStamp anymore for time tracking
Due to recent changes in Chrome, Firefox and Webkit use of the
event.timeStamp value will lead to unpredictable behaviour due to
precision changes. Therefore it's best to stick entirely to use
`Date.now()` when it comes to confirming the end of transition-
ending values. See #13494 for more info.

Applies to 1.2, 1.3, 1.4 and 1.5.

Closes #13494
Closes #13495
2016-01-05 12:55:16 +00:00
Peter Bacon Darwin ebc5a477db chore(npm-shrinkwrap): update protractor dependency 2015-12-18 09:38:34 +00:00
Peter Bacon Darwin 21c935a303 chore(Gruntfile): replace double quotes with single quotes 2015-12-17 22:29:29 +00:00
Peter Bacon Darwin 7e5ef766da chore(GruntFile): fix whitespace in lists 2015-12-17 22:29:29 +00:00
Peter Bacon Darwin 1cb96303e9 chore(GruntFile): move validate-angular-files task into its own file
Closes #13569
2015-12-17 22:29:28 +00:00
Matias Niemelä d2058d92bd chore(build): add a validation step for angularFiles
Closes #13553
2015-12-17 22:29:28 +00:00
Peter Bacon Darwin 053f4e26ae chore(angularFiles): add documentation only file to list of files
This prevents errors when checking `validate-angular-files`
2015-12-17 22:29:28 +00:00
Peter Bacon Darwin 45ca45a29a chore(npm-shrinkwrap): install glob package 2015-12-17 22:29:25 +00:00
Peter Bacon Darwin e2bf5726ab chore(jenkins): remove unused argument definition 2015-12-17 14:15:38 +00:00
Peter Bacon Darwin bf706f2f52 chore(jenkins): run Jenkins builds on Node 4 (via nvm)
Closes #13568
2015-12-17 14:11:09 +00:00
Peter Bacon Darwin d2fe381ea8 chore(jenkins): move jenkins_build.sh to scripts/jenkins/build.sh 2015-12-16 14:23:12 +00:00
Peter Bacon Darwin 63c83ffa43 chore(travis): update to use node 4.x 2015-12-16 11:15:48 +00:00
Martin Staffa 7fa13c3da2 chore(travis): add a new job that runs ci-checks
Previously, ddescribe, merge-conflicts, jshint, and jscs would run
after unit & e2e tests ran. The order was orginally changed as part of
https://github.com/angular/angular.js/pull/9792.

While the logic is sound that style errors shouldn't block tests from
running, ddescribe should always run. This was not guaraneteed; when
Travis exits with a warning after some browsers have run, ddescribe
doesn't get run and it doesn't become apparent that not
all tests have run.

Additionally, a separate job clearly separates style from test errors,
which e.g. means you can open a PR that includes an iit to speed up
the job, and see immediately if the test passes, because the ddescribe
error is in another job.
2015-12-16 10:38:12 +00:00
Georgios Kalpakas 4b91042559 docs(form): remove mention of interpolated control names not being supported
The docs state that interpolation cannot be used in control names.
This used to be true, but not anymore.

Closes #13520
2015-12-15 20:05:18 +02:00
Jason Bedard a9ecde1e33 perf(copy): avoid regex in isTypedArray
Closes: #12054
2015-11-19 10:00:37 +00:00
Jason Bedard ada25a9266 perf(copy): only validate/clear user specified destination
Closes #12068
2015-11-19 10:00:22 +00:00
Peter Bacon Darwin 0f956b2893 fix(angular.copy): support copying XML nodes
Closes #5429
Closes #12786
2015-11-19 09:59:44 +00:00
Jason Bedard 17eb3d717f fix(copy): do not copy the same object twice 2015-11-19 09:59:19 +00:00
Peter Bacon Darwin c9ccc801b9 fix(copy): support copying properties with a null prototype
Partially cherry-picked from f7b999703f
2015-11-19 09:58:24 +00:00
Justin Schiff 420490aa1b fix(angular.copy): support copying %TypedArray%s
angular.copy can now copy a %TypedArray%s.

Limitations: It is not possible to update the length of a %TypedArray%, so currently an error is thrown
if the destination object is a %TypedArray%. However, it is possible to change values in a typed array,
so in the future this may only be a problem if the length of the source and destination is different.

Closes #10745
2015-11-19 09:46:07 +00:00
Matias Niemelä 2a65c3deb7 chore(CHANGELOG): update with changes for 1.3.20 2015-09-29 13:54:03 -07:00
Igor Minar ef0c333776 build(travis): make sauce connect process query a bit more specific 2015-09-23 14:01:51 -07:00
Georgios Kalpakas bce1d8ecad chore(check-node-modules): make check/reinstall node_modules work across platforms
The previous implementations (based on shell scripts) threw errors on
Windows, because it was not able to `rm -rf` 'node_modules' (due to the
255 character limit in file-paths).

This implementation works consistently across platforms and is heavily based on
'https://github.com/angular/angular/blob/3b9c08676a4c921bbfa847802e08566fb601ba7a/tools/npm/check-node-modules.js'.

Fixes #11143
Closes #11353

Closes #12792
2015-09-23 23:25:04 +03:00
Igor Minar 5a1bc6eb32 build(travis): fix typo in a comment 2015-09-23 11:00:44 -07:00
Igor Minar 1f7a0b2b72 build(travis): gracefully shut down the sauce connect tunnel after the tests are done running
This is to prevent sauce connect tunnel leaks.

Closes #12921
2015-09-23 09:40:46 -07:00
Lucas Mirelmann a665550933 test($parse): fix test for Firefox and IE 2015-09-20 19:54:37 +02:00
Lucas Mirelmann d434f3db53 fix($parse): do not convert to string computed properties multiple times
Do not convert to string properties multiple times.
2015-09-20 13:39:33 +02:00
Peter Bacon Darwin 7e08975b67 chore(travis): upgrade Travis builds to use container infrastructure 2015-09-17 12:31:52 +01:00
Magee Mooney 82c481bb23 docs(gdocs.js): fix typo (Eror -> Error)
Closes #12858
2015-09-16 23:11:39 +01:00
Peter Bacon Darwin b1f46bb1b2 chore(bower/publish): move DIST_TAG so that it gets the correct value
In the position that DIST_TAG was being assigned it was trying to get the
`distTag` value from the wrong (i.e. a bower-...) repository.
2015-09-16 23:11:35 +01:00
Peter Bacon Darwin 3a6bf0d5bc revert: fix($compile): throw error on invalid directive name
This reverts commit 634e467172, which introduced
a breaking change between 1.3.15 and 1.3.16.

Closes #12169
2015-09-15 14:38:21 +01:00
Peter Bacon Darwin e201f9040f docs(CHANGELOG): update with 1.3.19 changes 2015-09-15 13:34:09 +01:00
Peter Bacon Darwin 40e9bcd1b4 chore(scripts/publish): get dist-tag from package.json
Closes #12722
2015-09-14 21:45:20 +01:00
Matias Niemelä f98e038418 feat(ngAnimate): introduce $animate.flush for unit testing 2015-09-14 13:08:57 -07:00
Lucas Galfaso ec98c94ccb 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:35:46 +01:00
Pawel Kozlowski f13055a0a5 fix($http): propagate status -1 for timed out requests
Fixes #4491
Closes #8756
2015-09-07 14:34:10 +01:00
Peter Bacon Darwin 623ce1ad2c 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-09-07 14:33:17 +01:00
Peter Bacon Darwin 34cf141838 refactor($location): compute appBaseNoFile only once 2015-09-07 14:33:17 +01:00
Martin Staffa 274e93537e 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-28 10:57:07 +02:00
Matias Niemelä f7622dcc0d docs(CHANGELOG): add changes for 1.3.18 2015-08-18 15:14:56 -07:00
Matias Niemelä 2c03a35743 fix($animate): clear class animations cache if animation is not started
Closes #12604
Closes #12603
2015-08-17 17:09:00 -07:00
Matias Niemelä 6b72598b87 fix($animate): do not throw errors if element is removed before animation starts
Closes #10205
2015-08-17 17:06:54 -07:00
Rouven Weßling 51e24d75c3 refactor(): remove more bits and pieces related to Internet Explorer 8
Closes #12407
2015-08-08 18:08:47 +02:00
Martin Staffa 64a142b58e 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 18:08:15 +02:00
Martin Staffa 0026ebf2de 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 22:07:59 +02:00
Eric Adams a4f73c9f99 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 22:06:35 +02:00
Satish Maurya bd5c4e5f0e 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 22:06:27 +02:00
Steven 9742565d61 docs(guide): Facebook was mispelled as Faceb0ok
Fixes typo :>

Closes #12470
2015-08-03 22:05:45 +02:00
Strikeskids 6f33dfa8cc 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-08-03 22:05:36 +02:00
Laisky.Cai 96f0c8df17 docs(guide/expression): replace tt by code
Replaces <tt> elements with <code> in expressions guide. Looks identical
in Chromium

Closes #12437

Conflicts:
	docs/content/guide/expression.ngdoc
2015-08-03 22:04:40 +02:00
Martin Staffa 53fb534889 docs(ngOptions): remove obsolete trkslct error page
Closes #12417
2015-08-03 22:02:33 +02:00
Blake Johnston 6271ac064c docs($compile): pluralize DOM element
Previous description includes singular `collection of DOM element`. Current change revises `element` to be plural.

Closes #12431
2015-08-03 22:02:25 +02:00
ColinFletch 2d71b5b053 docs(guide/Controllers): Syntax adjustments.
Closes #12379
2015-08-03 22:02:13 +02:00
Jesse Mandel a547dff09b docs(guide/module): fixed link to blog post 2015-07-19 16:38:37 +02:00
Andrew Passanisi 3f9517ea5b docs(error/ctrlfmt): fixed a small typo in ctrl error message
Closes #12320
2015-07-16 22:45:47 +02:00
Mohamed Samy 8b4ffdde7a 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:45:40 +02:00
Nabil Kadimi e57240d87d docs(guide/Dependency Injection): minor punctuation fixes
Closes #12268
2015-07-16 22:45:29 +02:00
shoja a51b4e6dc4 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:45:21 +02:00
Steve Mao 215be0b0ab docs(CONTRIBUTING): revert is a modifier
EG: https://github.com/angular/angular.js/commit/462f444b06ae5cad3ccb761b1dba7131df01a655

Closes #12032
2015-07-13 13:26:45 +01:00
Steve Mao 7c5880f998 docs(CONTRIBUTING): state what is mandatory or optional
Closes #12032
2015-07-13 13:25:45 +01:00
Steve Mao 0d941a986a docs(CONTRIBUTING): how to write a breaking change
Closes #12032
2015-07-13 13:25:45 +01:00
Peter Bacon Darwin 8714cabdb7 docs(guide/controller): add a line about controller as 2015-07-13 13:22:28 +01:00
Peter Bacon Darwin cbab2923ef docs(guide/controller): add a line about controller as 2015-07-13 13:20:28 +01:00
niteshthakur dba7e20e96 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:20:28 +01:00
Peter Bacon Darwin 24dd9ea649 docs($routeChangeSuccess): note that resolve values are available on current route
Closes #11413
2015-07-13 13:11:15 +01:00
Rouven Weßling 8bd59a593b refactor(ngCsp): use document.head
The `head` property is available from IE9 onwards.

Closes #11905
2015-07-13 10:07:52 +01:00
Martin Staffa 9a1349d2e0 docs(CHANGLOG): add changes for 1.3.17 2015-07-06 22:22:45 +02:00
Raphael Jamet 7e6155a6f1 refactor($templateRequest): Remove useless dependencies in tests 2015-07-01 12:16:14 -07:00
Raphael Jamet 0f034444c3 docs($templateRequest): update the description with caching changes
The previous changes to $templateRequest were not documented, they now are.
2015-07-01 12:16:03 -07:00
Raphael Jamet 74ecea9f2d 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:15:57 -07:00
Peter Bacon Darwin 8d5c08c6b8 chore(doc-gen): update to dgeni-packages 0.10.17
Make proper use of the new `git` package in dgeni-packages
2015-06-23 05:10:21 -07:00
Tsuyoshi Yoshizawa 0bb57d538f 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:41:47 +01:00
Peter Bacon Darwin 61a3fb676a 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:02:31 +01:00
Peter Bacon Darwin f486ebe80b 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:42:40 +01:00
Peter Bacon Darwin 03190fd896 chore(ngMock): check that ngMock.$browser.pollFns exists before emptying 2015-06-12 14:42:30 +01:00
Caitlin Potter 340e4da2eb test($location): ensure mock window can be wrapped by jqLite
Fixin da build

Closes #12086
2015-06-12 14:37:54 +01:00
Peter Bacon Darwin 46e4fa87fb test($locationSpec): refactor and clean up tests 2015-06-12 14:37:33 +01:00
Peter Bacon Darwin 45d43b9234 test($logSpec): don't pollute the global namespace with helpers 2015-06-11 14:32:35 +01:00
Conny Sjöblom 6b28aef1c5 fix(linky): allow case insensitive scheme detection
Closes #12073
Closes #12074
2015-06-11 12:16:07 +01:00
Matias Niemelä 5a1b4a06f4 docs(CHANGELOG): add changes for 1.3.16 2015-06-05 13:29:27 -07:00
Matias Niemelä 12f08c5e14 docs(CHANGELOG): update with 1.4.0 2015-06-05 13:19:37 -07:00
Chris Akers 706a93ab69 fix($cookies): update $cookies to prevent duplicate cookie writes and play nice with external code
Update the ngCookies service to prevent repetitive writes via $browser.cookies()
Also it is possible for $cookies to get confused about cookies modified outside of $cookies and
see those changes as user changes via the $cookies service which would then be set again. This
unnecessary setting of cookies can duplicate or overwrite depending on the original cookie's
domain. This update prevents that scenario.

Closes #11490
Closes #11515
2015-06-04 22:46:10 -07:00
Henry Zhu c4ae7d261a chore(jscs): remove .jscs.json.todo, rename config to .jscsrc
Closes #11993
2015-06-02 10:32:24 +01:00
Matias Niemelä 0adc036426 fix(core): ensure that multiple requests to requestAnimationFrame are buffered
IE11 (and maybe some other browsers) do not optimize multiple calls to
rAF. This code makes that happen internally within the $$rAF service
before the next frame kicks in.

Closes #11791
2015-06-01 07:42:05 -07:00
Ron Tsui 1ee58612a2 docs(README): improve unusual phrasing
Closes #11958
2015-06-01 08:01:53 +01:00
Yi EungJun ddc7f85493 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:26 +01:00
Daniel 90621a6c89 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:57:16 +01:00
Michael Watts 0c59599a45 docs(guide/Scopes): capitalisation of word scope
Closes #11970
2015-06-01 07:50:27 +01:00
Peter Bacon Darwin 4a4db1e7e6 docs(README.closure.md): clarify sentence
Closes #11979
2015-06-01 07:48:50 +01:00
pholly 10d8b010d3 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:46 +01:00
Matias Niemelä 3881831906 revert: fix(ngAnimate): throw an error if a callback is passed to animate methods
This reverts commit 39b078bad4.
2015-05-21 12:09:31 -07:00
Peter Bacon Darwin 9e3f82bbaf fix(select): prevent unknown option being added to select when bound to null property
If a select directive was bound, using ng-model, to a property with a value of null this would
result in an unknown option being added to the select element with the value "? object:null ?".
This change prevents a null value from adding an unknown option meaning that the extra option is
not added as a child of the select element.

Since select (without ngOptions) can only have string value options then `null` was never a
viable option value, so this is not a breaking change.

Closes #11872
Closes #11875
2015-05-18 22:42:16 +01:00
Peter Bacon Darwin 05156143c8 docs(error//nocb): add error doc for invalid parameter 2015-05-14 14:01:27 -07:00
Peter Bacon Darwin 39b078bad4 fix(ngAnimate): throw an error if a callback is passed to animate methods
As of bf0f550 (released in 1.3.0) it is no longer
valid to pass a callback to the following functions: `enter`, `move`, `leave`, `addClass`,
`removeClass`, `setClass` and `animate`.

To prevent confusing error messages, this change asserts that this parameter is
not a function.

Closes #11826
Closes #11713
2015-05-14 14:01:22 -07:00
Peter Bacon Darwin 9055b4e041 docs(CHANGELOG): update with 1.4.0-rc.2 2015-05-12 19:53:44 +01:00
Martin Staffa 6224a3eefb Revert "perf(ngStyleDirective): use $watchCollection"
This reverts commit 4c8d8ad508,
because it broke lazy one-time binding for object literals.

Closes #11613
2015-05-08 18:54:35 +02:00
Martin Staffa a45a34c261 test(ngStyle): ensure lazy one-time binding is supported
Closes #11405
2015-05-08 18:54:34 +02:00
Peter Bacon Darwin ceeeb6b4b1 docs(angular.element): clarify when jquery must be loaded for Angular to use it
Closes #3716
2015-05-05 20:03:44 +01:00
Nick Anderson cbc5f1c114 test(ngRepeat): fix test setup for ngRepeat stability test
The repeated template contained `{{key}}:{{val}}` but the repeat expression
was `"item in items"`, so `key` and `val` were not actually available.

The tests were passing anyway, since they did not rely upon the actual
text content of the template.

Closes #11761
2015-05-05 19:58:38 +01:00
Peter Bacon Darwin 4dfb80d96f docs($location): fix trailing whitespace
Closes #11741
Closes #11744
2015-05-05 19:54:35 +01:00
Damien Nozay 368039b881 docs($location): explain difference between $location.host() and location.host.
Closes #11741
Closes #11744
2015-05-05 19:52:10 +01:00
Rich Snapp 647f3f55eb fix(jqLite): check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
Closes #11508
2015-05-05 17:55:20 +01:00
Peter Bacon Darwin c8de0e425f docs($injector): add array annotation to all injectable parameters
Closes #11507
2015-05-05 15:05:03 +01:00
Kevin Brogan 9717c8fe1f docs($provide): add array annotation type to $provide.decorator parameter
The $provide.decorator function, as per the documentation, "is called using
the auto.injector.invoke method and is therefore fully injectable."

The current @param contradicts this by stating that only a functions may
be used as an argument.

Closes #11507
2015-05-05 15:04:53 +01:00
Martin Staffa fee437f9cf docs(changelog): wrap jqLite example containing html with code block
This prevents the markdown parser from garbling the input and putting
out broken html.

Closes #11778
Fixes #11777
Fixes #11539
2015-05-01 21:00:44 +01:00
Leonardo Braga 861b1a3d9d docs(ngModel): improve formatting of $modelValue
Closes #11483
2015-04-30 22:55:21 +02:00
Rodrigo Parra 72ff49f40f docs(ngSwitch): Replace tt tag with code tag
Use of tt is discouraged, see:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tt
http://www.w3.org/wiki/HTML/Elements/tt

Closes #11509
2015-04-30 22:55:21 +02:00
Jeff Wesson 7a529992c8 docs(form): replace obsolete tt element
Removes the [**obsolete** HTML Teletype Text Element `<tt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tt)
and replaces it with [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code).
This adds more semanticity and is part of the [HTML5 specification](http://www.w3.org/TR/html5/text-level-semantics.html#the-code-element).

Closes #11570
2015-04-30 22:55:21 +02:00
Steve Mao e89d6829bc docs(ngCloak): remove information for ie7
IE7 is not supported. Also change `#template2` text to `'world'`.

Closes #11661
2015-04-30 22:55:20 +02:00
Ron Tsui 1b343e7bb6 style(docs): improve formatting in code comment
Closes #11674
2015-04-30 22:55:20 +02:00
thatType b3c022d672 docs(contribute): transpose "however" and "it's"
Transpose "however" and "it's" on line 156 for slightly better readability

Closes #11686
2015-04-30 22:55:20 +02:00
Georgios Kalpakas 9dd0fe35d1 fix(filterFilter): fix matching against null/undefined
Included fixes:

* Do not convert `null`/`undefined` to strings for substring matching in
  non-strict comparison mode. Prevents `null`/`undefined` from being matched
  against e.g. 'u'.
* Let `null` (as a top-level filter expression) match "deeply" (as do booleans,
  numbers and strings).
  E.g. let `filterFilter(arr, null)` match an item like `{someProp: null}`.

Fixes #11573

Closes #11617
2015-04-28 19:52:28 +02:00
Mike Calvanese 7560a8d2d6 fix(ngTouch): check undefined tagName for SVG event target
When target click element is an SVG, event.target.tagName and event.target.blur are undefined in Chrome v40 on iOS 8.1.3
2015-04-27 22:05:26 +01:00
gonengar c68357dbf8 docs(guide/Unit Testing): fixing the example for testing filter.
Hi there,
It seems that in the example which starts at line 256 there needs to
be an injection for $filter as in the previous example.

Closes #11410
2015-04-27 22:41:37 +02:00
Logesh Paul eaf6981499 docs(*): definition list readability improvement
Closes #11398
Closes #11187
2015-04-27 22:41:36 +02:00
Viktor Zozulyak 1cc24f3c4f docs(angular.injector): missing optional parameter mark
Closes #11528
2015-04-27 22:41:35 +02:00
yankee42 9e3e26328e docs(ngModel): use arguments.length instead of angular.isDefined(newName) to distinguish getter/setter usage
Closes #11604
2015-04-27 22:41:34 +02:00
Adam 82b2961868 docs(angular.element): css() api incompatibility.
"When a number is passed as the value, jQuery will convert it to a string and add px to the end of that string."
http://api.jquery.com/css/#css2

jqLite does not appear to do this.

I can submit if fix desired.

Closes #11614
2015-04-27 22:41:33 +02:00
Bruno Coelho 3cb10edca0 docs(guide/Scopes): remove unnecessary parenthesis
Closes #11645
2015-04-27 22:41:32 +02:00
Martin Staffa b64519fea7 fix(ngModel): allow setting model to NaN when asyncValidator is present
Closes #11315
Closes #11411
2015-04-03 07:12:39 +01:00
Peter Bacon Darwin 830c81d0f1 chore(dependencies): general update (including new dgeni-packages)
Closes #11095
2015-04-03 06:03:55 +01:00
Peter Bacon Darwin 66650bfb36 docs(toJson): improve option param documentation
With an upgrade to dgeni-packages 0.10.13, this style of optional param
is rendered more correctly.

See #11095
2015-04-03 06:03:44 +01:00
Peter Bacon Darwin 900b3a416c style($browserSpec): fix typo 2015-04-02 22:50:59 +01:00
Georgios Kalpakas f40252205e test(browerTrigger): ensure touch events initialize correctly on touch enabled Chrome
On certain browsers (e.g. on desktop Chrome with touch-events enabled),
using the `initTouchEvent()` method (introduced in 06a9f0a) did not
correctly initialize the event, nor did the event get dispatched on
the target element.

Using the `Event` constructor and manually attaching a `TouchList`,
works around the issue (although not a proper fix).

Fixes #11471
Closes #11493
2015-04-02 21:24:12 +01:00
Michał Gołębiowski 40441f6dfc fix(ngTouch): register touches properly when jQuery is used
If jQuery was used with Angular the touch logic was looking for touches
under the original event object. However, jQuery wraps all events, keeping
the original one under the originalEvent property and copies/normalizes some
of event properties. Not all properties are copied, e.g. touches which caused
them to not be recognized properly.

Thanks to @mcmar & @pomerantsev for original patch ideas.

Fixes #4001
Closes #8584
Closes #10797
Closes #11488
2015-04-02 14:06:08 +01:00
Michał Gołębiowski 1f65087126 feat(travis): run unit tests on iOS 8
Refs #11471
Closes #11479
2015-04-02 13:27:23 +01:00
Matias Niemelä d5c99ea42b fix(ngAnimate): ensure that minified repaint code isn't removed
Closes #9936
2015-03-31 14:04:00 -07:00
Peter Bacon Darwin bbc5fdde50 style(): remove unused property 2015-03-26 13:12:03 +00:00
Fred Sauer b5685e23f0 docs($route): add param info for $routeUpdate event
Closes #11419
2015-03-25 14:42:10 +00:00
Peter Bacon Darwin 5b26521de2 docs(filters): clarify filter name restrictions
See #10122
2015-03-23 11:59:38 +00:00
Martin Staffa abfbfd6c1c docs($compile): clarify link fn's controller argument
Also add "bindToController" to exampe directive definition object.

Closes #10815

Conflicts:
	src/ng/compile.js
2015-03-22 18:16:36 +01:00
Bradley Price a0e91c4ef7 docs($http): remove trailing comma
Remove trailing comma to keep the same flow with all other code examples on page.
2015-03-22 18:13:48 +01:00
wiseleo 3353fb84aa docs(orderBy): replace operator = with ===
Fix documentation error on line 20 incorrectly mentioning
an assignment operator in a comparison operation.
Code on line 235 uses strict comparison operator.

Closes #11392
Closes #11393
2015-03-22 18:13:48 +01:00
Yuvraj Patil 3a22c6461d docs(guide/Unit Testing): update Jasmine's description
Jasmine is a "behavior-driven development framework",
not a "test-driven development framework"

Closes #11383
2015-03-21 14:39:44 +01:00
Martin Staffa 54f5d82d4f docs(guide/scope): fix grammar
Closes #9829
2015-03-21 14:39:43 +01:00
Martin Staffa e80434c93f docs(guide/direcive): don't use shorthand in ddo
All the other examples use the full syntax.
Closes #11180
2015-03-21 14:39:43 +01:00
RaphStein 7dd5d7a523 docs(ngAria): change aria-live attribute value from polite to assertive
For ngMessages directive ngAria generates aria-live with value assertive and not polite.

Closes #11280
2015-03-21 14:39:43 +01:00
Wesley Cho 6198c0d9c0 docs($httpBackend): change to more friendly language
- Change s**t to more neutral word

Closes #11380
Closes #11364
2015-03-20 10:56:48 +00:00
Julie Ralph 1acde764d5 chore(ci): fix location of print logs from wait_for_browser_provider 2015-03-19 14:41:35 -07:00
Julie Ralph 3bdb39f667 chore(test): bump Protractor version to 2.0.0 2015-03-19 13:29:55 -07:00
Peter Bacon Darwin f231dda29d docs(input[number]): clarify that model must be of type number
The docs also now link through to the error doc, which contains a runnable
example of how to work around this restriction.

Closes #11157
Closes #11334
2015-03-19 14:35:16 +00:00
Peter Bacon Darwin 03f858ea5c chore(docs): improve error doc layout and linking
You can now link to an error by its name, namespace:name or error:namespace:name.
For example these would all link to https://docs.angularjs.org/error/$compile/ctreq

```
{@link ctreq}
{@link $compile:ctreq}
{@link error:$compile:ctreq}
```
2015-03-19 14:35:16 +00:00
Peter Bacon Darwin 4a26249946 docs(error/ngModel/numfmt): provide documentation for this error
See: https://github.com/angular/angular.js/commit/db044c408a7f8082758b96ab739348810c36e15a#commitcomment-7577199

Closes #11157
Closes #11334
2015-03-19 14:35:16 +00:00
Julie Ralph 06364c8cdc chore(ci): force travis to print logs after driver provider timeout
Travis does not do the after_script step if before_script fails,
so wait_for_browser_provider.sh was not printing out logs.
Force it to print them manually.
2015-03-17 16:58:19 -07:00
Martin Staffa 1c282af5ab fix(ngAria): handle elements with role="checkbox/menuitemcheckbox"
Fixes #11317
Closes #11321
2015-03-17 21:43:19 +00:00
Julie Ralph 45f006f6fb chore(ci): make wait_for_browser_provider time out after 2 minutes
Before, if something went wrong, wait_for_browser_provider.sh would
wait indefinitely, and logs would never get printed. Now, we'll bail
early, and get some actual logs on what the problem was.

Closes #11350
2015-03-17 20:40:22 +00:00
Peter Bacon Darwin 731e1f6534 fix($http): throw error if success and error methods do not receive a function
Closes #11330
Closes #11333
2015-03-17 19:14:28 +00:00
Wesley Cho 634e467172 fix($compile): throw error on invalid directive name
Directive names must start with a lower case letter.
Previously the compiler would quietly fail.
This change adds an assertion that fails if this is not the case.

Closes #11281
Closes #11109
2015-03-17 13:53:24 +00:00
Peter Bacon Darwin 2ca34a0cd3 docs(CHANGELOG): add changes for 1.4.0-beta.6 and 1.3.15 2015-03-17 12:08:27 +00:00
robiferentz 181e5ebc3f fix(jqLite): attr should ignore comment, text and attribute nodes
Follow jQuery handling of the `attr` function

Close #11038
2015-03-17 11:47:37 +00:00
svershin 874392464b docs(misc/Downloading): update o latest stable version
Updated the CDN link and description to 1.3.14

Closes #11327
2015-03-15 21:01:49 +00:00
rodyhaddad 7e7244402d chore(security): add warning banner to top of security sensitive files 2015-03-15 20:42:43 +00:00
Julie Ralph 4b94b9e34f chore(ci): bump sc version to 4.3.7 2015-03-13 09:36:28 -07:00
Izhaki a2e7f54320 docs(guide/directives): add some extra sub-headings for clarity
Added `Normalization` and `Directive types`` subheadings
to the `Matching directive` heading
2015-03-12 22:37:51 +01:00
Ciro Nunes 9b2e11b6fa docs($templateCache): highlight the $templateCache service
Closes #11294
2015-03-12 22:37:50 +01:00
Devyn Stott 2114a50c9a docs($log): Add debug button to example
Add debug button to example. It was in teh docs but not the example.

No breaking changes.
2015-03-12 22:37:49 +01:00
Marcin Wosinek 38f92c3a27 docs(ngMessage): move up ngMessages link 2015-03-12 22:37:47 +01:00
Amy 7dbf1ef2d1 docs(guide/Conceptual Overview): add a hyphen for clarity
Minor change, but the heading for "View independent business logic..."
would be more clear if it had a hyphen, "View-independent".
Perhaps it's because I'm new to javascript and its terminology,
but I read "View" as a verb rather than a noun on the first pass and
had to read on a bit to understand that it was, instead,
referring to The View. If you go just by grammar rules,
making "view independent" into the compound adjective,
"view-independent", makes it clear that it is modifying "business logic".
(http://www.grammarbook.com/punctuation/hyphens.asp - see Rule 1).

Conflicts:
	docs/content/guide/concepts.ngdoc
2015-03-12 22:37:46 +01:00
Peter Bacon Darwin e13aae1ed0 test(ngMock): test shallow copy of mock controller bindings
See #11239
2015-03-12 19:59:09 +00:00
Julie Ralph 36eacb172a chore(ci): turn off verbose logging for sauce connect
We have not used the verbose data from these logs for months,
and it makes the Travis UI very slow.
2015-03-11 10:55:02 -07:00
Peter Bacon Darwin f2683f956f fix(date filter): display localised era for G format codes
This implementation is limited to displaying only AD (CE) years correctly,
since we do not support the `u` style year format that can be used to represent
dates before 1 AD.

Closes #10503
Closes #11266
2015-03-11 12:19:00 +00:00
Peter Bacon Darwin 1a670aa466 chore(ngLocale): regenerate locale files to include ERA info 2015-03-11 12:18:42 +00:00
Peter Bacon Darwin 578425303f fix(ng/$locale): add ERA info in generic locale
This change also updates the closure i18n converter to pull in the ERA
info for generated locale files.
2015-03-11 12:18:17 +00:00
Rouven Weßling 528cf09e3f fix(rootScope): prevent memory leak when destroying scopes
Closes #11173
Closes #11169
2015-03-09 14:56:45 +00:00
bborowin c849098fbf docs($compile): clarify when require will throw
To make things less confusing, explicitly state that require
WILL NOT throw a compile error if a link function is not specified.

Closes #11206
stackoverflow.com/questions/28730346/require-ddo-option-of-angular-directive-does-not-throw-an-error-when-it-should
2015-03-08 20:42:39 +01:00
Edward Delaporte 145d397988 docs(orderBy): Start with a simpler example.
Per the question raised at this Stack Overflow question:
http://stackoverflow.com/questions/24048590/angularjs-ng-repeat-orderby-date-not-working

The first example on this page is too complex to convey
the simplest possible case for using this function.

Closes #11144
2015-03-08 18:54:40 +01:00
Elliot Bentley 26d4d0dc22 docs(ngDisabled): Clarify "incorrect" example
Add obvious label to example of incorrect usage.
To a user scanning the docs (ie. me) it's easy to miss the fact
that this top example doesn't actually work.

Closes #11192
2015-03-08 18:54:27 +01:00
jmarkevicius 64a9faaf8e docs(guide/Animations): change *then* to *than* 2015-03-08 14:00:46 +01:00
Anthony Zotti b7aba16839 docs(form): Add comma to line 319 for readability
Line 319 is hard to read on the first glimpse.

Currently the sentence reads:
"In Angular forms can be nested"

The sentence should read either
"In Angular, forms can be nested"
or
"Forms can be nested in angular"

I changed it to the former in this pull request.

Closes #11271
2015-03-08 14:00:46 +01:00
b0ri5 a72e1c4767 docs(tutorial/0 - Bootstrapping): Add a "the" before "imperative / manual way"
I'm assuming "imperative / manual" is modifying "way" in which case I think "the" is needed.

I don't really know grammar, but as a native speaker it sounds odd without "the".

Closes #11269
2015-03-08 14:00:46 +01:00
Martin Staffa 6545212d24 docs(tutorial/0 - Bootstrapping): clarify where the callback is registered
Closes #11270
2015-03-08 14:00:45 +01:00
Peter Bacon Darwin 3fabbdb804 docs(isNumber): fix link to isFinite 2015-03-06 11:58:11 +00:00
Peter Bacon Darwin ce8be9c47f docs(isNumber): add info about using isFinite to exclude NaN
Closes #11230
2015-03-06 11:36:26 +00:00
Caitlin Potter b3878a36d9 feat(ngMock): allow mock $controller service to set up controller bindings
Adds a new mock for the $controller service, in order to simplify testing using the
bindToController feature.

```js
var dictionaryOfControllerBindings = {
  data: [
    { id: 0, phone: '...', name: '...' },
    { id: 1, phone: '...', name: '...' },
  ]
};

// When the MyCtrl constructor is called, `this.data ~= dictionaryOfControllerBindings.data`
$controller(MyCtrl, myLocals, dictionaryOfControllerBindings);
```

Closes #9425
Closes #11239
2015-03-06 10:55:33 +00:00
gdi2290 ebd84e8008 fix($animate): applyStyles from options on leave
Closes #10068
2015-03-04 14:26:38 +00:00
Peter Bacon Darwin e721169738 chore(privateMocks): use global angular to access helpers in they
When using `they` in modules such as `ngMessages` we do not have access to
the internal helper functions.
2015-03-04 13:13:34 +00:00
Matias Niemelä cdfbe25c00 chore(privateMocks): replace multiple occurrences of $prop for they() 2015-03-04 12:28:07 +00:00
Peter Bacon Darwin 0d4b15a4c9 chore(gruntFile): add tthey and xthey to ddescribe-iit check 2015-03-04 12:28:07 +00:00
Peter Bacon Darwin 0dd061c239 style(privateMocks): remove unnecessary comment 2015-03-04 12:28:06 +00:00
Peter Bacon Darwin 7288be25a7 feat(ngMock): add they helpers for testing multiple specs
There are now three new test helpers: `they`, `tthey` and `xthey`, which
will create multiple `it`, `iit` and `xit` blocks, respectively, parameterized
by each item in a collection that is passed.

(with tests and ammendments by @petebacondarwin)

Closes #10864
2015-03-04 12:27:45 +00:00
Steve Mao 2b279dd8a1 docs(CONTRIBUTING): add whitespaces for consistent styling
Closes #11214
2015-03-04 12:26:46 +00:00
Casey Howard 63b9956faf fix(filterFilter): Fix filtering using an object expression when the filter value is undefined
Fixes #10419
Closes #10424
2015-03-02 22:19:14 +00:00
Caitlin Potter 92767c098f fix($browser): don't crash if history.state access causes error in IE
Reportedly, MSIE can throw under certain conditions when fetching this attribute.
We don't have a reliable reproduction for this but it doesn't do any real harm
to wrap access to this variable in a try-catch block.

Fixes #10367
Closes #10369
2015-03-02 20:30:06 +00:00
Brian Ford 2fe9b1dd9e docs(TRIAGING.md): improve process around PRs plz! label
Closes #10375
2015-03-02 19:43:46 +00:00
Marcy Sutton b9ad91cf1e feat(ngAria): add button role to ngClick
Closes #9254
Closes #10318
2015-03-02 13:49:17 +00:00
Peter Bacon Darwin 40752a520a test(aria): clean up test style and rename helper
Also removes unnecessary calls to `$apply`
2015-03-02 13:49:17 +00:00
Marcy Sutton 21369943fa feat(ngAria): add roles to custom inputs
This change adds the missing roles: `slider`, `radio`, `checkbox`

Closes #10012
Closes #10318
2015-03-02 13:49:17 +00:00
Jason Bedard 190ea883c5 fix(form): allow dynamic form names which initially evaluate to blank
Conflicts:
	src/ng/directive/form.js

Closes #11096
2015-03-01 16:35:04 +01:00
Josh Kramer 3a093123ef docs(ngModel): fix contenteditable description
contenteditable is supported in many more browsers than Angular itself is.

http://caniuse.com/#feat=contenteditable

Closes #11172
2015-02-28 18:05:42 +01:00
Pawel Kozlowski b8e8f9af78 fix(Angular): properly compare RegExp with other objects for equality
Fixes #11204

Closes #11205
2015-02-28 10:58:41 +01:00
Dav 01161a0e9f fix(filterFilter): do not throw an error if property is null when comparing objects
Closes #10991
Closes #10992
Closes #11116
2015-02-27 21:47:46 +00:00
Adam Bradley 75abbd525f fix(templateRequest): avoid throwing syntax error in Android 2.3
Android 2.3 throws an `Uncaught SyntaxError: Unexpected token finally`
pointing at this line. Change `.finally` to bracket notation.

Fixes #11089
Closes #11051
Closes #11088
2015-02-25 16:40:19 +00:00
Julie Ralph 01a725a769 chore(ci): update Karma to 0.12.32-beta.0
This will hopefully make the CI more stable because of its updated
version of socket.io.
2015-02-24 13:16:06 -08:00
Peter Bacon Darwin f5781dbb60 docs(CHANGELOG): add changes for 1.4.0-beta.5 and 1.3.14 2015-02-24 17:52:09 +00:00
Peter Bacon Darwin 59205d7809 chore(bower/publish): run local precommit script if available
Closes #11164
2015-02-24 17:22:45 +00:00
Martin Staffa 0cf170df16 chore(grunt): use path.normalize in grunt shell:npm-install
This makes the command runnable on Windows clients.
2015-02-23 20:51:37 +01:00
Tero Parviainen 05a3b088fd docs(ngRepeat): extend description of tracking and duplicates
Add a section to the documentation on how tracking between items and DOM
elements is done, and why duplicates are not allowed in the collection.

Describe how the default tracking behaviour can be substituted with track by.

Tweak the wording in the `track by` section to discuss “tracking expressions”
instead of “tracking functions”.

Closes #8153
2015-02-23 20:17:09 +01:00
Martin Staffa 65df5da07a docs(ngDisabled): clarify the explanation of attributes & interpolation
Closes #11032
Closes #11133
2015-02-22 22:17:22 +01:00
Igor Minar 0689c3697f chore(npm): update dependencies 2015-02-21 19:03:50 -08:00
Igor Minar 0f53c29954 chore(travis,grunt): extract the npm install and cache busting logic into install-dependencies.sh
So now we are DRY.

Added extra error checking and improved the grunt file init setup so that stdio is visible in console.

Closes #11110
2015-02-21 18:55:19 -08:00
Igor Minar 11bfe85598 chore(grunt): blow away cached node_modules when npm-shrinkwrap.json changes
this replicates the travis setup in grunt from the previous commit

the reason why we duplicate this rather than having just a single place for this code is so that
we can individually time the actions on travis
2015-02-21 18:55:07 -08:00
Igor Minar 93c503fa16 chore(travis): don't break the build when travis cache is empty
`du` returns error code 2 when any of the directories don't exist which breaks the build.

this scenario is common when the cache was emptied or when travis is building forks that don't have travis cache enabled
2015-02-21 18:54:55 -08:00
Igor Minar 9d4e948e82 chore(travis): blow away cached node_modules when npm-shrinkwrap.json changes
`npm install` blindly accepts the node_modules cache and doesn't verify if it matches requirements in the current npm-shrinkwrap.json.

This means that if we are using travis cache and npm-shrinkwrap.json changes npm will keep on using the old dependencies, in spite of the guarantees that shrinkwrap claims to offer.

https://github.com/angular/angular.js/pull/11110#issuecomment-75302946

With this change, we will blow away the node_modules directory if the shrinkwrap changes compared to the one
used to populate node_modules.
2015-02-21 18:54:24 -08:00
Igor Minar 26f19d0399 chore(karma): use karma 0.12.31 instead of a custom fork
Previously Vojta set us up to use a custom fork of Karma that used socket.io 1.3.4. This change moves us to an official release of Karma but downgrades socket.io back to 0.9.16.

We now need to hurry up and finish the socket.io upgrade in karma which was blocked on shrinkwrap issues in Angular that are resolved with the previous few commits in this PR.

Conflicts:
	npm-shrinkwrap.clean.json
	npm-shrinkwrap.json
2015-02-21 18:54:08 -08:00
Igor Minar 5cd2e2291b chore(clean-shrinkwrap): drop from property from the clean shrinkwrap
it usually contains urls to temp directories which are not interesting, the info
we do want to preserve is in the `resolved` property and we do keep that one.

Conflicts:
	npm-shrinkwrap.clean.json
2015-02-21 18:41:10 -08:00
Igor Minar 69bbbe675e chore(clean-shrinkwrap): preserve git+https:// resolved property
previously we thought that git:// was enough, but we also want git+https:// otherwise we can miss important info
in clean shrinkwrap file

Conflicts:
	npm-shrinkwrap.clean.json
2015-02-21 18:40:11 -08:00
Igor Minar 825de1cdf2 chore(npm/travis): upgrade to npm 2.5 and require it via package.json
currently karma's dependencies don't install on node 0.12 or io.js so we'll just update npm in hope that that
this will mitigate "cb() never called!" erorrs. See: https://travis-ci.org/angular/angular.js/jobs/51474043#L2181
2015-02-21 18:40:11 -08:00
Igor Minar e5318c61ee chore(npm): don't clean npm-shrinkwrap.json instead generate npm-shrinkwrap.clean.json
Previously we would clean up npm-shrinkwarp.json file in order to achieve serialization
stability, which would then allow us to create human readable diffs that allow code reviews
of npm-shrinkwrap to be meaningful.

This cleanup process does have an impact on the functionality of npm which was only recently
discovered by Vojta, when we tried to update to new Karma version. See: Automattic/engine.io-client#370

According to Julie, the root cause of these issues is npm/npm/#3581.

The workaround implemented in this commit is not to interfere with npm-shrinkwrap.json file, but instead
preserve the cleaned up version of its content in npm-shrinkwrap.clean.json which can then be used to
produce human readable diffs for code reviews of npm dependency updates.
2015-02-21 18:37:56 -08:00
Igor Minar 67b40a19fb chore(travis): turn on caching for node_modules and bower_components directories
The cache behavior is documented at http://docs.travis-ci.com/user/caching/

This commit also disabled our custom caching via npm-bundler-deps.sh
2015-02-21 18:36:37 -08:00
Martin Staffa 5fbac749c9 docs($resource): fix list level
Closes #11055
2015-02-13 23:54:11 +01:00
Julie Ralph 0daadeb3d3 chore(ci): make all browserstack tests allowed failures 2015-02-13 10:20:34 -08:00
Peter Bacon Darwin 6b7625a095 fix(ngModel): fix issues when parserName is same as validator key
For $validate(), it is necessary to store the parseError state
in the controller. Otherwise, if the parser name equals a validator
key, $validate() will assume a parse error occured if the validator
is invalid.

Also, setting the validity for the parser now happens after setting
validity for the validator key. Otherwise, the parse key is set,
and then immediately afterwards the validator key is unset
(because parse errors remove all other validations).

Fixes #10698
Closes #10850
Closes #11046
2015-02-13 12:34:44 +00:00
Rouven Weßling ab7e0cd100 refactor(ngSanitize): remove workarounds for IE8
Closes #10758
2015-02-13 11:52:05 +00:00
Peter Bacon Darwin dee5f7fea5 test(ngSanitize): add tests for decodeEntities 2015-02-13 11:52:05 +00:00
Julie Ralph 140d149cee chore(ci): update to use the latest sauce connect (4.3 to 4.3.6) 2015-02-12 13:19:42 -08:00
Peter Bacon Darwin 4d65ddddf8 docs(FAQ): update the zipped file size 2015-02-12 11:59:53 +00:00
Tobyee abfce5327c fix(input): create max and/or min validator regardless of initial value
Also adds corresponding tests for ngMin / ngMax.

Fixes #10307
Closes #10327
2015-02-10 23:39:49 +01:00
Martin Staffa 944c150e6c fix(ngAria): correctly set "checked" attr for checkboxes and radios
Make sure the checked attribute is set correctly for:
- checkboxes with string and integer models using ngTrueValue /
ngFalseValue
- radios with integer models
- radios with boolean models using ngValue

Fixes #10389
Fixes #10212
2015-02-10 22:35:36 +01:00
Peter Bacon Darwin d8dc53d215 chore(CHANGELOG): add release name! 2015-02-09 11:16:46 +00:00
Peter Bacon Darwin 0ec206f5a6 chore(CHANGELOG): update to 1.4.0-beta.4 and 1.3.13 2015-02-09 10:39:03 +00:00
876 changed files with 25264 additions and 3354 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
+25 -17
View File
@@ -1,6 +1,13 @@
language: node_js
sudo: false
node_js:
- '0.10'
- '4.2'
cache:
directories:
- node_modules
- bower_components
- docs/bower_components
branches:
except:
@@ -8,46 +15,47 @@ branches:
env:
matrix:
- JOB=ci-checks
- JOB=unit BROWSER_PROVIDER=saucelabs
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
- JOB=unit BROWSER_PROVIDER=browserstack
- JOB=docs-e2e BROWSER_PROVIDER=browserstack
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack
global:
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
- SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
- BROWSER_STACK_USERNAME=VojtaJina
- BROWSER_STACK_ACCESS_KEY=QCQJ1ZpWXpBkSwEdD8ev
- LOGS_DIR=/tmp/angular-build/logs
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
matrix:
allow_failures:
- env: "JOB=unit BROWSER_PROVIDER=browserstack"
# node 4 likes the G++ v4.8 compiler
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
install:
# Check the size of caches
- du -sh ./node_modules ./bower_components/ ./docs/bower_components/ || true
# - npm config set registry http://23.251.144.68
# Disable the spinner, it looks bad on Travis
- npm config set spin false
# Log HTTP requests
- npm config set loglevel http
- time ./scripts/travis/npm-bundle-deps.sh
- time npm install
#- npm install -g npm@2.5
# Install npm dependencies and ensure that npm cache is not stale
- npm install
before_script:
- mkdir -p $LOGS_DIR
- ./scripts/travis/start_browser_provider.sh
- npm install -g grunt-cli
- grunt package
- ./scripts/travis/wait_for_browser_provider.sh
- ./scripts/travis/before_build.sh
script:
- ./scripts/travis/build.sh
after_script:
- ./scripts/travis/tear_down_browser_provider.sh
- ./scripts/travis/print_logs.sh
notifications:
+774 -2
View File
@@ -1,3 +1,775 @@
<a name="1.3.20"></a>
# 1.3.20 shallow-translucence (2015-09-29)
## Bug Fixes
- **$parse:** do not convert to string computed properties multiple times
([d434f3db](https://github.com/angular/angular.js/commit/d434f3db53d6209eb140b904e83bbde401686c16))
## Breaking Changes
<a name="1.3.19"></a>
# 1.3.19 glutinous-shriek (2015-09-15)
## Bug Fixes
- **$http:** propagate status -1 for timed out requests
([f13055a0](https://github.com/angular/angular.js/commit/f13055a0a53a39b160448713a5617edee6042801),
[#4491](https://github.com/angular/angular.js/issues/4491), [#8756](https://github.com/angular/angular.js/issues/8756))
- **$location:** don't crash if navigating outside the app base
([623ce1ad](https://github.com/angular/angular.js/commit/623ce1ad2cf68024719c5cae5d682d00195df30c),
[#11667](https://github.com/angular/angular.js/issues/11667))
- **$parse:** throw error when accessing a restricted property indirectly
([ec98c94c](https://github.com/angular/angular.js/commit/ec98c94ccbfc97b655447956738d5f6ff98b2f33),
[#12833](https://github.com/angular/angular.js/issues/12833))
- **ngModel:** validate pattern against the viewValue
([274e9353](https://github.com/angular/angular.js/commit/274e93537ed4e95aefeacea48909eb334894f0ac),
[#12344](https://github.com/angular/angular.js/issues/12344))
## Features
- **ngAnimate:** introduce `$animate.flush` for unit testing
([f98e0384](https://github.com/angular/angular.js/commit/f98e038418f7367b2373adcf4887f64a8e8bdcb0))
## Possible Breaking Changes
- **ngModel:** due to [274e9353](https://github.com/angular/angular.js/commit/274e93537ed4e95aefeacea48909eb334894f0ac),
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);
};
}
};
}
};
});
```
<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.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.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)
## Bug Fixes
- **$animate:**
- ignore invalid option parameter values
([72edd4df](https://github.com/angular/angular.js/commit/72edd4dff931c644eecb8f0d1c878dc839c76947),
[#11826](https://github.com/angular/angular.js/issues/11826))
- accept unwrapped DOM elements as inputs for enter + move
([f26fc26f](https://github.com/angular/angular.js/commit/f26fc26f6ea283b2fc5ddb18627b13850de2663e),
[#11848](https://github.com/angular/angular.js/issues/11848))
- **$animateCss:** ensure that custom durations do not confuse the gcs cache
([e0e1b520](https://github.com/angular/angular.js/commit/e0e1b5208767dd62f5586fdc607cb2e31dac9516),
[#11723](https://github.com/angular/angular.js/issues/11723), [#11852](https://github.com/angular/angular.js/issues/11852))
- **$http:** do not modify the config object passed into $http short methods
([f7a4b481](https://github.com/angular/angular.js/commit/f7a4b48121ed2b04af89bd2b754f500d1872360d))
- **ngAnimate:**
- close follow-up class-based animations when the same class is added/removed when removed/added
([db246eb7](https://github.com/angular/angular.js/commit/db246eb701529b41049fc118908e528920f13b24),
[#11717](https://github.com/angular/angular.js/issues/11717))
- ensure nested class-based animations are spaced out with a RAF
([213c2a70](https://github.com/angular/angular.js/commit/213c2a703293ee0af8229dde2b608687cd77ccfa),
[#11812](https://github.com/angular/angular.js/issues/11812))
- class-based animations must not set addClass/removeClass CSS classes on the element
([3a3db690](https://github.com/angular/angular.js/commit/3a3db690a16e888aa7371e3b02e2954b9ec2d558),
[#11810](https://github.com/angular/angular.js/issues/11810))
- ensure that repeated structural calls during pre-digest function
([2327f5a0](https://github.com/angular/angular.js/commit/2327f5a0a7e018a9b03aefabe1fbd0c9330e2eeb),
[#11867](https://github.com/angular/angular.js/issues/11867))
- ensure that cancelled class-based animations are properly cleaned up
([718ff844](https://github.com/angular/angular.js/commit/718ff84405558ac64402e1fca5caefd7d307ea1e),
[#11652](https://github.com/angular/angular.js/issues/11652))
- throw an error if a callback is passed to animate methods
([9bb4d6cc](https://github.com/angular/angular.js/commit/9bb4d6ccbe80b7704c6b7f53317ca8146bc103ca),
[#11826](https://github.com/angular/angular.js/issues/11826), [#11713](https://github.com/angular/angular.js/issues/11713))
- ensure anchored animations remove the leave element at correct time
([64c66d0e](https://github.com/angular/angular.js/commit/64c66d0eea11b575d2a71d00c70cfc5be12cd450),
[#11850](https://github.com/angular/angular.js/issues/11850))
- **select:** prevent unknown option being added to select when bound to null property
([4090491c](https://github.com/angular/angular.js/commit/4090491c73910c169d4fba0494a4e26b45dca7ec),
[#11872](https://github.com/angular/angular.js/issues/11872), [#11875](https://github.com/angular/angular.js/issues/11875))
## Features
- **filterFilter:** allow array like objects to be filtered
([1b0d0fd8](https://github.com/angular/angular.js/commit/1b0d0fd8d00b42dffd798845fe0947d594372613),
[#11782](https://github.com/angular/angular.js/issues/11782), [#11787](https://github.com/angular/angular.js/issues/11787))
<a name="1.4.0-rc.2"></a>
# 1.4.0-rc.2 rocket-zambonimation (2015-05-12)
## Bug Fixes
- **$compile:** ensure directive names have no leading or trailing whitespace
([bab474aa](https://github.com/angular/angular.js/commit/bab474aa8b146f6732857c3af1a8b3b010fda8b0),
[#11397](https://github.com/angular/angular.js/issues/11397), [#11772](https://github.com/angular/angular.js/issues/11772))
- **$httpParamSerializerJQLike:** follow jQuery logic for nested params
([2420a0a7](https://github.com/angular/angular.js/commit/2420a0a77e27b530dbb8c41319b2995eccf76791),
[#11551](https://github.com/angular/angular.js/issues/11551), [#11635](https://github.com/angular/angular.js/issues/11635))
- **jqLite:** check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
([426a5ac0](https://github.com/angular/angular.js/commit/426a5ac0547109648e5c5e358f668c274a111ab2),
[#11508](https://github.com/angular/angular.js/issues/11508))
- **ngAnimate:**
- ensure that multiple requests to requestAnimationFrame are buffered
([db20b830](https://github.com/angular/angular.js/commit/db20b830fc6074a00dc11d3f47d665c55e8bb515),
[#11791](https://github.com/angular/angular.js/issues/11791))
- ensure that an object is always returned even when no animation is set to run
([d5683d21](https://github.com/angular/angular.js/commit/d5683d21165e725bc5a850e795f681b0a8a008f5))
- force use of `ng-anchor` instead of a suffixed `-anchor` CSS class when triggering anchor animations
([df24410c](https://github.com/angular/angular.js/commit/df24410c17d51a8d44929b9cffee2c91cedfed72))
- rename `ng-animate-anchor` to `ng-anchor`
([e6d053de](https://github.com/angular/angular.js/commit/e6d053de0993c0d38de46ad8a9c6760537316430))
- ensure that shared CSS classes between anchor nodes are retained
([e0014002](https://github.com/angular/angular.js/commit/e0014002370278778077d0612f9fab6beb80d07a),
[#11681](https://github.com/angular/angular.js/issues/11681))
- prohibit usage of the `ng-animate` class with classNameFilter
([1002b80a](https://github.com/angular/angular.js/commit/1002b80a6fb5d98c424a01330234276d65d93c0b),
[#11431](https://github.com/angular/angular.js/issues/11431), [#11807](https://github.com/angular/angular.js/issues/11807))
- ensure that the temporary CSS classes are applied before detection
([f7e9ff1a](https://github.com/angular/angular.js/commit/f7e9ff1aba9ed70835c084e6e154f6b0bf9c3a19),
[#11769](https://github.com/angular/angular.js/issues/11769), [#11804](https://github.com/angular/angular.js/issues/11804))
- ensure that all jqLite elements are deconstructed properly
([64d05180](https://github.com/angular/angular.js/commit/64d05180a667e586328fbdbd328889d3b003571d),
[#11658](https://github.com/angular/angular.js/issues/11658))
- ensure animations are not attempted on text nodes
([2aacc2d6](https://github.com/angular/angular.js/commit/2aacc2d622893e05eb94b3974d562e681cc3a17f),
[#11703](https://github.com/angular/angular.js/issues/11703))
- ensure JS animations recognize $animateCss directly
([0681a540](https://github.com/angular/angular.js/commit/0681a5400e4150a961f9c8651e55623ca23b0cc2))
- **ngClass:** add/remove classes which are properties of Object.prototype
([f7b99970](https://github.com/angular/angular.js/commit/f7b999703f4f3bdaea035ce692f1a656b0c1a933),
[#11813](https://github.com/angular/angular.js/issues/11813), [#11814](https://github.com/angular/angular.js/issues/11814))
- **ngOptions:**
- ensure that tracked properties are always watched
([b5a9053b](https://github.com/angular/angular.js/commit/b5a9053ba33d48db2482ca6736d1fcae8b33d0f8),
[#11784](https://github.com/angular/angular.js/issues/11784))
- ensure label is watched in all cases
([ae98dadf](https://github.com/angular/angular.js/commit/ae98dadf6dca3313746f42a441c7659654dd9d50),
[#11765](https://github.com/angular/angular.js/issues/11765))
- iterate over the options collection in the same way as `ngRepeat`
([dfa722a8](https://github.com/angular/angular.js/commit/dfa722a8a6864793fd9580d8ae704a06d10b5509),
[#11733](https://github.com/angular/angular.js/issues/11733))
- use watchCollection not deep watch of ngModel
([47f9fc3e](https://github.com/angular/angular.js/commit/47f9fc3e70bc361e8c11fe68dc3ec4489238efb3),
[#11372](https://github.com/angular/angular.js/issues/11372), [#11653](https://github.com/angular/angular.js/issues/11653), [#11743](https://github.com/angular/angular.js/issues/11743))
- **ngTouch:**
- check undefined tagName for SVG event target
([74eb17d7](https://github.com/angular/angular.js/commit/74eb17d7c8232f72f134bf2546f10fed7234d276))
- don't prevent click event after a touchmove
([95521876](https://github.com/angular/angular.js/commit/95521876eb9eb330548b0549f0cfe22a26d88f6e),
[#10985](https://github.com/angular/angular.js/issues/10985))
## Features
- **$resource:** include request context in error message
([266bc652](https://github.com/angular/angular.js/commit/266bc6520ba4d188dbc949643def102604f98905),
[#11363](https://github.com/angular/angular.js/issues/11363))
## Breaking Changes
### ngAnimate
- **$animateCss:** due to [d5683d21](https://github.com/angular/angular.js/commit/d5683d21165e725bc5a850e795f681b0a8a008f5),
The $animateCss service will now always return an
object even if the animation is not set to run. If your code is using
$animateCss then please consider the following code change:
```
// before
var animator = $animateCss(element, { ... });
if (!animator) {
continueApp();
return;
}
var runner = animator.start();
runner.done(continueApp);
runner.then(continueApp);
// now
var animator = $animateCss(element, { ... });
var runner = animator.start();
runner.done(continueApp);
runner.then(continueApp);
```
- due to [df24410c](https://github.com/angular/angular.js/commit/df24410c17d51a8d44929b9cffee2c91cedfed72),
Prior to this fix there were to ways to apply CSS
animation code to an anchor animation. With this fix, the suffixed
CSS -anchor classes are now not used anymore for CSS anchor animations.
Instead just use the `ng-anchor` CSS class like so:
```html
<div class="container-animation" ng-if="on">
<div ng-animate-ref="1" class="my-anchor-element"></div>
</div>
<div class="container-animation" ng-if="!on">
<div ng-animate-ref="1" class="my-anchor-element"></div>
</div>
```
**before**:
```css
/* before (notice the container-animation CSS class) */
.container-animation-anchor {
transition:0.5s linear all;
}
```
**now**:
```css
/* now (just use `ng-anchor` on a class that both the
elements that contain `ng-animate-ref` share) */
.my-anchor-element.ng-anchor {
transition:0.5s linear all;
}
```
- due to [e6d053de](https://github.com/angular/angular.js/commit/e6d053de0993c0d38de46ad8a9c6760537316430),
if your CSS code made use of the `ng-animate-anchor`
CSS class for referencing the anchored animation element then your
code must now use `ng-anchor` instead.
- due to [1002b80a](https://github.com/angular/angular.js/commit/1002b80a6fb5d98c424a01330234276d65d93c0b),
partially or fully using a regex value containing
`ng-animate` as a token is not allowed anymore. Doing so will trigger a
minErr exception to be thrown.
So don't do this:
```js
// only animate elements that contain the `ng-animate` CSS class
$animateProvider.classNameFilter(/ng-animate/);
// or partially contain it
$animateProvider.classNameFilter(/some-class ng-animate another-class/);
```
but this is OK:
```js
$animateProvider.classNameFilter(/ng-animate-special/);
```
### ngOptions
- ** due to [dfa722a8](https://github.com/angular/angular.js/commit/dfa722a8a6864793fd9580d8ae704a06d10b5509),
Although it is unlikely that anyone is using it in this way, this change does change the
behaviour of `ngOptions` in the following case:
* you are iterating over an array-like object, using the array form of the `ngOptions` syntax
(`item.label for item in items`) and that object contains non-numeric property keys.
In this case these properties with non-numeric keys will be ignored.
** Here array-like is defined by the result of a call to this internal function:
https://github.com/angular/angular.js/blob/v1.4.0-rc.1/src/Angular.js#L198-L211 **
To get the desired behaviour you need to iterate using the object form of the `ngOptions` syntax
(`value.label` for (key, value) in items)`).
<a name="1.4.0-beta.6"></a>
# 1.4.0-beta.6 cookie-liberation (2015-03-17)
## Bug Fixes
- **$animate:** call `applyStyles` from options on `leave`
([4374f892](https://github.com/angular/angular.js/commit/4374f892c6fa4af6ba1f2ed47c5f888fdb5fadc5),
[#10068](https://github.com/angular/angular.js/issues/10068))
- **$browser:** don't crash if `history.state` access causes error in IE
([3b8163b7](https://github.com/angular/angular.js/commit/3b8163b7b664f24499e75460ab50c066eaec0f78),
[#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369))
- **$sanitize:** disallow unsafe svg animation tags
([67688d5c](https://github.com/angular/angular.js/commit/67688d5ca00f6de4c7fe6084e2fa762a00d25610),
[#11290](https://github.com/angular/angular.js/issues/11290))
- **Angular:** properly compare RegExp with other objects for equality
([f22e1fc9](https://github.com/angular/angular.js/commit/f22e1fc9610ae111a3ea8746a3a57169c99ce142),
[#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205))
- **date filter:** display localised era for `G` format codes
([2b4dfa9e](https://github.com/angular/angular.js/commit/2b4dfa9e2b63d7ebb78f3b0fd3439d18f932e1cd),
[#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266))
- **filterFilter:**
- fix filtering using an object expression when the filter value is undefined
([c62fa6bd](https://github.com/angular/angular.js/commit/c62fa6bd898e1048d4690d41034489dc60ba6ac2),
[#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424))
- do not throw an error if property is null when comparing objects
([2c4ffd6a](https://github.com/angular/angular.js/commit/2c4ffd6af4eb012c4054fe7c096267bbc5510af0),
[#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116))
- **form:** allow dynamic form names which initially evaluate to blank
([410f7c68](https://github.com/angular/angular.js/commit/410f7c682633c681be641cd2a321f9e51671d474))
- **jqLite:** attr should ignore comment, text and attribute nodes
([bb5bf7f8](https://github.com/angular/angular.js/commit/bb5bf7f8162d11610a53428e630b47030bdc38e5))
- **ng/$locale:** add ERA info in generic locale
([4acb0af2](https://github.com/angular/angular.js/commit/4acb0af24c7fb3705a197ca96adc532de4766a7a))
- **ngJq:** don't rely on existence of jqlite
([342e5f3c](https://github.com/angular/angular.js/commit/342e5f3ce38d2fd10c5d5a98ca66f864286a7922),
[#11044](https://github.com/angular/angular.js/issues/11044))
- **ngMessages:** ensure that multi-level transclusion works with `ngMessagesInclude`
([d7ec5f39](https://github.com/angular/angular.js/commit/d7ec5f392e1550658ddf271a30627b1749eccb69),
[#11196](https://github.com/angular/angular.js/issues/11196))
- **ngOptions:** fix model<->option interaction when using `track by`
([6a03ca27](https://github.com/angular/angular.js/commit/6a03ca274314352052c3082163367a146bb11c2d),
[#10869](https://github.com/angular/angular.js/issues/10869), [#10893](https://github.com/angular/angular.js/issues/10893))
- **rootScope:** prevent memory leak when destroying scopes
([fb7db4a0](https://github.com/angular/angular.js/commit/fb7db4a07bd1b0b67824d3808fe315419b272689),
[#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169))
## Features
- **$cookies:**
- allow passing cookie options
([92c366d2](https://github.com/angular/angular.js/commit/92c366d205da36ec26502aded23db71a6473dad7),
[#8324](https://github.com/angular/angular.js/issues/8324), [#3988](https://github.com/angular/angular.js/issues/3988), [#1786](https://github.com/angular/angular.js/issues/1786), [#950](https://github.com/angular/angular.js/issues/950))
- move logic into $cookies and deprecate $cookieStore
([38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
[#6411](https://github.com/angular/angular.js/issues/6411), [#7631](https://github.com/angular/angular.js/issues/7631))
- **$cookiesProvider:** provide path, domain, expires and secure options
([53c66369](https://github.com/angular/angular.js/commit/53c663699126815eabc2a3bc1e3bafc8b3874268))
- **$interval:** pass additional arguments to the callback
([4f1f9cfd](https://github.com/angular/angular.js/commit/4f1f9cfdb721cf308ca1162b2227836dc1d28388),
[#10632](https://github.com/angular/angular.js/issues/10632))
- **$timeout:** pass additional arguments to the callback
([3a4b6b83](https://github.com/angular/angular.js/commit/3a4b6b83efdb8051e5c4803c0892c19ceb2cba50),
[#10631](https://github.com/angular/angular.js/issues/10631))
- **angular.merge:** provide an alternative to `angular.extend` that merges 'deeply'
([c0498d45](https://github.com/angular/angular.js/commit/c0498d45feb913c318224ea70b5adf7112df6bac),
[#10507](https://github.com/angular/angular.js/issues/10507), [#10519](https://github.com/angular/angular.js/issues/10519))
- **filterFilter:** compare object with custom `toString()` to primitive
([f8c42161](https://github.com/angular/angular.js/commit/f8c421617096a8d613f4eb6d0f5b098ee149c029),
[#10464](https://github.com/angular/angular.js/issues/10464), [#10548](https://github.com/angular/angular.js/issues/10548))
- **ngAria:**
- add `button` role to `ngClick`
([bb365070](https://github.com/angular/angular.js/commit/bb365070a3ed7c2d26056d378ab6a8ef493b23cc),
[#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318))
- add roles to custom inputs
([29cdaee2](https://github.com/angular/angular.js/commit/29cdaee2b6e853bc3f8882a00661698d146ecd18),
[#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318))
- **ngLocale:** Add FIRSTDAYOFWEEK and WEEKENDRANGE from google data
([3d149c7f](https://github.com/angular/angular.js/commit/3d149c7f20ffabab5a635af9ddcfc7105112ab4a))
- **ngMock:**
- allow mock $controller service to set up controller bindings
([d02d0585](https://github.com/angular/angular.js/commit/d02d0585a086ecd2e1de628218b5a6d85c8fc7bd),
[#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239))
- add `they` helpers for testing multiple specs
([e650c458](https://github.com/angular/angular.js/commit/e650c45894abe6314a806e6b3e32c908df5c00fd),
[#10864](https://github.com/angular/angular.js/issues/10864))
- **ngModel:** support conversion to timezone other than UTC
([0413bee8](https://github.com/angular/angular.js/commit/0413bee8cc563a6555f8d42d5f183f6fbefc7350),
[#11005](https://github.com/angular/angular.js/issues/11005))
## Breaking Changes
- **$cookies:** due to [38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
`$cookies` no longer exposes properties that represent the current browser cookie
values. Now you must explicitly the methods described above to access the cookie
values. This also means that you can no longer watch the `$cookies` properties for
changes to the browser's cookies.
This feature is generally only needed if a 3rd party library was programmatically
changing the cookies at runtime. If you rely on this then you must either write code that
can react to the 3rd party library making the changes to cookies or implement your own polling
mechanism.
<a name="1.3.15"></a>
# 1.3.15 locality-filtration (2015-03-17)
## Bug Fixes
- **$animate:** call `applyStyles` with options on `leave`
([ebd84e80](https://github.com/angular/angular.js/commit/ebd84e8008f45ccaa84290f6da8c2a114fcfa8cd),
[#10068](https://github.com/angular/angular.js/issues/10068))
- **$browser:** don't crash if history.state access causes error in IE
([92767c09](https://github.com/angular/angular.js/commit/92767c098feaf8c58faf2d67f882305019d8160e),
[#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369))
- **Angular:** properly compare RegExp with other objects for equality
([b8e8f9af](https://github.com/angular/angular.js/commit/b8e8f9af78f4ef3e556dd3cef6bfee35ad4cb82a),
[#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205))
- **date filter:** display localised era for `G` format codes
([f2683f95](https://github.com/angular/angular.js/commit/f2683f956fcd3216eaa263db20b31e0d46338800),
[#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266))
- **filterFilter:**
- fix filtering using an object expression when the filter value is `undefined`
([63b9956f](https://github.com/angular/angular.js/commit/63b9956faf4c3679c88a9401b8ccbb111c0294ee),
[#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424))
- do not throw an error if property is null when comparing objects
([01161a0e](https://github.com/angular/angular.js/commit/01161a0e9fb1af93e9f06535aed8392ed7f116a4),
[#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116))
- **form:** allow dynamic form names which initially evaluate to blank
([190ea883](https://github.com/angular/angular.js/commit/190ea883c588d63f8b900a8de1d45c6c9ebb01ec),
[#11096](https://github.com/angular/angular.js/issues/11096))
- **ng/$locale:** add ERA info in generic locale
([57842530](https://github.com/angular/angular.js/commit/578425303f2480959da80f31920d08f277d42010))
- **rootScope:** prevent memory leak when destroying scopes
([528cf09e](https://github.com/angular/angular.js/commit/528cf09e3f78ad4e3bb6a329ebe315c4f29b4cdb),
[#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169))
- **templateRequest:** avoid throwing syntax error in Android 2.3
([75abbd52](https://github.com/angular/angular.js/commit/75abbd525f07866fdcc6fb311802b8fe700af174),
[#11089](https://github.com/angular/angular.js/issues/11089), [#11051](https://github.com/angular/angular.js/issues/11051), [#11088](https://github.com/angular/angular.js/issues/11088))
## Features
- **ngAria:**
- add `button` role to `ngClick`
([b9ad91cf](https://github.com/angular/angular.js/commit/b9ad91cf1e86310a2d2bf13b29fa13a9b835e1ce),
[#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318))
- add roles to custom inputs
([21369943](https://github.com/angular/angular.js/commit/21369943fafd577b36827a641b021b1c14cefb57),
[#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318))
- **ngMock:**
- allow mock $controller service to set up controller bindings
([b3878a36](https://github.com/angular/angular.js/commit/b3878a36d9f8e56ad7be1eedb9691c9bd12568cb),
[#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239))
- add `they` helpers for testing multiple specs
([7288be25](https://github.com/angular/angular.js/commit/7288be25a75d6ca6ac7eca05a7d6b12ccb3a22f8),
[#10864](https://github.com/angular/angular.js/issues/10864))
<a name="1.4.0-beta.5"></a>
# 1.4.0-beta.5 karmic-stabilization (2015-02-24)
## Bug Fixes
- **$http:** properly access request headers with mixed case
([5da1256f](https://github.com/angular/angular.js/commit/5da1256fc2812d5b28fb0af0de81256054856369),
[#10881](https://github.com/angular/angular.js/issues/10881), [#10883](https://github.com/angular/angular.js/issues/10883))
- **input:** create max and/or min validator regardless of initial value
([c211e7a5](https://github.com/angular/angular.js/commit/c211e7a5ad5f1fb8748125f14912aa8715081925),
[#10307](https://github.com/angular/angular.js/issues/10307), [#10327](https://github.com/angular/angular.js/issues/10327))
- **ngAria:** correctly set "checked" attr for checkboxes and radios
([d6eba217](https://github.com/angular/angular.js/commit/d6eba21733c6e67e90e3a4763d8d41ad89a73a0c),
[#10389](https://github.com/angular/angular.js/issues/10389), [#10212](https://github.com/angular/angular.js/issues/10212))
- **ngModel:** fix issues when parserName is same as validator key
([056a3170](https://github.com/angular/angular.js/commit/056a31700803c0a6014b43cfcc36c5c500cc596e),
[#10698](https://github.com/angular/angular.js/issues/10698), [#10850](https://github.com/angular/angular.js/issues/10850), [#11046](https://github.com/angular/angular.js/issues/11046))
- **ngOptions:** ngModel is optional
([ef894c87](https://github.com/angular/angular.js/commit/ef894c87eaead76d90169113ab6acc9287654ea3))
- **ngSanitize:** Do not ignore white-listed svg camelCased attributes
([46b80654](https://github.com/angular/angular.js/commit/46b80654cae9105642909cd55f73f7c26d2fbd80),
[#10779](https://github.com/angular/angular.js/issues/10779), [#10990](https://github.com/angular/angular.js/issues/10990), [#11124](https://github.com/angular/angular.js/issues/11124))
- **select:** remove unknown option when model is undefined and empty option is available
([30b48132](https://github.com/angular/angular.js/commit/30b48132e0fb92ea8dd25a9794b4c41a3a81a951),
[#11078](https://github.com/angular/angular.js/issues/11078), [#11092](https://github.com/angular/angular.js/issues/11092))
- **templateRequest:** avoid throwing syntax error in Android 2.3
([f6272333](https://github.com/angular/angular.js/commit/f6272333127d908b19da23f9cd8a74052711795b),
[#11089](https://github.com/angular/angular.js/issues/11089), [#11051](https://github.com/angular/angular.js/issues/11051), [#11088](https://github.com/angular/angular.js/issues/11088))
## Features
- **CommonJS:** - angular modules are now packaged for npm with helpful exports
- **limitTo:** extend the filter to take a beginning index argument
([aaae3cc4](https://github.com/angular/angular.js/commit/aaae3cc4160417e6dad802ed9d9f6d5471821a87),
[#5355](https://github.com/angular/angular.js/issues/5355), [#10899](https://github.com/angular/angular.js/issues/10899))
- **ngMessages:** provide support for dynamic message resolution
([c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
[#10036](https://github.com/angular/angular.js/issues/10036), [#9338](https://github.com/angular/angular.js/issues/9338))
- **ngOptions:** add support for disabling an option
([da9eac86](https://github.com/angular/angular.js/commit/da9eac8660343b1cd9fdcf9d2d1bda06067142d7),
[#638](https://github.com/angular/angular.js/issues/638), [#11017](https://github.com/angular/angular.js/issues/11017))
## Performance Improvements
- **$compile:**
- replace forEach(controller) with plain loops
([5b522867](https://github.com/angular/angular.js/commit/5b5228675f67c8f5e04c7183c3ef5e71cb2bf08b),
[#11084](https://github.com/angular/angular.js/issues/11084))
- avoid .data when fetching required controllers
([fa0aa839](https://github.com/angular/angular.js/commit/fa0aa83937378cf8fc720c38bcc5c78fc923624e))
- **ngOptions:** only watch labels if a display expression is specified
([51faaffd](https://github.com/angular/angular.js/commit/51faaffdbcc734c55d52ff6c42b386d5c90207ea))
## Breaking Changes
- **ngMessages:** due to [c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
The `ngMessagesInclude` attribute is now its own directive and that must
be placed as a **child** element within the element with the ngMessages
directive. (Keep in mind that the former behaviour of the
ngMessageInclude attribute was that all **included** ngMessage template
code was placed at the **bottom** of the element containing the
ngMessages directive; therefore to make this behave in the same way,
place the element containing the ngMessagesInclude directive at the
end of the container containing the ngMessages directive).
```html
<!-- AngularJS 1.3.x -->
<div ng-messages="model.$error" ng-messages-include="remote.html">
<div ng-message="required">Your message is required</div>
</div>
<!-- AngularJS 1.4.x -->
<div ng-messages="model.$error">
<div ng-message="required">Your message is required</div>
<div ng-messages-include="remote.html"></div>
</div>
```
<a name="1.3.14"></a>
# 1.3.14 instantaneous-browserification (2015-02-24)
## Features
- **CommonJS:** - angular modules are now packaged for npm with helpful exports
## Bug Fixes
- **input:** create max and/or min validator regardless of initial value
([abfce532](https://github.com/angular/angular.js/commit/abfce5327ce6fd29c33c62d2edf3600674a6b4c0),
[#10307](https://github.com/angular/angular.js/issues/10307), [#10327](https://github.com/angular/angular.js/issues/10327))
- **ngAria:** correctly set "checked" attr for checkboxes and radios
([944c150e](https://github.com/angular/angular.js/commit/944c150e6c3001e51d4bf5e2d8149ae4c565d1e3),
[#10389](https://github.com/angular/angular.js/issues/10389), [#10212](https://github.com/angular/angular.js/issues/10212))
- **ngModel:** fix issues when parserName is same as validator key
([6b7625a0](https://github.com/angular/angular.js/commit/6b7625a09508c4b5355121a9d4206a734b07b2e1),
[#10698](https://github.com/angular/angular.js/issues/10698), [#10850](https://github.com/angular/angular.js/issues/10850), [#11046](https://github.com/angular/angular.js/issues/11046))
<a name="1.4.0-beta.4"></a>
# 1.4.0-beta.4 overlyexplosive-poprocks (2015-02-09)
## Bug Fixes
- **$location:** prevent page reload if initial url has empty hash at the end
([a509e9aa](https://github.com/angular/angular.js/commit/a509e9aa149d0f88cc39f703d539f7ffd4cd6103),
[#10397](https://github.com/angular/angular.js/issues/10397), [#10960](https://github.com/angular/angular.js/issues/10960))
- **$parse:** Initialize elements in an array from left to right
([966f6d83](https://github.com/angular/angular.js/commit/966f6d831f9469a917601f9a10604612cd7bd792))
- **ngAria:** ensure native controls fire a single click
([9d53e5a3](https://github.com/angular/angular.js/commit/9d53e5a38dd369dec82d82e13e078df3d6054c8a),
[#10388](https://github.com/angular/angular.js/issues/10388), [#10766](https://github.com/angular/angular.js/issues/10766))
- **ngMock:** handle cases where injector is created before tests
([898714df](https://github.com/angular/angular.js/commit/898714df9ea38f9ef700015ced5ddea52f096b77),
[#10967](https://github.com/angular/angular.js/issues/10967))
- **sanitize:** handle newline characters inside special tags
([cc8755cd](https://github.com/angular/angular.js/commit/cc8755cda6efda0b52954388e8a8d5306e4bfbca),
[030a42e7](https://github.com/angular/angular.js/commit/030a42e79dec8a4bb73053762f7a54d797a058f6)
[#10943](https://github.com/angular/angular.js/issues/10943))
## Features
- **ng-jq:** adds the ability to force jqLite or a specific jQuery version
([09ee82d8](https://github.com/angular/angular.js/commit/09ee82d84dcbea4a6e8d85903af82dcd087a78a7))
<a name="1.3.13"></a>
# 1.3.13 meticulous-riffleshuffle (2015-02-09)
## Bug Fixes
- **$location:** prevent page reload if initial url has empty hash at the end
([4b3a590b](https://github.com/angular/angular.js/commit/4b3a590b009d7fdceda7f52e7ba0352a271b3256),
[#10397](https://github.com/angular/angular.js/issues/10397), [#10960](https://github.com/angular/angular.js/issues/10960))
- **ngAria:** ensure native controls fire a single click
([69ee593f](https://github.com/angular/angular.js/commit/69ee593fd2cb5f1d7757efbe6b256e4458752fd7),
[#10388](https://github.com/angular/angular.js/issues/10388), [#10766](https://github.com/angular/angular.js/issues/10766))
- **ngMock:** handle cases where injector is created before tests
([39ddef68](https://github.com/angular/angular.js/commit/39ddef682971d3b7282bf9d08f6eaf97b7f4bca4),
[#10967](https://github.com/angular/angular.js/issues/10967))
- **sanitize:** handle newline characters inside special tags
([11aedbd7](https://github.com/angular/angular.js/commit/11aedbd741ccddba060a9805adba1779391731da),
[ce49d4d6](https://github.com/angular/angular.js/commit/ce49d4d61bd02464b6c6376af8048f6eb09330a8)
[#10943](https://github.com/angular/angular.js/issues/10943))
<a name="1.4.0-beta.3"></a>
# 1.4.0-beta.3 substance-mimicry (2015-02-02)
@@ -4308,7 +5080,7 @@ For more info: http://blog.angularjs.org/2013/12/angularjs-13-new-release-approa
- properly toggle multiple classes
([4e73c80b](https://github.com/angular/angular.js/commit/4e73c80b17bd237a8491782bcf9e19f1889e12ed),
[#4467](https://github.com/angular/angular.js/issues/4467), [#6448](https://github.com/angular/angular.js/issues/6448))
- make jqLite('<iframe src="someurl">').contents() return iframe document, as in jQuery
- make `jqLite(<iframe src="someurl">').contents()` return iframe document, as in jQuery
([05fbed57](https://github.com/angular/angular.js/commit/05fbed5710b702c111c1425a9e241c40d13b0a54),
[#6320](https://github.com/angular/angular.js/issues/6320), [#6323](https://github.com/angular/angular.js/issues/6323))
- **numberFilter:** convert all non-finite/non-numbers/non-numeric strings to the empty string
@@ -8684,7 +9456,7 @@ with the `$route` service
mocks now part of `angular-mocks.js` (commit f5d08963)
### Bug Fixes
- <select> (one/multiple) could not chose from a list of objects (commit 347be5ae)
- `<select>` (one/multiple) could not chose from a list of objects (commit 347be5ae)
- null and other falsy values should not be rendered in the view (issue #242)
### Docs
+10 -4
View File
@@ -1,4 +1,4 @@
#Contributing to AngularJS
# Contributing to AngularJS
We'd love for you to contribute to our source code and to make AngularJS even better than it is
today! Here are the guidelines we'd like you to follow:
@@ -54,7 +54,7 @@ For large fixes, please build and test the documentation before submitting the P
accidentally introduced any layout or formatting issues. You should also make sure that your commit message
is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times.
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times.
## <a name="submit"></a> Submission Guidelines
@@ -199,9 +199,14 @@ 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.
### 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:
@@ -227,14 +232,15 @@ The subject contains succinct description of the change:
* don't capitalize first letter
* no dot (.) at the end
###Body
### Body
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
### 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].
+33 -16
View File
@@ -17,10 +17,6 @@ module.exports = function(grunt) {
NG_VERSION.cdn = versionInfo.cdnVersion;
var dist = 'angular-'+ NG_VERSION.full;
//global beforeEach
util.init();
//config
grunt.initConfig({
NG_VERSION: NG_VERSION,
@@ -159,7 +155,7 @@ module.exports = function(grunt) {
jscs: {
src: ['src/**/*.js', 'test/**/*.js'],
options: {
config: ".jscs.json"
config: '.jscsrc'
}
},
@@ -224,9 +220,9 @@ module.exports = function(grunt) {
dest: 'build/angular-aria.js',
src: util.wrap(files['angularModules']['ngAria'], 'module')
},
"promises-aplus-adapter": {
'promises-aplus-adapter': {
dest:'tmp/promises-aplus-adapter++.js',
src:['src/ng/q.js','lib/promises-aplus/promises-aplus-test-adapter.js']
src:['src/ng/q.js', 'lib/promises-aplus/promises-aplus-test-adapter.js']
}
},
@@ -245,17 +241,28 @@ module.exports = function(grunt) {
},
"ddescribe-iit": {
'ddescribe-iit': {
files: [
'src/**/*.js',
'test/**/*.js',
'!test/ngScenario/DescribeSpec.js',
'!src/ng/directive/attrs.js', // legitimate xit here
'!src/ngScenario/**/*.js'
]
'!src/ngScenario/**/*.js',
'!test/helpers/privateMocks*.js'
],
options: {
disallowed: [
'iit',
'xit',
'tthey',
'xthey',
'ddescribe',
'xdescribe'
]
}
},
"merge-conflict": {
'merge-conflict': {
files: [
'src/**/*',
'test/**/*',
@@ -285,7 +292,11 @@ module.exports = function(grunt) {
},
shell: {
"promises-aplus-tests": {
'npm-install': {
command: 'node scripts/npm/check-node-modules.js'
},
'promises-aplus-tests': {
options: {
stdout: false,
stderr: true,
@@ -311,9 +322,15 @@ module.exports = function(grunt) {
}
});
// global beforeEach task
if (!process.env.TRAVIS) {
grunt.task.run('shell:npm-install');
}
//alias tasks
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:protractor']);
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package', 'test:unit', 'test:promises-aplus', 'tests:docs', 'test:protractor']);
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
grunt.registerTask('test:jquery', 'Run the jQuery unit tests with Karma', ['tests:jquery']);
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['build', 'tests:modules']);
@@ -323,11 +340,11 @@ module.exports = function(grunt) {
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
grunt.registerTask('test:e2e', 'Alias for test:protractor', ['test:protractor']);
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter', 'shell:promises-aplus-tests']);
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
grunt.registerTask('default', ['package']);
};
+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
+5 -1
View File
@@ -55,7 +55,11 @@ This process based on the idea of minimizing user pain
* inconvenience - causes ugly/boilerplate code in apps
1. Label `component: *`
* In rare cases, it's ok to have multiple components.
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex.
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. In addition to applying this label, you must:
* Leave a comment explaining the problem and solution so someone can easily finish it.
* Assign the issue to yourself.
* Give feedback on PRs addressing this issue.
* You are responsible for mentoring contributors helping with this issue.
1. Label `origin: google` for issues from Google
1. Assign a milestone:
* Backlog - triaged fixes and features, should be the default choice
+2 -1
View File
@@ -32,6 +32,7 @@ var angularFiles = {
'src/ng/q.js',
'src/ng/raf.js',
'src/ng/rootScope.js',
'src/ng/rootElement.js',
'src/ng/sanitizeUri.js',
'src/ng/sce.js',
'src/ng/sniffer.js',
@@ -78,7 +79,7 @@ var angularFiles = {
],
'angularLoader': [
'stringify.js',
'src/stringify.js',
'src/minErr.js',
'src/loader.js'
],
+6
View File
@@ -583,6 +583,12 @@ ul.events > li {
margin-bottom:40px;
}
.definition-table td {
padding: 8px;
border: 1px solid #eee;
vertical-align: top;
}
@media only screen and (min-width: 769px) and (max-width: 991px) {
.main-body-grid {
margin-top: 160px;
+11 -6
View File
@@ -6,18 +6,18 @@ var packagePath = __dirname;
var Package = require('dgeni').Package;
// Create and export a new Dgeni package called angularjs. This package depends upon
// the ngdoc,nunjucks and examples packages defined in the dgeni-packages npm module.
// the ngdoc, nunjucks, and examples packages defined in the dgeni-packages npm module.
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'))
@@ -125,10 +124,16 @@ module.exports = new Package('angularjs', [
});
computeIdsProcessor.idTemplates.push({
docTypes: ['error', 'errorNamespace'],
docTypes: ['error'],
getId: function(doc) { return 'error:' + doc.namespace + ':' + doc.name; },
getAliases: function(doc) { return [doc.name, doc.namespace + ':' + doc.name, doc.id]; }
},
{
docTypes: ['errorNamespace'],
getId: function(doc) { return 'error:' + doc.name; },
getAliases: function(doc) { return [doc.id]; }
});
}
);
})
.config(function(checkAnchorLinksProcessor) {
-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
};
};
+1 -1
View File
@@ -1,7 +1,7 @@
{% extends "base.template.html" %}
{% block content %}
<h1>Error: {$ doc.id $}
<h1>Error: {$ doc.namespace $}:{$ doc.name $}
<div><span class='hint'>{$ doc.fullName $}</span></div>
</h1>
+12
View File
@@ -0,0 +1,12 @@
@ngdoc error
@name $animate:nocb
@fullName Do not pass a callback to animate methods
@description
Since Angular 1.3, the methods of {@link ng.$animate} do not accept a callback as the last parameter.
Instead, they return a promise to which you can attach `then` handlers to be run when the animation completes.
If you are getting this error then you need to update your code to use the promise-based API.
See https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9 for information about
the change to the animation API and the changes you need to make.
+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
+7
View File
@@ -0,0 +1,7 @@
@ngdoc error
@name ng:cpta
@fullName Copying TypedArray
@description
Copying TypedArray's with a destination is not supported because TypedArray
objects can not be mutated, they are fixed length.
@@ -0,0 +1,28 @@
@ngdoc error
@name ngModel:nopromise
@fullName No promise
@description
The return value of an async validator, must always be a promise. If you want to return a
non-promise value, you can convert it to a promise using {@link ng.$q#resolve `$q.resolve()`} or
{@link ng.$q#reject `$q.reject()`}.
Example:
```
.directive('asyncValidator', function($q) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
ngModel.$asyncValidators.myAsyncValidation = function(modelValue, viewValue) {
if (/* I don't need to hit the backend API */) {
return $q.resolve(); // to mark as valid or
// return $q.reject(); // to mark as invalid
} else {
// ...send a request to the backend and return a promise
}
};
}
};
})
```
+56
View File
@@ -0,0 +1,56 @@
@ngdoc error
@name ngModel:numfmt
@fullName Model is not of type `number`
@description
The number input directive `<input type="number">` requires the model to be a `number`.
If the model is something else, this error will be thrown.
Angular does not set validation errors on the `<input>` in this case
as this error is caused by incorrect application logic and not by bad input from the user.
If your model does not contain actual numbers then it is up to the application developer
to use a directive that will do the conversion in the `ngModel` `$formatters` and `$parsers`
pipeline.
## Example
In this example, our model stores the number as a string, so we provide the `stringToNumber`
directive to convert it into the format the `input[number]` directive expects.
<example module="numfmt-error-module">
<file name="index.html">
<table>
<tr ng-repeat="x in ['0', '1']">
<td>
<input type="number" string-to-number ng-model="x" /> {{ x }} : {{ typeOf(x) }}
</td>
</tr>
</table>
</file>
<file name="app.js">
angular.module('numfmt-error-module', [])
.run(function($rootScope) {
$rootScope.typeOf = function(value) {
return typeof value;
};
})
.directive('stringToNumber', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(value) {
return '' + value;
});
ngModel.$formatters.push(function(value) {
return parseFloat(value, 10);
});
}
};
});
</file>
</example>
@@ -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.
+8 -6
View File
@@ -213,11 +213,13 @@ The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redun
If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` if it isn't there
already.
For `ng-click`, keypress will also be bound to `div` and `li` elements. You can turn this
functionality on or off with the `bindKeypress` configuration option.
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.
For `ng-dblclick`, you must manually add `ng-keypress` to non-interactive elements such as `div`
or `taco-button` to enable keyboard access.
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.
<h3>Example</h3>
```html
@@ -233,7 +235,7 @@ Becomes:
The new ngMessages module makes it easy to display form validation or other messages with priority
sequencing and animation. To expose these visual messages to screen readers,
ngAria injects `aria-live="polite"`, causing them to be read aloud any time a message is shown,
ngAria injects `aria-live="assertive"`, causing them to be read aloud any time a message is shown,
regardless of the user's focus location.
###Example
@@ -247,7 +249,7 @@ regardless of the user's focus location.
Becomes:
```html
<div ng-messages="myForm.myName.$error" aria-live="polite">
<div ng-messages="myForm.myName.$error" aria-live="assertive">
<div ng-message="required">You did not enter a field</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
+1 -1
View File
@@ -236,7 +236,7 @@ The example below shows how to perform animations during class changes:
</file>
</example>
Although the CSS is a little different then what we saw before, the idea is the same.
Although the CSS is a little different than what we saw before, the idea is the same.
## Which directives support animations?
+3 -3
View File
@@ -179,11 +179,11 @@ The following graphic shows how everything works together after we introduced th
<img style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding2.png">
## View independent business logic: Services
## View-independent business logic: Services
Right now, the `InvoiceController` contains all logic of our example. When the application grows it
is a good practice to move view independent logic from the controller into a so called
<a name="service">"{@link services service}"</a>, so it can be reused by other parts
is a good practice to move view-independent logic from the controller into a
<a name="service">{@link services service}</a>, so it can be reused by other parts
of the application as well. Later on, we could also change that service to load the exchange rates
from the web, e.g. by calling the Yahoo Finance API, without changing the controller.
+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');
```
+34 -28
View File
@@ -51,9 +51,11 @@ In the following example, we say that the `<input>` element **matches** the `ngM
The following also **matches** `ngModel`:
```html
<input data-ng:model="foo">
<input data-ng-model="foo">
```
### Normalization
Angular **normalizes** an element's tag and attribute name to determine which elements match which
directives. We typically refer to directives by their case-sensitive
[camelCase](http://en.wikipedia.org/wiki/CamelCase) **normalized** name (e.g. `ngModel`).
@@ -100,6 +102,8 @@ If you want to use an HTML validating tool, you can instead use the `data`-prefi
The other forms shown above are accepted for legacy reasons but we advise you to avoid them.
</div>
### Directive types
`$compile` can match directives based on element names, attributes, class names, as well as comments.
All of the Angular-provided directives match attribute name, tag name, comments, or class name.
@@ -827,37 +831,39 @@ element?
<file name="script.js">
angular.module('dragModule', [])
.directive('myDraggable', ['$document', function($document) {
return function(scope, element, attr) {
var startX = 0, startY = 0, x = 0, y = 0;
return {
link: function(scope, element, attr) {
var startX = 0, startY = 0, x = 0, y = 0;
element.css({
position: 'relative',
border: '1px solid red',
backgroundColor: 'lightgrey',
cursor: 'pointer'
});
element.on('mousedown', function(event) {
// Prevent default dragging of selected content
event.preventDefault();
startX = event.pageX - x;
startY = event.pageY - y;
$document.on('mousemove', mousemove);
$document.on('mouseup', mouseup);
});
function mousemove(event) {
y = event.pageY - startY;
x = event.pageX - startX;
element.css({
top: y + 'px',
left: x + 'px'
position: 'relative',
border: '1px solid red',
backgroundColor: 'lightgrey',
cursor: 'pointer'
});
}
function mouseup() {
$document.off('mousemove', mousemove);
$document.off('mouseup', mouseup);
element.on('mousedown', function(event) {
// Prevent default dragging of selected content
event.preventDefault();
startX = event.pageX - x;
startY = event.pageY - y;
$document.on('mousemove', mousemove);
$document.on('mouseup', mouseup);
});
function mousemove(event) {
y = event.pageY - startY;
x = event.pageX - startX;
element.css({
top: y + 'px',
left: x + 'px'
});
}
function mouseup() {
$document.off('mousemove', mousemove);
$document.off('mouseup', mouseup);
}
}
};
}]);
+12 -9
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>
@@ -175,7 +175,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,10 +303,14 @@ 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:
@@ -340,5 +344,4 @@ When using a directive that takes an expression:
<ul>
<li ng-repeat="item in ::items">{{item.name}};</li>
</ul>
```
```
+4 -2
View File
@@ -92,8 +92,10 @@ means that it should be stateless and idempotent. Angular relies on these proper
the filter only when the inputs to the function change.
<div class="alert alert-warning">
**Note:** filter names must be valid angular expression identifiers, such as `uppercase` or `orderBy`.
Names with special characters, such as hyphens and dots, are not allowed.
**Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
(`myapp_subsection_filterx`).
</div>
The following sample filter reverses a text string. In addition, it conditionally makes the
+4
View File
@@ -93,6 +93,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>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<style type="text/css">
@@ -181,6 +183,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>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
</file>
+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)
+1 -1
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.
+3 -3
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.
@@ -245,7 +245,7 @@ of the `$watch` expressions and compares them with the previous value. This dirt
asynchronously. This means that assignment such as `$scope.username="angular"` will not
immediately cause a `$watch` to be notified, instead the `$watch` notification is delayed until
the `$digest` phase. This delay is desirable, since it coalesces multiple model updates into one
`$watch` notification as well as it guarantees that during the `$watch` notification no other
`$watch` notification as well as guarantees that during the `$watch` notification no other
`$watch`es are running. If a `$watch` changes the value of the model, it will force additional
`$digest` cycle.
@@ -264,7 +264,7 @@ the `$digest` phase. This delay is desirable, since it coalesces multiple model
3. **Model mutation**
For mutations to be properly observed, you should make them only within the {@link
ng.$rootScope.Scope#$apply scope.$apply()}. (Angular APIs do this
ng.$rootScope.Scope#$apply scope.$apply()}. Angular APIs do this
implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers,
or asynchronous work with {@link ng.$http $http}, {@link ng.$timeout $timeout}
or {@link ng.$interval $interval} services.
+6 -1
View File
@@ -62,7 +62,7 @@ are available on [the Karma website](http://karma-runner.github.io/0.12/intro/in
### Jasmine
[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a test driven development framework for
[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a behavior driven development framework for
JavaScript that has become the most popular choice for testing Angular applications. Jasmine
provides functions to help with structuring your tests and also making assertions. As your tests
grow, keeping them well structured and documented is vital, and Jasmine helps achieve this.
@@ -260,6 +260,11 @@ myModule.filter('length', function() {
});
describe('length filter', function() {
beforeEach(inject(function(_$filter_){
$filter= _$filter_;
}));
it('returns 0 when given null', function() {
var length = $filter('length');
expect(length(null)).toEqual(0);
+1 -1
View File
@@ -153,7 +153,7 @@ grunt test:unit --browsers Opera,Firefox
Note there should be _no spaces between browsers_. `Opera, Firefox` is INVALID.
During development it's however more productive to continuously run unit tests every time the source or test files
During development, however, it's more productive to continuously run unit tests every time the source or test files
change. To execute tests in this mode run:
1. To start the Karma server, capture Chrome browser and run unit tests, run:
+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.2.0:
example points to the minified version 1.3.14:
```
<!doctype html>
<html ng-app>
<head>
<title>My Angular App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body>
</body>
+1 -1
View File
@@ -67,7 +67,7 @@ illustration we typically build snappy apps with hundreds or thousands of active
### How big is the angular.js file that I need to include?
The size of the file is < 36KB compressed and minified.
The size of the file is ~50KB compressed and minified.
### Can I use the open-source Closure Library with Angular?
+5 -5
View File
@@ -65,7 +65,7 @@ __`app/index.html`:__
## What is the code doing?
* `ng-app` directive:
**`ng-app` directive:**
<html ng-app>
@@ -77,17 +77,17 @@ __`app/index.html`:__
This gives application developers the freedom to tell Angular if the entire html page or only a
portion of it should be treated as the Angular application.
* AngularJS script tag:
**AngularJS script tag:**
<script src="bower_components/angular/angular.js">
This code downloads the `angular.js` script and registers a callback that will be executed by the
This code downloads the `angular.js` script which registers a callback that will be executed by the
browser when the containing HTML page is fully downloaded. When the callback is executed, Angular
looks for the {@link ng.directive:ngApp ngApp} directive. If
Angular finds the directive, it will bootstrap the application with the root of the application DOM
being the element on which the `ngApp` directive was defined.
* Double-curly binding with an expression:
**Double-curly binding with an expression:**
Nothing here {{'yet' + '!'}}
@@ -111,7 +111,7 @@ being the element on which the `ngApp` directive was defined.
## Bootstrapping AngularJS apps
Bootstrapping AngularJS apps automatically using the `ngApp` directive is very easy and suitable
for most cases. In advanced cases, such as when using script loaders, you can use
for most cases. In advanced cases, such as when using script loaders, you can use the
{@link guide/bootstrap imperative / manual way} to bootstrap the app.
There are 3 important things that happen during the app bootstrap:
+1 -1
View File
@@ -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');
});
});
+1 -1
View File
@@ -173,7 +173,7 @@ function request(method, url, options, response) {
res.on('error', function (e) { console.log(e); });
break;
case 401:
console.log('Eror: Login credentials expired! Please login.');
console.log('Error: Login credentials expired! Please login.');
break;
default:
data = [];
+2
View File
@@ -185,6 +185,8 @@ describe("extractDateTimeSymbols", function() {
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
AMPMS: ['AM', 'PM'],
ERAS: ['av. J.-C.', 'ap. J.-C.'],
ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
medium: 'yyyy-MM-dd HH:mm:ss',
short: 'yy-MM-dd HH:mm',
fullDate: 'EEEE d MMMM y',
+2
View File
@@ -42,6 +42,8 @@ function convertDatetimeData(dataObj) {
datetimeFormats.DAY = dataObj.WEEKDAYS;
datetimeFormats.SHORTDAY = dataObj.SHORTWEEKDAYS;
datetimeFormats.AMPMS = dataObj.AMPMS;
datetimeFormats.ERAS = dataObj.ERAS;
datetimeFormats.ERANAMES = dataObj.ERANAMES;
datetimeFormats.medium = dataObj.DATEFORMATS[2] + ' ' + dataObj.TIMEFORMATS[2];
+12
View File
@@ -66,6 +66,12 @@ module.exports = function(config, specificOptions) {
platform: 'Windows 8.1',
version: '11'
},
'SL_iOS': {
base: "SauceLabs",
browserName: "iphone",
platform: "OS X 10.10",
version: "8.1"
},
'BS_Chrome': {
base: 'BrowserStack',
@@ -105,6 +111,12 @@ module.exports = function(config, specificOptions) {
browser_version: '11.0',
os: 'Windows',
os_version: '8.1'
},
'BS_iOS': {
base: 'BrowserStack',
device: 'iPhone 6',
os: 'ios',
os_version: '8.0'
}
}
});
+8
View File
@@ -0,0 +1,8 @@
#!/bin/bash
set -e -o pipefail
echo "Shutting down Browserstack tunnel"
echo "TODO: implement me"
exit 1
+1 -8
View File
@@ -14,13 +14,6 @@ var CSP_CSS_HEADER = '/* Include this file in your html if you are using the CSP
module.exports = {
init: function() {
if (!process.env.TRAVIS) {
shell.exec('npm install');
}
},
startKarma: function(config, singleRun, done){
var browsers = grunt.option('browsers');
var reporters = grunt.option('reporters');
@@ -123,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() && window.angular.element(document.head).prepend('<style type=\"text/css\">" + css + "</style>');";
state.js.push(js);
return state;
+58
View File
@@ -0,0 +1,58 @@
'use strict';
var path = require('path');
var fs = require('fs');
var glob = require("glob");
var _ = require('lodash');
var files = require('../../angularFiles').files;
module.exports = function(grunt) {
grunt.registerTask('validate-angular-files', function() {
var combinedFiles = _.clone(files.angularModules);
combinedFiles.ng = files.angularSrc;
combinedFiles.angularLoader = files.angularLoader;
var errorsDetected = false;
var directories = [];
var detectedFiles = {};
for (var section in combinedFiles) {
var sectionFiles = combinedFiles[section];
if (section != 'angularLoader') {
directories.push('src/' + section);
}
grunt.log.debug('Validating ' + sectionFiles.length + ' files from the "' + section + '" module.');
sectionFiles.forEach(function(file) {
detectedFiles[file] = true;
if (!fs.existsSync(file)) {
grunt.log.error(file + ' does not exist in the local file structure.');
errorsDetected = true;
}
});
}
directories.forEach(function(directory) {
glob.sync(directory + '/**/*').forEach(function(filePath) {
if (!fs.lstatSync(filePath).isDirectory()) {
var fileName = path.basename(filePath);
var isHiddenFile = fileName[0] == '.';
if (!isHiddenFile && !detectedFiles[filePath]) {
grunt.log.error(filePath + ' exists in the local file structure but isn\'t used by any module.');
errorsDetected = true;
}
}
});
});
if (errorsDetected) {
throw new Error('Not all files were properly detected in the local file structure.');
} else {
grunt.log.ok('All files were detected successfully!');
}
});
};
+3 -3
View File
@@ -12,9 +12,9 @@ set -e
# before_script:
# - curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash
CONNECT_URL="https://saucelabs.com/downloads/sc-4.3-linux.tar.gz"
CONNECT_URL="https://saucelabs.com/downloads/sc-4.3.7-linux.tar.gz"
CONNECT_DIR="/tmp/sauce-connect-$RANDOM"
CONNECT_DOWNLOAD="sc-4.3-linux.tar.gz"
CONNECT_DOWNLOAD="sc-4.3.7-linux.tar.gz"
CONNECT_LOG="$LOGS_DIR/sauce-connect"
CONNECT_STDOUT="$LOGS_DIR/sauce-connect.stdout"
@@ -46,5 +46,5 @@ echo "Starting Sauce Connect in the background, logging into:"
echo " $CONNECT_LOG"
echo " $CONNECT_STDOUT"
echo " $CONNECT_STDERR"
sauce-connect/bin/sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY $ARGS -v \
sauce-connect/bin/sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY $ARGS \
--logfile $CONNECT_LOG 2> $CONNECT_STDERR 1> $CONNECT_STDOUT &
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
set -e -o pipefail
echo "Shutting down Sauce Connect tunnel"
killall sc
while [[ -n `ps -ef | grep "sauce-connect-" | grep -v "grep"` ]]; do
printf "."
sleep .5
done
echo ""
echo "Sauce Connect tunnel has been shut down"
File diff suppressed because it is too large Load Diff
+7247 -1552
View File
File diff suppressed because it is too large Load Diff
+13 -2
View File
@@ -1,10 +1,20 @@
{
"name": "angularjs",
"branchVersion": "1.3.*",
"distTag": "previous_1_3",
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
},
"engines": {
"node": "~0.10",
"npm": "~2.5"
},
"engineStrict": true,
"scripts": {
"preinstall": "node scripts/npm/check-node-modules.js --purge",
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js"
},
"devDependencies": {
"angular-benchpress": "0.x.x",
"benchmark": "1.x.x",
@@ -15,6 +25,7 @@
"dgeni": "^0.4.0",
"dgeni-packages": "^0.10.0",
"event-stream": "~3.1.0",
"glob": "^6.0.1",
"grunt": "~0.4.2",
"grunt-bump": "~0.0.13",
"grunt-contrib-clean": "~0.6.0",
@@ -38,7 +49,7 @@
"jasmine-node": "~1.14.5",
"jasmine-reporters": "~1.0.1",
"jshint-stylish": "~1.0.0",
"karma": "vojtajina/karma#socketio_10",
"karma": "0.12.32",
"karma-browserstack-launcher": "0.1.2",
"karma-chrome-launcher": "0.1.5",
"karma-firefox-launcher": "0.1.3",
@@ -52,7 +63,7 @@
"marked": "~0.3.0",
"node-html-encoder": "0.0.2",
"promises-aplus-tests": "~2.1.0",
"protractor": "^1.6.0",
"protractor": "^2.0.0",
"q": "~1.0.0",
"q-io": "^1.10.9",
"qq": "^0.3.5",
+19 -13
View File
@@ -29,6 +29,8 @@ function init {
angular-touch
angular-messages
)
# get the npm dist-tag from a custom property (distTag) in package.json
DIST_TAG=$(readJsonProp "package.json" "distTag")
}
@@ -63,6 +65,21 @@ function prepare {
cp $BUILD_DIR/angular-csp.css $TMP_DIR/bower-angular
#
# Run local precommit script if there is one
#
for repo in "${REPOS[@]}"
do
if [ -f $TMP_DIR/bower-$repo/precommit.sh ]
then
echo "-- Running precommit.sh script for bower-$repo"
cd $TMP_DIR/bower-$repo
$TMP_DIR/bower-$repo/precommit.sh
cd $SCRIPT_DIR
fi
done
#
# update bower.json
# tag each repo
@@ -95,19 +112,8 @@ 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
echo "-- Publishing to npm as $DIST_TAG"
npm publish --tag=$DIST_TAG
fi
cd $SCRIPT_DIR
@@ -7,6 +7,8 @@ echo "#################################"
# Enable tracing and exit on first failure
set -xe
scripts/jenkins/set-node-version.sh
# This is the default set of browsers to use on the CI server unless overridden via env variable
if [[ -z "$BROWSERS" ]]
then
@@ -19,6 +21,7 @@ rm -f angular.js.size
# BUILD #
npm install -g grunt-cli
npm install --color false
grunt ci-checks package --no-color
+2 -11
View File
@@ -4,9 +4,7 @@ echo "#################################"
echo "#### Update master ##############"
echo "#################################"
ARG_DEFS=(
"[--no-test=(true|false)]"
)
ARG_DEFS=()
function init {
if [[ ! $VERBOSE ]]; then
@@ -17,14 +15,7 @@ function init {
function build {
cd ../..
if [[ $NO_TEST == "true" ]]; then
npm install --color false
grunt ci-checks package --no-color
else
./jenkins_build.sh
fi
scripts/jenkins/build.sh
cd $SCRIPT_DIR
}
+2
View File
@@ -35,8 +35,10 @@ function init {
}
function build {
./set-node-version.sh
cd ../..
npm install -g grunt-cli
npm install --color false
grunt ci-checks package --no-color
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
# Install nvm for this shell
source ~/.nvm/nvm.sh
# Use node.js at 4.2.x
nvm install 4.2
+74
View File
@@ -0,0 +1,74 @@
// Implementation based on:
// https://github.com/angular/angular/blob/3b9c08676a4c921bbfa847802e08566fb601ba7a/tools/npm/check-node-modules.js
'use strict';
// Imports
var fs = require('fs');
var path = require('path');
// Constants
var PROJECT_ROOT = path.join(__dirname, '../../');
var NODE_MODULES_DIR = 'node_modules';
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
// Run
_main();
// Functions - Definitions
function _main() {
var purgeIfStale = process.argv.indexOf('--purge') !== -1;
process.chdir(PROJECT_ROOT);
checkNodeModules(purgeIfStale);
}
function checkNodeModules(purgeIfStale) {
var nodeModulesOk = compareMarkerFiles(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE);
if (nodeModulesOk) {
console.log(':-) npm dependencies are looking good!');
} else if (purgeIfStale) {
console.log(':-( npm dependencies are stale or in an unknown state!');
console.log(' Purging \'' + NODE_MODULES_DIR + '\'...');
deleteDirSync(NODE_MODULES_DIR);
} else {
var separator = new Array(81).join('!');
console.warn(separator);
console.warn(':-( npm dependencies are stale or in an unknown state!');
console.warn('You can rebuild the dependencies by running `npm install`.');
console.warn(separator);
}
return nodeModulesOk;
}
function compareMarkerFiles(markerFilePath, cachedMarkerFilePath) {
if (!fs.existsSync(cachedMarkerFilePath)) return false;
var opts = {encoding: 'utf-8'};
var markerContent = fs.readFileSync(markerFilePath, opts);
var cachedMarkerContent = fs.readFileSync(cachedMarkerFilePath, opts);
return markerContent === cachedMarkerContent;
}
// Custom implementation of `rm -rf` that works consistently across OSes
function deleteDirSync(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach(deleteDirOrFileSync);
fs.rmdirSync(path);
}
// Helpers
function deleteDirOrFileSync(subpath) {
var curPath = path + '/' + subpath;
if (fs.lstatSync(curPath).isDirectory()) {
deleteDirSync(curPath);
} else {
fs.unlinkSync(curPath);
}
}
}
@@ -10,22 +10,17 @@
var _ = require('lodash');
var sorted = require('sorted-object');
var fs = require('fs');
var path = require('path');
function cleanModule(module, name) {
// keep `from` and `resolve` properties for git dependencies, delete otherwise
if (!(module.resolved && module.resolved.match(/^git:\/\//))) {
delete module.from;
// keep `resolve` properties for git dependencies, delete otherwise
delete module.from;
if (!(module.resolved && module.resolved.match(/^git(\+[a-z]+)?:\/\//))) {
delete module.resolved;
}
if (name === 'chokidar') {
if (module.version === '0.8.1') {
delete module.dependencies;
}
}
_.forEach(module.dependencies, function(mod, name) {
cleanModule(mod, name);
});
@@ -33,10 +28,11 @@ function cleanModule(module, name) {
console.log('Reading npm-shrinkwrap.json');
var shrinkwrap = require('./../npm-shrinkwrap.json');
var shrinkwrap = require('../../npm-shrinkwrap.json');
console.log('Cleaning shrinkwrap object');
cleanModule(shrinkwrap, shrinkwrap.name);
console.log('Writing cleaned npm-shrinkwrap.json');
fs.writeFileSync('./npm-shrinkwrap.json', JSON.stringify(sorted(shrinkwrap), null, 2) + "\n");
var cleanShrinkwrapPath = path.join(__dirname, '..', '..', 'npm-shrinkwrap.clean.json');
console.log('Writing cleaned to', cleanShrinkwrapPath);
fs.writeFileSync(cleanShrinkwrapPath, JSON.stringify(sorted(shrinkwrap), null, 2) + "\n");
+60
View File
@@ -0,0 +1,60 @@
'use strict';
// Imports
var fs = require('fs');
var path = require('path');
// Constants
var PROJECT_ROOT = path.join(__dirname, '../../');
var NODE_MODULES_DIR = 'node_modules';
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
// Run
_main();
// Functions - Definitions
function _main() {
process.chdir(PROJECT_ROOT);
copyFile(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE, onCopied);
}
// Implementation based on:
// https://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js#answer-21995878
function copyFile(srcPath, dstPath, callback) {
var callbackCalled = false;
if (!fs.existsSync(srcPath)) {
done(new Error('Missing source file: ' + srcPath));
return;
}
var rs = fs.createReadStream(srcPath);
rs.on('error', done);
var ws = fs.createWriteStream(dstPath);
ws.on('error', done);
ws.on('finish', done);
rs.pipe(ws);
// Helpers
function done(err) {
if (callback && !callbackCalled) {
callbackCalled = true;
callback(err);
}
}
}
function onCopied(err) {
if (err) {
var separator = new Array(81).join('!');
console.error(separator);
console.error(
'Failed to copy `' + NPM_SHRINKWRAP_FILE + '` to `' + NPM_SHRINKWRAP_CACHED_FILE + '`:');
console.error(err);
console.error(separator);
}
}
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
set -e
mkdir -p $LOGS_DIR
if [ $JOB != "ci-checks" ]; then
echo "start_browser_provider"
./scripts/travis/start_browser_provider.sh
fi
npm install -g grunt-cli
if [ $JOB != "ci-checks" ]; then
grunt package
echo "wait_for_browser_provider"
./scripts/travis/wait_for_browser_provider.sh
fi
+6 -5
View File
@@ -5,16 +5,17 @@ set -e
export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev`
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
if [ $JOB = "unit" ]; then
if [ $JOB = "ci-checks" ]; then
grunt ci-checks
elif [ $JOB = "unit" ]; then
if [ "$BROWSER_PROVIDER" == "browserstack" ]; then
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11"
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS"
else
BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11"
BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11,SL_iOS"
fi
grunt test:promises-aplus
grunt test:unit --browsers $BROWSERS --reporters dots
grunt ci-checks
grunt tests:docs --browsers $BROWSERS --reporters dots
elif [ $JOB = "docs-e2e" ]; then
grunt test:travis-protractor --specs "docs/app/e2e/**/*.scenario.js"
@@ -31,5 +32,5 @@ elif [ $JOB = "e2e" ]; then
export TARGET_SPECS="test/e2e/tests/**/*.js,$TARGET_SPECS"
grunt test:travis-protractor --specs "$TARGET_SPECS"
else
echo "Unknown job type. Please set JOB=unit or JOB=e2e-*."
echo "Unknown job type. Please set JOB=ci-checks, JOB=unit or JOB=e2e-*."
fi
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
# Has to be run from project root directory.
./lib/${BROWSER_PROVIDER}/teardown_tunnel.sh
@@ -2,6 +2,18 @@
# Wait for Connect to be ready before exiting
# Time out if we wait for more than 2 minutes, so that we can print logs.
let "counter=0"
while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do
let "counter++"
if [ $counter -gt 240 ]; then
echo "Timed out after 2 minutes waiting for browser provider ready file"
# We must manually print logs here because travis will not run
# after_script commands if the failure occurs before the script
# phase.
./scripts/travis/print_logs.sh
exit 5
fi
sleep .5
done
+1
View File
@@ -94,6 +94,7 @@
"skipDestroyOnNextJQueryCleanData": true,
"NODE_TYPE_ELEMENT": false,
"NODE_TYPE_ATTRIBUTE": false,
"NODE_TYPE_TEXT": false,
"NODE_TYPE_COMMENT": false,
"NODE_TYPE_COMMENT": false,
+128 -65
View File
@@ -36,6 +36,7 @@
isUndefined: true,
isDefined: true,
isObject: true,
isBlankObject: true,
isString: true,
isNumber: true,
isDate: true,
@@ -85,6 +86,7 @@
createMap: true,
NODE_TYPE_ELEMENT: true,
NODE_TYPE_ATTRIBUTE: true,
NODE_TYPE_TEXT: true,
NODE_TYPE_COMMENT: true,
NODE_TYPE_DOCUMENT: true,
@@ -171,6 +173,7 @@ var
splice = [].splice,
push = [].push,
toString = Object.prototype.toString,
getPrototypeOf = Object.getPrototypeOf,
ngMinErr = minErr('ng'),
/** @name angular */
@@ -196,7 +199,9 @@ function isArrayLike(obj) {
return false;
}
var length = obj.length;
// Support: iOS 8.2 (not reproducible in simulator)
// "length" in obj used to prevent JIT error (gh-11508)
var length = "length" in Object(obj) && obj.length;
if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
return true;
@@ -458,6 +463,16 @@ function isObject(value) {
}
/**
* Determine if a value is an object with a null prototype
*
* @returns {boolean} True if `value` is an `Object` with a null prototype
*/
function isBlankObject(value) {
return value !== null && typeof value === 'object' && !getPrototypeOf(value);
}
/**
* @ngdoc function
* @name angular.isString
@@ -482,6 +497,12 @@ function isString(value) {return typeof value === 'string';}
* @description
* Determines if a reference is a `Number`.
*
* This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
*
* If you wish to exclude these then you can use the native
* [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
* method.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Number`.
*/
@@ -588,6 +609,12 @@ function isPromiseLike(obj) {
}
var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
function isTypedArray(value) {
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
}
var trim = function(value) {
return isString(value) ? value.trim() : value;
};
@@ -704,77 +731,111 @@ function arrayRemove(array, value) {
</file>
</example>
*/
function copy(source, destination, stackSource, stackDest) {
if (isWindow(source) || isScope(source)) {
throw ngMinErr('cpws',
"Can't copy! Making copies of Window or Scope instances is not supported.");
function copy(source, destination) {
var stackSource = [];
var stackDest = [];
if (destination) {
if (isTypedArray(destination)) {
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
}
if (source === destination) {
throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
}
// Empty the destination object
if (isArray(destination)) {
destination.length = 0;
} else {
forEach(destination, function(value, key) {
if (key !== '$$hashKey') {
delete destination[key];
}
});
}
stackSource.push(source);
stackDest.push(destination);
return copyRecurse(source, destination);
}
if (!destination) {
destination = source;
if (source) {
if (isArray(source)) {
destination = copy(source, [], stackSource, stackDest);
} else if (isDate(source)) {
destination = new Date(source.getTime());
} else if (isRegExp(source)) {
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
destination.lastIndex = source.lastIndex;
} else if (isObject(source)) {
var emptyObject = Object.create(Object.getPrototypeOf(source));
destination = copy(source, emptyObject, stackSource, stackDest);
}
}
} else {
if (source === destination) throw ngMinErr('cpi',
"Can't copy! Source and destination are identical.");
return copyElement(source);
stackSource = stackSource || [];
stackDest = stackDest || [];
if (isObject(source)) {
var index = stackSource.indexOf(source);
if (index !== -1) return stackDest[index];
stackSource.push(source);
stackDest.push(destination);
}
var result;
function copyRecurse(source, destination) {
var h = destination.$$hashKey;
var result, key;
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);
for (var i = 0, ii = source.length; i < ii; i++) {
destination.push(copyElement(source[i]));
}
} else if (isBlankObject(source)) {
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
for (key in source) {
destination[key] = copyElement(source[key]);
}
} else if (source && typeof source.hasOwnProperty === 'function') {
// Slow path, which must rely on hasOwnProperty
for (key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = copyElement(source[key]);
}
destination.push(result);
}
} else {
var h = destination.$$hashKey;
if (isArray(destination)) {
destination.length = 0;
} else {
forEach(destination, function(value, key) {
delete destination[key];
});
}
for (var key in source) {
if (source.hasOwnProperty(key)) {
result = copy(source[key], null, stackSource, stackDest);
if (isObject(source[key])) {
stackSource.push(source[key]);
stackDest.push(result);
}
destination[key] = result;
// Slowest path --- hasOwnProperty can't be called as a method
for (key in source) {
if (hasOwnProperty.call(source, key)) {
destination[key] = copyElement(source[key]);
}
}
setHashKey(destination,h);
}
setHashKey(destination, h);
return destination;
}
function copyElement(source) {
// Simple values
if (!isObject(source)) {
return source;
}
// Already copied values
var index = stackSource.indexOf(source);
if (index !== -1) {
return stackDest[index];
}
if (isWindow(source) || isScope(source)) {
throw ngMinErr('cpws',
"Can't copy! Making copies of Window or Scope instances is not supported.");
}
var needsRecurse = false;
var destination;
if (isArray(source)) {
destination = [];
needsRecurse = true;
} else if (isTypedArray(source)) {
destination = new source.constructor(source);
} else if (isDate(source)) {
destination = new Date(source.getTime());
} else if (isRegExp(source)) {
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
destination.lastIndex = source.lastIndex;
} else if (isFunction(source.cloneNode)) {
destination = source.cloneNode(true);
} else {
destination = Object.create(getPrototypeOf(source));
needsRecurse = true;
}
stackSource.push(source);
stackDest.push(destination);
return needsRecurse
? copyRecurse(source, destination)
: destination;
}
return destination;
}
/**
@@ -850,10 +911,11 @@ function equals(o1, o2) {
} else if (isDate(o1)) {
if (!isDate(o2)) return false;
return equals(o1.getTime(), o2.getTime());
} else if (isRegExp(o1) && isRegExp(o2)) {
return o1.toString() == o2.toString();
} else if (isRegExp(o1)) {
return isRegExp(o2) ? o1.toString() == o2.toString() : false;
} else {
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
keySet = {};
for (key in o1) {
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
@@ -971,8 +1033,8 @@ function toJsonReplacer(key, value) {
* stripped since angular uses this notation internally.
*
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
* @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
* If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
* @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
* If set to an integer, the JSON output will contain that many spaces per indentation.
* @returns {string|undefined} JSON-ified string representing `obj`.
*/
function toJson(obj, pretty) {
@@ -1604,6 +1666,7 @@ function createMap() {
}
var NODE_TYPE_ELEMENT = 1;
var NODE_TYPE_ATTRIBUTE = 2;
var NODE_TYPE_TEXT = 3;
var NODE_TYPE_COMMENT = 8;
var NODE_TYPE_DOCUMENT = 9;
+8 -7
View File
@@ -179,7 +179,7 @@ function annotate(fn, strictDi, name) {
* Return an instance of the service.
*
* @param {string} name The name of the instance to retrieve.
* @param {string} caller An optional string to provide the origin of the function call for error messages.
* @param {string=} caller An optional string to provide the origin of the function call for error messages.
* @return {*} The instance.
*/
@@ -190,8 +190,8 @@ function annotate(fn, strictDi, name) {
* @description
* Invoke the method and supply the method arguments from the `$injector`.
*
* @param {!Function} fn The function to invoke. Function parameters are injected according to the
* {@link guide/di $inject Annotation} rules.
* @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
* injected according to the {@link guide/di $inject Annotation} rules.
* @param {Object=} self The `this` for the invoked method.
* @param {Object=} locals Optional object. If preset then any argument names are read from this
* object first, before the `$injector` is consulted.
@@ -458,8 +458,8 @@ function annotate(fn, strictDi, name) {
* configure your service in a provider.
*
* @param {string} name The name of the instance.
* @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
* for `$provide.provider(name, {$get: $getFn})`.
* @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
* Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
* @returns {Object} registered provider instance
*
* @example
@@ -494,7 +494,8 @@ function annotate(fn, strictDi, name) {
* as a type/class.
*
* @param {string} name The name of the instance.
* @param {Function} constructor A class (constructor function) that will be instantiated.
* @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
* that will be instantiated.
* @returns {Object} registered provider instance
*
* @example
@@ -593,7 +594,7 @@ function annotate(fn, strictDi, name) {
* object which replaces or wraps and delegates to the original service.
*
* @param {string} name The name of the service to decorate.
* @param {function()} decorator This function will be invoked when the service needs to be
* @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
* instantiated and should return the decorated service instance. The function is called using
* the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
* Local injection arguments:
+17 -2
View File
@@ -1,5 +1,16 @@
'use strict';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Any commits to this file should be reviewed with security in mind. *
* Changes to this file can potentially create security vulnerabilities. *
* An approval from 2 Core members with history of modifying *
* this file is required. *
* *
* Does the change somehow allow for arbitrary javascript to be executed? *
* Or allows for someone to change the prototype of built-in objects? *
* Or gives undesired access to variables likes document or window? *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* global JQLitePrototype: true,
addEventListenerFn: true,
removeEventListenerFn: true,
@@ -28,7 +39,7 @@
* Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
* commonly needed functionality with the goal of having a very small footprint.</div>
*
* To use jQuery, simply load it before `DOMContentLoaded` event fired.
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
*
* <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
* jqLite; they are never raw DOM references.</div>
@@ -44,7 +55,7 @@
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
* - [`clone()`](http://api.jquery.com/clone/)
* - [`contents()`](http://api.jquery.com/contents/)
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
* - [`data()`](http://api.jquery.com/data/)
* - [`detach()`](http://api.jquery.com/detach/)
* - [`empty()`](http://api.jquery.com/empty/)
@@ -587,6 +598,10 @@ forEach({
},
attr: function(element, name, value) {
var nodeType = element.nodeType;
if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
return;
}
var lowercasedName = lowercase(name);
if (BOOLEAN_ATTR[lowercasedName]) {
if (isDefined(value)) {
+8 -1
View File
@@ -231,10 +231,17 @@ function setupModuleLoader(window) {
* @ngdoc method
* @name angular.Module#filter
* @module ng
* @param {string} name Filter name.
* @param {string} name Filter name - this must be a valid angular expression identifier
* @param {Function} filterFactory Factory function for creating new instance of filter.
* @description
* See {@link ng.$filterProvider#register $filterProvider.register()}.
*
* <div class="alert alert-warning">
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
* (`myapp_subsection_filterx`).
* </div>
*/
filter: invokeLater('$filterProvider', 'register'),
+1
View File
@@ -210,6 +210,7 @@ var $AnimateProvider = ['$provide', function($provide) {
* @return {Promise} the animation callback promise
*/
leave: function(element, options) {
applyStyles(element, options);
element.remove();
return asyncPromise();
},
+11 -3
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);
}
/**
@@ -190,7 +190,7 @@ function Browser(window, document, $log, $sniffer) {
// Do the assignment again so that those two variables are referentially identical.
lastHistoryState = cachedState;
} else {
if (!sameBase) {
if (!sameBase || reloadLocation) {
reloadLocation = url;
}
if (replace) {
@@ -233,11 +233,19 @@ function Browser(window, document, $log, $sniffer) {
fireUrlChange();
}
function getCurrentState() {
try {
return history.state;
} catch (e) {
// MSIE can reportedly throw when there is no state (UNCONFIRMED).
}
}
// This variable should be used *only* inside the cacheState function.
var lastCachedState = null;
function cacheState() {
// This should be the only place in $browser where `history.state` is read.
cachedState = window.history.state;
cachedState = getCurrentState();
cachedState = isUndefined(cachedState) ? null : cachedState;
// Prevent callbacks fo fire twice if both hashchange & popstate were fired.
+1 -1
View File
@@ -372,7 +372,7 @@ function $CacheFactoryProvider() {
* the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
* element with ng-app attribute), otherwise the template will be ignored.
*
* Adding via the $templateCache service:
* Adding via the `$templateCache` service:
*
* ```js
* var myApp = angular.module('myApp', []);
+26 -7
View File
@@ -1,5 +1,16 @@
'use strict';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Any commits to this file should be reviewed with security in mind. *
* Changes to this file can potentially create security vulnerabilities. *
* An approval from 2 Core members with history of modifying *
* this file is required. *
* *
* Does the change somehow allow for arbitrary javascript to be executed? *
* Or allows for someone to change the prototype of built-in objects? *
* Or gives undesired access to variables likes document or window? *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
*
* DOM-related variables:
@@ -64,7 +75,8 @@
* templateNamespace: 'html',
* scope: false,
* controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
* controllerAs: 'stringAlias',
* controllerAs: 'stringIdentifier',
* bindToController: false,
* require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
* compile: function compile(tElement, tAttrs, transclude) {
* return {
@@ -211,7 +223,8 @@
* Require another directive and inject its controller as the fourth argument to the linking function. The
* `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
* injected argument will be an array in corresponding order. If no such directive can be
* found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:
* found, or if the directive does not have a controller, then an error is raised (unless no link function
* is specified, in which case error checking is skipped). The name can be prefixed with:
*
* * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
* * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
@@ -382,9 +395,15 @@
* * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
* between all directive linking functions.
*
* * `controller` - a controller instance - A controller instance if at least one directive on the
* element defines a controller. The controller is shared among all the directives, which allows
* the directives to use the controllers as a communication channel.
* * `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:
* * `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.
*
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
* This is the same as the `$transclude`
@@ -410,7 +429,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.
*
@@ -2165,7 +2184,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$compileNode.empty();
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
$templateRequest(templateUrl)
.then(function(content) {
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
+13 -9
View File
@@ -159,20 +159,24 @@
*
* @description
*
* We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
* This directive sets the `disabled` attribute on the element if the
* {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
*
* A special directive is necessary because we cannot use interpolation inside the `disabled`
* attribute. The following example would make the button enabled on Chrome/Firefox
* but not on older IEs:
*
* ```html
* <div ng-init="scope = { isDisabled: false }">
* <button disabled="{{scope.isDisabled}}">Disabled</button>
* <!-- See below for an example of ng-disabled being used correctly -->
* <div ng-init="isDisabled = false">
* <button disabled="{{isDisabled}}">Disabled</button>
* </div>
* ```
*
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as disabled. (Their presence means true and their absence means false.)
* This is because the HTML specification does not require browsers to preserve the values of
* boolean attributes such as `disabled` (Their presence means true and their absence means false.)
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngDisabled` directive solves this problem for the `disabled` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
*
* @example
<example>
@@ -191,7 +195,7 @@
*
* @element INPUT
* @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
* then special attribute "disabled" will be set on the element
* then the `disabled` attribute will be set on the element
*/
+22 -26
View File
@@ -316,15 +316,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
*
* # Alias: {@link ng.directive:ngForm `ngForm`}
*
* In Angular forms can be nested. This means that the outer form is valid when all of the child
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
* `<form>` but can be nested. This allows you to have nested forms, which is very useful when
* using Angular validation directives in forms that are dynamically generated using the
* {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
* attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
* `ngForm` directive and nest these in an outer `form` element.
*
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
* `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
* of controls needs to be determined.
*
* # CSS classes
* - `ng-valid` is set if the form is valid.
@@ -415,11 +411,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
<form name="myForm" ng-controller="FormController" class="my-form">
userType: <input name="input" ng-model="userType" required>
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
<tt>userType = {{userType}}</tt><br>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
<code>userType = {{userType}}</code><br>
<code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
<code>myForm.input.$error = {{myForm.input.$error}}</code><br>
<code>myForm.$valid = {{myForm.$valid}}</code><br>
<code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
</form>
</file>
<file name="protractor.js" type="protractor">
@@ -454,10 +450,12 @@ var formDirectiveFactory = function(isNgForm) {
name: 'form',
restrict: isNgForm ? 'EAC' : 'E',
controller: FormController,
compile: function ngFormCompile(formElement) {
compile: function ngFormCompile(formElement, attr) {
// Setup initial state of the control
formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
return {
pre: function ngFormPreLink(scope, formElement, attr, controller) {
// if `action` attr is not present on the form, prevent the default action (submission)
@@ -488,23 +486,21 @@ var formDirectiveFactory = function(isNgForm) {
});
}
var parentFormCtrl = controller.$$parentForm,
alias = controller.$name;
var parentFormCtrl = controller.$$parentForm;
if (alias) {
setter(scope, null, alias, controller, alias);
attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {
if (alias === newValue) return;
setter(scope, null, alias, undefined, alias);
alias = newValue;
setter(scope, null, alias, controller, alias);
parentFormCtrl.$$renameControl(controller, alias);
if (nameAttr) {
setter(scope, null, controller.$name, controller, controller.$name);
attr.$observe(nameAttr, function(newValue) {
if (controller.$name === newValue) return;
setter(scope, null, controller.$name, undefined, controller.$name);
parentFormCtrl.$$renameControl(controller, newValue);
setter(scope, null, controller.$name, controller, controller.$name);
});
}
formElement.on('$destroy', function() {
parentFormCtrl.$removeControl(controller);
if (alias) {
setter(scope, null, alias, undefined, alias);
if (nameAttr) {
setter(scope, null, attr[nameAttr], undefined, controller.$name);
}
extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
});
+20 -13
View File
@@ -6,7 +6,7 @@
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
@@ -587,7 +587,11 @@ var inputType = {
* Text input with number validation and transformation. Sets the `number` validation
* error if not a valid number.
*
* The model must always be a number, otherwise Angular will throw an error.
* <div class="alert alert-warning">
* The model must always be of type `number` otherwise Angular will throw an error.
* Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
* error docs for more information and an example of how to convert your model if necessary.
* </div>
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
@@ -1166,7 +1170,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;
@@ -1243,14 +1247,14 @@ 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();
}
return value;
});
if (attr.min || attr.ngMin) {
if (isDefined(attr.min) || attr.ngMin) {
var minVal;
ctrl.$validators.min = function(value) {
return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
@@ -1266,7 +1270,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
});
}
if (attr.max || attr.ngMax) {
if (isDefined(attr.max) || attr.ngMax) {
var maxVal;
ctrl.$validators.max = function(value) {
return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
@@ -1336,7 +1340,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);
@@ -1531,13 +1535,16 @@ var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
return {
restrict: 'E',
require: ['?ngModel'],
link: {
pre: function(scope, element, attr, ctrls) {
if (ctrls[0]) {
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
$browser, $filter, $parse);
compile: function(tElement, tAttr) {
if (lowercase(tAttr.type) === 'hidden') tAttr.$set('autocomplete', 'off');
return {
pre: function(scope, element, attr, ctrls) {
if (ctrls[0]) {
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
$browser, $filter, $parse);
}
}
}
};
}
};
}];
+1 -5
View File
@@ -33,17 +33,13 @@
* document; alternatively, the css rule above must be included in the external stylesheet of the
* application.
*
* Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
* cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
* class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
*
* @element ANY
*
* @example
<example>
<file name="index.html">
<div id="template1" ng-cloak>{{ 'hello' }}</div>
<div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
<div id="template2" class="ng-cloak">{{ 'world' }}</div>
</file>
<file name="protractor.js" type="protractor">
it('should remove the template directive and css class', function() {
+3 -3
View File
@@ -178,8 +178,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 +215,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();
+34 -28
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
@@ -129,8 +128,8 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`.
* data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
* collaborate together to achieve the desired result.
*
* Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
* contents be edited in place by the user. This will not work on older browsers.
* `contenteditable` is an HTML5 attribute, which tells the browser to let the element
* contents be edited in place by the user.
*
* We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
* module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
@@ -244,6 +243,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
ngModelGet = parsedNgModel,
ngModelSet = parsedNgModelAssign,
pendingDebounce = null,
parserValid,
ctrl = this;
this.$$setOptions = function(options) {
@@ -267,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));
}
};
@@ -501,7 +501,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* If the validity changes to invalid, the model will be set to `undefined`,
* unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
* If the validity changes to valid, it will set the model to the last available valid
* modelValue, i.e. either the last parsed value or the last value set from the scope.
* `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
*/
this.$validate = function() {
// ignore $validate before model is initialized
@@ -516,16 +516,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
// the model although neither viewValue nor the model on the scope changed
var modelValue = ctrl.$$rawModelValue;
// Check if the there's a parse error, so we don't unset it accidentially
var parserName = ctrl.$$parserName || 'parse';
var parserValid = ctrl.$error[parserName] ? false : undefined;
var prevValid = ctrl.$valid;
var prevModelValue = ctrl.$modelValue;
var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
// If there was no change in validity, don't update the model
// This prevents changing an invalid modelValue to undefined
if (!allowInvalid && prevValid !== allValid) {
@@ -543,12 +539,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
};
this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {
this.$$runValidators = function(modelValue, viewValue, doneCallback) {
currentValidationRunId++;
var localValidationRunId = currentValidationRunId;
// check parser error
if (!processParseErrors(parseValid)) {
if (!processParseErrors()) {
validationDone(false);
return;
}
@@ -558,21 +554,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
}
processAsyncValidators();
function processParseErrors(parseValid) {
function processParseErrors() {
var errorKey = ctrl.$$parserName || 'parse';
if (parseValid === undefined) {
if (parserValid === undefined) {
setValidity(errorKey, null);
} else {
setValidity(errorKey, parseValid);
if (!parseValid) {
if (!parserValid) {
forEach(ctrl.$validators, function(v, name) {
setValidity(name, null);
});
forEach(ctrl.$asyncValidators, function(v, name) {
setValidity(name, null);
});
return false;
}
// Set the parse error last, to prevent unsetting it, should a $validators key == parserName
setValidity(errorKey, parserValid);
return parserValid;
}
return true;
}
@@ -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('nopromise',
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
}
setValidity(name, undefined);
@@ -667,7 +664,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
this.$$parseAndValidate = function() {
var viewValue = ctrl.$$lastCommittedViewValue;
var modelValue = viewValue;
var parserValid = isUndefined(modelValue) ? undefined : true;
parserValid = isUndefined(modelValue) ? undefined : true;
if (parserValid) {
for (var i = 0; i < ctrl.$parsers.length; i++) {
@@ -693,7 +690,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
// Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
// This can happen if e.g. $setViewValue is called from inside a parser
ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
if (!allowInvalid) {
// Note: Don't check ctrl.$valid here, as we could have
// external validators (e.g. calculated on the server),
@@ -812,8 +809,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
// if scope model value and ngModel value are out of sync
// TODO(perf): why not move this to the action fn?
if (modelValue !== ctrl.$modelValue) {
if (modelValue !== ctrl.$modelValue &&
// checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
(ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
) {
ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
parserValid = undefined;
var formatters = ctrl.$formatters,
idx = formatters.length;
@@ -826,7 +827,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
ctrl.$render();
ctrl.$$runValidators(undefined, modelValue, viewValue, noop);
ctrl.$$runValidators(modelValue, viewValue, noop);
}
}
@@ -988,10 +989,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
var _name = 'Brian';
$scope.user = {
name: function(newName) {
if (angular.isDefined(newName)) {
_name = newName;
}
return _name;
// Note that newName can be undefined for two reasons:
// 1. Because it is called as a getter and thus called with no arguments
// 2. Because the property should actually be set to undefined. This happens e.g. if the
// input is invalid
return arguments.length ? (_name = newName) : _name;
}
};
}]);
@@ -1203,7 +1205,11 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
var _name = 'Brian';
$scope.user = {
name: function(newName) {
return angular.isDefined(newName) ? (_name = newName) : _name;
// Note that newName can be undefined for two reasons:
// 1. Because it is called as a getter and thus called with no arguments
// 2. Because the property should actually be set to undefined. This happens e.g. if the
// input is invalid
return arguments.length ? (_name = newName) : _name;
}
};
}]);
+55 -6
View File
@@ -46,6 +46,55 @@
* when keys are deleted and reinstated.
*
*
* # Tracking and Duplicates
*
* When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
*
* * When an item is added, a new instance of the template is added to the DOM.
* * When an item is removed, its template instance is removed from the DOM.
* * When items are reordered, their respective templates are reordered in the DOM.
*
* By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
* there are duplicates, it is not possible to maintain a one-to-one mapping between collection
* items and DOM elements.
*
* If you do need to repeat duplicate items, you can substitute the default tracking behavior
* with your own using the `track by` expression.
*
* For example, you may track items by the index of each item in the collection, using the
* special scope property `$index`:
* ```html
* <div ng-repeat="n in [42, 42, 43, 43] track by $index">
* {{n}}
* </div>
* ```
*
* You may use arbitrary expressions in `track by`, including references to custom functions
* on the scope:
* ```html
* <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
* {{n}}
* </div>
* ```
*
* If you are working with objects that have an identifier property, you can track
* by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
* will not have to rebuild the DOM elements for items it has already rendered, even if the
* JavaScript objects in the collection have been substituted for new ones:
* ```html
* <div ng-repeat="model in collection track by model.id">
* {{model.name}}
* </div>
* ```
*
* When no `track by` expression is provided, it is equivalent to tracking by the built-in
* `$id` function, which tracks items by their identity:
* ```html
* <div ng-repeat="obj in collection track by $id(obj)">
* {{obj.prop}}
* </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.
@@ -113,12 +162,12 @@
*
* For example: `(name, age) in {'adam':10, 'amalie':12}`.
*
* * `variable in expression track by tracking_expression` You can also provide an optional tracking function
* which can be used to associate the objects in the collection with the DOM elements. If no tracking function
* is specified the ng-repeat associates elements by identity in the collection. It is an error to have
* more than one tracking function to resolve to the same key. (This would mean that two distinct objects are
* mapped to the same DOM element, which is not possible.) Filters should be applied to the expression,
* before specifying a tracking expression.
* * `variable in expression track by tracking_expression` You can also provide an optional tracking expression
* 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.
*
* 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.
+2 -2
View File
@@ -47,10 +47,10 @@
</example>
*/
var ngStyleDirective = ngDirective(function(scope, element, attr) {
scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) { element.css(style, '');});
}
if (newStyles) element.css(newStyles);
});
}, true);
});
+2 -2
View File
@@ -43,7 +43,7 @@
*
* @scope
* @priority 1200
* @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
* @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
* On child elements add:
*
* * `ngSwitchWhen`: the case statement to match against. If match then this
@@ -60,7 +60,7 @@
<div ng-controller="ExampleController">
<select ng-model="selection" ng-options="item for item in items">
</select>
<tt>selection={{selection}}</tt>
<code>selection={{selection}}</code>
<hr/>
<div class="animate-switch-container"
ng-switch on="selection">
+1 -1
View File
@@ -316,7 +316,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
selectElement.val(viewValue);
if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
} else {
if (isUndefined(viewValue) && emptyOption) {
if (viewValue == null && emptyOption) {
selectElement.val('');
} else {
selectCtrl.renderUnknownOption(viewValue);
+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);
};
}
};
+14
View File
@@ -20,6 +20,13 @@
* Dependency Injected. To achieve this a filter definition consists of a factory function which is
* annotated with dependencies and is responsible for creating a filter function.
*
* <div class="alert alert-warning">
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
* (`myapp_subsection_filterx`).
* </div>
*
* ```js
* // Filter registration
* function MyModule($provide, $filterProvider) {
@@ -101,6 +108,13 @@ function $FilterProvider($provide) {
* @name $filterProvider#register
* @param {string|Object} name Name of the filter function, or an object map of filters where
* the keys are the filter names and the values are the filter factories.
*
* <div class="alert alert-warning">
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
* (`myapp_subsection_filterx`).
* </div>
* @returns {Object} Registered filter instance, or if a map of filters was provided then a map
* of the registered filter instances.
*/
+14 -4
View File
@@ -126,14 +126,16 @@ function filterFilter() {
return function(array, expression, comparator) {
if (!isArray(array)) return array;
var expressionType = (expression !== null) ? typeof expression : 'null';
var predicateFn;
var matchAgainstAnyProp;
switch (typeof expression) {
switch (expressionType) {
case 'function':
predicateFn = expression;
break;
case 'boolean':
case 'null':
case 'number':
case 'string':
matchAgainstAnyProp = true;
@@ -159,6 +161,14 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
comparator = equals;
} else if (!isFunction(comparator)) {
comparator = function(actual, expected) {
if (isUndefined(actual)) {
// No substring matching against `undefined`
return false;
}
if ((actual === null) || (expected === null)) {
// No substring matching against `null`; only match against `null`
return actual === expected;
}
if (isObject(actual) || isObject(expected)) {
// Prevent an object to be considered equal to a string like `'[object'`
return false;
@@ -181,8 +191,8 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
}
function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
var actualType = typeof actual;
var expectedType = typeof expected;
var actualType = (actual !== null) ? typeof actual : 'null';
var expectedType = (expected !== null) ? typeof expected : 'null';
if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
@@ -207,7 +217,7 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc
} else if (expectedType === 'object') {
for (key in expected) {
var expectedVal = expected[key];
if (isFunction(expectedVal)) {
if (isFunction(expectedVal) || isUndefined(expectedVal)) {
continue;
}
+18 -2
View File
@@ -80,6 +80,8 @@ 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.
*
* @param {number|string} number Number to format.
@@ -292,6 +294,14 @@ function ampmGetter(date, formats) {
return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
}
function eraGetter(date, formats) {
return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
}
function longEraGetter(date, formats) {
return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
}
var DATE_FORMATS = {
yyyy: dateGetter('FullYear', 4),
yy: dateGetter('FullYear', 2, 0, true),
@@ -318,10 +328,14 @@ var DATE_FORMATS = {
a: ampmGetter,
Z: timeZoneGetter,
ww: weekGetter(2),
w: weekGetter(1)
w: weekGetter(1),
G: eraGetter,
GG: eraGetter,
GGG: eraGetter,
GGGG: longEraGetter
};
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
NUMBER_STRING = /^\-?\d+$/;
/**
@@ -358,6 +372,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
* * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
* * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
* * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
* * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
*
* `format` string can also be one of the following predefined
* {@link guide/i18n localizable formats}:
+38 -1
View File
@@ -17,7 +17,7 @@
* Can be one of:
*
* - `function`: Getter function. The result of this function will be sorted using the
* `<`, `=`, `>` operator.
* `<`, `===`, `>` operator.
* - `string`: An Angular expression. The result of this expression is used to compare elements
* (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
* 3 first characters of a property called `name`). The result of a constant expression
@@ -34,6 +34,43 @@
* @param {boolean=} reverse Reverse the order of the array.
* @returns {Array} Sorted copy of the source array.
*
*
* @example
* The example below demonstrates a simple ngRepeat, where the data is sorted
* by age in descending order (predicate is set to `'-age'`).
* `reverse` is not set, which means it defaults to `false`.
<example module="orderByExample">
<file name="index.html">
<script>
angular.module('orderByExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.friends =
[{name:'John', phone:'555-1212', age:10},
{name:'Mary', phone:'555-9876', age:19},
{name:'Mike', phone:'555-4321', age:21},
{name:'Adam', phone:'555-5678', age:35},
{name:'Julie', phone:'555-8765', age:29}];
}]);
</script>
<div ng-controller="ExampleController">
<table class="friend">
<tr>
<th>Name</th>
<th>Phone Number</th>
<th>Age</th>
</tr>
<tr ng-repeat="friend in friends | orderBy:'-age'">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
</table>
</div>
</file>
</example>
*
* The predicate and reverse parameters can be controlled dynamically through scope properties,
* as shown in the next example.
* @example
<example module="orderByExample">
<file name="index.html">
+7 -3
View File
@@ -371,7 +371,7 @@ function $HttpProvider() {
* headers: {
* 'Content-Type': undefined
* },
* data: { test: 'test' },
* data: { test: 'test' }
* }
*
* $http(req).success(function(){...}).error(function(){...});
@@ -806,6 +806,8 @@ function $HttpProvider() {
}
promise.success = function(fn) {
assertArgFn(fn, 'fn');
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
@@ -813,6 +815,8 @@ function $HttpProvider() {
};
promise.error = function(fn) {
assertArgFn(fn, 'fn');
promise.then(null, function(response) {
fn(response.data, response.status, response.headers, config);
});
@@ -1106,8 +1110,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,
+2 -2
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;
@@ -137,7 +137,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
};
function jsonpReq(url, callbackId, done) {
// we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
// we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
// - fetches local scripts via XHR and evals them
// - adds and immediately removes script elements from the document
var script = rawDocument.createElement('script'), callback = null;
+9 -1
View File
@@ -59,7 +59,15 @@ function $LocaleProvider() {
mediumDate: 'MMM d, y',
shortDate: 'M/d/yy',
mediumTime: 'h:mm:ss a',
shortTime: 'h:mm a'
shortTime: 'h:mm a',
ERANAMES: [
"Before Christ",
"Anno Domini"
],
ERAS: [
"BC",
"AD"
]
},
pluralCat: function(num) {
+35 -11
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);
@@ -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;
};
@@ -413,11 +420,19 @@ var locationPrototype = {
*
* Return host of current url.
*
* Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
*
*
* ```js
* // given url http://example.com/#/some/path?foo=bar&baz=xoxo
* var host = $location.host();
* // => "example.com"
*
* // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
* host = $location.host();
* // => "example.com"
* host = location.host;
* // => "example.com:8080"
* ```
*
* @return {string} host of current url.
@@ -807,7 +822,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();
@@ -887,6 +904,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;
+1
View File
@@ -32,6 +32,7 @@
<button ng-click="$log.warn(message)">warn</button>
<button ng-click="$log.info(message)">info</button>
<button ng-click="$log.error(message)">error</button>
<button ng-click="$log.debug(message)">debug</button>
</div>
</file>
</example>
+32 -2
View File
@@ -1,5 +1,16 @@
'use strict';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Any commits to this file should be reviewed with security in mind. *
* Changes to this file can potentially create security vulnerabilities. *
* An approval from 2 Core members with history of modifying *
* this file is required. *
* *
* Does the change somehow allow for arbitrary javascript to be executed? *
* Or allows for someone to change the prototype of built-in objects? *
* Or gives undesired access to variables likes document or window? *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
var $parseMinErr = minErr('$parse');
// Sandboxing Angular Expressions
@@ -37,6 +48,25 @@ function ensureSafeMemberName(name, fullExpression) {
return name;
}
function getStringValue(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.
// Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
// this is, this will handle objects that misbehave.
name = name + '';
if (!isString(name)) {
throw $parseMinErr('iseccst',
'Cannot convert object to primitive value! '
+ 'Expression: {0}', fullExpression);
}
return name;
}
function ensureSafeObject(obj, fullExpression) {
// nifty check if obj is Function that is fast and works across iframes and other contexts
if (obj) {
@@ -678,7 +708,7 @@ Parser.prototype = {
return extend(function $parseObjectIndex(self, locals) {
var o = obj(self, locals),
i = indexFn(self, locals),
i = getStringValue(indexFn(self, locals), expression),
v;
ensureSafeMemberName(i, expression);
@@ -687,7 +717,7 @@ Parser.prototype = {
return v;
}, {
assign: function(self, value, locals) {
var key = ensureSafeMemberName(indexFn(self, locals), expression);
var key = ensureSafeMemberName(getStringValue(indexFn(self, locals), expression), expression);
// prevent overwriting of Function.constructor which would break ensureSafeObject check
var o = ensureSafeObject(obj(self, locals), expression);
if (!o) obj.assign(self, o = {}, locals);
+41 -3
View File
@@ -10,7 +10,7 @@ function $$RAFProvider() { //rAF
$window.webkitCancelRequestAnimationFrame;
var rafSupported = !!requestAnimationFrame;
var raf = rafSupported
var rafFn = rafSupported
? function(fn) {
var id = requestAnimationFrame(fn);
return function() {
@@ -24,8 +24,46 @@ function $$RAFProvider() { //rAF
};
};
raf.supported = rafSupported;
queueFn.supported = rafSupported;
return raf;
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;
}
}
};
}
}];
}
+24 -22
View File
@@ -80,9 +80,26 @@ function $RootScopeProvider() {
return TTL;
};
function createChildScopeClass(parent) {
function ChildScope() {
this.$$watchers = this.$$nextSibling =
this.$$childHead = this.$$childTail = null;
this.$$listeners = {};
this.$$listenerCount = {};
this.$id = nextUid();
this.$$ChildScope = null;
}
ChildScope.prototype = parent;
return ChildScope;
}
this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
function($injector, $exceptionHandler, $parse, $browser) {
function destroyChildScope($event) {
$event.currentScope.$$destroyed = true;
}
/**
* @ngdoc type
* @name $rootScope.Scope
@@ -91,12 +108,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:
@@ -205,15 +219,7 @@ function $RootScopeProvider() {
// Only create a child scope class if somebody asks for one,
// but cache it to allow the VM to optimize lookups.
if (!this.$$ChildScope) {
this.$$ChildScope = function ChildScope() {
this.$$watchers = this.$$nextSibling =
this.$$childHead = this.$$childTail = null;
this.$$listeners = {};
this.$$listenerCount = {};
this.$id = nextUid();
this.$$ChildScope = null;
};
this.$$ChildScope.prototype = this;
this.$$ChildScope = createChildScopeClass(this);
}
child = new this.$$ChildScope();
}
@@ -231,13 +237,9 @@ function $RootScopeProvider() {
// prototypically. In all other cases, this property needs to be set
// when the parent scope is destroyed.
// The listener needs to be added after the parent is set
if (isolate || parent != this) child.$on('$destroy', destroyChild);
if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
return child;
function destroyChild() {
child.$$destroyed = true;
}
},
/**
@@ -269,9 +271,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
+15 -4
View File
@@ -1,5 +1,16 @@
'use strict';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Any commits to this file should be reviewed with security in mind. *
* Changes to this file can potentially create security vulnerabilities. *
* An approval from 2 Core members with history of modifying *
* this file is required. *
* *
* Does the change somehow allow for arbitrary javascript to be executed? *
* Or allows for someone to change the prototype of built-in objects? *
* Or gives undesired access to variables likes document or window? *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
var $sceMinErr = minErr('$sce');
var SCE_CONTEXTS = {
@@ -534,7 +545,7 @@ function $SceDelegateProvider() {
* characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
* in a whitelist.
* - `**`: matches zero or more occurrences of *any* character. As such, it's not
* not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
* appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.
* http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
* not have been the intention.) Its usage at the very end of the path is ok. (e.g.
* http://foo.example.com/templates/**).
@@ -542,11 +553,11 @@ function $SceDelegateProvider() {
* - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
* (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
* accidentally introduce a bug when one updates a complex expression (imho, all regexes should
* have good test coverage.). For instance, the use of `.` in the regex is correct only in a
* have good test coverage). For instance, the use of `.` in the regex is correct only in a
* small number of cases. A `.` character in the regex used when matching the scheme or a
* subdomain could be matched against a `:` or literal `.` that was likely not intended. It
* is highly recommended to use the string patterns and only fall back to regular expressions
* if they as a last resort.
* as a last resort.
* - The regular expression must be an instance of RegExp (i.e. not a string.) It is
* matched against the **entire** *normalized / absolute URL* of the resource being tested
* (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
@@ -556,7 +567,7 @@ function $SceDelegateProvider() {
* remember to escape your regular expression (and be aware that you might need more than
* one level of escaping depending on your templating engine and the way you interpolated
* the value.) Do make use of your platform's escaping mechanism as it might be good
* enough before coding your own. e.g. Ruby has
* enough before coding your own. E.g. Ruby has
* [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
* and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
* Javascript lacks a similar built in function for escaping. Take a look at Google
+18 -7
View File
@@ -7,12 +7,14 @@ var $compileMinErr = minErr('$compile');
* @name $templateRequest
*
* @description
* The `$templateRequest` service downloads the provided template using `$http` and, upon success,
* stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
* of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
* by setting the 2nd parameter of the function to true).
* The `$templateRequest` service runs security checks then downloads the provided template using
* `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
* fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
* exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
* contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
* when `tpl` is of type string and `$templateCache` has the matching entry.
*
* @param {string} tpl The HTTP request template URL
* @param {string|TrustedResourceUrl} tpl The HTTP request template URL
* @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
*
* @return {Promise} the HTTP Promise for the given.
@@ -20,10 +22,19 @@ var $compileMinErr = minErr('$compile');
* @property {number} totalPendingRequests total amount of pending template requests being downloaded.
*/
function $TemplateRequestProvider() {
this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {
this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
function handleRequestFn(tpl, ignoreRequestError) {
handleRequestFn.totalPendingRequests++;
// We consider the template cache holds only trusted templates, so
// there's no need to go through whitelisting again for keys that already
// are included in there. This also makes Angular accept any script
// directive, no matter its name. However, we still need to unwrap trusted
// types.
if (!isString(tpl) || !$templateCache.get(tpl)) {
tpl = $sce.getTrustedResourceUrl(tpl);
}
var transformResponse = $http.defaults && $http.defaults.transformResponse;
if (isArray(transformResponse)) {
@@ -40,7 +51,7 @@ function $TemplateRequestProvider() {
};
return $http.get(tpl, httpOptions)
.finally(function() {
['finally'](function() {
handleRequestFn.totalPendingRequests--;
})
.then(function(response) {
+1 -8
View File
@@ -24,20 +24,13 @@ var originUrl = urlResolve(window.location.href);
*
* Implementation Notes for IE
* ---------------------------
* IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
* IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
* browsers. However, the parsed components will not be set if the URL assigned did not specify
* them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
* work around that by performing the parsing in a 2nd step by taking a previously normalized
* URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
* properties such as protocol, hostname, port, etc.
*
* IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one
* uses the inner HTML approach to assign the URL as part of an HTML snippet -
* http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.
* Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
* Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
* method and IE < 8 is unsupported.
*
* References:
* http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
* http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+16 -11
View File
@@ -432,9 +432,11 @@ angular.module('ngAnimate', ['ng'])
//so that all the animated elements within the animation frame
//will be properly updated and drawn on screen. This is
//required to perform multi-class CSS based animations with
//Firefox. DO NOT REMOVE THIS LINE.
var a = bod.offsetWidth + 1;
fn();
//Firefox. 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!
fn(bod.offsetWidth);
});
};
}])
@@ -1192,18 +1194,21 @@ angular.module('ngAnimate', ['ng'])
}
return cache.promise = runAnimationPostDigest(function(done) {
var parentElement = element.parent();
var elementNode = extractElementNode(element);
var parentNode = elementNode.parentNode;
var cache, parentNode, parentElement, elementNode = extractElementNode(element);
if (elementNode) {
cache = element.data(STORAGE_KEY);
element.removeData(STORAGE_KEY);
parentElement = element.parent();
parentNode = elementNode.parentNode;
}
// TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed
if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {
done();
return;
}
var cache = element.data(STORAGE_KEY);
element.removeData(STORAGE_KEY);
var state = element.data(NG_ANIMATE_STATE) || {};
var classes = resolveElementClasses(element, cache, state.active);
return !classes
@@ -1951,7 +1956,7 @@ angular.module('ngAnimate', ['ng'])
function onAnimationProgress(event) {
event.stopPropagation();
var ev = event.originalEvent || event;
var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
var timeStamp = ev.$manualTimeStamp || Date.now();
/* Firefox (or possibly just Gecko) likes to not round values up
* when a ms measurement is used for the animation */
@@ -1959,7 +1964,7 @@ angular.module('ngAnimate', ['ng'])
/* $manualTimeStamp is a mocked timeStamp value which is set
* within browserTrigger(). This is only here so that tests can
* mock animations properly. Real events fallback to event.timeStamp,
* mock animations properly. Real events fallback to Date.now(),
* or, if they don't, then a timeStamp is automatically created for them.
* We're checking to see if the timeStamp surpasses the expected delay,
* but we're using elapsedTime instead of the timeStamp on the 2nd
+105 -75
View File
@@ -22,13 +22,13 @@
*
* | Directive | Supported Attributes |
* |---------------------------------------------|----------------------------------------------------------------------------------------|
* | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required |
* | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
* | {@link ng.directive:ngShow ngShow} | aria-hidden |
* | {@link ng.directive:ngHide ngHide} | aria-hidden |
* | {@link ng.directive:ngClick ngClick} | tabindex, keypress event |
* | {@link ng.directive:ngDblclick ngDblclick} | tabindex |
* | {@link module:ngMessages ngMessages} | aria-live |
* | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
* | {@link ng.directive:ngClick ngClick} | tabindex, keypress event, button role |
*
* Find out more information about each directive by reading the
* {@link guide/accessibility ngAria Developer Guide}.
@@ -129,6 +129,7 @@ function $AriaProvider() {
* @name $aria
*
* @description
* @priority 200
*
* The $aria service contains helper methods for applying common
* [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives.
@@ -192,6 +193,10 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
return $aria.config(normalizedAttr) && !elem.attr(attr);
}
function shouldAttachRole(role, elem) {
return !elem.attr('role') && (elem.attr('type') === role) && (elem[0].nodeName !== 'INPUT');
}
function getShape(attr, elem) {
var type = attr.type,
role = attr.role;
@@ -205,82 +210,102 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, elem, attr, ngModel) {
priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
compile: function(elem, attr) {
var shape = getShape(attr, elem);
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
function ngAriaWatchModelValue() {
return ngModel.$modelValue;
}
return {
pre: function(scope, elem, attr, ngModel) {
if (shape === 'checkbox' && attr.type !== 'checkbox') {
//Use the input[checkbox] $isEmpty implementation for elements with checkbox roles
ngModel.$isEmpty = function(value) {
return value === false;
};
}
},
post: function(scope, elem, attr, ngModel) {
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
function getRadioReaction() {
if (needsTabIndex) {
needsTabIndex = false;
return function ngAriaRadioReaction(newVal) {
var boolVal = newVal === attr.value;
elem.attr('aria-checked', boolVal);
elem.attr('tabindex', 0 - !boolVal);
};
} else {
return function ngAriaRadioReaction(newVal) {
elem.attr('aria-checked', newVal === attr.value);
};
function ngAriaWatchModelValue() {
return ngModel.$modelValue;
}
function getRadioReaction() {
if (needsTabIndex) {
needsTabIndex = false;
return function ngAriaRadioReaction(newVal) {
var boolVal = (attr.value == ngModel.$viewValue);
elem.attr('aria-checked', boolVal);
elem.attr('tabindex', 0 - !boolVal);
};
} else {
return function ngAriaRadioReaction(newVal) {
elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
};
}
}
function ngAriaCheckboxReaction() {
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
}
switch (shape) {
case 'radio':
case 'checkbox':
if (shouldAttachRole(shape, elem)) {
elem.attr('role', shape);
}
if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) {
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
getRadioReaction() : ngAriaCheckboxReaction);
}
break;
case 'range':
if (shouldAttachRole(shape, elem)) {
elem.attr('role', 'slider');
}
if ($aria.config('ariaValue')) {
if (attr.min && !elem.attr('aria-valuemin')) {
elem.attr('aria-valuemin', attr.min);
}
if (attr.max && !elem.attr('aria-valuemax')) {
elem.attr('aria-valuemax', attr.max);
}
if (!elem.attr('aria-valuenow')) {
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
elem.attr('aria-valuenow', newVal);
});
}
}
break;
case 'multiline':
if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
elem.attr('aria-multiline', true);
}
break;
}
if (needsTabIndex) {
elem.attr('tabindex', 0);
}
if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
scope.$watch(function ngAriaRequiredWatch() {
return ngModel.$error.required;
}, function ngAriaRequiredReaction(newVal) {
elem.attr('aria-required', !!newVal);
});
}
if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) {
scope.$watch(function ngAriaInvalidWatch() {
return ngModel.$invalid;
}, function ngAriaInvalidReaction(newVal) {
elem.attr('aria-invalid', !!newVal);
});
}
}
}
function ngAriaCheckboxReaction(newVal) {
elem.attr('aria-checked', !!newVal);
}
switch (shape) {
case 'radio':
case 'checkbox':
if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) {
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
getRadioReaction() : ngAriaCheckboxReaction);
}
break;
case 'range':
if ($aria.config('ariaValue')) {
if (attr.min && !elem.attr('aria-valuemin')) {
elem.attr('aria-valuemin', attr.min);
}
if (attr.max && !elem.attr('aria-valuemax')) {
elem.attr('aria-valuemax', attr.max);
}
if (!elem.attr('aria-valuenow')) {
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
elem.attr('aria-valuenow', newVal);
});
}
}
break;
case 'multiline':
if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
elem.attr('aria-multiline', true);
}
break;
}
if (needsTabIndex) {
elem.attr('tabindex', 0);
}
if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
scope.$watch(function ngAriaRequiredWatch() {
return ngModel.$error.required;
}, function ngAriaRequiredReaction(newVal) {
elem.attr('aria-required', !!newVal);
});
}
if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) {
scope.$watch(function ngAriaInvalidWatch() {
return ngModel.$invalid;
}, function ngAriaInvalidReaction(newVal) {
elem.attr('aria-invalid', !!newVal);
});
}
};
}
};
}])
@@ -305,17 +330,22 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
return function(scope, elem, attr) {
var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA'];
function isNodeOneOf(elem, nodeTypeArray) {
if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
return true;
}
}
if (!elem.attr('role') && !isNodeOneOf(elem, nodeBlackList)) {
elem.attr('role', 'button');
}
if ($aria.config('tabindex') && !elem.attr('tabindex')) {
elem.attr('tabindex', 0);
}
if ($aria.config('bindKeypress') && !attr.ngKeypress && isNodeOneOf(elem, ['DIV', 'LI'])) {
if ($aria.config('bindKeypress') && !attr.ngKeypress && !isNodeOneOf(elem, nodeBlackList)) {
elem.on('keypress', function(event) {
if (event.keyCode === 32 || event.keyCode === 13) {
scope.$apply(callback);
+4 -3
View File
@@ -86,6 +86,7 @@ angular.module('ngCookies', ['ng']).
for (name in lastCookies) {
if (isUndefined(cookies[name])) {
$browser.cookies(name, undefined);
delete lastCookies[name];
}
}
@@ -98,13 +99,13 @@ angular.module('ngCookies', ['ng']).
}
if (value !== lastCookies[name]) {
$browser.cookies(name, value);
lastCookies[name] = value;
updated = true;
}
}
//verify what was actually stored
if (updated) {
updated = false;
browserCookies = $browser.cookies();
for (name in cookies) {
@@ -112,10 +113,10 @@ angular.module('ngCookies', ['ng']).
//delete or reset all cookies that the browser dropped from $cookies
if (isUndefined(browserCookies[name])) {
delete cookies[name];
delete lastCookies[name];
} else {
cookies[name] = browserCookies[name];
cookies[name] = lastCookies[name] = browserCookies[name];
}
updated = true;
}
}
}

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