Compare commits
174 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a65c3deb7 | |||
| ef0c333776 | |||
| bce1d8ecad | |||
| 5a1bc6eb32 | |||
| 1f7a0b2b72 | |||
| a665550933 | |||
| d434f3db53 | |||
| 7e08975b67 | |||
| 82c481bb23 | |||
| b1f46bb1b2 | |||
| 3a6bf0d5bc | |||
| e201f9040f | |||
| 40e9bcd1b4 | |||
| f98e038418 | |||
| ec98c94ccb | |||
| f13055a0a5 | |||
| 623ce1ad2c | |||
| 34cf141838 | |||
| 274e93537e | |||
| f7622dcc0d | |||
| 2c03a35743 | |||
| 6b72598b87 | |||
| 51e24d75c3 | |||
| 64a142b58e | |||
| 0026ebf2de | |||
| a4f73c9f99 | |||
| bd5c4e5f0e | |||
| 9742565d61 | |||
| 6f33dfa8cc | |||
| 96f0c8df17 | |||
| 53fb534889 | |||
| 6271ac064c | |||
| 2d71b5b053 | |||
| a547dff09b | |||
| 3f9517ea5b | |||
| 8b4ffdde7a | |||
| e57240d87d | |||
| a51b4e6dc4 | |||
| 215be0b0ab | |||
| 7c5880f998 | |||
| 0d941a986a | |||
| 8714cabdb7 | |||
| cbab2923ef | |||
| dba7e20e96 | |||
| 24dd9ea649 | |||
| 8bd59a593b | |||
| 9a1349d2e0 | |||
| 7e6155a6f1 | |||
| 0f034444c3 | |||
| 74ecea9f2d | |||
| 8d5c08c6b8 | |||
| 0bb57d538f | |||
| 61a3fb676a | |||
| f486ebe80b | |||
| 03190fd896 | |||
| 340e4da2eb | |||
| 46e4fa87fb | |||
| 45d43b9234 | |||
| 6b28aef1c5 | |||
| 5a1b4a06f4 | |||
| 12f08c5e14 | |||
| 706a93ab69 | |||
| c4ae7d261a | |||
| 0adc036426 | |||
| 1ee58612a2 | |||
| ddc7f85493 | |||
| 90621a6c89 | |||
| 0c59599a45 | |||
| 4a4db1e7e6 | |||
| 10d8b010d3 | |||
| 3881831906 | |||
| 9e3f82bbaf | |||
| 05156143c8 | |||
| 39b078bad4 | |||
| 9055b4e041 | |||
| 6224a3eefb | |||
| a45a34c261 | |||
| ceeeb6b4b1 | |||
| cbc5f1c114 | |||
| 4dfb80d96f | |||
| 368039b881 | |||
| 647f3f55eb | |||
| c8de0e425f | |||
| 9717c8fe1f | |||
| fee437f9cf | |||
| 861b1a3d9d | |||
| 72ff49f40f | |||
| 7a529992c8 | |||
| e89d6829bc | |||
| 1b343e7bb6 | |||
| b3c022d672 | |||
| 9dd0fe35d1 | |||
| 7560a8d2d6 | |||
| c68357dbf8 | |||
| eaf6981499 | |||
| 1cc24f3c4f | |||
| 9e3e26328e | |||
| 82b2961868 | |||
| 3cb10edca0 | |||
| b64519fea7 | |||
| 830c81d0f1 | |||
| 66650bfb36 | |||
| 900b3a416c | |||
| f40252205e | |||
| 40441f6dfc | |||
| 1f65087126 | |||
| d5c99ea42b | |||
| bbc5fdde50 | |||
| b5685e23f0 | |||
| 5b26521de2 | |||
| abfbfd6c1c | |||
| a0e91c4ef7 | |||
| 3353fb84aa | |||
| 3a22c6461d | |||
| 54f5d82d4f | |||
| e80434c93f | |||
| 7dd5d7a523 | |||
| 6198c0d9c0 | |||
| 1acde764d5 | |||
| 3bdb39f667 | |||
| f231dda29d | |||
| 03f858ea5c | |||
| 4a26249946 | |||
| 06364c8cdc | |||
| 1c282af5ab | |||
| 45f006f6fb | |||
| 731e1f6534 | |||
| 634e467172 | |||
| 2ca34a0cd3 | |||
| 181e5ebc3f | |||
| 874392464b | |||
| 7e7244402d | |||
| 4b94b9e34f | |||
| a2e7f54320 | |||
| 9b2e11b6fa | |||
| 2114a50c9a | |||
| 38f92c3a27 | |||
| 7dbf1ef2d1 | |||
| e13aae1ed0 | |||
| 36eacb172a | |||
| f2683f956f | |||
| 1a670aa466 | |||
| 578425303f | |||
| 528cf09e3f | |||
| c849098fbf | |||
| 145d397988 | |||
| 26d4d0dc22 | |||
| 64a9faaf8e | |||
| b7aba16839 | |||
| a72e1c4767 | |||
| 6545212d24 | |||
| 3fabbdb804 | |||
| ce8be9c47f | |||
| b3878a36d9 | |||
| ebd84e8008 | |||
| e721169738 | |||
| cdfbe25c00 | |||
| 0d4b15a4c9 | |||
| 0dd061c239 | |||
| 7288be25a7 | |||
| 2b279dd8a1 | |||
| 63b9956faf | |||
| 92767c098f | |||
| 2fe9b1dd9e | |||
| b9ad91cf1e | |||
| 40752a520a | |||
| 21369943fa | |||
| 190ea883c5 | |||
| 3a093123ef | |||
| b8e8f9af78 | |||
| 01161a0e9f | |||
| 75abbd525f | |||
| 01a725a769 | |||
| f5781dbb60 |
@@ -1,15 +0,0 @@
|
||||
// This is an incomplete TODO list of checks we want to start enforcing
|
||||
//
|
||||
// The goal is to enable these checks one by one by moving them to .jscs.json along with commits
|
||||
// that correct the existing code base issues and make the new check pass.
|
||||
|
||||
{
|
||||
"validateParameterSeparator": ", ", // Re-assert this rule when JSCS allows multiple spaces
|
||||
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
|
||||
"disallowImplicitTypeConversion": ["string"],
|
||||
"disallowMultipleLineBreaks": true,
|
||||
"validateJSDoc": {
|
||||
"checkParamNames": true,
|
||||
"requireParamTypes": true
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -1,4 +1,5 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '0.10'
|
||||
|
||||
@@ -47,7 +48,7 @@ install:
|
||||
- npm config set loglevel http
|
||||
- npm install -g npm@2.5
|
||||
# Instal npm dependecies and ensure that npm cache is not stale
|
||||
- scripts/npm/install-dependencies.sh
|
||||
- npm install
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
@@ -60,6 +61,7 @@ script:
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
after_script:
|
||||
- ./scripts/travis/tear_down_browser_provider.sh
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
notifications:
|
||||
|
||||
+722
-2
@@ -1,3 +1,723 @@
|
||||
<a name="1.3.20"></a>
|
||||
# 1.3.20 shallow-translucence (2015-09-29)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$parse:** do not convert to string computed properties multiple times
|
||||
([d434f3db](https://github.com/angular/angular.js/commit/d434f3db53d6209eb140b904e83bbde401686c16))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
|
||||
<a name="1.3.19"></a>
|
||||
# 1.3.19 glutinous-shriek (2015-09-15)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$http:** propagate status -1 for timed out requests
|
||||
([f13055a0](https://github.com/angular/angular.js/commit/f13055a0a53a39b160448713a5617edee6042801),
|
||||
[#4491](https://github.com/angular/angular.js/issues/4491), [#8756](https://github.com/angular/angular.js/issues/8756))
|
||||
- **$location:** don't crash if navigating outside the app base
|
||||
([623ce1ad](https://github.com/angular/angular.js/commit/623ce1ad2cf68024719c5cae5d682d00195df30c),
|
||||
[#11667](https://github.com/angular/angular.js/issues/11667))
|
||||
- **$parse:** throw error when accessing a restricted property indirectly
|
||||
([ec98c94c](https://github.com/angular/angular.js/commit/ec98c94ccbfc97b655447956738d5f6ff98b2f33),
|
||||
[#12833](https://github.com/angular/angular.js/issues/12833))
|
||||
- **ngModel:** validate pattern against the viewValue
|
||||
([274e9353](https://github.com/angular/angular.js/commit/274e93537ed4e95aefeacea48909eb334894f0ac),
|
||||
[#12344](https://github.com/angular/angular.js/issues/12344))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **ngAnimate:** introduce `$animate.flush` for unit testing
|
||||
([f98e0384](https://github.com/angular/angular.js/commit/f98e038418f7367b2373adcf4887f64a8e8bdcb0))
|
||||
|
||||
|
||||
## Possible Breaking Changes
|
||||
|
||||
- **ngModel:** due to [274e9353](https://github.com/angular/angular.js/commit/274e93537ed4e95aefeacea48909eb334894f0ac),
|
||||
|
||||
|
||||
The `ngPattern` and `pattern` directives will validate the regex
|
||||
against the `viewValue` of `ngModel`, i.e. the value of the model
|
||||
before the $parsers are applied. Previously, the modelValue
|
||||
(the result of the $parsers) was validated.
|
||||
|
||||
This fixes issues where `input[date]` and `input[number]` cannot
|
||||
be validated because the viewValue string is parsed into
|
||||
`Date` and `Number` respectively (starting with Angular 1.3).
|
||||
It also brings the directives in line with HTML5 constraint
|
||||
validation, which validates against the input value.
|
||||
|
||||
This change is unlikely to cause applications to fail, because even
|
||||
in Angular 1.2, the value that was validated by pattern could have
|
||||
been manipulated by the $parsers, as all validation was done
|
||||
inside this pipeline.
|
||||
|
||||
If you rely on the pattern being validated against the modelValue,
|
||||
you must create your own validator directive that overwrites
|
||||
the built-in pattern validator:
|
||||
|
||||
```
|
||||
.directive('patternModelOverwrite', function patternModelOverwriteDirective() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: '?ngModel',
|
||||
priority: 1,
|
||||
compile: function() {
|
||||
var regexp, patternExp;
|
||||
|
||||
return {
|
||||
pre: function(scope, elm, attr, ctrl) {
|
||||
if (!ctrl) return;
|
||||
|
||||
attr.$observe('pattern', function(regex) {
|
||||
/**
|
||||
* The built-in directive will call our overwritten validator
|
||||
* (see below). We just need to update the regex.
|
||||
* The preLink fn guaranetees our observer is called first.
|
||||
*/
|
||||
if (isString(regex) && regex.length > 0) {
|
||||
regex = new RegExp('^' + regex + '$');
|
||||
}
|
||||
|
||||
if (regex && !regex.test) {
|
||||
//The built-in validator will throw at this point
|
||||
return;
|
||||
}
|
||||
|
||||
regexp = regex || undefined;
|
||||
});
|
||||
|
||||
},
|
||||
post: function(scope, elm, attr, ctrl) {
|
||||
if (!ctrl) return;
|
||||
|
||||
regexp, patternExp = attr.ngPattern || attr.pattern;
|
||||
|
||||
//The postLink fn guarantees we overwrite the built-in pattern validator
|
||||
ctrl.$validators.pattern = function(value) {
|
||||
return ctrl.$isEmpty(value) ||
|
||||
isUndefined(regexp) ||
|
||||
regexp.test(value);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.3.18"></a>
|
||||
# 1.3.18 collective-penmanship (2015-08-18)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- clear class animations cache if animation is not started
|
||||
([2c03a357](https://github.com/angular/angular.js/commit/2c03a3574336ed814d020cf7ba36cee5b87e65b5),
|
||||
[#12604](https://github.com/angular/angular.js/issues/12604), [#12603](https://github.com/angular/angular.js/issues/12603))
|
||||
- do not throw errors if element is removed before animation starts
|
||||
([6b72598b](https://github.com/angular/angular.js/commit/6b72598b87022e1dd96bddc4451e007ef0601579),
|
||||
[#10205](https://github.com/angular/angular.js/issues/10205))
|
||||
- **ngModel:** correct minErr usage for correct doc creation
|
||||
([64a142b5](https://github.com/angular/angular.js/commit/64a142b58ed0a0e3896d82f3f9ce35373548d0ff),
|
||||
[#12386](https://github.com/angular/angular.js/issues/12386), [#12416](https://github.com/angular/angular.js/issues/12416))
|
||||
|
||||
|
||||
|
||||
<a name="1.3.17"></a>
|
||||
# 1.3.17 tsktskskly-euouae (2015-07-06)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$browser:** prevent infinite digest if changing hash when there is no hashPrefix
|
||||
([61a3fb67](https://github.com/angular/angular.js/commit/61a3fb676a186e22564fb0181c17647b35ca4e5e),
|
||||
[#10423](https://github.com/angular/angular.js/issues/10423), [#12145](https://github.com/angular/angular.js/issues/12145))
|
||||
- **$location:**
|
||||
- allow navigating outside the original base URL
|
||||
([0bb57d53](https://github.com/angular/angular.js/commit/0bb57d538f25a1b6f20025d87a451c39671b59aa),
|
||||
[#11302](https://github.com/angular/angular.js/issues/11302), [#4776](https://github.com/angular/angular.js/issues/4776))
|
||||
- do not get caught in infinite digest in IE9
|
||||
([f486ebe8](https://github.com/angular/angular.js/commit/f486ebe80b6d7854d3eb9029f14d94299cf493cb),
|
||||
[#11439](https://github.com/angular/angular.js/issues/11439), [#11675](https://github.com/angular/angular.js/issues/11675), [#11935](https://github.com/angular/angular.js/issues/11935), [#12083](https://github.com/angular/angular.js/issues/12083))
|
||||
- **linky:** allow case insensitive scheme detection
|
||||
([6b28aef1](https://github.com/angular/angular.js/commit/6b28aef1c537bfb2da21820d6ca154344efe266e),
|
||||
[#12073](https://github.com/angular/angular.js/issues/12073), [#12074](https://github.com/angular/angular.js/issues/12074))
|
||||
|
||||
|
||||
|
||||
<a name="1.3.16"></a>
|
||||
# 1.3.16 cookie-oatmealification (2015-06-05)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** throw error on invalid directive name
|
||||
([634e4671](https://github.com/angular/angular.js/commit/634e467172efa696eb32ef8942ffbedeecbd030e),
|
||||
[#11281](https://github.com/angular/angular.js/issues/11281), [#11109](https://github.com/angular/angular.js/issues/11109))
|
||||
- **$cookies:** update $cookies to prevent duplicate cookie writes and play nice with external code
|
||||
([706a93ab](https://github.com/angular/angular.js/commit/706a93ab6960e3474698ccf9a8048b3c32e567c6),
|
||||
[#11490](https://github.com/angular/angular.js/issues/11490), [#11515](https://github.com/angular/angular.js/issues/11515))
|
||||
- **$http:** throw error if `success` and `error` methods do not receive a function
|
||||
([731e1f65](https://github.com/angular/angular.js/commit/731e1f6534ab7fd1e053b8d7a25c902fcd934fea),
|
||||
[#11330](https://github.com/angular/angular.js/issues/11330), [#11333](https://github.com/angular/angular.js/issues/11333))
|
||||
- **core:** ensure that multiple requests to requestAnimationFrame are buffered
|
||||
([0adc0364](https://github.com/angular/angular.js/commit/0adc0364265b06c567ccc8e90a7f09cc46f235b2),
|
||||
[#11791](https://github.com/angular/angular.js/issues/11791))
|
||||
- **filterFilter:** fix matching against `null`/`undefined`
|
||||
([9dd0fe35](https://github.com/angular/angular.js/commit/9dd0fe35d1027e59b84b2396abee00d8683f3b50),
|
||||
[#11573](https://github.com/angular/angular.js/issues/11573), [#11617](https://github.com/angular/angular.js/issues/11617))
|
||||
- **jqLite:**
|
||||
- check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
|
||||
([647f3f55](https://github.com/angular/angular.js/commit/647f3f55eb7100a255272f7277f0f962de234a32),
|
||||
[#11508](https://github.com/angular/angular.js/issues/11508))
|
||||
- attr should ignore comment, text and attribute nodes
|
||||
([181e5ebc](https://github.com/angular/angular.js/commit/181e5ebc3fce5312feacaeace4fcad0d32f4d73c))
|
||||
- **ngAnimate:**
|
||||
- ensure that minified repaint code isn't removed
|
||||
([d5c99ea4](https://github.com/angular/angular.js/commit/d5c99ea42b834343fd0362cfc572f47e7536ccfb),
|
||||
[#9936](https://github.com/angular/angular.js/issues/9936))
|
||||
- **ngAria:** handle elements with role="checkbox/menuitemcheckbox"
|
||||
([1c282af5](https://github.com/angular/angular.js/commit/1c282af5abc205d4aac37c05c5cb725d71747134),
|
||||
[#11317](https://github.com/angular/angular.js/issues/11317), [#11321](https://github.com/angular/angular.js/issues/11321))
|
||||
- **ngModel:** allow setting model to NaN when asyncValidator is present
|
||||
([b64519fe](https://github.com/angular/angular.js/commit/b64519fea7f1a5ec75e32c4b71b012b827314153),
|
||||
[#11315](https://github.com/angular/angular.js/issues/11315), [#11411](https://github.com/angular/angular.js/issues/11411))
|
||||
- **ngTouch:**
|
||||
- check undefined tagName for SVG event target
|
||||
([7560a8d2](https://github.com/angular/angular.js/commit/7560a8d2d65955ddb60ede9d586502f4e3cbd062))
|
||||
- register touches properly when jQuery is used
|
||||
([40441f6d](https://github.com/angular/angular.js/commit/40441f6dfc5ebd5cdc679c269c4639238f5351eb),
|
||||
[#4001](https://github.com/angular/angular.js/issues/4001), [#8584](https://github.com/angular/angular.js/issues/8584), [#10797](https://github.com/angular/angular.js/issues/10797), [#11488](https://github.com/angular/angular.js/issues/11488))
|
||||
- **select:** prevent unknown option being added to select when bound to null property
|
||||
([9e3f82bb](https://github.com/angular/angular.js/commit/9e3f82bbaf83cad7bb3121db756099b0880562e6),
|
||||
[#11872](https://github.com/angular/angular.js/issues/11872), [#11875](https://github.com/angular/angular.js/issues/11875))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **travis:** run unit tests on iOS 8
|
||||
([1f650871](https://github.com/angular/angular.js/commit/1f650871266b88b3dab4a894a839a82ac9a06b69),
|
||||
[#11479](https://github.com/angular/angular.js/issues/11479))
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0"></a>
|
||||
# 1.4.0 jaracimrman-existence (2015-05-26)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ignore invalid option parameter values
|
||||
([72edd4df](https://github.com/angular/angular.js/commit/72edd4dff931c644eecb8f0d1c878dc839c76947),
|
||||
[#11826](https://github.com/angular/angular.js/issues/11826))
|
||||
- accept unwrapped DOM elements as inputs for enter + move
|
||||
([f26fc26f](https://github.com/angular/angular.js/commit/f26fc26f6ea283b2fc5ddb18627b13850de2663e),
|
||||
[#11848](https://github.com/angular/angular.js/issues/11848))
|
||||
- **$animateCss:** ensure that custom durations do not confuse the gcs cache
|
||||
([e0e1b520](https://github.com/angular/angular.js/commit/e0e1b5208767dd62f5586fdc607cb2e31dac9516),
|
||||
[#11723](https://github.com/angular/angular.js/issues/11723), [#11852](https://github.com/angular/angular.js/issues/11852))
|
||||
- **$http:** do not modify the config object passed into $http short methods
|
||||
([f7a4b481](https://github.com/angular/angular.js/commit/f7a4b48121ed2b04af89bd2b754f500d1872360d))
|
||||
- **ngAnimate:**
|
||||
- close follow-up class-based animations when the same class is added/removed when removed/added
|
||||
([db246eb7](https://github.com/angular/angular.js/commit/db246eb701529b41049fc118908e528920f13b24),
|
||||
[#11717](https://github.com/angular/angular.js/issues/11717))
|
||||
- ensure nested class-based animations are spaced out with a RAF
|
||||
([213c2a70](https://github.com/angular/angular.js/commit/213c2a703293ee0af8229dde2b608687cd77ccfa),
|
||||
[#11812](https://github.com/angular/angular.js/issues/11812))
|
||||
- class-based animations must not set addClass/removeClass CSS classes on the element
|
||||
([3a3db690](https://github.com/angular/angular.js/commit/3a3db690a16e888aa7371e3b02e2954b9ec2d558),
|
||||
[#11810](https://github.com/angular/angular.js/issues/11810))
|
||||
- ensure that repeated structural calls during pre-digest function
|
||||
([2327f5a0](https://github.com/angular/angular.js/commit/2327f5a0a7e018a9b03aefabe1fbd0c9330e2eeb),
|
||||
[#11867](https://github.com/angular/angular.js/issues/11867))
|
||||
- ensure that cancelled class-based animations are properly cleaned up
|
||||
([718ff844](https://github.com/angular/angular.js/commit/718ff84405558ac64402e1fca5caefd7d307ea1e),
|
||||
[#11652](https://github.com/angular/angular.js/issues/11652))
|
||||
- throw an error if a callback is passed to animate methods
|
||||
([9bb4d6cc](https://github.com/angular/angular.js/commit/9bb4d6ccbe80b7704c6b7f53317ca8146bc103ca),
|
||||
[#11826](https://github.com/angular/angular.js/issues/11826), [#11713](https://github.com/angular/angular.js/issues/11713))
|
||||
- ensure anchored animations remove the leave element at correct time
|
||||
([64c66d0e](https://github.com/angular/angular.js/commit/64c66d0eea11b575d2a71d00c70cfc5be12cd450),
|
||||
[#11850](https://github.com/angular/angular.js/issues/11850))
|
||||
- **select:** prevent unknown option being added to select when bound to null property
|
||||
([4090491c](https://github.com/angular/angular.js/commit/4090491c73910c169d4fba0494a4e26b45dca7ec),
|
||||
[#11872](https://github.com/angular/angular.js/issues/11872), [#11875](https://github.com/angular/angular.js/issues/11875))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **filterFilter:** allow array like objects to be filtered
|
||||
([1b0d0fd8](https://github.com/angular/angular.js/commit/1b0d0fd8d00b42dffd798845fe0947d594372613),
|
||||
[#11782](https://github.com/angular/angular.js/issues/11782), [#11787](https://github.com/angular/angular.js/issues/11787))
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-rc.2"></a>
|
||||
# 1.4.0-rc.2 rocket-zambonimation (2015-05-12)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** ensure directive names have no leading or trailing whitespace
|
||||
([bab474aa](https://github.com/angular/angular.js/commit/bab474aa8b146f6732857c3af1a8b3b010fda8b0),
|
||||
[#11397](https://github.com/angular/angular.js/issues/11397), [#11772](https://github.com/angular/angular.js/issues/11772))
|
||||
- **$httpParamSerializerJQLike:** follow jQuery logic for nested params
|
||||
([2420a0a7](https://github.com/angular/angular.js/commit/2420a0a77e27b530dbb8c41319b2995eccf76791),
|
||||
[#11551](https://github.com/angular/angular.js/issues/11551), [#11635](https://github.com/angular/angular.js/issues/11635))
|
||||
- **jqLite:** check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
|
||||
([426a5ac0](https://github.com/angular/angular.js/commit/426a5ac0547109648e5c5e358f668c274a111ab2),
|
||||
[#11508](https://github.com/angular/angular.js/issues/11508))
|
||||
- **ngAnimate:**
|
||||
- ensure that multiple requests to requestAnimationFrame are buffered
|
||||
([db20b830](https://github.com/angular/angular.js/commit/db20b830fc6074a00dc11d3f47d665c55e8bb515),
|
||||
[#11791](https://github.com/angular/angular.js/issues/11791))
|
||||
- ensure that an object is always returned even when no animation is set to run
|
||||
([d5683d21](https://github.com/angular/angular.js/commit/d5683d21165e725bc5a850e795f681b0a8a008f5))
|
||||
- force use of `ng-anchor` instead of a suffixed `-anchor` CSS class when triggering anchor animations
|
||||
([df24410c](https://github.com/angular/angular.js/commit/df24410c17d51a8d44929b9cffee2c91cedfed72))
|
||||
- rename `ng-animate-anchor` to `ng-anchor`
|
||||
([e6d053de](https://github.com/angular/angular.js/commit/e6d053de0993c0d38de46ad8a9c6760537316430))
|
||||
- ensure that shared CSS classes between anchor nodes are retained
|
||||
([e0014002](https://github.com/angular/angular.js/commit/e0014002370278778077d0612f9fab6beb80d07a),
|
||||
[#11681](https://github.com/angular/angular.js/issues/11681))
|
||||
- prohibit usage of the `ng-animate` class with classNameFilter
|
||||
([1002b80a](https://github.com/angular/angular.js/commit/1002b80a6fb5d98c424a01330234276d65d93c0b),
|
||||
[#11431](https://github.com/angular/angular.js/issues/11431), [#11807](https://github.com/angular/angular.js/issues/11807))
|
||||
- ensure that the temporary CSS classes are applied before detection
|
||||
([f7e9ff1a](https://github.com/angular/angular.js/commit/f7e9ff1aba9ed70835c084e6e154f6b0bf9c3a19),
|
||||
[#11769](https://github.com/angular/angular.js/issues/11769), [#11804](https://github.com/angular/angular.js/issues/11804))
|
||||
- ensure that all jqLite elements are deconstructed properly
|
||||
([64d05180](https://github.com/angular/angular.js/commit/64d05180a667e586328fbdbd328889d3b003571d),
|
||||
[#11658](https://github.com/angular/angular.js/issues/11658))
|
||||
- ensure animations are not attempted on text nodes
|
||||
([2aacc2d6](https://github.com/angular/angular.js/commit/2aacc2d622893e05eb94b3974d562e681cc3a17f),
|
||||
[#11703](https://github.com/angular/angular.js/issues/11703))
|
||||
- ensure JS animations recognize $animateCss directly
|
||||
([0681a540](https://github.com/angular/angular.js/commit/0681a5400e4150a961f9c8651e55623ca23b0cc2))
|
||||
- **ngClass:** add/remove classes which are properties of Object.prototype
|
||||
([f7b99970](https://github.com/angular/angular.js/commit/f7b999703f4f3bdaea035ce692f1a656b0c1a933),
|
||||
[#11813](https://github.com/angular/angular.js/issues/11813), [#11814](https://github.com/angular/angular.js/issues/11814))
|
||||
- **ngOptions:**
|
||||
- ensure that tracked properties are always watched
|
||||
([b5a9053b](https://github.com/angular/angular.js/commit/b5a9053ba33d48db2482ca6736d1fcae8b33d0f8),
|
||||
[#11784](https://github.com/angular/angular.js/issues/11784))
|
||||
- ensure label is watched in all cases
|
||||
([ae98dadf](https://github.com/angular/angular.js/commit/ae98dadf6dca3313746f42a441c7659654dd9d50),
|
||||
[#11765](https://github.com/angular/angular.js/issues/11765))
|
||||
- iterate over the options collection in the same way as `ngRepeat`
|
||||
([dfa722a8](https://github.com/angular/angular.js/commit/dfa722a8a6864793fd9580d8ae704a06d10b5509),
|
||||
[#11733](https://github.com/angular/angular.js/issues/11733))
|
||||
- use watchCollection not deep watch of ngModel
|
||||
([47f9fc3e](https://github.com/angular/angular.js/commit/47f9fc3e70bc361e8c11fe68dc3ec4489238efb3),
|
||||
[#11372](https://github.com/angular/angular.js/issues/11372), [#11653](https://github.com/angular/angular.js/issues/11653), [#11743](https://github.com/angular/angular.js/issues/11743))
|
||||
- **ngTouch:**
|
||||
- check undefined tagName for SVG event target
|
||||
([74eb17d7](https://github.com/angular/angular.js/commit/74eb17d7c8232f72f134bf2546f10fed7234d276))
|
||||
- don't prevent click event after a touchmove
|
||||
([95521876](https://github.com/angular/angular.js/commit/95521876eb9eb330548b0549f0cfe22a26d88f6e),
|
||||
[#10985](https://github.com/angular/angular.js/issues/10985))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$resource:** include request context in error message
|
||||
([266bc652](https://github.com/angular/angular.js/commit/266bc6520ba4d188dbc949643def102604f98905),
|
||||
[#11363](https://github.com/angular/angular.js/issues/11363))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
### ngAnimate
|
||||
|
||||
- **$animateCss:** due to [d5683d21](https://github.com/angular/angular.js/commit/d5683d21165e725bc5a850e795f681b0a8a008f5),
|
||||
The $animateCss service will now always return an
|
||||
object even if the animation is not set to run. If your code is using
|
||||
$animateCss then please consider the following code change:
|
||||
|
||||
```
|
||||
// before
|
||||
var animator = $animateCss(element, { ... });
|
||||
if (!animator) {
|
||||
continueApp();
|
||||
return;
|
||||
}
|
||||
var runner = animator.start();
|
||||
runner.done(continueApp);
|
||||
runner.then(continueApp);
|
||||
|
||||
// now
|
||||
var animator = $animateCss(element, { ... });
|
||||
var runner = animator.start();
|
||||
runner.done(continueApp);
|
||||
runner.then(continueApp);
|
||||
```
|
||||
|
||||
- due to [df24410c](https://github.com/angular/angular.js/commit/df24410c17d51a8d44929b9cffee2c91cedfed72),
|
||||
Prior to this fix there were to ways to apply CSS
|
||||
animation code to an anchor animation. With this fix, the suffixed
|
||||
CSS -anchor classes are now not used anymore for CSS anchor animations.
|
||||
|
||||
Instead just use the `ng-anchor` CSS class like so:
|
||||
|
||||
```html
|
||||
<div class="container-animation" ng-if="on">
|
||||
<div ng-animate-ref="1" class="my-anchor-element"></div>
|
||||
</div>
|
||||
|
||||
<div class="container-animation" ng-if="!on">
|
||||
<div ng-animate-ref="1" class="my-anchor-element"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**before**:
|
||||
```css
|
||||
/* before (notice the container-animation CSS class) */
|
||||
.container-animation-anchor {
|
||||
transition:0.5s linear all;
|
||||
}
|
||||
```
|
||||
|
||||
**now**:
|
||||
```css
|
||||
/* now (just use `ng-anchor` on a class that both the
|
||||
elements that contain `ng-animate-ref` share) */
|
||||
.my-anchor-element.ng-anchor {
|
||||
transition:0.5s linear all;
|
||||
}
|
||||
```
|
||||
|
||||
- due to [e6d053de](https://github.com/angular/angular.js/commit/e6d053de0993c0d38de46ad8a9c6760537316430),
|
||||
if your CSS code made use of the `ng-animate-anchor`
|
||||
CSS class for referencing the anchored animation element then your
|
||||
code must now use `ng-anchor` instead.
|
||||
|
||||
- due to [1002b80a](https://github.com/angular/angular.js/commit/1002b80a6fb5d98c424a01330234276d65d93c0b),
|
||||
partially or fully using a regex value containing
|
||||
`ng-animate` as a token is not allowed anymore. Doing so will trigger a
|
||||
minErr exception to be thrown.
|
||||
|
||||
So don't do this:
|
||||
|
||||
```js
|
||||
// only animate elements that contain the `ng-animate` CSS class
|
||||
$animateProvider.classNameFilter(/ng-animate/);
|
||||
|
||||
// or partially contain it
|
||||
$animateProvider.classNameFilter(/some-class ng-animate another-class/);
|
||||
```
|
||||
|
||||
but this is OK:
|
||||
|
||||
```js
|
||||
$animateProvider.classNameFilter(/ng-animate-special/);
|
||||
```
|
||||
|
||||
|
||||
### ngOptions
|
||||
|
||||
- ** due to [dfa722a8](https://github.com/angular/angular.js/commit/dfa722a8a6864793fd9580d8ae704a06d10b5509),
|
||||
|
||||
|
||||
Although it is unlikely that anyone is using it in this way, this change does change the
|
||||
behaviour of `ngOptions` in the following case:
|
||||
|
||||
* you are iterating over an array-like object, using the array form of the `ngOptions` syntax
|
||||
(`item.label for item in items`) and that object contains non-numeric property keys.
|
||||
|
||||
In this case these properties with non-numeric keys will be ignored.
|
||||
|
||||
** Here array-like is defined by the result of a call to this internal function:
|
||||
https://github.com/angular/angular.js/blob/v1.4.0-rc.1/src/Angular.js#L198-L211 **
|
||||
|
||||
To get the desired behaviour you need to iterate using the object form of the `ngOptions` syntax
|
||||
(`value.label` for (key, value) in items)`).
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-beta.6"></a>
|
||||
# 1.4.0-beta.6 cookie-liberation (2015-03-17)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:** call `applyStyles` from options on `leave`
|
||||
([4374f892](https://github.com/angular/angular.js/commit/4374f892c6fa4af6ba1f2ed47c5f888fdb5fadc5),
|
||||
[#10068](https://github.com/angular/angular.js/issues/10068))
|
||||
- **$browser:** don't crash if `history.state` access causes error in IE
|
||||
([3b8163b7](https://github.com/angular/angular.js/commit/3b8163b7b664f24499e75460ab50c066eaec0f78),
|
||||
[#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369))
|
||||
- **$sanitize:** disallow unsafe svg animation tags
|
||||
([67688d5c](https://github.com/angular/angular.js/commit/67688d5ca00f6de4c7fe6084e2fa762a00d25610),
|
||||
[#11290](https://github.com/angular/angular.js/issues/11290))
|
||||
- **Angular:** properly compare RegExp with other objects for equality
|
||||
([f22e1fc9](https://github.com/angular/angular.js/commit/f22e1fc9610ae111a3ea8746a3a57169c99ce142),
|
||||
[#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205))
|
||||
- **date filter:** display localised era for `G` format codes
|
||||
([2b4dfa9e](https://github.com/angular/angular.js/commit/2b4dfa9e2b63d7ebb78f3b0fd3439d18f932e1cd),
|
||||
[#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266))
|
||||
- **filterFilter:**
|
||||
- fix filtering using an object expression when the filter value is undefined
|
||||
([c62fa6bd](https://github.com/angular/angular.js/commit/c62fa6bd898e1048d4690d41034489dc60ba6ac2),
|
||||
[#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424))
|
||||
- do not throw an error if property is null when comparing objects
|
||||
([2c4ffd6a](https://github.com/angular/angular.js/commit/2c4ffd6af4eb012c4054fe7c096267bbc5510af0),
|
||||
[#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116))
|
||||
- **form:** allow dynamic form names which initially evaluate to blank
|
||||
([410f7c68](https://github.com/angular/angular.js/commit/410f7c682633c681be641cd2a321f9e51671d474))
|
||||
- **jqLite:** attr should ignore comment, text and attribute nodes
|
||||
([bb5bf7f8](https://github.com/angular/angular.js/commit/bb5bf7f8162d11610a53428e630b47030bdc38e5))
|
||||
- **ng/$locale:** add ERA info in generic locale
|
||||
([4acb0af2](https://github.com/angular/angular.js/commit/4acb0af24c7fb3705a197ca96adc532de4766a7a))
|
||||
- **ngJq:** don't rely on existence of jqlite
|
||||
([342e5f3c](https://github.com/angular/angular.js/commit/342e5f3ce38d2fd10c5d5a98ca66f864286a7922),
|
||||
[#11044](https://github.com/angular/angular.js/issues/11044))
|
||||
- **ngMessages:** ensure that multi-level transclusion works with `ngMessagesInclude`
|
||||
([d7ec5f39](https://github.com/angular/angular.js/commit/d7ec5f392e1550658ddf271a30627b1749eccb69),
|
||||
[#11196](https://github.com/angular/angular.js/issues/11196))
|
||||
- **ngOptions:** fix model<->option interaction when using `track by`
|
||||
([6a03ca27](https://github.com/angular/angular.js/commit/6a03ca274314352052c3082163367a146bb11c2d),
|
||||
[#10869](https://github.com/angular/angular.js/issues/10869), [#10893](https://github.com/angular/angular.js/issues/10893))
|
||||
- **rootScope:** prevent memory leak when destroying scopes
|
||||
([fb7db4a0](https://github.com/angular/angular.js/commit/fb7db4a07bd1b0b67824d3808fe315419b272689),
|
||||
[#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$cookies:**
|
||||
- allow passing cookie options
|
||||
([92c366d2](https://github.com/angular/angular.js/commit/92c366d205da36ec26502aded23db71a6473dad7),
|
||||
[#8324](https://github.com/angular/angular.js/issues/8324), [#3988](https://github.com/angular/angular.js/issues/3988), [#1786](https://github.com/angular/angular.js/issues/1786), [#950](https://github.com/angular/angular.js/issues/950))
|
||||
- move logic into $cookies and deprecate $cookieStore
|
||||
([38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
|
||||
[#6411](https://github.com/angular/angular.js/issues/6411), [#7631](https://github.com/angular/angular.js/issues/7631))
|
||||
- **$cookiesProvider:** provide path, domain, expires and secure options
|
||||
([53c66369](https://github.com/angular/angular.js/commit/53c663699126815eabc2a3bc1e3bafc8b3874268))
|
||||
- **$interval:** pass additional arguments to the callback
|
||||
([4f1f9cfd](https://github.com/angular/angular.js/commit/4f1f9cfdb721cf308ca1162b2227836dc1d28388),
|
||||
[#10632](https://github.com/angular/angular.js/issues/10632))
|
||||
- **$timeout:** pass additional arguments to the callback
|
||||
([3a4b6b83](https://github.com/angular/angular.js/commit/3a4b6b83efdb8051e5c4803c0892c19ceb2cba50),
|
||||
[#10631](https://github.com/angular/angular.js/issues/10631))
|
||||
- **angular.merge:** provide an alternative to `angular.extend` that merges 'deeply'
|
||||
([c0498d45](https://github.com/angular/angular.js/commit/c0498d45feb913c318224ea70b5adf7112df6bac),
|
||||
[#10507](https://github.com/angular/angular.js/issues/10507), [#10519](https://github.com/angular/angular.js/issues/10519))
|
||||
- **filterFilter:** compare object with custom `toString()` to primitive
|
||||
([f8c42161](https://github.com/angular/angular.js/commit/f8c421617096a8d613f4eb6d0f5b098ee149c029),
|
||||
[#10464](https://github.com/angular/angular.js/issues/10464), [#10548](https://github.com/angular/angular.js/issues/10548))
|
||||
- **ngAria:**
|
||||
- add `button` role to `ngClick`
|
||||
([bb365070](https://github.com/angular/angular.js/commit/bb365070a3ed7c2d26056d378ab6a8ef493b23cc),
|
||||
[#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- add roles to custom inputs
|
||||
([29cdaee2](https://github.com/angular/angular.js/commit/29cdaee2b6e853bc3f8882a00661698d146ecd18),
|
||||
[#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- **ngLocale:** Add FIRSTDAYOFWEEK and WEEKENDRANGE from google data
|
||||
([3d149c7f](https://github.com/angular/angular.js/commit/3d149c7f20ffabab5a635af9ddcfc7105112ab4a))
|
||||
- **ngMock:**
|
||||
- allow mock $controller service to set up controller bindings
|
||||
([d02d0585](https://github.com/angular/angular.js/commit/d02d0585a086ecd2e1de628218b5a6d85c8fc7bd),
|
||||
[#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239))
|
||||
- add `they` helpers for testing multiple specs
|
||||
([e650c458](https://github.com/angular/angular.js/commit/e650c45894abe6314a806e6b3e32c908df5c00fd),
|
||||
[#10864](https://github.com/angular/angular.js/issues/10864))
|
||||
- **ngModel:** support conversion to timezone other than UTC
|
||||
([0413bee8](https://github.com/angular/angular.js/commit/0413bee8cc563a6555f8d42d5f183f6fbefc7350),
|
||||
[#11005](https://github.com/angular/angular.js/issues/11005))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$cookies:** due to [38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
|
||||
|
||||
|
||||
`$cookies` no longer exposes properties that represent the current browser cookie
|
||||
values. Now you must explicitly the methods described above to access the cookie
|
||||
values. This also means that you can no longer watch the `$cookies` properties for
|
||||
changes to the browser's cookies.
|
||||
|
||||
This feature is generally only needed if a 3rd party library was programmatically
|
||||
changing the cookies at runtime. If you rely on this then you must either write code that
|
||||
can react to the 3rd party library making the changes to cookies or implement your own polling
|
||||
mechanism.
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.3.15"></a>
|
||||
# 1.3.15 locality-filtration (2015-03-17)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:** call `applyStyles` with options on `leave`
|
||||
([ebd84e80](https://github.com/angular/angular.js/commit/ebd84e8008f45ccaa84290f6da8c2a114fcfa8cd),
|
||||
[#10068](https://github.com/angular/angular.js/issues/10068))
|
||||
- **$browser:** don't crash if history.state access causes error in IE
|
||||
([92767c09](https://github.com/angular/angular.js/commit/92767c098feaf8c58faf2d67f882305019d8160e),
|
||||
[#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369))
|
||||
- **Angular:** properly compare RegExp with other objects for equality
|
||||
([b8e8f9af](https://github.com/angular/angular.js/commit/b8e8f9af78f4ef3e556dd3cef6bfee35ad4cb82a),
|
||||
[#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205))
|
||||
- **date filter:** display localised era for `G` format codes
|
||||
([f2683f95](https://github.com/angular/angular.js/commit/f2683f956fcd3216eaa263db20b31e0d46338800),
|
||||
[#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266))
|
||||
- **filterFilter:**
|
||||
- fix filtering using an object expression when the filter value is `undefined`
|
||||
([63b9956f](https://github.com/angular/angular.js/commit/63b9956faf4c3679c88a9401b8ccbb111c0294ee),
|
||||
[#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424))
|
||||
- do not throw an error if property is null when comparing objects
|
||||
([01161a0e](https://github.com/angular/angular.js/commit/01161a0e9fb1af93e9f06535aed8392ed7f116a4),
|
||||
[#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116))
|
||||
- **form:** allow dynamic form names which initially evaluate to blank
|
||||
([190ea883](https://github.com/angular/angular.js/commit/190ea883c588d63f8b900a8de1d45c6c9ebb01ec),
|
||||
[#11096](https://github.com/angular/angular.js/issues/11096))
|
||||
- **ng/$locale:** add ERA info in generic locale
|
||||
([57842530](https://github.com/angular/angular.js/commit/578425303f2480959da80f31920d08f277d42010))
|
||||
- **rootScope:** prevent memory leak when destroying scopes
|
||||
([528cf09e](https://github.com/angular/angular.js/commit/528cf09e3f78ad4e3bb6a329ebe315c4f29b4cdb),
|
||||
[#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169))
|
||||
- **templateRequest:** avoid throwing syntax error in Android 2.3
|
||||
([75abbd52](https://github.com/angular/angular.js/commit/75abbd525f07866fdcc6fb311802b8fe700af174),
|
||||
[#11089](https://github.com/angular/angular.js/issues/11089), [#11051](https://github.com/angular/angular.js/issues/11051), [#11088](https://github.com/angular/angular.js/issues/11088))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **ngAria:**
|
||||
- add `button` role to `ngClick`
|
||||
([b9ad91cf](https://github.com/angular/angular.js/commit/b9ad91cf1e86310a2d2bf13b29fa13a9b835e1ce),
|
||||
[#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- add roles to custom inputs
|
||||
([21369943](https://github.com/angular/angular.js/commit/21369943fafd577b36827a641b021b1c14cefb57),
|
||||
[#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- **ngMock:**
|
||||
- allow mock $controller service to set up controller bindings
|
||||
([b3878a36](https://github.com/angular/angular.js/commit/b3878a36d9f8e56ad7be1eedb9691c9bd12568cb),
|
||||
[#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239))
|
||||
- add `they` helpers for testing multiple specs
|
||||
([7288be25](https://github.com/angular/angular.js/commit/7288be25a75d6ca6ac7eca05a7d6b12ccb3a22f8),
|
||||
[#10864](https://github.com/angular/angular.js/issues/10864))
|
||||
|
||||
|
||||
<a name="1.4.0-beta.5"></a>
|
||||
# 1.4.0-beta.5 karmic-stabilization (2015-02-24)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$http:** properly access request headers with mixed case
|
||||
([5da1256f](https://github.com/angular/angular.js/commit/5da1256fc2812d5b28fb0af0de81256054856369),
|
||||
[#10881](https://github.com/angular/angular.js/issues/10881), [#10883](https://github.com/angular/angular.js/issues/10883))
|
||||
- **input:** create max and/or min validator regardless of initial value
|
||||
([c211e7a5](https://github.com/angular/angular.js/commit/c211e7a5ad5f1fb8748125f14912aa8715081925),
|
||||
[#10307](https://github.com/angular/angular.js/issues/10307), [#10327](https://github.com/angular/angular.js/issues/10327))
|
||||
- **ngAria:** correctly set "checked" attr for checkboxes and radios
|
||||
([d6eba217](https://github.com/angular/angular.js/commit/d6eba21733c6e67e90e3a4763d8d41ad89a73a0c),
|
||||
[#10389](https://github.com/angular/angular.js/issues/10389), [#10212](https://github.com/angular/angular.js/issues/10212))
|
||||
- **ngModel:** fix issues when parserName is same as validator key
|
||||
([056a3170](https://github.com/angular/angular.js/commit/056a31700803c0a6014b43cfcc36c5c500cc596e),
|
||||
[#10698](https://github.com/angular/angular.js/issues/10698), [#10850](https://github.com/angular/angular.js/issues/10850), [#11046](https://github.com/angular/angular.js/issues/11046))
|
||||
- **ngOptions:** ngModel is optional
|
||||
([ef894c87](https://github.com/angular/angular.js/commit/ef894c87eaead76d90169113ab6acc9287654ea3))
|
||||
- **ngSanitize:** Do not ignore white-listed svg camelCased attributes
|
||||
([46b80654](https://github.com/angular/angular.js/commit/46b80654cae9105642909cd55f73f7c26d2fbd80),
|
||||
[#10779](https://github.com/angular/angular.js/issues/10779), [#10990](https://github.com/angular/angular.js/issues/10990), [#11124](https://github.com/angular/angular.js/issues/11124))
|
||||
- **select:** remove unknown option when model is undefined and empty option is available
|
||||
([30b48132](https://github.com/angular/angular.js/commit/30b48132e0fb92ea8dd25a9794b4c41a3a81a951),
|
||||
[#11078](https://github.com/angular/angular.js/issues/11078), [#11092](https://github.com/angular/angular.js/issues/11092))
|
||||
- **templateRequest:** avoid throwing syntax error in Android 2.3
|
||||
([f6272333](https://github.com/angular/angular.js/commit/f6272333127d908b19da23f9cd8a74052711795b),
|
||||
[#11089](https://github.com/angular/angular.js/issues/11089), [#11051](https://github.com/angular/angular.js/issues/11051), [#11088](https://github.com/angular/angular.js/issues/11088))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **CommonJS:** - angular modules are now packaged for npm with helpful exports
|
||||
|
||||
- **limitTo:** extend the filter to take a beginning index argument
|
||||
([aaae3cc4](https://github.com/angular/angular.js/commit/aaae3cc4160417e6dad802ed9d9f6d5471821a87),
|
||||
[#5355](https://github.com/angular/angular.js/issues/5355), [#10899](https://github.com/angular/angular.js/issues/10899))
|
||||
- **ngMessages:** provide support for dynamic message resolution
|
||||
([c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
|
||||
[#10036](https://github.com/angular/angular.js/issues/10036), [#9338](https://github.com/angular/angular.js/issues/9338))
|
||||
- **ngOptions:** add support for disabling an option
|
||||
([da9eac86](https://github.com/angular/angular.js/commit/da9eac8660343b1cd9fdcf9d2d1bda06067142d7),
|
||||
[#638](https://github.com/angular/angular.js/issues/638), [#11017](https://github.com/angular/angular.js/issues/11017))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$compile:**
|
||||
- replace forEach(controller) with plain loops
|
||||
([5b522867](https://github.com/angular/angular.js/commit/5b5228675f67c8f5e04c7183c3ef5e71cb2bf08b),
|
||||
[#11084](https://github.com/angular/angular.js/issues/11084))
|
||||
- avoid .data when fetching required controllers
|
||||
([fa0aa839](https://github.com/angular/angular.js/commit/fa0aa83937378cf8fc720c38bcc5c78fc923624e))
|
||||
- **ngOptions:** only watch labels if a display expression is specified
|
||||
([51faaffd](https://github.com/angular/angular.js/commit/51faaffdbcc734c55d52ff6c42b386d5c90207ea))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **ngMessages:** due to [c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
|
||||
|
||||
|
||||
The `ngMessagesInclude` attribute is now its own directive and that must
|
||||
be placed as a **child** element within the element with the ngMessages
|
||||
directive. (Keep in mind that the former behaviour of the
|
||||
ngMessageInclude attribute was that all **included** ngMessage template
|
||||
code was placed at the **bottom** of the element containing the
|
||||
ngMessages directive; therefore to make this behave in the same way,
|
||||
place the element containing the ngMessagesInclude directive at the
|
||||
end of the container containing the ngMessages directive).
|
||||
|
||||
```html
|
||||
<!-- AngularJS 1.3.x -->
|
||||
<div ng-messages="model.$error" ng-messages-include="remote.html">
|
||||
<div ng-message="required">Your message is required</div>
|
||||
</div>
|
||||
|
||||
<!-- AngularJS 1.4.x -->
|
||||
<div ng-messages="model.$error">
|
||||
<div ng-message="required">Your message is required</div>
|
||||
<div ng-messages-include="remote.html"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
<a name="1.3.14"></a>
|
||||
# 1.3.14 instantaneous-browserification (2015-02-24)
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **CommonJS:** - angular modules are now packaged for npm with helpful exports
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **input:** create max and/or min validator regardless of initial value
|
||||
([abfce532](https://github.com/angular/angular.js/commit/abfce5327ce6fd29c33c62d2edf3600674a6b4c0),
|
||||
[#10307](https://github.com/angular/angular.js/issues/10307), [#10327](https://github.com/angular/angular.js/issues/10327))
|
||||
- **ngAria:** correctly set "checked" attr for checkboxes and radios
|
||||
([944c150e](https://github.com/angular/angular.js/commit/944c150e6c3001e51d4bf5e2d8149ae4c565d1e3),
|
||||
[#10389](https://github.com/angular/angular.js/issues/10389), [#10212](https://github.com/angular/angular.js/issues/10212))
|
||||
- **ngModel:** fix issues when parserName is same as validator key
|
||||
([6b7625a0](https://github.com/angular/angular.js/commit/6b7625a09508c4b5355121a9d4206a734b07b2e1),
|
||||
[#10698](https://github.com/angular/angular.js/issues/10698), [#10850](https://github.com/angular/angular.js/issues/10850), [#11046](https://github.com/angular/angular.js/issues/11046))
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-beta.4"></a>
|
||||
# 1.4.0-beta.4 overlyexplosive-poprocks (2015-02-09)
|
||||
|
||||
@@ -4360,7 +5080,7 @@ For more info: http://blog.angularjs.org/2013/12/angularjs-13-new-release-approa
|
||||
- properly toggle multiple classes
|
||||
([4e73c80b](https://github.com/angular/angular.js/commit/4e73c80b17bd237a8491782bcf9e19f1889e12ed),
|
||||
[#4467](https://github.com/angular/angular.js/issues/4467), [#6448](https://github.com/angular/angular.js/issues/6448))
|
||||
- make jqLite('<iframe src="someurl">').contents() return iframe document, as in jQuery
|
||||
- make `jqLite(<iframe src="someurl">').contents()` return iframe document, as in jQuery
|
||||
([05fbed57](https://github.com/angular/angular.js/commit/05fbed5710b702c111c1425a9e241c40d13b0a54),
|
||||
[#6320](https://github.com/angular/angular.js/issues/6320), [#6323](https://github.com/angular/angular.js/issues/6323))
|
||||
- **numberFilter:** convert all non-finite/non-numbers/non-numeric strings to the empty string
|
||||
@@ -8736,7 +9456,7 @@ with the `$route` service
|
||||
mocks now part of `angular-mocks.js` (commit f5d08963)
|
||||
|
||||
### Bug Fixes
|
||||
- <select> (one/multiple) could not chose from a list of objects (commit 347be5ae)
|
||||
- `<select>` (one/multiple) could not chose from a list of objects (commit 347be5ae)
|
||||
- null and other falsy values should not be rendered in the view (issue #242)
|
||||
|
||||
### Docs
|
||||
|
||||
+10
-4
@@ -1,4 +1,4 @@
|
||||
#Contributing to AngularJS
|
||||
# Contributing to AngularJS
|
||||
|
||||
We'd love for you to contribute to our source code and to make AngularJS even better than it is
|
||||
today! Here are the guidelines we'd like you to follow:
|
||||
@@ -54,7 +54,7 @@ For large fixes, please build and test the documentation before submitting the P
|
||||
accidentally introduced any layout or formatting issues. You should also make sure that your commit message
|
||||
is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
|
||||
|
||||
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times.
|
||||
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times.
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
@@ -199,9 +199,14 @@ format that includes a **type**, a **scope** and a **subject**:
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
to read on github as well as in various git tools.
|
||||
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
@@ -227,14 +232,15 @@ The subject contains succinct description of the change:
|
||||
* don't capitalize first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
###Body
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
###Footer
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
|
||||
+15
-4
@@ -155,7 +155,7 @@ module.exports = function(grunt) {
|
||||
jscs: {
|
||||
src: ['src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
config: ".jscs.json"
|
||||
config: ".jscsrc"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -247,8 +247,19 @@ module.exports = function(grunt) {
|
||||
'test/**/*.js',
|
||||
'!test/ngScenario/DescribeSpec.js',
|
||||
'!src/ng/directive/attrs.js', // legitimate xit here
|
||||
'!src/ngScenario/**/*.js'
|
||||
]
|
||||
'!src/ngScenario/**/*.js',
|
||||
'!test/helpers/privateMocks*.js'
|
||||
],
|
||||
options: {
|
||||
disallowed: [
|
||||
'iit',
|
||||
'xit',
|
||||
'tthey',
|
||||
'xthey',
|
||||
'ddescribe',
|
||||
'xdescribe'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"merge-conflict": {
|
||||
@@ -282,7 +293,7 @@ module.exports = function(grunt) {
|
||||
|
||||
shell: {
|
||||
"npm-install": {
|
||||
command: path.normalize('scripts/npm/install-dependencies.sh')
|
||||
command: 'node scripts/npm/check-node-modules.js'
|
||||
},
|
||||
|
||||
"promises-aplus-tests": {
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
Using AngularJS with the Closure Compiler
|
||||
=========================================
|
||||
|
||||
The Closure Compiler project contains externs definitions for AngularJS
|
||||
JavaScript in its `contrib/externs` directory.
|
||||
The Closure Compiler project contains definitions for the AngularJS JavaScript
|
||||
in its `contrib/externs` directory.
|
||||
|
||||
The definitions contain externs for use with the Closure compiler (aka
|
||||
JSCompiler). Passing these files to the --externs parameter of a compiler
|
||||
|
||||
@@ -10,7 +10,7 @@ the browser how to do dependency injection and inversion of control.
|
||||
|
||||
Oh yeah and it helps with server-side communication, taming async callbacks with promises and
|
||||
deferreds. It also makes client-side navigation and deeplinking with hashbang urls or HTML5 pushState a
|
||||
piece of cake. The best of all: it makes development fun!
|
||||
piece of cake. Best of all?? It makes development fun!
|
||||
|
||||
* Web site: http://angularjs.org
|
||||
* Tutorial: http://docs.angularjs.org/tutorial
|
||||
|
||||
+5
-1
@@ -55,7 +55,11 @@ This process based on the idea of minimizing user pain
|
||||
* inconvenience - causes ugly/boilerplate code in apps
|
||||
1. Label `component: *`
|
||||
* In rare cases, it's ok to have multiple components.
|
||||
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex.
|
||||
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. In addition to applying this label, you must:
|
||||
* Leave a comment explaining the problem and solution so someone can easily finish it.
|
||||
* Assign the issue to yourself.
|
||||
* Give feedback on PRs addressing this issue.
|
||||
* You are responsible for mentoring contributors helping with this issue.
|
||||
1. Label `origin: google` for issues from Google
|
||||
1. Assign a milestone:
|
||||
* Backlog - triaged fixes and features, should be the default choice
|
||||
|
||||
@@ -583,6 +583,12 @@ ul.events > li {
|
||||
margin-bottom:40px;
|
||||
}
|
||||
|
||||
.definition-table td {
|
||||
padding: 8px;
|
||||
border: 1px solid #eee;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 769px) and (max-width: 991px) {
|
||||
.main-body-grid {
|
||||
margin-top: 160px;
|
||||
|
||||
+11
-6
@@ -6,18 +6,18 @@ var packagePath = __dirname;
|
||||
var Package = require('dgeni').Package;
|
||||
|
||||
// Create and export a new Dgeni package called angularjs. This package depends upon
|
||||
// the ngdoc,nunjucks and examples packages defined in the dgeni-packages npm module.
|
||||
// the ngdoc, nunjucks, and examples packages defined in the dgeni-packages npm module.
|
||||
module.exports = new Package('angularjs', [
|
||||
require('dgeni-packages/ngdoc'),
|
||||
require('dgeni-packages/nunjucks'),
|
||||
require('dgeni-packages/examples')
|
||||
require('dgeni-packages/examples'),
|
||||
require('dgeni-packages/git')
|
||||
])
|
||||
|
||||
|
||||
.factory(require('./services/errorNamespaceMap'))
|
||||
.factory(require('./services/getMinerrInfo'))
|
||||
.factory(require('./services/getVersion'))
|
||||
.factory(require('./services/gitData'))
|
||||
|
||||
.factory(require('./services/deployments/debug'))
|
||||
.factory(require('./services/deployments/default'))
|
||||
@@ -26,7 +26,6 @@ module.exports = new Package('angularjs', [
|
||||
|
||||
.factory(require('./inline-tag-defs/type'))
|
||||
|
||||
|
||||
.processor(require('./processors/error-docs'))
|
||||
.processor(require('./processors/index-page'))
|
||||
.processor(require('./processors/keywords'))
|
||||
@@ -125,10 +124,16 @@ module.exports = new Package('angularjs', [
|
||||
});
|
||||
|
||||
computeIdsProcessor.idTemplates.push({
|
||||
docTypes: ['error', 'errorNamespace'],
|
||||
docTypes: ['error'],
|
||||
getId: function(doc) { return 'error:' + doc.namespace + ':' + doc.name; },
|
||||
getAliases: function(doc) { return [doc.name, doc.namespace + ':' + doc.name, doc.id]; }
|
||||
},
|
||||
{
|
||||
docTypes: ['errorNamespace'],
|
||||
getId: function(doc) { return 'error:' + doc.name; },
|
||||
getAliases: function(doc) { return [doc.id]; }
|
||||
});
|
||||
}
|
||||
);
|
||||
})
|
||||
|
||||
.config(function(checkAnchorLinksProcessor) {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var versionInfo = require('../../../lib/versions/version-info');
|
||||
|
||||
/**
|
||||
* @dgService gitData
|
||||
* @description
|
||||
* Information from the local git repository
|
||||
*/
|
||||
module.exports = function gitData() {
|
||||
return {
|
||||
version: versionInfo.currentVersion,
|
||||
versions: versionInfo.previousVersions,
|
||||
info: versionInfo.gitRepoInfo
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
{% extends "base.template.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Error: {$ doc.id $}
|
||||
<h1>Error: {$ doc.namespace $}:{$ doc.name $}
|
||||
<div><span class='hint'>{$ doc.fullName $}</span></div>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@ngdoc error
|
||||
@name $animate:nocb
|
||||
@fullName Do not pass a callback to animate methods
|
||||
@description
|
||||
|
||||
Since Angular 1.3, the methods of {@link ng.$animate} do not accept a callback as the last parameter.
|
||||
Instead, they return a promise to which you can attach `then` handlers to be run when the animation completes.
|
||||
|
||||
If you are getting this error then you need to update your code to use the promise-based API.
|
||||
|
||||
See https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9 for information about
|
||||
the change to the animation API and the changes you need to make.
|
||||
@@ -11,7 +11,7 @@ Supported formats:
|
||||
1. `__name__`
|
||||
2. `__name__ as __identifier__`
|
||||
|
||||
N'either `__name__` or `__identifier__` may contain spaces.
|
||||
Neither `__name__` or `__identifier__` may contain spaces.
|
||||
|
||||
Example of incorrect usage that leads to this error:
|
||||
```html
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
@ngdoc error
|
||||
@name ngModel:numfmt
|
||||
@fullName Model is not of type `number`
|
||||
@description
|
||||
|
||||
The number input directive `<input type="number">` requires the model to be a `number`.
|
||||
|
||||
If the model is something else, this error will be thrown.
|
||||
|
||||
Angular does not set validation errors on the `<input>` in this case
|
||||
as this error is caused by incorrect application logic and not by bad input from the user.
|
||||
|
||||
If your model does not contain actual numbers then it is up to the application developer
|
||||
to use a directive that will do the conversion in the `ngModel` `$formatters` and `$parsers`
|
||||
pipeline.
|
||||
|
||||
## Example
|
||||
|
||||
In this example, our model stores the number as a string, so we provide the `stringToNumber`
|
||||
directive to convert it into the format the `input[number]` directive expects.
|
||||
|
||||
|
||||
<example module="numfmt-error-module">
|
||||
<file name="index.html">
|
||||
<table>
|
||||
<tr ng-repeat="x in ['0', '1']">
|
||||
<td>
|
||||
<input type="number" string-to-number ng-model="x" /> {{ x }} : {{ typeOf(x) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</file>
|
||||
<file name="app.js">
|
||||
angular.module('numfmt-error-module', [])
|
||||
|
||||
.run(function($rootScope) {
|
||||
$rootScope.typeOf = function(value) {
|
||||
return typeof value;
|
||||
};
|
||||
})
|
||||
|
||||
.directive('stringToNumber', function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, element, attrs, ngModel) {
|
||||
ngModel.$parsers.push(function(value) {
|
||||
return '' + value;
|
||||
});
|
||||
ngModel.$formatters.push(function(value) {
|
||||
return parseFloat(value, 10);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
@@ -1,33 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngOptions:trkslct
|
||||
@fullName Comprehension expression cannot contain both `select as` and `track by` expressions.
|
||||
@description
|
||||
|
||||
NOTE: This error was introduced in 1.3.0-rc.5, and was removed for 1.3.0-rc.6 in order to
|
||||
not break existing apps.
|
||||
|
||||
This error occurs when 'ngOptions' is passed a comprehension expression that contains both a
|
||||
`select as` expression and a `track by` expression. These two expressions are fundamentally
|
||||
incompatible.
|
||||
|
||||
* Example of bad expression: `<select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">`
|
||||
`values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}]`,
|
||||
`$scope.selected = {name: 'aSubItem'};`
|
||||
* track by is always applied to `value`, with purpose to preserve the selection,
|
||||
(to `item` in this case)
|
||||
* To calculate whether an item is selected, `ngOptions` does the following:
|
||||
1. apply `track by` to the values in the array:
|
||||
In the example: [1,2]
|
||||
2. apply `track by` to the already selected value in `ngModel`:
|
||||
In the example: this is not possible, as `track by` refers to `item.id`, but the selected
|
||||
value from `ngModel` is `{name: aSubItem}`.
|
||||
|
||||
Here's an example of how to make this example work by using `track by` without `select as`:
|
||||
|
||||
```
|
||||
<select ng-model="selected" ng-options="item.label for item in values track by item.id">
|
||||
```
|
||||
|
||||
Note: This would store the whole `item` as the model to `scope.selected` instead of `item.subItem`.
|
||||
|
||||
For more information on valid expression syntax, see 'ngOptions' in {@link ng.directive:select select} directive docs.
|
||||
@@ -213,11 +213,13 @@ The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redun
|
||||
If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` if it isn't there
|
||||
already.
|
||||
|
||||
For `ng-click`, keypress will also be bound to `div` and `li` elements. You can turn this
|
||||
functionality on or off with the `bindKeypress` configuration option.
|
||||
To fix widespread accessibility problems with `ng-click` on div elements, ngAria will dynamically
|
||||
bind keypress by default as long as the element isn't an anchor, button, input or textarea.
|
||||
You can turn this functionality on or off with the `bindKeypress` configuration option. ngAria
|
||||
will also add the `button` role to communicate to users of assistive technologies.
|
||||
|
||||
For `ng-dblclick`, you must manually add `ng-keypress` to non-interactive elements such as `div`
|
||||
or `taco-button` to enable keyboard access.
|
||||
For `ng-dblclick`, you must still manually add `ng-keypress` and role to non-interactive elements such
|
||||
as `div` or `taco-button` to enable keyboard access.
|
||||
|
||||
<h3>Example</h3>
|
||||
```html
|
||||
@@ -233,7 +235,7 @@ Becomes:
|
||||
|
||||
The new ngMessages module makes it easy to display form validation or other messages with priority
|
||||
sequencing and animation. To expose these visual messages to screen readers,
|
||||
ngAria injects `aria-live="polite"`, causing them to be read aloud any time a message is shown,
|
||||
ngAria injects `aria-live="assertive"`, causing them to be read aloud any time a message is shown,
|
||||
regardless of the user's focus location.
|
||||
###Example
|
||||
|
||||
@@ -247,7 +249,7 @@ regardless of the user's focus location.
|
||||
Becomes:
|
||||
|
||||
```html
|
||||
<div ng-messages="myForm.myName.$error" aria-live="polite">
|
||||
<div ng-messages="myForm.myName.$error" aria-live="assertive">
|
||||
<div ng-message="required">You did not enter a field</div>
|
||||
<div ng-message="maxlength">Your field is too long</div>
|
||||
</div>
|
||||
|
||||
@@ -236,7 +236,7 @@ The example below shows how to perform animations during class changes:
|
||||
</file>
|
||||
</example>
|
||||
|
||||
Although the CSS is a little different then what we saw before, the idea is the same.
|
||||
Although the CSS is a little different than what we saw before, the idea is the same.
|
||||
|
||||
## Which directives support animations?
|
||||
|
||||
|
||||
@@ -179,11 +179,11 @@ The following graphic shows how everything works together after we introduced th
|
||||
|
||||
<img style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding2.png">
|
||||
|
||||
## View independent business logic: Services
|
||||
## View-independent business logic: Services
|
||||
|
||||
Right now, the `InvoiceController` contains all logic of our example. When the application grows it
|
||||
is a good practice to move view independent logic from the controller into a so called
|
||||
<a name="service">"{@link services service}"</a>, so it can be reused by other parts
|
||||
is a good practice to move view-independent logic from the controller into a
|
||||
<a name="service">{@link services service}</a>, so it can be reused by other parts
|
||||
of the application as well. Later on, we could also change that service to load the exchange rates
|
||||
from the web, e.g. by calling the Yahoo Finance API, without changing the controller.
|
||||
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
|
||||
# Understanding Controllers
|
||||
|
||||
In Angular, a Controller is a JavaScript **constructor function** that is used to augment the
|
||||
In Angular, a Controller is defined by a JavaScript **constructor function** that is used to augment the
|
||||
{@link scope Angular Scope}.
|
||||
|
||||
When a Controller is attached to the DOM via the {@link ng.directive:ngController ng-controller}
|
||||
directive, Angular will instantiate a new Controller object, using the specified Controller's
|
||||
**constructor function**. A new **child scope** will be available as an injectable parameter to the
|
||||
Controller's constructor function as `$scope`.
|
||||
**constructor function**. A new **child scope** will be created and made available as an injectable
|
||||
parameter to the Controller's constructor function as `$scope`.
|
||||
|
||||
If the controller has been attached using the `controller as` syntax then the controller instance will
|
||||
be assigned to a property on the new scope.
|
||||
|
||||
Use controllers to:
|
||||
|
||||
@@ -106,7 +109,7 @@ needed for a single view.
|
||||
|
||||
The most common way to keep Controllers slim is by encapsulating work that doesn't belong to
|
||||
controllers into services and then using these services in Controllers via dependency injection.
|
||||
This is discussed in the {@link di Dependency Injection} {@link services
|
||||
This is discussed in the {@link di Dependency Injection} and {@link services
|
||||
Services} sections of this guide.
|
||||
|
||||
|
||||
@@ -162,7 +165,7 @@ scope is augmented (managed) by the `SpicyController` Controller.
|
||||
starts with capital letter and ends with "Controller".
|
||||
- Assigning a property to `$scope` creates or updates the model.
|
||||
- Controller methods can be created through direct assignment to scope (see the `chiliSpicy` method)
|
||||
- The Controller methods and properties are available in the template (for the `<div>` element and
|
||||
- The Controller methods and properties are available in the template (for both the `<div>` element and
|
||||
its children).
|
||||
|
||||
## Spicy Arguments Example
|
||||
@@ -302,7 +305,7 @@ describe('myController function', function() {
|
||||
```
|
||||
|
||||
|
||||
If you need to test a nested Controller you need to create the same scope hierarchy
|
||||
If you need to test a nested Controller you must create the same scope hierarchy
|
||||
in your test that exists in the DOM:
|
||||
|
||||
```js
|
||||
|
||||
@@ -163,8 +163,8 @@ someModule.controller('MyController', function($scope, greeter) {
|
||||
});
|
||||
```
|
||||
|
||||
Given a function the injector can infer the names of the services to inject by examining the
|
||||
function declaration and extracting the parameter names. In the above example `$scope`, and
|
||||
Given a function, the injector can infer the names of the services to inject by examining the
|
||||
function declaration and extracting the parameter names. In the above example, `$scope` and
|
||||
`greeter` are two services which need to be injected into the function.
|
||||
|
||||
One advantage of this approach is that there's no array of names to keep in sync with the
|
||||
@@ -293,7 +293,7 @@ Create a new injector that can provide components defined in our `myModule` modu
|
||||
`greeter` service from the injector. (This is usually done automatically by angular bootstrap).
|
||||
|
||||
```js
|
||||
var injector = angular.injector(['myModule', 'ng']);
|
||||
var injector = angular.injector(['ng', 'myModule']);
|
||||
var greeter = injector.get('greeter');
|
||||
```
|
||||
|
||||
|
||||
@@ -51,9 +51,11 @@ In the following example, we say that the `<input>` element **matches** the `ngM
|
||||
The following also **matches** `ngModel`:
|
||||
|
||||
```html
|
||||
<input data-ng:model="foo">
|
||||
<input data-ng-model="foo">
|
||||
```
|
||||
|
||||
### Normalization
|
||||
|
||||
Angular **normalizes** an element's tag and attribute name to determine which elements match which
|
||||
directives. We typically refer to directives by their case-sensitive
|
||||
[camelCase](http://en.wikipedia.org/wiki/CamelCase) **normalized** name (e.g. `ngModel`).
|
||||
@@ -100,6 +102,8 @@ If you want to use an HTML validating tool, you can instead use the `data`-prefi
|
||||
The other forms shown above are accepted for legacy reasons but we advise you to avoid them.
|
||||
</div>
|
||||
|
||||
### Directive types
|
||||
|
||||
`$compile` can match directives based on element names, attributes, class names, as well as comments.
|
||||
|
||||
All of the Angular-provided directives match attribute name, tag name, comments, or class name.
|
||||
@@ -827,37 +831,39 @@ element?
|
||||
<file name="script.js">
|
||||
angular.module('dragModule', [])
|
||||
.directive('myDraggable', ['$document', function($document) {
|
||||
return function(scope, element, attr) {
|
||||
var startX = 0, startY = 0, x = 0, y = 0;
|
||||
return {
|
||||
link: function(scope, element, attr) {
|
||||
var startX = 0, startY = 0, x = 0, y = 0;
|
||||
|
||||
element.css({
|
||||
position: 'relative',
|
||||
border: '1px solid red',
|
||||
backgroundColor: 'lightgrey',
|
||||
cursor: 'pointer'
|
||||
});
|
||||
|
||||
element.on('mousedown', function(event) {
|
||||
// Prevent default dragging of selected content
|
||||
event.preventDefault();
|
||||
startX = event.pageX - x;
|
||||
startY = event.pageY - y;
|
||||
$document.on('mousemove', mousemove);
|
||||
$document.on('mouseup', mouseup);
|
||||
});
|
||||
|
||||
function mousemove(event) {
|
||||
y = event.pageY - startY;
|
||||
x = event.pageX - startX;
|
||||
element.css({
|
||||
top: y + 'px',
|
||||
left: x + 'px'
|
||||
position: 'relative',
|
||||
border: '1px solid red',
|
||||
backgroundColor: 'lightgrey',
|
||||
cursor: 'pointer'
|
||||
});
|
||||
}
|
||||
|
||||
function mouseup() {
|
||||
$document.off('mousemove', mousemove);
|
||||
$document.off('mouseup', mouseup);
|
||||
element.on('mousedown', function(event) {
|
||||
// Prevent default dragging of selected content
|
||||
event.preventDefault();
|
||||
startX = event.pageX - x;
|
||||
startY = event.pageY - y;
|
||||
$document.on('mousemove', mousemove);
|
||||
$document.on('mouseup', mouseup);
|
||||
});
|
||||
|
||||
function mousemove(event) {
|
||||
y = event.pageY - startY;
|
||||
x = event.pageX - startX;
|
||||
element.css({
|
||||
top: y + 'px',
|
||||
left: x + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
function mouseup() {
|
||||
$document.off('mousemove', mousemove);
|
||||
$document.off('mouseup', mouseup);
|
||||
}
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
@@ -28,13 +28,13 @@ Angular expressions are like JavaScript expressions with the following differenc
|
||||
|
||||
* **No Control Flow Statements:** You cannot use the following in an Angular expression:
|
||||
conditionals, loops, or exceptions.
|
||||
|
||||
|
||||
* **No Function Declarations:** You cannot declare functions in an Angular expression,
|
||||
even inside `ng-init` directive.
|
||||
|
||||
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
|
||||
|
||||
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
|
||||
in an Angular expression.
|
||||
|
||||
|
||||
* **No Comma And Void Operators:** You cannot use `,` or `void` in an Angular expression.
|
||||
|
||||
* **Filters:** You can use {@link guide/filter filters} within expressions to format data before
|
||||
@@ -70,7 +70,7 @@ You can try evaluating different expressions here:
|
||||
<ul>
|
||||
<li ng-repeat="expr in exprs track by $index">
|
||||
[ <a href="" ng-click="removeExp($index)">X</a> ]
|
||||
<tt>{{expr}}</tt> => <span ng-bind="$parent.$eval(expr)"></span>
|
||||
<code>{{expr}}</code> => <span ng-bind="$parent.$eval(expr)"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -175,7 +175,7 @@ expression, delegate to a JavaScript method instead.
|
||||
## No function declarations or RegExp creation with literal notation
|
||||
|
||||
You can't declare functions or create regular expressions from within AngularJS expressions. This is
|
||||
to avoid complex model transformation logic inside templates. Such logic is better placed in a
|
||||
to avoid complex model transformation logic inside templates. Such logic is better placed in a
|
||||
controller or in a dedicated filter where it can be tested properly.
|
||||
|
||||
## `$event`
|
||||
@@ -303,10 +303,14 @@ then the expression is not fulfilled and will remain watched.
|
||||
keep dirty-checking the watch in the future digest loops by following the same
|
||||
algorithm starting from step 1
|
||||
|
||||
#### Special case for object literals
|
||||
|
||||
Unlike simple values, object-literals are watched until every key is defined.
|
||||
See http://www.bennadel.com/blog/2760-one-time-data-bindings-for-object-literal-expressions-in-angularjs-1-3.htm
|
||||
|
||||
### How to benefit from one-time binding
|
||||
|
||||
If the expression will not change once set, it is a candidate for one-time binding.
|
||||
If the expression will not change once set, it is a candidate for one-time binding.
|
||||
Here are three example cases.
|
||||
|
||||
When interpolating text or attributes:
|
||||
@@ -340,5 +344,4 @@ When using a directive that takes an expression:
|
||||
<ul>
|
||||
<li ng-repeat="item in ::items">{{item.name}};</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
```
|
||||
@@ -92,8 +92,10 @@ means that it should be stateless and idempotent. Angular relies on these proper
|
||||
the filter only when the inputs to the function change.
|
||||
|
||||
<div class="alert alert-warning">
|
||||
**Note:** filter names must be valid angular expression identifiers, such as `uppercase` or `orderBy`.
|
||||
Names with special characters, such as hyphens and dots, are not allowed.
|
||||
**Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
|
||||
your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
|
||||
(`myapp_subsection_filterx`).
|
||||
</div>
|
||||
|
||||
The following sample filter reverses a text string. In addition, it conditionally makes the
|
||||
|
||||
@@ -93,6 +93,8 @@ and failing to satisfy its validity.
|
||||
<input type="button" ng-click="reset()" value="Reset" />
|
||||
<input type="submit" ng-click="update(user)" value="Save" />
|
||||
</form>
|
||||
<pre>form = {{user | json}}</pre>
|
||||
<pre>master = {{master | json}}</pre>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
@@ -181,6 +183,8 @@ didn't interact with a control
|
||||
<input type="button" ng-click="reset(form)" value="Reset" />
|
||||
<input type="submit" ng-click="update(user)" value="Save" />
|
||||
</form>
|
||||
<pre>form = {{user | json}}</pre>
|
||||
<pre>master = {{master | json}}</pre>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ In Angular applications, you move the job of filling page templates with data fr
|
||||
|
||||
## Specific Topics
|
||||
|
||||
* **Login: **[Google example](https://developers.google.com/+/photohunt/python), [AngularJS Faceb0ok library](https://github.com/pc035860/angular-easyfb), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
|
||||
* **Login: **[Google example](https://developers.google.com/+/photohunt/python), [AngularJS Facebook library](https://github.com/pc035860/angular-easyfb), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
|
||||
* **Mobile:** [Angular on Mobile Guide](http://www.ng-newsletter.com/posts/angular-on-mobile.html), [PhoneGap](http://devgirl.org/2013/06/10/quick-start-guide-phonegap-and-angularjs/)
|
||||
* **Other Languages:** [CoffeeScript](http://www.coffeescriptlove.com/2013/08/angularjs-and-coffeescript-tutorials.html), [Dart](https://github.com/angular/angular.dart.tutorial/wiki)
|
||||
* **Realtime: **[Socket.io](http://www.creativebloq.com/javascript/angularjs-collaboration-board-socketio-2132885), [OmniBinder](https://github.com/jeffbcross/omnibinder)
|
||||
|
||||
@@ -76,7 +76,7 @@ that you break your application to multiple modules like this:
|
||||
initialization code.
|
||||
|
||||
We've also
|
||||
[written a document](http://blog.angularjs.org/2014/02/an-angularjs-style-guide-and-best.html)
|
||||
[written a document](http://angularjs.blogspot.com/2014/02/an-angularjs-style-guide-and-best.html)
|
||||
on how we organize large apps at Google.
|
||||
|
||||
The above is a suggestion. Tailor it to your needs.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# What are Scopes?
|
||||
|
||||
{@link ng.$rootScope.Scope scope} is an object that refers to the application
|
||||
{@link ng.$rootScope.Scope Scope} is an object that refers to the application
|
||||
model. It is an execution context for {@link expression expressions}. Scopes are
|
||||
arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can
|
||||
watch {@link guide/expression expressions} and propagate events.
|
||||
@@ -245,7 +245,7 @@ of the `$watch` expressions and compares them with the previous value. This dirt
|
||||
asynchronously. This means that assignment such as `$scope.username="angular"` will not
|
||||
immediately cause a `$watch` to be notified, instead the `$watch` notification is delayed until
|
||||
the `$digest` phase. This delay is desirable, since it coalesces multiple model updates into one
|
||||
`$watch` notification as well as it guarantees that during the `$watch` notification no other
|
||||
`$watch` notification as well as guarantees that during the `$watch` notification no other
|
||||
`$watch`es are running. If a `$watch` changes the value of the model, it will force additional
|
||||
`$digest` cycle.
|
||||
|
||||
@@ -264,7 +264,7 @@ the `$digest` phase. This delay is desirable, since it coalesces multiple model
|
||||
3. **Model mutation**
|
||||
|
||||
For mutations to be properly observed, you should make them only within the {@link
|
||||
ng.$rootScope.Scope#$apply scope.$apply()}. (Angular APIs do this
|
||||
ng.$rootScope.Scope#$apply scope.$apply()}. Angular APIs do this
|
||||
implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers,
|
||||
or asynchronous work with {@link ng.$http $http}, {@link ng.$timeout $timeout}
|
||||
or {@link ng.$interval $interval} services.
|
||||
|
||||
@@ -62,7 +62,7 @@ are available on [the Karma website](http://karma-runner.github.io/0.12/intro/in
|
||||
|
||||
### Jasmine
|
||||
|
||||
[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a test driven development framework for
|
||||
[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a behavior driven development framework for
|
||||
JavaScript that has become the most popular choice for testing Angular applications. Jasmine
|
||||
provides functions to help with structuring your tests and also making assertions. As your tests
|
||||
grow, keeping them well structured and documented is vital, and Jasmine helps achieve this.
|
||||
@@ -260,6 +260,11 @@ myModule.filter('length', function() {
|
||||
});
|
||||
|
||||
describe('length filter', function() {
|
||||
|
||||
beforeEach(inject(function(_$filter_){
|
||||
$filter= _$filter_;
|
||||
}));
|
||||
|
||||
it('returns 0 when given null', function() {
|
||||
var length = $filter('length');
|
||||
expect(length(null)).toEqual(0);
|
||||
|
||||
@@ -153,7 +153,7 @@ grunt test:unit --browsers Opera,Firefox
|
||||
|
||||
Note there should be _no spaces between browsers_. `Opera, Firefox` is INVALID.
|
||||
|
||||
During development it's however more productive to continuously run unit tests every time the source or test files
|
||||
During development, however, it's more productive to continuously run unit tests every time the source or test files
|
||||
change. To execute tests in this mode run:
|
||||
|
||||
1. To start the Karma server, capture Chrome browser and run unit tests, run:
|
||||
|
||||
@@ -15,14 +15,14 @@ development.
|
||||
production.
|
||||
|
||||
To point your code to an angular script on the Google CDN server, use the following template. This
|
||||
example points to the minified version 1.2.0:
|
||||
example points to the minified version 1.3.14:
|
||||
|
||||
```
|
||||
<!doctype html>
|
||||
<html ng-app>
|
||||
<head>
|
||||
<title>My Angular App</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
|
||||
@@ -65,7 +65,7 @@ __`app/index.html`:__
|
||||
|
||||
## What is the code doing?
|
||||
|
||||
* `ng-app` directive:
|
||||
**`ng-app` directive:**
|
||||
|
||||
<html ng-app>
|
||||
|
||||
@@ -77,17 +77,17 @@ __`app/index.html`:__
|
||||
This gives application developers the freedom to tell Angular if the entire html page or only a
|
||||
portion of it should be treated as the Angular application.
|
||||
|
||||
* AngularJS script tag:
|
||||
**AngularJS script tag:**
|
||||
|
||||
<script src="bower_components/angular/angular.js">
|
||||
|
||||
This code downloads the `angular.js` script and registers a callback that will be executed by the
|
||||
This code downloads the `angular.js` script which registers a callback that will be executed by the
|
||||
browser when the containing HTML page is fully downloaded. When the callback is executed, Angular
|
||||
looks for the {@link ng.directive:ngApp ngApp} directive. If
|
||||
Angular finds the directive, it will bootstrap the application with the root of the application DOM
|
||||
being the element on which the `ngApp` directive was defined.
|
||||
|
||||
* Double-curly binding with an expression:
|
||||
**Double-curly binding with an expression:**
|
||||
|
||||
Nothing here {{'yet' + '!'}}
|
||||
|
||||
@@ -111,7 +111,7 @@ being the element on which the `ngApp` directive was defined.
|
||||
## Bootstrapping AngularJS apps
|
||||
|
||||
Bootstrapping AngularJS apps automatically using the `ngApp` directive is very easy and suitable
|
||||
for most cases. In advanced cases, such as when using script loaders, you can use
|
||||
for most cases. In advanced cases, such as when using script loaders, you can use the
|
||||
{@link guide/bootstrap imperative / manual way} to bootstrap the app.
|
||||
|
||||
There are 3 important things that happen during the app bootstrap:
|
||||
|
||||
@@ -313,7 +313,7 @@ to various URLs and verify that the correct view was rendered.
|
||||
it('should redirect index.html to index.html#/phones', function() {
|
||||
browser.get('app/index.html');
|
||||
browser.getLocationAbsUrl().then(function(url) {
|
||||
expect(url.split('#')[1]).toBe('/phones');
|
||||
expect(url).toEqual('/phones');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ function request(method, url, options, response) {
|
||||
res.on('error', function (e) { console.log(e); });
|
||||
break;
|
||||
case 401:
|
||||
console.log('Eror: Login credentials expired! Please login.');
|
||||
console.log('Error: Login credentials expired! Please login.');
|
||||
break;
|
||||
default:
|
||||
data = [];
|
||||
|
||||
@@ -185,6 +185,8 @@ describe("extractDateTimeSymbols", function() {
|
||||
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
|
||||
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
ERAS: ['av. J.-C.', 'ap. J.-C.'],
|
||||
ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
|
||||
medium: 'yyyy-MM-dd HH:mm:ss',
|
||||
short: 'yy-MM-dd HH:mm',
|
||||
fullDate: 'EEEE d MMMM y',
|
||||
|
||||
@@ -42,6 +42,8 @@ function convertDatetimeData(dataObj) {
|
||||
datetimeFormats.DAY = dataObj.WEEKDAYS;
|
||||
datetimeFormats.SHORTDAY = dataObj.SHORTWEEKDAYS;
|
||||
datetimeFormats.AMPMS = dataObj.AMPMS;
|
||||
datetimeFormats.ERAS = dataObj.ERAS;
|
||||
datetimeFormats.ERANAMES = dataObj.ERANAMES;
|
||||
|
||||
|
||||
datetimeFormats.medium = dataObj.DATEFORMATS[2] + ' ' + dataObj.TIMEFORMATS[2];
|
||||
|
||||
@@ -66,6 +66,12 @@ module.exports = function(config, specificOptions) {
|
||||
platform: 'Windows 8.1',
|
||||
version: '11'
|
||||
},
|
||||
'SL_iOS': {
|
||||
base: "SauceLabs",
|
||||
browserName: "iphone",
|
||||
platform: "OS X 10.10",
|
||||
version: "8.1"
|
||||
},
|
||||
|
||||
'BS_Chrome': {
|
||||
base: 'BrowserStack',
|
||||
@@ -105,6 +111,12 @@ module.exports = function(config, specificOptions) {
|
||||
browser_version: '11.0',
|
||||
os: 'Windows',
|
||||
os_version: '8.1'
|
||||
},
|
||||
'BS_iOS': {
|
||||
base: 'BrowserStack',
|
||||
device: 'iPhone 6',
|
||||
os: 'ios',
|
||||
os_version: '8.0'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Browserstack tunnel"
|
||||
echo "TODO: implement me"
|
||||
exit 1
|
||||
+1
-1
@@ -116,7 +116,7 @@ module.exports = {
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/'/g, "\\'")
|
||||
.replace(/\r?\n/g, '\\n');
|
||||
js = "!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>');";
|
||||
js = "!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type=\"text/css\">" + css + "</style>');";
|
||||
state.js.push(js);
|
||||
|
||||
return state;
|
||||
|
||||
@@ -12,9 +12,9 @@ set -e
|
||||
# before_script:
|
||||
# - curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash
|
||||
|
||||
CONNECT_URL="https://saucelabs.com/downloads/sc-4.3.6-linux.tar.gz"
|
||||
CONNECT_URL="https://saucelabs.com/downloads/sc-4.3.7-linux.tar.gz"
|
||||
CONNECT_DIR="/tmp/sauce-connect-$RANDOM"
|
||||
CONNECT_DOWNLOAD="sc-4.3.6-linux.tar.gz"
|
||||
CONNECT_DOWNLOAD="sc-4.3.7-linux.tar.gz"
|
||||
|
||||
CONNECT_LOG="$LOGS_DIR/sauce-connect"
|
||||
CONNECT_STDOUT="$LOGS_DIR/sauce-connect.stdout"
|
||||
@@ -46,5 +46,5 @@ echo "Starting Sauce Connect in the background, logging into:"
|
||||
echo " $CONNECT_LOG"
|
||||
echo " $CONNECT_STDOUT"
|
||||
echo " $CONNECT_STDERR"
|
||||
sauce-connect/bin/sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY $ARGS -v \
|
||||
sauce-connect/bin/sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY $ARGS \
|
||||
--logfile $CONNECT_LOG 2> $CONNECT_STDERR 1> $CONNECT_STDOUT &
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Sauce Connect tunnel"
|
||||
|
||||
killall sc
|
||||
|
||||
while [[ -n `ps -ef | grep "sauce-connect-" | grep -v "grep"` ]]; do
|
||||
printf "."
|
||||
sleep .5
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Sauce Connect tunnel has been shut down"
|
||||
+832
-269
File diff suppressed because it is too large
Load Diff
Generated
+2972
-2109
File diff suppressed because it is too large
Load Diff
+7
-2
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"branchVersion": "1.3.*",
|
||||
"distTag": "previous_1_3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.js.git"
|
||||
@@ -10,6 +11,10 @@
|
||||
"npm": "~2.5"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"scripts": {
|
||||
"preinstall": "node scripts/npm/check-node-modules.js --purge",
|
||||
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-benchpress": "0.x.x",
|
||||
"benchmark": "1.x.x",
|
||||
@@ -43,7 +48,7 @@
|
||||
"jasmine-node": "~1.14.5",
|
||||
"jasmine-reporters": "~1.0.1",
|
||||
"jshint-stylish": "~1.0.0",
|
||||
"karma": "~0.12.0",
|
||||
"karma": "0.12.32",
|
||||
"karma-browserstack-launcher": "0.1.2",
|
||||
"karma-chrome-launcher": "0.1.5",
|
||||
"karma-firefox-launcher": "0.1.3",
|
||||
@@ -57,7 +62,7 @@
|
||||
"marked": "~0.3.0",
|
||||
"node-html-encoder": "0.0.2",
|
||||
"promises-aplus-tests": "~2.1.0",
|
||||
"protractor": "^1.6.0",
|
||||
"protractor": "^2.0.0",
|
||||
"q": "~1.0.0",
|
||||
"q-io": "^1.10.9",
|
||||
"qq": "^0.3.5",
|
||||
|
||||
@@ -29,6 +29,8 @@ function init {
|
||||
angular-touch
|
||||
angular-messages
|
||||
)
|
||||
# get the npm dist-tag from a custom property (distTag) in package.json
|
||||
DIST_TAG=$(readJsonProp "package.json" "distTag")
|
||||
}
|
||||
|
||||
|
||||
@@ -110,19 +112,8 @@ function publish {
|
||||
|
||||
# don't publish every build to npm
|
||||
if [ "${NEW_VERSION/+sha}" = "$NEW_VERSION" ] ; then
|
||||
if [ "${NEW_VERSION/-}" = "$NEW_VERSION" ] ; then
|
||||
if [[ $NEW_VERSION =~ ^1\.2\.[0-9]+$ ]] ; then
|
||||
# publish 1.2.x releases with the appropriate tag
|
||||
# this ensures that `npm install` by default will not grab `1.2.x` releases
|
||||
npm publish --tag=old
|
||||
else
|
||||
# publish releases as "latest"
|
||||
npm publish
|
||||
fi
|
||||
else
|
||||
# publish prerelease builds with the beta tag
|
||||
npm publish --tag=beta
|
||||
fi
|
||||
echo "-- Publishing to npm as $DIST_TAG"
|
||||
npm publish --tag=$DIST_TAG
|
||||
fi
|
||||
|
||||
cd $SCRIPT_DIR
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Implementation based on:
|
||||
// https://github.com/angular/angular/blob/3b9c08676a4c921bbfa847802e08566fb601ba7a/tools/npm/check-node-modules.js
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
var purgeIfStale = process.argv.indexOf('--purge') !== -1;
|
||||
|
||||
process.chdir(PROJECT_ROOT);
|
||||
checkNodeModules(purgeIfStale);
|
||||
}
|
||||
|
||||
function checkNodeModules(purgeIfStale) {
|
||||
var nodeModulesOk = compareMarkerFiles(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE);
|
||||
|
||||
if (nodeModulesOk) {
|
||||
console.log(':-) npm dependencies are looking good!');
|
||||
} else if (purgeIfStale) {
|
||||
console.log(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.log(' Purging \'' + NODE_MODULES_DIR + '\'...');
|
||||
deleteDirSync(NODE_MODULES_DIR);
|
||||
} else {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.warn(separator);
|
||||
console.warn(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.warn('You can rebuild the dependencies by running `npm install`.');
|
||||
console.warn(separator);
|
||||
}
|
||||
|
||||
return nodeModulesOk;
|
||||
}
|
||||
|
||||
function compareMarkerFiles(markerFilePath, cachedMarkerFilePath) {
|
||||
if (!fs.existsSync(cachedMarkerFilePath)) return false;
|
||||
|
||||
var opts = {encoding: 'utf-8'};
|
||||
var markerContent = fs.readFileSync(markerFilePath, opts);
|
||||
var cachedMarkerContent = fs.readFileSync(cachedMarkerFilePath, opts);
|
||||
|
||||
return markerContent === cachedMarkerContent;
|
||||
}
|
||||
|
||||
// Custom implementation of `rm -rf` that works consistently across OSes
|
||||
function deleteDirSync(path) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.readdirSync(path).forEach(deleteDirOrFileSync);
|
||||
fs.rmdirSync(path);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function deleteDirOrFileSync(subpath) {
|
||||
var curPath = path + '/' + subpath;
|
||||
|
||||
if (fs.lstatSync(curPath).isDirectory()) {
|
||||
deleteDirSync(curPath);
|
||||
} else {
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
process.chdir(PROJECT_ROOT);
|
||||
copyFile(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE, onCopied);
|
||||
}
|
||||
|
||||
// Implementation based on:
|
||||
// https://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js#answer-21995878
|
||||
function copyFile(srcPath, dstPath, callback) {
|
||||
var callbackCalled = false;
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
done(new Error('Missing source file: ' + srcPath));
|
||||
return;
|
||||
}
|
||||
|
||||
var rs = fs.createReadStream(srcPath);
|
||||
rs.on('error', done);
|
||||
|
||||
var ws = fs.createWriteStream(dstPath);
|
||||
ws.on('error', done);
|
||||
ws.on('finish', done);
|
||||
|
||||
rs.pipe(ws);
|
||||
|
||||
// Helpers
|
||||
function done(err) {
|
||||
if (callback && !callbackCalled) {
|
||||
callbackCalled = true;
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onCopied(err) {
|
||||
if (err) {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.error(separator);
|
||||
console.error(
|
||||
'Failed to copy `' + NPM_SHRINKWRAP_FILE + '` to `' + NPM_SHRINKWRAP_CACHED_FILE + '`:');
|
||||
console.error(err);
|
||||
console.error(separator);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SHRINKWRAP_FILE=npm-shrinkwrap.json
|
||||
SHRINKWRAP_CACHED_FILE=node_modules/npm-shrinkwrap.cached.json
|
||||
|
||||
if diff -q $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE; then
|
||||
echo 'No shrinkwrap changes detected. npm install will be skipped...';
|
||||
else
|
||||
echo 'Blowing away node_modules and reinstalling npm dependencies...'
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
cp $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE
|
||||
echo 'npm install successful!'
|
||||
fi
|
||||
@@ -7,9 +7,9 @@ export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
if [ $JOB = "unit" ]; then
|
||||
if [ "$BROWSER_PROVIDER" == "browserstack" ]; then
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11"
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS"
|
||||
else
|
||||
BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11"
|
||||
BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11,SL_iOS"
|
||||
fi
|
||||
|
||||
grunt test:promises-aplus
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Has to be run from project root directory.
|
||||
|
||||
./lib/${BROWSER_PROVIDER}/teardown_tunnel.sh
|
||||
@@ -2,6 +2,18 @@
|
||||
|
||||
|
||||
# Wait for Connect to be ready before exiting
|
||||
# Time out if we wait for more than 2 minutes, so that we can print logs.
|
||||
let "counter=0"
|
||||
|
||||
while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do
|
||||
let "counter++"
|
||||
if [ $counter -gt 240 ]; then
|
||||
echo "Timed out after 2 minutes waiting for browser provider ready file"
|
||||
# We must manually print logs here because travis will not run
|
||||
# after_script commands if the failure occurs before the script
|
||||
# phase.
|
||||
./scripts/travis/print_logs.sh
|
||||
exit 5
|
||||
fi
|
||||
sleep .5
|
||||
done
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
"skipDestroyOnNextJQueryCleanData": true,
|
||||
|
||||
"NODE_TYPE_ELEMENT": false,
|
||||
"NODE_TYPE_ATTRIBUTE": false,
|
||||
"NODE_TYPE_TEXT": false,
|
||||
"NODE_TYPE_COMMENT": false,
|
||||
"NODE_TYPE_COMMENT": false,
|
||||
|
||||
+17
-6
@@ -85,6 +85,7 @@
|
||||
createMap: true,
|
||||
|
||||
NODE_TYPE_ELEMENT: true,
|
||||
NODE_TYPE_ATTRIBUTE: true,
|
||||
NODE_TYPE_TEXT: true,
|
||||
NODE_TYPE_COMMENT: true,
|
||||
NODE_TYPE_DOCUMENT: true,
|
||||
@@ -196,7 +197,9 @@ function isArrayLike(obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var length = obj.length;
|
||||
// Support: iOS 8.2 (not reproducible in simulator)
|
||||
// "length" in obj used to prevent JIT error (gh-11508)
|
||||
var length = "length" in Object(obj) && obj.length;
|
||||
|
||||
if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
|
||||
return true;
|
||||
@@ -482,6 +485,12 @@ function isString(value) {return typeof value === 'string';}
|
||||
* @description
|
||||
* Determines if a reference is a `Number`.
|
||||
*
|
||||
* This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
|
||||
*
|
||||
* If you wish to exclude these then you can use the native
|
||||
* [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
|
||||
* method.
|
||||
*
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is a `Number`.
|
||||
*/
|
||||
@@ -850,10 +859,11 @@ function equals(o1, o2) {
|
||||
} else if (isDate(o1)) {
|
||||
if (!isDate(o2)) return false;
|
||||
return equals(o1.getTime(), o2.getTime());
|
||||
} else if (isRegExp(o1) && isRegExp(o2)) {
|
||||
return o1.toString() == o2.toString();
|
||||
} else if (isRegExp(o1)) {
|
||||
return isRegExp(o2) ? o1.toString() == o2.toString() : false;
|
||||
} else {
|
||||
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
|
||||
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
|
||||
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
|
||||
keySet = {};
|
||||
for (key in o1) {
|
||||
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
|
||||
@@ -971,8 +981,8 @@ function toJsonReplacer(key, value) {
|
||||
* stripped since angular uses this notation internally.
|
||||
*
|
||||
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
|
||||
* @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
|
||||
* If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
|
||||
* @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
|
||||
* If set to an integer, the JSON output will contain that many spaces per indentation.
|
||||
* @returns {string|undefined} JSON-ified string representing `obj`.
|
||||
*/
|
||||
function toJson(obj, pretty) {
|
||||
@@ -1604,6 +1614,7 @@ function createMap() {
|
||||
}
|
||||
|
||||
var NODE_TYPE_ELEMENT = 1;
|
||||
var NODE_TYPE_ATTRIBUTE = 2;
|
||||
var NODE_TYPE_TEXT = 3;
|
||||
var NODE_TYPE_COMMENT = 8;
|
||||
var NODE_TYPE_DOCUMENT = 9;
|
||||
|
||||
@@ -179,7 +179,7 @@ function annotate(fn, strictDi, name) {
|
||||
* Return an instance of the service.
|
||||
*
|
||||
* @param {string} name The name of the instance to retrieve.
|
||||
* @param {string} caller An optional string to provide the origin of the function call for error messages.
|
||||
* @param {string=} caller An optional string to provide the origin of the function call for error messages.
|
||||
* @return {*} The instance.
|
||||
*/
|
||||
|
||||
@@ -190,8 +190,8 @@ function annotate(fn, strictDi, name) {
|
||||
* @description
|
||||
* Invoke the method and supply the method arguments from the `$injector`.
|
||||
*
|
||||
* @param {!Function} fn The function to invoke. Function parameters are injected according to the
|
||||
* {@link guide/di $inject Annotation} rules.
|
||||
* @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
|
||||
* injected according to the {@link guide/di $inject Annotation} rules.
|
||||
* @param {Object=} self The `this` for the invoked method.
|
||||
* @param {Object=} locals Optional object. If preset then any argument names are read from this
|
||||
* object first, before the `$injector` is consulted.
|
||||
@@ -458,8 +458,8 @@ function annotate(fn, strictDi, name) {
|
||||
* configure your service in a provider.
|
||||
*
|
||||
* @param {string} name The name of the instance.
|
||||
* @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
|
||||
* for `$provide.provider(name, {$get: $getFn})`.
|
||||
* @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
|
||||
* Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
|
||||
* @returns {Object} registered provider instance
|
||||
*
|
||||
* @example
|
||||
@@ -494,7 +494,8 @@ function annotate(fn, strictDi, name) {
|
||||
* as a type/class.
|
||||
*
|
||||
* @param {string} name The name of the instance.
|
||||
* @param {Function} constructor A class (constructor function) that will be instantiated.
|
||||
* @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
|
||||
* that will be instantiated.
|
||||
* @returns {Object} registered provider instance
|
||||
*
|
||||
* @example
|
||||
@@ -593,7 +594,7 @@ function annotate(fn, strictDi, name) {
|
||||
* object which replaces or wraps and delegates to the original service.
|
||||
*
|
||||
* @param {string} name The name of the service to decorate.
|
||||
* @param {function()} decorator This function will be invoked when the service needs to be
|
||||
* @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
|
||||
* instantiated and should return the decorated service instance. The function is called using
|
||||
* the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
|
||||
* Local injection arguments:
|
||||
|
||||
+17
-2
@@ -1,5 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Any commits to this file should be reviewed with security in mind. *
|
||||
* Changes to this file can potentially create security vulnerabilities. *
|
||||
* An approval from 2 Core members with history of modifying *
|
||||
* this file is required. *
|
||||
* *
|
||||
* Does the change somehow allow for arbitrary javascript to be executed? *
|
||||
* Or allows for someone to change the prototype of built-in objects? *
|
||||
* Or gives undesired access to variables likes document or window? *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/* global JQLitePrototype: true,
|
||||
addEventListenerFn: true,
|
||||
removeEventListenerFn: true,
|
||||
@@ -28,7 +39,7 @@
|
||||
* Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
|
||||
* commonly needed functionality with the goal of having a very small footprint.</div>
|
||||
*
|
||||
* To use jQuery, simply load it before `DOMContentLoaded` event fired.
|
||||
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
|
||||
*
|
||||
* <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
|
||||
* jqLite; they are never raw DOM references.</div>
|
||||
@@ -44,7 +55,7 @@
|
||||
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
|
||||
* - [`clone()`](http://api.jquery.com/clone/)
|
||||
* - [`contents()`](http://api.jquery.com/contents/)
|
||||
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`
|
||||
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
|
||||
* - [`data()`](http://api.jquery.com/data/)
|
||||
* - [`detach()`](http://api.jquery.com/detach/)
|
||||
* - [`empty()`](http://api.jquery.com/empty/)
|
||||
@@ -587,6 +598,10 @@ forEach({
|
||||
},
|
||||
|
||||
attr: function(element, name, value) {
|
||||
var nodeType = element.nodeType;
|
||||
if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
|
||||
return;
|
||||
}
|
||||
var lowercasedName = lowercase(name);
|
||||
if (BOOLEAN_ATTR[lowercasedName]) {
|
||||
if (isDefined(value)) {
|
||||
|
||||
+8
-1
@@ -231,10 +231,17 @@ function setupModuleLoader(window) {
|
||||
* @ngdoc method
|
||||
* @name angular.Module#filter
|
||||
* @module ng
|
||||
* @param {string} name Filter name.
|
||||
* @param {string} name Filter name - this must be a valid angular expression identifier
|
||||
* @param {Function} filterFactory Factory function for creating new instance of filter.
|
||||
* @description
|
||||
* See {@link ng.$filterProvider#register $filterProvider.register()}.
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
|
||||
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
|
||||
* (`myapp_subsection_filterx`).
|
||||
* </div>
|
||||
*/
|
||||
filter: invokeLater('$filterProvider', 'register'),
|
||||
|
||||
|
||||
@@ -210,6 +210,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
leave: function(element, options) {
|
||||
applyStyles(element, options);
|
||||
element.remove();
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
+11
-3
@@ -63,7 +63,7 @@ function Browser(window, document, $log, $sniffer) {
|
||||
|
||||
function getHash(url) {
|
||||
var index = url.indexOf('#');
|
||||
return index === -1 ? '' : url.substr(index + 1);
|
||||
return index === -1 ? '' : url.substr(index);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,7 +190,7 @@ function Browser(window, document, $log, $sniffer) {
|
||||
// Do the assignment again so that those two variables are referentially identical.
|
||||
lastHistoryState = cachedState;
|
||||
} else {
|
||||
if (!sameBase) {
|
||||
if (!sameBase || reloadLocation) {
|
||||
reloadLocation = url;
|
||||
}
|
||||
if (replace) {
|
||||
@@ -233,11 +233,19 @@ function Browser(window, document, $log, $sniffer) {
|
||||
fireUrlChange();
|
||||
}
|
||||
|
||||
function getCurrentState() {
|
||||
try {
|
||||
return history.state;
|
||||
} catch (e) {
|
||||
// MSIE can reportedly throw when there is no state (UNCONFIRMED).
|
||||
}
|
||||
}
|
||||
|
||||
// This variable should be used *only* inside the cacheState function.
|
||||
var lastCachedState = null;
|
||||
function cacheState() {
|
||||
// This should be the only place in $browser where `history.state` is read.
|
||||
cachedState = window.history.state;
|
||||
cachedState = getCurrentState();
|
||||
cachedState = isUndefined(cachedState) ? null : cachedState;
|
||||
|
||||
// Prevent callbacks fo fire twice if both hashchange & popstate were fired.
|
||||
|
||||
@@ -372,7 +372,7 @@ function $CacheFactoryProvider() {
|
||||
* the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
|
||||
* element with ng-app attribute), otherwise the template will be ignored.
|
||||
*
|
||||
* Adding via the $templateCache service:
|
||||
* Adding via the `$templateCache` service:
|
||||
*
|
||||
* ```js
|
||||
* var myApp = angular.module('myApp', []);
|
||||
|
||||
+26
-7
@@ -1,5 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Any commits to this file should be reviewed with security in mind. *
|
||||
* Changes to this file can potentially create security vulnerabilities. *
|
||||
* An approval from 2 Core members with history of modifying *
|
||||
* this file is required. *
|
||||
* *
|
||||
* Does the change somehow allow for arbitrary javascript to be executed? *
|
||||
* Or allows for someone to change the prototype of built-in objects? *
|
||||
* Or gives undesired access to variables likes document or window? *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
|
||||
*
|
||||
* DOM-related variables:
|
||||
@@ -64,7 +75,8 @@
|
||||
* templateNamespace: 'html',
|
||||
* scope: false,
|
||||
* controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
|
||||
* controllerAs: 'stringAlias',
|
||||
* controllerAs: 'stringIdentifier',
|
||||
* bindToController: false,
|
||||
* require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
|
||||
* compile: function compile(tElement, tAttrs, transclude) {
|
||||
* return {
|
||||
@@ -211,7 +223,8 @@
|
||||
* Require another directive and inject its controller as the fourth argument to the linking function. The
|
||||
* `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
|
||||
* injected argument will be an array in corresponding order. If no such directive can be
|
||||
* found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:
|
||||
* found, or if the directive does not have a controller, then an error is raised (unless no link function
|
||||
* is specified, in which case error checking is skipped). The name can be prefixed with:
|
||||
*
|
||||
* * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
|
||||
* * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
|
||||
@@ -382,9 +395,15 @@
|
||||
* * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
|
||||
* between all directive linking functions.
|
||||
*
|
||||
* * `controller` - a controller instance - A controller instance if at least one directive on the
|
||||
* element defines a controller. The controller is shared among all the directives, which allows
|
||||
* the directives to use the controllers as a communication channel.
|
||||
* * `controller` - the directive's required controller instance(s) - Instances are shared
|
||||
* among all directives, which allows the directives to use the controllers as a communication
|
||||
* channel. The exact value depends on the directive's `require` property:
|
||||
* * `string`: the controller instance
|
||||
* * `array`: array of controller instances
|
||||
* * no controller(s) required: `undefined`
|
||||
*
|
||||
* If a required controller cannot be found, and it is optional, the instance is `null`,
|
||||
* otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
|
||||
*
|
||||
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
|
||||
* This is the same as the `$transclude`
|
||||
@@ -410,7 +429,7 @@
|
||||
*
|
||||
* ### Transclusion
|
||||
*
|
||||
* Transclusion is the process of extracting a collection of DOM element from one part of the DOM and
|
||||
* Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
|
||||
* copying them to another part of the DOM, while maintaining their connection to the original AngularJS
|
||||
* scope from where they were taken.
|
||||
*
|
||||
@@ -2165,7 +2184,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
$compileNode.empty();
|
||||
|
||||
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
|
||||
$templateRequest(templateUrl)
|
||||
.then(function(content) {
|
||||
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@
|
||||
* but not on older IEs:
|
||||
*
|
||||
* ```html
|
||||
* <!-- See below for an example of ng-disabled being used correctly -->
|
||||
* <div ng-init="isDisabled = false">
|
||||
* <button disabled="{{isDisabled}}">Disabled</button>
|
||||
* </div>
|
||||
|
||||
+19
-19
@@ -316,7 +316,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
*
|
||||
* # Alias: {@link ng.directive:ngForm `ngForm`}
|
||||
*
|
||||
* In Angular forms can be nested. This means that the outer form is valid when all of the child
|
||||
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
|
||||
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
|
||||
* `<form>` but can be nested. This allows you to have nested forms, which is very useful when
|
||||
@@ -415,11 +415,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
<form name="myForm" ng-controller="FormController" class="my-form">
|
||||
userType: <input name="input" ng-model="userType" required>
|
||||
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
|
||||
<tt>userType = {{userType}}</tt><br>
|
||||
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
|
||||
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
|
||||
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
|
||||
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
|
||||
<code>userType = {{userType}}</code><br>
|
||||
<code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
|
||||
<code>myForm.input.$error = {{myForm.input.$error}}</code><br>
|
||||
<code>myForm.$valid = {{myForm.$valid}}</code><br>
|
||||
<code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
|
||||
</form>
|
||||
</file>
|
||||
<file name="protractor.js" type="protractor">
|
||||
@@ -454,10 +454,12 @@ var formDirectiveFactory = function(isNgForm) {
|
||||
name: 'form',
|
||||
restrict: isNgForm ? 'EAC' : 'E',
|
||||
controller: FormController,
|
||||
compile: function ngFormCompile(formElement) {
|
||||
compile: function ngFormCompile(formElement, attr) {
|
||||
// Setup initial state of the control
|
||||
formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
|
||||
|
||||
var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
|
||||
|
||||
return {
|
||||
pre: function ngFormPreLink(scope, formElement, attr, controller) {
|
||||
// if `action` attr is not present on the form, prevent the default action (submission)
|
||||
@@ -488,23 +490,21 @@ var formDirectiveFactory = function(isNgForm) {
|
||||
});
|
||||
}
|
||||
|
||||
var parentFormCtrl = controller.$$parentForm,
|
||||
alias = controller.$name;
|
||||
var parentFormCtrl = controller.$$parentForm;
|
||||
|
||||
if (alias) {
|
||||
setter(scope, null, alias, controller, alias);
|
||||
attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {
|
||||
if (alias === newValue) return;
|
||||
setter(scope, null, alias, undefined, alias);
|
||||
alias = newValue;
|
||||
setter(scope, null, alias, controller, alias);
|
||||
parentFormCtrl.$$renameControl(controller, alias);
|
||||
if (nameAttr) {
|
||||
setter(scope, null, controller.$name, controller, controller.$name);
|
||||
attr.$observe(nameAttr, function(newValue) {
|
||||
if (controller.$name === newValue) return;
|
||||
setter(scope, null, controller.$name, undefined, controller.$name);
|
||||
parentFormCtrl.$$renameControl(controller, newValue);
|
||||
setter(scope, null, controller.$name, controller, controller.$name);
|
||||
});
|
||||
}
|
||||
formElement.on('$destroy', function() {
|
||||
parentFormCtrl.$removeControl(controller);
|
||||
if (alias) {
|
||||
setter(scope, null, alias, undefined, alias);
|
||||
if (nameAttr) {
|
||||
setter(scope, null, attr[nameAttr], undefined, controller.$name);
|
||||
}
|
||||
extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
DIRTY_CLASS: false,
|
||||
UNTOUCHED_CLASS: false,
|
||||
TOUCHED_CLASS: false,
|
||||
$ngModelMinErr: false,
|
||||
ngModelMinErr: false,
|
||||
*/
|
||||
|
||||
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
|
||||
@@ -587,7 +587,11 @@ var inputType = {
|
||||
* Text input with number validation and transformation. Sets the `number` validation
|
||||
* error if not a valid number.
|
||||
*
|
||||
* The model must always be a number, otherwise Angular will throw an error.
|
||||
* <div class="alert alert-warning">
|
||||
* The model must always be of type `number` otherwise Angular will throw an error.
|
||||
* Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
|
||||
* error docs for more information and an example of how to convert your model if necessary.
|
||||
* </div>
|
||||
*
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
* @param {string=} name Property name of the form under which the control is published.
|
||||
@@ -1166,7 +1170,7 @@ function createDateInputType(type, regexp, parseDate, format) {
|
||||
|
||||
ctrl.$formatters.push(function(value) {
|
||||
if (value && !isDate(value)) {
|
||||
throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
|
||||
throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
|
||||
}
|
||||
if (isValidDate(value)) {
|
||||
previousDate = value;
|
||||
@@ -1243,7 +1247,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
||||
ctrl.$formatters.push(function(value) {
|
||||
if (!ctrl.$isEmpty(value)) {
|
||||
if (!isNumber(value)) {
|
||||
throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
|
||||
throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
|
||||
}
|
||||
value = value.toString();
|
||||
}
|
||||
@@ -1336,7 +1340,7 @@ function parseConstantExpr($parse, context, name, expression, fallback) {
|
||||
if (isDefined(expression)) {
|
||||
parseFn = $parse(expression);
|
||||
if (!parseFn.constant) {
|
||||
throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +
|
||||
throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
|
||||
'`{1}`.', name, expression);
|
||||
}
|
||||
return parseFn(context);
|
||||
|
||||
@@ -33,17 +33,13 @@
|
||||
* document; alternatively, the css rule above must be included in the external stylesheet of the
|
||||
* application.
|
||||
*
|
||||
* Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
|
||||
* cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
|
||||
* class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
|
||||
*
|
||||
* @element ANY
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div id="template1" ng-cloak>{{ 'hello' }}</div>
|
||||
<div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
|
||||
<div id="template2" class="ng-cloak">{{ 'world' }}</div>
|
||||
</file>
|
||||
<file name="protractor.js" type="protractor">
|
||||
it('should remove the template directive and css class', function() {
|
||||
|
||||
@@ -178,8 +178,8 @@
|
||||
* @param {Object} angularEvent Synthetic event object.
|
||||
* @param {String} src URL of content to load.
|
||||
*/
|
||||
var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',
|
||||
function($templateRequest, $anchorScroll, $animate, $sce) {
|
||||
var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
|
||||
function($templateRequest, $anchorScroll, $animate) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: 400,
|
||||
@@ -215,7 +215,7 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce
|
||||
}
|
||||
};
|
||||
|
||||
scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
|
||||
scope.$watch(srcExp, function ngIncludeWatchAction(src) {
|
||||
var afterAnimation = function() {
|
||||
if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
|
||||
+20
-13
@@ -16,8 +16,7 @@ var VALID_CLASS = 'ng-valid',
|
||||
TOUCHED_CLASS = 'ng-touched',
|
||||
PENDING_CLASS = 'ng-pending';
|
||||
|
||||
|
||||
var $ngModelMinErr = new minErr('ngModel');
|
||||
var ngModelMinErr = minErr('ngModel');
|
||||
|
||||
/**
|
||||
* @ngdoc type
|
||||
@@ -129,8 +128,8 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`.
|
||||
* data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
|
||||
* collaborate together to achieve the desired result.
|
||||
*
|
||||
* Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
|
||||
* contents be edited in place by the user. This will not work on older browsers.
|
||||
* `contenteditable` is an HTML5 attribute, which tells the browser to let the element
|
||||
* contents be edited in place by the user.
|
||||
*
|
||||
* We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
|
||||
* module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
|
||||
@@ -268,7 +267,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
}
|
||||
};
|
||||
} else if (!parsedNgModel.assign) {
|
||||
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
|
||||
throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
|
||||
$attr.ngModel, startingTag($element));
|
||||
}
|
||||
};
|
||||
@@ -502,7 +501,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* If the validity changes to invalid, the model will be set to `undefined`,
|
||||
* unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
|
||||
* If the validity changes to valid, it will set the model to the last available valid
|
||||
* modelValue, i.e. either the last parsed value or the last value set from the scope.
|
||||
* `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
|
||||
*/
|
||||
this.$validate = function() {
|
||||
// ignore $validate before model is initialized
|
||||
@@ -597,7 +596,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
forEach(ctrl.$asyncValidators, function(validator, name) {
|
||||
var promise = validator(modelValue, viewValue);
|
||||
if (!isPromiseLike(promise)) {
|
||||
throw $ngModelMinErr("$asyncValidators",
|
||||
throw ngModelMinErr("$asyncValidators",
|
||||
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
|
||||
}
|
||||
setValidity(name, undefined);
|
||||
@@ -810,7 +809,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
|
||||
// if scope model value and ngModel value are out of sync
|
||||
// TODO(perf): why not move this to the action fn?
|
||||
if (modelValue !== ctrl.$modelValue) {
|
||||
if (modelValue !== ctrl.$modelValue &&
|
||||
// checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
|
||||
(ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
|
||||
) {
|
||||
ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
|
||||
parserValid = undefined;
|
||||
|
||||
@@ -987,10 +989,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
var _name = 'Brian';
|
||||
$scope.user = {
|
||||
name: function(newName) {
|
||||
if (angular.isDefined(newName)) {
|
||||
_name = newName;
|
||||
}
|
||||
return _name;
|
||||
// Note that newName can be undefined for two reasons:
|
||||
// 1. Because it is called as a getter and thus called with no arguments
|
||||
// 2. Because the property should actually be set to undefined. This happens e.g. if the
|
||||
// input is invalid
|
||||
return arguments.length ? (_name = newName) : _name;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1202,7 +1205,11 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
||||
var _name = 'Brian';
|
||||
$scope.user = {
|
||||
name: function(newName) {
|
||||
return angular.isDefined(newName) ? (_name = newName) : _name;
|
||||
// Note that newName can be undefined for two reasons:
|
||||
// 1. Because it is called as a getter and thus called with no arguments
|
||||
// 2. Because the property should actually be set to undefined. This happens e.g. if the
|
||||
// input is invalid
|
||||
return arguments.length ? (_name = newName) : _name;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
@@ -47,10 +47,10 @@
|
||||
</example>
|
||||
*/
|
||||
var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
||||
scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
|
||||
scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
|
||||
if (oldStyles && (newStyles !== oldStyles)) {
|
||||
forEach(oldStyles, function(val, style) { element.css(style, '');});
|
||||
}
|
||||
if (newStyles) element.css(newStyles);
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
*
|
||||
* @scope
|
||||
* @priority 1200
|
||||
* @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
|
||||
* @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
|
||||
* On child elements add:
|
||||
*
|
||||
* * `ngSwitchWhen`: the case statement to match against. If match then this
|
||||
@@ -60,7 +60,7 @@
|
||||
<div ng-controller="ExampleController">
|
||||
<select ng-model="selection" ng-options="item for item in items">
|
||||
</select>
|
||||
<tt>selection={{selection}}</tt>
|
||||
<code>selection={{selection}}</code>
|
||||
<hr/>
|
||||
<div class="animate-switch-container"
|
||||
ng-switch on="selection">
|
||||
|
||||
@@ -316,7 +316,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
selectElement.val(viewValue);
|
||||
if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
|
||||
} else {
|
||||
if (isUndefined(viewValue) && emptyOption) {
|
||||
if (viewValue == null && emptyOption) {
|
||||
selectElement.val('');
|
||||
} else {
|
||||
selectCtrl.renderUnknownOption(viewValue);
|
||||
|
||||
@@ -43,8 +43,9 @@ var patternDirective = function() {
|
||||
ctrl.$validate();
|
||||
});
|
||||
|
||||
ctrl.$validators.pattern = function(value) {
|
||||
return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);
|
||||
ctrl.$validators.pattern = function(modelValue, viewValue) {
|
||||
// HTML5 pattern constraint validates the input value, so we validate the viewValue
|
||||
return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
* Dependency Injected. To achieve this a filter definition consists of a factory function which is
|
||||
* annotated with dependencies and is responsible for creating a filter function.
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
|
||||
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
|
||||
* (`myapp_subsection_filterx`).
|
||||
* </div>
|
||||
*
|
||||
* ```js
|
||||
* // Filter registration
|
||||
* function MyModule($provide, $filterProvider) {
|
||||
@@ -101,6 +108,13 @@ function $FilterProvider($provide) {
|
||||
* @name $filterProvider#register
|
||||
* @param {string|Object} name Name of the filter function, or an object map of filters where
|
||||
* the keys are the filter names and the values are the filter factories.
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
|
||||
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
|
||||
* (`myapp_subsection_filterx`).
|
||||
* </div>
|
||||
* @returns {Object} Registered filter instance, or if a map of filters was provided then a map
|
||||
* of the registered filter instances.
|
||||
*/
|
||||
|
||||
+14
-4
@@ -126,14 +126,16 @@ function filterFilter() {
|
||||
return function(array, expression, comparator) {
|
||||
if (!isArray(array)) return array;
|
||||
|
||||
var expressionType = (expression !== null) ? typeof expression : 'null';
|
||||
var predicateFn;
|
||||
var matchAgainstAnyProp;
|
||||
|
||||
switch (typeof expression) {
|
||||
switch (expressionType) {
|
||||
case 'function':
|
||||
predicateFn = expression;
|
||||
break;
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
case 'number':
|
||||
case 'string':
|
||||
matchAgainstAnyProp = true;
|
||||
@@ -159,6 +161,14 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
|
||||
comparator = equals;
|
||||
} else if (!isFunction(comparator)) {
|
||||
comparator = function(actual, expected) {
|
||||
if (isUndefined(actual)) {
|
||||
// No substring matching against `undefined`
|
||||
return false;
|
||||
}
|
||||
if ((actual === null) || (expected === null)) {
|
||||
// No substring matching against `null`; only match against `null`
|
||||
return actual === expected;
|
||||
}
|
||||
if (isObject(actual) || isObject(expected)) {
|
||||
// Prevent an object to be considered equal to a string like `'[object'`
|
||||
return false;
|
||||
@@ -181,8 +191,8 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
|
||||
}
|
||||
|
||||
function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
|
||||
var actualType = typeof actual;
|
||||
var expectedType = typeof expected;
|
||||
var actualType = (actual !== null) ? typeof actual : 'null';
|
||||
var expectedType = (expected !== null) ? typeof expected : 'null';
|
||||
|
||||
if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
|
||||
return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
|
||||
@@ -207,7 +217,7 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc
|
||||
} else if (expectedType === 'object') {
|
||||
for (key in expected) {
|
||||
var expectedVal = expected[key];
|
||||
if (isFunction(expectedVal)) {
|
||||
if (isFunction(expectedVal) || isUndefined(expectedVal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ function currencyFilter($locale) {
|
||||
* @description
|
||||
* Formats a number as text.
|
||||
*
|
||||
* If the input is null or undefined, it will just be returned.
|
||||
* If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
|
||||
* If the input is not a number an empty string is returned.
|
||||
*
|
||||
* @param {number|string} number Number to format.
|
||||
@@ -292,6 +294,14 @@ function ampmGetter(date, formats) {
|
||||
return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
|
||||
}
|
||||
|
||||
function eraGetter(date, formats) {
|
||||
return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
|
||||
}
|
||||
|
||||
function longEraGetter(date, formats) {
|
||||
return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
|
||||
}
|
||||
|
||||
var DATE_FORMATS = {
|
||||
yyyy: dateGetter('FullYear', 4),
|
||||
yy: dateGetter('FullYear', 2, 0, true),
|
||||
@@ -318,10 +328,14 @@ var DATE_FORMATS = {
|
||||
a: ampmGetter,
|
||||
Z: timeZoneGetter,
|
||||
ww: weekGetter(2),
|
||||
w: weekGetter(1)
|
||||
w: weekGetter(1),
|
||||
G: eraGetter,
|
||||
GG: eraGetter,
|
||||
GGG: eraGetter,
|
||||
GGGG: longEraGetter
|
||||
};
|
||||
|
||||
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,
|
||||
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
|
||||
NUMBER_STRING = /^\-?\d+$/;
|
||||
|
||||
/**
|
||||
@@ -358,6 +372,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
|
||||
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
|
||||
* * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
|
||||
* * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
|
||||
* * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
|
||||
* * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
|
||||
*
|
||||
* `format` string can also be one of the following predefined
|
||||
* {@link guide/i18n localizable formats}:
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Can be one of:
|
||||
*
|
||||
* - `function`: Getter function. The result of this function will be sorted using the
|
||||
* `<`, `=`, `>` operator.
|
||||
* `<`, `===`, `>` operator.
|
||||
* - `string`: An Angular expression. The result of this expression is used to compare elements
|
||||
* (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
|
||||
* 3 first characters of a property called `name`). The result of a constant expression
|
||||
@@ -34,6 +34,43 @@
|
||||
* @param {boolean=} reverse Reverse the order of the array.
|
||||
* @returns {Array} Sorted copy of the source array.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* The example below demonstrates a simple ngRepeat, where the data is sorted
|
||||
* by age in descending order (predicate is set to `'-age'`).
|
||||
* `reverse` is not set, which means it defaults to `false`.
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
angular.module('orderByExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.friends =
|
||||
[{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}];
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="ExampleController">
|
||||
<table class="friend">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Phone Number</th>
|
||||
<th>Age</th>
|
||||
</tr>
|
||||
<tr ng-repeat="friend in friends | orderBy:'-age'">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<td>{{friend.age}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</file>
|
||||
</example>
|
||||
*
|
||||
* The predicate and reverse parameters can be controlled dynamically through scope properties,
|
||||
* as shown in the next example.
|
||||
* @example
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
|
||||
+7
-3
@@ -371,7 +371,7 @@ function $HttpProvider() {
|
||||
* headers: {
|
||||
* 'Content-Type': undefined
|
||||
* },
|
||||
* data: { test: 'test' },
|
||||
* data: { test: 'test' }
|
||||
* }
|
||||
*
|
||||
* $http(req).success(function(){...}).error(function(){...});
|
||||
@@ -806,6 +806,8 @@ function $HttpProvider() {
|
||||
}
|
||||
|
||||
promise.success = function(fn) {
|
||||
assertArgFn(fn, 'fn');
|
||||
|
||||
promise.then(function(response) {
|
||||
fn(response.data, response.status, response.headers, config);
|
||||
});
|
||||
@@ -813,6 +815,8 @@ function $HttpProvider() {
|
||||
};
|
||||
|
||||
promise.error = function(fn) {
|
||||
assertArgFn(fn, 'fn');
|
||||
|
||||
promise.then(null, function(response) {
|
||||
fn(response.data, response.status, response.headers, config);
|
||||
});
|
||||
@@ -1106,8 +1110,8 @@ function $HttpProvider() {
|
||||
* Resolves the raw $http promise.
|
||||
*/
|
||||
function resolvePromise(response, status, headers, statusText) {
|
||||
// normalize internal statuses to 0
|
||||
status = Math.max(status, 0);
|
||||
//status: HTTP response status code, 0, -1 (aborted by timeout / promise)
|
||||
status = status >= -1 ? status : 0;
|
||||
|
||||
(isSuccess(status) ? deferred.resolve : deferred.reject)({
|
||||
data: response,
|
||||
|
||||
@@ -58,7 +58,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
||||
xhr.onload = function requestLoaded() {
|
||||
var statusText = xhr.statusText || '';
|
||||
|
||||
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
|
||||
// responseText is the old-school way of retrieving response (supported by IE9)
|
||||
// response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
|
||||
var response = ('response' in xhr) ? xhr.response : xhr.responseText;
|
||||
|
||||
@@ -137,7 +137,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
||||
};
|
||||
|
||||
function jsonpReq(url, callbackId, done) {
|
||||
// we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
|
||||
// we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
|
||||
// - fetches local scripts via XHR and evals them
|
||||
// - adds and immediately removes script elements from the document
|
||||
var script = rawDocument.createElement('script'), callback = null;
|
||||
|
||||
+9
-1
@@ -59,7 +59,15 @@ function $LocaleProvider() {
|
||||
mediumDate: 'MMM d, y',
|
||||
shortDate: 'M/d/yy',
|
||||
mediumTime: 'h:mm:ss a',
|
||||
shortTime: 'h:mm a'
|
||||
shortTime: 'h:mm a',
|
||||
ERANAMES: [
|
||||
"Before Christ",
|
||||
"Anno Domini"
|
||||
],
|
||||
ERAS: [
|
||||
"BC",
|
||||
"AD"
|
||||
]
|
||||
},
|
||||
|
||||
pluralCat: function(num) {
|
||||
|
||||
+35
-11
@@ -89,12 +89,12 @@ function serverBase(url) {
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} appBase application base URL
|
||||
* @param {string} appBaseNoFile application base URL stripped of any filename
|
||||
* @param {string} basePrefix url path prefix
|
||||
*/
|
||||
function LocationHtml5Url(appBase, basePrefix) {
|
||||
function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
|
||||
this.$$html5 = true;
|
||||
basePrefix = basePrefix || '';
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
parseAbsoluteUrl(appBase, this);
|
||||
|
||||
|
||||
@@ -168,10 +168,10 @@ function LocationHtml5Url(appBase, basePrefix) {
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} appBase application base URL
|
||||
* @param {string} appBaseNoFile application base URL stripped of any filename
|
||||
* @param {string} hashPrefix hashbang prefix
|
||||
*/
|
||||
function LocationHashbangUrl(appBase, hashPrefix) {
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
|
||||
|
||||
parseAbsoluteUrl(appBase, this);
|
||||
|
||||
@@ -185,7 +185,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
|
||||
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
|
||||
var withoutHashUrl;
|
||||
|
||||
if (withoutBaseUrl.charAt(0) === '#') {
|
||||
if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
|
||||
|
||||
// The rest of the url starts with a hash so we have
|
||||
// got either a hashbang path or a plain hash fragment
|
||||
@@ -199,7 +199,15 @@ function LocationHashbangUrl(appBase, hashPrefix) {
|
||||
// There was no hashbang path nor hash fragment:
|
||||
// If we are in HTML5 mode we use what is left as the path;
|
||||
// Otherwise we ignore what is left
|
||||
withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
|
||||
if (this.$$html5) {
|
||||
withoutHashUrl = withoutBaseUrl;
|
||||
} else {
|
||||
withoutHashUrl = '';
|
||||
if (isUndefined(withoutBaseUrl)) {
|
||||
appBase = url;
|
||||
this.replace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parseAppUrl(withoutHashUrl, this);
|
||||
@@ -272,14 +280,13 @@ function LocationHashbangUrl(appBase, hashPrefix) {
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} appBase application base URL
|
||||
* @param {string} appBaseNoFile application base URL stripped of any filename
|
||||
* @param {string} hashPrefix hashbang prefix
|
||||
*/
|
||||
function LocationHashbangInHtml5Url(appBase, hashPrefix) {
|
||||
function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
|
||||
this.$$html5 = true;
|
||||
LocationHashbangUrl.apply(this, arguments);
|
||||
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
|
||||
this.$$parseLinkUrl = function(url, relHref) {
|
||||
if (relHref && relHref[0] === '#') {
|
||||
// special case for links to hash fragments:
|
||||
@@ -309,7 +316,7 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
|
||||
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
||||
|
||||
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
||||
// include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
|
||||
// include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
|
||||
this.$$absUrl = appBase + hashPrefix + this.$$url;
|
||||
};
|
||||
|
||||
@@ -413,11 +420,19 @@ var locationPrototype = {
|
||||
*
|
||||
* Return host of current url.
|
||||
*
|
||||
* Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
|
||||
*
|
||||
*
|
||||
* ```js
|
||||
* // given url http://example.com/#/some/path?foo=bar&baz=xoxo
|
||||
* var host = $location.host();
|
||||
* // => "example.com"
|
||||
*
|
||||
* // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
|
||||
* host = $location.host();
|
||||
* // => "example.com"
|
||||
* host = location.host;
|
||||
* // => "example.com:8080"
|
||||
* ```
|
||||
*
|
||||
* @return {string} host of current url.
|
||||
@@ -807,7 +822,9 @@ function $LocationProvider() {
|
||||
appBase = stripHash(initialUrl);
|
||||
LocationMode = LocationHashbangUrl;
|
||||
}
|
||||
$location = new LocationMode(appBase, '#' + hashPrefix);
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
|
||||
$location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
|
||||
$location.$$parseLinkUrl(initialUrl, initialUrl);
|
||||
|
||||
$location.$$state = $browser.state();
|
||||
@@ -887,6 +904,13 @@ function $LocationProvider() {
|
||||
|
||||
// update $location when $browser url changes
|
||||
$browser.onUrlChange(function(newUrl, newState) {
|
||||
|
||||
if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
|
||||
// If we are navigating outside of the app then force a reload
|
||||
$window.location.href = newUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
$rootScope.$evalAsync(function() {
|
||||
var oldUrl = $location.absUrl();
|
||||
var oldState = $location.$$state;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<button ng-click="$log.warn(message)">warn</button>
|
||||
<button ng-click="$log.info(message)">info</button>
|
||||
<button ng-click="$log.error(message)">error</button>
|
||||
<button ng-click="$log.debug(message)">debug</button>
|
||||
</div>
|
||||
</file>
|
||||
</example>
|
||||
|
||||
+32
-2
@@ -1,5 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Any commits to this file should be reviewed with security in mind. *
|
||||
* Changes to this file can potentially create security vulnerabilities. *
|
||||
* An approval from 2 Core members with history of modifying *
|
||||
* this file is required. *
|
||||
* *
|
||||
* Does the change somehow allow for arbitrary javascript to be executed? *
|
||||
* Or allows for someone to change the prototype of built-in objects? *
|
||||
* Or gives undesired access to variables likes document or window? *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
var $parseMinErr = minErr('$parse');
|
||||
|
||||
// Sandboxing Angular Expressions
|
||||
@@ -37,6 +48,25 @@ function ensureSafeMemberName(name, fullExpression) {
|
||||
return name;
|
||||
}
|
||||
|
||||
function getStringValue(name, fullExpression) {
|
||||
// From the JavaScript docs:
|
||||
// Property names must be strings. This means that non-string objects cannot be used
|
||||
// as keys in an object. Any non-string object, including a number, is typecasted
|
||||
// into a string via the toString method.
|
||||
//
|
||||
// So, to ensure that we are checking the same `name` that JavaScript would use,
|
||||
// we cast it to a string, if possible.
|
||||
// Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
|
||||
// this is, this will handle objects that misbehave.
|
||||
name = name + '';
|
||||
if (!isString(name)) {
|
||||
throw $parseMinErr('iseccst',
|
||||
'Cannot convert object to primitive value! '
|
||||
+ 'Expression: {0}', fullExpression);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function ensureSafeObject(obj, fullExpression) {
|
||||
// nifty check if obj is Function that is fast and works across iframes and other contexts
|
||||
if (obj) {
|
||||
@@ -678,7 +708,7 @@ Parser.prototype = {
|
||||
|
||||
return extend(function $parseObjectIndex(self, locals) {
|
||||
var o = obj(self, locals),
|
||||
i = indexFn(self, locals),
|
||||
i = getStringValue(indexFn(self, locals), expression),
|
||||
v;
|
||||
|
||||
ensureSafeMemberName(i, expression);
|
||||
@@ -687,7 +717,7 @@ Parser.prototype = {
|
||||
return v;
|
||||
}, {
|
||||
assign: function(self, value, locals) {
|
||||
var key = ensureSafeMemberName(indexFn(self, locals), expression);
|
||||
var key = ensureSafeMemberName(getStringValue(indexFn(self, locals), expression), expression);
|
||||
// prevent overwriting of Function.constructor which would break ensureSafeObject check
|
||||
var o = ensureSafeObject(obj(self, locals), expression);
|
||||
if (!o) obj.assign(self, o = {}, locals);
|
||||
|
||||
+41
-3
@@ -10,7 +10,7 @@ function $$RAFProvider() { //rAF
|
||||
$window.webkitCancelRequestAnimationFrame;
|
||||
|
||||
var rafSupported = !!requestAnimationFrame;
|
||||
var raf = rafSupported
|
||||
var rafFn = rafSupported
|
||||
? function(fn) {
|
||||
var id = requestAnimationFrame(fn);
|
||||
return function() {
|
||||
@@ -24,8 +24,46 @@ function $$RAFProvider() { //rAF
|
||||
};
|
||||
};
|
||||
|
||||
raf.supported = rafSupported;
|
||||
queueFn.supported = rafSupported;
|
||||
|
||||
return raf;
|
||||
var cancelLastRAF;
|
||||
var taskCount = 0;
|
||||
var taskQueue = [];
|
||||
return queueFn;
|
||||
|
||||
function flush() {
|
||||
for (var i = 0; i < taskQueue.length; i++) {
|
||||
var task = taskQueue[i];
|
||||
if (task) {
|
||||
taskQueue[i] = null;
|
||||
task();
|
||||
}
|
||||
}
|
||||
taskCount = taskQueue.length = 0;
|
||||
}
|
||||
|
||||
function queueFn(asyncFn) {
|
||||
var index = taskQueue.length;
|
||||
|
||||
taskCount++;
|
||||
taskQueue.push(asyncFn);
|
||||
|
||||
if (index === 0) {
|
||||
cancelLastRAF = rafFn(flush);
|
||||
}
|
||||
|
||||
return function cancelQueueFn() {
|
||||
if (index >= 0) {
|
||||
taskQueue[index] = null;
|
||||
index = null;
|
||||
|
||||
if (--taskCount === 0 && cancelLastRAF) {
|
||||
cancelLastRAF();
|
||||
cancelLastRAF = null;
|
||||
taskQueue.length = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+24
-22
@@ -80,9 +80,26 @@ function $RootScopeProvider() {
|
||||
return TTL;
|
||||
};
|
||||
|
||||
function createChildScopeClass(parent) {
|
||||
function ChildScope() {
|
||||
this.$$watchers = this.$$nextSibling =
|
||||
this.$$childHead = this.$$childTail = null;
|
||||
this.$$listeners = {};
|
||||
this.$$listenerCount = {};
|
||||
this.$id = nextUid();
|
||||
this.$$ChildScope = null;
|
||||
}
|
||||
ChildScope.prototype = parent;
|
||||
return ChildScope;
|
||||
}
|
||||
|
||||
this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
|
||||
function($injector, $exceptionHandler, $parse, $browser) {
|
||||
|
||||
function destroyChildScope($event) {
|
||||
$event.currentScope.$$destroyed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc type
|
||||
* @name $rootScope.Scope
|
||||
@@ -91,12 +108,9 @@ function $RootScopeProvider() {
|
||||
* A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
|
||||
* {@link auto.$injector $injector}. Child scopes are created using the
|
||||
* {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
|
||||
* compiled HTML template is executed.)
|
||||
* compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
|
||||
* an in-depth introduction and usage examples.
|
||||
*
|
||||
* Here is a simple scope snippet to show how you can interact with the scope.
|
||||
* ```html
|
||||
* <file src="./test/ng/rootScopeSpec.js" tag="docs1" />
|
||||
* ```
|
||||
*
|
||||
* # Inheritance
|
||||
* A scope can inherit from a parent scope, as in this example:
|
||||
@@ -205,15 +219,7 @@ function $RootScopeProvider() {
|
||||
// Only create a child scope class if somebody asks for one,
|
||||
// but cache it to allow the VM to optimize lookups.
|
||||
if (!this.$$ChildScope) {
|
||||
this.$$ChildScope = function ChildScope() {
|
||||
this.$$watchers = this.$$nextSibling =
|
||||
this.$$childHead = this.$$childTail = null;
|
||||
this.$$listeners = {};
|
||||
this.$$listenerCount = {};
|
||||
this.$id = nextUid();
|
||||
this.$$ChildScope = null;
|
||||
};
|
||||
this.$$ChildScope.prototype = this;
|
||||
this.$$ChildScope = createChildScopeClass(this);
|
||||
}
|
||||
child = new this.$$ChildScope();
|
||||
}
|
||||
@@ -231,13 +237,9 @@ function $RootScopeProvider() {
|
||||
// prototypically. In all other cases, this property needs to be set
|
||||
// when the parent scope is destroyed.
|
||||
// The listener needs to be added after the parent is set
|
||||
if (isolate || parent != this) child.$on('$destroy', destroyChild);
|
||||
if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
|
||||
|
||||
return child;
|
||||
|
||||
function destroyChild() {
|
||||
child.$$destroyed = true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -269,9 +271,9 @@ function $RootScopeProvider() {
|
||||
*
|
||||
*
|
||||
* If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
|
||||
* you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
|
||||
* can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
|
||||
* change is detected, be prepared for multiple calls to your listener.)
|
||||
* you can register a `watchExpression` function with no `listener`. (Be prepared for
|
||||
* multiple calls to your `watchExpression` because it will execute multiple times in a
|
||||
* single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
|
||||
*
|
||||
* After a watcher is registered with the scope, the `listener` fn is called asynchronously
|
||||
* (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
|
||||
|
||||
+15
-4
@@ -1,5 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Any commits to this file should be reviewed with security in mind. *
|
||||
* Changes to this file can potentially create security vulnerabilities. *
|
||||
* An approval from 2 Core members with history of modifying *
|
||||
* this file is required. *
|
||||
* *
|
||||
* Does the change somehow allow for arbitrary javascript to be executed? *
|
||||
* Or allows for someone to change the prototype of built-in objects? *
|
||||
* Or gives undesired access to variables likes document or window? *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
var $sceMinErr = minErr('$sce');
|
||||
|
||||
var SCE_CONTEXTS = {
|
||||
@@ -534,7 +545,7 @@ function $SceDelegateProvider() {
|
||||
* characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
|
||||
* in a whitelist.
|
||||
* - `**`: matches zero or more occurrences of *any* character. As such, it's not
|
||||
* not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
|
||||
* appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.
|
||||
* http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
|
||||
* not have been the intention.) Its usage at the very end of the path is ok. (e.g.
|
||||
* http://foo.example.com/templates/**).
|
||||
@@ -542,11 +553,11 @@ function $SceDelegateProvider() {
|
||||
* - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
|
||||
* (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
|
||||
* accidentally introduce a bug when one updates a complex expression (imho, all regexes should
|
||||
* have good test coverage.). For instance, the use of `.` in the regex is correct only in a
|
||||
* have good test coverage). For instance, the use of `.` in the regex is correct only in a
|
||||
* small number of cases. A `.` character in the regex used when matching the scheme or a
|
||||
* subdomain could be matched against a `:` or literal `.` that was likely not intended. It
|
||||
* is highly recommended to use the string patterns and only fall back to regular expressions
|
||||
* if they as a last resort.
|
||||
* as a last resort.
|
||||
* - The regular expression must be an instance of RegExp (i.e. not a string.) It is
|
||||
* matched against the **entire** *normalized / absolute URL* of the resource being tested
|
||||
* (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
|
||||
@@ -556,7 +567,7 @@ function $SceDelegateProvider() {
|
||||
* remember to escape your regular expression (and be aware that you might need more than
|
||||
* one level of escaping depending on your templating engine and the way you interpolated
|
||||
* the value.) Do make use of your platform's escaping mechanism as it might be good
|
||||
* enough before coding your own. e.g. Ruby has
|
||||
* enough before coding your own. E.g. Ruby has
|
||||
* [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
|
||||
* and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
|
||||
* Javascript lacks a similar built in function for escaping. Take a look at Google
|
||||
|
||||
@@ -7,12 +7,14 @@ var $compileMinErr = minErr('$compile');
|
||||
* @name $templateRequest
|
||||
*
|
||||
* @description
|
||||
* The `$templateRequest` service downloads the provided template using `$http` and, upon success,
|
||||
* stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
|
||||
* of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
|
||||
* by setting the 2nd parameter of the function to true).
|
||||
* The `$templateRequest` service runs security checks then downloads the provided template using
|
||||
* `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
|
||||
* fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
|
||||
* exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
|
||||
* contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
|
||||
* when `tpl` is of type string and `$templateCache` has the matching entry.
|
||||
*
|
||||
* @param {string} tpl The HTTP request template URL
|
||||
* @param {string|TrustedResourceUrl} tpl The HTTP request template URL
|
||||
* @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
|
||||
*
|
||||
* @return {Promise} the HTTP Promise for the given.
|
||||
@@ -20,10 +22,19 @@ var $compileMinErr = minErr('$compile');
|
||||
* @property {number} totalPendingRequests total amount of pending template requests being downloaded.
|
||||
*/
|
||||
function $TemplateRequestProvider() {
|
||||
this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {
|
||||
this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
|
||||
function handleRequestFn(tpl, ignoreRequestError) {
|
||||
handleRequestFn.totalPendingRequests++;
|
||||
|
||||
// We consider the template cache holds only trusted templates, so
|
||||
// there's no need to go through whitelisting again for keys that already
|
||||
// are included in there. This also makes Angular accept any script
|
||||
// directive, no matter its name. However, we still need to unwrap trusted
|
||||
// types.
|
||||
if (!isString(tpl) || !$templateCache.get(tpl)) {
|
||||
tpl = $sce.getTrustedResourceUrl(tpl);
|
||||
}
|
||||
|
||||
var transformResponse = $http.defaults && $http.defaults.transformResponse;
|
||||
|
||||
if (isArray(transformResponse)) {
|
||||
@@ -40,7 +51,7 @@ function $TemplateRequestProvider() {
|
||||
};
|
||||
|
||||
return $http.get(tpl, httpOptions)
|
||||
.finally(function() {
|
||||
['finally'](function() {
|
||||
handleRequestFn.totalPendingRequests--;
|
||||
})
|
||||
.then(function(response) {
|
||||
|
||||
+1
-8
@@ -24,20 +24,13 @@ var originUrl = urlResolve(window.location.href);
|
||||
*
|
||||
* Implementation Notes for IE
|
||||
* ---------------------------
|
||||
* IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
|
||||
* IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
|
||||
* browsers. However, the parsed components will not be set if the URL assigned did not specify
|
||||
* them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
|
||||
* work around that by performing the parsing in a 2nd step by taking a previously normalized
|
||||
* URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
|
||||
* properties such as protocol, hostname, port, etc.
|
||||
*
|
||||
* IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one
|
||||
* uses the inner HTML approach to assign the URL as part of an HTML snippet -
|
||||
* http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.
|
||||
* Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
|
||||
* Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
|
||||
* method and IE < 8 is unsupported.
|
||||
*
|
||||
* References:
|
||||
* http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
|
||||
* http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
|
||||
|
||||
@@ -432,9 +432,11 @@ angular.module('ngAnimate', ['ng'])
|
||||
//so that all the animated elements within the animation frame
|
||||
//will be properly updated and drawn on screen. This is
|
||||
//required to perform multi-class CSS based animations with
|
||||
//Firefox. DO NOT REMOVE THIS LINE.
|
||||
var a = bod.offsetWidth + 1;
|
||||
fn();
|
||||
//Firefox. DO NOT REMOVE THIS LINE. DO NOT OPTIMIZE THIS LINE.
|
||||
//THE MINIFIER WILL REMOVE IT OTHERWISE WHICH WILL RESULT IN AN
|
||||
//UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND WILL
|
||||
//TAKE YEARS AWAY FROM YOUR LIFE!
|
||||
fn(bod.offsetWidth);
|
||||
});
|
||||
};
|
||||
}])
|
||||
@@ -1192,18 +1194,21 @@ angular.module('ngAnimate', ['ng'])
|
||||
}
|
||||
|
||||
return cache.promise = runAnimationPostDigest(function(done) {
|
||||
var parentElement = element.parent();
|
||||
var elementNode = extractElementNode(element);
|
||||
var parentNode = elementNode.parentNode;
|
||||
var cache, parentNode, parentElement, elementNode = extractElementNode(element);
|
||||
if (elementNode) {
|
||||
cache = element.data(STORAGE_KEY);
|
||||
element.removeData(STORAGE_KEY);
|
||||
|
||||
parentElement = element.parent();
|
||||
parentNode = elementNode.parentNode;
|
||||
}
|
||||
|
||||
// TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed
|
||||
if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
var cache = element.data(STORAGE_KEY);
|
||||
element.removeData(STORAGE_KEY);
|
||||
|
||||
var state = element.data(NG_ANIMATE_STATE) || {};
|
||||
var classes = resolveElementClasses(element, cache, state.active);
|
||||
return !classes
|
||||
|
||||
+103
-75
@@ -22,13 +22,13 @@
|
||||
*
|
||||
* | Directive | Supported Attributes |
|
||||
* |---------------------------------------------|----------------------------------------------------------------------------------------|
|
||||
* | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required |
|
||||
* | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
|
||||
* | {@link ng.directive:ngShow ngShow} | aria-hidden |
|
||||
* | {@link ng.directive:ngHide ngHide} | aria-hidden |
|
||||
* | {@link ng.directive:ngClick ngClick} | tabindex, keypress event |
|
||||
* | {@link ng.directive:ngDblclick ngDblclick} | tabindex |
|
||||
* | {@link module:ngMessages ngMessages} | aria-live |
|
||||
* | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
|
||||
* | {@link ng.directive:ngClick ngClick} | tabindex, keypress event, button role |
|
||||
*
|
||||
* Find out more information about each directive by reading the
|
||||
* {@link guide/accessibility ngAria Developer Guide}.
|
||||
@@ -193,6 +193,10 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
||||
return $aria.config(normalizedAttr) && !elem.attr(attr);
|
||||
}
|
||||
|
||||
function shouldAttachRole(role, elem) {
|
||||
return !elem.attr('role') && (elem.attr('type') === role) && (elem[0].nodeName !== 'INPUT');
|
||||
}
|
||||
|
||||
function getShape(attr, elem) {
|
||||
var type = attr.type,
|
||||
role = attr.role;
|
||||
@@ -207,82 +211,101 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
||||
restrict: 'A',
|
||||
require: '?ngModel',
|
||||
priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
|
||||
link: function(scope, elem, attr, ngModel) {
|
||||
compile: function(elem, attr) {
|
||||
var shape = getShape(attr, elem);
|
||||
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
|
||||
|
||||
function ngAriaWatchModelValue() {
|
||||
return ngModel.$modelValue;
|
||||
}
|
||||
return {
|
||||
pre: function(scope, elem, attr, ngModel) {
|
||||
if (shape === 'checkbox' && attr.type !== 'checkbox') {
|
||||
//Use the input[checkbox] $isEmpty implementation for elements with checkbox roles
|
||||
ngModel.$isEmpty = function(value) {
|
||||
return value === false;
|
||||
};
|
||||
}
|
||||
},
|
||||
post: function(scope, elem, attr, ngModel) {
|
||||
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
|
||||
|
||||
function getRadioReaction() {
|
||||
if (needsTabIndex) {
|
||||
needsTabIndex = false;
|
||||
return function ngAriaRadioReaction(newVal) {
|
||||
var boolVal = (attr.value == ngModel.$viewValue);
|
||||
elem.attr('aria-checked', boolVal);
|
||||
elem.attr('tabindex', 0 - !boolVal);
|
||||
};
|
||||
} else {
|
||||
return function ngAriaRadioReaction(newVal) {
|
||||
elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
|
||||
};
|
||||
function ngAriaWatchModelValue() {
|
||||
return ngModel.$modelValue;
|
||||
}
|
||||
|
||||
function getRadioReaction() {
|
||||
if (needsTabIndex) {
|
||||
needsTabIndex = false;
|
||||
return function ngAriaRadioReaction(newVal) {
|
||||
var boolVal = (attr.value == ngModel.$viewValue);
|
||||
elem.attr('aria-checked', boolVal);
|
||||
elem.attr('tabindex', 0 - !boolVal);
|
||||
};
|
||||
} else {
|
||||
return function ngAriaRadioReaction(newVal) {
|
||||
elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function ngAriaCheckboxReaction() {
|
||||
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
|
||||
}
|
||||
|
||||
switch (shape) {
|
||||
case 'radio':
|
||||
case 'checkbox':
|
||||
if (shouldAttachRole(shape, elem)) {
|
||||
elem.attr('role', shape);
|
||||
}
|
||||
if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) {
|
||||
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
|
||||
getRadioReaction() : ngAriaCheckboxReaction);
|
||||
}
|
||||
break;
|
||||
case 'range':
|
||||
if (shouldAttachRole(shape, elem)) {
|
||||
elem.attr('role', 'slider');
|
||||
}
|
||||
if ($aria.config('ariaValue')) {
|
||||
if (attr.min && !elem.attr('aria-valuemin')) {
|
||||
elem.attr('aria-valuemin', attr.min);
|
||||
}
|
||||
if (attr.max && !elem.attr('aria-valuemax')) {
|
||||
elem.attr('aria-valuemax', attr.max);
|
||||
}
|
||||
if (!elem.attr('aria-valuenow')) {
|
||||
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
|
||||
elem.attr('aria-valuenow', newVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'multiline':
|
||||
if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
|
||||
elem.attr('aria-multiline', true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (needsTabIndex) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
|
||||
if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
|
||||
scope.$watch(function ngAriaRequiredWatch() {
|
||||
return ngModel.$error.required;
|
||||
}, function ngAriaRequiredReaction(newVal) {
|
||||
elem.attr('aria-required', !!newVal);
|
||||
});
|
||||
}
|
||||
|
||||
if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) {
|
||||
scope.$watch(function ngAriaInvalidWatch() {
|
||||
return ngModel.$invalid;
|
||||
}, function ngAriaInvalidReaction(newVal) {
|
||||
elem.attr('aria-invalid', !!newVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ngAriaCheckboxReaction(newVal) {
|
||||
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
|
||||
}
|
||||
|
||||
switch (shape) {
|
||||
case 'radio':
|
||||
case 'checkbox':
|
||||
if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) {
|
||||
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
|
||||
getRadioReaction() : ngAriaCheckboxReaction);
|
||||
}
|
||||
break;
|
||||
case 'range':
|
||||
if ($aria.config('ariaValue')) {
|
||||
if (attr.min && !elem.attr('aria-valuemin')) {
|
||||
elem.attr('aria-valuemin', attr.min);
|
||||
}
|
||||
if (attr.max && !elem.attr('aria-valuemax')) {
|
||||
elem.attr('aria-valuemax', attr.max);
|
||||
}
|
||||
if (!elem.attr('aria-valuenow')) {
|
||||
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
|
||||
elem.attr('aria-valuenow', newVal);
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'multiline':
|
||||
if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
|
||||
elem.attr('aria-multiline', true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (needsTabIndex) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
|
||||
if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
|
||||
scope.$watch(function ngAriaRequiredWatch() {
|
||||
return ngModel.$error.required;
|
||||
}, function ngAriaRequiredReaction(newVal) {
|
||||
elem.attr('aria-required', !!newVal);
|
||||
});
|
||||
}
|
||||
|
||||
if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) {
|
||||
scope.$watch(function ngAriaInvalidWatch() {
|
||||
return ngModel.$invalid;
|
||||
}, function ngAriaInvalidReaction(newVal) {
|
||||
elem.attr('aria-invalid', !!newVal);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}])
|
||||
@@ -307,17 +330,22 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
||||
var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
|
||||
return function(scope, elem, attr) {
|
||||
|
||||
var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA'];
|
||||
|
||||
function isNodeOneOf(elem, nodeTypeArray) {
|
||||
if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!elem.attr('role') && !isNodeOneOf(elem, nodeBlackList)) {
|
||||
elem.attr('role', 'button');
|
||||
}
|
||||
|
||||
if ($aria.config('tabindex') && !elem.attr('tabindex')) {
|
||||
elem.attr('tabindex', 0);
|
||||
}
|
||||
|
||||
if ($aria.config('bindKeypress') && !attr.ngKeypress && isNodeOneOf(elem, ['DIV', 'LI'])) {
|
||||
if ($aria.config('bindKeypress') && !attr.ngKeypress && !isNodeOneOf(elem, nodeBlackList)) {
|
||||
elem.on('keypress', function(event) {
|
||||
if (event.keyCode === 32 || event.keyCode === 13) {
|
||||
scope.$apply(callback);
|
||||
|
||||
@@ -86,6 +86,7 @@ angular.module('ngCookies', ['ng']).
|
||||
for (name in lastCookies) {
|
||||
if (isUndefined(cookies[name])) {
|
||||
$browser.cookies(name, undefined);
|
||||
delete lastCookies[name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,13 +99,13 @@ angular.module('ngCookies', ['ng']).
|
||||
}
|
||||
if (value !== lastCookies[name]) {
|
||||
$browser.cookies(name, value);
|
||||
lastCookies[name] = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
//verify what was actually stored
|
||||
if (updated) {
|
||||
updated = false;
|
||||
browserCookies = $browser.cookies();
|
||||
|
||||
for (name in cookies) {
|
||||
@@ -112,10 +113,10 @@ angular.module('ngCookies', ['ng']).
|
||||
//delete or reset all cookies that the browser dropped from $cookies
|
||||
if (isUndefined(browserCookies[name])) {
|
||||
delete cookies[name];
|
||||
delete lastCookies[name];
|
||||
} else {
|
||||
cookies[name] = browserCookies[name];
|
||||
cookies[name] = lastCookies[name] = browserCookies[name];
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"Gumqata",
|
||||
"Sabti"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"ERAS": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"MONTH": [
|
||||
"Qunxa Garablu",
|
||||
"Kudo",
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"Gumqata",
|
||||
"Sabti"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"ERAS": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"MONTH": [
|
||||
"Qunxa Garablu",
|
||||
"Kudo",
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"Gumqata",
|
||||
"Sabti"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"ERAS": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"MONTH": [
|
||||
"Qunxa Garablu",
|
||||
"Kudo",
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"Gumqata",
|
||||
"Sabti"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"ERAS": [
|
||||
"Yaasuusuk Duma",
|
||||
"Yaasuusuk Wadir"
|
||||
],
|
||||
"MONTH": [
|
||||
"Qunxa Garablu",
|
||||
"Kudo",
|
||||
|
||||
Vendored
+8
@@ -16,6 +16,14 @@ $provide.value("$locale", {
|
||||
"Vrydag",
|
||||
"Saterdag"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"voor Christus",
|
||||
"na Christus"
|
||||
],
|
||||
"ERAS": [
|
||||
"v.C.",
|
||||
"n.C."
|
||||
],
|
||||
"MONTH": [
|
||||
"Januarie",
|
||||
"Februarie",
|
||||
|
||||
Vendored
+8
@@ -16,6 +16,14 @@ $provide.value("$locale", {
|
||||
"Vrydag",
|
||||
"Saterdag"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"voor Christus",
|
||||
"na Christus"
|
||||
],
|
||||
"ERAS": [
|
||||
"v.C.",
|
||||
"n.C."
|
||||
],
|
||||
"MONTH": [
|
||||
"Januarie",
|
||||
"Februarie",
|
||||
|
||||
Vendored
+8
@@ -16,6 +16,14 @@ $provide.value("$locale", {
|
||||
"Vrydag",
|
||||
"Saterdag"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"voor Christus",
|
||||
"na Christus"
|
||||
],
|
||||
"ERAS": [
|
||||
"v.C.",
|
||||
"n.C."
|
||||
],
|
||||
"MONTH": [
|
||||
"Januarie",
|
||||
"Februarie",
|
||||
|
||||
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"tsu\u0294ugh\u0268\u0302m",
|
||||
"tsu\u0294ndz\u0268k\u0254\u0294\u0254"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"S\u011be K\u0268\u0300lesto",
|
||||
"B\u01cea K\u0268\u0300lesto"
|
||||
],
|
||||
"ERAS": [
|
||||
"SK",
|
||||
"BK"
|
||||
],
|
||||
"MONTH": [
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300k\u0197\u0300z\u00f9\u0294",
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"tsu\u0294ugh\u0268\u0302m",
|
||||
"tsu\u0294ndz\u0268k\u0254\u0294\u0254"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"S\u011be K\u0268\u0300lesto",
|
||||
"B\u01cea K\u0268\u0300lesto"
|
||||
],
|
||||
"ERAS": [
|
||||
"SK",
|
||||
"BK"
|
||||
],
|
||||
"MONTH": [
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300k\u0197\u0300z\u00f9\u0294",
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"Fida",
|
||||
"Memeneda"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"Ansa Kristo",
|
||||
"Kristo Ekyiri"
|
||||
],
|
||||
"ERAS": [
|
||||
"AK",
|
||||
"KE"
|
||||
],
|
||||
"MONTH": [
|
||||
"Sanda-\u0186p\u025bp\u0254n",
|
||||
"Kwakwar-\u0186gyefuo",
|
||||
|
||||
Vendored
+8
@@ -34,6 +34,14 @@ $provide.value("$locale", {
|
||||
"Fida",
|
||||
"Memeneda"
|
||||
],
|
||||
"ERANAMES": [
|
||||
"Ansa Kristo",
|
||||
"Kristo Ekyiri"
|
||||
],
|
||||
"ERAS": [
|
||||
"AK",
|
||||
"KE"
|
||||
],
|
||||
"MONTH": [
|
||||
"Sanda-\u0186p\u025bp\u0254n",
|
||||
"Kwakwar-\u0186gyefuo",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user