Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eba192b863 | |||
| 75099e6137 | |||
| 172a40931b | |||
| 23e5109b64 | |||
| cc84ce3bf5 | |||
| bee2d1fbb9 | |||
| 7101a02c93 | |||
| 888be00712 | |||
| 05597c24c7 | |||
| bf55f23325 | |||
| ab051e78ea | |||
| 87d46a84c3 | |||
| ae764f1844 | |||
| ad8092ed80 | |||
| 55e1b3e1c8 | |||
| 6f465a2b26 | |||
| 3ecac62251 | |||
| c64610269d | |||
| 5c2302949b | |||
| 7c84e2632f | |||
| 18d18f07db | |||
| 9f5be534fc | |||
| 1cd7912614 | |||
| 514da451fc | |||
| 2788cc4e12 | |||
| 7f6322df6a | |||
| 5bd8613168 | |||
| 32b507890e | |||
| bfedafdede | |||
| cdefbe3425 | |||
| f75f4bce82 | |||
| 4349de3d41 | |||
| df545d7eed | |||
| 3b5f346314 | |||
| 3aab87b381 | |||
| 0973175058 | |||
| 112da45c07 | |||
| e3dc85841d | |||
| ef1c352bc9 | |||
| a5b6444324 | |||
| dd18c00b1d | |||
| a0fad24dc2 | |||
| da0e3c99f5 | |||
| a41c58e285 | |||
| bce5b49133 | |||
| 816b84230c | |||
| 873acf8fab | |||
| 9063a0c2e7 | |||
| 03cbc0d6b1 | |||
| 931789ec14 | |||
| 9bc807783f | |||
| 2d6ee651b1 | |||
| 7ca24a8264 | |||
| 1d8e42070a | |||
| fe6b2fbfc4 | |||
| 5a222244fb | |||
| 4026074aba | |||
| d9a596addd | |||
| 8c0898b21c | |||
| d9b693bb7a | |||
| da94ab2e63 | |||
| 2fd8dc7061 | |||
| 01012a4d7a | |||
| ce84429adf | |||
| a26acb64fe | |||
| 7088ed1ed3 | |||
| 7027844d42 | |||
| 16c584ed7f |
+8
-3
@@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.10
|
||||
- '0.10'
|
||||
|
||||
branches:
|
||||
except:
|
||||
@@ -19,8 +19,13 @@ env:
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
|
||||
|
||||
install:
|
||||
- npm config set registry http://23.251.144.68
|
||||
- npm install
|
||||
# - 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
|
||||
# Run npm install twice, because it is flaky.
|
||||
- npm install || npm install
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
|
||||
+543
@@ -1,3 +1,546 @@
|
||||
|
||||
<a name="1.3.0-beta.15"></a>
|
||||
# 1.3.0-beta.15 unbelievable-advancement (2014-07-11)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ensure that parallel class-based animations are all eventually closed
|
||||
([f07af61f](https://github.com/angular/angular.js/commit/f07af61f050fcdcece15c13ee8c6a6d32f86d3a1),
|
||||
[#7766](https://github.com/angular/angular.js/issues/7766))
|
||||
- remove the ng-animate className after canceling animation
|
||||
([e18db78d](https://github.com/angular/angular.js/commit/e18db78d7793b1e94d9b19ac15b89d39f21a5729),
|
||||
[#7784](https://github.com/angular/angular.js/issues/7784), [#7801](https://github.com/angular/angular.js/issues/7801), [#7894](https://github.com/angular/angular.js/issues/7894))
|
||||
- **$http:**
|
||||
- don't remove content-type header if data is set by request transform
|
||||
([c7c363cf](https://github.com/angular/angular.js/commit/c7c363cf8d4533f94c5534c83dd1c7135633ddd8),
|
||||
[#7910](https://github.com/angular/angular.js/issues/7910))
|
||||
- add ability to remove default headers
|
||||
([172a4093](https://github.com/angular/angular.js/commit/172a40931be5fe47e7732e5ba173895a1d59c5cd),
|
||||
[#5784](https://github.com/angular/angular.js/issues/5784))
|
||||
- **$location:** remove query args when passed in object
|
||||
([2c7d0857](https://github.com/angular/angular.js/commit/2c7d0857ccbdb3a0967acc20e4346a7e1a6be792),
|
||||
[#6565](https://github.com/angular/angular.js/issues/6565))
|
||||
- **input:**
|
||||
- escape forward slash in email regexp
|
||||
([a88c215f](https://github.com/angular/angular.js/commit/a88c215f17829c1cfdec36bc1ef40bae10c41dff),
|
||||
[#8096](https://github.com/angular/angular.js/issues/8096))
|
||||
- modify email validation regexp to match rfc1035
|
||||
([af6f943a](https://github.com/angular/angular.js/commit/af6f943a22f26cf2968f0ae3a1fab2fd09b52a2b),
|
||||
[#6026](https://github.com/angular/angular.js/issues/6026))
|
||||
- **jqLite:**
|
||||
- correctly dealoc svg elements in IE
|
||||
([012ab1f8](https://github.com/angular/angular.js/commit/012ab1f8745c8985d3f132c2dfa8fd84e7dc7041))
|
||||
- remove exposed dealoc method
|
||||
([9c5b407f](https://github.com/angular/angular.js/commit/9c5b407fd1e296dd525c129743f2b2b47da4dc0d))
|
||||
- **ngModel:** test & update correct model when running $validate
|
||||
([f3cb2741](https://github.com/angular/angular.js/commit/f3cb2741161353f387d02725637ce4ba062a9bc0),
|
||||
[#7836](https://github.com/angular/angular.js/issues/7836), [#7837](https://github.com/angular/angular.js/issues/7837))
|
||||
- **parseKeyValue:** ignore properties in prototype chain
|
||||
([cb42766a](https://github.com/angular/angular.js/commit/cb42766a14f8123aa288b6e20f879141970fb84d),
|
||||
[#8070](https://github.com/angular/angular.js/issues/8070), [#8068](https://github.com/angular/angular.js/issues/8068))
|
||||
- **select:** auto-select new option that is marked as selected
|
||||
([b8ae73e1](https://github.com/angular/angular.js/commit/b8ae73e17c19d9aebf572a75c05a7d981dcac807),
|
||||
[#6828](https://github.com/angular/angular.js/issues/6828))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$animate:** allow directives to cancel animation events
|
||||
([ca752790](https://github.com/angular/angular.js/commit/ca752790d95480b7ad1125a7ddb52b726b987a24),
|
||||
[#7722](https://github.com/angular/angular.js/issues/7722))
|
||||
- **$controller:** disable using global controller constructors
|
||||
([3f2232b5](https://github.com/angular/angular.js/commit/3f2232b5a181512fac23775b1df4a6ebda67d018))
|
||||
- **FormController:** add `$rollbackViewValue` to rollback all controls
|
||||
([85b77314](https://github.com/angular/angular.js/commit/85b77314ed8e4b45d7365a24a47349ed94672aeb),
|
||||
[#7595](https://github.com/angular/angular.js/issues/7595))
|
||||
- **input:** support constant expressions for ngTrueValue/ngFalseValue
|
||||
([c90cefe1](https://github.com/angular/angular.js/commit/c90cefe16142d973a123e945fc9058e8a874c357),
|
||||
[#8041](https://github.com/angular/angular.js/issues/8041), [#5346](https://github.com/angular/angular.js/issues/5346), [#1199](https://github.com/angular/angular.js/issues/1199))
|
||||
- **ngAnimate:** conditionally allow child animations to run in parallel with parent animations
|
||||
([8252b8be](https://github.com/angular/angular.js/commit/8252b8be946367f1759065adf528adc908da00a2),
|
||||
[#7946](https://github.com/angular/angular.js/issues/7946))
|
||||
- **ngModel:** bind to getters/setters
|
||||
([b9fcf017](https://github.com/angular/angular.js/commit/b9fcf017316d37e91959949f56692644ce09d54a),
|
||||
[#768](https://github.com/angular/angular.js/issues/768))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$compile:** no longer need nodeType filter when setting $scope data
|
||||
([b0ca5195](https://github.com/angular/angular.js/commit/b0ca5195e88a42611e933c49d7d2768b181b2d1b),
|
||||
[#7887](https://github.com/angular/angular.js/issues/7887))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$controller:** due to [3f2232b5](https://github.com/angular/angular.js/commit/3f2232b5a181512fac23775b1df4a6ebda67d018),
|
||||
|
||||
`$controller` will no longer look for controllers on `window`.
|
||||
The old behavior of looking on `window` for controllers was originally intended
|
||||
for use in examples, demos, and toy apps. We found that allowing global controller
|
||||
functions encouraged poor practices, so we resolved to disable this behavior by
|
||||
default.
|
||||
|
||||
To migrate, register your controllers with modules rather than exposing them
|
||||
as globals:
|
||||
|
||||
Before:
|
||||
|
||||
```javascript
|
||||
function MyController() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```javascript
|
||||
angular.module('myApp', []).controller('MyController', [function() {
|
||||
// ...
|
||||
}]);
|
||||
```
|
||||
|
||||
Although it's not recommended, you can re-enable the old behavior like this:
|
||||
|
||||
```javascript
|
||||
angular.module('myModule').config(['$controllerProvider', function($controllerProvider) {
|
||||
// this option might be handy for migrating old apps, but please don't use it
|
||||
// in new ones!
|
||||
$controllerProvider.allowGlobals();
|
||||
}]);
|
||||
```
|
||||
- **input:** due to [c90cefe1](https://github.com/angular/angular.js/commit/c90cefe16142d973a123e945fc9058e8a874c357),
|
||||
|
||||
|
||||
Previously, these attributes would always be treated as strings. However, they are now parsed as
|
||||
expressions, and will throw if an expression is non-constant.
|
||||
|
||||
To convert non-constant strings into constant expressions, simply wrap them in an extra pair of quotes, like so:
|
||||
|
||||
<input type="checkbox" ng-model="..." ng-true-value="'truthyValue'">
|
||||
|
||||
Closes #8041
|
||||
Closes #5346
|
||||
Closes #1199
|
||||
|
||||
<a name="1.2.20"></a>
|
||||
# 1.2.20 accidental-beautification (2014-07-11)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$http:**
|
||||
- don't remove content-type header if data is set by request transform
|
||||
([7027844d](https://github.com/angular/angular.js/commit/7027844d42cd428cb799f38f9e9b303da013ac4f),
|
||||
[#7910](https://github.com/angular/angular.js/issues/7910))
|
||||
- add ability to remove default headers
|
||||
([172a4093](https://github.com/angular/angular.js/commit/172a40931be5fe47e7732e5ba173895a1d59c5cd),
|
||||
[#5784](https://github.com/angular/angular.js/issues/5784))
|
||||
- **$location:** remove query args when passed in object
|
||||
([a26acb64](https://github.com/angular/angular.js/commit/a26acb64fe2ed3e05bf21ac1c058d6ac59b89870),
|
||||
[#6565](https://github.com/angular/angular.js/issues/6565))
|
||||
- **input:**
|
||||
- escape forward slash in email regexp
|
||||
([da0e3c99](https://github.com/angular/angular.js/commit/da0e3c99f51c196f58758841d4d8492a9fa09e20),
|
||||
[#8096](https://github.com/angular/angular.js/issues/8096))
|
||||
- modify email validation regexp to match rfc1035
|
||||
([816b8423](https://github.com/angular/angular.js/commit/816b84230cdd8273ba19e8dec3b6f2e800f76612),
|
||||
[#6026](https://github.com/angular/angular.js/issues/6026))
|
||||
- **parseKeyValue:** ignore properties in prototype chain
|
||||
([873acf8f](https://github.com/angular/angular.js/commit/873acf8fab3eb41914920259e713e1916e3c4f38),
|
||||
[#8070](https://github.com/angular/angular.js/issues/8070), [#8068](https://github.com/angular/angular.js/issues/8068))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **ngAnimate:** conditionally allow child animations to run in parallel with parent animations
|
||||
([931789ec](https://github.com/angular/angular.js/commit/931789ec1476e1d06739e63cb423eb87172b5ebc),
|
||||
[#7946](https://github.com/angular/angular.js/issues/7946))
|
||||
|
||||
|
||||
<a name="1.3.0-beta.14"></a>
|
||||
# 1.3.0-beta.14 harmonious-cacophonies (2014-06-30)
|
||||
|
||||
|
||||
This release contains security fixes for $parse that prevent arbitrary code execution via Angular
|
||||
expressions under some very specific conditions. The only applications affected by these
|
||||
vulnerabilities are those that match all of the following conditions:
|
||||
|
||||
- application mixes server-side and client-side templating
|
||||
- the server-side templating contains XSS vulnerabilities
|
||||
- the vulnerabilities in the server-side templating are being guarded by server-side XSS filters or
|
||||
on the client-side via [CSP](http://en.wikipedia.org/wiki/Content_Security_Policy)
|
||||
- the server-side XSS vulnerabilities can be used to augment the client-side template processed by
|
||||
Angular
|
||||
|
||||
Applications not meeting all of the conditions are not vulnerable.
|
||||
|
||||
This fix is in both 1.3.0-beta.14 and 1.2.19 release.
|
||||
|
||||
The Angular team would like to thank [Jann Horn](http://thejh.net) for reporting these
|
||||
vulnerabilities via [security@angularjs.org].
|
||||
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** bind ng-attr-* even if unbound attribute follows ng-attr-*
|
||||
([8b0258d8](https://github.com/angular/angular.js/commit/8b0258d878cac20cd25c0958fd6e136a08b97df6),
|
||||
[#7739](https://github.com/angular/angular.js/issues/7739))
|
||||
- **$http:**
|
||||
- should not read statusText on IE<10 when request is aborted
|
||||
([31ae3e71](https://github.com/angular/angular.js/commit/31ae3e71647eadbbe1df40f9dedb55e1e0715f98))
|
||||
- add the PATCH shortcut back
|
||||
([b28b5caa](https://github.com/angular/angular.js/commit/b28b5caab1529b3970f10f0a4de43c0c975e3886),
|
||||
[#5894](https://github.com/angular/angular.js/issues/5894))
|
||||
- **$injector:** check if a fn is an array explicitly
|
||||
([b1a6baac](https://github.com/angular/angular.js/commit/b1a6baac2de84a1ecdc000085e8bbd016eb5c100),
|
||||
[#7904](https://github.com/angular/angular.js/issues/7904), [#2653](https://github.com/angular/angular.js/issues/2653))
|
||||
- **$interval:** when canceling, use clearInterval from $window instead of global scope.
|
||||
([a4904c0f](https://github.com/angular/angular.js/commit/a4904c0f83838222b98a875c56779a7f1a4a650a))
|
||||
- **$parse:**
|
||||
- prevent invocation of Function's bind, call and apply
|
||||
([77ada4c8](https://github.com/angular/angular.js/commit/77ada4c82d6b8fc6d977c26f3cdb48c2f5fbe5a5))
|
||||
- forbid __proto__ properties in angular expressions
|
||||
([6081f207](https://github.com/angular/angular.js/commit/6081f20769e64a800ee8075c168412b21f026d99))
|
||||
- forbid __{define,lookup}{Getter,Setter}__ properties
|
||||
([48fa3aad](https://github.com/angular/angular.js/commit/48fa3aadd546036c7e69f71046f659ab1de244c6))
|
||||
- forbid referencing Object in angular expressions
|
||||
([528be29d](https://github.com/angular/angular.js/commit/528be29d1662122a34e204dd607e1c0bd9c16bbc))
|
||||
- handle constants as one-time binding expressions
|
||||
([d9763f1b](https://github.com/angular/angular.js/commit/d9763f1bd355190b9d4e5723e4632cbc232f0543),
|
||||
[#7970](https://github.com/angular/angular.js/issues/7970))
|
||||
- **$timeout/$interval:** if invokeApply is false, do not use evalAsync
|
||||
([19b6b343](https://github.com/angular/angular.js/commit/19b6b3433ae9f8523cbc72ae97dbcf0c06960148),
|
||||
[#7999](https://github.com/angular/angular.js/issues/7999), [#7103](https://github.com/angular/angular.js/issues/7103))
|
||||
- **Angular:** nodeName should always be lowercase
|
||||
([dafb8a3c](https://github.com/angular/angular.js/commit/dafb8a3cd12e7c3247838f536c25eb796331658d),
|
||||
[#3987](https://github.com/angular/angular.js/issues/3987))
|
||||
- **Angular.copy:** preserve prototype chain when copying objects
|
||||
([b59b04f9](https://github.com/angular/angular.js/commit/b59b04f98a0b59eead53f6a53391ce1bbcbe9b57),
|
||||
[#5063](https://github.com/angular/angular.js/issues/5063), [#3767](https://github.com/angular/angular.js/issues/3767), [#4996](https://github.com/angular/angular.js/issues/4996))
|
||||
- **core:** drop the toBoolean function
|
||||
([bdfc9c02](https://github.com/angular/angular.js/commit/bdfc9c02d021e08babfbc966a007c71b4946d69d),
|
||||
[#3969](https://github.com/angular/angular.js/issues/3969), [#4277](https://github.com/angular/angular.js/issues/4277), [#7960](https://github.com/angular/angular.js/issues/7960))
|
||||
- **injector:** allow multiple loading of function modules
|
||||
([2f0a4488](https://github.com/angular/angular.js/commit/2f0a4488731fdb0e8217325dbb52a576defd09bd),
|
||||
[#7255](https://github.com/angular/angular.js/issues/7255))
|
||||
- **input:**
|
||||
- improve html5 validation support
|
||||
([1f6a5a1a](https://github.com/angular/angular.js/commit/1f6a5a1a9255a2db19a1ea4c04cdbcdbb2850b6c),
|
||||
[#7936](https://github.com/angular/angular.js/issues/7936), [#7937](https://github.com/angular/angular.js/issues/7937))
|
||||
- escape forward slash in email regexp
|
||||
([b775e2bc](https://github.com/angular/angular.js/commit/b775e2bca1093e9df62a269b5bda968555ea0ded),
|
||||
[#7938](https://github.com/angular/angular.js/issues/7938))
|
||||
- **jqLite:**
|
||||
- never add to the cache for non-element/document nodes
|
||||
([91754a76](https://github.com/angular/angular.js/commit/91754a76e0ef9a7456a5b9819d1c5807c0a575bb),
|
||||
[#7966](https://github.com/angular/angular.js/issues/7966))
|
||||
- don't attach event handlers to comments or text nodes
|
||||
([462dbb20](https://github.com/angular/angular.js/commit/462dbb2016a218d84760b6da171f1b15c9e416c3),
|
||||
[#7913](https://github.com/angular/angular.js/issues/7913), [#7942](https://github.com/angular/angular.js/issues/7942))
|
||||
- convert NodeList to an Array to make PhantomJS 1.x happy
|
||||
([ceaea861](https://github.com/angular/angular.js/commit/ceaea861ebec957c99bbca6fd88ed33fbc15afbf),
|
||||
[#7851](https://github.com/angular/angular.js/issues/7851))
|
||||
- **numberFilter:** correctly round fractions despite floating-point arithmetics issues in JS
|
||||
([189cd064](https://github.com/angular/angular.js/commit/189cd064feeb710fe54ee2ca83449b3eaf82b403),
|
||||
[#7870](https://github.com/angular/angular.js/issues/7870), [#7878](https://github.com/angular/angular.js/issues/7878))
|
||||
- **testabilityPatch:** fix invocations of angular.mock.dump
|
||||
([e8e07502](https://github.com/angular/angular.js/commit/e8e07502776e48bf48b83a836f7422d164cbb1d7))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **NgModel:**
|
||||
- port the email input type to use the validators pipeline
|
||||
([67379242](https://github.com/angular/angular.js/commit/6737924210570e8369ab72415e3098c6df4d3f6b))
|
||||
- port the URL input type to use the validators pipeline
|
||||
([3ee65730](https://github.com/angular/angular.js/commit/3ee65730639fc61d76e1055a6ca74e35eb48b838))
|
||||
- **jqLite:** support isDefaultPrevented for triggerHandler dummies
|
||||
([7e71acd1](https://github.com/angular/angular.js/commit/7e71acd1781ed44a7306d94338388c90f4420a24),
|
||||
[#8008](https://github.com/angular/angular.js/issues/8008))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **forEach:** use native for loop instead of forEach for Arrays
|
||||
([36625de0](https://github.com/angular/angular.js/commit/36625de0d3ebc1fc091af474d942c6ce16b0a1c0))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$parse:**
|
||||
- due to [77ada4c8](https://github.com/angular/angular.js/commit/77ada4c82d6b8fc6d977c26f3cdb48c2f5fbe5a5),
|
||||
|
||||
You can no longer invoke .bind, .call or .apply on a function in angular expressions.
|
||||
This is to disallow changing the behaviour of existing functions
|
||||
in an unforseen fashion.
|
||||
- due to [6081f207](https://github.com/angular/angular.js/commit/6081f20769e64a800ee8075c168412b21f026d99),
|
||||
|
||||
The (deprecated) __proto__ propery does not work inside angular expressions
|
||||
anymore.
|
||||
- due to [48fa3aad](https://github.com/angular/angular.js/commit/48fa3aadd546036c7e69f71046f659ab1de244c6),
|
||||
|
||||
This prevents the use of __{define,lookup}{Getter,Setter}__ inside angular
|
||||
expressions. If you really need them for some reason, please wrap/bind them to make them
|
||||
less dangerous, then make them available through the scope object.
|
||||
- due to [528be29d](https://github.com/angular/angular.js/commit/528be29d1662122a34e204dd607e1c0bd9c16bbc),
|
||||
|
||||
This prevents the use of `Object` inside angular expressions.
|
||||
If you need Object.keys, make it accessible in the scope.
|
||||
- **Angular.copy:** due to [b59b04f9](https://github.com/angular/angular.js/commit/b59b04f98a0b59eead53f6a53391ce1bbcbe9b57),
|
||||
|
||||
|
||||
This changes `angular.copy` so that it applies the prototype of the original
|
||||
object to the copied object. Previously, `angular.copy` would copy properties
|
||||
of the original object's prototype chain directly onto the copied object.
|
||||
|
||||
This means that if you iterate over only the copied object's `hasOwnProperty`
|
||||
properties, it will no longer contain the properties from the prototype.
|
||||
This is actually much more reasonable behaviour and it is unlikely that
|
||||
applications are actually relying on this.
|
||||
|
||||
If this behaviour is relied upon, in an app, then one should simply iterate
|
||||
over all the properties on the object (and its inherited properties) and
|
||||
not filter them with `hasOwnProperty`.
|
||||
|
||||
**Be aware that this change also uses a feature that is not compatible with
|
||||
IE8.** If you need this to work on IE8 then you would need to provide a polyfill
|
||||
for `Object.create` and `Object.getPrototypeOf`.
|
||||
- **core:** due to [bdfc9c02](https://github.com/angular/angular.js/commit/bdfc9c02d021e08babfbc966a007c71b4946d69d),
|
||||
values 'f', '0', 'false', 'no', 'n', '[]' are no longer
|
||||
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
|
||||
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".
|
||||
|
||||
Closes #3969
|
||||
Closes #4277
|
||||
Closes #7960
|
||||
|
||||
<a name="1.2.19"></a>
|
||||
# 1.2.19 precognitive-flashbacks (2014-06-30)
|
||||
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** bind ng-attr-* even if unbound attribute follows ng-attr-*
|
||||
([ed59370d](https://github.com/angular/angular.js/commit/ed59370d805a88c9ac012a8e417faf2a9f902776))
|
||||
- **$http:** should not read statusText on IE<10 when request is aborted
|
||||
([0c80df21](https://github.com/angular/angular.js/commit/0c80df21b66f4b147b6b55c27ad794be5802b411))
|
||||
- **$injector:** check if a fn is an array explicitly
|
||||
([67c11b9a](https://github.com/angular/angular.js/commit/67c11b9a3914a24aaf72f36bbe038ba5efa7ddf3),
|
||||
[#7904](https://github.com/angular/angular.js/issues/7904), [#2653](https://github.com/angular/angular.js/issues/2653))
|
||||
- **$interval:** when canceling, use clearInterval from $window instead of global scope.
|
||||
([f780ccfa](https://github.com/angular/angular.js/commit/f780ccfa1c9a8d4c6191b0756ff77dc5749cf8c5))
|
||||
- **$parse:**
|
||||
- make the window check in ensureSafeObject IE8 friendly
|
||||
([ba62e975](https://github.com/angular/angular.js/commit/ba62e975f1a0cebf08dedbb1501f72b166af66db))
|
||||
- prevent invocation of Function's bind, call and apply
|
||||
([07fa87a8](https://github.com/angular/angular.js/commit/07fa87a8a82b8be155d8c898bb79e5d9277adfb4))
|
||||
- forbid __proto__ properties in angular expressions
|
||||
([cb713e60](https://github.com/angular/angular.js/commit/cb713e6045413a25b54ad3267476fa29efd70646))
|
||||
- forbid __{define,lookup}{Getter,Setter}__ properties
|
||||
([89ca8597](https://github.com/angular/angular.js/commit/89ca8597341aa5585bcf728fa677022b7ec9c071))
|
||||
- forbid referencing Object in angular expressions
|
||||
([bc6fb7cc](https://github.com/angular/angular.js/commit/bc6fb7cc94afddcb11b94f74d13812a6be1cdb64))
|
||||
- **injector:** allow multiple loading of function modules
|
||||
([d71f16e7](https://github.com/angular/angular.js/commit/d71f16e7459f1d3705ccf47a13227d4727be9670),
|
||||
[#7255](https://github.com/angular/angular.js/issues/7255))
|
||||
- **input:**
|
||||
- improve html5 validation support
|
||||
([ab2e83c8](https://github.com/angular/angular.js/commit/ab2e83c8c8fa60ca15b1a9539a6587dc363b20f1),
|
||||
[#7937](https://github.com/angular/angular.js/issues/7937), [#7957](https://github.com/angular/angular.js/issues/7957))
|
||||
- escape forward slash in email regexp
|
||||
([2a45cea0](https://github.com/angular/angular.js/commit/2a45cea0baaf615b799b54897bfe40d32381e7a2),
|
||||
[#7938](https://github.com/angular/angular.js/issues/7938))
|
||||
- **jqLite:** change expando property to a more unique name
|
||||
([74e1cc68](https://github.com/angular/angular.js/commit/74e1cc683be315f6db05e22e185b3d27460d132a))
|
||||
- **numberFilter:** correctly round fractions despite floating-point arithmetics issues in JS
|
||||
([e5f454c8](https://github.com/angular/angular.js/commit/e5f454c8afc15336dc1faa52704a483cedfacd4a),
|
||||
[#7870](https://github.com/angular/angular.js/issues/7870), [#7878](https://github.com/angular/angular.js/issues/7878))
|
||||
- **testabilityPatch:** fix invocations of angular.mock.dump
|
||||
([5e944a1c](https://github.com/angular/angular.js/commit/5e944a1cf1356bd069d3616f24323a0cb3ace87c))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **jqLite:** don't use reflection to access expandoId
|
||||
([a4faa5cd](https://github.com/angular/angular.js/commit/a4faa5cde722556bd41d75daf346c63a9b6962e9))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$parse:**
|
||||
- due to [07fa87a8](https://github.com/angular/angular.js/commit/07fa87a8a82b8be155d8c898bb79e5d9277adfb4),
|
||||
|
||||
You can no longer invoke .bind, .call or .apply on a function in angular expressions.
|
||||
This is to disallow changing the behaviour of existing functions
|
||||
in an unforseen fashion.
|
||||
- due to [cb713e60](https://github.com/angular/angular.js/commit/cb713e6045413a25b54ad3267476fa29efd70646),
|
||||
|
||||
The (deprecated) __proto__ propery does not work inside angular expressions
|
||||
anymore.
|
||||
- due to [89ca8597](https://github.com/angular/angular.js/commit/89ca8597341aa5585bcf728fa677022b7ec9c071),
|
||||
|
||||
This prevents the use of __{define,lookup}{Getter,Setter}__ inside angular
|
||||
expressions. If you really need them for some reason, please wrap/bind them to make them
|
||||
less dangerous, then make them available through the scope object.
|
||||
- due to [bc6fb7cc](https://github.com/angular/angular.js/commit/bc6fb7cc94afddcb11b94f74d13812a6be1cdb64),
|
||||
|
||||
This prevents the use of `Object` inside angular expressions.
|
||||
If you need Object.keys, make it accessible in the scope.
|
||||
|
||||
<a name="1.3.0-beta.13"></a>
|
||||
# 1.3.0-beta.13 idiosyncratic-numerification (2014-06-16)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **jqLite:** change expando property to a more unique name
|
||||
([20c3c9e2](https://github.com/angular/angular.js/commit/20c3c9e25f6417773333727549ed2ca2d3505b44))
|
||||
|
||||
|
||||
|
||||
<a name="1.3.0-beta.12"></a>
|
||||
# 1.3.0-beta.12 ephemeral-acceleration (2014-06-13)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- ensure transclude works at root of templateUrl
|
||||
([398053c5](https://github.com/angular/angular.js/commit/398053c56352487751d14ea41b3b892960397019),
|
||||
[#7183](https://github.com/angular/angular.js/issues/7183), [#7772](https://github.com/angular/angular.js/issues/7772))
|
||||
- always error if two directives add isolate-scope and new-scope
|
||||
([2cde927e](https://github.com/angular/angular.js/commit/2cde927e58c8d1588569d94a797e43cdfbcedaf9),
|
||||
[#4402](https://github.com/angular/angular.js/issues/4402), [#4421](https://github.com/angular/angular.js/issues/4421))
|
||||
- **$injector:** report circularity in circular dependency error message
|
||||
([545d22b4](https://github.com/angular/angular.js/commit/545d22b47006c1efa420ba551d4850affdba8016),
|
||||
[#7500](https://github.com/angular/angular.js/issues/7500))
|
||||
- **$parse:** Handle one-time to `null`
|
||||
([600a41a7](https://github.com/angular/angular.js/commit/600a41a7b65f2dd139664fca6331c40451db75be),
|
||||
[#7743](https://github.com/angular/angular.js/issues/7743), [#7787](https://github.com/angular/angular.js/issues/7787))
|
||||
- **NgModel:**
|
||||
- ensure pattern and ngPattern use the same validator
|
||||
([1be9bb9d](https://github.com/angular/angular.js/commit/1be9bb9d3527e0758350c4f7417a4228d8571440))
|
||||
- make ngMinlength and ngMaxlength as standalone directives
|
||||
([26d91b65](https://github.com/angular/angular.js/commit/26d91b653ac224d9d4166fea855346f5e4c4a7b4),
|
||||
[#6750](https://github.com/angular/angular.js/issues/6750))
|
||||
- make sure the ngMinlength and ngMaxlength validators use the $validators pipeline
|
||||
([5b8e7ecf](https://github.com/angular/angular.js/commit/5b8e7ecfeb722cfc7a5d92f05b57950a2aa6158b),
|
||||
[#6304](https://github.com/angular/angular.js/issues/6304))
|
||||
- make sure the pattern validator uses the $validators pipeline
|
||||
([e63d4253](https://github.com/angular/angular.js/commit/e63d4253d06ed7d344358e2c0b03311c548bc978))
|
||||
- make sure the required validator uses the $validators pipeline
|
||||
([e53554a0](https://github.com/angular/angular.js/commit/e53554a0e238cba7a150fd7ccf61e5e4cc0c0426),
|
||||
[#5164](https://github.com/angular/angular.js/issues/5164))
|
||||
- **jqLite:** data should store data only on Element and Document nodes
|
||||
([a196c8bc](https://github.com/angular/angular.js/commit/a196c8bca82a28c08896d31f1863cf4ecd11401c))
|
||||
- **ngResource:** don't convert literal values into Resource objects when isArray is true
|
||||
([16dfcb61](https://github.com/angular/angular.js/commit/16dfcb61aed28cdef3bfbed540e2deea6d9e9632),
|
||||
[#6314](https://github.com/angular/angular.js/issues/6314), [#7741](https://github.com/angular/angular.js/issues/7741))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **NgModel:** introduce the $validators pipeline
|
||||
([a8c7cb81](https://github.com/angular/angular.js/commit/a8c7cb81c9e67b52d5c649bf3d8cec06c5976852))
|
||||
- **attrs:** trigger observers for specific ng-attributes
|
||||
([d9b90d7c](https://github.com/angular/angular.js/commit/d9b90d7c10a8e1bacbee0aeb7e86093cca9e8ed2),
|
||||
[#7758](https://github.com/angular/angular.js/issues/7758))
|
||||
- **input:** add $touched and $untouched states
|
||||
([adcc5a00](https://github.com/angular/angular.js/commit/adcc5a00bf582d2b291c18e99093bb0854f7217c))
|
||||
- **ngInclude:** emit $includeContentError when HTTP request fails
|
||||
([e4419daf](https://github.com/angular/angular.js/commit/e4419daf705d6d2d116ced573f72c24b5c53be1f),
|
||||
[#5803](https://github.com/angular/angular.js/issues/5803))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$compile:** move ng-binding class stamping for interpolation into compile phase
|
||||
([35358fdd](https://github.com/angular/angular.js/commit/35358fddc10652ef78c72cba7b7c2d5a810631d5))
|
||||
- **$http:** move xsrf cookie check to after cache check in $http
|
||||
([dd1d189e](https://github.com/angular/angular.js/commit/dd1d189ee785a37fe1d9bddf3818152db6aa210a),
|
||||
[#7717](https://github.com/angular/angular.js/issues/7717))
|
||||
- **Scope:** change Scope#id to be a simple number
|
||||
([8c6a8171](https://github.com/angular/angular.js/commit/8c6a8171f9bdaa5cdabc0cc3f7d3ce10af7b434d))
|
||||
- **forEach:** cache array length
|
||||
([55991e33](https://github.com/angular/angular.js/commit/55991e33af6fece07ea347a059da061b76fc95f5))
|
||||
- **isArray:** use native Array.isArray
|
||||
([751ebc17](https://github.com/angular/angular.js/commit/751ebc17f7fc7be26613db0a3cdee05fc401318b),
|
||||
[#7735](https://github.com/angular/angular.js/issues/7735))
|
||||
- **isWindow** optimize internal isWindow call
|
||||
([b68ac4cb](https://github.com/angular/angular.js/commit/b68ac4cb4c172447ba0022fe6e7ce0ca4cb9407e))
|
||||
- **jqLite:**
|
||||
- cache collection length for all methods that work on a single element
|
||||
([41d2eba5](https://github.com/angular/angular.js/commit/41d2eba5f8322903247280000bfc5e5e8a1c1a3e))
|
||||
- improve performance of jqLite#text
|
||||
([92489886](https://github.com/angular/angular.js/commit/92489886dcce3bca00fe827aeb0817297b8a175c))
|
||||
- optimize adding nodes to a jqLite collection
|
||||
([31faeaa7](https://github.com/angular/angular.js/commit/31faeaa7293716251ed437fa54432bb89d9d48de))
|
||||
- optimize element dealocation
|
||||
([e35abc9d](https://github.com/angular/angular.js/commit/e35abc9d2fac0471cbe8089dc0e33a72b8029ada))
|
||||
- don't use reflection to access expandoId
|
||||
([ea9a130a](https://github.com/angular/angular.js/commit/ea9a130a43d165f4f4389d01ac409dd3047efcb4))
|
||||
- **ngBind:** set the ng-binding class during compilation instead of linking
|
||||
([fd5f3896](https://github.com/angular/angular.js/commit/fd5f3896764107635310ae52df1d80a6e08fba31))
|
||||
- **shallowCopy:** use Object.keys to improve performance
|
||||
([04468db4](https://github.com/angular/angular.js/commit/04468db44185e3d7968abdb23d77bf623cb5021b))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$compile:** due to [2cde927e](https://github.com/angular/angular.js/commit/2cde927e58c8d1588569d94a797e43cdfbcedaf9),
|
||||
|
||||
|
||||
Requesting isolate scope and any other scope on a single element is an error.
|
||||
Before this change, the compiler let two directives request a child scope
|
||||
and an isolate scope if the compiler applied them in the order of non-isolate
|
||||
scope directive followed by isolate scope directive.
|
||||
|
||||
Now the compiler will error regardless of the order.
|
||||
|
||||
If you find that your code is now throwing a `$compile:multidir` error,
|
||||
check that you do not have directives on the same element that are trying
|
||||
to request both an isolate and a non-isolate scope and fix your code.
|
||||
|
||||
Closes #4402
|
||||
Closes #4421
|
||||
- **NgModel:** due to [1be9bb9d](https://github.com/angular/angular.js/commit/1be9bb9d3527e0758350c4f7417a4228d8571440),
|
||||
|
||||
|
||||
If an expression is used on ng-pattern (such as `ng-pattern="exp"`) or on the
|
||||
pattern attribute (something like on `pattern="{{ exp }}"`) and the expression
|
||||
itself evaluates to a string then the validator will not parse the string as a
|
||||
literal regular expression object (a value like `/abc/i`). Instead, the entire
|
||||
string will be created as the regular expression to test against. This means
|
||||
that any expression flags will not be placed on the RegExp object. To get around
|
||||
this limitation, use a regular expression object as the value for the expression.
|
||||
|
||||
//before
|
||||
$scope.exp = '/abc/i';
|
||||
|
||||
//after
|
||||
$scope.exp = /abc/i;
|
||||
- **Scope:** due to [8c6a8171](https://github.com/angular/angular.js/commit/8c6a8171f9bdaa5cdabc0cc3f7d3ce10af7b434d),
|
||||
Scope#$id is now of time number rather than string. Since the
|
||||
id is primarily being used for debugging purposes this change should not affect
|
||||
anyone.
|
||||
- **forEach:** due to [55991e33](https://github.com/angular/angular.js/commit/55991e33af6fece07ea347a059da061b76fc95f5),
|
||||
forEach will iterate only over the initial number of items in
|
||||
the array. So if items are added to the array during the iteration, these won't
|
||||
be iterated over during the initial forEach call.
|
||||
|
||||
This change also makes our forEach behave more like Array#forEach.
|
||||
- **jqLite:** due to [a196c8bc](https://github.com/angular/angular.js/commit/a196c8bca82a28c08896d31f1863cf4ecd11401c),
|
||||
previously it was possible to set jqLite data on Text/Comment
|
||||
nodes, but now that is allowed only on Element and Document nodes just like in
|
||||
jQuery. We don't expect that app code actually depends on this accidental feature.
|
||||
|
||||
|
||||
|
||||
<a name="1.2.18"></a>
|
||||
# 1.2.18 ear-extendability (2014-06-13)
|
||||
|
||||
|
||||
@@ -107,6 +107,9 @@ module.exports = function(grunt) {
|
||||
options: {
|
||||
jshintrc: true,
|
||||
},
|
||||
tests: {
|
||||
files: { src: 'test/**/*.js' },
|
||||
},
|
||||
ng: {
|
||||
files: { src: files['angularSrc'] },
|
||||
},
|
||||
|
||||
@@ -211,6 +211,10 @@ code.highlighted {
|
||||
color:maroon;
|
||||
}
|
||||
|
||||
ul + p {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.docs-version-jump {
|
||||
min-width:100%;
|
||||
max-width:100%;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
@ngdoc error
|
||||
@name $parse:isecobj
|
||||
@fullName Referencing Object Disallowed
|
||||
@description
|
||||
|
||||
Occurs when an expression attempts to access the 'Object' object (Root object in JavaScript).
|
||||
|
||||
Angular bans access to Object from within expressions since access is a known way to modify
|
||||
the behaviour of existing objects.
|
||||
|
||||
To resolve this error, avoid Object access.
|
||||
@@ -161,7 +161,7 @@ In this second scenario, we are already inside a `$digest` when the ngFocus dire
|
||||
call to `$apply()`, causing this error to be thrown.
|
||||
|
||||
It is possible to workaround this problem by moving the call to set the focus outside of the digest,
|
||||
by using `$timeOut(fn, 0, false)`, where the `false` value tells Angular not to wrap this `fn` in a
|
||||
by using `$timeout(fn, 0, false)`, where the `false` value tells Angular not to wrap this `fn` in a
|
||||
`$apply` block:
|
||||
|
||||
```
|
||||
|
||||
@@ -15,9 +15,9 @@ By default, only URLs that belong to the same origin are trusted. These are urls
|
||||
The {@link ng.directive:ngInclude ngInclude} directive and {@link guide/directive directives} that specify a `templateUrl` require a trusted resource URL.
|
||||
|
||||
To load templates from other domains and/or protocols, either adjust the {@link
|
||||
api/ng.$sceDelegateProvider#resourceUrlWhitelist whitelist}/ {@link
|
||||
api/ng.$sceDelegateProvider#resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
|
||||
api/ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl}.
|
||||
ng.$sceDelegateProvider#resourceUrlWhitelist whitelist}/ {@link
|
||||
ng.$sceDelegateProvider#resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
|
||||
ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl}.
|
||||
|
||||
**Note**: The browser's [Same Origin
|
||||
Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) and
|
||||
|
||||
@@ -622,23 +622,24 @@ The Angular's compiler currently does not support two-way binding for methods (s
|
||||
to the $location object (using {@link input[text] ngModel} directive on an input
|
||||
field), you will need to specify an extra model property (e.g. `locationPath`) with two {@link ng.$rootScope.Scope#$watch $watchers}
|
||||
which push $location updates in both directions. For example:
|
||||
<example>
|
||||
<example module="locationExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="LocationController">
|
||||
<input type="text" ng-model="locationPath" />
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function LocationController($scope, $location) {
|
||||
$scope.$watch('locationPath', function(path) {
|
||||
$location.path(path);
|
||||
});
|
||||
$scope.$watch(function() {
|
||||
return $location.path();
|
||||
}, function(path) {
|
||||
$scope.locationPath = path;
|
||||
});
|
||||
}
|
||||
angular.module('locationExample', [])
|
||||
.controller('LocationController', ['$scope', '$location', function ($scope, $location) {
|
||||
$scope.$watch('locationPath', function(path) {
|
||||
$location.path(path);
|
||||
});
|
||||
$scope.$watch(function() {
|
||||
return $location.path();
|
||||
}, function(path) {
|
||||
$scope.locationPath = path;
|
||||
});
|
||||
}]);
|
||||
</file>
|
||||
</example>
|
||||
|
||||
|
||||
@@ -37,27 +37,8 @@ The properties contain the **view model** (the model that will be presented by t
|
||||
`$scope` properties will be available to the template at the point in the DOM where the Controller
|
||||
is registered.
|
||||
|
||||
The following example shows a very simple constructor function for a Controller, `GreetingController`,
|
||||
which attaches a `greeting` property containing the string `'Hola!'` to the `$scope`:
|
||||
|
||||
```js
|
||||
function GreetingController($scope) {
|
||||
$scope.greeting = 'Hola!';
|
||||
}
|
||||
```
|
||||
|
||||
Once the Controller has been attached to the DOM, the `greeting` property can be data-bound to the
|
||||
template:
|
||||
|
||||
```js
|
||||
<div ng-controller="GreetingController">
|
||||
{{ greeting }}
|
||||
</div>
|
||||
```
|
||||
|
||||
**NOTE**: Although Angular allows you to create Controller functions in the global scope, this is
|
||||
not recommended. In a real application you should use the `.controller` method of your
|
||||
{@link module Angular Module} for your application as follows:
|
||||
The following example demonstrates creating a `GreetingController`, which attaches a `greeting`
|
||||
property containing the string `'Hola!'` to the `$scope`:
|
||||
|
||||
```js
|
||||
var myApp = angular.module('myApp',[]);
|
||||
@@ -67,9 +48,24 @@ myApp.controller('GreetingController', ['$scope', function($scope) {
|
||||
}]);
|
||||
```
|
||||
|
||||
We create an {@link module Angular Module}, `myApp`, for our application. Then we add the controller's
|
||||
constructor function to the module using the `.controller()` method. This keeps the controller's
|
||||
constructor function out of the global scope.
|
||||
|
||||
<div class="alert alert-info">
|
||||
We have used an **inline injection annotation** to explicitly specify the dependency
|
||||
of the Controller on the `$scope` service provided by Angular. See the guide on
|
||||
[Dependency Injection](http://docs.angularjs.org/guide/di) for more information.
|
||||
{@link guide/di Dependency Injection} for more information.
|
||||
</div>
|
||||
|
||||
We attach our controller to the DOM using the `ng-controller` directive. The `greeting` property can
|
||||
now be data-bound to the template:
|
||||
|
||||
```js
|
||||
<div ng-controller="GreetingController">
|
||||
{{ greeting }}
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
# Adding Behavior to a Scope Object
|
||||
@@ -333,6 +329,3 @@ describe('state', function() {
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -218,15 +218,22 @@ DI is pervasive throughout Angular. You can use it when defining components or w
|
||||
and `config` blocks for a module.
|
||||
|
||||
- Components such as services, directives, filters and animations are defined by an injectable factory
|
||||
method or constructor function. These components can be injected with "service" components as
|
||||
dependencies.
|
||||
|
||||
- The `run` and `config` methods accept a function, which can also be injected with "service"
|
||||
method or constructor function. These components can be injected with "service" and "value"
|
||||
components as dependencies.
|
||||
|
||||
- The `run` method accepts a function, which can be injected with "service", "value" and "constant"
|
||||
components as dependencies. Note that you cannot inject "providers" into `run` blocks.
|
||||
|
||||
- The `config` method accepts a function, which can be injected with "provider" and "constant"
|
||||
components as dependencies. Note that you cannot inject "service" or "value" components into
|
||||
configuration
|
||||
|
||||
- Controllers are defined by a constructor function, which can be injected with any of the "service"
|
||||
components as dependencies, but they can also be provided with special dependencies. See "DI in
|
||||
Controllers" below.
|
||||
and "value" components as dependencies, but they can also be provided with special dependencies. See
|
||||
{@link di#controllers Controllers} below for a list of these special dependencies.
|
||||
|
||||
See {@link module#module-loading-dependencies Modules} for more details about injecting dependencies
|
||||
into `run` and `config` blocks.
|
||||
|
||||
|
||||
### Factory Methods
|
||||
|
||||
@@ -50,9 +50,9 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
|
||||
|
||||
You can try evaluating different expressions here:
|
||||
|
||||
<example>
|
||||
<example module="expressionExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Cntl2" class="expressions">
|
||||
<div ng-controller="ExampleController" class="expressions">
|
||||
Expression:
|
||||
<input type='text' ng-model="expr" size="80"/>
|
||||
<button ng-click="addExp(expr)">Evaluate</button>
|
||||
@@ -66,23 +66,24 @@ You can try evaluating different expressions here:
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
function Cntl2($scope) {
|
||||
var exprs = $scope.exprs = [];
|
||||
$scope.expr = '3*10|currency';
|
||||
$scope.addExp = function(expr) {
|
||||
exprs.push(expr);
|
||||
};
|
||||
angular.module('expressionExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
var exprs = $scope.exprs = [];
|
||||
$scope.expr = '3*10|currency';
|
||||
$scope.addExp = function(expr) {
|
||||
exprs.push(expr);
|
||||
};
|
||||
|
||||
$scope.removeExp = function(index) {
|
||||
exprs.splice(index, 1);
|
||||
};
|
||||
}
|
||||
$scope.removeExp = function(index) {
|
||||
exprs.splice(index, 1);
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
it('should allow user expression testing', function() {
|
||||
element(by.css('.expressions button')).click();
|
||||
var lis = element(by.css('.expressions ul')).element.all(by.repeater('expr in exprs'));
|
||||
var lis = element(by.css('.expressions ul')).all(by.repeater('expr in exprs'));
|
||||
expect(lis.count()).toBe(1);
|
||||
expect(lis.get(0).getText()).toEqual('[ X ] 3*10|currency => $30.00');
|
||||
});
|
||||
@@ -101,9 +102,9 @@ This restriction is intentional. It prevents accidental access to the global sta
|
||||
Instead use services like `$window` and `$location` in functions called from expressions. Such services
|
||||
provide mockable access to globals.
|
||||
|
||||
<example>
|
||||
<example module="expressionExample">
|
||||
<file name="index.html">
|
||||
<div class="example2" ng-controller="Cntl1">
|
||||
<div class="example2" ng-controller="ExampleController">
|
||||
Name: <input ng-model="name" type="text"/>
|
||||
<button ng-click="greet()">Greet</button>
|
||||
<button ng-click="window.alert('Should not see me')">Won't greet</button>
|
||||
@@ -111,13 +112,14 @@ provide mockable access to globals.
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
function Cntl1($window, $scope){
|
||||
$scope.name = 'World';
|
||||
angular.module('expressionExample', [])
|
||||
.controller('ExampleController', ['$window', '$scope', function($window, $scope) {
|
||||
$scope.name = 'World';
|
||||
|
||||
$scope.greet = function() {
|
||||
$window.alert('Hello ' + $scope.name);
|
||||
};
|
||||
}
|
||||
$scope.greet = function() {
|
||||
$window.alert('Hello ' + $scope.name);
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
|
||||
@@ -16,9 +16,9 @@ The key directive in understanding two-way data-binding is {@link ng.directive:n
|
||||
The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
|
||||
In addition it provides an {@link ngModel.NgModelController API} for other directives to augment its behavior.
|
||||
|
||||
<example>
|
||||
<example module="formExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Controller">
|
||||
<div ng-controller="ExampleController">
|
||||
<form novalidate class="simple-form">
|
||||
Name: <input type="text" ng-model="user.name" /><br />
|
||||
E-mail: <input type="email" ng-model="user.email" /><br />
|
||||
@@ -32,19 +32,20 @@ In addition it provides an {@link ngModel.NgModelController API} for other direc
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function Controller($scope) {
|
||||
$scope.master = {};
|
||||
angular.module('formExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.master = {};
|
||||
|
||||
$scope.update = function(user) {
|
||||
$scope.master = angular.copy(user);
|
||||
};
|
||||
$scope.update = function(user) {
|
||||
$scope.master = angular.copy(user);
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
$scope.user = angular.copy($scope.master);
|
||||
};
|
||||
$scope.reset = function() {
|
||||
$scope.user = angular.copy($scope.master);
|
||||
};
|
||||
|
||||
$scope.reset();
|
||||
}
|
||||
$scope.reset();
|
||||
}]);
|
||||
</script>
|
||||
</file>
|
||||
</example>
|
||||
@@ -67,9 +68,9 @@ The following example uses the CSS to display validity of each form control.
|
||||
In the example both `user.name` and `user.email` are required, but are rendered with red background only when they are dirty.
|
||||
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.
|
||||
|
||||
<example>
|
||||
<example module="formExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Controller">
|
||||
<div ng-controller="ExampleController">
|
||||
<form novalidate class="css-form">
|
||||
Name:
|
||||
<input type="text" ng-model="user.name" required /><br />
|
||||
@@ -92,19 +93,20 @@ This ensures that the user is not distracted with an error until after interacti
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function Controller($scope) {
|
||||
$scope.master = {};
|
||||
angular.module('formExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.master = {};
|
||||
|
||||
$scope.update = function(user) {
|
||||
$scope.master = angular.copy(user);
|
||||
};
|
||||
$scope.update = function(user) {
|
||||
$scope.master = angular.copy(user);
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
$scope.user = angular.copy($scope.master);
|
||||
};
|
||||
$scope.reset = function() {
|
||||
$scope.user = angular.copy($scope.master);
|
||||
};
|
||||
|
||||
$scope.reset();
|
||||
}
|
||||
$scope.reset();
|
||||
}]);
|
||||
</script>
|
||||
</file>
|
||||
</example>
|
||||
@@ -130,7 +132,7 @@ This allows us to extend the above example with these features:
|
||||
- SAVE button is enabled only if form has some changes and is valid
|
||||
- custom error messages for `user.email` and `user.agree`
|
||||
|
||||
<example>
|
||||
<example module="formExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Controller">
|
||||
<form name="form" class="css-form" novalidate>
|
||||
@@ -159,23 +161,24 @@ This allows us to extend the above example with these features:
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
function Controller($scope) {
|
||||
$scope.master = {};
|
||||
angular.module('formExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.master = {};
|
||||
|
||||
$scope.update = function(user) {
|
||||
$scope.master = angular.copy(user);
|
||||
};
|
||||
$scope.update = function(user) {
|
||||
$scope.master = angular.copy(user);
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
$scope.user = angular.copy($scope.master);
|
||||
};
|
||||
$scope.reset = function() {
|
||||
$scope.user = angular.copy($scope.master);
|
||||
};
|
||||
|
||||
$scope.isUnchanged = function(user) {
|
||||
return angular.equals(user, $scope.master);
|
||||
};
|
||||
$scope.isUnchanged = function(user) {
|
||||
return angular.equals(user, $scope.master);
|
||||
};
|
||||
|
||||
$scope.reset();
|
||||
}
|
||||
$scope.reset();
|
||||
}]);
|
||||
</file>
|
||||
</example>
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ You write the following binding using the currency filter:
|
||||
|
||||
If your app is currently in the `en-US` locale, the browser will show `$1000.00`. If someone in the
|
||||
Japanese locale (`ja`) views your app, their browser will show a balance of `¥1000.00` instead.
|
||||
This is problematinc because $1000 is not the same as ¥1000.
|
||||
This is problematic because $1000 is not the same as ¥1000.
|
||||
|
||||
In this case, you need to override the default currency symbol by providing the
|
||||
{@link ng.filter:currency} currency filter with a currency symbol as a parameter.
|
||||
|
||||
@@ -42,15 +42,16 @@ arrangement isolates the controller from the directive as well as from DOM. This
|
||||
point since it makes the controllers view agnostic, which greatly improves the testing story of
|
||||
the applications.
|
||||
|
||||
<example>
|
||||
<example module="scopeExample">
|
||||
<file name="script.js">
|
||||
function MyController($scope) {
|
||||
$scope.username = 'World';
|
||||
angular.module('scopeExample', [])
|
||||
.controller('MyController', ['$scope', function($scope) {
|
||||
$scope.username = 'World';
|
||||
|
||||
$scope.sayHello = function() {
|
||||
$scope.greeting = 'Hello ' + $scope.username + '!';
|
||||
};
|
||||
}
|
||||
$scope.sayHello = function() {
|
||||
$scope.greeting = 'Hello ' + $scope.username + '!';
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
<file name="index.html">
|
||||
<div ng-controller="MyController">
|
||||
@@ -122,13 +123,13 @@ inheritance, and child scopes prototypically inherit from their parents.
|
||||
This example illustrates scopes in application, and prototypical inheritance of properties. The example is followed by
|
||||
a diagram depicting the scope boundaries.
|
||||
|
||||
<example>
|
||||
<example module="scopeExample">
|
||||
<file name="index.html">
|
||||
<div class="show-scope-demo">
|
||||
<div ng-controller="GreetCtrl">
|
||||
<div ng-controller="GreetController">
|
||||
Hello {{name}}!
|
||||
</div>
|
||||
<div ng-controller="ListCtrl">
|
||||
<div ng-controller="ListController">
|
||||
<ol>
|
||||
<li ng-repeat="name in names">{{name}} from {{department}}</li>
|
||||
</ol>
|
||||
@@ -136,14 +137,14 @@ a diagram depicting the scope boundaries.
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function GreetCtrl($scope, $rootScope) {
|
||||
$scope.name = 'World';
|
||||
$rootScope.department = 'Angular';
|
||||
}
|
||||
|
||||
function ListCtrl($scope) {
|
||||
$scope.names = ['Igor', 'Misko', 'Vojta'];
|
||||
}
|
||||
angular.module('scopeExample', [])
|
||||
.controller('GreetController', ['$scope', '$rootScope', function($scope, $rootScope) {
|
||||
$scope.name = 'World';
|
||||
$rootScope.department = 'Angular';
|
||||
}])
|
||||
.controller('ListController', ['$scope', function($scope) {
|
||||
$scope.names = ['Igor', 'Misko', 'Vojta'];
|
||||
}]);
|
||||
</file>
|
||||
<file name="style.css">
|
||||
.show-scope-demo.ng-scope,
|
||||
@@ -190,14 +191,15 @@ Scopes can propagate events in similar fashion to DOM events. The event can be {
|
||||
ng.$rootScope.Scope#$broadcast broadcasted} to the scope children or {@link
|
||||
ng.$rootScope.Scope#$emit emitted} to scope parents.
|
||||
|
||||
<example>
|
||||
<example module="eventExample">
|
||||
<file name="script.js">
|
||||
function EventController($scope) {
|
||||
$scope.count = 0;
|
||||
$scope.$on('MyEvent', function() {
|
||||
$scope.count++;
|
||||
});
|
||||
}
|
||||
angular.module('eventExample', [])
|
||||
.controller('EventController', ['$scope', function($scope) {
|
||||
$scope.count = 0;
|
||||
$scope.$on('MyEvent', function() {
|
||||
$scope.count++;
|
||||
});
|
||||
}]);
|
||||
</file>
|
||||
<file name="index.html">
|
||||
<div ng-controller="EventController">
|
||||
|
||||
@@ -88,8 +88,10 @@ being the element on which the `ngApp` directive was defined.
|
||||
|
||||
Nothing here {{'yet' + '!'}}
|
||||
|
||||
This line demonstrates the core feature of Angular's templating capabilities – a binding, denoted
|
||||
by double-curlies `{{ }}` as well as a simple expression `'yet' + '!'` used in this binding.
|
||||
This line demonstrates two core features of Angular's templating capabilities:
|
||||
|
||||
* a binding, denoted by double-curlies `{{ }}`
|
||||
* a simple expression `'yet' + '!'` used in this binding.
|
||||
|
||||
The binding tells Angular that it should evaluate an expression and insert the result into the
|
||||
DOM in place of the binding. Rather than a one-time insert, as we'll see in the next steps, a
|
||||
|
||||
@@ -78,12 +78,17 @@ utilize the browser's history (back and forward navigation) and bookmarks.
|
||||
As you {@link tutorial/step_05 noticed}, {@link guide/di dependency injection} (DI) is at the core of
|
||||
AngularJS, so it's important for you to understand a thing or two about how it works.
|
||||
|
||||
When the application bootstraps, Angular creates an injector that will be used for all DI stuff in
|
||||
this app. The injector itself doesn't know anything about what `$http` or `$route` services do, in
|
||||
fact it doesn't even know about the existence of these services unless it is configured with proper
|
||||
module definitions. The sole responsibilities of the injector are to load specified module
|
||||
definition(s), register all service providers defined in these modules, and when asked, inject
|
||||
a specified function with dependencies (services) that it lazily instantiates via their providers.
|
||||
When the application bootstraps, Angular creates an injector that will be used to find and inject all
|
||||
of the services that are required by your app. The injector itself doesn't know anything about what
|
||||
`$http` or `$route` services do, in fact it doesn't even know about the existence of these services
|
||||
unless it is configured with proper module definitions.
|
||||
|
||||
The injector only carries out the following steps :
|
||||
|
||||
* load the module definition(s) that you specify in your app
|
||||
* register all Providers defined in these module definitions
|
||||
* when asked to do so, inject a specified function and any necessary dependencies (services) that
|
||||
it lazily instantiates via their Providers.
|
||||
|
||||
Providers are objects that provide (create) instances of services and expose configuration APIs
|
||||
that can be used to control the creation and runtime behavior of a service. In case of the `$route`
|
||||
|
||||
Generated
+106
-3
@@ -2690,13 +2690,100 @@
|
||||
}
|
||||
},
|
||||
"protractor": {
|
||||
"version": "0.19.0",
|
||||
"version": "1.0.0-rc4",
|
||||
"dependencies": {
|
||||
"request": {
|
||||
"version": "2.36.0",
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "0.6.6"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0"
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.2.11"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.5.2"
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.1"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "0.12.1",
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.2.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "0.1.4",
|
||||
"dependencies": {
|
||||
"combined-stream": {
|
||||
"version": "0.0.5",
|
||||
"dependencies": {
|
||||
"delayed-stream": {
|
||||
"version": "0.0.5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.0"
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "0.10.0",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "0.1.2"
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.1.11"
|
||||
},
|
||||
"ctype": {
|
||||
"version": "0.5.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"hawk": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"hoek": {
|
||||
"version": "0.9.1"
|
||||
},
|
||||
"boom": {
|
||||
"version": "0.4.2"
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "0.2.2"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "0.2.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.5.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selenium-webdriver": {
|
||||
"version": "2.39.0"
|
||||
"version": "2.42.1"
|
||||
},
|
||||
"minijasminenode": {
|
||||
"version": "0.2.7"
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"jasminewd": {
|
||||
"version": "1.0.3"
|
||||
},
|
||||
"saucelabs": {
|
||||
"version": "0.1.1"
|
||||
@@ -2733,6 +2820,22 @@
|
||||
"version": "0.0.8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "2.4.1"
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.2.6",
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.1.32",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"version": "0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
"karma-sauce-launcher": "0.2.0",
|
||||
"karma-script-launcher": "0.1.0",
|
||||
"karma-browserstack-launcher": "0.0.7",
|
||||
"protractor": "~0.19.0",
|
||||
"protractor": "1.0.0-rc4",
|
||||
"yaml-js": "~0.0.8",
|
||||
"rewire": "1.1.3",
|
||||
"promises-aplus-tests": "~1.3.2",
|
||||
|
||||
@@ -22,6 +22,7 @@ exports.config = {
|
||||
},
|
||||
|
||||
jasmineNodeOpts: {
|
||||
defaultTimeoutInterval: 30000
|
||||
defaultTimeoutInterval: 60000,
|
||||
showTiming: true
|
||||
}
|
||||
};
|
||||
|
||||
+16
-15
@@ -731,9 +731,9 @@ function isLeafNode (node) {
|
||||
* @returns {*} The copy or updated `destination`, if `destination` was specified.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="copyExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Controller">
|
||||
<div ng-controller="ExampleController">
|
||||
<form novalidate class="simple-form">
|
||||
Name: <input type="text" ng-model="user.name" /><br />
|
||||
E-mail: <input type="email" ng-model="user.email" /><br />
|
||||
@@ -747,21 +747,22 @@ function isLeafNode (node) {
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function Controller($scope) {
|
||||
$scope.master= {};
|
||||
angular.module('copyExample')
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.master= {};
|
||||
|
||||
$scope.update = function(user) {
|
||||
// Example with 1 argument
|
||||
$scope.master= angular.copy(user);
|
||||
};
|
||||
$scope.update = function(user) {
|
||||
// Example with 1 argument
|
||||
$scope.master= angular.copy(user);
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
// Example with 2 arguments
|
||||
angular.copy($scope.master, $scope.user);
|
||||
};
|
||||
$scope.reset = function() {
|
||||
// Example with 2 arguments
|
||||
angular.copy($scope.master, $scope.user);
|
||||
};
|
||||
|
||||
$scope.reset();
|
||||
}
|
||||
$scope.reset();
|
||||
}]);
|
||||
</script>
|
||||
</file>
|
||||
</example>
|
||||
@@ -1105,7 +1106,7 @@ function parseKeyValue(/**string*/keyValue) {
|
||||
key = tryDecodeURIComponent(key_value[0]);
|
||||
if ( isDefined(key) ) {
|
||||
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
|
||||
if (!obj[key]) {
|
||||
if (!hasOwnProperty.call(obj, key)) {
|
||||
obj[key] = val;
|
||||
} else if(isArray(obj[key])) {
|
||||
obj[key].push(val);
|
||||
|
||||
+8
-9
@@ -162,7 +162,7 @@
|
||||
* local name. Given `<widget my-attr="count = count + value">` and widget definition of
|
||||
* `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
|
||||
* a function wrapper for the `count = count + value` expression. Often it's desirable to
|
||||
* pass data from the isolated scope via an expression and to the parent scope, this can be
|
||||
* pass data from the isolated scope via an expression to the parent scope, this can be
|
||||
* done by passing a map of local variable names and values into the expression wrapper fn.
|
||||
* For example, if the expression is `increment(amount)` then we can specify the amount value
|
||||
* by calling the `localFn` as `localFn({amount: 22})`.
|
||||
@@ -389,10 +389,10 @@
|
||||
* to illustrate how `$compile` works.
|
||||
* </div>
|
||||
*
|
||||
<example module="compile">
|
||||
<example module="compileExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
angular.module('compile', [], function($compileProvider) {
|
||||
angular.module('compileExample', [], function($compileProvider) {
|
||||
// configure new 'compile' directive by passing a directive
|
||||
// factory function. The factory function injects the '$compile'
|
||||
$compileProvider.directive('compile', function($compile) {
|
||||
@@ -416,15 +416,14 @@
|
||||
}
|
||||
);
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
function Ctrl($scope) {
|
||||
});
|
||||
})
|
||||
.controller('GreeterController', ['$scope', function($scope) {
|
||||
$scope.name = 'Angular';
|
||||
$scope.html = 'Hello {{name}}';
|
||||
}
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="GreeterController">
|
||||
<input ng-model="name"> <br>
|
||||
<textarea ng-model="html"></textarea> <br>
|
||||
<div compile="html"></div>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
return browser.driver.getCurrentUrl().then(function(url) {
|
||||
return url.match(/\/123$/);
|
||||
});
|
||||
}, 1000, 'page should navigate to /123');
|
||||
}, 5000, 'page should navigate to /123');
|
||||
});
|
||||
|
||||
xit('should execute ng-click but not reload when href empty string and name specified', function() {
|
||||
@@ -94,7 +94,7 @@
|
||||
return browser.driver.getCurrentUrl().then(function(url) {
|
||||
return url.match(/\/6$/);
|
||||
});
|
||||
}, 1000, 'page should navigate to /6');
|
||||
}, 5000, 'page should navigate to /6');
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
|
||||
@@ -314,12 +314,13 @@ function FormController(element, attrs, $scope, $animate) {
|
||||
* </pre>
|
||||
*
|
||||
* @example
|
||||
<example deps="angular-animate.js" animations="true" fixBase="true">
|
||||
<example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.userType = 'guest';
|
||||
}
|
||||
angular.module('formExample', [])
|
||||
.controller('FormController', ['$scope', function($scope) {
|
||||
$scope.userType = 'guest';
|
||||
}]);
|
||||
</script>
|
||||
<style>
|
||||
.my-form {
|
||||
@@ -331,7 +332,7 @@ function FormController(element, attrs, $scope, $animate) {
|
||||
background: red;
|
||||
}
|
||||
</style>
|
||||
<form name="myForm" ng-controller="Ctrl" class="my-form">
|
||||
<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>
|
||||
|
||||
+77
-66
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
|
||||
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
|
||||
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
||||
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
|
||||
|
||||
var inputType = {
|
||||
@@ -39,15 +39,16 @@ var inputType = {
|
||||
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
|
||||
*
|
||||
* @example
|
||||
<example name="text-input-directive">
|
||||
<example name="text-input-directive" module="textInputExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.text = 'guest';
|
||||
$scope.word = /^\s*\w*\s*$/;
|
||||
}
|
||||
angular.module('textInputExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.text = 'guest';
|
||||
$scope.word = /^\s*\w*\s*$/;
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
Single word: <input type="text" name="input" ng-model="text"
|
||||
ng-pattern="word" required ng-trim="false">
|
||||
<span class="error" ng-show="myForm.input.$error.required">
|
||||
@@ -119,14 +120,15 @@ var inputType = {
|
||||
* interaction with the input element.
|
||||
*
|
||||
* @example
|
||||
<example name="number-input-directive">
|
||||
<example name="number-input-directive" module="numberExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.value = 12;
|
||||
}
|
||||
angular.module('numberExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.value = 12;
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
Number: <input type="number" name="input" ng-model="value"
|
||||
min="0" max="99" required>
|
||||
<span class="error" ng-show="myForm.input.$error.required">
|
||||
@@ -194,14 +196,15 @@ var inputType = {
|
||||
* interaction with the input element.
|
||||
*
|
||||
* @example
|
||||
<example name="url-input-directive">
|
||||
<example name="url-input-directive" module="urlExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.text = 'http://google.com';
|
||||
}
|
||||
angular.module('urlExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.text = 'http://google.com';
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
URL: <input type="url" name="input" ng-model="text" required>
|
||||
<span class="error" ng-show="myForm.input.$error.required">
|
||||
Required!</span>
|
||||
@@ -270,14 +273,15 @@ var inputType = {
|
||||
* interaction with the input element.
|
||||
*
|
||||
* @example
|
||||
<example name="email-input-directive">
|
||||
<example name="email-input-directive" module="emailExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.text = 'me@example.com';
|
||||
}
|
||||
angular.module('emailExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.text = 'me@example.com';
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
Email: <input type="email" name="input" ng-model="text" required>
|
||||
<span class="error" ng-show="myForm.input.$error.required">
|
||||
Required!</span>
|
||||
@@ -336,18 +340,19 @@ var inputType = {
|
||||
* be set when selected.
|
||||
*
|
||||
* @example
|
||||
<example name="radio-input-directive">
|
||||
<example name="radio-input-directive" module="radioExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.color = 'blue';
|
||||
$scope.specialValue = {
|
||||
"id": "12345",
|
||||
"value": "green"
|
||||
};
|
||||
}
|
||||
angular.module('radioExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.color = 'blue';
|
||||
$scope.specialValue = {
|
||||
"id": "12345",
|
||||
"value": "green"
|
||||
};
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
<input type="radio" ng-model="color" value="red"> Red <br/>
|
||||
<input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
|
||||
<input type="radio" ng-model="color" value="blue"> Blue <br/>
|
||||
@@ -386,15 +391,16 @@ var inputType = {
|
||||
* interaction with the input element.
|
||||
*
|
||||
* @example
|
||||
<example name="checkbox-input-directive">
|
||||
<example name="checkbox-input-directive" module="checkboxExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.value1 = true;
|
||||
$scope.value2 = 'YES'
|
||||
}
|
||||
angular.module('checkboxExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.value1 = true;
|
||||
$scope.value2 = 'YES'
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
Value1: <input type="checkbox" ng-model="value1"> <br/>
|
||||
Value2: <input type="checkbox" ng-model="value2"
|
||||
ng-true-value="YES" ng-false-value="NO"> <br/>
|
||||
@@ -794,14 +800,15 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
||||
* interaction with the input element.
|
||||
*
|
||||
* @example
|
||||
<example name="input-directive">
|
||||
<example name="input-directive" module="inputExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.user = {name: 'guest', last: 'visitor'};
|
||||
}
|
||||
angular.module('inputExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.user = {name: 'guest', last: 'visitor'};
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<form name="myForm">
|
||||
User name: <input type="text" name="userName" ng-model="user.name" required>
|
||||
<span class="error" ng-show="myForm.userName.$error.required">
|
||||
@@ -1319,12 +1326,13 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* </pre>
|
||||
*
|
||||
* @example
|
||||
* <example deps="angular-animate.js" animations="true" fixBase="true">
|
||||
* <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.val = '1';
|
||||
}
|
||||
angular.module('inputExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.val = '1';
|
||||
}]);
|
||||
</script>
|
||||
<style>
|
||||
.my-input {
|
||||
@@ -1339,7 +1347,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
</style>
|
||||
Update input to see transitions when valid/invalid.
|
||||
Integer is a valid value.
|
||||
<form name="testForm" ng-controller="Ctrl">
|
||||
<form name="testForm" ng-controller="ExampleController">
|
||||
<input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
|
||||
</form>
|
||||
</file>
|
||||
@@ -1383,17 +1391,18 @@ var ngModelDirective = function() {
|
||||
* in input value.
|
||||
*
|
||||
* @example
|
||||
* <example name="ngChange-directive">
|
||||
* <example name="ngChange-directive" module="changeExample">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* function Controller($scope) {
|
||||
* $scope.counter = 0;
|
||||
* $scope.change = function() {
|
||||
* $scope.counter++;
|
||||
* };
|
||||
* }
|
||||
* angular.module('changeExample', [])
|
||||
* .controller('ExampleController', ['$scope', function($scope) {
|
||||
* $scope.counter = 0;
|
||||
* $scope.change = function() {
|
||||
* $scope.counter++;
|
||||
* };
|
||||
* }]);
|
||||
* </script>
|
||||
* <div ng-controller="Controller">
|
||||
* <div ng-controller="ExampleController">
|
||||
* <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
|
||||
* <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
|
||||
* <label for="ng-change-example2">Confirmed</label><br />
|
||||
@@ -1474,14 +1483,15 @@ var requiredDirective = function() {
|
||||
* specified in form `/something/` then the value will be converted into a regular expression.
|
||||
*
|
||||
* @example
|
||||
<example name="ngList-directive">
|
||||
<example name="ngList-directive" module="listExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.names = ['igor', 'misko', 'vojta'];
|
||||
}
|
||||
angular.module('listExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.names = ['igor', 'misko', 'vojta'];
|
||||
}]);
|
||||
</script>
|
||||
<form name="myForm" ng-controller="Ctrl">
|
||||
<form name="myForm" ng-controller="ExampleController">
|
||||
List: <input name="namesInput" ng-model="names" ng-list required>
|
||||
<span class="error" ng-show="myForm.namesInput.$error.required">
|
||||
Required!</span>
|
||||
@@ -1573,15 +1583,16 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
|
||||
* of the `input` element
|
||||
*
|
||||
* @example
|
||||
<example name="ngValue-directive">
|
||||
<example name="ngValue-directive" module="valueExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.names = ['pizza', 'unicorns', 'robots'];
|
||||
$scope.my = { favorite: 'unicorns' };
|
||||
}
|
||||
angular.module('valueExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.names = ['pizza', 'unicorns', 'robots'];
|
||||
$scope.my = { favorite: 'unicorns' };
|
||||
}]);
|
||||
</script>
|
||||
<form ng-controller="Ctrl">
|
||||
<form ng-controller="ExampleController">
|
||||
<h2>Which is your favorite?</h2>
|
||||
<label ng-repeat="name in names" for="{{name}}">
|
||||
{{name}}
|
||||
|
||||
+21
-19
@@ -26,14 +26,15 @@
|
||||
*
|
||||
* @example
|
||||
* Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
|
||||
<example>
|
||||
<example module="bindExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.name = 'Whirled';
|
||||
}
|
||||
angular.module('bindExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.name = 'Whirled';
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Enter name: <input type="text" ng-model="name"><br>
|
||||
Hello <span ng-bind="name"></span>!
|
||||
</div>
|
||||
@@ -84,15 +85,16 @@ var ngBindDirective = ngDirective({
|
||||
*
|
||||
* @example
|
||||
* Try it here: enter text in text box and watch the greeting change.
|
||||
<example>
|
||||
<example module="bindExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.salutation = 'Hello';
|
||||
$scope.name = 'World';
|
||||
}
|
||||
angular.module('bindExample', [])
|
||||
.controller('ExampleController', ['$scope', function ($scope) {
|
||||
$scope.salutation = 'Hello';
|
||||
$scope.name = 'World';
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Salutation: <input type="text" ng-model="salutation"><br>
|
||||
Name: <input type="text" ng-model="name"><br>
|
||||
<pre ng-bind-template="{{salutation}} {{name}}!"></pre>
|
||||
@@ -150,20 +152,20 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
|
||||
* @example
|
||||
Try it here: enter text in text box and watch the greeting change.
|
||||
|
||||
<example module="ngBindHtmlExample" deps="angular-sanitize.js">
|
||||
<example module="bindHtmlExample" deps="angular-sanitize.js">
|
||||
<file name="index.html">
|
||||
<div ng-controller="ngBindHtmlCtrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<p ng-bind-html="myHTML"></p>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
angular.module('ngBindHtmlExample', ['ngSanitize'])
|
||||
|
||||
.controller('ngBindHtmlCtrl', ['$scope', function ngBindHtmlCtrl($scope) {
|
||||
$scope.myHTML =
|
||||
'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>';
|
||||
}]);
|
||||
angular.module('bindHtmlExample', ['ngSanitize'])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.myHTML =
|
||||
'I am an <code>HTML</code>string with ' +
|
||||
'<a href="#">links!</a> and other <em>stuff</em>';
|
||||
}]);
|
||||
</file>
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
*
|
||||
* This example demonstrates the `controller as` syntax.
|
||||
*
|
||||
* <example name="ngControllerAs">
|
||||
* <example name="ngControllerAs" module="controllerAsExample">
|
||||
* <file name="index.html">
|
||||
* <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
|
||||
* Name: <input type="text" ng-model="settings.name"/>
|
||||
@@ -75,6 +75,9 @@
|
||||
* </div>
|
||||
* </file>
|
||||
* <file name="app.js">
|
||||
* angular.module('controllerAsExample', [])
|
||||
* .controller('SettingsController1', SettingsController1);
|
||||
*
|
||||
* function SettingsController1() {
|
||||
* this.name = "John Smith";
|
||||
* this.contacts = [
|
||||
@@ -103,29 +106,29 @@
|
||||
* <file name="protractor.js" type="protractor">
|
||||
* it('should check controller as', function() {
|
||||
* var container = element(by.id('ctrl-as-exmpl'));
|
||||
* expect(container.findElement(by.model('settings.name'))
|
||||
* expect(container.element(by.model('settings.name'))
|
||||
* .getAttribute('value')).toBe('John Smith');
|
||||
*
|
||||
* var firstRepeat =
|
||||
* container.findElement(by.repeater('contact in settings.contacts').row(0));
|
||||
* container.element(by.repeater('contact in settings.contacts').row(0));
|
||||
* var secondRepeat =
|
||||
* container.findElement(by.repeater('contact in settings.contacts').row(1));
|
||||
* container.element(by.repeater('contact in settings.contacts').row(1));
|
||||
*
|
||||
* expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
|
||||
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
||||
* .toBe('408 555 1212');
|
||||
*
|
||||
* expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
|
||||
* expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
|
||||
* .toBe('john.smith@example.org');
|
||||
*
|
||||
* firstRepeat.findElement(by.linkText('clear')).click();
|
||||
* firstRepeat.element(by.linkText('clear')).click();
|
||||
*
|
||||
* expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
|
||||
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
||||
* .toBe('');
|
||||
*
|
||||
* container.findElement(by.linkText('add')).click();
|
||||
* container.element(by.linkText('add')).click();
|
||||
*
|
||||
* expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
|
||||
* .findElement(by.model('contact.value'))
|
||||
* expect(container.element(by.repeater('contact in settings.contacts').row(2))
|
||||
* .element(by.model('contact.value'))
|
||||
* .getAttribute('value'))
|
||||
* .toBe('yourname@example.org');
|
||||
* });
|
||||
@@ -134,7 +137,7 @@
|
||||
*
|
||||
* This example demonstrates the "attach to `$scope`" style of controller.
|
||||
*
|
||||
* <example name="ngController">
|
||||
* <example name="ngController" module="controllerExample">
|
||||
* <file name="index.html">
|
||||
* <div id="ctrl-exmpl" ng-controller="SettingsController2">
|
||||
* Name: <input type="text" ng-model="name"/>
|
||||
@@ -155,6 +158,9 @@
|
||||
* </div>
|
||||
* </file>
|
||||
* <file name="app.js">
|
||||
* angular.module('controllerExample', [])
|
||||
* .controller('SettingsController2', ['$scope', SettingsController2]);
|
||||
*
|
||||
* function SettingsController2($scope) {
|
||||
* $scope.name = "John Smith";
|
||||
* $scope.contacts = [
|
||||
@@ -184,28 +190,28 @@
|
||||
* it('should check controller', function() {
|
||||
* var container = element(by.id('ctrl-exmpl'));
|
||||
*
|
||||
* expect(container.findElement(by.model('name'))
|
||||
* expect(container.element(by.model('name'))
|
||||
* .getAttribute('value')).toBe('John Smith');
|
||||
*
|
||||
* var firstRepeat =
|
||||
* container.findElement(by.repeater('contact in contacts').row(0));
|
||||
* container.element(by.repeater('contact in contacts').row(0));
|
||||
* var secondRepeat =
|
||||
* container.findElement(by.repeater('contact in contacts').row(1));
|
||||
* container.element(by.repeater('contact in contacts').row(1));
|
||||
*
|
||||
* expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
|
||||
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
||||
* .toBe('408 555 1212');
|
||||
* expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
|
||||
* expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
|
||||
* .toBe('john.smith@example.org');
|
||||
*
|
||||
* firstRepeat.findElement(by.linkText('clear')).click();
|
||||
* firstRepeat.element(by.linkText('clear')).click();
|
||||
*
|
||||
* expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
|
||||
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
||||
* .toBe('');
|
||||
*
|
||||
* container.findElement(by.linkText('add')).click();
|
||||
* container.element(by.linkText('add')).click();
|
||||
*
|
||||
* expect(container.findElement(by.repeater('contact in contacts').row(2))
|
||||
* .findElement(by.model('contact.value'))
|
||||
* expect(container.element(by.repeater('contact in contacts').row(2))
|
||||
* .element(by.model('contact.value'))
|
||||
* .getAttribute('value'))
|
||||
* .toBe('yourname@example.org');
|
||||
* });
|
||||
|
||||
@@ -313,21 +313,22 @@ forEach(
|
||||
* ({@link guide/expression#-event- Event object is available as `$event`})
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="submitExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.list = [];
|
||||
$scope.text = 'hello';
|
||||
$scope.submit = function() {
|
||||
if ($scope.text) {
|
||||
$scope.list.push(this.text);
|
||||
$scope.text = '';
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('submitExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.list = [];
|
||||
$scope.text = 'hello';
|
||||
$scope.submit = function() {
|
||||
if ($scope.text) {
|
||||
$scope.list.push(this.text);
|
||||
$scope.text = '';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
</script>
|
||||
<form ng-submit="submit()" ng-controller="Ctrl">
|
||||
<form ng-submit="submit()" ng-controller="ExampleController">
|
||||
Enter text and hit enter:
|
||||
<input type="text" ng-model="text" name="text" />
|
||||
<input type="submit" id="submit" value="Submit" />
|
||||
@@ -339,7 +340,7 @@ forEach(
|
||||
expect(element(by.binding('list')).getText()).toBe('list=[]');
|
||||
element(by.css('#submit')).click();
|
||||
expect(element(by.binding('list')).getText()).toContain('hello');
|
||||
expect(element(by.input('text')).getAttribute('value')).toBe('');
|
||||
expect(element(by.model('text')).getAttribute('value')).toBe('');
|
||||
});
|
||||
it('should ignore empty strings', function() {
|
||||
expect(element(by.binding('list')).getText()).toBe('list=[]');
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
* - Otherwise enable scrolling only if the expression evaluates to truthy value.
|
||||
*
|
||||
* @example
|
||||
<example module="ngAnimate" deps="angular-animate.js" animations="true">
|
||||
<example module="includeExample" deps="angular-animate.js" animations="true">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<select ng-model="template" ng-options="t.name for t in templates">
|
||||
<option value="">(blank)</option>
|
||||
</select>
|
||||
@@ -57,12 +57,13 @@
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function Ctrl($scope) {
|
||||
$scope.templates =
|
||||
[ { name: 'template1.html', url: 'template1.html'},
|
||||
{ name: 'template2.html', url: 'template2.html'} ];
|
||||
$scope.template = $scope.templates[0];
|
||||
}
|
||||
angular.module('includeExample', ['ngAnimate'])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.templates =
|
||||
[ { name: 'template1.html', url: 'template1.html'},
|
||||
{ name: 'template2.html', url: 'template2.html'} ];
|
||||
$scope.template = $scope.templates[0];
|
||||
}]);
|
||||
</file>
|
||||
<file name="template1.html">
|
||||
Content of template1.html
|
||||
@@ -125,7 +126,7 @@
|
||||
return;
|
||||
}
|
||||
templateSelect.click();
|
||||
templateSelect.element.all(by.css('option')).get(2).click();
|
||||
templateSelect.all(by.css('option')).get(2).click();
|
||||
expect(includeElem.getText()).toMatch(/Content of template2.html/);
|
||||
});
|
||||
|
||||
@@ -135,7 +136,7 @@
|
||||
return;
|
||||
}
|
||||
templateSelect.click();
|
||||
templateSelect.element.all(by.css('option')).get(0).click();
|
||||
templateSelect.all(by.css('option')).get(0).click();
|
||||
expect(includeElem.isPresent()).toBe(false);
|
||||
});
|
||||
</file>
|
||||
|
||||
@@ -29,14 +29,15 @@
|
||||
* @param {expression} ngInit {@link guide/expression Expression} to eval.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="initExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.list = [['a', 'b'], ['c', 'd']];
|
||||
}
|
||||
angular.module('initExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.list = [['a', 'b'], ['c', 'd']];
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<div ng-repeat="innerList in list" ng-init="outerIndex = $index">
|
||||
<div ng-repeat="value in innerList" ng-init="innerIndex = $index">
|
||||
<span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
|
||||
|
||||
@@ -89,16 +89,17 @@
|
||||
* @param {number=} offset Offset to deduct from the total number.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="pluralizeExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.person1 = 'Igor';
|
||||
$scope.person2 = 'Misko';
|
||||
$scope.personCount = 1;
|
||||
}
|
||||
angular.module('pluralizeExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.person1 = 'Igor';
|
||||
$scope.person2 = 'Misko';
|
||||
$scope.personCount = 1;
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
|
||||
Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
|
||||
Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
*
|
||||
*
|
||||
* @example
|
||||
<example module="ngAnimate" deps="angular-animate.js" animations="true">
|
||||
<example module="switchExample" deps="angular-animate.js" animations="true">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<select ng-model="selection" ng-options="item for item in items">
|
||||
</select>
|
||||
<tt>selection={{selection}}</tt>
|
||||
@@ -71,10 +71,11 @@
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function Ctrl($scope) {
|
||||
$scope.items = ['settings', 'home', 'other'];
|
||||
$scope.selection = $scope.items[0];
|
||||
}
|
||||
angular.module('switchExample', ['ngAnimate'])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.items = ['settings', 'home', 'other'];
|
||||
$scope.selection = $scope.items[0];
|
||||
}]);
|
||||
</file>
|
||||
<file name="animations.css">
|
||||
.animate-switch-container {
|
||||
@@ -117,11 +118,11 @@
|
||||
expect(switchElem.getText()).toMatch(/Settings Div/);
|
||||
});
|
||||
it('should change to home', function() {
|
||||
select.element.all(by.css('option')).get(1).click();
|
||||
select.all(by.css('option')).get(1).click();
|
||||
expect(switchElem.getText()).toMatch(/Home Span/);
|
||||
});
|
||||
it('should select default', function() {
|
||||
select.element.all(by.css('option')).get(2).click();
|
||||
select.all(by.css('option')).get(2).click();
|
||||
expect(switchElem.getText()).toMatch(/default/);
|
||||
});
|
||||
</file>
|
||||
|
||||
@@ -13,15 +13,10 @@
|
||||
* @element ANY
|
||||
*
|
||||
* @example
|
||||
<example module="transclude">
|
||||
<example module="transcludeExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.title = 'Lorem Ipsum';
|
||||
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
||||
}
|
||||
|
||||
angular.module('transclude', [])
|
||||
angular.module('transcludeExample', [])
|
||||
.directive('pane', function(){
|
||||
return {
|
||||
restrict: 'E',
|
||||
@@ -32,9 +27,13 @@
|
||||
'<div ng-transclude></div>' +
|
||||
'</div>'
|
||||
};
|
||||
});
|
||||
})
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.title = 'Lorem Ipsum';
|
||||
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<input ng-model="title"><br>
|
||||
<textarea ng-model="text"></textarea> <br/>
|
||||
<pane title="{{title}}">{{text}}</pane>
|
||||
|
||||
+14
-13
@@ -72,21 +72,22 @@ var ngOptionsMinErr = minErr('ngOptions');
|
||||
* `value` variable (e.g. `value.propertyName`).
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="selectExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function MyCntrl($scope) {
|
||||
$scope.colors = [
|
||||
{name:'black', shade:'dark'},
|
||||
{name:'white', shade:'light'},
|
||||
{name:'red', shade:'dark'},
|
||||
{name:'blue', shade:'dark'},
|
||||
{name:'yellow', shade:'light'}
|
||||
];
|
||||
$scope.myColor = $scope.colors[2]; // red
|
||||
}
|
||||
angular.module('selectExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.colors = [
|
||||
{name:'black', shade:'dark'},
|
||||
{name:'white', shade:'light'},
|
||||
{name:'red', shade:'dark'},
|
||||
{name:'blue', shade:'dark'},
|
||||
{name:'yellow', shade:'light'}
|
||||
];
|
||||
$scope.myColor = $scope.colors[2]; // red
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="MyCntrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<ul>
|
||||
<li ng-repeat="color in colors">
|
||||
Name: <input ng-model="color.name">
|
||||
@@ -123,7 +124,7 @@ var ngOptionsMinErr = minErr('ngOptions');
|
||||
<file name="protractor.js" type="protractor">
|
||||
it('should check ng-options', function() {
|
||||
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
|
||||
element.all(by.select('myColor')).first().click();
|
||||
element.all(by.model('myColor')).first().click();
|
||||
element.all(by.css('select[ng-model="myColor"] option')).first().click();
|
||||
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
|
||||
element(by.css('.nullable select[ng-model="myColor"]')).click();
|
||||
|
||||
+7
-6
@@ -9,18 +9,19 @@
|
||||
* A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="documentExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="MainCtrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<p>$document title: <b ng-bind="title"></b></p>
|
||||
<p>window.document title: <b ng-bind="windowTitle"></b></p>
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function MainCtrl($scope, $document) {
|
||||
$scope.title = $document[0].title;
|
||||
$scope.windowTitle = angular.element(window.document)[0].title;
|
||||
}
|
||||
angular.module('documentExample', [])
|
||||
.controller('ExampleController', ['$scope', '$document', function($scope, $document) {
|
||||
$scope.title = $document[0].title;
|
||||
$scope.windowTitle = angular.element(window.document)[0].title;
|
||||
}]);
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
|
||||
+12
-10
@@ -15,14 +15,15 @@
|
||||
*
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="currencyExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.amount = 1234.56;
|
||||
}
|
||||
angular.module('currencyExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.amount = 1234.56;
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<input type="number" ng-model="amount"> <br>
|
||||
default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
|
||||
custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
|
||||
@@ -74,14 +75,15 @@ function currencyFilter($locale) {
|
||||
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="numberFilterExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.val = 1234.56789;
|
||||
}
|
||||
angular.module('numberFilterExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.val = 1234.56789;
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Enter number: <input ng-model='val'><br>
|
||||
Default formatting: <span id='number-default'>{{val | number}}</span><br>
|
||||
No fractions: <span>{{val | number:0}}</span><br>
|
||||
|
||||
@@ -19,17 +19,18 @@
|
||||
* had less than `limit` elements.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="limitToExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.numbers = [1,2,3,4,5,6,7,8,9];
|
||||
$scope.letters = "abcdefghi";
|
||||
$scope.numLimit = 3;
|
||||
$scope.letterLimit = 3;
|
||||
}
|
||||
angular.module('limitToExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.numbers = [1,2,3,4,5,6,7,8,9];
|
||||
$scope.letters = "abcdefghi";
|
||||
$scope.numLimit = 3;
|
||||
$scope.letterLimit = 3;
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
|
||||
<p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
|
||||
Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
|
||||
|
||||
+28
-27
@@ -28,20 +28,21 @@
|
||||
* @returns {Array} Sorted copy of the source array.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($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}]
|
||||
$scope.predicate = '-age';
|
||||
}
|
||||
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}];
|
||||
$scope.predicate = '-age';
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
||||
<hr/>
|
||||
[ <a href="" ng-click="predicate=''">unsorted</a> ]
|
||||
@@ -69,7 +70,7 @@
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Ctrl">
|
||||
<table class="friend">
|
||||
@@ -89,21 +90,21 @@
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
function Ctrl($scope, $filter) {
|
||||
var orderBy = $filter('orderBy');
|
||||
$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 }
|
||||
];
|
||||
|
||||
$scope.order = function(predicate, reverse) {
|
||||
$scope.friends = orderBy($scope.friends, predicate, reverse);
|
||||
};
|
||||
$scope.order('-age',false);
|
||||
}
|
||||
angular.module('orderByExample', [])
|
||||
.controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
|
||||
var orderBy = $filter('orderBy');
|
||||
$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 }
|
||||
];
|
||||
$scope.order = function(predicate, reverse) {
|
||||
$scope.friends = orderBy($scope.friends, predicate, reverse);
|
||||
};
|
||||
$scope.order('-age',false);
|
||||
}]);
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
|
||||
+55
-28
@@ -83,12 +83,39 @@ function isSuccess(status) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc provider
|
||||
* @name $httpProvider
|
||||
* @description
|
||||
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
|
||||
* */
|
||||
function $HttpProvider() {
|
||||
var JSON_START = /^\s*(\[|\{[^\{])/,
|
||||
JSON_END = /[\}\]]\s*$/,
|
||||
PROTECTION_PREFIX = /^\)\]\}',?\n/,
|
||||
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
|
||||
|
||||
/**
|
||||
* @ngdoc property
|
||||
* @name $httpProvider#defaults
|
||||
* @description
|
||||
*
|
||||
* Object containing default values for all {@link ng.$http $http} requests.
|
||||
*
|
||||
* - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
|
||||
* Defaults value is `'XSRF-TOKEN'`.
|
||||
*
|
||||
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
|
||||
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
|
||||
*
|
||||
* - **`defaults.headers`** - {Object} - Default headers for all $http requests.
|
||||
* Refer to {@link ng.$http#setting-http-headers $http} for documentation on
|
||||
* setting default headers.
|
||||
* - **`defaults.headers.common`**
|
||||
* - **`defaults.headers.post`**
|
||||
* - **`defaults.headers.put`**
|
||||
* - **`defaults.headers.patch`**
|
||||
**/
|
||||
var defaults = this.defaults = {
|
||||
// transform incoming response data
|
||||
transformResponse: [function(data) {
|
||||
@@ -578,9 +605,9 @@ function $HttpProvider() {
|
||||
*
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="httpExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="FetchCtrl">
|
||||
<div ng-controller="FetchController">
|
||||
<select ng-model="method">
|
||||
<option>GET</option>
|
||||
<option>JSONP</option>
|
||||
@@ -602,30 +629,32 @@ function $HttpProvider() {
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function FetchCtrl($scope, $http, $templateCache) {
|
||||
$scope.method = 'GET';
|
||||
$scope.url = 'http-hello.html';
|
||||
angular.module('httpExample', [])
|
||||
.controller('FetchController', ['$scope', '$http', '$templateCache',
|
||||
function($scope, $http, $templateCache) {
|
||||
$scope.method = 'GET';
|
||||
$scope.url = 'http-hello.html';
|
||||
|
||||
$scope.fetch = function() {
|
||||
$scope.code = null;
|
||||
$scope.response = null;
|
||||
$scope.fetch = function() {
|
||||
$scope.code = null;
|
||||
$scope.response = null;
|
||||
|
||||
$http({method: $scope.method, url: $scope.url, cache: $templateCache}).
|
||||
success(function(data, status) {
|
||||
$scope.status = status;
|
||||
$scope.data = data;
|
||||
}).
|
||||
error(function(data, status) {
|
||||
$scope.data = data || "Request failed";
|
||||
$scope.status = status;
|
||||
});
|
||||
};
|
||||
$http({method: $scope.method, url: $scope.url, cache: $templateCache}).
|
||||
success(function(data, status) {
|
||||
$scope.status = status;
|
||||
$scope.data = data;
|
||||
}).
|
||||
error(function(data, status) {
|
||||
$scope.data = data || "Request failed";
|
||||
$scope.status = status;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.updateModel = function(method, url) {
|
||||
$scope.method = method;
|
||||
$scope.url = url;
|
||||
};
|
||||
}
|
||||
$scope.updateModel = function(method, url) {
|
||||
$scope.method = method;
|
||||
$scope.url = url;
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
<file name="http-hello.html">
|
||||
Hello, $http!
|
||||
@@ -679,7 +708,7 @@ function $HttpProvider() {
|
||||
var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
|
||||
|
||||
// strip content-type if data is undefined
|
||||
if (isUndefined(config.data)) {
|
||||
if (isUndefined(reqData)) {
|
||||
forEach(headers, function(value, header) {
|
||||
if (lowercase(header) === 'content-type') {
|
||||
delete headers[header];
|
||||
@@ -748,10 +777,6 @@ function $HttpProvider() {
|
||||
|
||||
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
|
||||
|
||||
// execute if header value is function
|
||||
execHeaders(defHeaders);
|
||||
execHeaders(reqHeaders);
|
||||
|
||||
// using for-in instead of forEach to avoid unecessary iteration after header has been found
|
||||
defaultHeadersIteration:
|
||||
for (defHeaderName in defHeaders) {
|
||||
@@ -766,6 +791,8 @@ function $HttpProvider() {
|
||||
reqHeaders[defHeaderName] = defHeaders[defHeaderName];
|
||||
}
|
||||
|
||||
// execute if header value is a function for merged headers
|
||||
execHeaders(reqHeaders);
|
||||
return reqHeaders;
|
||||
|
||||
function execHeaders(headers) {
|
||||
|
||||
+38
-37
@@ -42,25 +42,27 @@ function $IntervalProvider() {
|
||||
* @returns {promise} A promise which will be notified on each iteration.
|
||||
*
|
||||
* @example
|
||||
* <example module="time">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* function Ctrl2($scope,$interval) {
|
||||
* $scope.format = 'M/d/yy h:mm:ss a';
|
||||
* $scope.blood_1 = 100;
|
||||
* $scope.blood_2 = 120;
|
||||
* <example module="intervalExample">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* angular.module('intervalExample', [])
|
||||
* .controller('ExampleController', ['$scope', '$interval',
|
||||
* function($scope, $interval) {
|
||||
* $scope.format = 'M/d/yy h:mm:ss a';
|
||||
* $scope.blood_1 = 100;
|
||||
* $scope.blood_2 = 120;
|
||||
*
|
||||
* var stop;
|
||||
* $scope.fight = function() {
|
||||
* // Don't start a new fight if we are already fighting
|
||||
* if ( angular.isDefined(stop) ) return;
|
||||
* var stop;
|
||||
* $scope.fight = function() {
|
||||
* // Don't start a new fight if we are already fighting
|
||||
* if ( angular.isDefined(stop) ) return;
|
||||
*
|
||||
* stop = $interval(function() {
|
||||
* if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
|
||||
* $scope.blood_1 = $scope.blood_1 - 3;
|
||||
* $scope.blood_2 = $scope.blood_2 - 4;
|
||||
* $scope.blood_1 = $scope.blood_1 - 3;
|
||||
* $scope.blood_2 = $scope.blood_2 - 4;
|
||||
* } else {
|
||||
* $scope.stopFight();
|
||||
* $scope.stopFight();
|
||||
* }
|
||||
* }, 100);
|
||||
* };
|
||||
@@ -75,22 +77,21 @@ function $IntervalProvider() {
|
||||
* $scope.resetFight = function() {
|
||||
* $scope.blood_1 = 100;
|
||||
* $scope.blood_2 = 120;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* $scope.$on('$destroy', function() {
|
||||
* // Make sure that the interval is destroyed too
|
||||
* // Make sure that the interval nis destroyed too
|
||||
* $scope.stopFight();
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* angular.module('time', [])
|
||||
* // Register the 'myCurrentTime' directive factory method.
|
||||
* // We inject $interval and dateFilter service since the factory method is DI.
|
||||
* .directive('myCurrentTime', function($interval, dateFilter) {
|
||||
* })
|
||||
* // Register the 'myCurrentTime' directive factory method.
|
||||
* // We inject $interval and dateFilter service since the factory method is DI.
|
||||
* .directive('myCurrentTime', ['$interval', 'dateFilter',
|
||||
* function($interval, dateFilter) {
|
||||
* // return the directive link function. (compile function not needed)
|
||||
* return function(scope, element, attrs) {
|
||||
* var format, // date format
|
||||
* stopTime; // so that we can cancel the time updates
|
||||
* stopTime; // so that we can cancel the time updates
|
||||
*
|
||||
* // used to update the UI
|
||||
* function updateTime() {
|
||||
@@ -106,28 +107,28 @@ function $IntervalProvider() {
|
||||
* stopTime = $interval(updateTime, 1000);
|
||||
*
|
||||
* // listen on DOM destroy (removal) event, and cancel the next UI update
|
||||
* // to prevent updating time ofter the DOM element was removed.
|
||||
* // to prevent updating time after the DOM element was removed.
|
||||
* element.bind('$destroy', function() {
|
||||
* $interval.cancel(stopTime);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
* </script>
|
||||
* </script>
|
||||
*
|
||||
* <div>
|
||||
* <div ng-controller="Ctrl2">
|
||||
* Date format: <input ng-model="format"> <hr/>
|
||||
* Current time is: <span my-current-time="format"></span>
|
||||
* <hr/>
|
||||
* Blood 1 : <font color='red'>{{blood_1}}</font>
|
||||
* Blood 2 : <font color='red'>{{blood_2}}</font>
|
||||
* <button type="button" data-ng-click="fight()">Fight</button>
|
||||
* <button type="button" data-ng-click="stopFight()">StopFight</button>
|
||||
* <button type="button" data-ng-click="resetFight()">resetFight</button>
|
||||
* </div>
|
||||
* <div>
|
||||
* <div ng-controller="ExampleController">
|
||||
* Date format: <input ng-model="format"> <hr/>
|
||||
* Current time is: <span my-current-time="format"></span>
|
||||
* <hr/>
|
||||
* Blood 1 : <font color='red'>{{blood_1}}</font>
|
||||
* Blood 2 : <font color='red'>{{blood_2}}</font>
|
||||
* <button type="button" data-ng-click="fight()">Fight</button>
|
||||
* <button type="button" data-ng-click="stopFight()">StopFight</button>
|
||||
* <button type="button" data-ng-click="resetFight()">resetFight</button>
|
||||
* </div>
|
||||
* </div>
|
||||
*
|
||||
* </file>
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
function interval(fn, delay, count, invokeApply) {
|
||||
|
||||
+10
-2
@@ -427,14 +427,17 @@ LocationHashbangInHtml5Url.prototype =
|
||||
* If the argument is a hash object containing an array of values, these values will be encoded
|
||||
* as duplicate search parameters in the url.
|
||||
*
|
||||
* @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will
|
||||
* override only a single search property.
|
||||
* @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
|
||||
* will override only a single search property.
|
||||
*
|
||||
* If `paramValue` is an array, it will override the property of the `search` component of
|
||||
* `$location` specified via the first argument.
|
||||
*
|
||||
* If `paramValue` is `null`, the property specified via the first argument will be deleted.
|
||||
*
|
||||
* If `paramValue` is `true`, the property specified via the first argument will be added with no
|
||||
* value nor trailing equal sign.
|
||||
*
|
||||
* @return {Object} If called with no arguments returns the parsed `search` object. If called with
|
||||
* one or more arguments returns `$location` object itself.
|
||||
*/
|
||||
@@ -446,6 +449,11 @@ LocationHashbangInHtml5Url.prototype =
|
||||
if (isString(search)) {
|
||||
this.$$search = parseKeyValue(search);
|
||||
} else if (isObject(search)) {
|
||||
// remove object undefined or null properties
|
||||
forEach(search, function(value, key) {
|
||||
if (value == null) delete search[key];
|
||||
});
|
||||
|
||||
this.$$search = search;
|
||||
} else {
|
||||
throw $locationMinErr('isrcharg',
|
||||
|
||||
+8
-7
@@ -15,15 +15,16 @@
|
||||
* {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="logExample">
|
||||
<file name="script.js">
|
||||
function LogCtrl($scope, $log) {
|
||||
$scope.$log = $log;
|
||||
$scope.message = 'Hello World!';
|
||||
}
|
||||
angular.module('logExample', [])
|
||||
.controller('LogController', ['$scope', '$log', function($scope, $log) {
|
||||
$scope.$log = $log;
|
||||
$scope.message = 'Hello World!';
|
||||
}]);
|
||||
</file>
|
||||
<file name="index.html">
|
||||
<div ng-controller="LogCtrl">
|
||||
<div ng-controller="LogController">
|
||||
<p>Reload this page with open console, enter text and hit the log button...</p>
|
||||
Message:
|
||||
<input type="text" ng-model="message"/>
|
||||
@@ -47,7 +48,7 @@ function $LogProvider(){
|
||||
self = this;
|
||||
|
||||
/**
|
||||
* @ngdoc property
|
||||
* @ngdoc method
|
||||
* @name $logProvider#debugEnabled
|
||||
* @description
|
||||
* @param {boolean=} flag enable or disable debug level messages
|
||||
|
||||
+1
-26
@@ -985,26 +985,6 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
|
||||
};
|
||||
}
|
||||
|
||||
function simpleGetterFn1(key0, fullExp) {
|
||||
ensureSafeMemberName(key0, fullExp);
|
||||
|
||||
return function simpleGetterFn1(scope, locals) {
|
||||
if (scope == null) return undefined;
|
||||
return ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
|
||||
};
|
||||
}
|
||||
|
||||
function simpleGetterFn2(key0, key1, fullExp) {
|
||||
ensureSafeMemberName(key0, fullExp);
|
||||
ensureSafeMemberName(key1, fullExp);
|
||||
|
||||
return function simpleGetterFn2(scope, locals) {
|
||||
if (scope == null) return undefined;
|
||||
scope = ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
|
||||
return scope == null ? undefined : scope[key1];
|
||||
};
|
||||
}
|
||||
|
||||
function getterFn(path, options, fullExp) {
|
||||
// Check whether the cache has this getter already.
|
||||
// We can use hasOwnProperty directly on the cache because we ensure,
|
||||
@@ -1017,13 +997,8 @@ function getterFn(path, options, fullExp) {
|
||||
pathKeysLength = pathKeys.length,
|
||||
fn;
|
||||
|
||||
// When we have only 1 or 2 tokens, use optimized special case closures.
|
||||
// http://jsperf.com/angularjs-parse-getter/6
|
||||
if (!options.unwrapPromises && pathKeysLength === 1) {
|
||||
fn = simpleGetterFn1(pathKeys[0], fullExp);
|
||||
} else if (!options.unwrapPromises && pathKeysLength === 2) {
|
||||
fn = simpleGetterFn2(pathKeys[0], pathKeys[1], fullExp);
|
||||
} else if (options.csp) {
|
||||
if (options.csp) {
|
||||
if (pathKeysLength < 6) {
|
||||
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
|
||||
options);
|
||||
|
||||
+93
-92
@@ -112,19 +112,21 @@ function adjustMatchers(matchers) {
|
||||
*
|
||||
* Here is what a secure configuration for this scenario might look like:
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* angular.module('myApp', []).config(function($sceDelegateProvider) {
|
||||
* $sceDelegateProvider.resourceUrlWhitelist([
|
||||
* // Allow same origin resource loads.
|
||||
* 'self',
|
||||
* // Allow loading from our assets domain. Notice the difference between * and **.
|
||||
* 'http://srv*.assets.example.com/**']);
|
||||
* ```
|
||||
* angular.module('myApp', []).config(function($sceDelegateProvider) {
|
||||
* $sceDelegateProvider.resourceUrlWhitelist([
|
||||
* // Allow same origin resource loads.
|
||||
* 'self',
|
||||
* // Allow loading from our assets domain. Notice the difference between * and **.
|
||||
* 'http://srv*.assets.example.com/**'
|
||||
* ]);
|
||||
*
|
||||
* // The blacklist overrides the whitelist so the open redirect here is blocked.
|
||||
* $sceDelegateProvider.resourceUrlBlacklist([
|
||||
* 'http://myapp.example.com/clickThru**']);
|
||||
* });
|
||||
* </pre>
|
||||
* // The blacklist overrides the whitelist so the open redirect here is blocked.
|
||||
* $sceDelegateProvider.resourceUrlBlacklist([
|
||||
* 'http://myapp.example.com/clickThru**'
|
||||
* ]);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
function $SceDelegateProvider() {
|
||||
@@ -419,10 +421,10 @@ function $SceDelegateProvider() {
|
||||
*
|
||||
* Here's an example of a binding in a privileged context:
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* <input ng-model="userHtml">
|
||||
* <div ng-bind-html="userHtml">
|
||||
* </pre>
|
||||
* ```
|
||||
* <input ng-model="userHtml">
|
||||
* <div ng-bind-html="userHtml"></div>
|
||||
* ```
|
||||
*
|
||||
* Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
|
||||
* disabled, this application allows the user to render arbitrary HTML into the DIV.
|
||||
@@ -462,15 +464,15 @@ function $SceDelegateProvider() {
|
||||
* ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
|
||||
* simplified):
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* var ngBindHtmlDirective = ['$sce', function($sce) {
|
||||
* return function(scope, element, attr) {
|
||||
* scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
|
||||
* element.html(value || '');
|
||||
* });
|
||||
* };
|
||||
* }];
|
||||
* </pre>
|
||||
* ```
|
||||
* var ngBindHtmlDirective = ['$sce', function($sce) {
|
||||
* return function(scope, element, attr) {
|
||||
* scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
|
||||
* element.html(value || '');
|
||||
* });
|
||||
* };
|
||||
* }];
|
||||
* ```
|
||||
*
|
||||
* ## Impact on loading templates
|
||||
*
|
||||
@@ -574,66 +576,65 @@ function $SceDelegateProvider() {
|
||||
*
|
||||
* ## Show me an example using SCE.
|
||||
*
|
||||
* @example
|
||||
<example module="mySceApp" deps="angular-sanitize.js">
|
||||
<file name="index.html">
|
||||
<div ng-controller="myAppController as myCtrl">
|
||||
<i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
|
||||
<b>User comments</b><br>
|
||||
By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
|
||||
$sanitize is available. If $sanitize isn't available, this results in an error instead of an
|
||||
exploit.
|
||||
<div class="well">
|
||||
<div ng-repeat="userComment in myCtrl.userComments">
|
||||
<b>{{userComment.name}}</b>:
|
||||
<span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
var mySceApp = angular.module('mySceApp', ['ngSanitize']);
|
||||
|
||||
mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
|
||||
var self = this;
|
||||
$http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
|
||||
self.userComments = userComments;
|
||||
});
|
||||
self.explicitlyTrustedHtml = $sce.trustAsHtml(
|
||||
'<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
||||
'sanitization."">Hover over this text.</span>');
|
||||
});
|
||||
</file>
|
||||
|
||||
<file name="test_data.json">
|
||||
[
|
||||
{ "name": "Alice",
|
||||
"htmlComment":
|
||||
"<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
|
||||
},
|
||||
{ "name": "Bob",
|
||||
"htmlComment": "<i>Yes!</i> Am I the only other one?"
|
||||
}
|
||||
]
|
||||
</file>
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
describe('SCE doc demo', function() {
|
||||
it('should sanitize untrusted values', function() {
|
||||
expect(element(by.css('.htmlComment')).getInnerHtml())
|
||||
.toBe('<span>Is <i>anyone</i> reading this?</span>');
|
||||
});
|
||||
|
||||
it('should NOT sanitize explicitly trusted values', function() {
|
||||
expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
|
||||
'<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
||||
'sanitization."">Hover over this text.</span>');
|
||||
});
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
* <example module="mySceApp" deps="angular-sanitize.js">
|
||||
* <file name="index.html">
|
||||
* <div ng-controller="myAppController as myCtrl">
|
||||
* <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
|
||||
* <b>User comments</b><br>
|
||||
* By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
|
||||
* $sanitize is available. If $sanitize isn't available, this results in an error instead of an
|
||||
* exploit.
|
||||
* <div class="well">
|
||||
* <div ng-repeat="userComment in myCtrl.userComments">
|
||||
* <b>{{userComment.name}}</b>:
|
||||
* <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
|
||||
* <br>
|
||||
* </div>
|
||||
* </div>
|
||||
* </div>
|
||||
* </file>
|
||||
*
|
||||
* <file name="script.js">
|
||||
* var mySceApp = angular.module('mySceApp', ['ngSanitize']);
|
||||
*
|
||||
* mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
|
||||
* var self = this;
|
||||
* $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
|
||||
* self.userComments = userComments;
|
||||
* });
|
||||
* self.explicitlyTrustedHtml = $sce.trustAsHtml(
|
||||
* '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
||||
* 'sanitization."">Hover over this text.</span>');
|
||||
* });
|
||||
* </file>
|
||||
*
|
||||
* <file name="test_data.json">
|
||||
* [
|
||||
* { "name": "Alice",
|
||||
* "htmlComment":
|
||||
* "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
|
||||
* },
|
||||
* { "name": "Bob",
|
||||
* "htmlComment": "<i>Yes!</i> Am I the only other one?"
|
||||
* }
|
||||
* ]
|
||||
* </file>
|
||||
*
|
||||
* <file name="protractor.js" type="protractor">
|
||||
* describe('SCE doc demo', function() {
|
||||
* it('should sanitize untrusted values', function() {
|
||||
* expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
|
||||
* .toBe('<span>Is <i>anyone</i> reading this?</span>');
|
||||
* });
|
||||
*
|
||||
* it('should NOT sanitize explicitly trusted values', function() {
|
||||
* expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
|
||||
* '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
||||
* 'sanitization."">Hover over this text.</span>');
|
||||
* });
|
||||
* });
|
||||
* </file>
|
||||
* </example>
|
||||
*
|
||||
*
|
||||
*
|
||||
@@ -647,13 +648,13 @@ function $SceDelegateProvider() {
|
||||
*
|
||||
* That said, here's how you can completely disable SCE:
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
|
||||
* // Completely disable SCE. For demonstration purposes only!
|
||||
* // Do not use in new projects.
|
||||
* $sceProvider.enabled(false);
|
||||
* });
|
||||
* </pre>
|
||||
* ```
|
||||
* angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
|
||||
* // Completely disable SCE. For demonstration purposes only!
|
||||
* // Do not use in new projects.
|
||||
* $sceProvider.enabled(false);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
/* jshint maxlen: 100 */
|
||||
|
||||
+8
-7
@@ -16,17 +16,18 @@
|
||||
* expression.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<example module="windowExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope, $window) {
|
||||
$scope.greeting = 'Hello, World!';
|
||||
$scope.doGreeting = function(greeting) {
|
||||
angular.module('windowExample', [])
|
||||
.controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
|
||||
$scope.greeting = 'Hello, World!';
|
||||
$scope.doGreeting = function(greeting) {
|
||||
$window.alert(greeting);
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
<input type="text" ng-model="greeting" />
|
||||
<button ng-click="doGreeting(greeting)">ALERT</button>
|
||||
</div>
|
||||
|
||||
+75
-19
@@ -58,8 +58,22 @@
|
||||
* <ANY class="slide" ng-include="..."></ANY>
|
||||
* ```
|
||||
*
|
||||
* Keep in mind that if an animation is running, any child elements cannot be animated until the parent element's
|
||||
* animation has completed.
|
||||
* Keep in mind that, by default, if an animation is running, any child elements cannot be animated
|
||||
* until the parent element's animation has completed. This blocking feature can be overridden by
|
||||
* placing the `ng-animate-children` attribute on a parent container tag.
|
||||
*
|
||||
* ```html
|
||||
* <div class="slide-animation" ng-if="on" ng-animate-children>
|
||||
* <div class="fade-animation" ng-if="on">
|
||||
* <div class="explode-animation" ng-if="on">
|
||||
* ...
|
||||
* </div>
|
||||
* </div>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* When the `on` expression value changes and an animation is triggered then each of the elements within
|
||||
* will all animate without the block being applied to child elements.
|
||||
*
|
||||
* <h2>CSS-defined Animations</h2>
|
||||
* The animate service will automatically apply two CSS classes to the animated element and these two CSS classes
|
||||
@@ -249,6 +263,19 @@ angular.module('ngAnimate', ['ng'])
|
||||
* Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
|
||||
*
|
||||
*/
|
||||
.directive('ngAnimateChildren', function() {
|
||||
var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
|
||||
return function(scope, element, attrs) {
|
||||
var val = attrs.ngAnimateChildren;
|
||||
if(angular.isString(val) && val.length === 0) { //empty attribute
|
||||
element.data(NG_ANIMATE_CHILDREN, true);
|
||||
} else {
|
||||
scope.$watch(val, function(value) {
|
||||
element.data(NG_ANIMATE_CHILDREN, !!value);
|
||||
});
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
//this private service is only used within CSS-enabled animations
|
||||
//IE8 + IE9 do not support rAF natively, but that is fine since they
|
||||
@@ -277,6 +304,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
|
||||
var ELEMENT_NODE = 1;
|
||||
var NG_ANIMATE_STATE = '$$ngAnimateState';
|
||||
var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
|
||||
var NG_ANIMATE_CLASS_NAME = 'ng-animate';
|
||||
var rootAnimateState = {running: true};
|
||||
|
||||
@@ -326,6 +354,12 @@ angular.module('ngAnimate', ['ng'])
|
||||
return classNameFilter.test(className);
|
||||
};
|
||||
|
||||
function blockElementAnimations(element) {
|
||||
var data = element.data(NG_ANIMATE_STATE) || {};
|
||||
data.running = true;
|
||||
element.data(NG_ANIMATE_STATE, data);
|
||||
}
|
||||
|
||||
function lookup(name) {
|
||||
if (name) {
|
||||
var matches = [],
|
||||
@@ -552,7 +586,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
parentElement = prepareElement(parentElement);
|
||||
afterElement = prepareElement(afterElement);
|
||||
|
||||
this.enabled(false, element);
|
||||
blockElementAnimations(element);
|
||||
$delegate.enter(element, parentElement, afterElement);
|
||||
$rootScope.$$postDigest(function() {
|
||||
element = stripCommentsFromElement(element);
|
||||
@@ -590,7 +624,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
leave : function(element, doneCallback) {
|
||||
element = angular.element(element);
|
||||
cancelChildAnimations(element);
|
||||
this.enabled(false, element);
|
||||
blockElementAnimations(element);
|
||||
$rootScope.$$postDigest(function() {
|
||||
performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {
|
||||
$delegate.leave(element);
|
||||
@@ -634,7 +668,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
afterElement = prepareElement(afterElement);
|
||||
|
||||
cancelChildAnimations(element);
|
||||
this.enabled(false, element);
|
||||
blockElementAnimations(element);
|
||||
$delegate.move(element, parentElement, afterElement);
|
||||
$rootScope.$$postDigest(function() {
|
||||
element = stripCommentsFromElement(element);
|
||||
@@ -808,9 +842,12 @@ angular.module('ngAnimate', ['ng'])
|
||||
|
||||
//only allow animations if the currently running animation is not structural
|
||||
//or if there is no animation running at all
|
||||
var skipAnimations = runner.isClassBased ?
|
||||
ngAnimateState.disabled || (lastAnimation && !lastAnimation.isClassBased) :
|
||||
false;
|
||||
var skipAnimations;
|
||||
if (runner.isClassBased) {
|
||||
skipAnimations = ngAnimateState.running ||
|
||||
ngAnimateState.disabled ||
|
||||
(lastAnimation && !lastAnimation.isClassBased);
|
||||
}
|
||||
|
||||
//skip the animation if animations are disabled, a parent is already being animated,
|
||||
//the element is not currently attached to the document body or then completely close
|
||||
@@ -1027,30 +1064,49 @@ angular.module('ngAnimate', ['ng'])
|
||||
}
|
||||
|
||||
function animationsDisabled(element, parentElement) {
|
||||
if (rootAnimateState.disabled) return true;
|
||||
|
||||
if(isMatchingElement(element, $rootElement)) {
|
||||
return rootAnimateState.disabled || rootAnimateState.running;
|
||||
if (rootAnimateState.disabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMatchingElement(element, $rootElement)) {
|
||||
return rootAnimateState.running;
|
||||
}
|
||||
|
||||
var allowChildAnimations, parentRunningAnimation, hasParent;
|
||||
do {
|
||||
//the element did not reach the root element which means that it
|
||||
//is not apart of the DOM. Therefore there is no reason to do
|
||||
//any animations on it
|
||||
if(parentElement.length === 0) break;
|
||||
if (parentElement.length === 0) break;
|
||||
|
||||
var isRoot = isMatchingElement(parentElement, $rootElement);
|
||||
var state = isRoot ? rootAnimateState : parentElement.data(NG_ANIMATE_STATE);
|
||||
var result = state && (!!state.disabled || state.running || state.totalActive > 0);
|
||||
if(isRoot || result) {
|
||||
return result;
|
||||
var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});
|
||||
if (state.disabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(isRoot) return true;
|
||||
//no matter what, for an animation to work it must reach the root element
|
||||
//this implies that the element is attached to the DOM when the animation is run
|
||||
if (isRoot) {
|
||||
hasParent = true;
|
||||
}
|
||||
|
||||
//once a flag is found that is strictly false then everything before
|
||||
//it will be discarded and all child animations will be restricted
|
||||
if (allowChildAnimations !== false) {
|
||||
var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);
|
||||
if(angular.isDefined(animateChildrenFlag)) {
|
||||
allowChildAnimations = animateChildrenFlag;
|
||||
}
|
||||
}
|
||||
|
||||
parentRunningAnimation = parentRunningAnimation ||
|
||||
state.running ||
|
||||
(state.last && !state.last.isClassBased);
|
||||
}
|
||||
while(parentElement = parentElement.parent());
|
||||
|
||||
return true;
|
||||
return !hasParent || (!allowChildAnimations && parentRunningAnimation);
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
+16
-14
@@ -34,12 +34,13 @@ angular.module('ngCookies', ['ng']).
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* function ExampleController($cookies) {
|
||||
* // Retrieving a cookie
|
||||
* var favoriteCookie = $cookies.myFavorite;
|
||||
* // Setting a cookie
|
||||
* $cookies.myFavorite = 'oatmeal';
|
||||
* }
|
||||
* angular.module('cookiesExample', ['ngCookies'])
|
||||
* .controller('ExampleController', ['$cookies', function($cookies) {
|
||||
* // Retrieving a cookie
|
||||
* var favoriteCookie = $cookies.myFavorite;
|
||||
* // Setting a cookie
|
||||
* $cookies.myFavorite = 'oatmeal';
|
||||
* }]);
|
||||
* ```
|
||||
*/
|
||||
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
|
||||
@@ -137,14 +138,15 @@ angular.module('ngCookies', ['ng']).
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* function ExampleController($cookies) {
|
||||
* // Put cookie
|
||||
* $cookieStore.put('myFavorite','oatmeal');
|
||||
* // Get cookie
|
||||
* var favoriteCookie = $cookieStore.get('myFavorite');
|
||||
* // Removing a cookie
|
||||
* $cookieStore.remove('myFavorite');
|
||||
* }
|
||||
* angular.module('cookieStoreExample', ['ngCookies'])
|
||||
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
|
||||
* // Put cookie
|
||||
* $cookieStore.put('myFavorite','oatmeal');
|
||||
* // Get cookie
|
||||
* var favoriteCookie = $cookieStore.get('myFavorite');
|
||||
* // Removing a cookie
|
||||
* $cookieStore.remove('myFavorite');
|
||||
* }]);
|
||||
* ```
|
||||
*/
|
||||
factory('$cookieStore', ['$cookies', function($cookies) {
|
||||
|
||||
@@ -21,20 +21,21 @@
|
||||
<span ng-bind-html="linky_expression | linky"></span>
|
||||
*
|
||||
* @example
|
||||
<example module="ngSanitize" deps="angular-sanitize.js">
|
||||
<example module="linkyExample" deps="angular-sanitize.js">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope) {
|
||||
$scope.snippet =
|
||||
'Pretty text with some links:\n'+
|
||||
'http://angularjs.org/,\n'+
|
||||
'mailto:us@somewhere.org,\n'+
|
||||
'another@somewhere.org,\n'+
|
||||
'and one more: ftp://127.0.0.1/.';
|
||||
$scope.snippetWithTarget = 'http://angularjs.org/';
|
||||
}
|
||||
angular.module('linkyExample', ['ngSanitize'])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.snippet =
|
||||
'Pretty text with some links:\n'+
|
||||
'http://angularjs.org/,\n'+
|
||||
'mailto:us@somewhere.org,\n'+
|
||||
'another@somewhere.org,\n'+
|
||||
'and one more: ftp://127.0.0.1/.';
|
||||
$scope.snippetWithTarget = 'http://angularjs.org/';
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
||||
<table>
|
||||
<tr>
|
||||
|
||||
+12
-11
@@ -52,20 +52,21 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
|
||||
* @returns {string} Sanitized html.
|
||||
*
|
||||
* @example
|
||||
<example module="ngSanitize" deps="angular-sanitize.js">
|
||||
<example module="sanitizeExample" deps="angular-sanitize.js">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
function Ctrl($scope, $sce) {
|
||||
$scope.snippet =
|
||||
'<p style="color:blue">an html\n' +
|
||||
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
|
||||
'snippet</p>';
|
||||
$scope.deliberatelyTrustDangerousSnippet = function() {
|
||||
return $sce.trustAsHtml($scope.snippet);
|
||||
};
|
||||
}
|
||||
angular.module('sanitizeExample', ['ngSanitize'])
|
||||
.controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
|
||||
$scope.snippet =
|
||||
'<p style="color:blue">an html\n' +
|
||||
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
|
||||
'snippet</p>';
|
||||
$scope.deliberatelyTrustDangerousSnippet = function() {
|
||||
return $sce.trustAsHtml($scope.snippet);
|
||||
};
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="Ctrl">
|
||||
<div ng-controller="ExampleController">
|
||||
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
||||
<table>
|
||||
<tr>
|
||||
|
||||
+22
-23
@@ -16,6 +16,7 @@
|
||||
"sub": true,
|
||||
"undef": true,
|
||||
"browser": true,
|
||||
"indent": 2,
|
||||
"globals": {
|
||||
/* auto/injector.js */
|
||||
"createInjector": false,
|
||||
@@ -42,7 +43,6 @@
|
||||
"isArrayLike": false,
|
||||
"forEach": false,
|
||||
"sortedKeys": false,
|
||||
"forEachSorted": false,
|
||||
"reverseParams": false,
|
||||
"nextUid": false,
|
||||
"setHashKey": false,
|
||||
@@ -103,9 +103,6 @@
|
||||
"getBlockElements": false,
|
||||
"VALIDITY_STATE_PROPERTY": true,
|
||||
|
||||
/* filters.js */
|
||||
"getFirstThursdayOfYear": false,
|
||||
|
||||
/* AngularPublic.js */
|
||||
"version": false,
|
||||
"publishExternalAPI": false,
|
||||
@@ -148,24 +145,6 @@
|
||||
"urlResolve": false,
|
||||
"urlIsSameOrigin": false,
|
||||
|
||||
/* ng/compile.js */
|
||||
"directiveNormalize": false,
|
||||
|
||||
/* ng/parse.js */
|
||||
"setter": false,
|
||||
|
||||
/* ng/directive/directives.js */
|
||||
"ngDirective": false,
|
||||
|
||||
/* ng/directive/input.js */
|
||||
"VALID_CLASS": false,
|
||||
"INVALID_CLASS": false,
|
||||
"PRISTINE_CLASS": false,
|
||||
"DIRTY_CLASS": false,
|
||||
|
||||
/* ng/directive/form.js */
|
||||
"nullFormCtrl": false,
|
||||
|
||||
/* jasmine / karma */
|
||||
"it": false,
|
||||
"iit": false,
|
||||
@@ -176,10 +155,30 @@
|
||||
"expect": false,
|
||||
"jasmine": false,
|
||||
"spyOn": false,
|
||||
"waits": false,
|
||||
"waitsFor": false,
|
||||
"runs": false,
|
||||
"dump": false,
|
||||
|
||||
/* e2e */
|
||||
"browser": false,
|
||||
"element": false,
|
||||
"by": false,
|
||||
|
||||
/* testabilityPatch / matchers */
|
||||
"inject": false,
|
||||
"module": false,
|
||||
"dealoc": false
|
||||
"dealoc": false,
|
||||
"dealoc": false,
|
||||
"_jQuery": false,
|
||||
"_jqLiteMode": false,
|
||||
"sortedHtml": false,
|
||||
"childrenTagsOf": false,
|
||||
"assertHidden": false,
|
||||
"assertVisible": false,
|
||||
"provideLog": false,
|
||||
"spyOnlyCallsWithArgs": false,
|
||||
"createMockStyleSheet": false,
|
||||
"browserTrigger": false
|
||||
}
|
||||
}
|
||||
|
||||
+33
-20
@@ -118,7 +118,7 @@ describe('angular', function() {
|
||||
|
||||
it('should throw an exception when source and destination are equivalent', function() {
|
||||
var src, dst;
|
||||
src = dst = {key: 'value'};
|
||||
src = dst = {key: 'value'};
|
||||
expect(function() { copy(src, dst); }).toThrowMinErr("ng", "cpi", "Can't copy! Source and destination are identical.");
|
||||
src = dst = [2, 4];
|
||||
expect(function() { copy(src, dst); }).toThrowMinErr("ng", "cpi", "Can't copy! Source and destination are identical.");
|
||||
@@ -223,7 +223,7 @@ describe('angular', function() {
|
||||
|
||||
it('should omit properties from prototype chain', function() {
|
||||
var original, clone = {};
|
||||
function Func() {};
|
||||
function Func() {}
|
||||
Func.prototype.hello = "world";
|
||||
|
||||
original = new Func();
|
||||
@@ -349,6 +349,7 @@ describe('angular', function() {
|
||||
});
|
||||
|
||||
it('should correctly test for keys that are present on Object.prototype', function() {
|
||||
/* 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!
|
||||
if (msie<=8) return;
|
||||
@@ -470,6 +471,13 @@ describe('angular', function() {
|
||||
expect(parseKeyValue('flag1&flag1=value&flag1=value2&flag1')).
|
||||
toEqual({flag1: [true,'value','value2',true]});
|
||||
});
|
||||
|
||||
|
||||
it('should ignore properties higher in the prototype chain', function() {
|
||||
expect(parseKeyValue('toString=123')).toEqual({
|
||||
'toString': '123'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toKeyValue', function() {
|
||||
@@ -490,7 +498,7 @@ describe('angular', function() {
|
||||
expect(toKeyValue({key: [323,'value',true]})).toEqual('key=323&key=value&key');
|
||||
expect(toKeyValue({key: [323,'value',true, 1234]})).
|
||||
toEqual('key=323&key=value&key&key=1234');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -505,13 +513,14 @@ describe('angular', function() {
|
||||
var obj = new MyObj(),
|
||||
log = [];
|
||||
|
||||
forEach(obj, function(value, key) { log.push(key + ':' + value)});
|
||||
forEach(obj, function(value, key) { log.push(key + ':' + value); });
|
||||
|
||||
expect(log).toEqual(['bar:barVal', 'baz:bazVal']);
|
||||
});
|
||||
|
||||
|
||||
it('should not break if obj is an array we override hasOwnProperty', function() {
|
||||
/* jshint -W001 */
|
||||
var obj = [];
|
||||
obj[0] = 1;
|
||||
obj[1] = 2;
|
||||
@@ -539,7 +548,7 @@ describe('angular', function() {
|
||||
log = [];
|
||||
|
||||
|
||||
forEach(nodeList, function(value, key) { log.push(key + ':' + value.innerHTML)});
|
||||
forEach(nodeList, function(value, key) { log.push(key + ':' + value.innerHTML); });
|
||||
expect(log).toEqual(['0:a', '1:b', '2:c']);
|
||||
});
|
||||
|
||||
@@ -554,7 +563,7 @@ describe('angular', function() {
|
||||
var htmlCollection = document.getElementsByName('x'),
|
||||
log = [];
|
||||
|
||||
forEach(htmlCollection, function(value, key) { log.push(key + ':' + value.innerHTML)});
|
||||
forEach(htmlCollection, function(value, key) { log.push(key + ':' + value.innerHTML); });
|
||||
expect(log).toEqual(['0:a', '1:c']);
|
||||
});
|
||||
|
||||
@@ -569,7 +578,7 @@ describe('angular', function() {
|
||||
var htmlCollection = document.querySelectorAll('[name="x"]'),
|
||||
log = [];
|
||||
|
||||
forEach(htmlCollection, function(value, key) { log.push(key + ':' + value.innerHTML)});
|
||||
forEach(htmlCollection, function(value, key) { log.push(key + ':' + value.innerHTML); });
|
||||
expect(log).toEqual(['0:a', '1:c']);
|
||||
});
|
||||
}
|
||||
@@ -578,28 +587,28 @@ describe('angular', function() {
|
||||
var args,
|
||||
log = [];
|
||||
|
||||
(function(){ args = arguments}('a', 'b', 'c'));
|
||||
(function(){ args = arguments; }('a', 'b', 'c'));
|
||||
|
||||
forEach(args, function(value, key) { log.push(key + ':' + value)});
|
||||
forEach(args, function(value, key) { log.push(key + ':' + value); });
|
||||
expect(log).toEqual(['0:a', '1:b', '2:c']);
|
||||
});
|
||||
|
||||
it('should handle string values like arrays', function() {
|
||||
var log = [];
|
||||
|
||||
forEach('bar', function(value, key) { log.push(key + ':' + value)});
|
||||
forEach('bar', function(value, key) { log.push(key + ':' + value); });
|
||||
expect(log).toEqual(['0:b', '1:a', '2:r']);
|
||||
});
|
||||
|
||||
|
||||
it('should handle objects with length property as objects', function() {
|
||||
var obj = {
|
||||
'foo' : 'bar',
|
||||
'length': 2
|
||||
},
|
||||
log = [];
|
||||
'foo' : 'bar',
|
||||
'length': 2
|
||||
},
|
||||
log = [];
|
||||
|
||||
forEach(obj, function(value, key) { log.push(key + ':' + value)});
|
||||
forEach(obj, function(value, key) { log.push(key + ':' + value); });
|
||||
expect(log).toEqual(['foo:bar', 'length:2']);
|
||||
});
|
||||
|
||||
@@ -607,13 +616,13 @@ describe('angular', function() {
|
||||
it('should handle objects of custom types with length property as objects', function() {
|
||||
function CustomType() {
|
||||
this.length = 2;
|
||||
this.foo = 'bar'
|
||||
this.foo = 'bar';
|
||||
}
|
||||
|
||||
var obj = new CustomType(),
|
||||
log = [];
|
||||
|
||||
forEach(obj, function(value, key) { log.push(key + ':' + value)});
|
||||
forEach(obj, function(value, key) { log.push(key + ':' + value); });
|
||||
expect(log).toEqual(['length:2', 'foo:bar']);
|
||||
});
|
||||
});
|
||||
@@ -783,7 +792,9 @@ describe('angular', function() {
|
||||
expect(function() {
|
||||
angularInit(appElement, bootstrap);
|
||||
}).toThrowMatching(
|
||||
/\[\$injector:modulerr] Failed to instantiate module doesntexist due to:\n.*\[\$injector:nomod] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it\./
|
||||
new RegExp('\\[\\$injector:modulerr] Failed to instantiate module doesntexist due to:\\n' +
|
||||
'.*\\[\\$injector:nomod] Module \'doesntexist\' is not available! You either ' +
|
||||
'misspelled the module name or forgot to load it\\.')
|
||||
);
|
||||
});
|
||||
|
||||
@@ -811,7 +822,7 @@ describe('angular', function() {
|
||||
);
|
||||
|
||||
dealoc(document);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -972,7 +983,9 @@ describe('angular', function() {
|
||||
expect(function() {
|
||||
angular.bootstrap(element, ['doesntexist']);
|
||||
}).toThrowMatching(
|
||||
/\[\$injector:modulerr\] Failed to instantiate module doesntexist due to:\n.*\[\$injector:nomod\] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it\./);
|
||||
new RegExp('\\[\\$injector:modulerr\\] Failed to instantiate module doesntexist due to:\\n' +
|
||||
'.*\\[\\$injector:nomod\\] Module \'doesntexist\' is not available! You either ' +
|
||||
'misspelled the module name or forgot to load it\\.'));
|
||||
|
||||
expect(element.html()).toBe('{{1+2}}');
|
||||
dealoc(element);
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ describe('Binder', function() {
|
||||
var errorLogs = $exceptionHandler.errors;
|
||||
|
||||
$rootScope.error = {
|
||||
'throw': function() {throw 'ErrorMsg1';}
|
||||
'throw': function() {throw 'ErrorMsg1';}
|
||||
};
|
||||
$rootScope.$apply();
|
||||
|
||||
|
||||
+32
-29
@@ -110,6 +110,7 @@ describe('injector', function() {
|
||||
|
||||
|
||||
function fn(a, b, c, d) {
|
||||
/* jshint -W040 */
|
||||
args = [this, a, b, c, d];
|
||||
return a + b + c + d;
|
||||
}
|
||||
@@ -147,6 +148,7 @@ describe('injector', function() {
|
||||
|
||||
|
||||
describe('annotation', function() {
|
||||
/* global annotate: false */
|
||||
it('should return $inject', function() {
|
||||
function fn() {}
|
||||
fn.$inject = ['a'];
|
||||
@@ -159,6 +161,7 @@ describe('injector', function() {
|
||||
|
||||
|
||||
it('should create $inject', function() {
|
||||
var extraParans = angular.noop;
|
||||
// keep the multi-line to make sure we can handle it
|
||||
function $f_n0 /*
|
||||
*/(
|
||||
@@ -175,7 +178,7 @@ describe('injector', function() {
|
||||
|
||||
|
||||
it('should strip leading and trailing underscores from arg name during inference', function() {
|
||||
function beforeEachFn(_foo_) { /* foo = _foo_ */ };
|
||||
function beforeEachFn(_foo_) { /* foo = _foo_ */ }
|
||||
expect(annotate(beforeEachFn)).toEqual(['foo']);
|
||||
});
|
||||
|
||||
@@ -239,10 +242,9 @@ describe('injector', function() {
|
||||
|
||||
describe('module', function() {
|
||||
it('should provide $injector even when no module is requested', function() {
|
||||
var $provide,
|
||||
$injector = createInjector([
|
||||
angular.extend(function(p) { $provide = p; }, {$inject: ['$provide']})
|
||||
]);
|
||||
var $provide, $injector = createInjector([
|
||||
angular.extend(function(p) { $provide = p; }, {$inject: ['$provide']})
|
||||
]);
|
||||
expect($injector.get('$injector')).toBe($injector);
|
||||
});
|
||||
|
||||
@@ -321,9 +323,9 @@ describe('injector', function() {
|
||||
angular.module('a', [], function(){ log += 'a'; }).run(function() { log += 'A'; });
|
||||
angular.module('b', ['a'], function(){ log += 'b'; }).run(function() { log += 'B'; });
|
||||
createInjector([
|
||||
'b',
|
||||
valueFn(function() { log += 'C'; }),
|
||||
[valueFn(function() { log += 'D'; })]
|
||||
'b',
|
||||
valueFn(function() { log += 'C'; }),
|
||||
[valueFn(function() { log += 'D'; })]
|
||||
]);
|
||||
expect(log).toEqual('abABCD');
|
||||
});
|
||||
@@ -351,19 +353,19 @@ describe('injector', function() {
|
||||
it('should create configuration injectable constants', function() {
|
||||
var log = [];
|
||||
createInjector([
|
||||
function($provide){
|
||||
$provide.constant('abc', 123);
|
||||
$provide.constant({a: 'A', b:'B'});
|
||||
return function(a) {
|
||||
log.push(a);
|
||||
}
|
||||
},
|
||||
function(abc) {
|
||||
log.push(abc);
|
||||
return function(b) {
|
||||
log.push(b);
|
||||
}
|
||||
}
|
||||
function($provide){
|
||||
$provide.constant('abc', 123);
|
||||
$provide.constant({a: 'A', b:'B'});
|
||||
return function(a) {
|
||||
log.push(a);
|
||||
};
|
||||
},
|
||||
function(abc) {
|
||||
log.push(abc);
|
||||
return function(b) {
|
||||
log.push(b);
|
||||
};
|
||||
}
|
||||
]).get('abc');
|
||||
expect(log).toEqual([123, 'A', 'B']);
|
||||
});
|
||||
@@ -445,7 +447,7 @@ describe('injector', function() {
|
||||
|
||||
|
||||
it('should configure $provide provider type', function() {
|
||||
function Type() {};
|
||||
function Type() {}
|
||||
Type.prototype.$get = function() {
|
||||
expect(this instanceof Type).toBe(true);
|
||||
return 'abc';
|
||||
@@ -459,7 +461,7 @@ describe('injector', function() {
|
||||
it('should configure $provide using an array', function() {
|
||||
function Type(PREFIX) {
|
||||
this.prefix = PREFIX;
|
||||
};
|
||||
}
|
||||
Type.prototype.$get = function() {
|
||||
return this.prefix + 'def';
|
||||
};
|
||||
@@ -550,7 +552,7 @@ describe('injector', function() {
|
||||
return function(val) {
|
||||
log.push('myService:' + val + ',' + dep1);
|
||||
return 'origReturn';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
$provide.decorator('myService', function($delegate) {
|
||||
@@ -577,7 +579,7 @@ describe('injector', function() {
|
||||
return function(val) {
|
||||
log.push('myService:' + val);
|
||||
return 'origReturn';
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
$provide.decorator('myService', function($delegate, dep1) {
|
||||
@@ -727,7 +729,8 @@ describe('injector', function() {
|
||||
})).toEqual('melville:moby');
|
||||
expect($injector.invoke(function(book, author) {
|
||||
expect(this).toEqual($injector);
|
||||
return author + ':' + book;}, $injector)).toEqual('melville:moby');
|
||||
return author + ':' + book;
|
||||
}, $injector)).toEqual('melville:moby');
|
||||
});
|
||||
|
||||
|
||||
@@ -745,7 +748,7 @@ describe('injector', function() {
|
||||
|
||||
it('should invoke method which is annotated', function() {
|
||||
expect($injector.invoke(extend(function(b, a) {
|
||||
return a + ':' + b
|
||||
return a + ':' + b;
|
||||
}, {$inject:['book', 'author']}))).toEqual('melville:moby');
|
||||
expect($injector.invoke(extend(function(b, a) {
|
||||
expect(this).toEqual($injector);
|
||||
@@ -878,10 +881,10 @@ describe('injector', function() {
|
||||
|
||||
|
||||
it('should prevent instance lookup in module', function() {
|
||||
function instanceLookupInModule(name) { throw Error('FAIL'); }
|
||||
function instanceLookupInModule(name) { throw new Error('FAIL'); }
|
||||
expect(function() {
|
||||
createInjector([function($provide) {
|
||||
$provide.value('name', 'angular')
|
||||
$provide.value('name', 'angular');
|
||||
}, instanceLookupInModule]);
|
||||
}).toThrowMatching(/\[\$injector:unpr] Unknown provider: name/);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
describe('docs.angularjs.org', function () {
|
||||
describe('App', function () {
|
||||
// it('should filter the module list when searching', function () {
|
||||
// browser.get();
|
||||
// browser.waitForAngular();
|
||||
|
||||
// var search = element(by.input('q'));
|
||||
// var search = element(by.model('q'));
|
||||
// search.clear();
|
||||
// search.sendKeys('ngBind');
|
||||
|
||||
@@ -32,7 +34,7 @@ describe('docs.angularjs.org', function () {
|
||||
|
||||
browser.switchTo().frame('example-input-directive');
|
||||
|
||||
var nameInput = element(by.input('user.name'));
|
||||
var nameInput = element(by.model('user.name'));
|
||||
nameInput.sendKeys('!!!');
|
||||
|
||||
var code = element(by.css('tt'));
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
beforeEach(function() {
|
||||
|
||||
function cssMatcher(presentClasses, absentClasses) {
|
||||
@@ -39,7 +41,7 @@ beforeEach(function() {
|
||||
}
|
||||
});
|
||||
return hidden;
|
||||
};
|
||||
}
|
||||
|
||||
this.addMatchers({
|
||||
toBeInvalid: cssMatcher('ng-invalid', 'ng-valid'),
|
||||
@@ -128,7 +130,7 @@ beforeEach(function() {
|
||||
|
||||
this.message = function() {
|
||||
if (this.actual.callCount != 1) {
|
||||
if (this.actual.callCount == 0) {
|
||||
if (this.actual.callCount === 0) {
|
||||
return [
|
||||
'Expected spy ' + this.actual.identity + ' to have been called once with ' +
|
||||
jasmine.pp(expectedArgs) + ' but it was never called.',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
function createMockStyleSheet(doc, wind) {
|
||||
doc = doc ? doc[0] : document;
|
||||
wind = wind || window;
|
||||
@@ -17,7 +19,7 @@ function createMockStyleSheet(doc, wind) {
|
||||
try {
|
||||
ss.addRule(selector, styles);
|
||||
}
|
||||
catch(e) {}
|
||||
catch(e2) {}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -25,4 +27,4 @@ function createMockStyleSheet(doc, wind) {
|
||||
head.removeChild(node);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
describe('private mocks', function() {
|
||||
describe('createMockStyleSheet', function() {
|
||||
|
||||
@@ -29,7 +31,7 @@ describe('private mocks', function() {
|
||||
return node.currentStyle ?
|
||||
node.currentStyle[key] :
|
||||
$window.getComputedStyle(node)[key];
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* global jQuery: true, uid: true */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
@@ -150,7 +151,7 @@ function sortedHtml(element, showNgClass) {
|
||||
|
||||
var attr = attributes[i];
|
||||
if(attr.name.match(/^ng[\:\-]/) ||
|
||||
(attr.value || attr.value == '') &&
|
||||
(attr.value || attr.value === '') &&
|
||||
attr.value !='null' &&
|
||||
attr.value !='auto' &&
|
||||
attr.value !='false' &&
|
||||
@@ -283,7 +284,7 @@ function provideLog($provide) {
|
||||
var currentMessages = messages;
|
||||
messages = [];
|
||||
return currentMessages;
|
||||
}
|
||||
};
|
||||
|
||||
log.fn = function(msg) {
|
||||
return function() {
|
||||
@@ -299,7 +300,7 @@ function provideLog($provide) {
|
||||
|
||||
function pending() {
|
||||
dump('PENDING');
|
||||
};
|
||||
}
|
||||
|
||||
function trace(name) {
|
||||
dump(new Error(name).stack);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* global $: false */
|
||||
'use strict';
|
||||
|
||||
if (window.jQuery) {
|
||||
|
||||
+41
-38
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
describe('jqLite', function() {
|
||||
var scope, a, b, c;
|
||||
|
||||
@@ -57,7 +59,7 @@ describe('jqLite', function() {
|
||||
it('should allow construction with html', function() {
|
||||
var nodes = jqLite('<div>1</div><span>2</span>');
|
||||
expect(nodes[0].parentNode).toBeDefined();
|
||||
expect(nodes[0].parentNode.nodeType).toBe(11); /** Document Fragment **/;
|
||||
expect(nodes[0].parentNode.nodeType).toBe(11); /** Document Fragment **/
|
||||
expect(nodes[0].parentNode).toBe(nodes[1].parentNode);
|
||||
expect(nodes.length).toEqual(2);
|
||||
expect(nodes[0].innerHTML).toEqual('1');
|
||||
@@ -68,7 +70,7 @@ describe('jqLite', function() {
|
||||
it('should allow construction of html with leading whitespace', function() {
|
||||
var nodes = jqLite(' \n\r \r\n<div>1</div><span>2</span>');
|
||||
expect(nodes[0].parentNode).toBeDefined();
|
||||
expect(nodes[0].parentNode.nodeType).toBe(11); /** Document Fragment **/;
|
||||
expect(nodes[0].parentNode.nodeType).toBe(11); /** Document Fragment **/
|
||||
expect(nodes[0].parentNode).toBe(nodes[1].parentNode);
|
||||
expect(nodes.length).toBe(2);
|
||||
expect(nodes[0].innerHTML).toBe('1');
|
||||
@@ -473,7 +475,7 @@ describe('jqLite', function() {
|
||||
span = div.find('span'),
|
||||
log = '';
|
||||
|
||||
span.on('click', function() { log+= 'click;'});
|
||||
span.on('click', function() { log+= 'click;'; });
|
||||
browserTrigger(span);
|
||||
expect(log).toEqual('click;');
|
||||
|
||||
@@ -945,21 +947,21 @@ describe('jqLite', function() {
|
||||
if (jqLite.fn) return; // don't run in jQuery
|
||||
var eventFn;
|
||||
var window = {
|
||||
document: {},
|
||||
location: {},
|
||||
alert: noop,
|
||||
setInterval: noop,
|
||||
length:10, // pretend you are an array
|
||||
addEventListener: function(type, fn){
|
||||
expect(type).toEqual('hashchange');
|
||||
eventFn = fn;
|
||||
},
|
||||
removeEventListener: noop,
|
||||
attachEvent: function(type, fn){
|
||||
expect(type).toEqual('onhashchange');
|
||||
eventFn = fn;
|
||||
},
|
||||
detachEvent: noop
|
||||
document: {},
|
||||
location: {},
|
||||
alert: noop,
|
||||
setInterval: noop,
|
||||
length:10, // pretend you are an array
|
||||
addEventListener: function(type, fn){
|
||||
expect(type).toEqual('hashchange');
|
||||
eventFn = fn;
|
||||
},
|
||||
removeEventListener: noop,
|
||||
attachEvent: function(type, fn){
|
||||
expect(type).toEqual('onhashchange');
|
||||
eventFn = fn;
|
||||
},
|
||||
detachEvent: noop
|
||||
};
|
||||
var log;
|
||||
var jWindow = jqLite(window).on('hashchange', function() {
|
||||
@@ -1046,16 +1048,17 @@ describe('jqLite', function() {
|
||||
if (window.jQuery) return;
|
||||
var browserMoveTrigger = function(from, to){
|
||||
var fireEvent = function(type, element, relatedTarget){
|
||||
var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]);
|
||||
var evnt, msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]);
|
||||
if (msie < 9){
|
||||
var evnt = document.createEventObject();
|
||||
evnt = document.createEventObject();
|
||||
evnt.srcElement = element;
|
||||
evnt.relatedTarget = relatedTarget;
|
||||
element.fireEvent('on' + type, evnt);
|
||||
return;
|
||||
};
|
||||
var evnt = document.createEvent('MouseEvents'),
|
||||
originalPreventDefault = evnt.preventDefault,
|
||||
}
|
||||
evnt = document.createEvent('MouseEvents');
|
||||
|
||||
var originalPreventDefault = evnt.preventDefault,
|
||||
appWindow = window,
|
||||
fakeProcessDefault = true,
|
||||
finalProcessDefault;
|
||||
@@ -1657,25 +1660,25 @@ describe('jqLite', function() {
|
||||
|
||||
describe('camelCase', function() {
|
||||
|
||||
it('should leave non-dashed strings alone', function() {
|
||||
expect(camelCase('foo')).toBe('foo');
|
||||
expect(camelCase('')).toBe('');
|
||||
expect(camelCase('fooBar')).toBe('fooBar');
|
||||
});
|
||||
it('should leave non-dashed strings alone', function() {
|
||||
expect(camelCase('foo')).toBe('foo');
|
||||
expect(camelCase('')).toBe('');
|
||||
expect(camelCase('fooBar')).toBe('fooBar');
|
||||
});
|
||||
|
||||
|
||||
it('should covert dash-separated strings to camelCase', function() {
|
||||
expect(camelCase('foo-bar')).toBe('fooBar');
|
||||
expect(camelCase('foo-bar-baz')).toBe('fooBarBaz');
|
||||
expect(camelCase('foo:bar_baz')).toBe('fooBarBaz');
|
||||
});
|
||||
it('should covert dash-separated strings to camelCase', function() {
|
||||
expect(camelCase('foo-bar')).toBe('fooBar');
|
||||
expect(camelCase('foo-bar-baz')).toBe('fooBarBaz');
|
||||
expect(camelCase('foo:bar_baz')).toBe('fooBarBaz');
|
||||
});
|
||||
|
||||
|
||||
it('should covert browser specific css properties', function() {
|
||||
expect(camelCase('-moz-foo-bar')).toBe('MozFooBar');
|
||||
expect(camelCase('-webkit-foo-bar')).toBe('webkitFooBar');
|
||||
expect(camelCase('-webkit-foo-bar')).toBe('webkitFooBar');
|
||||
});
|
||||
it('should covert browser specific css properties', function() {
|
||||
expect(camelCase('-moz-foo-bar')).toBe('MozFooBar');
|
||||
expect(camelCase('-webkit-foo-bar')).toBe('webkitFooBar');
|
||||
expect(camelCase('-webkit-foo-bar')).toBe('webkitFooBar');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
/* global _jQuery: true, _jqLiteMode: true */
|
||||
'use strict';
|
||||
|
||||
var _jQuery = jQuery,
|
||||
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
/* global _jQuery: true, _jqLiteMode: true */
|
||||
'use strict';
|
||||
|
||||
var _jQuery = jQuery.noConflict(true),
|
||||
|
||||
+1
-1
@@ -81,5 +81,5 @@ describe('module loader', function() {
|
||||
|
||||
it('should expose `$$minErr` on the `angular` object', function() {
|
||||
expect(window.angular.$$minErr).toEqual(jasmine.any(Function));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
describe('$anchorScroll', function() {
|
||||
|
||||
var elmSpy;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
describe("$animate", function() {
|
||||
|
||||
describe("without animation", function() {
|
||||
var element, $rootElement;
|
||||
|
||||
beforeEach(module(function() {
|
||||
return function($compile, _$rootElement_, $rootScope) {
|
||||
element = $compile('<div></div>')($rootScope);
|
||||
|
||||
@@ -49,7 +49,7 @@ function MockWindow() {
|
||||
function MockDocument() {
|
||||
var self = this;
|
||||
|
||||
this[0] = window.document
|
||||
this[0] = window.document;
|
||||
this.basePath = '/';
|
||||
|
||||
this.find = function(name) {
|
||||
@@ -62,15 +62,15 @@ function MockDocument() {
|
||||
throw new Error(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new Error(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
describe('browser', function() {
|
||||
|
||||
/* global Browser: false */
|
||||
var browser, fakeWindow, fakeDocument, logs, scripts, removedScripts, sniffer;
|
||||
|
||||
beforeEach(function() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
describe('$cacheFactory', function() {
|
||||
|
||||
it('should be injected', inject(function($cacheFactory) {
|
||||
@@ -176,7 +178,7 @@ describe('$cacheFactory', function() {
|
||||
describe('LRU cache', function() {
|
||||
|
||||
it('should create cache with defined capacity', inject(function($cacheFactory) {
|
||||
cache = $cacheFactory('cache1', {capacity: 5});
|
||||
var cache = $cacheFactory('cache1', {capacity: 5});
|
||||
expect(cache.info().size).toBe(0);
|
||||
|
||||
for (var i=0; i<5; i++) {
|
||||
@@ -193,6 +195,7 @@ describe('$cacheFactory', function() {
|
||||
|
||||
|
||||
describe('eviction', function() {
|
||||
var cache;
|
||||
|
||||
beforeEach(inject(function($cacheFactory) {
|
||||
cache = $cacheFactory('cache1', {capacity: 2});
|
||||
|
||||
+129
-109
@@ -82,13 +82,13 @@ describe('$compile', function() {
|
||||
element.text('SUCCESS');
|
||||
}
|
||||
};
|
||||
})
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, log) {
|
||||
element = $compile('<div></div>')($rootScope);
|
||||
expect(element.text()).toEqual('SUCCESS');
|
||||
expect(log).toEqual('OK');
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow registration of multiple directives with same name', function() {
|
||||
@@ -282,7 +282,7 @@ describe('$compile', function() {
|
||||
expect(attr).toBe(templateAttr);
|
||||
expect(scope).toEqual($rootScope);
|
||||
element.text('worked');
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -397,7 +397,7 @@ describe('$compile', function() {
|
||||
expect(element.children().length).toBe(1);
|
||||
expect(element.text()).toBe('Hello');
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('compiler control', function() {
|
||||
@@ -436,46 +436,46 @@ describe('$compile', function() {
|
||||
describe('restrict', function() {
|
||||
|
||||
it('should allow restriction of attributes', function() {
|
||||
module(function() {
|
||||
forEach({div:'E', attr:'A', clazz:'C', all:'EAC'}, function(restrict, name) {
|
||||
directive(name, function(log) {
|
||||
return {
|
||||
restrict: restrict,
|
||||
compile: valueFn(function(scope, element, attr) {
|
||||
log(name);
|
||||
})
|
||||
};
|
||||
});
|
||||
module(function() {
|
||||
forEach({div:'E', attr:'A', clazz:'C', all:'EAC'}, function(restrict, name) {
|
||||
directive(name, function(log) {
|
||||
return {
|
||||
restrict: restrict,
|
||||
compile: valueFn(function(scope, element, attr) {
|
||||
log(name);
|
||||
})
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($rootScope, $compile, log) {
|
||||
dealoc($compile('<span div class="div"></span>')($rootScope));
|
||||
expect(log).toEqual('');
|
||||
log.reset();
|
||||
});
|
||||
inject(function($rootScope, $compile, log) {
|
||||
dealoc($compile('<span div class="div"></span>')($rootScope));
|
||||
expect(log).toEqual('');
|
||||
log.reset();
|
||||
|
||||
dealoc($compile('<div></div>')($rootScope));
|
||||
expect(log).toEqual('div');
|
||||
log.reset();
|
||||
dealoc($compile('<div></div>')($rootScope));
|
||||
expect(log).toEqual('div');
|
||||
log.reset();
|
||||
|
||||
dealoc($compile('<attr class=""attr"></attr>')($rootScope));
|
||||
expect(log).toEqual('');
|
||||
log.reset();
|
||||
dealoc($compile('<attr class=""attr"></attr>')($rootScope));
|
||||
expect(log).toEqual('');
|
||||
log.reset();
|
||||
|
||||
dealoc($compile('<span attr></span>')($rootScope));
|
||||
expect(log).toEqual('attr');
|
||||
log.reset();
|
||||
dealoc($compile('<span attr></span>')($rootScope));
|
||||
expect(log).toEqual('attr');
|
||||
log.reset();
|
||||
|
||||
dealoc($compile('<clazz clazz></clazz>')($rootScope));
|
||||
expect(log).toEqual('');
|
||||
log.reset();
|
||||
dealoc($compile('<clazz clazz></clazz>')($rootScope));
|
||||
expect(log).toEqual('');
|
||||
log.reset();
|
||||
|
||||
dealoc($compile('<span class="clazz"></span>')($rootScope));
|
||||
expect(log).toEqual('clazz');
|
||||
log.reset();
|
||||
dealoc($compile('<span class="clazz"></span>')($rootScope));
|
||||
expect(log).toEqual('clazz');
|
||||
log.reset();
|
||||
|
||||
dealoc($compile('<all class="all" all></all>')($rootScope));
|
||||
expect(log).toEqual('all; all; all');
|
||||
});
|
||||
dealoc($compile('<all class="all" all></all>')($rootScope));
|
||||
expect(log).toEqual('all; all; all');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -658,7 +658,8 @@ describe('$compile', function() {
|
||||
element = $compile('<div replace-with-interpolated-style></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.css('width')).toBe('2px');
|
||||
}));
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
it('should merge interpolated css class', inject(function($compile, $rootScope) {
|
||||
@@ -699,19 +700,19 @@ describe('$compile', function() {
|
||||
return {
|
||||
replace: true,
|
||||
template: 'dada'
|
||||
}
|
||||
};
|
||||
});
|
||||
directive('multiRootElem', function() {
|
||||
return {
|
||||
replace: true,
|
||||
template: '<div></div><div></div>'
|
||||
}
|
||||
};
|
||||
});
|
||||
directive('singleRootWithWhiteSpace', function() {
|
||||
return {
|
||||
replace: true,
|
||||
template: ' <div></div> \n'
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -820,32 +821,38 @@ describe('$compile', function() {
|
||||
beforeEach(module(
|
||||
function() {
|
||||
directive('hello', valueFn({
|
||||
restrict: 'CAM', templateUrl: 'hello.html', transclude: true
|
||||
restrict: 'CAM',
|
||||
templateUrl: 'hello.html',
|
||||
transclude: true
|
||||
}));
|
||||
directive('cau', valueFn({
|
||||
restrict: 'CAM', templateUrl: 'cau.html'
|
||||
restrict: 'CAM',
|
||||
templateUrl: 'cau.html'
|
||||
}));
|
||||
directive('crossDomainTemplate', valueFn({
|
||||
restrict: 'CAM', templateUrl: 'http://example.com/should-not-load.html'
|
||||
}));
|
||||
directive('trustedTemplate', function($sce) { return {
|
||||
restrict: 'CAM',
|
||||
templateUrl: function() {
|
||||
return $sce.trustAsResourceUrl('http://example.com/trusted-template.html');
|
||||
}};
|
||||
templateUrl: 'http://example.com/should-not-load.html'
|
||||
}));
|
||||
directive('trustedTemplate', function($sce) {
|
||||
return {
|
||||
restrict: 'CAM',
|
||||
templateUrl: function() {
|
||||
return $sce.trustAsResourceUrl('http://example.com/trusted-template.html');
|
||||
}
|
||||
};
|
||||
});
|
||||
directive('cError', valueFn({
|
||||
restrict: 'CAM',
|
||||
templateUrl:'error.html',
|
||||
compile: function() {
|
||||
throw Error('cError');
|
||||
throw new Error('cError');
|
||||
}
|
||||
}));
|
||||
directive('lError', valueFn({
|
||||
restrict: 'CAM',
|
||||
templateUrl: 'error.html',
|
||||
compile: function() {
|
||||
throw Error('lError');
|
||||
throw new Error('lError');
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -866,7 +873,7 @@ describe('$compile', function() {
|
||||
replace: true,
|
||||
templateUrl:'error.html',
|
||||
compile: function() {
|
||||
throw Error('cError');
|
||||
throw new Error('cError');
|
||||
}
|
||||
}));
|
||||
directive('iLError', valueFn({
|
||||
@@ -874,7 +881,7 @@ describe('$compile', function() {
|
||||
replace: true,
|
||||
templateUrl: 'error.html',
|
||||
compile: function() {
|
||||
throw Error('lError');
|
||||
throw new Error('lError');
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -919,23 +926,25 @@ describe('$compile', function() {
|
||||
));
|
||||
|
||||
it('should not load cross domain templates by default', inject(
|
||||
function($compile, $rootScope, $templateCache, $sce) {
|
||||
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');
|
||||
}));
|
||||
function($compile, $rootScope, $templateCache, $sce) {
|
||||
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 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>');
|
||||
element = $compile('<div class="trustedTemplate"></div>')($rootScope);
|
||||
expect(sortedHtml(element)).
|
||||
toEqual('<div class="trustedTemplate"></div>');
|
||||
$httpBackend.flush();
|
||||
expect(sortedHtml(element)).
|
||||
toEqual('<div class="trustedTemplate"><span>example.com/trusted_template_contents</span></div>');
|
||||
}));
|
||||
function($compile, $httpBackend, $rootScope, $sce) {
|
||||
$httpBackend.expect('GET', 'http://example.com/trusted-template.html').respond('<span>example.com/trusted_template_contents</span>');
|
||||
element = $compile('<div class="trustedTemplate"></div>')($rootScope);
|
||||
expect(sortedHtml(element)).
|
||||
toEqual('<div class="trustedTemplate"></div>');
|
||||
$httpBackend.flush();
|
||||
expect(sortedHtml(element)).
|
||||
toEqual('<div class="trustedTemplate"><span>example.com/trusted_template_contents</span></div>');
|
||||
}
|
||||
));
|
||||
|
||||
it('should append template via $http and cache it in $templateCache', inject(
|
||||
function($compile, $httpBackend, $templateCache, $rootScope, $browser) {
|
||||
@@ -1293,15 +1302,15 @@ describe('$compile', function() {
|
||||
function logDirective (name, priority, options) {
|
||||
directive(name, function(log) {
|
||||
return (extend({
|
||||
priority: priority,
|
||||
compile: function() {
|
||||
log(name + '-C');
|
||||
return {
|
||||
pre: function() { log(name + '-PreL'); },
|
||||
post: function() { log(name + '-PostL'); }
|
||||
}
|
||||
}
|
||||
}, options || {}));
|
||||
priority: priority,
|
||||
compile: function() {
|
||||
log(name + '-C');
|
||||
return {
|
||||
pre: function() { log(name + '-PreL'); },
|
||||
post: function() { log(name + '-PostL'); }
|
||||
};
|
||||
}
|
||||
}, options || {}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1462,7 +1471,7 @@ describe('$compile', function() {
|
||||
return {
|
||||
replace: true,
|
||||
templateUrl: 'template.html'
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2078,9 +2087,9 @@ describe('$compile', function() {
|
||||
post: function($scope, $element, $attrs) {
|
||||
log('postLink=' + $attrs.myName);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
module(function() {
|
||||
@@ -2094,7 +2103,7 @@ describe('$compile', function() {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($rootScope, $compile, log) {
|
||||
@@ -2191,7 +2200,7 @@ describe('$compile', function() {
|
||||
|
||||
|
||||
it('should translate {{}} in terminal nodes', inject(function($rootScope, $compile) {
|
||||
element = $compile('<select ng:model="x"><option value="">Greet {{name}}!</option></select>')($rootScope)
|
||||
element = $compile('<select ng:model="x"><option value="">Greet {{name}}!</option></select>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(sortedHtml(element).replace(' selected="true"', '')).
|
||||
toEqual('<select ng:model="x">' +
|
||||
@@ -2257,7 +2266,7 @@ describe('$compile', function() {
|
||||
log(val);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2270,7 +2279,7 @@ describe('$compile', function() {
|
||||
|
||||
expect(log).toEqual(['carrot']);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2283,7 +2292,7 @@ describe('$compile', function() {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
compile: function() {
|
||||
log('t' + uppercase(name))
|
||||
log('t' + uppercase(name));
|
||||
return {
|
||||
pre: function() {
|
||||
log('pre' + uppercase(name));
|
||||
@@ -2424,7 +2433,7 @@ describe('$compile', function() {
|
||||
template: {element: templateElement, attr:templateAttr},
|
||||
link: {element: element, attr: attr}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}),
|
||||
second: valueFn({
|
||||
@@ -2435,7 +2444,7 @@ describe('$compile', function() {
|
||||
template: {element: templateElement, attr:templateAttr},
|
||||
link: {element: element, attr: attr}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -2590,7 +2599,7 @@ describe('$compile', function() {
|
||||
link: function(scope) {
|
||||
regularScope = scope;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -2602,7 +2611,7 @@ describe('$compile', function() {
|
||||
});
|
||||
expect(element.find('input').val()).toBe('from-parent');
|
||||
expect(componentScope).not.toBe(regularScope);
|
||||
expect(componentScope.$parent).toBe(regularScope)
|
||||
expect(componentScope.$parent).toBe(regularScope);
|
||||
}));
|
||||
|
||||
|
||||
@@ -2637,7 +2646,7 @@ describe('$compile', function() {
|
||||
});
|
||||
|
||||
inject(function($rootScope, $templateCache) {
|
||||
$templateCache.put('other.html', 'value: {{value}}')
|
||||
$templateCache.put('other.html', 'value: {{value}}');
|
||||
compile('<div my-component other-tpl-dir>');
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
@@ -2716,14 +2725,14 @@ describe('$compile', function() {
|
||||
componentScope.ref = 'misko';
|
||||
|
||||
$rootScope.$apply();
|
||||
expect($rootScope.name).toEqual({mark:123})
|
||||
expect($rootScope.name).toEqual({mark:123});
|
||||
expect(componentScope.ref).toBe($rootScope.name);
|
||||
expect(componentScope.refAlias).toBe($rootScope.name);
|
||||
|
||||
$rootScope.name = 'igor';
|
||||
componentScope.ref = {};
|
||||
$rootScope.$apply();
|
||||
expect($rootScope.name).toEqual('igor')
|
||||
expect($rootScope.name).toEqual('igor');
|
||||
expect(componentScope.ref).toBe($rootScope.name);
|
||||
expect(componentScope.refAlias).toBe($rootScope.name);
|
||||
}));
|
||||
@@ -3142,7 +3151,7 @@ describe('$compile', function() {
|
||||
link: function($scope, $element) {
|
||||
log($element.attr('scope-tester') + '=' + ($scope.$root === $scope ? 'non-isolate' : 'isolate'));
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3156,7 +3165,7 @@ describe('$compile', function() {
|
||||
expect(log).toEqual('inside=isolate; ' +
|
||||
'outside replaced=non-isolate; ' + // outside
|
||||
'outside replaced=isolate; ' + // replaced
|
||||
'sibling=non-isolate')
|
||||
'sibling=non-isolate');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3338,7 +3347,7 @@ describe('$compile', function() {
|
||||
controller: asyncCtrlSpy,
|
||||
compile: function() {
|
||||
return function() {
|
||||
}
|
||||
};
|
||||
}
|
||||
}));
|
||||
});
|
||||
@@ -3398,7 +3407,7 @@ describe('$compile', function() {
|
||||
element = $compile('<div parent-directive><div child-directive></div>childContentText;</div>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
expect(log).toEqual('parentController; childController');
|
||||
expect(element.text()).toBe('childTemplateText;childContentText;')
|
||||
expect(element.text()).toBe('childTemplateText;childContentText;');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3502,7 +3511,7 @@ describe('$compile', function() {
|
||||
'</div>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
expect(log).toEqual('parentController; childController; babyController');
|
||||
expect(element.text()).toBe('childContentText;babyTemplateText;')
|
||||
expect(element.text()).toBe('childContentText;babyTemplateText;');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3605,7 +3614,7 @@ describe('$compile', function() {
|
||||
replace: true,
|
||||
scope: true,
|
||||
template: '<ul><li>W:{{$parent.$id}}-{{$id}};</li><li ng-transclude></li></ul>'
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function(log, $rootScope, $compile) {
|
||||
@@ -3637,7 +3646,7 @@ describe('$compile', function() {
|
||||
$httpBackend.
|
||||
expect('GET', 'chapter.html').
|
||||
respond('<div>chapter-<div section>[<div ng-transclude></div>]</div></div>');
|
||||
}
|
||||
};
|
||||
});
|
||||
inject(function(log, $rootScope, $compile, $httpBackend) {
|
||||
element = $compile('<div><div book>paragraph</div></div>')($rootScope);
|
||||
@@ -3755,9 +3764,9 @@ describe('$compile', function() {
|
||||
$compile('<div><div ng-transclude></div></div>')($rootScope);
|
||||
} catch(e) {
|
||||
expect(e.message).toMatch(new RegExp(
|
||||
'^\\\[ngTransclude:orphan\\\] ' +
|
||||
'^\\[ngTransclude:orphan\\] ' +
|
||||
'Illegal use of ngTransclude directive in the template! ' +
|
||||
'No parent directive that requires a transclusion found\. ' +
|
||||
'No parent directive that requires a transclusion found\\. ' +
|
||||
'Element: <div ng-transclude.+'));
|
||||
}
|
||||
});
|
||||
@@ -4257,11 +4266,11 @@ describe('$compile', function() {
|
||||
return function(scope, element, attrs, ctrl) {
|
||||
log('link');
|
||||
var cursor = element;
|
||||
template(scope.$new(), function(clone) {cursor.after(cursor = clone)});
|
||||
ctrl.$transclude(function(clone) {cursor.after(clone)});
|
||||
template(scope.$new(), function(clone) { cursor.after(cursor = clone); });
|
||||
ctrl.$transclude(function(clone) { cursor.after(clone); });
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function(log, $rootScope, $compile) {
|
||||
@@ -4434,7 +4443,7 @@ describe('$compile', function() {
|
||||
});
|
||||
inject(function($compile) {
|
||||
element = $compile('<div transclude></div>')($rootScope);
|
||||
expect(_$transclude).toBeDefined()
|
||||
expect(_$transclude).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4559,7 +4568,8 @@ describe('$compile', function() {
|
||||
expect(log.toArray()).toEqual([
|
||||
"outer:#comment:outer:",
|
||||
"innerAgain:#comment:innerAgain:",
|
||||
"inner:#comment:innerAgain:"]);
|
||||
"inner:#comment:innerAgain:"
|
||||
]);
|
||||
expect(child.length).toBe(1);
|
||||
expect(child.contents().length).toBe(2);
|
||||
expect(lowercase(nodeName_(child.contents().eq(0)))).toBe('#comment');
|
||||
@@ -4644,6 +4654,7 @@ describe('$compile', function() {
|
||||
}));
|
||||
|
||||
it('should not sanitize attributes other than src', inject(function($compile, $rootScope) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<img title="{{testUrl}}"></img>')($rootScope);
|
||||
$rootScope.testUrl = "javascript:doEvilStuff()";
|
||||
$rootScope.$apply();
|
||||
@@ -4688,6 +4699,7 @@ describe('$compile', function() {
|
||||
describe('a[href] sanitization', function() {
|
||||
|
||||
it('should not sanitize href on elements other than anchor', inject(function($compile, $rootScope) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<div href="{{testUrl}}"></div>')($rootScope);
|
||||
$rootScope.testUrl = "javascript:doEvilStuff()";
|
||||
$rootScope.$apply();
|
||||
@@ -4696,6 +4708,7 @@ describe('$compile', function() {
|
||||
}));
|
||||
|
||||
it('should not sanitize attributes other than href', inject(function($compile, $rootScope) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<a title="{{testUrl}}"></a>')($rootScope);
|
||||
$rootScope.testUrl = "javascript:doEvilStuff()";
|
||||
$rootScope.$apply();
|
||||
@@ -4759,6 +4772,7 @@ describe('$compile', function() {
|
||||
}));
|
||||
|
||||
it('should pass through arbitrary values on onXYZ event attributes that contain a hyphen', inject(function($compile, $rootScope) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<button on-click="{{onClickJs}}"></script>')($rootScope);
|
||||
$rootScope.onClickJs = 'javascript:doSomething()';
|
||||
$rootScope.$apply();
|
||||
@@ -4789,22 +4803,24 @@ describe('$compile', function() {
|
||||
it('should clear out src attributes for a different domain', inject(function($compile, $rootScope, $sce) {
|
||||
element = $compile('<iframe src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = "http://a.different.domain.example.com";
|
||||
expect(function() { $rootScope.$apply() }).toThrowMinErr(
|
||||
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
|
||||
"$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " +
|
||||
"loading resource from url not allowed by $sceDelegate policy. URL: " +
|
||||
"http://a.different.domain.example.com");
|
||||
}));
|
||||
|
||||
it('should clear out JS src attributes', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<iframe src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = "javascript:alert(1);";
|
||||
expect(function() { $rootScope.$apply() }).toThrowMinErr(
|
||||
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
|
||||
"$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " +
|
||||
"loading resource from url not allowed by $sceDelegate policy. URL: " +
|
||||
"javascript:alert(1);");
|
||||
}));
|
||||
|
||||
it('should clear out non-resource_url src attributes', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<iframe src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = $sce.trustAsUrl("javascript:doTrustedStuff()");
|
||||
expect($rootScope.$apply).toThrowMinErr(
|
||||
@@ -4813,6 +4829,7 @@ describe('$compile', function() {
|
||||
}));
|
||||
|
||||
it('should pass through $sce.trustAs() values in src attributes', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<iframe src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = $sce.trustAsResourceUrl("javascript:doTrustedStuff()");
|
||||
$rootScope.$apply();
|
||||
@@ -4832,22 +4849,24 @@ describe('$compile', function() {
|
||||
it('should clear out action attribute for a different domain', inject(function($compile, $rootScope, $sce) {
|
||||
element = $compile('<form action="{{testUrl}}"></form>')($rootScope);
|
||||
$rootScope.testUrl = "http://a.different.domain.example.com";
|
||||
expect(function() { $rootScope.$apply() }).toThrowMinErr(
|
||||
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
|
||||
"$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " +
|
||||
"loading resource from url not allowed by $sceDelegate policy. URL: " +
|
||||
"http://a.different.domain.example.com");
|
||||
}));
|
||||
|
||||
it('should clear out JS action attribute', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<form action="{{testUrl}}"></form>')($rootScope);
|
||||
$rootScope.testUrl = "javascript:alert(1);";
|
||||
expect(function() { $rootScope.$apply() }).toThrowMinErr(
|
||||
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
|
||||
"$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " +
|
||||
"loading resource from url not allowed by $sceDelegate policy. URL: " +
|
||||
"javascript:alert(1);");
|
||||
}));
|
||||
|
||||
it('should clear out non-resource_url action attribute', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<form action="{{testUrl}}"></form>')($rootScope);
|
||||
$rootScope.testUrl = $sce.trustAsUrl("javascript:doTrustedStuff()");
|
||||
expect($rootScope.$apply).toThrowMinErr(
|
||||
@@ -4856,6 +4875,7 @@ describe('$compile', function() {
|
||||
}));
|
||||
|
||||
it('should pass through $sce.trustAs() values in action attribute', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<form action="{{testUrl}}"></form>')($rootScope);
|
||||
$rootScope.testUrl = $sce.trustAsResourceUrl("javascript:doTrustedStuff()");
|
||||
$rootScope.$apply();
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('$controller', function() {
|
||||
describe('provider', function() {
|
||||
|
||||
it('should allow registration of controllers', function() {
|
||||
var FooCtrl = function($scope) { $scope.foo = 'bar' },
|
||||
var FooCtrl = function($scope) { $scope.foo = 'bar'; },
|
||||
scope = {},
|
||||
ctrl;
|
||||
|
||||
@@ -29,8 +29,8 @@ describe('$controller', function() {
|
||||
|
||||
|
||||
it('should allow registration of map of controllers', function() {
|
||||
var FooCtrl = function($scope) { $scope.foo = 'foo' },
|
||||
BarCtrl = function($scope) { $scope.bar = 'bar' },
|
||||
var FooCtrl = function($scope) { $scope.foo = 'foo'; },
|
||||
BarCtrl = function($scope) { $scope.bar = 'bar'; },
|
||||
scope = {},
|
||||
ctrl;
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('$controller', function() {
|
||||
|
||||
|
||||
it('should allow registration of controllers annotated with arrays', function() {
|
||||
var FooCtrl = function($scope) { $scope.foo = 'bar' },
|
||||
var FooCtrl = function($scope) { $scope.foo = 'bar'; },
|
||||
scope = {},
|
||||
ctrl;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('boolean attr directives', function() {
|
||||
|
||||
it('should properly evaluate 0 as false', inject(function($rootScope, $compile) {
|
||||
// jQuery does not treat 0 as false, when setting attr()
|
||||
element = $compile('<button ng-disabled="isDisabled">Button</button>')($rootScope)
|
||||
element = $compile('<button ng-disabled="isDisabled">Button</button>')($rootScope);
|
||||
$rootScope.isDisabled = 0;
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('disabled')).toBeFalsy();
|
||||
@@ -21,7 +21,7 @@ describe('boolean attr directives', function() {
|
||||
|
||||
|
||||
it('should bind disabled', inject(function($rootScope, $compile) {
|
||||
element = $compile('<button ng-disabled="isDisabled">Button</button>')($rootScope)
|
||||
element = $compile('<button ng-disabled="isDisabled">Button</button>')($rootScope);
|
||||
$rootScope.isDisabled = false;
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('disabled')).toBeFalsy();
|
||||
@@ -32,7 +32,7 @@ describe('boolean attr directives', function() {
|
||||
|
||||
|
||||
it('should bind checked', inject(function($rootScope, $compile) {
|
||||
element = $compile('<input type="checkbox" ng-checked="isChecked" />')($rootScope)
|
||||
element = $compile('<input type="checkbox" ng-checked="isChecked" />')($rootScope);
|
||||
$rootScope.isChecked = false;
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('checked')).toBeFalsy();
|
||||
@@ -43,8 +43,8 @@ describe('boolean attr directives', function() {
|
||||
|
||||
|
||||
it('should bind selected', inject(function($rootScope, $compile) {
|
||||
element = $compile('<select><option value=""></option><option ng-selected="isSelected">Greetings!</option></select>')($rootScope)
|
||||
jqLite(document.body).append(element)
|
||||
element = $compile('<select><option value=""></option><option ng-selected="isSelected">Greetings!</option></select>')($rootScope);
|
||||
jqLite(document.body).append(element);
|
||||
$rootScope.isSelected=false;
|
||||
$rootScope.$digest();
|
||||
expect(element.children()[1].selected).toBeFalsy();
|
||||
@@ -55,7 +55,7 @@ describe('boolean attr directives', function() {
|
||||
|
||||
|
||||
it('should bind readonly', inject(function($rootScope, $compile) {
|
||||
element = $compile('<input type="text" ng-readonly="isReadonly" />')($rootScope)
|
||||
element = $compile('<input type="text" ng-readonly="isReadonly" />')($rootScope);
|
||||
$rootScope.isReadonly=false;
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('readOnly')).toBeFalsy();
|
||||
@@ -66,7 +66,7 @@ describe('boolean attr directives', function() {
|
||||
|
||||
|
||||
it('should bind open', inject(function($rootScope, $compile) {
|
||||
element = $compile('<details ng-open="isOpen"></details>')($rootScope)
|
||||
element = $compile('<details ng-open="isOpen"></details>')($rootScope);
|
||||
$rootScope.isOpen=false;
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('open')).toBeFalsy();
|
||||
@@ -78,7 +78,7 @@ describe('boolean attr directives', function() {
|
||||
|
||||
describe('multiple', function() {
|
||||
it('should NOT bind to multiple via ngMultiple', inject(function($rootScope, $compile) {
|
||||
element = $compile('<select ng-multiple="isMultiple"></select>')($rootScope)
|
||||
element = $compile('<select ng-multiple="isMultiple"></select>')($rootScope);
|
||||
$rootScope.isMultiple=false;
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('multiple')).toBeFalsy();
|
||||
@@ -92,7 +92,7 @@ describe('boolean attr directives', function() {
|
||||
if (msie < 9) return; //IE8 doesn't support biding to boolean attributes
|
||||
|
||||
expect(function() {
|
||||
$compile('<select multiple="{{isMultiple}}"></select>')
|
||||
$compile('<select multiple="{{isMultiple}}"></select>');
|
||||
}).toThrowMinErr('$compile', 'selmulti', 'Binding to the \'multiple\' attribute is not supported. ' +
|
||||
'Element: <select multiple="{{isMultiple}}">');
|
||||
|
||||
@@ -225,7 +225,7 @@ describe('ngHref', function() {
|
||||
|
||||
|
||||
it('should interpolate the expression and bind to href', inject(function($compile, $rootScope) {
|
||||
element = $compile('<div ng-href="some/{{id}}"></div>')($rootScope)
|
||||
element = $compile('<div ng-href="some/{{id}}"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('href')).toEqual('some/');
|
||||
|
||||
@@ -247,7 +247,7 @@ describe('ngHref', function() {
|
||||
|
||||
|
||||
it('should bind href even if no interpolation', inject(function($rootScope, $compile) {
|
||||
element = $compile('<a ng-href="http://server"></a>')($rootScope)
|
||||
element = $compile('<a ng-href="http://server"></a>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.attr('href')).toEqual('http://server');
|
||||
}));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* global FormController: false */
|
||||
'use strict';
|
||||
|
||||
describe('form', function() {
|
||||
@@ -148,9 +149,9 @@ describe('form', function() {
|
||||
'<input name="hasOwnProperty" ng-model="some" />'+
|
||||
'<input name="other" ng-model="someOther" />'+
|
||||
'</form>');
|
||||
expect(function() {
|
||||
$compile(doc)(scope);
|
||||
}).toThrowMinErr('ng', 'badname');
|
||||
expect(function() {
|
||||
$compile(doc)(scope);
|
||||
}).toThrowMinErr('ng', 'badname');
|
||||
});
|
||||
|
||||
|
||||
@@ -177,7 +178,7 @@ describe('form', function() {
|
||||
|
||||
scope.submitMe = function() {
|
||||
submitted = true;
|
||||
}
|
||||
};
|
||||
|
||||
if (msie!=8) addEventListenerFn(doc[0], 'submit', assertPreventDefaultListener);
|
||||
|
||||
@@ -218,11 +219,11 @@ describe('form', function() {
|
||||
// $location change) that will cause some directive to destroy the dom (e.g. ngView+$route)
|
||||
doc.empty();
|
||||
destroyed = true;
|
||||
}
|
||||
};
|
||||
|
||||
scope.submitMe = function() {
|
||||
submitted = true;
|
||||
}
|
||||
};
|
||||
|
||||
var assertPreventDefaultListener = function(e) {
|
||||
reloadPrevented = e.defaultPrevented || (e.returnValue === false);
|
||||
@@ -434,7 +435,7 @@ describe('form', function() {
|
||||
expect(parent.$error.myRule).toBe(false);
|
||||
expect(child.$error.myRule).toBe(false);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
describe('validation', function() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
describe('NgModelController', function() {
|
||||
/* global NgModelController: false */
|
||||
var ctrl, scope, ngModelAccessor, element, parentFormCtrl;
|
||||
|
||||
beforeEach(inject(function($rootScope, $controller) {
|
||||
@@ -9,7 +10,7 @@ describe('NgModelController', function() {
|
||||
parentFormCtrl = {
|
||||
$setValidity: jasmine.createSpy('$setValidity'),
|
||||
$setDirty: jasmine.createSpy('$setDirty')
|
||||
}
|
||||
};
|
||||
|
||||
element = jqLite('<form><input></form>');
|
||||
element.data('$formController', parentFormCtrl);
|
||||
@@ -17,7 +18,9 @@ describe('NgModelController', function() {
|
||||
scope = $rootScope;
|
||||
ngModelAccessor = jasmine.createSpy('ngModel accessor');
|
||||
ctrl = $controller(NgModelController, {
|
||||
$scope: scope, $element: element.find('input'), $attrs: attrs
|
||||
$scope: scope,
|
||||
$element: element.find('input'),
|
||||
$attrs: attrs
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -387,24 +390,20 @@ describe('ngModel', function() {
|
||||
it('should keep previously defined watches consistent when changes in validity are made',
|
||||
inject(function($compile, $rootScope) {
|
||||
|
||||
var isFormValid;
|
||||
$rootScope.$watch('myForm.$valid', function(value) { isFormValid = value; });
|
||||
|
||||
var element = $compile('<form name="myForm">' +
|
||||
'<input name="myControl" ng-model="value" required >' +
|
||||
'</form>')($rootScope);
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(isFormValid).toBe(false);
|
||||
expect($rootScope.myForm.$valid).toBe(false);
|
||||
|
||||
$rootScope.value='value';
|
||||
$rootScope.$apply();
|
||||
expect(isFormValid).toBe(true);
|
||||
expect($rootScope.myForm.$valid).toBe(true);
|
||||
|
||||
dealoc(element);
|
||||
}));
|
||||
var isFormValid;
|
||||
$rootScope.$watch('myForm.$valid', function(value) { isFormValid = value; });
|
||||
var element = $compile('<form name="myForm">' +
|
||||
'<input name="myControl" ng-model="value" required >' +
|
||||
'</form>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
expect(isFormValid).toBe(false);
|
||||
expect($rootScope.myForm.$valid).toBe(false);
|
||||
$rootScope.value='value';
|
||||
$rootScope.$apply();
|
||||
expect(isFormValid).toBe(true);
|
||||
expect($rootScope.myForm.$valid).toBe(true);
|
||||
dealoc(element);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
@@ -472,7 +471,7 @@ describe('input', function() {
|
||||
this.message = function() {
|
||||
return "Attribute '" + attributeName + "' expected to be off but was '" + actualValue +
|
||||
"' in: " + angular.mock.dump(this.actual);
|
||||
}
|
||||
};
|
||||
|
||||
return !actualValue || actualValue == 'false';
|
||||
}
|
||||
@@ -495,7 +494,7 @@ describe('input', function() {
|
||||
expect(scope.name).toEqual('adam');
|
||||
});
|
||||
|
||||
if (!(msie < 9)) {
|
||||
if (!msie || msie >= 9) {
|
||||
describe('compositionevents', function() {
|
||||
it('should not update the model between "compositionstart" and "compositionend" on non android', inject(function($sniffer) {
|
||||
$sniffer.android = false;
|
||||
@@ -529,7 +528,7 @@ describe('input', function() {
|
||||
|
||||
it('should update the model on "compositionend"', function() {
|
||||
compileInput('<input type="text" ng-model="name" name="alias" />');
|
||||
if (!(msie < 9)) {
|
||||
if (!msie || msie >= 9) {
|
||||
browserTrigger(inputElm, 'compositionstart');
|
||||
changeInputValueTo('caitp');
|
||||
expect(scope.name).toBeUndefined();
|
||||
@@ -976,7 +975,7 @@ describe('input', function() {
|
||||
});
|
||||
|
||||
expect(inputElm).toBeValid();
|
||||
expect(inputElm.val()).toBe('0')
|
||||
expect(inputElm.val()).toBe('0');
|
||||
expect(scope.form.alias.$error.required).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -1013,12 +1012,16 @@ describe('input', function() {
|
||||
|
||||
|
||||
describe('EMAIL_REGEXP', function() {
|
||||
|
||||
/* global EMAIL_REGEXP: false */
|
||||
it('should validate email', function() {
|
||||
expect(EMAIL_REGEXP.test('a@b.com')).toBe(true);
|
||||
expect(EMAIL_REGEXP.test('a@b.museum')).toBe(true);
|
||||
expect(EMAIL_REGEXP.test('a@B.c')).toBe(true);
|
||||
expect(EMAIL_REGEXP.test('a@.b.c')).toBe(false);
|
||||
expect(EMAIL_REGEXP.test('a@-b.c')).toBe(false);
|
||||
expect(EMAIL_REGEXP.test('a@b-.c')).toBe(false);
|
||||
expect(EMAIL_REGEXP.test('a@3b.c')).toBe(true);
|
||||
expect(EMAIL_REGEXP.test('a@b')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1043,7 +1046,7 @@ describe('input', function() {
|
||||
|
||||
|
||||
describe('URL_REGEXP', function() {
|
||||
|
||||
/* global URL_REGEXP: false */
|
||||
it('should validate url', function() {
|
||||
expect(URL_REGEXP.test('http://server:123/path')).toBe(true);
|
||||
expect(URL_REGEXP.test('a@B.c')).toBe(false);
|
||||
@@ -1558,7 +1561,7 @@ describe('NgModel animations', function() {
|
||||
}
|
||||
}
|
||||
return animations;
|
||||
};
|
||||
}
|
||||
|
||||
function assertValidAnimation(animation, event, className) {
|
||||
expect(animation.event).toBe(event);
|
||||
|
||||
@@ -72,7 +72,8 @@ describe('ngClass', function() {
|
||||
$rootScope.$digest();
|
||||
expect(element.hasClass('A')).toBeFalsy();
|
||||
expect(element.hasClass('B')).toBeTruthy();
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should support adding multiple classes via a space delimited string', inject(function($rootScope, $compile) {
|
||||
@@ -195,16 +196,16 @@ describe('ngClass', function() {
|
||||
|
||||
|
||||
it("should allow ngClassOdd/Even on the same element with overlapping classes", inject(function($rootScope, $compile, $animate) {
|
||||
var className;
|
||||
var className;
|
||||
|
||||
element = $compile('<ul><li ng-repeat="i in [0,1,2]" ng-class-odd="\'same odd\'" ng-class-even="\'same even\'"></li><ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
var e1 = jqLite(element[0].childNodes[1]);
|
||||
var e2 = jqLite(element[0].childNodes[5]);
|
||||
expect(e1.hasClass('same')).toBeTruthy();
|
||||
expect(e1.hasClass('odd')).toBeTruthy();
|
||||
expect(e2.hasClass('same')).toBeTruthy();
|
||||
expect(e2.hasClass('odd')).toBeTruthy();
|
||||
element = $compile('<ul><li ng-repeat="i in [0,1,2]" ng-class-odd="\'same odd\'" ng-class-even="\'same even\'"></li><ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
var e1 = jqLite(element[0].childNodes[1]);
|
||||
var e2 = jqLite(element[0].childNodes[5]);
|
||||
expect(e1.hasClass('same')).toBeTruthy();
|
||||
expect(e1.hasClass('odd')).toBeTruthy();
|
||||
expect(e2.hasClass('same')).toBeTruthy();
|
||||
expect(e2.hasClass('odd')).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should allow ngClass with overlapping classes', inject(function($rootScope, $compile, $animate) {
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('ngController', function() {
|
||||
|
||||
$window.Public = function() {
|
||||
this.mark = 'works';
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
|
||||
@@ -226,8 +226,8 @@ describe('ngIf and transcludes', function() {
|
||||
describe('ngIf animations', function () {
|
||||
var body, element, $rootElement;
|
||||
|
||||
function html(html) {
|
||||
$rootElement.html(html);
|
||||
function html(content) {
|
||||
$rootElement.html(content);
|
||||
element = $rootElement.children().eq(0);
|
||||
return element;
|
||||
}
|
||||
@@ -272,7 +272,8 @@ describe('ngIf animations', function () {
|
||||
expect(item.element.text()).toBe('Hi');
|
||||
|
||||
expect(element.children().length).toBe(1);
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
it('should fire off the leave animation',
|
||||
inject(function ($compile, $rootScope, $animate) {
|
||||
@@ -297,7 +298,8 @@ describe('ngIf animations', function () {
|
||||
expect(item.element.text()).toBe('Hi');
|
||||
|
||||
expect(element.children().length).toBe(0);
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
it('should destroy the previous leave animation if a new one takes place', function() {
|
||||
module(function($provide) {
|
||||
|
||||
@@ -112,7 +112,7 @@ describe('ngInclude', function() {
|
||||
it('should fire $includeContentRequested event on scope after making the xhr call', inject(
|
||||
function ($rootScope, $compile, $httpBackend) {
|
||||
var contentRequestedSpy = jasmine.createSpy('content requested').andCallFake(function (event) {
|
||||
expect(event.targetScope).toBe($rootScope);
|
||||
expect(event.targetScope).toBe($rootScope);
|
||||
});
|
||||
|
||||
$httpBackend.whenGET('url').respond('my partial');
|
||||
@@ -233,7 +233,8 @@ describe('ngInclude', function() {
|
||||
var called = 0;
|
||||
// we want to assert only during first watch
|
||||
$rootScope.$watch(function() {
|
||||
if (!called++) expect(element.text()).toBe('');
|
||||
if (!called) expect(element.text()).toBe('');
|
||||
called++;
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
@@ -249,7 +250,7 @@ describe('ngInclude', function() {
|
||||
$rootScope.templateUrl = 'myUrl1';
|
||||
$rootScope.logger = function(msg) {
|
||||
log[msg] = true;
|
||||
}
|
||||
};
|
||||
$compile(element)($rootScope);
|
||||
expect(log).toEqual({});
|
||||
|
||||
@@ -451,16 +452,17 @@ describe('ngInclude', function() {
|
||||
}));
|
||||
|
||||
it('should only call $anchorScroll after the "enter" animation completes', inject(
|
||||
compileAndLink('<div><ng:include src="tpl" autoscroll></ng:include></div>'),
|
||||
function($rootScope, $animate, $timeout) {
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
compileAndLink('<div><ng:include src="tpl" autoscroll></ng:include></div>'),
|
||||
function($rootScope, $animate, $timeout) {
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
|
||||
$rootScope.$apply("tpl = 'template.html'");
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$rootScope.$apply("tpl = 'template.html'");
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -569,8 +571,8 @@ describe('ngInclude and transcludes', function() {
|
||||
describe('ngInclude animations', function() {
|
||||
var body, element, $rootElement;
|
||||
|
||||
function html(html) {
|
||||
$rootElement.html(html);
|
||||
function html(content) {
|
||||
$rootElement.html(content);
|
||||
element = $rootElement.children().eq(0);
|
||||
return element;
|
||||
}
|
||||
@@ -611,7 +613,8 @@ describe('ngInclude animations', function() {
|
||||
var animation = $animate.queue.pop();
|
||||
expect(animation.event).toBe('enter');
|
||||
expect(animation.element.text()).toBe('data');
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
it('should fire off the leave animation',
|
||||
inject(function($compile, $rootScope, $templateCache, $animate) {
|
||||
@@ -635,7 +638,8 @@ describe('ngInclude animations', function() {
|
||||
animation = $animate.queue.shift();
|
||||
expect(animation.event).toBe('leave');
|
||||
expect(animation.element.text()).toBe('data');
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
it('should animate two separate ngInclude elements',
|
||||
inject(function($compile, $rootScope, $templateCache, $animate) {
|
||||
@@ -661,7 +665,8 @@ describe('ngInclude animations', function() {
|
||||
expect(itemA.attr('ng-include')).toBe('tpl');
|
||||
expect(itemB.attr('ng-include')).toBe('tpl');
|
||||
expect(itemA).not.toEqual(itemB);
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should destroy the previous leave animation if a new one takes place', function() {
|
||||
module(function($provide) {
|
||||
|
||||
@@ -240,6 +240,6 @@ describe('ngPluralize', function() {
|
||||
expect(element.text()).toBe('Igor and 2 other people are viewing.');
|
||||
expect(elementAlt.text()).toBe('Igor and 2 other people are viewing.');
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -79,6 +79,7 @@ describe('ngRepeat', function() {
|
||||
});
|
||||
|
||||
it('should iterate over an array-like class', function() {
|
||||
/* jshint -W009 */
|
||||
function Collection() {}
|
||||
Collection.prototype = new Array();
|
||||
Collection.prototype.length = 0;
|
||||
@@ -395,10 +396,10 @@ describe('ngRepeat', function() {
|
||||
|
||||
|
||||
it("should throw error when left-hand-side of ngRepeat can't be parsed", function() {
|
||||
element = jqLite('<ul><li ng-repeat="i dont parse in foo"></li></ul>');
|
||||
$compile(element)(scope);
|
||||
element = jqLite('<ul><li ng-repeat="i dont parse in foo"></li></ul>');
|
||||
$compile(element)(scope);
|
||||
expect($exceptionHandler.errors.shift()[0].message).
|
||||
toMatch(/^\[ngRepeat:iidexp\] '_item_' in '_item_ in _collection_' should be an identifier or '\(_key_, _value_\)' expression, but got 'i dont parse'\./);
|
||||
toMatch(/^\[ngRepeat:iidexp\] '_item_' in '_item_ in _collection_' should be an identifier or '\(_key_, _value_\)' expression, but got 'i dont parse'\./);
|
||||
});
|
||||
|
||||
|
||||
@@ -818,7 +819,7 @@ describe('ngRepeat', function() {
|
||||
expect(children[1].nextSibling.nodeValue).toBe(' end ngRepeat: val in values ');
|
||||
expect(children[2].nextSibling.nodeType).toBe(8);
|
||||
expect(children[2].nextSibling.nodeValue).toBe(' end ngRepeat: val in values ');
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.values = [1, 2, 3];
|
||||
|
||||
@@ -1045,7 +1046,7 @@ describe('ngRepeat', function() {
|
||||
inject(function($compile, $rootScope) {
|
||||
element = $compile('<div><div ng-repeat="i in [1,2]" elm-trans>{{i}}</div></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.text()).toBe('[[1]][[2]]')
|
||||
expect(element.text()).toBe('[[1]][[2]]');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1143,8 +1144,8 @@ describe('ngRepeat and transcludes', function() {
|
||||
describe('ngRepeat animations', function() {
|
||||
var body, element, $rootElement;
|
||||
|
||||
function html(html) {
|
||||
$rootElement.html(html);
|
||||
function html(content) {
|
||||
$rootElement.html(content);
|
||||
element = $rootElement.children().eq(0);
|
||||
return element;
|
||||
}
|
||||
@@ -1268,6 +1269,7 @@ describe('ngRepeat animations', function() {
|
||||
item = $animate.queue.shift();
|
||||
expect(item.event).toBe('move');
|
||||
expect(item.element.text()).toBe('3');
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
@@ -55,9 +55,9 @@ describe('ngShow / ngHide', function() {
|
||||
describe('ngShow / ngHide animations', function() {
|
||||
var body, element, $rootElement;
|
||||
|
||||
function html(html) {
|
||||
function html(content) {
|
||||
body.append($rootElement);
|
||||
$rootElement.html(html);
|
||||
$rootElement.html(content);
|
||||
element = $rootElement.children().eq(0);
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -26,22 +26,24 @@ describe('ngSrc', function() {
|
||||
it('should error on src attributes for a different domain', inject(function($compile, $rootScope) {
|
||||
element = $compile('<iframe ng-src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = "http://a.different.domain.example.com";
|
||||
expect(function() { $rootScope.$apply() }).toThrowMinErr(
|
||||
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
|
||||
"$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " +
|
||||
"loading resource from url not allowed by $sceDelegate policy. URL: " +
|
||||
"http://a.different.domain.example.com");
|
||||
}));
|
||||
|
||||
it('should error on JS src attributes', inject(function($compile, $rootScope) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<iframe ng-src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = "javascript:alert(1);";
|
||||
expect(function() { $rootScope.$apply() }).toThrowMinErr(
|
||||
expect(function() { $rootScope.$apply(); }).toThrowMinErr(
|
||||
"$interpolate", "interr", "Can't interpolate: {{testUrl}}\nError: [$sce:insecurl] Blocked " +
|
||||
"loading resource from url not allowed by $sceDelegate policy. URL: " +
|
||||
"javascript:alert(1);");
|
||||
}));
|
||||
|
||||
it('should error on non-resource_url src attributes', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<iframe ng-src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = $sce.trustAsUrl("javascript:doTrustedStuff()");
|
||||
expect($rootScope.$apply).toThrowMinErr(
|
||||
@@ -51,6 +53,7 @@ describe('ngSrc', function() {
|
||||
}));
|
||||
|
||||
it('should pass through $sce.trustAs() values in src attributes', inject(function($compile, $rootScope, $sce) {
|
||||
/* jshint scripturl:true */
|
||||
element = $compile('<iframe ng-src="{{testUrl}}"></iframe>')($rootScope);
|
||||
$rootScope.testUrl = $sce.trustAsResourceUrl("javascript:doTrustedStuff()");
|
||||
$rootScope.$apply();
|
||||
|
||||
@@ -240,8 +240,8 @@ describe('ngSwitch', function() {
|
||||
describe('ngSwitch animations', function() {
|
||||
var body, element, $rootElement;
|
||||
|
||||
function html(html) {
|
||||
$rootElement.html(html);
|
||||
function html(content) {
|
||||
$rootElement.html(content);
|
||||
element = $rootElement.children().eq(0);
|
||||
return element;
|
||||
}
|
||||
@@ -281,7 +281,8 @@ describe('ngSwitch animations', function() {
|
||||
item = $animate.queue.shift();
|
||||
expect(item.event).toBe('enter');
|
||||
expect(item.element.text()).toBe('one');
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should fire off the leave animation',
|
||||
@@ -314,7 +315,8 @@ describe('ngSwitch animations', function() {
|
||||
item = $animate.queue.shift();
|
||||
expect(item.event).toBe('enter');
|
||||
expect(item.element.text()).toBe('three');
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
it('should destroy the previous leave animation if a new one takes place', function() {
|
||||
module(function($provide) {
|
||||
|
||||
@@ -218,7 +218,7 @@ describe('select', function() {
|
||||
|
||||
it('should not break if both the select and repeater models change at once', function() {
|
||||
scope.robots = ['c3p0', 'r2d2'];
|
||||
scope.robot = 'c3p0'
|
||||
scope.robot = 'c3p0';
|
||||
compile('<select ng-model="robot">' +
|
||||
'<option value="">--select--</option>' +
|
||||
'<option ng-repeat="r in robots">{{r}}</option>' +
|
||||
@@ -1206,7 +1206,7 @@ describe('select', function() {
|
||||
|
||||
it('should deselect all options when model is emptied', function() {
|
||||
createMultiSelect();
|
||||
scope.$apply(function() {
|
||||
scope.$apply(function() {
|
||||
scope.values = [{name: 'A'}, {name: 'B'}];
|
||||
scope.selected = [scope.values[0]];
|
||||
});
|
||||
@@ -1217,7 +1217,7 @@ describe('select', function() {
|
||||
});
|
||||
|
||||
expect(element.find('option')[0].selected).toEqual(false);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1325,7 +1325,7 @@ describe('select', function() {
|
||||
});
|
||||
|
||||
it('should set value even if self closing HTML', function() {
|
||||
scope.x = 'hello'
|
||||
scope.x = 'hello';
|
||||
compile('<select ng-model="x"><option>hello</select>');
|
||||
expect(element).toEqualSelect(['hello']);
|
||||
});
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
describe('$exceptionHandler', function() {
|
||||
it('should log errors with single argument', function() {
|
||||
module(function($provide){
|
||||
$provide.provider('$exceptionHandler', $ExceptionHandlerProvider);
|
||||
});
|
||||
inject(function($log, $exceptionHandler) {
|
||||
$exceptionHandler('myError');
|
||||
expect($log.error.logs.shift()).toEqual(['myError']);
|
||||
});
|
||||
/* global $ExceptionHandlerProvider:false */
|
||||
it('should log errors with single argument', function() {
|
||||
module(function($provide){
|
||||
$provide.provider('$exceptionHandler', $ExceptionHandlerProvider);
|
||||
});
|
||||
inject(function($log, $exceptionHandler) {
|
||||
$exceptionHandler('myError');
|
||||
expect($log.error.logs.shift()).toEqual(['myError']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should log errors with multiple arguments', function() {
|
||||
module(function($provide){
|
||||
$provide.provider('$exceptionHandler', $ExceptionHandlerProvider);
|
||||
});
|
||||
inject(function($log, $exceptionHandler) {
|
||||
$exceptionHandler('myError', 'comment');
|
||||
expect($log.error.logs.shift()).toEqual(['myError', 'comment']);
|
||||
});
|
||||
it('should log errors with multiple arguments', function() {
|
||||
module(function($provide){
|
||||
$provide.provider('$exceptionHandler', $ExceptionHandlerProvider);
|
||||
});
|
||||
inject(function($log, $exceptionHandler) {
|
||||
$exceptionHandler('myError', 'comment');
|
||||
expect($log.error.logs.shift()).toEqual(['myError', 'comment']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -77,7 +77,8 @@ describe('Filter: filter', function() {
|
||||
{person: {name: 'Joan'}}];
|
||||
expect(filter(items, {person: {name: 'Jo'}}).length).toBe(2);
|
||||
expect(filter(items, {person: {name: 'Jo'}})).toEqual([
|
||||
{person: {name: 'John'}}, {person: {name: 'Joan'}}]);
|
||||
{person: {name: 'John'}}, {person: {name: 'Joan'}}
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -94,8 +95,8 @@ describe('Filter: filter', function() {
|
||||
|
||||
it('should support boolean properties', function() {
|
||||
var items = [{name: 'tom', current: true},
|
||||
{name: 'demi', current: false},
|
||||
{name: 'sofia'}];
|
||||
{name: 'demi', current: false},
|
||||
{name: 'sofia'}];
|
||||
|
||||
expect(filter(items, {current:true}).length).toBe(1);
|
||||
expect(filter(items, {current:true})[0].name).toBe('tom');
|
||||
@@ -118,26 +119,26 @@ describe('Filter: filter', function() {
|
||||
expect(filter(items, expr, true)).toEqual([items[1]]);
|
||||
expect(filter(items, expr, false)).toEqual([items[1], items[2]]);
|
||||
|
||||
var items = [
|
||||
items = [
|
||||
{key: 'value1', nonkey: 1},
|
||||
{key: 'value2', nonkey: 2},
|
||||
{key: 'value12', nonkey: 3},
|
||||
{key: 'value1', nonkey:4},
|
||||
{key: 'Value1', nonkey:5}
|
||||
];
|
||||
var expr = {key: 'value1'};
|
||||
expr = {key: 'value1'};
|
||||
expect(filter(items, expr, true)).toEqual([items[0], items[3]]);
|
||||
|
||||
var items = [
|
||||
items = [
|
||||
{key: 1, nonkey: 1},
|
||||
{key: 2, nonkey: 2},
|
||||
{key: 12, nonkey: 3},
|
||||
{key: 1, nonkey:4}
|
||||
];
|
||||
var expr = { key: 1 };
|
||||
expr = { key: 1 };
|
||||
expect(filter(items, expr, true)).toEqual([items[0], items[3]]);
|
||||
|
||||
var expr = 12;
|
||||
expr = 12;
|
||||
expect(filter(items, expr, true)).toEqual([items[2]]);
|
||||
});
|
||||
|
||||
@@ -151,7 +152,7 @@ describe('Filter: filter', function() {
|
||||
var expr = {key: 10};
|
||||
var comparator = function (obj,value) {
|
||||
return obj > value;
|
||||
}
|
||||
};
|
||||
expect(filter(items, expr, comparator)).toEqual([items[2]]);
|
||||
|
||||
expr = 10;
|
||||
|
||||
@@ -19,6 +19,7 @@ describe('filters', function() {
|
||||
});
|
||||
|
||||
describe('formatNumber', function() {
|
||||
/* global formatNumber: false */
|
||||
var pattern;
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -68,18 +69,18 @@ describe('filters', function() {
|
||||
expect(num).toBe('123.100');
|
||||
num = formatNumber(123.12, pattern, ',', '.');
|
||||
expect(num).toBe('123.12');
|
||||
var num = formatNumber(123.1116, pattern, ',', '.');
|
||||
num = formatNumber(123.1116, pattern, ',', '.');
|
||||
expect(num).toBe('123.112');
|
||||
});
|
||||
|
||||
it('should format the same with string as well as numeric fractionSize', function(){
|
||||
var num = formatNumber(123.1, pattern, ',', '.', "0");
|
||||
expect(num).toBe('123');
|
||||
var num = formatNumber(123.1, pattern, ',', '.', 0);
|
||||
num = formatNumber(123.1, pattern, ',', '.', 0);
|
||||
expect(num).toBe('123');
|
||||
var num = formatNumber(123.1, pattern, ',', '.', "3");
|
||||
num = formatNumber(123.1, pattern, ',', '.', "3");
|
||||
expect(num).toBe('123.100');
|
||||
var num = formatNumber(123.1, pattern, ',', '.', 3);
|
||||
num = formatNumber(123.1, pattern, ',', '.', 3);
|
||||
expect(num).toBe('123.100');
|
||||
});
|
||||
});
|
||||
@@ -121,6 +122,7 @@ describe('filters', function() {
|
||||
|
||||
|
||||
it('should do basic filter', function() {
|
||||
/* jshint -W008 */
|
||||
expect(number(0, 0)).toEqual('0');
|
||||
expect(number(-999)).toEqual('-999');
|
||||
expect(number(123)).toEqual('123');
|
||||
@@ -276,19 +278,19 @@ describe('filters', function() {
|
||||
var westOfUTCPartial = new angular.mock.TzDate(+5.5, '2010-09-03T12:05:08.000Z');
|
||||
|
||||
expect(date(utc, "yyyy-MM-ddTHH:mm:ssZ")).
|
||||
toEqual('2010-09-03T12:05:08+0000')
|
||||
toEqual('2010-09-03T12:05:08+0000');
|
||||
|
||||
expect(date(eastOfUTC, "yyyy-MM-ddTHH:mm:ssZ")).
|
||||
toEqual('2010-09-03T17:05:08+0500')
|
||||
toEqual('2010-09-03T17:05:08+0500');
|
||||
|
||||
expect(date(westOfUTC, "yyyy-MM-ddTHH:mm:ssZ")).
|
||||
toEqual('2010-09-03T07:05:08-0500')
|
||||
toEqual('2010-09-03T07:05:08-0500');
|
||||
|
||||
expect(date(eastOfUTCPartial, "yyyy-MM-ddTHH:mm:ssZ")).
|
||||
toEqual('2010-09-03T17:35:08+0530')
|
||||
toEqual('2010-09-03T17:35:08+0530');
|
||||
|
||||
expect(date(westOfUTCPartial, "yyyy-MM-ddTHH:mm:ssZ")).
|
||||
toEqual('2010-09-03T06:35:08-0530')
|
||||
toEqual('2010-09-03T06:35:08-0530');
|
||||
});
|
||||
|
||||
it('should treat single quoted strings as string literals', function() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
describe('Filter: limitTo', function() {
|
||||
var items;
|
||||
var str
|
||||
var str;
|
||||
var limitTo;
|
||||
|
||||
beforeEach(inject(function($filter) {
|
||||
@@ -67,7 +67,7 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(str, '9')).toEqual(str);
|
||||
expect(limitTo(str, -9)).toEqual(str);
|
||||
expect(limitTo(str, '-9')).toEqual(str);
|
||||
})
|
||||
});
|
||||
|
||||
it('should return entire input array when limited by Infinity', function() {
|
||||
expect(limitTo(items, Infinity)).toEqual(items);
|
||||
|
||||
@@ -32,13 +32,15 @@ describe('Filter: orderBy', function() {
|
||||
});
|
||||
|
||||
it('should support string predicates with names containing non-identifier characters', function() {
|
||||
/* jshint -W008 */
|
||||
expect(orderBy([{"Tip %": .25}, {"Tip %": .15}, {"Tip %": .40}], '"Tip %"'))
|
||||
.toEqualData([{"Tip %": .15}, {"Tip %": .25}, {"Tip %": .40}]);
|
||||
expect(orderBy([{"원": 76000}, {"원": 31000}, {"원": 156000}], '"원"'))
|
||||
.toEqualData([{"원": 31000}, {"원": 76000}, {"원": 156000}])
|
||||
.toEqualData([{"원": 31000}, {"원": 76000}, {"원": 156000}]);
|
||||
});
|
||||
|
||||
it('should throw if quoted string predicate is quoted incorrectly', function() {
|
||||
/* jshint -W008 */
|
||||
expect(function() {
|
||||
return orderBy([{"Tip %": .15}, {"Tip %": .25}, {"Tip %": .40}], '"Tip %\'');
|
||||
}).toThrow();
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/* global createHttpBackend: false, createMockXhr: false, MockXhr: false */
|
||||
'use strict';
|
||||
|
||||
describe('$httpBackend', function() {
|
||||
|
||||
var $backend, $browser, callbacks,
|
||||
@@ -42,12 +45,14 @@ describe('$httpBackend', function() {
|
||||
// msie8 depends on modifying readyState for testing. This property is readonly,
|
||||
// so it requires a fake object. For other browsers, we do need to make use of
|
||||
// event listener registration/deregistration, so these stubs are needed.
|
||||
if (msie <= 8) return {
|
||||
attachEvent: noop,
|
||||
detachEvent: noop,
|
||||
addEventListener: noop,
|
||||
removeEventListener: noop
|
||||
};
|
||||
if (msie <= 8) {
|
||||
return {
|
||||
attachEvent: noop,
|
||||
detachEvent: noop,
|
||||
addEventListener: noop,
|
||||
removeEventListener: noop
|
||||
};
|
||||
}
|
||||
// Return a proper script element...
|
||||
return document.createElement(arguments[0]);
|
||||
}),
|
||||
@@ -307,7 +312,7 @@ describe('$httpBackend', function() {
|
||||
expect(response).toBe('response');
|
||||
});
|
||||
|
||||
$backend = createHttpBackend($browser, function() { return new SyncXhr() });
|
||||
$backend = createHttpBackend($browser, function() { return new SyncXhr(); });
|
||||
$backend('GET', '/url', null, callback);
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
});
|
||||
@@ -518,6 +523,7 @@ describe('$httpBackend', function() {
|
||||
});
|
||||
|
||||
it('should convert 0 to 404 if no content - relative url', function() {
|
||||
/* global urlParsingNode: true */
|
||||
var originalUrlParsingNode = urlParsingNode;
|
||||
|
||||
//temporarily overriding the DOM element to pretend that the test runs origin with file:// protocol
|
||||
|
||||
+57
-21
@@ -9,12 +9,12 @@ describe('$http', function() {
|
||||
});
|
||||
|
||||
beforeEach(module(function($exceptionHandlerProvider) {
|
||||
$exceptionHandlerProvider.mode('log');
|
||||
$exceptionHandlerProvider.mode('log');
|
||||
}));
|
||||
|
||||
afterEach(inject(function($exceptionHandler, $httpBackend, $rootScope) {
|
||||
forEach($exceptionHandler.errors, function(e) {
|
||||
dump('Unhandled exception: ', e)
|
||||
dump('Unhandled exception: ', e);
|
||||
});
|
||||
|
||||
if ($exceptionHandler.errors.length) {
|
||||
@@ -28,7 +28,7 @@ describe('$http', function() {
|
||||
|
||||
describe('$httpProvider', function() {
|
||||
describe('interceptors', function() {
|
||||
it('should accept injected rejected response interceptor', function() {
|
||||
it('should accept injected rejected response interceptor', function() {
|
||||
var wasCalled = false;
|
||||
module(function($httpProvider, $provide) {
|
||||
$httpProvider.responseInterceptors.push('injectedInterceptor');
|
||||
@@ -83,7 +83,7 @@ describe('$http', function() {
|
||||
return {
|
||||
response: function(response) {
|
||||
response.data += ':1';
|
||||
savedResponse = response
|
||||
savedResponse = response;
|
||||
return $q.reject(':2');
|
||||
}
|
||||
};
|
||||
@@ -194,7 +194,7 @@ describe('$http', function() {
|
||||
response.data += '!';
|
||||
return response;
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// return a new resolved promise representing modified response object
|
||||
@@ -221,7 +221,7 @@ describe('$http', function() {
|
||||
response.data = uppercase(response.data);
|
||||
return response;
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
$httpProvider.responseInterceptors.push('myInterceptor');
|
||||
});
|
||||
@@ -344,7 +344,7 @@ describe('$http', function() {
|
||||
$rootScope.$apply();
|
||||
expect(config.method).toEqual('get');
|
||||
expect(config.url).toEqual('/url');
|
||||
expect(config.headers.foo).toEqual('bar')
|
||||
expect(config.headers.foo).toEqual('bar');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -442,8 +442,8 @@ describe('$http', function() {
|
||||
|
||||
|
||||
it('should expand arrays in params map', inject(function($httpBackend, $http) {
|
||||
$httpBackend.expect('GET', '/url?a=1&a=2&a=3').respond('');
|
||||
$http({url: '/url', params: {a: [1,2,3]}, method: 'GET'});
|
||||
$httpBackend.expect('GET', '/url?a=1&a=2&a=3').respond('');
|
||||
$http({url: '/url', params: {a: [1,2,3]}, method: 'GET'});
|
||||
}));
|
||||
|
||||
|
||||
@@ -460,7 +460,7 @@ describe('$http', function() {
|
||||
it('should not add question mark when params is empty', function() {
|
||||
$httpBackend.expect('GET', '/url').respond('');
|
||||
$http({url: '/url', params: {}, method: 'GET'});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -591,7 +591,7 @@ describe('$http', function() {
|
||||
expect(r.headers('nothing')).toBe(null);
|
||||
});
|
||||
|
||||
$http({url: '/url', method: 'GET'}).then(callback)
|
||||
$http({url: '/url', method: 'GET'}).then(callback);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
@@ -629,6 +629,7 @@ describe('$http', function() {
|
||||
|
||||
|
||||
describe('response headers parser', function() {
|
||||
/* global parseHeaders: false */
|
||||
|
||||
it('should parse basic', function() {
|
||||
var parsed = parseHeaders(
|
||||
@@ -771,6 +772,18 @@ describe('$http', function() {
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should delete default headers if custom header function returns null', function () {
|
||||
|
||||
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
|
||||
return !('Accept' in headers);
|
||||
}).respond('');
|
||||
|
||||
$http({url: '/url', method: 'POST', data: 'messageBody', headers: {
|
||||
'Accept': function() { return null; }
|
||||
}});
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should override default headers with custom in a case insensitive manner', function() {
|
||||
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
|
||||
return headers['accept'] == 'Rewritten' &&
|
||||
@@ -812,6 +825,22 @@ describe('$http', function() {
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should NOT delete Content-Type header if request data/body is set by request transform', function() {
|
||||
$httpBackend.expect('POST', '/url', {'one' : 'two'}, function(headers) {
|
||||
return headers['Content-Type'] == 'application/json;charset=utf-8';
|
||||
}).respond('');
|
||||
|
||||
$http({
|
||||
url: '/url',
|
||||
method: 'POST',
|
||||
transformRequest : function(data) {
|
||||
data = {'one' : 'two'};
|
||||
return data;
|
||||
}
|
||||
});
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('should set the XSRF cookie into a XSRF header', inject(function($browser) {
|
||||
function checkXSRF(secret, header) {
|
||||
@@ -833,8 +862,8 @@ describe('$http', function() {
|
||||
$http({url: '/url', method: 'POST', headers: {'S-ome': 'Header'}});
|
||||
$http({url: '/url', method: 'PUT', headers: {'Another': 'Header'}});
|
||||
$http({url: '/url', method: 'DELETE', headers: {}});
|
||||
$http({url: '/url', method: 'GET', xsrfHeaderName: 'aHeader'})
|
||||
$http({url: '/url', method: 'GET', xsrfCookieName: 'aCookie'})
|
||||
$http({url: '/url', method: 'GET', xsrfHeaderName: 'aHeader'});
|
||||
$http({url: '/url', method: 'GET', xsrfCookieName: 'aCookie'});
|
||||
|
||||
$httpBackend.flush();
|
||||
}));
|
||||
@@ -1057,8 +1086,8 @@ describe('$http', function() {
|
||||
|
||||
|
||||
it('should pipeline more functions', function() {
|
||||
function first(d, h) {return d + '-first' + ':' + h('h1')}
|
||||
function second(d) {return uppercase(d)}
|
||||
function first(d, h) {return d + '-first' + ':' + h('h1');}
|
||||
function second(d) {return uppercase(d);}
|
||||
|
||||
$httpBackend.expect('POST', '/url', 'REQ-FIRST:V1').respond(200);
|
||||
$http.post('/url', 'req', {
|
||||
@@ -1142,8 +1171,8 @@ describe('$http', function() {
|
||||
|
||||
|
||||
it('should pipeline more functions', function() {
|
||||
function first(d, h) {return d + '-first' + ':' + h('h1')}
|
||||
function second(d) {return uppercase(d)}
|
||||
function first(d, h) {return d + '-first' + ':' + h('h1');}
|
||||
function second(d) {return uppercase(d);}
|
||||
|
||||
$httpBackend.expect('POST', '/url').respond(200, 'resp', {h1: 'v1'});
|
||||
$http.post('/url', '', {transformResponse: [first, second]}).success(callback);
|
||||
@@ -1352,7 +1381,7 @@ describe('$http', function() {
|
||||
describe('$http.defaults.cache', function () {
|
||||
|
||||
it('should be undefined by default', function() {
|
||||
expect($http.defaults.cache).toBeUndefined()
|
||||
expect($http.defaults.cache).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should cache requests when no cache given in request config', function() {
|
||||
@@ -1530,7 +1559,7 @@ describe('$http', function() {
|
||||
expect($http.defaults.headers.post).not.toBe($http.defaults.headers.put);
|
||||
expect($http.defaults.headers.post).not.toBe($http.defaults.headers.patch);
|
||||
expect($http.defaults.headers.put).not.toBe($http.defaults.headers.patch);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1550,7 +1579,11 @@ describe('$http', function() {
|
||||
|
||||
inject(function($http, $rootScope) {
|
||||
$http({
|
||||
method: 'GET', url: 'some.html', timeout: 12345, withCredentials: true, responseType: 'json'
|
||||
method: 'GET',
|
||||
url: 'some.html',
|
||||
timeout: 12345,
|
||||
withCredentials: true,
|
||||
responseType: 'json'
|
||||
});
|
||||
$rootScope.$digest();
|
||||
expect($httpBackend).toHaveBeenCalledOnce();
|
||||
@@ -1574,7 +1607,10 @@ describe('$http', function() {
|
||||
inject(function($http, $rootScope) {
|
||||
$http.defaults.withCredentials = true;
|
||||
$http({
|
||||
method: 'GET', url: 'some.html', timeout: 12345, responseType: 'json'
|
||||
method: 'GET',
|
||||
url: 'some.html',
|
||||
timeout: 12345,
|
||||
responseType: 'json'
|
||||
});
|
||||
$rootScope.$digest();
|
||||
expect($httpBackend).toHaveBeenCalledOnce();
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('$interpolate', function() {
|
||||
|
||||
|
||||
it('should ignore undefined return value', inject(function($interpolate, $rootScope) {
|
||||
$rootScope.foo = function() {return undefined};
|
||||
$rootScope.foo = function() {return undefined;};
|
||||
expect($interpolate("Hello {{'World' + foo()}}")($rootScope)).toEqual('Hello World');
|
||||
}));
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('$interpolate', function() {
|
||||
describe('interpolating in a trusted context', function() {
|
||||
var sce;
|
||||
beforeEach(function() {
|
||||
function log() {};
|
||||
function log() {}
|
||||
var fakeLog = {log: log, warn: log, info: log, error: log};
|
||||
module(function($provide, $sceProvider) {
|
||||
$provide.value('$log', fakeLog);
|
||||
@@ -106,8 +106,8 @@ describe('$interpolate', function() {
|
||||
var foo = sce.trustAsCss("foo");
|
||||
var bar = sce.trustAsCss("bar");
|
||||
expect(function() {
|
||||
return $interpolate('{{foo}}{{bar}}', true, sce.CSS)(
|
||||
{foo: foo, bar: bar}); }).toThrowMinErr(
|
||||
return $interpolate('{{foo}}{{bar}}', true, sce.CSS)({foo: foo, bar: bar});
|
||||
}).toThrowMinErr(
|
||||
"$interpolate", "noconcat", "Error while interpolating: {{foo}}{{bar}}\n" +
|
||||
"Strict Contextual Escaping disallows interpolations that concatenate multiple " +
|
||||
"expressions when a trusted value is required. See " +
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
describe('$interval', function() {
|
||||
|
||||
/* global $IntervalProvider: false */
|
||||
beforeEach(module(function($provide){
|
||||
var repeatFns = [],
|
||||
nextRepeatId = 0,
|
||||
@@ -58,7 +58,7 @@ describe('$interval', function() {
|
||||
|
||||
expect(counter).toBe(0);
|
||||
|
||||
$window.flush(1000)
|
||||
$window.flush(1000);
|
||||
expect(counter).toBe(1);
|
||||
|
||||
$window.flush(1000);
|
||||
@@ -113,7 +113,7 @@ describe('$interval', function() {
|
||||
|
||||
it('should allow you to specify a number of iterations', inject(function($interval, $window) {
|
||||
var counter = 0;
|
||||
$interval(function() {counter++}, 1000, 2);
|
||||
$interval(function() {counter++;}, 1000, 2);
|
||||
|
||||
$window.flush(1000);
|
||||
expect(counter).toBe(1);
|
||||
@@ -157,7 +157,8 @@ describe('$interval', function() {
|
||||
$window.flush(1000);
|
||||
|
||||
expect(log).toEqual([
|
||||
'tick', 'promise update: 0', 'tick', 'promise update: 1', 'promise success: 2']);
|
||||
'tick', 'promise update: 0', 'tick', 'promise update: 1', 'promise success: 2'
|
||||
]);
|
||||
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
describe('$locale', function() {
|
||||
|
||||
/* global $LocaleProvider: false */
|
||||
var $locale = new $LocaleProvider().$get();
|
||||
|
||||
it('should have locale id set to en-us', function() {
|
||||
|
||||
+32
-20
@@ -1,6 +1,6 @@
|
||||
/* global LocationHashbangUrl: false, LocationHtml5Url: false */
|
||||
'use strict';
|
||||
|
||||
|
||||
describe('$location', function() {
|
||||
var url;
|
||||
|
||||
@@ -14,6 +14,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
describe('File Protocol', function () {
|
||||
/* global urlParsingNode: true */
|
||||
var urlParsingNodePlaceholder;
|
||||
|
||||
beforeEach(inject(function ($sniffer) {
|
||||
@@ -117,6 +118,15 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
|
||||
it('search() should remove multiple parameters', function() {
|
||||
url.search({one: 1, two: true});
|
||||
expect(url.search()).toEqual({one: 1, two: true});
|
||||
url.search({one: null, two: null});
|
||||
expect(url.search()).toEqual({});
|
||||
expect(url.absUrl()).toBe('http://www.domain.com:9877/path/b#hash');
|
||||
});
|
||||
|
||||
|
||||
it('search() should handle multiple value', function() {
|
||||
url.search('a&b');
|
||||
expect(url.search()).toEqual({a: true, b: true});
|
||||
@@ -221,7 +231,7 @@ describe('$location', function() {
|
||||
|
||||
it('should set path to forward-slash when empty', function() {
|
||||
url = new LocationHtml5Url('http://server/');
|
||||
url.$$parse('http://server/')
|
||||
url.$$parse('http://server/');
|
||||
expect(url.path()).toBe('/');
|
||||
expect(url.absUrl()).toBe('http://server/');
|
||||
});
|
||||
@@ -437,28 +447,28 @@ describe('$location', function() {
|
||||
|
||||
it('should return decoded characters for search specified with setter', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/')
|
||||
locationUrl.$$parse('http://host.com/');
|
||||
locationUrl.search('q', '1/2 3');
|
||||
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
||||
});
|
||||
|
||||
it('should return an array for duplicate params', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com');
|
||||
locationUrl.$$parse('http://host.com')
|
||||
locationUrl.$$parse('http://host.com');
|
||||
locationUrl.search('q', ['1/2 3','4/5 6']);
|
||||
expect(locationUrl.search()).toEqual({'q': ['1/2 3','4/5 6']});
|
||||
});
|
||||
|
||||
it('should encode an array correctly from search and add to url', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com');
|
||||
locationUrl.$$parse('http://host.com')
|
||||
locationUrl.$$parse('http://host.com');
|
||||
locationUrl.search({'q': ['1/2 3','4/5 6']});
|
||||
expect(locationUrl.absUrl()).toEqual('http://host.com?q=1%2F2%203&q=4%2F5%206');
|
||||
});
|
||||
|
||||
it('should rewrite params when specifing a single param in search', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com');
|
||||
locationUrl.$$parse('http://host.com')
|
||||
locationUrl.$$parse('http://host.com');
|
||||
locationUrl.search({'q': '1/2 3'});
|
||||
expect(locationUrl.absUrl()).toEqual('http://host.com?q=1%2F2%203');
|
||||
locationUrl.search({'q': '4/5 6'});
|
||||
@@ -747,7 +757,7 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
describe('PATH_MATCH', function() {
|
||||
|
||||
/* global PATH_MATCH: false */
|
||||
it('should parse just path', function() {
|
||||
var match = PATH_MATCH.exec('/path');
|
||||
expect(match[1]).toBe('/path');
|
||||
@@ -1120,7 +1130,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
// don't run next tests on IE<9, as browserTrigger does not simulate pressed keys
|
||||
if (!(msie < 9)) {
|
||||
if (!msie || msie >= 9) {
|
||||
|
||||
it('should not rewrite when clicked with ctrl pressed', function() {
|
||||
configureService('/a?b=c', true, true);
|
||||
@@ -1154,10 +1164,10 @@ describe('$location', function() {
|
||||
module(function() {
|
||||
return function($browser) {
|
||||
window.location.hash = 'someHash';
|
||||
base = window.location.href
|
||||
base = window.location.href;
|
||||
$browser.url(base);
|
||||
base = base.split('#')[0];
|
||||
}
|
||||
};
|
||||
});
|
||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
||||
// we need to do this otherwise we can't simulate events
|
||||
@@ -1189,7 +1199,7 @@ describe('$location', function() {
|
||||
$browser.url(base = window.location.href);
|
||||
base = base.split('#')[0];
|
||||
$locationProvider.hashPrefix('!');
|
||||
}
|
||||
};
|
||||
});
|
||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
||||
// we need to do this otherwise we can't simulate events
|
||||
@@ -1222,7 +1232,7 @@ describe('$location', function() {
|
||||
});
|
||||
return function($browser) {
|
||||
$browser.url(base = 'http://server/');
|
||||
}
|
||||
};
|
||||
});
|
||||
inject(function($location) {
|
||||
// make IE happy
|
||||
@@ -1252,7 +1262,7 @@ describe('$location', function() {
|
||||
});
|
||||
return function($browser) {
|
||||
$browser.url(base = 'http://server/');
|
||||
}
|
||||
};
|
||||
});
|
||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
||||
// make IE happy
|
||||
@@ -1293,7 +1303,7 @@ describe('$location', function() {
|
||||
$browser.url(base = window.location.href);
|
||||
base = base.split('#')[0];
|
||||
$locationProvider.hashPrefix('!');
|
||||
}
|
||||
};
|
||||
});
|
||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
||||
// we need to do this otherwise we can't simulate events
|
||||
@@ -1348,7 +1358,7 @@ describe('$location', function() {
|
||||
event.preventDefault();
|
||||
});
|
||||
$rootScope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl) {
|
||||
throw Error('location should have been canceled');
|
||||
throw new Error('location should have been canceled');
|
||||
});
|
||||
|
||||
expect($location.url()).toEqual('');
|
||||
@@ -1398,7 +1408,7 @@ describe('$location', function() {
|
||||
$rootElement.html('<a href="http://server/#/somePath">link</a>');
|
||||
$compile($rootElement)($rootScope);
|
||||
jqLite(document.body).append($rootElement);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
inject(function($location, $rootScope, $browser, $rootElement) {
|
||||
@@ -1431,7 +1441,7 @@ describe('$location', function() {
|
||||
$rootElement.html('<a href="http://server/somePath">link</a>');
|
||||
$compile($rootElement)($rootScope);
|
||||
jqLite(document.body).append($rootElement);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
inject(function($location, $rootScope, $browser, $rootElement) {
|
||||
@@ -1507,6 +1517,7 @@ describe('$location', function() {
|
||||
var location;
|
||||
|
||||
it('should rewrite URL', function() {
|
||||
/* jshint scripturl: true */
|
||||
location = new LocationHashbangUrl('http://server/pre/', '#');
|
||||
|
||||
expect(location.$$rewrite('http://other')).toEqual(undefined);
|
||||
@@ -1518,7 +1529,7 @@ describe('$location', function() {
|
||||
it("should not set hash if one was not originally specified", function() {
|
||||
location = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
|
||||
location.$$parse('http://server/pre/index.html')
|
||||
location.$$parse('http://server/pre/index.html');
|
||||
expect(location.url()).toBe('');
|
||||
expect(location.absUrl()).toBe('http://server/pre/index.html');
|
||||
});
|
||||
@@ -1526,7 +1537,7 @@ describe('$location', function() {
|
||||
it("should parse hash if one was specified", function() {
|
||||
location = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
|
||||
location.$$parse('http://server/pre/index.html#/foo/bar')
|
||||
location.$$parse('http://server/pre/index.html#/foo/bar');
|
||||
expect(location.url()).toBe('/foo/bar');
|
||||
expect(location.absUrl()).toBe('http://server/pre/index.html#/foo/bar');
|
||||
});
|
||||
@@ -1535,7 +1546,7 @@ describe('$location', function() {
|
||||
it("should prefix hash url with / if one was originally missing", function() {
|
||||
location = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
|
||||
location.$$parse('http://server/pre/index.html#not-starting-with-slash')
|
||||
location.$$parse('http://server/pre/index.html#not-starting-with-slash');
|
||||
expect(location.url()).toBe('/not-starting-with-slash');
|
||||
expect(location.absUrl()).toBe('http://server/pre/index.html#/not-starting-with-slash');
|
||||
});
|
||||
@@ -1553,6 +1564,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
describe('LocationHashbangInHtml5Url', function() {
|
||||
/* global LocationHashbangInHtml5Url: false */
|
||||
var location, locationIndex;
|
||||
|
||||
beforeEach(function() {
|
||||
|
||||
+18
-17
@@ -1,3 +1,4 @@
|
||||
/* global $LogProvider: false */
|
||||
'use strict';
|
||||
|
||||
function initService(debugEnabled) {
|
||||
@@ -118,24 +119,24 @@ describe('$log', function() {
|
||||
|
||||
describe("$log.debug", function () {
|
||||
|
||||
beforeEach(initService(false));
|
||||
beforeEach(initService(false));
|
||||
|
||||
it("should skip debugging output if disabled", inject(
|
||||
function(){
|
||||
$window.console = {log: log,
|
||||
warn: warn,
|
||||
info: info,
|
||||
error: error,
|
||||
debug: debug};
|
||||
},
|
||||
function($log) {
|
||||
$log.log();
|
||||
$log.warn();
|
||||
$log.info();
|
||||
$log.error();
|
||||
$log.debug();
|
||||
expect(logger).toEqual('log;warn;info;error;');
|
||||
}
|
||||
it("should skip debugging output if disabled", inject(
|
||||
function(){
|
||||
$window.console = {log: log,
|
||||
warn: warn,
|
||||
info: info,
|
||||
error: error,
|
||||
debug: debug};
|
||||
},
|
||||
function($log) {
|
||||
$log.log();
|
||||
$log.warn();
|
||||
$log.info();
|
||||
$log.error();
|
||||
$log.debug();
|
||||
expect(logger).toEqual('log;warn;info;error;');
|
||||
}
|
||||
));
|
||||
|
||||
});
|
||||
|
||||
+11
-6
@@ -3,6 +3,7 @@
|
||||
describe('parser', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
/* global getterFnCache: true, promiseWarningCache: true */
|
||||
// clear caches
|
||||
getterFnCache = {};
|
||||
promiseWarningCache = {};
|
||||
@@ -13,6 +14,7 @@ describe('parser', function() {
|
||||
var lex;
|
||||
|
||||
beforeEach(function () {
|
||||
/* global Lexer: false */
|
||||
lex = function () {
|
||||
var lexer = new Lexer({csp: false, unwrapPromises: false});
|
||||
return lexer.lex.apply(lexer, arguments);
|
||||
@@ -225,6 +227,7 @@ describe('parser', function() {
|
||||
}));
|
||||
|
||||
it('should parse expressions', function() {
|
||||
/*jshint -W006, -W007 */
|
||||
expect(scope.$eval("-1")).toEqual(-1);
|
||||
expect(scope.$eval("1 + 2.5")).toEqual(3.5);
|
||||
expect(scope.$eval("1 + -2.5")).toEqual(-1.5);
|
||||
@@ -235,6 +238,7 @@ describe('parser', function() {
|
||||
});
|
||||
|
||||
it('should parse comparison', function() {
|
||||
/* jshint -W041 */
|
||||
expect(scope.$eval("false")).toBeFalsy();
|
||||
expect(scope.$eval("!true")).toBeFalsy();
|
||||
expect(scope.$eval("1==1")).toBeTruthy();
|
||||
@@ -367,11 +371,11 @@ describe('parser', function() {
|
||||
// Assign to x1 and build path 'x1.x2.x3. ... .x[n]' to access the final value.
|
||||
scope.x1 = obj;
|
||||
var path = 'x1';
|
||||
for (var i = 2; i <= pathLength; i++) {
|
||||
for (i = 2; i <= pathLength; i++) {
|
||||
path += '.x' + i;
|
||||
}
|
||||
expect(scope.$eval(path)).toBe(42);
|
||||
locals['x' + pathLength] = 'not 42'
|
||||
locals['x' + pathLength] = 'not 42';
|
||||
expect(scope.$eval(path, locals)).toBe(42);
|
||||
});
|
||||
});
|
||||
@@ -444,7 +448,7 @@ describe('parser', function() {
|
||||
|
||||
it('should evaluate function call from a return value', function() {
|
||||
scope.val = 33;
|
||||
scope.getter = function() { return function() { return this.val; }};
|
||||
scope.getter = function() { return function() { return this.val; }; };
|
||||
expect(scope.$eval("getter()()")).toBe(33);
|
||||
});
|
||||
|
||||
@@ -580,6 +584,7 @@ describe('parser', function() {
|
||||
});
|
||||
|
||||
it('should evaluate negation', function() {
|
||||
/* jshint -W018 */
|
||||
expect(scope.$eval("!false || true")).toEqual(!false || true);
|
||||
expect(scope.$eval("!11 == 10")).toEqual(!11 == 10);
|
||||
expect(scope.$eval("12/6/2")).toEqual(12/6/2);
|
||||
@@ -709,7 +714,7 @@ describe('parser', function() {
|
||||
'Expression: $eval.call()');
|
||||
|
||||
expect(function() {
|
||||
scope.$eval('fn()')
|
||||
scope.$eval('fn()');
|
||||
}).toThrowMinErr(
|
||||
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
|
||||
'Expression: fn()');
|
||||
@@ -976,9 +981,9 @@ describe('parser', function() {
|
||||
'null,' +
|
||||
'"alert(1)"' +
|
||||
')()' +
|
||||
'')
|
||||
'');
|
||||
}).toThrow();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should call the function from the received instance and not from a new one', function() {
|
||||
|
||||
+31
-29
@@ -72,7 +72,7 @@ describe('q', function() {
|
||||
name = 'success' + (name || '');
|
||||
return function() {
|
||||
return _logInvocation(name, arguments, (returnValDefined ? returnVal : arguments[0]), throwReturnVal);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +88,7 @@ describe('q', function() {
|
||||
name = 'finally' + (name || '');
|
||||
return function() {
|
||||
return _logInvocation(name, arguments, (returnValDefined ? returnVal : arguments[0]), throwReturnVal);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +104,7 @@ describe('q', function() {
|
||||
name = 'progress' + (name || '');
|
||||
return function() {
|
||||
return _logInvocation(name, arguments, (returnValDefined ? returnVal : arguments[0]), throwReturnVal);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +125,7 @@ describe('q', function() {
|
||||
} else {
|
||||
return _logInvocation(name, arguments, returnVal, throwReturnVal);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** helper for synchronous resolution of deferred */
|
||||
@@ -177,13 +177,14 @@ describe('q', function() {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
/* global qFactory: false */
|
||||
q = qFactory(mockNextTick.nextTick, noop),
|
||||
defer = q.defer;
|
||||
deferred = defer()
|
||||
deferred = defer();
|
||||
promise = deferred.promise;
|
||||
log = [];
|
||||
mockNextTick.queue = [];
|
||||
@@ -343,7 +344,7 @@ describe('q', function() {
|
||||
expect(mockNextTick.queue.length).toBe(0);
|
||||
expect(logStr()).toBe('');
|
||||
|
||||
promise.then(success(2), error(2))
|
||||
promise.then(success(2), error(2));
|
||||
expect(logStr()).toBe('');
|
||||
mockNextTick.flush();
|
||||
expect(logStr()).toBe('success2(foo)->foo');
|
||||
@@ -364,7 +365,7 @@ describe('q', function() {
|
||||
expect(mockNextTick.queue.length).toBe(0);
|
||||
expect(logStr()).toBe('');
|
||||
|
||||
promise.then(success(2), error(2))
|
||||
promise.then(success(2), error(2));
|
||||
expect(logStr()).toBe('');
|
||||
mockNextTick.flush();
|
||||
expect(logStr()).toBe('error2(foo)->reject(foo)');
|
||||
@@ -442,7 +443,7 @@ describe('q', function() {
|
||||
log = [];
|
||||
deferred.reject('bar');
|
||||
deferred.resolve('baz');
|
||||
deferred.notify('qux')
|
||||
deferred.notify('qux');
|
||||
expect(mockNextTick.queue.length).toBe(0);
|
||||
expect(logStr()).toBe('');
|
||||
|
||||
@@ -769,7 +770,7 @@ describe('q', function() {
|
||||
|
||||
it('should not take an argument',
|
||||
function() {
|
||||
promise['finally'](fin(1))
|
||||
promise['finally'](fin(1));
|
||||
syncResolve(deferred, 'foo');
|
||||
expect(logStr()).toBe('finally1()');
|
||||
});
|
||||
@@ -778,7 +779,7 @@ describe('q', function() {
|
||||
|
||||
it('should call the callback',
|
||||
function() {
|
||||
promise.then(success(1))['finally'](fin(1))
|
||||
promise.then(success(1))['finally'](fin(1));
|
||||
syncResolve(deferred, 'foo');
|
||||
expect(logStr()).toBe('success1(foo)->foo; finally1()');
|
||||
});
|
||||
@@ -800,7 +801,7 @@ describe('q', function() {
|
||||
then(success('BB', 'bb'), error('BB'));
|
||||
promise.then(success('C', 'c'), error('C'))['finally'](fin('CC', 'IGNORED'))
|
||||
.then(success('CCC', 'cc'), error('CCC'))
|
||||
.then(success('CCCC', 'ccc'), error('CCCC'))
|
||||
.then(success('CCCC', 'ccc'), error('CCCC'));
|
||||
syncResolve(deferred, 'RESOLVED_VAL');
|
||||
|
||||
expect(log).toEqual(['successA(RESOLVED_VAL)->a',
|
||||
@@ -822,7 +823,7 @@ describe('q', function() {
|
||||
returnedDef.resolve('bar');
|
||||
|
||||
promise['finally'](fin(1, returnedDef.promise))
|
||||
.then(success(2))
|
||||
.then(success(2));
|
||||
|
||||
syncResolve(deferred, 'foo');
|
||||
|
||||
@@ -833,10 +834,10 @@ describe('q', function() {
|
||||
describe("that is rejected", function() {
|
||||
it("should reject with this new rejection reason",
|
||||
function () {
|
||||
var returnedDef = defer()
|
||||
var returnedDef = defer();
|
||||
returnedDef.reject('bar');
|
||||
promise['finally'](fin(1, returnedDef.promise))
|
||||
.then(success(2), error(1))
|
||||
.then(success(2), error(1));
|
||||
syncResolve(deferred, 'foo');
|
||||
expect(logStr()).toBe('finally1()->{}; error1(bar)->reject(bar)');
|
||||
});
|
||||
@@ -847,7 +848,7 @@ describe('q', function() {
|
||||
describe("when the callback throws an exception", function() {
|
||||
it("should reject with this new exception", function() {
|
||||
promise['finally'](fin(1, "exception", true))
|
||||
.then(success(1), error(2))
|
||||
.then(success(1), error(2));
|
||||
syncResolve(deferred, 'foo');
|
||||
expect(logStr()).toBe('finally1()->throw(exception); error2(exception)->reject(exception)');
|
||||
});
|
||||
@@ -860,14 +861,14 @@ describe('q', function() {
|
||||
|
||||
it("should call the callback", function () {
|
||||
promise['finally'](fin(1))
|
||||
.then(success(2), error(1))
|
||||
.then(success(2), error(1));
|
||||
syncReject(deferred, 'foo');
|
||||
expect(logStr()).toBe('finally1(); error1(foo)->reject(foo)');
|
||||
});
|
||||
|
||||
it('should reject with the original reason', function() {
|
||||
promise['finally'](fin(1), "hello")
|
||||
.then(success(2), error(2))
|
||||
.then(success(2), error(2));
|
||||
syncReject(deferred, 'original');
|
||||
expect(logStr()).toBe('finally1(); error2(original)->reject(original)');
|
||||
});
|
||||
@@ -877,10 +878,10 @@ describe('q', function() {
|
||||
describe("that is fulfilled", function() {
|
||||
|
||||
it("should reject with the original reason after that promise resolves", function () {
|
||||
var returnedDef = defer()
|
||||
var returnedDef = defer();
|
||||
returnedDef.resolve('bar');
|
||||
promise['finally'](fin(1, returnedDef.promise))
|
||||
.then(success(2), error(2))
|
||||
.then(success(2), error(2));
|
||||
syncReject(deferred, 'original');
|
||||
expect(logStr()).toBe('finally1()->{}; error2(original)->reject(original)');
|
||||
});
|
||||
@@ -890,10 +891,10 @@ describe('q', function() {
|
||||
describe("that is rejected", function () {
|
||||
|
||||
it("should reject with the new reason", function() {
|
||||
var returnedDef = defer()
|
||||
var returnedDef = defer();
|
||||
returnedDef.reject('bar');
|
||||
promise['finally'](fin(1, returnedDef.promise))
|
||||
.then(success(2), error(1))
|
||||
.then(success(2), error(1));
|
||||
syncResolve(deferred, 'foo');
|
||||
expect(logStr()).toBe('finally1()->{}; error1(bar)->reject(bar)');
|
||||
});
|
||||
@@ -906,7 +907,7 @@ describe('q', function() {
|
||||
|
||||
it("should reject with this new exception", function() {
|
||||
promise['finally'](fin(1, "exception", true))
|
||||
.then(success(1), error(2))
|
||||
.then(success(1), error(2));
|
||||
syncResolve(deferred, 'foo');
|
||||
expect(logStr()).toBe('finally1()->throw(exception); error2(exception)->reject(exception)');
|
||||
});
|
||||
@@ -918,7 +919,7 @@ describe('q', function() {
|
||||
|
||||
describe('catch', function() {
|
||||
it('should be a shorthand for defining promise error handlers', function() {
|
||||
promise['catch'](error(1)).then(null, error(2))
|
||||
promise['catch'](error(1)).then(null, error(2));
|
||||
syncReject(deferred, 'foo');
|
||||
expect(logStr()).toBe('error1(foo)->reject(foo); error2(foo)->reject(foo)');
|
||||
});
|
||||
@@ -937,7 +938,7 @@ describe('q', function() {
|
||||
|
||||
|
||||
it('should package an exception into a rejected promise', function() {
|
||||
var rejectedPromise = q.reject(Error('not gonna happen'));
|
||||
var rejectedPromise = q.reject(new Error('not gonna happen'));
|
||||
promise.then(success(), error());
|
||||
syncResolve(deferred, rejectedPromise);
|
||||
expect(log).toEqual(['error(Error: not gonna happen)->reject(Error: not gonna happen)']);
|
||||
@@ -955,7 +956,7 @@ describe('q', function() {
|
||||
it('should catch exceptions thrown in errback and forward them to derived promises', function() {
|
||||
var rejectedPromise = q.reject('rejected');
|
||||
rejectedPromise.then(null, error('Broken', 'catch me!', true)).
|
||||
then(null, error('Affected'))
|
||||
then(null, error('Affected'));
|
||||
mockNextTick.flush();
|
||||
expect(log).toEqual(['errorBroken(rejected)->throw(catch me!)', 'errorAffected(catch me!)->reject(catch me!)']);
|
||||
});
|
||||
@@ -1355,13 +1356,13 @@ describe('q', function() {
|
||||
logger: function(e) {
|
||||
mockExceptionLogger.log.push(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
q = qFactory(mockNextTick.nextTick, mockExceptionLogger.logger),
|
||||
defer = q.defer;
|
||||
deferred = defer()
|
||||
deferred = defer();
|
||||
promise = deferred.promise;
|
||||
log = [];
|
||||
mockExceptionLogger.log = [];
|
||||
@@ -1413,7 +1414,8 @@ describe('q', function() {
|
||||
log = [];
|
||||
syncResolve(deferred, 'ok');
|
||||
expect(logStr()).toBe('success(ok)->ok');
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ describe('$$rAF', function() {
|
||||
|
||||
try {
|
||||
$$rAF.flush();
|
||||
} catch(e) {};
|
||||
} catch(e) {}
|
||||
expect(present).toBe(true);
|
||||
}));
|
||||
|
||||
|
||||
+26
-22
@@ -13,6 +13,7 @@ describe('Scope', function() {
|
||||
|
||||
|
||||
it('should expose the constructor', inject(function($rootScope) {
|
||||
/* jshint -W103 */
|
||||
if (msie) return;
|
||||
expect($rootScope.__proto__).toBe($rootScope.constructor.prototype);
|
||||
}));
|
||||
@@ -251,7 +252,7 @@ describe('Scope', function() {
|
||||
|
||||
try {
|
||||
$rootScope.$digest();
|
||||
throw Error('Should have thrown exception');
|
||||
throw new Error('Should have thrown exception');
|
||||
} catch(e) {
|
||||
expect(e.message.match(/"fn: (watcherA|function)/g).length).toBe(10);
|
||||
}
|
||||
@@ -260,27 +261,27 @@ describe('Scope', function() {
|
||||
|
||||
it('should prevent infinite loop when creating and resolving a promise in a watched expression', function() {
|
||||
module(function($rootScopeProvider) {
|
||||
$rootScopeProvider.digestTtl(10);
|
||||
$rootScopeProvider.digestTtl(10);
|
||||
});
|
||||
inject(function($rootScope, $q) {
|
||||
var d = $q.defer();
|
||||
var d = $q.defer();
|
||||
|
||||
d.resolve('Hello, world.');
|
||||
$rootScope.$watch(function () {
|
||||
var $d2 = $q.defer();
|
||||
$d2.resolve('Goodbye.');
|
||||
$d2.promise.then(function () { });
|
||||
return d.promise;
|
||||
}, function () { return 0; });
|
||||
d.resolve('Hello, world.');
|
||||
$rootScope.$watch(function () {
|
||||
var $d2 = $q.defer();
|
||||
$d2.resolve('Goodbye.');
|
||||
$d2.promise.then(function () { });
|
||||
return d.promise;
|
||||
}, function () { return 0; });
|
||||
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).toThrowMinErr('$rootScope', 'infdig', '10 $digest() iterations reached. Aborting!\n'+
|
||||
'Watchers fired in the last 5 iterations: []');
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).toThrowMinErr('$rootScope', 'infdig', '10 $digest() iterations reached. Aborting!\n'+
|
||||
'Watchers fired in the last 5 iterations: []');
|
||||
|
||||
expect($rootScope.$$phase).toBeNull();
|
||||
});
|
||||
expect($rootScope.$$phase).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should not fire upon $watch registration on initial $digest', inject(function($rootScope) {
|
||||
@@ -748,7 +749,7 @@ describe('Scope', function() {
|
||||
$rootScope.$watch(log.fn('w4'), function() {
|
||||
log('w4action');
|
||||
$rootScope.$evalAsync(function() {
|
||||
log('evalAsync')
|
||||
log('evalAsync');
|
||||
});
|
||||
});
|
||||
$rootScope.$digest();
|
||||
@@ -1067,7 +1068,8 @@ describe('Scope', function() {
|
||||
expect($rootScope.$$asyncQueue).toEqual([
|
||||
{scope: $rootScope, expression: 'rootExpression'},
|
||||
{scope: childScope, expression: 'childExpression'},
|
||||
{scope: isolateScope, expression: 'isolateExpression'}]);
|
||||
{scope: isolateScope, expression: 'isolateExpression'}
|
||||
]);
|
||||
}));
|
||||
|
||||
|
||||
@@ -1247,9 +1249,11 @@ describe('Scope', function() {
|
||||
});
|
||||
});
|
||||
|
||||
expect(function() { childScope2.$apply(function() {
|
||||
childScope2.x = 'something';
|
||||
}); }).toThrowMinErr('$rootScope', 'inprog', '$digest already in progress');
|
||||
expect(function() {
|
||||
childScope2.$apply(function() {
|
||||
childScope2.x = 'something';
|
||||
});
|
||||
}).toThrowMinErr('$rootScope', 'inprog', '$digest already in progress');
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -1668,7 +1672,7 @@ describe('Scope', function() {
|
||||
expect(scope.greeting).toEqual(undefined);
|
||||
|
||||
scope.$watch('name', function() {
|
||||
scope.greeting = scope.salutation + ' ' + scope.name + '!';
|
||||
scope.greeting = scope.salutation + ' ' + scope.name + '!';
|
||||
}); // initialize the watch
|
||||
|
||||
expect(scope.greeting).toEqual(undefined);
|
||||
|
||||
@@ -12,7 +12,7 @@ describe('sanitizeUri', function() {
|
||||
};
|
||||
sanitizeImg = function(uri) {
|
||||
return $$sanitizeUri(uri, true);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ describe('sanitizeUri', function() {
|
||||
describe('img[src] sanitization', function() {
|
||||
|
||||
it('should sanitize javascript: urls', function() {
|
||||
/* jshint scripturl:true */
|
||||
testUrl = "javascript:doEvilStuff()";
|
||||
expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
|
||||
});
|
||||
@@ -50,6 +51,7 @@ describe('sanitizeUri', function() {
|
||||
});
|
||||
|
||||
it('should sanitize obfuscated javascript: urls', function() {
|
||||
/* jshint scripturl:true */
|
||||
// case-sensitive
|
||||
testUrl = "JaVaScRiPt:doEvilStuff()";
|
||||
expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
|
||||
@@ -79,6 +81,7 @@ describe('sanitizeUri', function() {
|
||||
});
|
||||
|
||||
it('should sanitize ng-src bindings as well', function() {
|
||||
/* jshint scripturl:true */
|
||||
testUrl = "javascript:doEvilStuff()";
|
||||
expect(sanitizeImg(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
|
||||
});
|
||||
@@ -115,6 +118,7 @@ describe('sanitizeUri', function() {
|
||||
|
||||
|
||||
it('should allow reconfiguration of the src whitelist', function() {
|
||||
/* jshint scripturl:true */
|
||||
var returnVal;
|
||||
expect(sanitizeUriProvider.imgSrcSanitizationWhitelist() instanceof RegExp).toBe(true);
|
||||
returnVal = sanitizeUriProvider.imgSrcSanitizationWhitelist(/javascript:/);
|
||||
@@ -133,6 +137,7 @@ describe('sanitizeUri', function() {
|
||||
describe('a[href] sanitization', function() {
|
||||
|
||||
it('should sanitize javascript: urls', inject(function() {
|
||||
/* jshint scripturl:true */
|
||||
testUrl = "javascript:doEvilStuff()";
|
||||
expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
|
||||
}));
|
||||
@@ -145,6 +150,7 @@ describe('sanitizeUri', function() {
|
||||
|
||||
|
||||
it('should sanitize obfuscated javascript: urls', inject(function() {
|
||||
/* jshint scripturl:true */
|
||||
// case-sensitive
|
||||
testUrl = "JaVaScRiPt:doEvilStuff()";
|
||||
expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
|
||||
@@ -175,6 +181,7 @@ describe('sanitizeUri', function() {
|
||||
|
||||
|
||||
it('should sanitize ngHref bindings as well', inject(function() {
|
||||
/* jshint scripturl:true */
|
||||
testUrl = "javascript:doEvilStuff()";
|
||||
expect(sanitizeHref(testUrl)).toBe('unsafe:javascript:doEvilStuff()');
|
||||
}));
|
||||
@@ -213,16 +220,17 @@ describe('sanitizeUri', function() {
|
||||
}));
|
||||
|
||||
it('should allow reconfiguration of the href whitelist', function() {
|
||||
/* jshint scripturl:true */
|
||||
var returnVal;
|
||||
expect(sanitizeUriProvider.aHrefSanitizationWhitelist() instanceof RegExp).toBe(true);
|
||||
returnVal = sanitizeUriProvider.aHrefSanitizationWhitelist(/javascript:/);
|
||||
expect(returnVal).toBe(sanitizeUriProvider);
|
||||
|
||||
testUrl = "javascript:doEvilStuff()";
|
||||
expect(sanitizeHref(testUrl)).toBe('javascript:doEvilStuff()');
|
||||
expect(sanitizeHref(testUrl)).toBe('javascript:doEvilStuff()');
|
||||
|
||||
testUrl = "http://recon/figured";
|
||||
expect(sanitizeHref(testUrl)).toBe('unsafe:http://recon/figured');
|
||||
expect(sanitizeHref(testUrl)).toBe('unsafe:http://recon/figured');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+33
-20
@@ -38,6 +38,7 @@ describe('SCE', function() {
|
||||
|
||||
inject(function($window, $injector) {
|
||||
function constructSce() {
|
||||
/* global $SceProvider: false */
|
||||
var sceProvider = new $SceProvider();
|
||||
sceProvider.enabled(enabled);
|
||||
return $injector.invoke(sceProvider.$get, sceProvider);
|
||||
@@ -162,7 +163,7 @@ describe('SCE', function() {
|
||||
};
|
||||
}
|
||||
var wrappedValue = new TrustedValueHolder("originalValue");
|
||||
expect(function() { return $sce.getTrusted($sce.HTML, wrappedValue) }).toThrowMinErr(
|
||||
expect(function() { return $sce.getTrusted($sce.HTML, wrappedValue); }).toThrowMinErr(
|
||||
'$sce', 'unsafe', 'Attempting to use an unsafe value in a safe context.');
|
||||
}));
|
||||
|
||||
@@ -179,9 +180,9 @@ describe('SCE', function() {
|
||||
it('should override the default $sce.trustAs/valueOf/etc.', function() {
|
||||
module(function($provide) {
|
||||
$provide.value('$sceDelegate', {
|
||||
trustAs: function(type, value) { return "wrapped:" + value; },
|
||||
getTrusted: function(type, value) { return "unwrapped:" + value; },
|
||||
valueOf: function(value) { return "valueOf:" + value; }
|
||||
trustAs: function(type, value) { return "wrapped:" + value; },
|
||||
getTrusted: function(type, value) { return "unwrapped:" + value; },
|
||||
valueOf: function(value) { return "valueOf:" + value; }
|
||||
});
|
||||
});
|
||||
|
||||
@@ -196,7 +197,7 @@ describe('SCE', function() {
|
||||
|
||||
|
||||
describe('$sce.parseAs', function($sce) {
|
||||
it('should parse constant literals as trusted', inject(function($sce) {
|
||||
it('should parse constant literals as trusted', inject(function($sce) {
|
||||
expect($sce.parseAsJs('1')()).toBe(1);
|
||||
expect($sce.parseAsJs('1', $sce.ANY)()).toBe(1);
|
||||
expect($sce.parseAsJs('1', $sce.HTML)()).toBe(1);
|
||||
@@ -218,7 +219,7 @@ describe('SCE', function() {
|
||||
it('should NOT return untrusted values from expression function', inject(function($sce) {
|
||||
var exprFn = $sce.parseAs($sce.HTML, 'foo');
|
||||
expect(function() {
|
||||
return exprFn({}, {'foo': true})
|
||||
return exprFn({}, {'foo': true});
|
||||
}).toThrowMinErr(
|
||||
'$sce', 'unsafe', 'Attempting to use an unsafe value in a safe context.');
|
||||
}));
|
||||
@@ -226,7 +227,7 @@ describe('SCE', function() {
|
||||
it('should NOT return trusted values of the wrong type from expression function', inject(function($sce) {
|
||||
var exprFn = $sce.parseAs($sce.HTML, 'foo');
|
||||
expect(function() {
|
||||
return exprFn({}, {'foo': $sce.trustAs($sce.JS, '123')})
|
||||
return exprFn({}, {'foo': $sce.trustAs($sce.JS, '123')});
|
||||
}).toThrowMinErr(
|
||||
'$sce', 'unsafe', 'Attempting to use an unsafe value in a safe context.');
|
||||
}));
|
||||
@@ -262,11 +263,11 @@ describe('SCE', function() {
|
||||
}
|
||||
});
|
||||
inject(testFn);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
it('should default to "self" which allows relative urls', runTest({}, function($sce, $document) {
|
||||
expect($sce.getTrustedResourceUrl('foo/bar')).toEqual('foo/bar');
|
||||
expect($sce.getTrustedResourceUrl('foo/bar')).toEqual('foo/bar');
|
||||
}));
|
||||
|
||||
it('should reject everything when whitelist is empty', runTest(
|
||||
@@ -276,7 +277,8 @@ describe('SCE', function() {
|
||||
}, function($sce) {
|
||||
expect(function() { $sce.getTrustedResourceUrl('#'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: #');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should match against normalized urls', runTest(
|
||||
{
|
||||
@@ -285,7 +287,8 @@ describe('SCE', function() {
|
||||
}, function($sce) {
|
||||
expect(function() { $sce.getTrustedResourceUrl('foo'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should not accept unknown matcher type', function() {
|
||||
expect(function() {
|
||||
@@ -296,6 +299,7 @@ describe('SCE', function() {
|
||||
});
|
||||
|
||||
describe('adjustMatcher', function() {
|
||||
/* global adjustMatcher: false */
|
||||
it('should rewrite regex into regex and add ^ & $ on either end', function() {
|
||||
expect(adjustMatcher(/a.*b/).exec('a.b')).not.toBeNull();
|
||||
expect(adjustMatcher(/a.*b/).exec('-a.b-')).toBeNull();
|
||||
@@ -318,7 +322,8 @@ describe('SCE', function() {
|
||||
// https doesn't match (mismatched protocol.)
|
||||
expect(function() { $sce.getTrustedResourceUrl('https://example.com/foo'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: https://example.com/foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should match entire regex', runTest(
|
||||
{
|
||||
@@ -335,7 +340,8 @@ describe('SCE', function() {
|
||||
// Prefix not allowed even though original regex does not contain a leading ^.
|
||||
expect(function() { $sce.getTrustedResourceUrl('xhttp://example.com/foo'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: xhttp://example.com/foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
});
|
||||
|
||||
describe('string matchers', function() {
|
||||
@@ -354,7 +360,8 @@ describe('SCE', function() {
|
||||
// You can match a suffix.
|
||||
expect(function() { $sce.getTrustedResourceUrl('xhttp://example.com/foo'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: xhttp://example.com/foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should support the * wildcard', runTest(
|
||||
{
|
||||
@@ -382,7 +389,8 @@ describe('SCE', function() {
|
||||
// The * wildcard does not match ';'
|
||||
expect(function() { $sce.getTrustedResourceUrl('http://example-com/foo;bar'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: http://example-com/foo;bar');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should support the ** wildcard', runTest(
|
||||
{
|
||||
@@ -394,7 +402,8 @@ describe('SCE', function() {
|
||||
expect($sce.getTrustedResourceUrl('http://example.com/foo-bar')).toEqual('http://example.com/foo-bar');
|
||||
// The ** wildcard accepts the ':/.?&' characters.
|
||||
expect($sce.getTrustedResourceUrl('http://example.com/foo:1/2.3?4&5-6')).toEqual('http://example.com/foo:1/2.3?4&5-6');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should not accept *** in the string', function() {
|
||||
expect(function() {
|
||||
@@ -412,7 +421,8 @@ describe('SCE', function() {
|
||||
blackList: []
|
||||
}, function($sce) {
|
||||
expect($sce.getTrustedResourceUrl('foo')).toEqual('foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should support the special string "self" in blacklist', runTest(
|
||||
{
|
||||
@@ -421,7 +431,8 @@ describe('SCE', function() {
|
||||
}, function($sce) {
|
||||
expect(function() { $sce.getTrustedResourceUrl('foo'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
});
|
||||
|
||||
it('should have blacklist override the whitelist', runTest(
|
||||
@@ -431,7 +442,8 @@ describe('SCE', function() {
|
||||
}, function($sce) {
|
||||
expect(function() { $sce.getTrustedResourceUrl('foo'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: foo');
|
||||
}));
|
||||
}
|
||||
));
|
||||
|
||||
it('should support multiple items in both lists', runTest(
|
||||
{
|
||||
@@ -445,7 +457,8 @@ describe('SCE', function() {
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: http://example.com/3');
|
||||
expect(function() { $sce.getTrustedResourceUrl('open_redirect'); }).toThrowMinErr(
|
||||
'$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: open_redirect');
|
||||
}));
|
||||
}
|
||||
));
|
||||
});
|
||||
|
||||
describe('sanitizing html', function() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
describe('$sniffer', function() {
|
||||
|
||||
function sniffer($window, $document) {
|
||||
/* global $SnifferProvider: false */
|
||||
$window.navigator = {};
|
||||
$document = jqLite($document || {});
|
||||
if (!$document[0].body) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user