Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a65c3deb7 | |||
| ef0c333776 | |||
| bce1d8ecad | |||
| 5a1bc6eb32 | |||
| 1f7a0b2b72 | |||
| a665550933 | |||
| d434f3db53 | |||
| 7e08975b67 | |||
| 82c481bb23 | |||
| b1f46bb1b2 | |||
| 3a6bf0d5bc | |||
| e201f9040f | |||
| 40e9bcd1b4 | |||
| f98e038418 | |||
| ec98c94ccb | |||
| f13055a0a5 | |||
| 623ce1ad2c | |||
| 34cf141838 | |||
| 274e93537e | |||
| f7622dcc0d | |||
| 2c03a35743 | |||
| 6b72598b87 | |||
| 51e24d75c3 | |||
| 64a142b58e | |||
| 0026ebf2de | |||
| a4f73c9f99 | |||
| bd5c4e5f0e | |||
| 9742565d61 | |||
| 6f33dfa8cc | |||
| 96f0c8df17 | |||
| 53fb534889 | |||
| 6271ac064c | |||
| 2d71b5b053 | |||
| a547dff09b | |||
| 3f9517ea5b | |||
| 8b4ffdde7a | |||
| e57240d87d | |||
| a51b4e6dc4 | |||
| 215be0b0ab | |||
| 7c5880f998 | |||
| 0d941a986a | |||
| 8714cabdb7 | |||
| cbab2923ef | |||
| dba7e20e96 | |||
| 24dd9ea649 | |||
| 8bd59a593b | |||
| 9a1349d2e0 | |||
| 7e6155a6f1 | |||
| 0f034444c3 | |||
| 74ecea9f2d | |||
| 8d5c08c6b8 | |||
| 0bb57d538f | |||
| 61a3fb676a | |||
| f486ebe80b | |||
| 03190fd896 | |||
| 340e4da2eb | |||
| 46e4fa87fb | |||
| 45d43b9234 | |||
| 6b28aef1c5 |
+3
-1
@@ -1,4 +1,5 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '0.10'
|
||||
|
||||
@@ -47,7 +48,7 @@ install:
|
||||
- npm config set loglevel http
|
||||
- npm install -g npm@2.5
|
||||
# Instal npm dependecies and ensure that npm cache is not stale
|
||||
- scripts/npm/install-dependencies.sh
|
||||
- npm install
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
@@ -60,6 +61,7 @@ script:
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
after_script:
|
||||
- ./scripts/travis/tear_down_browser_provider.sh
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
notifications:
|
||||
|
||||
+157
@@ -1,3 +1,160 @@
|
||||
<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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -235,6 +240,7 @@ The body should include the motivation for the change and contrast this with pre
|
||||
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].
|
||||
|
||||
|
||||
+1
-1
@@ -293,7 +293,7 @@ module.exports = function(grunt) {
|
||||
|
||||
shell: {
|
||||
"npm-install": {
|
||||
command: path.normalize('scripts/npm/install-dependencies.sh')
|
||||
command: 'node scripts/npm/check-node-modules.js'
|
||||
},
|
||||
|
||||
"promises-aplus-tests": {
|
||||
|
||||
@@ -10,14 +10,14 @@ var Package = require('dgeni').Package;
|
||||
module.exports = new Package('angularjs', [
|
||||
require('dgeni-packages/ngdoc'),
|
||||
require('dgeni-packages/nunjucks'),
|
||||
require('dgeni-packages/examples')
|
||||
require('dgeni-packages/examples'),
|
||||
require('dgeni-packages/git')
|
||||
])
|
||||
|
||||
|
||||
.factory(require('./services/errorNamespaceMap'))
|
||||
.factory(require('./services/getMinerrInfo'))
|
||||
.factory(require('./services/getVersion'))
|
||||
.factory(require('./services/gitData'))
|
||||
|
||||
.factory(require('./services/deployments/debug'))
|
||||
.factory(require('./services/deployments/default'))
|
||||
@@ -26,7 +26,6 @@ module.exports = new Package('angularjs', [
|
||||
|
||||
.factory(require('./inline-tag-defs/type'))
|
||||
|
||||
|
||||
.processor(require('./processors/error-docs'))
|
||||
.processor(require('./processors/index-page'))
|
||||
.processor(require('./processors/keywords'))
|
||||
|
||||
@@ -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,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:baddir
|
||||
@fullName Invalid Directive Name
|
||||
@description
|
||||
|
||||
This error occurs when the name of a directive is not valid.
|
||||
|
||||
Directives must start with a lowercase character.
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
```
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -344,5 +344,4 @@ When using a directive that takes an expression:
|
||||
<ul>
|
||||
<li ng-repeat="item in ::items">{{item.name}};</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
```
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Browserstack tunnel"
|
||||
echo "TODO: implement me"
|
||||
exit 1
|
||||
+1
-1
@@ -116,7 +116,7 @@ module.exports = {
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/'/g, "\\'")
|
||||
.replace(/\r?\n/g, '\\n');
|
||||
js = "!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>');";
|
||||
js = "!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type=\"text/css\">" + css + "</style>');";
|
||||
state.js.push(js);
|
||||
|
||||
return state;
|
||||
|
||||
Executable
+16
@@ -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"
|
||||
+22
-16
@@ -2385,10 +2385,10 @@
|
||||
}
|
||||
},
|
||||
"dgeni-packages": {
|
||||
"version": "0.10.13",
|
||||
"version": "0.10.17",
|
||||
"dependencies": {
|
||||
"catharsis": {
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"dependencies": {
|
||||
"underscore-contrib": {
|
||||
"version": "0.3.0",
|
||||
@@ -2404,10 +2404,10 @@
|
||||
"version": "2.3.0",
|
||||
"dependencies": {
|
||||
"camel-case": {
|
||||
"version": "1.1.1"
|
||||
"version": "1.1.2"
|
||||
},
|
||||
"constant-case": {
|
||||
"version": "1.1.0"
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"dot-case": {
|
||||
"version": "1.1.1"
|
||||
@@ -2428,7 +2428,7 @@
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"pascal-case": {
|
||||
"version": "1.1.0"
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"path-case": {
|
||||
"version": "1.1.1"
|
||||
@@ -2440,10 +2440,10 @@
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"swap-case": {
|
||||
"version": "1.1.0"
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"title-case": {
|
||||
"version": "1.1.0"
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"upper-case": {
|
||||
"version": "1.1.2"
|
||||
@@ -2468,7 +2468,7 @@
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.8.2",
|
||||
"version": "3.8.3",
|
||||
"dependencies": {
|
||||
"domhandler": {
|
||||
"version": "2.3.0"
|
||||
@@ -2518,21 +2518,21 @@
|
||||
"version": "0.3.0",
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0"
|
||||
"version": "2.6.4"
|
||||
},
|
||||
"sigmund": {
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nunjucks": {
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.4",
|
||||
"dependencies": {
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"dependencies": {
|
||||
"wordwrap": {
|
||||
"version": "0.0.2"
|
||||
"version": "0.0.3"
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10"
|
||||
@@ -2552,10 +2552,10 @@
|
||||
"version": "0.2.14",
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0"
|
||||
"version": "2.6.4"
|
||||
},
|
||||
"sigmund": {
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2582,10 +2582,10 @@
|
||||
"version": "0.1.6"
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "0.3.5",
|
||||
"version": "0.3.6",
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.5.3"
|
||||
"version": "1.8.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2621,6 +2621,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "4.3.6"
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.5.1"
|
||||
},
|
||||
"winston": {
|
||||
"version": "0.7.3",
|
||||
"dependencies": {
|
||||
|
||||
Generated
+1786
-1776
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"branchVersion": "1.3.*",
|
||||
"distTag": "previous_1_3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.js.git"
|
||||
@@ -10,6 +11,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",
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -110,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SHRINKWRAP_FILE=npm-shrinkwrap.json
|
||||
SHRINKWRAP_CACHED_FILE=node_modules/npm-shrinkwrap.cached.json
|
||||
|
||||
if diff -q $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE; then
|
||||
echo 'No shrinkwrap changes detected. npm install will be skipped...';
|
||||
else
|
||||
echo 'Blowing away node_modules and reinstalling npm dependencies...'
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
cp $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE
|
||||
echo 'npm install successful!'
|
||||
fi
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Has to be run from project root directory.
|
||||
|
||||
./lib/${BROWSER_PROVIDER}/teardown_tunnel.sh
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+2
-11
@@ -429,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.
|
||||
*
|
||||
@@ -757,14 +757,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
function assertValidDirectiveName(name) {
|
||||
var letter = name.charAt(0);
|
||||
if (!letter || letter !== lowercase(letter)) {
|
||||
throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $compileProvider#directive
|
||||
@@ -783,7 +775,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
this.directive = function registerDirective(name, directiveFactory) {
|
||||
assertNotHasOwnProperty(name, 'directive');
|
||||
if (isString(name)) {
|
||||
assertValidDirectiveName(name);
|
||||
assertArg(directiveFactory, 'directiveFactory');
|
||||
if (!hasDirectives.hasOwnProperty(name)) {
|
||||
hasDirectives[name] = [];
|
||||
@@ -2193,7 +2184,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
$compileNode.empty();
|
||||
|
||||
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
|
||||
$templateRequest(templateUrl)
|
||||
.then(function(content) {
|
||||
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1170,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;
|
||||
@@ -1247,7 +1247,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
||||
ctrl.$formatters.push(function(value) {
|
||||
if (!ctrl.$isEmpty(value)) {
|
||||
if (!isNumber(value)) {
|
||||
throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
|
||||
throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
|
||||
}
|
||||
value = value.toString();
|
||||
}
|
||||
@@ -1340,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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -268,7 +267,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
}
|
||||
};
|
||||
} else if (!parsedNgModel.assign) {
|
||||
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
|
||||
throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
|
||||
$attr.ngModel, startingTag($element));
|
||||
}
|
||||
};
|
||||
@@ -597,7 +596,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
forEach(ctrl.$asyncValidators, function(validator, name) {
|
||||
var promise = validator(modelValue, viewValue);
|
||||
if (!isPromiseLike(promise)) {
|
||||
throw $ngModelMinErr("$asyncValidators",
|
||||
throw ngModelMinErr("$asyncValidators",
|
||||
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
|
||||
}
|
||||
setValidity(name, undefined);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
+2
-2
@@ -1110,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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+27
-11
@@ -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;
|
||||
};
|
||||
|
||||
@@ -815,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();
|
||||
@@ -895,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;
|
||||
|
||||
+21
-2
@@ -48,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) {
|
||||
@@ -689,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);
|
||||
@@ -698,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);
|
||||
|
||||
+5
-8
@@ -108,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:
|
||||
@@ -274,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
|
||||
|
||||
+4
-4
@@ -545,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/**).
|
||||
@@ -553,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
|
||||
@@ -567,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
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
+1
-8
@@ -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
|
||||
|
||||
@@ -1194,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
|
||||
|
||||
Vendored
+50
-11
@@ -782,8 +782,8 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
|
||||
};
|
||||
});
|
||||
|
||||
$provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser',
|
||||
function($delegate, $$asyncCallback, $timeout, $browser) {
|
||||
$provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser', '$rootScope', '$$rAF',
|
||||
function($delegate, $$asyncCallback, $timeout, $browser, $rootScope, $$rAF) {
|
||||
var animate = {
|
||||
queue: [],
|
||||
cancel: $delegate.cancel,
|
||||
@@ -803,6 +803,43 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
|
||||
fn();
|
||||
});
|
||||
reflowQueue = [];
|
||||
},
|
||||
flush: function() {
|
||||
$rootScope.$digest();
|
||||
var doNextRun, somethingFlushed = false;
|
||||
do {
|
||||
doNextRun = false;
|
||||
if (reflowQueue.length) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
this.triggerReflow();
|
||||
}
|
||||
if ($$rAF.queue.length) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
$$rAF.flush();
|
||||
}
|
||||
if ($$asyncCallback.queue.length) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
this.triggerCallbackEvents();
|
||||
}
|
||||
if (timeoutsRemaining()) {
|
||||
var oldValue = timeoutsRemaining();
|
||||
this.triggerCallbackPromise();
|
||||
var newValue = timeoutsRemaining();
|
||||
if (newValue < oldValue) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
}
|
||||
}
|
||||
} while (doNextRun);
|
||||
|
||||
if (!somethingFlushed) {
|
||||
throw new Error('No pending animations ready to be closed or flushed');
|
||||
}
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
function timeoutsRemaining() {
|
||||
return $browser.deferredFns.length;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1752,8 +1789,7 @@ angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $
|
||||
}];
|
||||
|
||||
angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||
var queue = [];
|
||||
var rafFn = function(fn) {
|
||||
var queue, rafFn = function(fn) {
|
||||
var index = queue.length;
|
||||
queue.push(fn);
|
||||
return function() {
|
||||
@@ -1761,6 +1797,8 @@ angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||
};
|
||||
};
|
||||
|
||||
queue = rafFn.queue = [];
|
||||
|
||||
rafFn.supported = $delegate.supported;
|
||||
|
||||
rafFn.flush = function() {
|
||||
@@ -1773,22 +1811,22 @@ angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||
queue[i]();
|
||||
}
|
||||
|
||||
queue = [];
|
||||
queue.length = 0;
|
||||
};
|
||||
|
||||
return rafFn;
|
||||
}];
|
||||
|
||||
angular.mock.$AsyncCallbackDecorator = ['$delegate', function($delegate) {
|
||||
var callbacks = [];
|
||||
var addFn = function(fn) {
|
||||
callbacks.push(fn);
|
||||
var queue, addFn = function(fn) {
|
||||
queue.push(fn);
|
||||
};
|
||||
queue = addFn.queue = [];
|
||||
addFn.flush = function() {
|
||||
angular.forEach(callbacks, function(fn) {
|
||||
angular.forEach(queue, function(fn) {
|
||||
fn();
|
||||
});
|
||||
callbacks = [];
|
||||
queue.length = 0;
|
||||
};
|
||||
return addFn;
|
||||
}];
|
||||
@@ -2237,7 +2275,8 @@ if (window.jasmine || window.mocha) {
|
||||
|
||||
if (injector) {
|
||||
injector.get('$rootElement').off();
|
||||
injector.get('$browser').pollFns.length = 0;
|
||||
var $browser = injector.get('$browser');
|
||||
if ($browser.pollFns) $browser.pollFns.length = 0;
|
||||
}
|
||||
|
||||
// clean up jquery's fragment cache
|
||||
|
||||
@@ -407,7 +407,9 @@ function $RouteProvider() {
|
||||
* @name $route#$routeChangeSuccess
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted after a route dependencies are resolved.
|
||||
* Broadcasted after a route change has happened successfully.
|
||||
* The `resolve` dependencies are now available in the `current.locals` property.
|
||||
*
|
||||
* {@link ngRoute.directive:ngView ngView} listens for the directive
|
||||
* to instantiate the controller and render the view.
|
||||
*
|
||||
@@ -591,9 +593,8 @@ function $RouteProvider() {
|
||||
if (angular.isFunction(templateUrl)) {
|
||||
templateUrl = templateUrl(nextRoute.params);
|
||||
}
|
||||
templateUrl = $sce.getTrustedResourceUrl(templateUrl);
|
||||
if (angular.isDefined(templateUrl)) {
|
||||
nextRoute.loadedTemplateUrl = templateUrl;
|
||||
nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl);
|
||||
template = $templateRequest(templateUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@
|
||||
*/
|
||||
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
|
||||
var LINKY_URL_REGEXP =
|
||||
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,
|
||||
MAILTO_REGEXP = /^mailto:/;
|
||||
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/i,
|
||||
MAILTO_REGEXP = /^mailto:/i;
|
||||
|
||||
return function(text, target) {
|
||||
if (!text) return text;
|
||||
|
||||
+2
-1
@@ -165,6 +165,7 @@
|
||||
"spyOnlyCallsWithArgs": false,
|
||||
"createMockStyleSheet": false,
|
||||
"browserTrigger": false,
|
||||
"jqLiteCacheSize": false
|
||||
"jqLiteCacheSize": false,
|
||||
"browserSupportsCssAnimations": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,3 +56,12 @@ function createMockStyleSheet(doc, wind) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function browserSupportsCssAnimations() {
|
||||
var nav = window.navigator.appVersion;
|
||||
if (nav.indexOf('MSIE') >= 0) {
|
||||
var version = parseInt(navigator.appVersion.match(/MSIE ([\d.]+)/)[1]);
|
||||
return version >= 10; //only IE10+ support keyframes / transitions
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,9 @@ function MockWindow(options) {
|
||||
return getHash(locationHref);
|
||||
},
|
||||
set hash(value) {
|
||||
locationHref = stripHash(locationHref) + '#' + value;
|
||||
// replace the hash with the new one (stripping off a leading hash if there is one)
|
||||
// See hash setter spec: https://url.spec.whatwg.org/#urlutils-and-urlutilsreadonly-members
|
||||
locationHref = stripHash(locationHref) + '#' + value.replace(/^#/,'');
|
||||
},
|
||||
replace: function(url) {
|
||||
locationHref = url;
|
||||
|
||||
+12
-12
@@ -147,7 +147,6 @@ describe('$compile', function() {
|
||||
|
||||
|
||||
describe('configuration', function() {
|
||||
|
||||
it('should register a directive', function() {
|
||||
module(function() {
|
||||
directive('div', function(log) {
|
||||
@@ -202,15 +201,6 @@ describe('$compile', function() {
|
||||
});
|
||||
inject(function($compile) {});
|
||||
});
|
||||
|
||||
it('should throw an exception if a directive name starts with a non-lowercase letter', function() {
|
||||
module(function() {
|
||||
expect(function() {
|
||||
directive('BadDirectiveName', function() { });
|
||||
}).toThrowMinErr('$compile','baddir', "Directive name 'BadDirectiveName' is invalid. The first character must be a lowercase letter");
|
||||
});
|
||||
inject(function($compile) {});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1281,14 +1271,24 @@ describe('$compile', function() {
|
||||
));
|
||||
|
||||
it('should not load cross domain templates by default', inject(
|
||||
function($compile, $rootScope, $templateCache, $sce) {
|
||||
function($compile, $rootScope) {
|
||||
expect(function() {
|
||||
$templateCache.put('http://example.com/should-not-load.html', 'Should not load even if in cache.');
|
||||
$compile('<div class="crossDomainTemplate"></div>')($rootScope);
|
||||
}).toThrowMinErr('$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: http://example.com/should-not-load.html');
|
||||
}
|
||||
));
|
||||
|
||||
it('should trust what is already in the template cache', inject(
|
||||
function($compile, $httpBackend, $rootScope, $templateCache) {
|
||||
$httpBackend.expect('GET', 'http://example.com/should-not-load.html').respond('<span>example.com/remote-version</span>');
|
||||
$templateCache.put('http://example.com/should-not-load.html', '<span>example.com/cached-version</span>');
|
||||
element = $compile('<div class="crossDomainTemplate"></div>')($rootScope);
|
||||
expect(sortedHtml(element)).toEqual('<div class="crossDomainTemplate"></div>');
|
||||
$rootScope.$digest();
|
||||
expect(sortedHtml(element)).toEqual('<div class="crossDomainTemplate"><span>example.com/cached-version</span></div>');
|
||||
}
|
||||
));
|
||||
|
||||
it('should load cross domain templates when trusted', inject(
|
||||
function($compile, $httpBackend, $rootScope, $sce) {
|
||||
$httpBackend.expect('GET', 'http://example.com/trusted-template.html').respond('<span>example.com/trusted_template_contents</span>');
|
||||
|
||||
@@ -472,7 +472,7 @@ describe('ngClass animations', function() {
|
||||
//is spaced-out then it is required so that the original digestion
|
||||
//is kicked into gear
|
||||
$rootScope.$digest();
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(element.data('state')).toBe('crazy-enter');
|
||||
expect(enterComplete).toBe(true);
|
||||
|
||||
@@ -433,7 +433,7 @@ describe('ngInclude', function() {
|
||||
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
@@ -450,7 +450,7 @@ describe('ngInclude', function() {
|
||||
});
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.tpl = 'another.html';
|
||||
@@ -459,7 +459,7 @@ describe('ngInclude', function() {
|
||||
|
||||
expect($animate.queue.shift().event).toBe('leave');
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.tpl = 'template.html';
|
||||
@@ -468,7 +468,7 @@ describe('ngInclude', function() {
|
||||
|
||||
expect($animate.queue.shift().event).toBe('leave');
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalled();
|
||||
expect(autoScrollSpy.callCount).toBe(3);
|
||||
@@ -484,7 +484,7 @@ describe('ngInclude', function() {
|
||||
});
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
@@ -500,7 +500,7 @@ describe('ngInclude', function() {
|
||||
});
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.tpl = 'template.html';
|
||||
@@ -522,7 +522,7 @@ describe('ngInclude', function() {
|
||||
|
||||
$rootScope.$apply("tpl = 'template.html'");
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
@@ -1486,7 +1486,7 @@ describe('ngRepeat animations', function() {
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.text()).toBe('123'); // the original order should be preserved
|
||||
$animate.triggerReflow();
|
||||
$animate.flush();
|
||||
$timeout.flush(1500); // 1s * 1.5 closing buffer
|
||||
expect(element.text()).toBe('13');
|
||||
|
||||
|
||||
@@ -204,6 +204,21 @@ describe('validators', function() {
|
||||
expect($rootScope.form.test.$error.pattern).toBe(true);
|
||||
expect(inputElm).not.toBeValid();
|
||||
});
|
||||
|
||||
|
||||
it('should validate the viewValue and not the modelValue', function() {
|
||||
var inputElm = helper.compileInput('<input type="text" name="test" ng-model="value" pattern="\\d{4}">');
|
||||
var ctrl = inputElm.controller('ngModel');
|
||||
|
||||
ctrl.$parsers.push(function(value) {
|
||||
return (value * 10) + '';
|
||||
});
|
||||
|
||||
helper.changeInputValueTo('1234');
|
||||
expect($rootScope.form.test.$error.pattern).not.toBe(true);
|
||||
expect($rootScope.form.test.$modelValue).toBe('12340');
|
||||
expect(inputElm).toBeValid();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ describe('$httpBackend', function() {
|
||||
|
||||
|
||||
it('should read responseText if response was not defined', function() {
|
||||
// old browsers like IE8, don't support responseType, so they always respond with responseText
|
||||
// old browsers like IE9, don't support responseType, so they always respond with responseText
|
||||
|
||||
$backend('GET', '/whatever', null, callback, {}, null, null, 'blob');
|
||||
|
||||
|
||||
+1
-1
@@ -1657,7 +1657,7 @@ describe('$http', function() {
|
||||
$http({method: 'GET', url: '/some', timeout: canceler.promise}).error(
|
||||
function(data, status, headers, config) {
|
||||
expect(data).toBeUndefined();
|
||||
expect(status).toBe(0);
|
||||
expect(status).toBe(-1);
|
||||
expect(headers()).toEqual({});
|
||||
expect(config.url).toBe('/some');
|
||||
callback();
|
||||
|
||||
+1068
-742
File diff suppressed because it is too large
Load Diff
+7
-6
@@ -1,12 +1,6 @@
|
||||
/* global $LogProvider: false */
|
||||
'use strict';
|
||||
|
||||
function initService(debugEnabled) {
|
||||
return module(function($logProvider) {
|
||||
$logProvider.debugEnabled(debugEnabled);
|
||||
});
|
||||
}
|
||||
|
||||
describe('$log', function() {
|
||||
var $window, logger, log, warn, info, error, debug;
|
||||
|
||||
@@ -178,4 +172,11 @@ describe('$log', function() {
|
||||
expect(errorArgs).toEqual(['abc', 'message\nsourceURL:123']);
|
||||
});
|
||||
});
|
||||
|
||||
function initService(debugEnabled) {
|
||||
return module(function($logProvider) {
|
||||
$logProvider.debugEnabled(debugEnabled);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -1190,6 +1190,20 @@ describe('parser', function() {
|
||||
scope.$eval('{}["__proto__"].foo = 1');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
|
||||
expect(function() {
|
||||
scope.$eval('{}[["__proto__"]]');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
expect(function() {
|
||||
scope.$eval('{}[["__proto__"]].foo = 1');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
|
||||
expect(function() {
|
||||
scope.$eval('0[["__proto__"]]');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
expect(function() {
|
||||
scope.$eval('0[["__proto__"]].foo = 1');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
|
||||
scope.a = "__pro";
|
||||
scope.b = "to__";
|
||||
expect(function() {
|
||||
@@ -1201,6 +1215,15 @@ describe('parser', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should prevent the exploit', function() {
|
||||
expect(function() {
|
||||
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
|
||||
});
|
||||
if (!msie || msie > 10) {
|
||||
expect((1)['__proto__'].foo).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it('should prevent the exploit', function() {
|
||||
expect(function() {
|
||||
scope.$eval('' +
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
|
||||
describe('SCE', function() {
|
||||
|
||||
// Work around an IE8 bug. Though window.inject === angular.mock.inject, if it's invoked the
|
||||
// window scope, IE8 loses the exception object that bubbles up and replaces it with a TypeError.
|
||||
// By using a local alias, it gets invoked on the global scope instead of window.
|
||||
// Ref: https://github.com/angular/angular.js/pull/4221#/issuecomment-25515813
|
||||
var inject = angular.mock.inject;
|
||||
|
||||
describe('when disabled', function() {
|
||||
beforeEach(function() {
|
||||
module(function($sceProvider) {
|
||||
|
||||
+252
-258
File diff suppressed because it is too large
Load Diff
Vendored
+179
-6
@@ -719,8 +719,6 @@ describe('ngMock', function() {
|
||||
|
||||
it('should serialize scope that has overridden "hasOwnProperty"', inject(function($rootScope, $sniffer) {
|
||||
/* jshint -W001 */
|
||||
// MS IE8 just doesn't work for this kind of thing, since "for ... in" doesn't return
|
||||
// things like hasOwnProperty even if it is explicitly defined on the actual object!
|
||||
$rootScope.hasOwnProperty = 'X';
|
||||
expect(d($rootScope)).toMatch(/Scope\(.*\): \{/);
|
||||
expect(d($rootScope)).toMatch(/hasOwnProperty: "X"/);
|
||||
@@ -906,10 +904,6 @@ describe('ngMock', function() {
|
||||
});
|
||||
|
||||
|
||||
// We don't run the following tests on IE8.
|
||||
// IE8 throws "Object does not support this property or method." error,
|
||||
// when thrown from a function defined on window (which `inject` is).
|
||||
|
||||
it('should not change thrown Errors', inject(function($sniffer) {
|
||||
expect(function() {
|
||||
inject(function() {
|
||||
@@ -1834,6 +1828,185 @@ describe('ngMockE2E', function() {
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngAnimateMock', function() {
|
||||
|
||||
beforeEach(module('ngAnimate'));
|
||||
beforeEach(module('ngAnimateMock'));
|
||||
|
||||
var ss, element, trackedAnimations;
|
||||
|
||||
beforeEach(module(function($animateProvider) {
|
||||
trackedAnimations = [];
|
||||
$animateProvider.register('.animate', function($timeout) {
|
||||
return {
|
||||
leave: logFn('leave'),
|
||||
addClass: logFn('addClass')
|
||||
};
|
||||
|
||||
function logFn(method) {
|
||||
return function(element) {
|
||||
trackedAnimations.push(getDoneCallback(arguments));
|
||||
// this will never finish an animation so we'll issue a call
|
||||
// to timeout so that the mock driver won't throw an exception
|
||||
$timeout(angular.noop, 0, false);
|
||||
};
|
||||
}
|
||||
|
||||
function getDoneCallback(args) {
|
||||
for (var i = args.length; i > 0; i--) {
|
||||
if (angular.isFunction(args[i])) return args[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return function($animate, $rootElement, $document, $rootScope, $window) {
|
||||
if (ss) {
|
||||
ss.destroy();
|
||||
}
|
||||
ss = createMockStyleSheet($document, $window);
|
||||
|
||||
element = angular.element('<div class="animate"></div>');
|
||||
$rootElement.append(element);
|
||||
angular.element($document[0].body).append($rootElement);
|
||||
$animate.enabled(true);
|
||||
$rootScope.$digest();
|
||||
};
|
||||
}));
|
||||
|
||||
describe('$animate.queue', function() {
|
||||
it('should maintain a queue of the executed animations', inject(function($animate) {
|
||||
element.removeClass('animate'); // we don't care to test any actual animations
|
||||
var options = {};
|
||||
|
||||
$animate.addClass(element, 'on', options);
|
||||
var first = $animate.queue[0];
|
||||
expect(first.element).toBe(element);
|
||||
expect(first.event).toBe('addClass');
|
||||
expect(first.options).toBe(options);
|
||||
|
||||
$animate.removeClass(element, 'off', options);
|
||||
var second = $animate.queue[1];
|
||||
expect(second.element).toBe(element);
|
||||
expect(second.event).toBe('removeClass');
|
||||
expect(second.options).toBe(options);
|
||||
|
||||
$animate.leave(element, options);
|
||||
var third = $animate.queue[2];
|
||||
expect(third.element).toBe(element);
|
||||
expect(third.event).toBe('leave');
|
||||
expect(third.options).toBe(options);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('$animate.flush()', function() {
|
||||
it('should throw an error if there is nothing to animate', inject(function($animate) {
|
||||
expect(function() {
|
||||
$animate.flush();
|
||||
}).toThrow('No pending animations ready to be closed or flushed');
|
||||
}));
|
||||
|
||||
it('should trigger the animation to start',
|
||||
inject(function($animate) {
|
||||
|
||||
expect(trackedAnimations.length).toBe(0);
|
||||
$animate.leave(element);
|
||||
$animate.flush();
|
||||
expect(trackedAnimations.length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should trigger the animation to end once run and called',
|
||||
inject(function($animate) {
|
||||
|
||||
$animate.leave(element);
|
||||
$animate.flush();
|
||||
expect(element.parent().length).toBe(1);
|
||||
|
||||
trackedAnimations[0]();
|
||||
$animate.flush();
|
||||
expect(element.parent().length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should trigger the animation promise callback to fire once run and closed',
|
||||
inject(function($animate) {
|
||||
|
||||
var doneSpy = jasmine.createSpy();
|
||||
$animate.leave(element).then(doneSpy);
|
||||
$animate.flush();
|
||||
|
||||
trackedAnimations[0]();
|
||||
expect(doneSpy).not.toHaveBeenCalled();
|
||||
$animate.flush();
|
||||
expect(doneSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should trigger a series of CSS animations to trigger and start once run',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
if (!browserSupportsCssAnimations()) return;
|
||||
|
||||
ss.addRule('.leave-me.ng-leave', 'transition:1s linear all;');
|
||||
|
||||
var i, elm, elms = [];
|
||||
for (i = 0; i < 5; i++) {
|
||||
elm = angular.element('<div class="leave-me"></div>');
|
||||
element.append(elm);
|
||||
elms.push(elm);
|
||||
|
||||
$animate.leave(elm);
|
||||
}
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
elm = elms[i];
|
||||
expect(elm.hasClass('ng-leave')).toBe(true);
|
||||
expect(elm.hasClass('ng-leave-active')).toBe(false);
|
||||
}
|
||||
|
||||
$animate.flush();
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
elm = elms[i];
|
||||
expect(elm.hasClass('ng-leave')).toBe(true);
|
||||
expect(elm.hasClass('ng-leave-active')).toBe(true);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should trigger parent and child animations to run within the same flush',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
var child = angular.element('<div class="animate child"></div>');
|
||||
element.append(child);
|
||||
|
||||
expect(trackedAnimations.length).toBe(0);
|
||||
|
||||
$animate.addClass(element, 'go');
|
||||
$animate.addClass(child, 'start');
|
||||
$animate.flush();
|
||||
|
||||
expect(trackedAnimations.length).toBe(2);
|
||||
}));
|
||||
|
||||
it('should trigger animation callbacks when called',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
var spy = jasmine.createSpy();
|
||||
element.on('$animate:before', spy);
|
||||
element.on('$animate:close', spy);
|
||||
|
||||
$animate.addClass(element, 'on');
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
$animate.flush();
|
||||
expect(spy.callCount).toBe(1);
|
||||
|
||||
trackedAnimations[0]();
|
||||
$animate.flush();
|
||||
expect(spy.callCount).toBe(2);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('make sure that we can create an injector outside of tests', function() {
|
||||
|
||||
@@ -501,8 +501,7 @@ describe('ngView', function() {
|
||||
|
||||
$location.url('/foo');
|
||||
$rootScope.$digest();
|
||||
// using toMatch because in IE8+jquery the space doesn't get preserved. jquery bug?
|
||||
expect(element.text()).toMatch(/\s*WORKS/);
|
||||
expect(element.text()).toEqual(' \n WORKS');
|
||||
|
||||
var div = element.find('div');
|
||||
expect(div.parent()[0].nodeName.toUpperCase()).toBeOneOf('NG:VIEW', 'VIEW');
|
||||
@@ -713,7 +712,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$location.path('/');
|
||||
$rootScope.$digest();
|
||||
@@ -777,7 +776,7 @@ describe('ngView animations', function() {
|
||||
expect($animate.queue.shift().event).toBe('addClass');
|
||||
expect($animate.queue.shift().event).toBe('removeClass');
|
||||
|
||||
$animate.triggerReflow();
|
||||
$animate.flush();
|
||||
|
||||
expect(item.hasClass('classy')).toBe(false);
|
||||
expect(item.hasClass('boring')).toBe(true);
|
||||
@@ -915,7 +914,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
@@ -929,7 +928,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
@@ -942,7 +941,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
@@ -956,7 +955,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
@@ -973,7 +972,7 @@ describe('ngView animations', function() {
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect($animate.enter).toHaveBeenCalledOnce();
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
|
||||
@@ -20,6 +20,15 @@ describe('linky', function() {
|
||||
expect(linky(undefined)).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should be case-insensitive', function() {
|
||||
expect(linky('WWW.example.com')).toEqual('<a href="http://WWW.example.com">WWW.example.com</a>');
|
||||
expect(linky('WWW.EXAMPLE.COM')).toEqual('<a href="http://WWW.EXAMPLE.COM">WWW.EXAMPLE.COM</a>');
|
||||
expect(linky('HTTP://www.example.com')).toEqual('<a href="HTTP://www.example.com">HTTP://www.example.com</a>');
|
||||
expect(linky('HTTP://example.com')).toEqual('<a href="HTTP://example.com">HTTP://example.com</a>');
|
||||
expect(linky('HTTPS://www.example.com')).toEqual('<a href="HTTPS://www.example.com">HTTPS://www.example.com</a>');
|
||||
expect(linky('HTTPS://example.com')).toEqual('<a href="HTTPS://example.com">HTTPS://example.com</a>');
|
||||
});
|
||||
|
||||
it('should handle www.', function() {
|
||||
expect(linky('www.example.com')).toEqual('<a href="http://www.example.com">www.example.com</a>');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user