Compare commits
370 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca7f4a387c | |||
| 898a3fd3b9 | |||
| 9473371343 | |||
| e5275590db | |||
| 78297d252d | |||
| e5e0884eaf | |||
| 551d1c20cf | |||
| f5aa207960 | |||
| 4412fe238f | |||
| 8088284f66 | |||
| 25f1bbaad1 | |||
| bd7b217729 | |||
| 50557a6cd3 | |||
| 1c13a4f45d | |||
| 1a98c0ee34 | |||
| b837fc3116 | |||
| aff74ec87b | |||
| 077ee37942 | |||
| 0efef2385f | |||
| 7da22e6685 | |||
| 92bdd7627f | |||
| 39ebb06baf | |||
| 9cf6b197ab | |||
| 4971ef12d4 | |||
| 7c792f4cc9 | |||
| 4daafd3dbe | |||
| fe11265fdc | |||
| 75292a6cb5 | |||
| 4ff6c85792 | |||
| e26bc2370b | |||
| 33713deeb8 | |||
| 17715fa366 | |||
| 96288d02d3 | |||
| 8be98e4fdf | |||
| cf83b4f445 | |||
| 15bfea8339 | |||
| 9b90c32f31 | |||
| f4bf744516 | |||
| 0d96995fcc | |||
| 2a85a634f8 | |||
| 00d2b2c4cf | |||
| e688f07023 | |||
| 8e2f7d37e4 | |||
| f5bc3ed9b4 | |||
| 11d60af3dc | |||
| 865f6065e7 | |||
| 91c0b364af | |||
| fce07f55e5 | |||
| c8768d12f2 | |||
| af6342d6fb | |||
| a179757fad | |||
| 35eada68c4 | |||
| bfad2a4f4a | |||
| 54e816552f | |||
| 4fc734665e | |||
| b8736e65b0 | |||
| b9bed7d9da | |||
| b2fc39d2dd | |||
| 7c0731edb2 | |||
| 8fe781fbe7 | |||
| 23932a26ff | |||
| 3ca4ca463c | |||
| 395f3ec638 | |||
| 964a901bd8 | |||
| a995ee17ee | |||
| 794d1c1ebe | |||
| 662fb282c1 | |||
| ffb6b2fb56 | |||
| 941c1c35f1 | |||
| 29a05984fe | |||
| 4038aabffa | |||
| 773efd0812 | |||
| 80881949fc | |||
| 2c8d87e064 | |||
| 33c67ce785 | |||
| ad4296d966 | |||
| 469b14a525 | |||
| 1caf0b6bee | |||
| 9f716dd590 | |||
| 914a934b6f | |||
| a4ada8ba9c | |||
| 40c974ab14 | |||
| 06f002b161 | |||
| 8226ff8b8e | |||
| d67e999dfb | |||
| a8e03b3a90 | |||
| 6f3e26c404 | |||
| 1c75ea613d | |||
| c8e1db2050 | |||
| 74ed28665d | |||
| 4ad0ca130d | |||
| b51dd3010d | |||
| 6e6f31943c | |||
| 66fee7e22a | |||
| beea571660 | |||
| 0c8a9a0e1a | |||
| fd83d3724a | |||
| 2fcfd75a14 | |||
| 2d40507547 | |||
| ecf9304811 | |||
| b9ab88776b | |||
| 00bf218304 | |||
| 95fbf168d1 | |||
| 51a27c0f1a | |||
| f02811f0bb | |||
| bcf78ebb18 | |||
| 3050dd1b47 | |||
| 1efdb4745a | |||
| d73f7dff45 | |||
| f047ad2628 | |||
| 049d3def80 | |||
| 00778aa239 | |||
| 6b123a0419 | |||
| 4079eea6b3 | |||
| d277ac2eb8 | |||
| 9deb123d04 | |||
| 1c2d2e8ba0 | |||
| 144bcc84ab | |||
| 693021c449 | |||
| dc818e1165 | |||
| e51174bf13 | |||
| 7f3f3dd3eb | |||
| d077966ff1 | |||
| 0df4ff800a | |||
| 6208b76afa | |||
| 70dac5ae82 | |||
| aafbd94439 | |||
| e732f8e579 | |||
| 9f67da6252 | |||
| b3a3c6a72e | |||
| e8cdabe129 | |||
| 3af71bee75 | |||
| f2724b2bbc | |||
| 38500669f6 | |||
| 862c9d8bb2 | |||
| 240d5896ec | |||
| 64ef084b91 | |||
| 8b27c3f064 | |||
| 8366622bed | |||
| d3de0066b0 | |||
| b7e5133b2e | |||
| 42c97c5db5 | |||
| e1f4f23f78 | |||
| 630280c7fb | |||
| 496a67c10e | |||
| 7dcfe5e03e | |||
| 9e83b8355e | |||
| 03726f7fbd | |||
| 75893ae9e7 | |||
| d9ca245917 | |||
| 3259aabdf3 | |||
| befeeb3689 | |||
| 79577c5d31 | |||
| b71d7c3f3c | |||
| fa4c7b7f1d | |||
| 652b83eb22 | |||
| 20cf7d5e3a | |||
| ded2518756 | |||
| b366f0352a | |||
| 76c2491a31 | |||
| ef3df93afe | |||
| 106f90aafa | |||
| 86e8088b38 | |||
| a654bdfed9 | |||
| 2c22c57e58 | |||
| a4dfa4d061 | |||
| bc0d8c4eea | |||
| 9b84fcad76 | |||
| f33ce173c9 | |||
| 181fc567d8 | |||
| 94207f8fb6 | |||
| 35a21532b7 | |||
| 1c97a6057b | |||
| 658a865c5b | |||
| f8cf28a788 | |||
| 4dd10fd964 | |||
| 26119c09d1 | |||
| 927ebd9986 | |||
| f5536ab43c | |||
| 9e6a9b9922 | |||
| bfa66a90c2 | |||
| cdd1227a30 | |||
| 19ecdb54bf | |||
| 30aa3eff4c | |||
| 8d39bd8abf | |||
| 472d076cca | |||
| 1ae0be13c2 | |||
| 159efdd429 | |||
| 4755a35b7d | |||
| b2f8b0b875 | |||
| 24cd70058d | |||
| e46ab43422 | |||
| 8a62a8c7f0 | |||
| b6c2f8b854 | |||
| 00ee090f4f | |||
| 544001f5a3 | |||
| 7175d0d0e3 | |||
| 010d9b6853 | |||
| 122ab074ca | |||
| e22bf9ac78 | |||
| 324cb6b358 | |||
| 80a2176e20 | |||
| 681affef59 | |||
| 0ca8b1df20 | |||
| 20fb626b78 | |||
| 7ea2c7f36e | |||
| 912cbdd468 | |||
| 0202663e93 | |||
| 159bbf11ac | |||
| 9d2cc8341c | |||
| 38520a1a73 | |||
| 470eb37d29 | |||
| 4baf25b3ce | |||
| eb193686a5 | |||
| 4bebe7830b | |||
| 146cbf7eaa | |||
| b8e356191f | |||
| f48244ce5e | |||
| ebba426c0c | |||
| aa11dfc162 | |||
| c6110e8b08 | |||
| 290b5049c2 | |||
| f8a07dd9fe | |||
| 6f39f10827 | |||
| c3a654b7c8 | |||
| e7293daf2a | |||
| c71d414a95 | |||
| 06d4e18cda | |||
| 966e01cf26 | |||
| 67afd9dc63 | |||
| 4175860af1 | |||
| 6fb90bda9a | |||
| 770dd2dcfd | |||
| 0ff7bba2e3 | |||
| 82b0929e4e | |||
| 7d2c6eeef8 | |||
| 6d8c1950a0 | |||
| 1a5ea22079 | |||
| 4f9eb2c6e4 | |||
| 43769fb676 | |||
| 170cd96646 | |||
| 1d18e60ef7 | |||
| ea8016c4c8 | |||
| c3d5e33e18 | |||
| 2f6b6fb7a1 | |||
| ea2518fcea | |||
| 7e67e525a5 | |||
| 0e001084ff | |||
| 85e3203918 | |||
| f95bc42cee | |||
| 9080d2c53c | |||
| 728f7e2a85 | |||
| 5f704065a7 | |||
| 64631bf2e6 | |||
| aa35b243f8 | |||
| 1cc9c9ca9d | |||
| dc48aadd26 | |||
| ebce2f7253 | |||
| d0e50fdcd0 | |||
| d88167318d | |||
| 0a75a3db6e | |||
| b643f0d322 | |||
| 01dd588a28 | |||
| 3d6dc3fe31 | |||
| 0c81e9fd25 | |||
| 5df80e1854 | |||
| ba9fb82f18 | |||
| b497f3e47f | |||
| 39b634e50a | |||
| cf28c1a276 | |||
| 92e41ac904 | |||
| d33cedda16 | |||
| 6838c97945 | |||
| f827a8e050 | |||
| a844138060 | |||
| 8ae9e94ecb | |||
| 1bd451d082 | |||
| c11a7d676f | |||
| 0827e88e21 | |||
| 1363cbd6b4 | |||
| 44a96a4c14 | |||
| 1cf10ab810 | |||
| ed3a33a063 | |||
| a268c29fb0 | |||
| adb286389c | |||
| 94533e5706 | |||
| 99d2c46a16 | |||
| 929ec6ba5a | |||
| 39ff3332a3 | |||
| 4c92a3ccc7 | |||
| dc0b856e9c | |||
| bb281f85e7 | |||
| 496e08a605 | |||
| 548a1348d9 | |||
| 9845570be8 | |||
| 35d35e6a7e | |||
| 5abf593e6b | |||
| 9efe60f294 | |||
| 8553b56e97 | |||
| a8f7e9cfde | |||
| 7b8a16b238 | |||
| d2695b04a7 | |||
| 6f3b8622ad | |||
| 97ac7634df | |||
| ef3846a7a6 | |||
| 93985804a9 | |||
| 533d9b7670 | |||
| 0d6fc2dce5 | |||
| addb1ae37d | |||
| f13852c179 | |||
| 5298672411 | |||
| 058d462fa7 | |||
| f91eb0e9ec | |||
| 861636c625 | |||
| e7423168fb | |||
| 4bcf6c17c8 | |||
| d506b8a9df | |||
| e0cf496f3c | |||
| a5221f320a | |||
| 18a2e4fbfc | |||
| 32d3cbb3aa | |||
| acc53ce6ad | |||
| 0f6d37ead5 | |||
| 11695ca6e2 | |||
| cce084ee89 | |||
| d935c245c0 | |||
| b871b98a57 | |||
| 1cb6bd4944 | |||
| 3abb3fefe6 | |||
| 8ed682941a | |||
| 44ce9c8288 | |||
| 2ff1b09ab7 | |||
| 976cd036da | |||
| 21d6db382d | |||
| fc7d2d2737 | |||
| c77b607e61 | |||
| ec22d2276e | |||
| 344dffbc54 | |||
| 7db5f361b0 | |||
| d494a69ef6 | |||
| 91212d9440 | |||
| b661887072 | |||
| 60b7b003fd | |||
| 6ba5404406 | |||
| 2b68136a20 | |||
| dc49b4d952 | |||
| 96f2e3bef5 | |||
| 70ce425e6a | |||
| 9e492c358c | |||
| 92c7ce5bec | |||
| 618356e481 | |||
| 1f4aa47193 | |||
| 528cedaa0c | |||
| 1622182737 | |||
| 36efe6c1a2 | |||
| 5081982e30 | |||
| 97d79eec80 | |||
| e4aeae0c73 | |||
| 7202bfafcd | |||
| 4cef752985 | |||
| d38f6ff401 | |||
| 8f6dac9536 | |||
| de5b8dc781 | |||
| 41834e6f4a | |||
| dbb42b5c85 | |||
| f012374f12 | |||
| 14e0b9c352 | |||
| 9ea52d818b | |||
| d518a64d93 | |||
| fe0af2c073 |
+12
-11
@@ -19,10 +19,10 @@ env:
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
|
||||
- JOB=unit BROWSER_PROVIDER=browserstack
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack
|
||||
# - JOB=unit BROWSER_PROVIDER=browserstack
|
||||
# - JOB=docs-e2e BROWSER_PROVIDER=browserstack
|
||||
# - JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack
|
||||
# - JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack
|
||||
global:
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
@@ -31,12 +31,12 @@ env:
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: "JOB=unit BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=docs-e2e BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack"
|
||||
#matrix:
|
||||
# allow_failures:
|
||||
# - env: "JOB=unit BROWSER_PROVIDER=browserstack"
|
||||
# - env: "JOB=docs-e2e BROWSER_PROVIDER=browserstack"
|
||||
# - env: "JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack"
|
||||
# - env: "JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack"
|
||||
|
||||
install:
|
||||
# Check the size of caches
|
||||
@@ -48,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
|
||||
@@ -61,6 +61,7 @@ script:
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
after_script:
|
||||
- ./scripts/travis/tear_down_browser_provider.sh
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
notifications:
|
||||
|
||||
+1019
-1
File diff suppressed because it is too large
Load Diff
+14
-5
@@ -19,7 +19,7 @@ Help us keep Angular open and inclusive. Please read and follow our [Code of Con
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
If you have questions about how to use AngularJS, please direct these to the [Google Group][groups]
|
||||
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc].
|
||||
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc] and [Gitter][gitter].
|
||||
|
||||
## <a name="issue"></a> Found an Issue?
|
||||
If you find a bug in the source code or a mistake in the documentation, you can help us by
|
||||
@@ -71,7 +71,7 @@ chances of your issue being dealt with quickly:
|
||||
* **Angular Version(s)** - is it a regression?
|
||||
* **Browsers and Operating System** - is this a problem with all browsers or only IE8?
|
||||
* **Reproduce the Error** - provide a live example (using [Plunker][plunker] or
|
||||
[JSFiddle][jsfiddle]) or a unambiguous set of steps.
|
||||
[JSFiddle][jsfiddle]) or an unambiguous set of steps.
|
||||
* **Related Issues** - has a similar issue been reported before?
|
||||
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
|
||||
causing the problem (line of code or commit)
|
||||
@@ -187,6 +187,8 @@ We have very precise rules over how our git commit messages can be formatted. T
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the AngularJS change log**.
|
||||
|
||||
The commit message formatting can be added using a typical git workflow or through the use of a CLI wizard ([Commitizen](https://github.com/commitizen/cz-cli)). To use the wizard, run `npm run commit` in your terminal after staging your changes in git.
|
||||
|
||||
### Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
@@ -199,8 +201,13 @@ format that includes a **type**, a **scope** and a **subject**:
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
to read on github as well as in various git tools.
|
||||
to read on GitHub as well as in various git tools.
|
||||
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
@@ -210,7 +217,7 @@ Must be one of the following:
|
||||
* **docs**: Documentation only changes
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
|
||||
semi-colons, etc)
|
||||
* **refactor**: A code change that neither fixes a bug or adds a feature
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **perf**: A code change that improves performance
|
||||
* **test**: Adding missing tests
|
||||
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
|
||||
@@ -228,13 +235,14 @@ The subject contains succinct description of the change:
|
||||
* no dot (.) at the end
|
||||
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
@@ -262,6 +270,7 @@ You can find out more detailed information about contributing in the
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[dev-doc]: https://docs.angularjs.org/guide
|
||||
[github]: https://github.com/angular/angular.js
|
||||
[gitter]: https://gitter.im/angular/angular.js
|
||||
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
|
||||
|
||||
+7
-3
@@ -115,7 +115,7 @@ module.exports = function(grunt) {
|
||||
files: { src: 'test/**/*.js' },
|
||||
},
|
||||
ng: {
|
||||
files: { src: files['angularSrc'] },
|
||||
files: { src: files['angularSrc'].concat('!src/angular.bind.js') },
|
||||
},
|
||||
ngAnimate: {
|
||||
files: { src: 'src/ngAnimate/**/*.js' },
|
||||
@@ -156,7 +156,11 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
jscs: {
|
||||
src: ['src/**/*.js', 'test/**/*.js'],
|
||||
src: [
|
||||
'src/**/*.js',
|
||||
'test/**/*.js',
|
||||
'!src/angular.bind.js' // we ignore this file since contains an early return statement
|
||||
],
|
||||
options: {
|
||||
config: ".jscsrc"
|
||||
}
|
||||
@@ -301,7 +305,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": {
|
||||
|
||||
@@ -21,7 +21,7 @@ piece of cake. Best of all?? It makes development fun!
|
||||
|
||||
Building AngularJS
|
||||
---------
|
||||
[Once you have your environment setup](http://docs.angularjs.org/misc/contribute) just run:
|
||||
[Once you have your environment set up](http://docs.angularjs.org/misc/contribute) just run:
|
||||
|
||||
grunt package
|
||||
|
||||
|
||||
Vendored
+11
-6
@@ -14,13 +14,14 @@ var angularFiles = {
|
||||
|
||||
'src/ng/anchorScroll.js',
|
||||
'src/ng/animate.js',
|
||||
'src/ng/asyncCallback.js',
|
||||
'src/ng/animateCss.js',
|
||||
'src/ng/browser.js',
|
||||
'src/ng/cacheFactory.js',
|
||||
'src/ng/compile.js',
|
||||
'src/ng/controller.js',
|
||||
'src/ng/document.js',
|
||||
'src/ng/exceptionHandler.js',
|
||||
'src/ng/forceReflow.js',
|
||||
'src/ng/http.js',
|
||||
'src/ng/httpBackend.js',
|
||||
'src/ng/interpolate.js',
|
||||
@@ -76,7 +77,10 @@ var angularFiles = {
|
||||
'src/ng/directive/script.js',
|
||||
'src/ng/directive/select.js',
|
||||
'src/ng/directive/style.js',
|
||||
'src/ng/directive/validators.js'
|
||||
'src/ng/directive/validators.js',
|
||||
'src/angular.bind.js',
|
||||
'src/publishExternalApis.js',
|
||||
'src/ngLocale/angular-locale_en-us.js'
|
||||
],
|
||||
|
||||
'angularLoader': [
|
||||
@@ -97,6 +101,7 @@ var angularFiles = {
|
||||
'src/ngAnimate/animateQueue.js',
|
||||
'src/ngAnimate/animateRunner.js',
|
||||
'src/ngAnimate/animation.js',
|
||||
'src/ngAnimate/ngAnimateSwap.js',
|
||||
'src/ngAnimate/module.js'
|
||||
],
|
||||
'ngCookies': [
|
||||
@@ -179,7 +184,6 @@ var angularFiles = {
|
||||
'bower_components/jquery/dist/jquery.js',
|
||||
'test/jquery_remove.js',
|
||||
'@angularSrc',
|
||||
'src/publishExternalApis.js',
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest'
|
||||
@@ -188,7 +192,8 @@ var angularFiles = {
|
||||
'karmaExclude': [
|
||||
'test/jquery_alias.js',
|
||||
'src/angular-bootstrap.js',
|
||||
'src/ngScenario/angular-bootstrap.js'
|
||||
'src/ngScenario/angular-bootstrap.js',
|
||||
'src/angular.bind.js'
|
||||
],
|
||||
|
||||
'karmaScenario': [
|
||||
@@ -215,7 +220,6 @@ var angularFiles = {
|
||||
'bower_components/jquery/dist/jquery.js',
|
||||
'test/jquery_alias.js',
|
||||
'@angularSrc',
|
||||
'src/publishExternalApis.js',
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest'
|
||||
@@ -224,7 +228,8 @@ var angularFiles = {
|
||||
'karmaJqueryExclude': [
|
||||
'src/angular-bootstrap.js',
|
||||
'src/ngScenario/angular-bootstrap.js',
|
||||
'test/jquery_remove.js'
|
||||
'test/jquery_remove.js',
|
||||
'src/angular.bind.js'
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ var noArgs = function (fn) {
|
||||
|
||||
var identity = function (i) { return i; };
|
||||
|
||||
// like Q.all, but runs the comands in series
|
||||
// like Q.all, but runs the commands in series
|
||||
// useful for ensuring env state (like which branch is checked out)
|
||||
var allInSeries = function (fn) {
|
||||
return function (args) {
|
||||
|
||||
@@ -56,7 +56,7 @@ li.doc-example-live {
|
||||
}
|
||||
|
||||
div.syntaxhighlighter {
|
||||
padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars http://is.gd/gSMgC */
|
||||
padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars */
|
||||
}
|
||||
|
||||
/* TABS - tutorial environment navigation */
|
||||
|
||||
@@ -315,8 +315,13 @@ iframe.example {
|
||||
color:white;
|
||||
}
|
||||
|
||||
.search-results-group .search-results {
|
||||
padding: 0 5px 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.search-results-frame > .search-results-group:first-child > .search-results {
|
||||
border-right:1px solid #050505;
|
||||
border-right:1px solid #222;
|
||||
}
|
||||
|
||||
.search-results-group.col-group-api { width:30%; }
|
||||
@@ -325,10 +330,57 @@ iframe.example {
|
||||
.search-results-group.col-group-misc,
|
||||
.search-results-group.col-group-error { width:15%; float: right; }
|
||||
|
||||
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
|
||||
.search-results-group.col-group-api .search-results {
|
||||
-moz-column-count: 2;
|
||||
-ms-column-count: 2;
|
||||
-webkit-column-count: 2;
|
||||
column-count: 2;
|
||||
/* Prevent bullets in the second column from being hidden in Chrome and IE */
|
||||
-webkit-column-gap: 2em;
|
||||
-ms-column-gap: 2em;
|
||||
column-gap: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results-group .search-result {
|
||||
word-wrap: break-word;
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
hyphens: auto;
|
||||
-ms-column-break-inside: avoid;
|
||||
-webkit-column-break-inside: avoid;
|
||||
-moz-column-break-inside: avoid; /* Unsupported */
|
||||
column-break-inside: avoid;
|
||||
text-indent: -0.65em; /* Make sure line wrapped words are aligned vertically */
|
||||
}
|
||||
|
||||
@supports (-moz-column-count: 2) {
|
||||
.search-results-group .search-result {
|
||||
/* Prevents column breaks inside words in FF, but has adverse effects in IE11 and Chrome */
|
||||
overflow: hidden;
|
||||
padding-left: 1em; /* In FF the list item bullet is otherwise hidden */
|
||||
margin-left: -1em; /* offset the padding left */
|
||||
}
|
||||
}
|
||||
|
||||
.search-result:before {
|
||||
content: "\002D\00A0"; /* Dash and non-breaking space as List item type */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-results-group.col-group-api .search-result {
|
||||
width:48%;
|
||||
display:inline-block;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
|
||||
.search-results-group.col-group-api .search-result {
|
||||
width:auto;
|
||||
display: list-item;
|
||||
}
|
||||
}
|
||||
|
||||
.search-close {
|
||||
@@ -682,6 +734,11 @@ ul.events > li {
|
||||
padding-bottom:60px;
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
.search-results-frame > .search-results-group:first-child > .search-results {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.search-results-group {
|
||||
float:none!important;
|
||||
display:block!important;
|
||||
@@ -689,14 +746,42 @@ ul.events > li {
|
||||
border:0!important;
|
||||
padding:0!important;
|
||||
}
|
||||
|
||||
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
|
||||
.search-results-group .search-results {
|
||||
-moz-column-count: 2;
|
||||
-ms-column-count: 2;
|
||||
-webkit-column-count: 2;
|
||||
column-count: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results-group .search-result {
|
||||
display:inline-block!important;
|
||||
padding:0 5px;
|
||||
width:auto!important;
|
||||
text-indent: initial;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.search-results-group .search-result:after {
|
||||
content:", ";
|
||||
}
|
||||
|
||||
.search-results-group .search-result:before {
|
||||
content: "";
|
||||
}
|
||||
|
||||
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
|
||||
.search-results-group .search-result {
|
||||
display: list-item !important;
|
||||
}
|
||||
|
||||
.search-results-group .search-result:after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
padding-bottom:0px;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* global importScripts, onmessage: true, postMessage, lunr */
|
||||
|
||||
// Load up the lunr library
|
||||
importScripts('../components/lunr.js-0.4.2/lunr.min.js');
|
||||
importScripts('../components/lunr.js-0.5.12/lunr.min.js');
|
||||
|
||||
// Create the lunr index - the docs should be an array of object, each object containing
|
||||
// the path and search terms for a page
|
||||
|
||||
@@ -11,7 +11,15 @@ angular.module('search', [])
|
||||
var MIN_SEARCH_LENGTH = 2;
|
||||
if(q.length >= MIN_SEARCH_LENGTH) {
|
||||
docsSearch(q).then(function(hits) {
|
||||
var results = {};
|
||||
// Make sure the areas are always in the same order
|
||||
var results = {
|
||||
api: [],
|
||||
guide: [],
|
||||
tutorial: [],
|
||||
error: [],
|
||||
misc: []
|
||||
};
|
||||
|
||||
angular.forEach(hits, function(hit) {
|
||||
var area = hit.area;
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "AngularJS-docs-app",
|
||||
"dependencies": {
|
||||
"jquery": "2.1.1",
|
||||
"lunr.js": "0.4.3",
|
||||
"lunr.js": "0.5.12",
|
||||
"open-sans-fontface": "1.0.4",
|
||||
"google-code-prettify": "1.0.1",
|
||||
"bootstrap": "3.1.1"
|
||||
|
||||
@@ -42,7 +42,7 @@ module.exports = new Package('angularjs', [
|
||||
|
||||
readFilesProcessor.basePath = path.resolve(__dirname,'../..');
|
||||
readFilesProcessor.sourceFiles = [
|
||||
{ include: 'src/**/*.js', basePath: 'src' },
|
||||
{ include: 'src/**/*.js', exclude: 'src/angular.bind.js', basePath: 'src' },
|
||||
{ include: 'docs/content/**/*.ngdoc', basePath: 'docs/content' }
|
||||
];
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<li class="disabled"><a href="http://angularjs.org/">Why AngularJS?</a></li>
|
||||
<li><a href="http://www.youtube.com/user/angularjs">Watch</a></li>
|
||||
<li><a href="tutorial">Tutorial</a></li>
|
||||
<li><a href="http://builtwith.angularjs.org/">Case Studies</a></li>
|
||||
<li><a href="https://www.madewithangular.com/">Case Studies</a></li>
|
||||
<li><a href="https://github.com/angular/angular-seed">Seed App project template</a></li>
|
||||
<li><a href="misc/faq">FAQ</a></li>
|
||||
</ul>
|
||||
@@ -147,13 +147,13 @@
|
||||
<div class="search-results-container" ng-show="hasResults">
|
||||
<div class="container">
|
||||
<div class="search-results-frame">
|
||||
<div ng-repeat="(key, value) in results" class="search-results-group" ng-class="colClassName + ' col-group-' + key">
|
||||
<div ng-repeat="(key, value) in results track by key" class="search-results-group" ng-class="colClassName + ' col-group-' + key" ng-show="value.length > 0">
|
||||
<h4 class="search-results-group-heading">{{ key }}</h4>
|
||||
<div class="search-results">
|
||||
<div ng-repeat="item in value" class="search-result">
|
||||
- <a ng-click="hideResults()" ng-href="{{ item.path }}">{{ item.name }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="search-results">
|
||||
<!-- Do not insert a line break between li and a. Chrome will insert an actual line-break, which breaks the list item view.
|
||||
TODO: use a html minifier instead -->
|
||||
<li ng-repeat="item in value" class="search-result"><a ng-click="hideResults()" ng-href="{{ item.path }}">{{ item.name }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<a href="" ng-click="hideResults()" class="search-close">
|
||||
|
||||
@@ -8,7 +8,7 @@ but the required directive controller is not present on the current DOM element
|
||||
|
||||
To resolve this error ensure that there is no typo in the required controller name and that the required directive controller is present on the current element.
|
||||
|
||||
If the required controller is expected to be on a ancestor element, make sure that you prefix the controller name in the `require` definition with `^`.
|
||||
If the required controller is expected to be on an ancestor element, make sure that you prefix the controller name in the `require` definition with `^`.
|
||||
|
||||
If the required controller is optionally requested, use `?` or `^?` to specify that.
|
||||
|
||||
|
||||
@@ -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,45 @@
|
||||
@ngdoc error
|
||||
@name $http:legacy
|
||||
@fullName The `success` and `error` methods on the promise returned from `$http` have been disabled.
|
||||
@description
|
||||
|
||||
This error occurs when the legacy promise extensions (`success` and `error`)
|
||||
{@link $httpProvider#useLegacyPromiseExtensions legacy `$http` promise extensions} have been disabled.
|
||||
|
||||
To resolve this error, either turn on the legacy extensions by adding
|
||||
`$httpProvider.useLegacyPromiseExtensions(true);` to your application's configuration; or refactor you
|
||||
use of `$http` to use `.then()` rather than `.success()` and `.error()`.
|
||||
|
||||
For example if you code looked like this:
|
||||
|
||||
```js
|
||||
// Simple GET request example :
|
||||
$http.get('/someUrl').
|
||||
success(function(data, status, headers, config) {
|
||||
// This callback will be called asynchronously
|
||||
// when the response is available
|
||||
}).
|
||||
error(function(data, status, headers, config) {
|
||||
// called asynchronously if an error occurs
|
||||
// or server returns response with an error status.
|
||||
});
|
||||
```
|
||||
|
||||
then you would change it to look like:
|
||||
|
||||
```js
|
||||
// Simple GET request example :
|
||||
$http.get('/someUrl').
|
||||
then(function(response) {
|
||||
// (The response object contains the data, status, headers and config properties)
|
||||
// This callback will be called asynchronously
|
||||
// when the response is available.
|
||||
}, function(response) {
|
||||
// called asynchronously if an error occurs
|
||||
// or server returns response with an error status.
|
||||
});
|
||||
```
|
||||
|
||||
For more information, see the
|
||||
{@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`}
|
||||
documentation.
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sanitize:badparse
|
||||
@fullName Parsing Error while Sanitizing
|
||||
@description
|
||||
|
||||
This error occurs when the HTML string passed to '$sanitize' can't be parsed by the sanitizer.
|
||||
The error contains part of the html string that can't be parsed.
|
||||
|
||||
The parser is more strict than a typical browser parser, so it's possible that some obscure input would produce this error despite the string being recognized as valid HTML by a browser.
|
||||
|
||||
If a valid html code results in this error, please file a bug.
|
||||
@@ -0,0 +1,10 @@
|
||||
@ngdoc error
|
||||
@name $sanitize:noinert
|
||||
@fullName Can't create an inert html document
|
||||
@description
|
||||
|
||||
This error occurs when `$sanitize` sanitizer determines that `document.implementation.createHTMLDocument ` api is not supported by the current browser.
|
||||
|
||||
This api is necessary for safe parsing of HTML strings into DOM trees and without it the sanitizer can't sanitize the input.
|
||||
|
||||
The api is present in all supported browsers including IE 9.0, so the presence of this error usually indicates that Angular's `$sanitize` is being used on an unsupported platform.
|
||||
@@ -0,0 +1,13 @@
|
||||
@ngdoc error
|
||||
@name $sanitize:uinput
|
||||
@fullName Failed to sanitize html because the input is unstable
|
||||
@description
|
||||
|
||||
This error occurs when `$sanitize` sanitizer tries to check the input for possible mXSS payload and the verification
|
||||
errors due to the input mutating indefinitely. This could be a sign that the payload contains code exploiting an mXSS
|
||||
vulnerability in the browser.
|
||||
|
||||
mXSS attack exploit browser bugs that cause some browsers parse a certain html strings into DOM, which once serialized
|
||||
doesn't match the original input. These browser bugs can be exploited by attackers to create payload which looks
|
||||
harmless to sanitizers, but due to mutations caused by the browser are turned into dangerous code once processed after
|
||||
sanitization.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,52 @@
|
||||
@ngdoc error
|
||||
@name orderBy:notarray
|
||||
@fullName Value is not array-like
|
||||
@description
|
||||
|
||||
This error occurs when {@link ng.orderBy orderBy} is not passed an array-like value:
|
||||
```html
|
||||
<div ng-repeat="(key, value) in myObj | orderBy:someProp">
|
||||
{{ key }} : {{ value }}
|
||||
</div>
|
||||
```
|
||||
|
||||
`orderBy` must be used with an array-like value so a subset of items can be returned.
|
||||
The array can be initialized asynchronously and therefore `null` or `undefined` won't throw this error.
|
||||
|
||||
To use `orderBy` to order the properties of an object, you can create your own array based on that object:
|
||||
```js
|
||||
angular.module('aModule', [])
|
||||
.controller('aController', function($scope) {
|
||||
var myObj = {
|
||||
one: {id: 1, name: 'Some thing'},
|
||||
two: {id: 2, name: 'Another thing'},
|
||||
three: {id: 3, name: 'A third thing'}
|
||||
};
|
||||
|
||||
$scope.arrFromMyObj = Object.keys(myObj).map(function(key) {
|
||||
return myObj[key];
|
||||
});
|
||||
});
|
||||
```
|
||||
That can be used as:
|
||||
```html
|
||||
<label>
|
||||
Order by:
|
||||
<select ng-model="orderProp" ng-options="prop for prop in ['id', 'name']"></select>
|
||||
</label>
|
||||
<div ng-repeat="item in arrFromMyObj | orderBy:orderProp">
|
||||
[{{ item.id }}] {{ item.name }}
|
||||
</div>
|
||||
```
|
||||
|
||||
You could as well convert the object to an array using a filter such as
|
||||
[toArrayFilter](https://github.com/petebacondarwin/angular-toArrayFilter):
|
||||
```html
|
||||
<label>
|
||||
Order by:
|
||||
<select ng-model="orderProp" ng-options="prop for prop in ['id', 'name']"></select>
|
||||
</label>
|
||||
<div ng-repeat="item in myObj | toArray:false | orderBy:orderProp">
|
||||
[{{ item.id }}] {{ item.name }}
|
||||
</div>
|
||||
```
|
||||
@@ -301,7 +301,7 @@ it('should show example', inject(
|
||||
### Fallback for legacy browsers
|
||||
|
||||
For browsers that support the HTML5 history API, `$location` uses the HTML5 history API to write
|
||||
path and search. If the history API is not supported by a browser, `$location` supplies a Hasbang
|
||||
path and search. If the history API is not supported by a browser, `$location` supplies a Hashbang
|
||||
URL. This frees you from having to worry about whether the browser viewing your app supports the
|
||||
history API or not; the `$location` service makes this transparent to you.
|
||||
|
||||
@@ -356,15 +356,15 @@ legacy browsers and hashbang links in modern browser:
|
||||
|
||||
### Example
|
||||
|
||||
Here you can see two `$location` instances, both in **Html5 mode**, but on different browsers, so
|
||||
that you can see the differences. These `$location` services are connected to a fake browsers. Each
|
||||
input represents the address bar of the browser.
|
||||
Here you can see two `$location` instances that show the difference between **Html5 mode** and **Html5 Fallback mode**.
|
||||
Note that to simulate different levels of browser support, the `$location` instances are connected to
|
||||
a fakeBrowser service, which you don't have to set up in actual projects.
|
||||
|
||||
Note that when you type hashbang url into first browser (or vice versa) it doesn't rewrite /
|
||||
Note that when you type hashbang url into the first browser (or vice versa) it doesn't rewrite /
|
||||
redirect to regular / hashbang url, as this conversion happens only during parsing the initial URL
|
||||
= on page reload.
|
||||
|
||||
In these examples we use `<base href="/base/index.html" />`
|
||||
In these examples we use `<base href="/base/index.html" />`. The inputs represent the address bar of the browser.
|
||||
|
||||
#### Browser in HTML5 mode
|
||||
<example module="html5-mode" name="location-html5-mode">
|
||||
@@ -389,6 +389,7 @@ In these examples we use `<base href="/base/index.html" />`
|
||||
<file name="app.js">
|
||||
angular.module('html5-mode', ['fake-browser', 'address-bar'])
|
||||
|
||||
// Configure the fakeBrowser. Do not set these values in actual projects.
|
||||
.constant('initUrl', 'http://www.example.com/base/path?a=b#h')
|
||||
.constant('baseHref', '/base/index.html')
|
||||
.value('$sniffer', { history: true })
|
||||
@@ -538,6 +539,7 @@ In these examples we use `<base href="/base/index.html" />`
|
||||
<file name="app.js">
|
||||
angular.module('hashbang-mode', ['fake-browser', 'address-bar'])
|
||||
|
||||
// Configure the fakeBrowser. Do not set these values in actual projects.
|
||||
.constant('initUrl', 'http://www.example.com/base/index.html#!/path?a=b#h')
|
||||
.constant('baseHref', '/base/index.html')
|
||||
.value('$sniffer', { history: false })
|
||||
|
||||
@@ -23,9 +23,9 @@ angular.module('myApp', ['ngAria'])...
|
||||
###Using ngAria
|
||||
Most of what ngAria does is only visible "under the hood". To see the module in action, once you've
|
||||
added it as a dependency, you can test a few things:
|
||||
* Using your favorite element inspector, look for ngAria attributes in your own code.
|
||||
* Using your favorite element inspector, look for attributes added by ngAria in your own code.
|
||||
* Test using your keyboard to ensure `tabindex` is used correctly.
|
||||
* Fire up a screen reader such as VoiceOver to listen for ARIA support.
|
||||
* Fire up a screen reader such as VoiceOver or NVDA to check for ARIA support.
|
||||
[Helpful screen reader tips.](http://webaim.org/articles/screenreader_testing/)
|
||||
|
||||
##Supported directives
|
||||
@@ -41,8 +41,8 @@ Currently, ngAria interfaces with the following directives:
|
||||
|
||||
<h2 id="ngmodel">ngModel</h2>
|
||||
|
||||
Most of ngAria's heavy lifting happens in the {@link ngModel ngModel}
|
||||
directive. For elements using ngModel, special attention is paid by ngAria if that element also
|
||||
Much of ngAria's heavy lifting happens in the {@link ngModel ngModel}
|
||||
directive. For elements using ngModel, special attention is paid by ngAria if that element also
|
||||
has a role or type of `checkbox`, `radio`, `range` or `textbox`.
|
||||
|
||||
For those elements using ngModel, ngAria will dynamically bind and update the following ARIA
|
||||
@@ -134,10 +134,8 @@ attributes (if they have not been explicitly specified by the developer):
|
||||
|
||||
ngAria will also add `tabIndex`, ensuring custom elements with these roles will be reachable from
|
||||
the keyboard. It is still up to **you** as a developer to **ensure custom controls will be
|
||||
operable** from the keybard. Think of `ng-click` on a `<div>` or `<md-checkbox>`: you still need
|
||||
to bind `ng-keypress` to make it fully operable from the keyboard. As a rule, any time you create
|
||||
a widget involving user interaction, be sure to test it with your keyboard and at least one mobile
|
||||
and desktop screen reader (preferably more).
|
||||
accessible**. As a rule, any time you create a widget involving user interaction, be sure to test
|
||||
it with your keyboard and at least one mobile and desktop screen reader.
|
||||
|
||||
<h2 id="ngdisabled">ngDisabled</h2>
|
||||
|
||||
@@ -160,7 +158,7 @@ Becomes:
|
||||
```
|
||||
|
||||
>You can check whether a control is legitimately disabled for a screen reader by visiting
|
||||
[chrome://accessibility](chrome://accessibility).
|
||||
[chrome://accessibility](chrome://accessibility) and inspecting [the accessibility tree](http://www.paciellogroup.com/blog/2015/01/the-browser-accessibility-tree/).
|
||||
|
||||
<h2 id="ngshow">ngShow</h2>
|
||||
|
||||
@@ -210,16 +208,25 @@ The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redun
|
||||
`display: none`. See explanation for {@link guide/accessibility#ngshow ngShow} when overriding the default CSS.
|
||||
|
||||
<h2><span id="ngclick">ngClick</span> and <span id="ngdblclick">ngDblclick</span></h2>
|
||||
If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` if it isn't there
|
||||
already.
|
||||
If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` to any element not in
|
||||
a node blacklist:
|
||||
|
||||
To fix widespread accessibility problems with `ng-click` on div elements, ngAria will dynamically
|
||||
bind keypress by default as long as the element isn't an anchor, button, input or textarea.
|
||||
You can turn this functionality on or off with the `bindKeypress` configuration option. ngAria
|
||||
will also add the `button` role to communicate to users of assistive technologies.
|
||||
* Button
|
||||
* Anchor
|
||||
* Input
|
||||
* Textarea
|
||||
* Select
|
||||
* Details/Summary
|
||||
|
||||
For `ng-dblclick`, you must still manually add `ng-keypress` and role to non-interactive elements such
|
||||
as `div` or `taco-button` to enable keyboard access.
|
||||
To fix widespread accessibility problems with `ng-click` on `div` elements, ngAria will
|
||||
dynamically bind a keypress event by default as long as the element isn't in the node blacklist.
|
||||
You can turn this functionality on or off with the `bindKeypress` configuration option.
|
||||
|
||||
ngAria will also add the `button` role to communicate to users of assistive technologies. This can
|
||||
be disabled with the `bindRoleForClick` configuration option.
|
||||
|
||||
For `ng-dblclick`, you must still manually add `ng-keypress` and a role to non-interactive elements
|
||||
such as `div` or `taco-button` to enable keyboard access.
|
||||
|
||||
<h3>Example</h3>
|
||||
```html
|
||||
@@ -260,62 +267,18 @@ The attribute magic of ngAria may not work for every scenario. To disable indivi
|
||||
you can use the {@link ngAria.$ariaProvider#config config} method. Just keep in mind this will
|
||||
tell ngAria to ignore the attribute globally.
|
||||
|
||||
<example module="ngAria_ngDisabledExample" deps="angular-aria.js">
|
||||
<example module="ngAria_ngClickExample" deps="angular-aria.js">
|
||||
<file name="index.html">
|
||||
<style>
|
||||
[role=checkbox] {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
[role=checkbox] .icon:before {
|
||||
content: '\2610';
|
||||
display: inline-block;
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
speak: none;
|
||||
}
|
||||
[role=checkbox].active .icon:before {
|
||||
content: '\2611';
|
||||
}
|
||||
</style>
|
||||
<form ng-controller="formsController">
|
||||
<div ng-model="someModel" show-attrs>
|
||||
Div with ngModel and aria-invalid disabled
|
||||
<div ng-click="someFunction" show-attrs>
|
||||
<div> with ng-click and bindRoleForClick, tabindex set to false
|
||||
</div>
|
||||
<div role="checkbox" ng-model="checked" ng-class="{active: checked}"
|
||||
aria-label="Custom Checkbox" ng-click="toggleCheckbox()" some-checkbox show-attrs>
|
||||
<span class="icon" aria-hidden="true"></span>
|
||||
Custom Checkbox for comparison
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
angular.module('ngAria_ngDisabledExample', ['ngAria'], function config($ariaProvider) {
|
||||
angular.module('ngAria_ngClickExample', ['ngAria'], function config($ariaProvider) {
|
||||
$ariaProvider.config({
|
||||
ariaInvalid: false,
|
||||
tabindex: true
|
||||
bindRoleForClick: false,
|
||||
tabindex: false
|
||||
});
|
||||
})
|
||||
.controller('formsController', function($scope){
|
||||
$scope.checked = false;
|
||||
$scope.toggleCheckbox = function(){
|
||||
$scope.checked = !$scope.checked;
|
||||
}
|
||||
})
|
||||
.directive('someCheckbox', function(){
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function($scope, $el, $attrs) {
|
||||
$el.on('keypress', function(event){
|
||||
event.preventDefault();
|
||||
if(event.keyCode === 32 || event.keyCode === 13){
|
||||
$scope.toggleCheckbox();
|
||||
$scope.$apply();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.directive('showAttrs', function() {
|
||||
return function(scope, el, attrs) {
|
||||
var pre = document.createElement('pre');
|
||||
|
||||
@@ -8,22 +8,22 @@
|
||||
This section briefly touches on all of the important parts of AngularJS using a simple example.
|
||||
For a more in-depth explanation, see the {@link tutorial/ tutorial}.
|
||||
|
||||
| Concept | Description |
|
||||
|------------------|------------------------------------------|
|
||||
|{@link concepts#template Template} | HTML with additional markup |
|
||||
|{@link concepts#directive Directives} | extend HTML with custom attributes and elements |
|
||||
|{@link concepts#model Model} | the data shown to the user in the view and with which the user interacts |
|
||||
|{@link concepts#scope Scope} | context where the model is stored so that controllers, directives and expressions can access it |
|
||||
|{@link concepts#expression Expressions} | access variables and functions from the scope |
|
||||
|{@link concepts#compiler Compiler} | parses the template and instantiates directives and expressions |
|
||||
|{@link concepts#filter Filter} | formats the value of an expression for display to the user |
|
||||
|{@link concepts#view View} | what the user sees (the DOM) |
|
||||
|{@link concepts#databinding Data Binding} | sync data between the model and the view |
|
||||
|{@link concepts#controller Controller} | the business logic behind views |
|
||||
|{@link concepts#di Dependency Injection} | Creates and wires objects and functions |
|
||||
|{@link concepts#injector Injector} | dependency injection container |
|
||||
|{@link concepts#module Module} | a container for the different parts of an app including controllers, services, filters, directives which configures the Injector |
|
||||
|{@link concepts#service Service} | reusable business logic independent of views |
|
||||
| Concept | Description |
|
||||
|--------------------------------------------|--------------------------------------------------------------------------|
|
||||
|{@link concepts#template Template} | HTML with additional markup |
|
||||
|{@link concepts#directive Directives} | extend HTML with custom attributes and elements |
|
||||
|{@link concepts#model Model} | the data shown to the user in the view and with which the user interacts |
|
||||
|{@link concepts#scope Scope} | context where the model is stored so that controllers, directives and expressions can access it |
|
||||
|{@link concepts#expression Expressions} | access variables and functions from the scope |
|
||||
|{@link concepts#compiler Compiler} | parses the template and instantiates directives and expressions |
|
||||
|{@link concepts#filter Filter} | formats the value of an expression for display to the user |
|
||||
|{@link concepts#view View} | what the user sees (the DOM) |
|
||||
|{@link concepts#databinding Data Binding} | sync data between the model and the view |
|
||||
|{@link concepts#controller Controller} | the business logic behind views |
|
||||
|{@link concepts#di Dependency Injection} | Creates and wires objects and functions |
|
||||
|{@link concepts#injector Injector} | dependency injection container |
|
||||
|{@link concepts#module Module} | a container for the different parts of an app including controllers, services, filters, directives which configures the Injector |
|
||||
|{@link concepts#service Service} | reusable business logic independent of views |
|
||||
|
||||
|
||||
## A first example: Data binding
|
||||
@@ -334,9 +334,9 @@ The following example shows how this is done with Angular:
|
||||
var refresh = function() {
|
||||
var url = YAHOO_FINANCE_URL_PATTERN.
|
||||
replace('PAIRS', 'USD' + currencies.join('","USD'));
|
||||
return $http.jsonp(url).success(function(data) {
|
||||
return $http.jsonp(url).then(function(response) {
|
||||
var newUsdToForeignRates = {};
|
||||
angular.forEach(data.query.results.rate, function(rate) {
|
||||
angular.forEach(response.data.query.results.rate, function(rate) {
|
||||
var currency = rate.id.substring(3,6);
|
||||
newUsdToForeignRates[currency] = window.parseFloat(rate.Rate);
|
||||
});
|
||||
@@ -348,8 +348,7 @@ The following example shows how this is done with Angular:
|
||||
|
||||
return {
|
||||
currencies: currencies,
|
||||
convert: convert,
|
||||
refresh: refresh
|
||||
convert: convert
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
|
||||
# Understanding Controllers
|
||||
|
||||
In Angular, a Controller is a JavaScript **constructor function** that is used to augment the
|
||||
In Angular, a Controller is defined by a JavaScript **constructor function** that is used to augment the
|
||||
{@link scope Angular Scope}.
|
||||
|
||||
When a Controller is attached to the DOM via the {@link ng.directive:ngController ng-controller}
|
||||
directive, Angular will instantiate a new Controller object, using the specified Controller's
|
||||
**constructor function**. A new **child scope** will be available as an injectable parameter to the
|
||||
Controller's constructor function as `$scope`.
|
||||
**constructor function**. A new **child scope** will be created and made available as an injectable
|
||||
parameter to the Controller's constructor function as `$scope`.
|
||||
|
||||
If the controller has been attached using the `controller as` syntax then the controller instance will
|
||||
be assigned to a property on the new scope.
|
||||
|
||||
Use controllers to:
|
||||
|
||||
@@ -106,7 +109,7 @@ needed for a single view.
|
||||
|
||||
The most common way to keep Controllers slim is by encapsulating work that doesn't belong to
|
||||
controllers into services and then using these services in Controllers via dependency injection.
|
||||
This is discussed in the {@link di Dependency Injection} {@link services
|
||||
This is discussed in the {@link di Dependency Injection} and {@link services
|
||||
Services} sections of this guide.
|
||||
|
||||
|
||||
@@ -162,7 +165,7 @@ scope is augmented (managed) by the `SpicyController` Controller.
|
||||
starts with capital letter and ends with "Controller".
|
||||
- Assigning a property to `$scope` creates or updates the model.
|
||||
- Controller methods can be created through direct assignment to scope (see the `chiliSpicy` method)
|
||||
- The Controller methods and properties are available in the template (for the `<div>` element and
|
||||
- The Controller methods and properties are available in the template (for both the `<div>` element and
|
||||
its children).
|
||||
|
||||
## Spicy Arguments Example
|
||||
@@ -302,7 +305,7 @@ describe('myController function', function() {
|
||||
```
|
||||
|
||||
|
||||
If you need to test a nested Controller you need to create the same scope hierarchy
|
||||
If you need to test a nested Controller you must create the same scope hierarchy
|
||||
in your test that exists in the DOM:
|
||||
|
||||
```js
|
||||
|
||||
@@ -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');
|
||||
```
|
||||
|
||||
|
||||
@@ -19,8 +19,9 @@ how to implement them.
|
||||
## What are Directives?
|
||||
|
||||
At a high level, directives are markers on a DOM element (such as an attribute, element
|
||||
name, comment or CSS class) that tell AngularJS's **HTML compiler** ({@link ng.$compile `$compile`}) to
|
||||
attach a specified behavior to that DOM element or even transform the DOM element and its children.
|
||||
name, comment or CSS class) that tell AngularJS's **HTML compiler** ({@link ng.$compile `$compile`})
|
||||
to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform
|
||||
the DOM element and its children.
|
||||
|
||||
Angular comes with a set of these directives built-in, like `ngBind`, `ngModel`, and `ngClass`.
|
||||
Much like you create controllers and services, you can create your own directives for Angular to use.
|
||||
@@ -30,7 +31,7 @@ When Angular {@link guide/bootstrap bootstraps} your application, the
|
||||
<div class="alert alert-info">
|
||||
**What does it mean to "compile" an HTML template?**
|
||||
|
||||
For AngularJS, "compilation" means attaching event listeners to the HTML to make it interactive.
|
||||
For AngularJS, "compilation" means attaching directives to the HTML to make it interactive.
|
||||
The reason we use the term "compile" is that the recursive process of attaching directives
|
||||
mirrors the process of compiling source code in
|
||||
[compiled programming languages](http://en.wikipedia.org/wiki/Compiled_languages).
|
||||
@@ -42,18 +43,27 @@ mirrors the process of compiling source code in
|
||||
Before we can write a directive, we need to know how Angular's {@link guide/compiler HTML compiler}
|
||||
determines when to use a given directive.
|
||||
|
||||
In the following example, we say that the `<input>` element **matches** the `ngModel` directive.
|
||||
Similar to the terminology used when an [element **matches** a selector](https://developer.mozilla.org/en-US/docs/Web/API/Element.matches), we say an element **matches** a
|
||||
directive when the directive is part of its declaration.
|
||||
|
||||
In the following example, we say that the `<input>` element **matches** the `ngModel` directive
|
||||
|
||||
```html
|
||||
<input ng-model="foo">
|
||||
```
|
||||
|
||||
The following also **matches** `ngModel`:
|
||||
The following `<input>` element also **matches** `ngModel`:
|
||||
|
||||
```html
|
||||
<input data-ng-model="foo">
|
||||
```
|
||||
|
||||
And the following <person> element **matches** the `person` directive:
|
||||
|
||||
```html
|
||||
<person>{{name}}</person>
|
||||
```
|
||||
|
||||
### Normalization
|
||||
|
||||
Angular **normalizes** an element's tag and attribute name to determine which elements match which
|
||||
@@ -577,14 +587,24 @@ want to reuse throughout your app.
|
||||
In this example we will build a directive that displays the current time.
|
||||
Once a second, it updates the DOM to reflect the current time.
|
||||
|
||||
Directives that want to modify the DOM typically use the `link` option.
|
||||
`link` takes a function with the following signature, `function link(scope, element, attrs) { ... }`
|
||||
where:
|
||||
Directives that want to modify the DOM typically use the `link` option to register DOM listeners
|
||||
as well as update the DOM. It is executed after the template has been cloned and is where
|
||||
directive logic will be put.
|
||||
|
||||
`link` takes a function with the following signature,
|
||||
`function link(scope, element, attrs, controller, transcludeFn) { ... }`, where:
|
||||
|
||||
* `scope` is an Angular scope object.
|
||||
* `element` is the jqLite-wrapped element that this directive matches.
|
||||
* `attrs` is a hash object with key-value pairs of normalized attribute names and their
|
||||
corresponding attribute values.
|
||||
* `controller` is the directive's required controller instance(s) or its own controller (if any).
|
||||
The exact value depends on the directive's require property.
|
||||
* `transcludeFn` is a transclude linking function pre-bound to the correct transclusion scope.
|
||||
|
||||
<div class="alert alert-info">
|
||||
For more details on the `link` option refer to the {@link ng.$compile#-link- `$compile` API} page.
|
||||
</div>
|
||||
|
||||
In our `link` function, we want to update the displayed time once a second, or whenever a user
|
||||
changes the time formatting string that our directive binds to. We will use the `$interval` service
|
||||
@@ -892,7 +912,7 @@ to which tab is active.
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
scope: {},
|
||||
controller: function($scope) {
|
||||
controller: ['$scope', function($scope) {
|
||||
var panes = $scope.panes = [];
|
||||
|
||||
$scope.select = function(pane) {
|
||||
@@ -908,7 +928,7 @@ to which tab is active.
|
||||
}
|
||||
panes.push(pane);
|
||||
};
|
||||
},
|
||||
}],
|
||||
templateUrl: 'my-tabs.html'
|
||||
};
|
||||
})
|
||||
|
||||
@@ -70,7 +70,7 @@ You can try evaluating different expressions here:
|
||||
<ul>
|
||||
<li ng-repeat="expr in exprs track by $index">
|
||||
[ <a href="" ng-click="removeExp($index)">X</a> ]
|
||||
<tt>{{expr}}</tt> => <span ng-bind="$parent.$eval(expr)"></span>
|
||||
<code>{{expr}}</code> => <span ng-bind="$parent.$eval(expr)"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -141,6 +141,9 @@ provide mockable access to globals.
|
||||
}
|
||||
element(by.css('[ng-click="greet()"]')).click();
|
||||
|
||||
// We need to give the browser time to display the alert
|
||||
browser.wait(protractor.ExpectedConditions.alertIsPresent(), 1000);
|
||||
|
||||
var alertDialog = browser.switchTo().alert();
|
||||
|
||||
expect(alertDialog.getText()).toEqual('Hello World');
|
||||
@@ -344,4 +347,4 @@ When using a directive that takes an expression:
|
||||
<ul>
|
||||
<li ng-repeat="item in ::items | orderBy:'name'">{{item.name}};</li>
|
||||
</ul>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ for other directives to augment its behavior.
|
||||
<input type="button" ng-click="reset()" value="Reset" />
|
||||
<input type="submit" ng-click="update(user)" value="Save" />
|
||||
</form>
|
||||
<pre>form = {{user | json}}</pre>
|
||||
<pre>user = {{user | json}}</pre>
|
||||
<pre>master = {{master | json}}</pre>
|
||||
</div>
|
||||
|
||||
@@ -95,6 +95,8 @@ and failing to satisfy its validity.
|
||||
<input type="button" ng-click="reset()" value="Reset" />
|
||||
<input type="submit" ng-click="update(user)" value="Save" />
|
||||
</form>
|
||||
<pre>user = {{user | json}}</pre>
|
||||
<pre>master = {{master | json}}</pre>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
@@ -183,6 +185,8 @@ didn't interact with a control
|
||||
<input type="button" ng-click="reset(form)" value="Reset" />
|
||||
<input type="submit" ng-click="update(user)" value="Save" />
|
||||
</form>
|
||||
<pre>user = {{user | json}}</pre>
|
||||
<pre>master = {{master | json}}</pre>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
@@ -379,7 +383,7 @@ In the following example we create two directives:
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
var usernames = ['Jim', 'John', 'Jill', 'Jackie'];
|
||||
var usernames = ['Jim', 'John', 'Jill', 'Jackie'];
|
||||
|
||||
ctrl.$asyncValidators.username = function(modelValue, viewValue) {
|
||||
|
||||
|
||||
@@ -156,8 +156,94 @@ The syntax extension is based on a subset of the ICU MessageFormat syntax that c
|
||||
gender selections. Please refer to the links in the “Further Reading” section at the bottom of this
|
||||
section.
|
||||
|
||||
You may find it helpful to play with our [Plnkr Example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview)
|
||||
as you read the examples below.
|
||||
You may find it helpful to play with the following example as you read the explanations below:
|
||||
|
||||
<example name="message-format-example" module="messageFormatExample" deps="angular-message-format.js">
|
||||
<file name="index.html">
|
||||
<div ng-controller="ckCtrl">
|
||||
<b>Set number of recipients</b>
|
||||
<button ng-click="setNumRecipients(0)">None</button>
|
||||
<button ng-click="setNumRecipients(1)">One</button>
|
||||
<button ng-click="setNumRecipients(2)">Two</button>
|
||||
<button ng-click="setNumRecipients(3)">Three</button>
|
||||
|
||||
|
||||
<br><br>
|
||||
<b>Sender's</b> name: <input ng-model="sender.name">
|
||||
|
||||
<br><br><b>Recipients</b><br>
|
||||
<div ng-repeat="recipient in recipients">
|
||||
Name: <input ng-model="recipient.name">
|
||||
Gender: <button ng-click="setGender(recipient, 'male')">male</button>
|
||||
<button ng-click="setGender(recipient, 'female')">female</button>
|
||||
<button ng-click="setGender(recipient, 'other')">other</button>
|
||||
</div>
|
||||
|
||||
<br><br><b>Message</b><br>
|
||||
{{recipients.length, plural, offset:1
|
||||
=0 {You ({{sender.name}}) gave no gifts}
|
||||
=1 { {{ recipients[0].gender, select,
|
||||
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) a gift.}
|
||||
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) a gift.}
|
||||
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) a gift.}
|
||||
}}
|
||||
}
|
||||
one { {{ recipients[0].gender, select,
|
||||
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) and one other person a gift.}
|
||||
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) and one other person a gift.}
|
||||
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) and one other person a gift.}
|
||||
}}
|
||||
}
|
||||
other {You ({{sender.name}}) gave {{recipients.length}} people gifts. }
|
||||
}}
|
||||
|
||||
<br><br><b>In an attribute</b><br>
|
||||
<div attrib="{{recipients.length, plural, offset:1
|
||||
=0 {You ({{sender.name}}) gave no gifts}
|
||||
=1 { {{ recipients[0].gender, select,
|
||||
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) a gift.}
|
||||
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) a gift.}
|
||||
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) a gift.}
|
||||
}}
|
||||
}
|
||||
one { {{ recipients[0].gender, select,
|
||||
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) and one other person a gift.}
|
||||
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) and one other person a gift.}
|
||||
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) and one other person a gift.}
|
||||
}}
|
||||
}
|
||||
other {You ({{sender.name}}) gave {{recipients.length}} people gifts. }
|
||||
}}">
|
||||
This div has an attribute interpolated with messageformat. Use the DOM inspector to check it out.
|
||||
</div>
|
||||
</div>
|
||||
</file>
|
||||
<file name="app.js">
|
||||
function Person(name, gender) {
|
||||
this.name = name;
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
angular.module('messageFormatExample', ['ngMessageFormat'])
|
||||
.controller('ckCtrl', function ($scope, $injector, $parse) {
|
||||
var people = [ new Person("Alice", "female"),
|
||||
new Person("Bob", "male"),
|
||||
new Person("Charlie", "male") ];
|
||||
|
||||
$scope.sender = new Person("Harry Potter", "male");
|
||||
$scope.recipients = people.slice();
|
||||
|
||||
$scope.setNumRecipients = function(n) {
|
||||
n = n > people.length ? people.length : n;
|
||||
$scope.recipients = people.slice(0, n);
|
||||
};
|
||||
|
||||
$scope.setGender = function(person, gender) {
|
||||
person.gender = gender;
|
||||
};
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
|
||||
### Plural Syntax
|
||||
|
||||
@@ -333,9 +419,9 @@ allows you to nest plural and gender expressions in any order.
|
||||
Please note that if these are intended to reach a translator and be translated, it is recommended
|
||||
that the messages appear as a whole and not be split up.
|
||||
|
||||
### More complex example that demonstrates nesting
|
||||
### Demonstration of nesting
|
||||
|
||||
This is taken from the [plunker example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview) linked to earlier.
|
||||
This is taken from the above example.
|
||||
|
||||
```text
|
||||
{{recipients.length, plural, offset:1
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -170,6 +170,25 @@ other inline messages situated as children within the `ngMessages` container dir
|
||||
Depending on where the `ngMessagesInclude` directive is placed it will be prioritized inline with the other messages
|
||||
before and after it.
|
||||
|
||||
Also due to [c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
|
||||
it is no longer possible to use interpolation inside the `ngMessages` attribute expression. This technique
|
||||
is generally not recommended, and can easily break when a directive implementation changes. In cases
|
||||
where a simple expression is not possible, you can delegate accessing the object to a function:
|
||||
|
||||
```html
|
||||
<div ng-messages="ctrl.form['field_{{$index}}'].$error">...</div>
|
||||
```
|
||||
would become
|
||||
```html
|
||||
<div ng-messages="ctrl.getMessages($index)">...</div>
|
||||
```
|
||||
where `ctrl.getMessages()`
|
||||
```javascript
|
||||
ctrl.getMessages = function($index) {
|
||||
return ctrl.form['field_' + $index].$error;
|
||||
}
|
||||
```
|
||||
|
||||
### ngOptions
|
||||
|
||||
The `ngOptions` directive has also been refactored and as a result some long-standing bugs
|
||||
@@ -189,13 +208,18 @@ But in practice this is not what people want and so this change iterates over pr
|
||||
in the order they are returned by Object.keys(obj), which is almost always the order
|
||||
in which the properties were defined.
|
||||
|
||||
Also due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
|
||||
setting the ngOptions attribute expression after the element is compiled, will no longer trigger the ngOptions behavior.
|
||||
This worked previously because the ngOptions logic was part of the select directive, while
|
||||
it is now implemented in the ngOptions directive itself.
|
||||
|
||||
### select
|
||||
|
||||
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
|
||||
the `select` directive will now use strict comparison of the `ngModel` scope value against `option`
|
||||
values to determine which option is selected. This means `Number` scope values will not be matched
|
||||
against numeric option strings.
|
||||
values to determine which option is selected. This means non-string scope values (such as `Number` or `Boolean`)
|
||||
will not be matched against equivalent option strings (such as the strings `"123"`, `"true"` or `"false"`).
|
||||
|
||||
In Angular 1.3.x, setting `scope.x = 200` would select the option with the value 200 in the following `select`:
|
||||
|
||||
```
|
||||
@@ -206,7 +230,8 @@ In Angular 1.3.x, setting `scope.x = 200` would select the option with the value
|
||||
```
|
||||
|
||||
In Angular 1.4.x, the 'unknown option' will be selected.
|
||||
To remedy this, you can simply initialize the model as a string: `scope.x = '200'`, or if you want to
|
||||
|
||||
To remedy this, you can initialize the model as a string: `scope.x = '200'`, or if you want to
|
||||
keep the model as a `Number`, you can do the conversion via `$formatters` and `$parsers` on `ngModel`:
|
||||
|
||||
```js
|
||||
@@ -248,7 +273,7 @@ is marked as optional and the attribute is not specified, no function will be ad
|
||||
|
||||
Due to [62d514b](https://github.com/angular/angular.js/commit/62d514b06937cc7dd86e973ea11165c88343b42d),
|
||||
returning an object from a controller constructor function will now override the scope. Views that use the
|
||||
controllerAs method will no longer get the this reference, but the returned object.
|
||||
controllerAs method will no longer get the this reference, but the returned object.
|
||||
|
||||
|
||||
## Cookies (`ngCookies`)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -44,7 +44,7 @@ and {@link angular.reloadWithDebugInfo `angular.reloadWithDebugInfo`}.
|
||||
|
||||
## Strict DI Mode
|
||||
|
||||
Using strict di mode in your production application will throw errors when a injectable
|
||||
Using strict di mode in your production application will throw errors when an injectable
|
||||
function is not
|
||||
{@link di#dependency-annotation annotated explicitly}. Strict di mode is intended to help
|
||||
you make sure that your code will work when minified. However, it also will force you to
|
||||
|
||||
@@ -391,7 +391,7 @@ implementing custom event callbacks, or when working with third-party library ca
|
||||
5. The {@link ng.$rootScope.Scope#$watch $watch} list is a set of expressions
|
||||
which may have changed since last iteration. If a change is detected then the `$watch`
|
||||
function is called which typically updates the DOM with the new value.
|
||||
6. Once the Angular {@link ng.$rootScope.Scope#$digest $digest} loop finishes
|
||||
6. Once the Angular {@link ng.$rootScope.Scope#$digest $digest} loop finishes,
|
||||
the execution leaves the Angular and JavaScript context. This is followed by the browser
|
||||
re-rendering the DOM to reflect any changes.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
JavaScript is a dynamically typed language which comes with great power of expression, but it also
|
||||
comes with almost no help from the compiler. For this reason we feel very strongly that any code
|
||||
written in JavaScript needs to come with a strong set of tests. We have built many features into
|
||||
Angular which makes testing your Angular applications easy. So there is no excuse for not testing.
|
||||
Angular which make testing your Angular applications easy. With Angular, there is no excuse for not testing.
|
||||
|
||||
## Separation of Concerns
|
||||
|
||||
@@ -20,13 +20,13 @@ related pieces such as the DOM elements, or making any XHR calls to fetch the da
|
||||
|
||||
While this may seem obvious it can be very difficult to call an individual function on a
|
||||
typical project. The reason is that the developers often mix concerns resulting in a
|
||||
piece of code which does everything. It makes an XHR request, it sorts the response data and then it
|
||||
piece of code which does everything. It makes an XHR request, it sorts the response data, and then it
|
||||
manipulates the DOM.
|
||||
|
||||
With Angular we try to make it easy for you to do the right thing, and so we
|
||||
provide dependency injection for your XHR requests, which can be mocked, and we provide abstractions which
|
||||
allow you to test your model without having to resort to manipulating the DOM. The test can then
|
||||
assert that the data has been sorted without having to create or look at the state of the DOM or
|
||||
With Angular, we try to make it easy for you to do the right thing. For your XHR requests, we
|
||||
provide dependency injection, so your requests can be simulated. For the DOM, we abstract it, so you can
|
||||
test your model without having to manipulate the DOM directly. Your tests can then
|
||||
assert that the data has been sorted without having to create or look at the state of the DOM or to
|
||||
wait for any XHR requests to return data. The individual sort function can be tested in isolation.
|
||||
|
||||
## With great power comes great responsibility
|
||||
|
||||
@@ -15,14 +15,14 @@ development.
|
||||
production.
|
||||
|
||||
To point your code to an angular script on the Google CDN server, use the following template. This
|
||||
example points to the minified version 1.3.14:
|
||||
example points to the minified version 1.4.5:
|
||||
|
||||
```
|
||||
<!doctype html>
|
||||
<html ng-app>
|
||||
<head>
|
||||
<title>My Angular App</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
|
||||
@@ -86,9 +86,15 @@ Yes. See instructions in {@link downloading}.
|
||||
|
||||
### What browsers does Angular work with?
|
||||
|
||||
We run our extensive test suite against the following browsers: Safari, Chrome, Firefox, Opera 15,
|
||||
IE9 and mobile browsers (Android, Chrome Mobile, iOS Safari). See {@link guide/ie Internet
|
||||
Explorer Compatibility} for more details on supporting legacy IE browsers.
|
||||
We run our extensive test suite against the following browsers: the latest versions of Chrome,
|
||||
Firefox, Safari, and Safari for iOs, as well as Internet Explorer versions 9-11. See {@link guide/ie
|
||||
Internet Explorer Compatibility} for more details on supporting legacy IE browsers.
|
||||
|
||||
If a browser is untested, it doesn't mean it won't work; for example, older Android (2.3.x)
|
||||
is supported in the sense that we avoid the dot notation for reserved words as property names,
|
||||
but we don't actively test changes against it. You can also expect browsers to work that share
|
||||
a large part of their codebase with a browser we test, such as Opera > version 12
|
||||
(uses the Blink engine), or the various Firefox derivatives.
|
||||
|
||||
|
||||
### What's Angular's performance like?
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
<ul doc-tutorial-nav="0"></ul>
|
||||
|
||||
|
||||
You are now ready to build the AngularJS phonecat app. In this step, you will become familiar
|
||||
with the most important source code files, learn how to start the development servers bundled with
|
||||
In this step of the tutorial, you will become familiar with the most important source code files of
|
||||
the AngularJS phonecat app. You will also learn how to start the development servers bundled with
|
||||
angular-seed, and run the application in the browser.
|
||||
|
||||
Before you continue, make sure you have set up your development environment and installed all necessary
|
||||
dependencies, as described in {@link tutorial/index#get-started Get Started}.
|
||||
|
||||
In `angular-phonecat` directory, run this command:
|
||||
In the `angular-phonecat` directory, run this command:
|
||||
|
||||
```
|
||||
git checkout -f step-0
|
||||
|
||||
@@ -195,8 +195,19 @@ to ensure that Karma and its necessary plugins are installed. You can do this by
|
||||
|
||||
To run the tests, and then watch the files for changes: `npm test`.
|
||||
|
||||
* Karma will start a new instance of Chrome browser automatically. Just ignore it and let it run in
|
||||
the background. Karma will use this browser for test execution.
|
||||
* Karma will start new instances of Chrome and Firefox browsers automatically. Just ignore them and
|
||||
let them run in the background. Karma will use these browsers for test execution.
|
||||
* If you only have one of the browsers installed on your machine (either Chrome or Firefox), make
|
||||
sure to update the karma configuration file before running the test. Locate the configuration file
|
||||
in `test/karma.conf.js`, then update the `browsers` property.
|
||||
|
||||
E.g. if you only have Chrome installed:
|
||||
<pre>
|
||||
...
|
||||
browsers: ['Chrome'],
|
||||
...
|
||||
</pre>
|
||||
|
||||
* You should see the following or similar output in the terminal:
|
||||
|
||||
<pre>
|
||||
@@ -250,7 +261,7 @@ browser is limited, which results in your karma tests running extremely slow.
|
||||
<tr><th>row number</th></tr>
|
||||
<tr ng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>{{i+1}}</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
Extra points: try and make an 8x8 table using an additional `ng-repeat`.
|
||||
|
||||
* Make the unit test fail by changing `expect(scope.phones.length).toBe(3)` to instead use `toBe(4)`.
|
||||
|
||||
@@ -75,7 +75,7 @@ __`test/e2e/scenarios.js`__:
|
||||
query.sendKeys('nexus');
|
||||
element.all(by.css('.phones li a')).first().click();
|
||||
browser.getLocationAbsUrl().then(function(url) {
|
||||
expect(url.split('#')[1]).toBe('/phones/nexus-s');
|
||||
expect(url).toBe('/phones/nexus-s');
|
||||
});
|
||||
});
|
||||
...
|
||||
|
||||
@@ -33,17 +33,17 @@ We are using [Bower][bower] to install client-side dependencies. This step upda
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"angular": "~1.3.0",
|
||||
"angular-mocks": "~1.3.0",
|
||||
"jquery": "2.1.1",
|
||||
"angular": "1.4.x",
|
||||
"angular-mocks": "1.4.x",
|
||||
"jquery": "~2.1.1",
|
||||
"bootstrap": "~3.1.1",
|
||||
"angular-route": "~1.3.0"
|
||||
"angular-route": "1.4.x"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The new dependency `"angular-route": "~1.3.0"` tells bower to install a version of the
|
||||
angular-route component that is compatible with version 1.3.x. We must tell bower to download
|
||||
The new dependency `"angular-route": "1.4.x"` tells bower to install a version of the
|
||||
angular-route component that is compatible with version 1.4.x. We must tell bower to download
|
||||
and install this dependency.
|
||||
|
||||
If you have bower installed globally, then you can run `bower install` but for this project, we have
|
||||
@@ -313,7 +313,7 @@ to various URLs and verify that the correct view was rendered.
|
||||
it('should redirect index.html to index.html#/phones', function() {
|
||||
browser.get('app/index.html');
|
||||
browser.getLocationAbsUrl().then(function(url) {
|
||||
expect(url.split('#')[1]).toBe('/phones');
|
||||
expect(url).toEqual('/phones');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -32,17 +32,18 @@ We are using [Bower][bower] to install client side dependencies. This step upda
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"angular": "~1.3.0",
|
||||
"angular-mocks": "~1.3.0",
|
||||
"angular": "1.4.x",
|
||||
"angular-mocks": "1.4.x",
|
||||
"jquery": "~2.1.1",
|
||||
"bootstrap": "~3.1.1",
|
||||
"angular-route": "~1.3.0",
|
||||
"angular-resource": "~1.3.0"
|
||||
"angular-route": "1.4.x",
|
||||
"angular-resource": "1.4.x"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The new dependency `"angular-resource": "~1.3.0"` tells bower to install a version of the
|
||||
angular-resource component that is compatible with version 1.3.x. We must ask bower to download
|
||||
The new dependency `"angular-resource": "1.4.x"` tells bower to install a version of the
|
||||
angular-resource component that is compatible with version 1.4.x. We must ask bower to download
|
||||
and install this dependency. We can do this by running:
|
||||
|
||||
```
|
||||
|
||||
@@ -36,20 +36,20 @@ We are using [Bower][bower] to install client side dependencies. This step upda
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"angular": "~1.3.0",
|
||||
"angular-mocks": "~1.3.0",
|
||||
"bootstrap": "~3.1.1",
|
||||
"angular-route": "~1.3.0",
|
||||
"angular-resource": "~1.3.0",
|
||||
"angular": "1.4.x",
|
||||
"angular-mocks": "1.4.x",
|
||||
"jquery": "~2.1.1",
|
||||
"angular-animate": "~1.3.0"
|
||||
"bootstrap": "~3.1.1",
|
||||
"angular-route": "1.4.x",
|
||||
"angular-resource": "1.4.x",
|
||||
"angular-animate": "1.4.x"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `"angular-animate": "~1.3.0"` tells bower to install a version of the
|
||||
angular-animate component that is compatible with version 1.3.x.
|
||||
* `"jquery": "2.1.1"` tells bower to install the 2.1.1 version of jQuery. Note that this is not an
|
||||
* `"angular-animate": "1.4.x"` tells bower to install a version of the
|
||||
angular-animate component that is compatible with version 1.4.x.
|
||||
* `"jquery": "~2.1.1"` tells bower to install the 2.1.1 version of jQuery. Note that this is not an
|
||||
Angular library, it is the standard jQuery library. We can use bower to install a wide range of 3rd
|
||||
party libraries.
|
||||
|
||||
@@ -111,7 +111,7 @@ __`app/index.html`.__
|
||||
```
|
||||
|
||||
<div class="alert alert-error">
|
||||
**Important:** Be sure to use jQuery version 2.1 or newer when using Angular 1.3; jQuery 1.x is
|
||||
**Important:** Be sure to use jQuery version 2.1 or newer when using Angular 1.4; jQuery 1.x is
|
||||
not officially supported.
|
||||
Be sure to load jQuery before all AngularJS scripts, otherwise AngularJS won't detect jQuery and
|
||||
animations will not work as expected.
|
||||
@@ -239,9 +239,9 @@ The name of the starting class is the name of the event that is fired (like `ent
|
||||
The active class name is the same as the starting class's but with an `-active` suffix.
|
||||
This two-class CSS naming convention allows the developer to craft an animation, beginning to end.
|
||||
|
||||
In our example above, elements expand from a height of **0** to **120 pixels** when items are added or moved,
|
||||
around and collapsing the items before removing them from the list.
|
||||
There's also a nice fade-in and fade-out effect that also occurs at the same time. All of this is handled
|
||||
In our example above, elements are expanded from a height of **0** to **120 pixels** when they're added to the
|
||||
list and are collapsed back down to **0 pixels** before being removed from the list.
|
||||
There's also a nice fade-in and fade-out effect that occurs at the same time. All of this is handled
|
||||
by the CSS transition declarations at the top of the example code above.
|
||||
|
||||
Although most modern browsers have good support for [CSS transitions](http://caniuse.com/#feat=css-transitions)
|
||||
|
||||
+3
-2
@@ -21,6 +21,7 @@ var outputFolder = '../build/docs';
|
||||
var bowerFolder = 'bower_components';
|
||||
|
||||
var src = 'app/src/**/*.js';
|
||||
var ignoredFiles = '!src/angular.bind.js';
|
||||
var assets = 'app/assets/**/*';
|
||||
|
||||
|
||||
@@ -50,7 +51,7 @@ gulp.task('build-app', function() {
|
||||
var minFile = 'docs.min.js';
|
||||
var folder = outputFolder + '/js/';
|
||||
|
||||
return gulp.src(src)
|
||||
return gulp.src([src, ignoredFiles])
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat(file))
|
||||
.pipe(gulp.dest(folder))
|
||||
@@ -107,5 +108,5 @@ gulp.task('jshint', ['doc-gen'], function() {
|
||||
gulp.task('default', ['assets', 'doc-gen', 'build-app', 'jshint']);
|
||||
|
||||
gulp.task('watch', function() {
|
||||
gulp.watch([src, assets], ['assets', 'build-app']);
|
||||
gulp.watch([src, ignoredFiles, assets], ['assets', 'build-app']);
|
||||
});
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -303,8 +303,8 @@ goog.i18n.currency.CurrencyInfo = {
|
||||
'KRW': [0, '\u20A9', 'KR₩'],
|
||||
'LKR': [2, 'Rs', 'SLRs'],
|
||||
'LTL': [2, 'Lt', 'Lt'],
|
||||
'LVL': [2, 'Ls', 'Ls'],
|
||||
'MNT': [0, '\u20AE', 'MN₮'],
|
||||
'MVR': [2, 'Rf', 'MVR'],
|
||||
'MXN': [2, '$', 'Mex$'],
|
||||
'MYR': [2, 'RM', 'RM'],
|
||||
'NOK': [50, 'kr', 'NOkr'],
|
||||
@@ -339,6 +339,7 @@ goog.i18n.currency.CurrencyInfo = {
|
||||
goog.i18n.currency.CurrencyInfoTier2 = {
|
||||
'AFN': [48, 'Af.', 'AFN'],
|
||||
'AMD': [0, 'Dram', 'dram'],
|
||||
'ANG': [2, 'NAf.', 'ANG'],
|
||||
'AOA': [2, 'Kz', 'Kz'],
|
||||
'ARS': [2, '$', 'AR$'],
|
||||
'AWG': [2, 'Afl.', 'Afl.'],
|
||||
@@ -414,6 +415,7 @@ goog.i18n.currency.CurrencyInfoTier2 = {
|
||||
'SLL': [0, 'SLL', 'SLL'],
|
||||
'SOS': [0, 'SOS', 'SOS'],
|
||||
'SRD': [2, '$', 'SR$'],
|
||||
'SSP': [2, '£', 'SSP'],
|
||||
'STD': [0, 'Db', 'Db'],
|
||||
'SYP': [0, '£', 'SY£'],
|
||||
'SZL': [2, 'SZL', 'SZL'],
|
||||
@@ -430,5 +432,6 @@ goog.i18n.currency.CurrencyInfoTier2 = {
|
||||
'XCD': [2, '$', 'EC$'],
|
||||
'XOF': [0, 'CFA', 'CFA'],
|
||||
'XPF': [0, 'FCFP', 'FCFP'],
|
||||
'ZMK': [0, 'ZMK', 'ZMK']
|
||||
'ZMW': [0, 'ZMW', 'ZMW'],
|
||||
'ZWD': [0, '$', 'Z$']
|
||||
};
|
||||
|
||||
+305
-54
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* This file is autogenerated by script. See
|
||||
* http://go/generate_datetime_constants.py using --for_closure
|
||||
* File generated from CLDR ver. 26
|
||||
* File generated from CLDR ver. 27.0.1
|
||||
*
|
||||
* To reduce the file size (which may cause issues in some JS
|
||||
* developing environments), this file will only contain locales
|
||||
@@ -36,9 +36,11 @@ goog.provide('goog.i18n.DateTimeSymbols_af');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_am');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_ar');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_az');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_be');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_bg');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_bn');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_br');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_bs');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_ca');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_chr');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_cs');
|
||||
@@ -50,6 +52,7 @@ goog.provide('goog.i18n.DateTimeSymbols_de_CH');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_el');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_en');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_en_AU');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_en_CA');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_en_GB');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_en_IE');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_en_IN');
|
||||
@@ -60,6 +63,8 @@ goog.provide('goog.i18n.DateTimeSymbols_en_ZA');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_es');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_es_419');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_es_ES');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_es_MX');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_es_US');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_et');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_eu');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_fa');
|
||||
@@ -118,6 +123,7 @@ goog.provide('goog.i18n.DateTimeSymbols_sk');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_sl');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_sq');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_sr');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_sr_Latn');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_sv');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_sw');
|
||||
goog.provide('goog.i18n.DateTimeSymbols_ta');
|
||||
@@ -343,6 +349,52 @@ goog.i18n.DateTimeSymbols_az = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale be.
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_be = {
|
||||
ERAS: ['да н.э.', 'н.э.'],
|
||||
ERANAMES: ['да н.э.', 'н.э.'],
|
||||
NARROWMONTHS: ['с', 'л', 'с', 'к', 'м', 'ч', 'л', 'ж', 'в', 'к',
|
||||
'л', 'с'],
|
||||
STANDALONENARROWMONTHS: ['с', 'л', 'с', 'к', 'м', 'ч', 'л', 'ж', 'в',
|
||||
'к', 'л', 'с'],
|
||||
MONTHS: ['студзеня', 'лютага', 'сакавіка',
|
||||
'красавіка', 'мая', 'чэрвеня', 'ліпеня',
|
||||
'жніўня', 'верасня', 'кастрычніка',
|
||||
'лістапада', 'снежня'],
|
||||
STANDALONEMONTHS: ['студзень', 'люты', 'сакавік',
|
||||
'красавік', 'май', 'чэрвень', 'ліпень',
|
||||
'жнівень', 'верасень', 'кастрычнік',
|
||||
'лістапад', 'снежань'],
|
||||
SHORTMONTHS: ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр',
|
||||
'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
|
||||
STANDALONESHORTMONTHS: ['сту', 'лют', 'сак', 'кра', 'май',
|
||||
'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
|
||||
WEEKDAYS: ['нядзеля', 'панядзелак', 'аўторак',
|
||||
'серада', 'чацвер', 'пятніца', 'субота'],
|
||||
STANDALONEWEEKDAYS: ['нядзеля', 'панядзелак',
|
||||
'аўторак', 'серада', 'чацвер', 'пятніца',
|
||||
'субота'],
|
||||
SHORTWEEKDAYS: ['нд', 'пн', 'аў', 'ср', 'чц', 'пт', 'сб'],
|
||||
STANDALONESHORTWEEKDAYS: ['нд', 'пн', 'аў', 'ср', 'чц', 'пт',
|
||||
'сб'],
|
||||
NARROWWEEKDAYS: ['н', 'п', 'а', 'с', 'ч', 'п', 'с'],
|
||||
STANDALONENARROWWEEKDAYS: ['н', 'п', 'а', 'с', 'ч', 'п', 'с'],
|
||||
SHORTQUARTERS: ['1-шы кв.', '2-гі кв.', '3-ці кв.',
|
||||
'4-ты кв.'],
|
||||
QUARTERS: ['1-шы квартал', '2-гі квартал',
|
||||
'3-ці квартал', '4-ты квартал'],
|
||||
AMPMS: ['да палудня', 'пасля палудня'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd.M.y', 'd.M.yy'],
|
||||
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 6
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale bg.
|
||||
*/
|
||||
@@ -439,16 +491,10 @@ goog.i18n.DateTimeSymbols_bn = {
|
||||
NARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ', 'শু', 'শ'],
|
||||
STANDALONENARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ',
|
||||
'শু', 'শ'],
|
||||
SHORTQUARTERS: [
|
||||
'প্র. ত্রৈ. এক. চতুর্থাংশ',
|
||||
'দ্বি.ত্রৈ.এক. চতুর্থাংশ',
|
||||
'তৃ.ত্রৈ.এক.চতুর্থাংশ',
|
||||
'চ.ত্রৈ.এক চতুর্থাংশ'],
|
||||
QUARTERS: [
|
||||
'প্রথম ত্রৈমাসিকের এক চতুর্থাংশ',
|
||||
'দ্বিতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
|
||||
'তৃতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
|
||||
'চতুর্থ ত্রৈমাসিকের এক চতুর্থাংশ'],
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['ত্রৈমাসিক', 'ষাণ্মাসিক',
|
||||
'তৃতীয় চতুর্থাংশ',
|
||||
'চতুর্থ ত্রৈমাসিক'],
|
||||
AMPMS: ['am', 'pm'],
|
||||
DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
@@ -497,6 +543,44 @@ goog.i18n.DateTimeSymbols_br = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale bs.
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_bs = {
|
||||
ERAS: ['p. n. e.', 'n. e.'],
|
||||
ERANAMES: ['Prije nove ere', 'Nove ere'],
|
||||
NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
|
||||
STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
|
||||
'n', 'd'],
|
||||
MONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli',
|
||||
'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
|
||||
STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'juni',
|
||||
'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
|
||||
SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep',
|
||||
'okt', 'nov', 'dec'],
|
||||
STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
|
||||
'aug', 'sep', 'okt', 'nov', 'dec'],
|
||||
WEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak',
|
||||
'petak', 'subota'],
|
||||
STANDALONEWEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda',
|
||||
'četvrtak', 'petak', 'subota'],
|
||||
SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
|
||||
STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
|
||||
NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Č', 'P', 'S'],
|
||||
STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
|
||||
SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
|
||||
QUARTERS: ['Prvi kvartal', 'Drugi kvartal', 'Treći kvartal',
|
||||
'Četvrti kvartal'],
|
||||
AMPMS: ['prije podne', 'popodne'],
|
||||
DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd. MMM. y.', 'dd.MM.yy.'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} \'u\' {0}', '{1} \'u\' {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 6
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale ca.
|
||||
*/
|
||||
@@ -507,8 +591,9 @@ goog.i18n.DateTimeSymbols_ca = {
|
||||
'NV', 'DS'],
|
||||
STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
|
||||
'ST', 'OC', 'NV', 'DS'],
|
||||
MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
|
||||
'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
|
||||
MONTHS: ['de gener', 'de febrer', 'de març', 'd’abril', 'de maig',
|
||||
'de juny', 'de juliol', 'd’agost', 'de setembre', 'd’octubre',
|
||||
'de novembre', 'de desembre'],
|
||||
STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
|
||||
'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
|
||||
SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
|
||||
@@ -609,7 +694,7 @@ goog.i18n.DateTimeSymbols_cs = {
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1. čtvrtletí', '2. čtvrtletí', '3. čtvrtletí',
|
||||
'4. čtvrtletí'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
AMPMS: ['dopoledne', 'odpoledne'],
|
||||
DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. M. y', 'dd.MM.yy'],
|
||||
TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
@@ -684,7 +769,7 @@ goog.i18n.DateTimeSymbols_da = {
|
||||
SHORTQUARTERS: ['1. kvt.', '2. kvt.', '3. kvt.', '4. kvt.'],
|
||||
QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'dd/MM/y', 'dd/MM/yy'],
|
||||
DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd/MM/y'],
|
||||
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
|
||||
DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
@@ -758,7 +843,7 @@ goog.i18n.DateTimeSymbols_de_AT = {
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
|
||||
AMPMS: ['vorm.', 'nachm.'],
|
||||
DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'dd. MMM y', 'dd.MM.yy'],
|
||||
DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
@@ -882,10 +967,47 @@ goog.i18n.DateTimeSymbols_en_AU = {
|
||||
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['am', 'pm'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/y'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale en_CA.
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_en_CA = {
|
||||
ERAS: ['BC', 'AD'],
|
||||
ERANAMES: ['Before Christ', 'Anno Domini'],
|
||||
NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
|
||||
STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
|
||||
'N', 'D'],
|
||||
MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
|
||||
'August', 'September', 'October', 'November', 'December'],
|
||||
STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
|
||||
'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
||||
'Oct', 'Nov', 'Dec'],
|
||||
STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
|
||||
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
|
||||
'Saturday'],
|
||||
STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
|
||||
'Friday', 'Saturday'],
|
||||
SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||
STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||
NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'y-MM-dd'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 5
|
||||
@@ -919,7 +1041,7 @@ goog.i18n.DateTimeSymbols_en_GB = {
|
||||
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['am', 'pm'],
|
||||
AMPMS: ['a.m.', 'p.m.'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
@@ -958,7 +1080,7 @@ goog.i18n.DateTimeSymbols_en_IE = {
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['a.m.', 'p.m.'],
|
||||
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
@@ -993,7 +1115,7 @@ goog.i18n.DateTimeSymbols_en_IN = {
|
||||
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['am', 'pm'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
@@ -1030,7 +1152,7 @@ goog.i18n.DateTimeSymbols_en_SG = {
|
||||
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['am', 'pm'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
@@ -1074,7 +1196,7 @@ goog.i18n.DateTimeSymbols_en_ZA = {
|
||||
SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y/MM/dd'],
|
||||
DATEFORMATS: ['EEEE, dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y/MM/dd'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
@@ -1088,7 +1210,7 @@ goog.i18n.DateTimeSymbols_en_ZA = {
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_es = {
|
||||
ERAS: ['a. C.', 'd. C.'],
|
||||
ERANAMES: ['antes de Cristo', 'anno Dómini'],
|
||||
ERANAMES: ['antes de Cristo', 'después de Cristo'],
|
||||
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
|
||||
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
|
||||
'N', 'D'],
|
||||
@@ -1114,7 +1236,7 @@ goog.i18n.DateTimeSymbols_es = {
|
||||
'4.º trimestre'],
|
||||
AMPMS: ['a. m.', 'p. m.'],
|
||||
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
|
||||
'd \'de\' MMM \'de\' y', 'd/M/yy'],
|
||||
'd MMM y', 'd/M/yy'],
|
||||
TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
|
||||
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
@@ -1129,17 +1251,17 @@ goog.i18n.DateTimeSymbols_es = {
|
||||
goog.i18n.DateTimeSymbols_es_419 = {
|
||||
ERAS: ['a. C.', 'd. C.'],
|
||||
ERANAMES: ['antes de Cristo', 'después de Cristo'],
|
||||
NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
|
||||
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
|
||||
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
|
||||
'N', 'D'],
|
||||
MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
|
||||
'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
|
||||
'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
|
||||
STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
|
||||
'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||
SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
|
||||
'set.', 'oct.', 'nov.', 'dic.'],
|
||||
'sept.', 'oct.', 'nov.', 'dic.'],
|
||||
STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
|
||||
'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
|
||||
'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
|
||||
WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
|
||||
'sábado'],
|
||||
STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
|
||||
@@ -1149,12 +1271,12 @@ goog.i18n.DateTimeSymbols_es_419 = {
|
||||
'Sáb.'],
|
||||
NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
|
||||
STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
|
||||
SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
|
||||
SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
|
||||
QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
|
||||
'4.º trimestre'],
|
||||
AMPMS: ['a. m.', 'p. m.'],
|
||||
AMPMS: ['a. m.', 'p. m.'],
|
||||
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
|
||||
'd \'de\' MMM \'de\' y', 'd/M/yy'],
|
||||
'd MMM y', 'd/M/yy'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
@@ -1169,6 +1291,86 @@ goog.i18n.DateTimeSymbols_es_419 = {
|
||||
goog.i18n.DateTimeSymbols_es_ES = goog.i18n.DateTimeSymbols_es;
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale es_MX.
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_es_MX = {
|
||||
ERAS: ['a. C.', 'd. C.'],
|
||||
ERANAMES: ['antes de Cristo', 'después de Cristo'],
|
||||
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
|
||||
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
|
||||
'N', 'D'],
|
||||
MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
|
||||
'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
|
||||
STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
|
||||
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||
SHORTMONTHS: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep',
|
||||
'oct', 'nov', 'dic'],
|
||||
STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
|
||||
'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
|
||||
WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
|
||||
'sábado'],
|
||||
STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
|
||||
'Viernes', 'Sábado'],
|
||||
SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
|
||||
STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
|
||||
'Sáb.'],
|
||||
NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
|
||||
STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
|
||||
SHORTQUARTERS: ['1er. trim.', '2º. trim.', '3er. trim.', '4º trim.'],
|
||||
QUARTERS: ['1er. trimestre', '2º. trimestre', '3er. trimestre',
|
||||
'4º trimestre'],
|
||||
AMPMS: ['a.m.', 'p.m.'],
|
||||
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
|
||||
'dd/MM/y', 'dd/MM/yy'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale es_US.
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_es_US = {
|
||||
ERAS: ['a. C.', 'd. C.'],
|
||||
ERANAMES: ['antes de Cristo', 'después de Cristo'],
|
||||
NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
|
||||
STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
|
||||
'N', 'D'],
|
||||
MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
|
||||
'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
|
||||
STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
|
||||
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||
SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
|
||||
'sept.', 'oct.', 'nov.', 'dic.'],
|
||||
STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
|
||||
'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
|
||||
WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
|
||||
'sábado'],
|
||||
STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
|
||||
'Viernes', 'Sábado'],
|
||||
SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
|
||||
STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
|
||||
'Sáb.'],
|
||||
NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
|
||||
STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
|
||||
SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
|
||||
QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
|
||||
'4.º trimestre'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
|
||||
'd MMM y', 'd/M/yy'],
|
||||
TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
|
||||
DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale et.
|
||||
*/
|
||||
@@ -1327,7 +1529,8 @@ goog.i18n.DateTimeSymbols_fi = {
|
||||
AMPMS: ['ap.', 'ip.'],
|
||||
DATEFORMATS: ['cccc d. MMMM y', 'd. MMMM y', 'd.M.y', 'd.M.y'],
|
||||
TIMEFORMATS: ['H.mm.ss zzzz', 'H.mm.ss z', 'H.mm.ss', 'H.mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
DATETIMEFORMATS: ['{1} \'klo\' {0}', '{1} \'klo\' {0}', '{1} \'klo\' {0}',
|
||||
'{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 3
|
||||
@@ -1440,10 +1643,9 @@ goog.i18n.DateTimeSymbols_fr_CA = {
|
||||
SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
|
||||
QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'y-MM-dd', 'yy-MM-dd'],
|
||||
TIMEFORMATS: ['HH \'h\' mm \'min\' ss \'s\' zzzz', 'HH:mm:ss z', 'HH:mm:ss',
|
||||
'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} \'à\' {0}', '{1} \'à\' {0}', '{1} {0}', '{1} {0}'],
|
||||
DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'yy-MM-dd'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 5
|
||||
@@ -1697,7 +1899,7 @@ goog.i18n.DateTimeSymbols_he = {
|
||||
QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
|
||||
AMPMS: ['לפנה״צ', 'אחה״צ'],
|
||||
DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
|
||||
DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
|
||||
'{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
@@ -2073,7 +2275,7 @@ goog.i18n.DateTimeSymbols_iw = {
|
||||
QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
|
||||
AMPMS: ['לפנה״צ', 'אחה״צ'],
|
||||
DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
|
||||
DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
|
||||
'{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
@@ -2941,7 +3143,7 @@ goog.i18n.DateTimeSymbols_my = {
|
||||
'တတိယ သုံးလပတ်',
|
||||
'စတုတ္ထ သုံးလပတ်'],
|
||||
AMPMS: ['နံနက်', 'ညနေ'],
|
||||
DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
|
||||
DATEFORMATS: ['EEEE၊ dd MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1}မှာ {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
@@ -2999,7 +3201,7 @@ goog.i18n.DateTimeSymbols_ne = {
|
||||
STANDALONENARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७',
|
||||
'८', '९', '१०', '११', '१२'],
|
||||
MONTHS: ['जनवरी', 'फेब्रुअरी', 'मार्च',
|
||||
'अप्रिल', 'मे', 'जुन', 'जुलाई',
|
||||
'अप्रिल', 'मई', 'जुन', 'जुलाई',
|
||||
'अगस्ट', 'सेप्टेम्बर',
|
||||
'अक्टोबर', 'नोभेम्बर',
|
||||
'डिसेम्बर'],
|
||||
@@ -3019,10 +3221,10 @@ goog.i18n.DateTimeSymbols_ne = {
|
||||
'अक्टोबर', 'नोभेम्बर',
|
||||
'डिसेम्बर'],
|
||||
WEEKDAYS: ['आइतबार', 'सोमबार',
|
||||
'मङ्गलबार', 'बुधबार', 'बिहीबार',
|
||||
'मङ्गलबार', 'बुधबार', 'बिहिबार',
|
||||
'शुक्रबार', 'शनिबार'],
|
||||
STANDALONEWEEKDAYS: ['आइतबार', 'सोमबार',
|
||||
'मङ्गलबार', 'बुधबार', 'बिहीबार',
|
||||
'मङ्गलबार', 'बुधबार', 'बिहिबार',
|
||||
'शुक्रबार', 'शनिबार'],
|
||||
SHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल', 'बुध',
|
||||
'बिही', 'शुक्र', 'शनि'],
|
||||
@@ -3036,8 +3238,7 @@ goog.i18n.DateTimeSymbols_ne = {
|
||||
'चौथो सत्र'],
|
||||
QUARTERS: ['पहिलो सत्र', 'दोस्रो सत्र',
|
||||
'तेस्रो सत्र', 'चौथो सत्र'],
|
||||
AMPMS: ['पूर्व मध्यान्ह',
|
||||
'उत्तर मध्यान्ह'],
|
||||
AMPMS: ['पूर्वाह्न', 'अपराह्न'],
|
||||
DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
|
||||
@@ -3265,7 +3466,7 @@ goog.i18n.DateTimeSymbols_pl = {
|
||||
SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
|
||||
QUARTERS: ['I kwartał', 'II kwartał', 'III kwartał', 'IV kwartał'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'dd.MM.y', 'dd.MM.y'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
@@ -3330,12 +3531,12 @@ goog.i18n.DateTimeSymbols_pt_PT = {
|
||||
'N', 'D'],
|
||||
MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
|
||||
'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
|
||||
STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
|
||||
'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
|
||||
STANDALONEMONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
|
||||
'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
|
||||
SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
|
||||
'out', 'nov', 'dez'],
|
||||
STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
|
||||
'Ago', 'Set', 'Out', 'Nov', 'Dez'],
|
||||
STANDALONESHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul',
|
||||
'ago', 'set', 'out', 'nov', 'dez'],
|
||||
WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
|
||||
'quinta-feira', 'sexta-feira', 'sábado'],
|
||||
STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
|
||||
@@ -3570,7 +3771,7 @@ goog.i18n.DateTimeSymbols_sl = {
|
||||
'4. četrtletje'],
|
||||
AMPMS: ['dop.', 'pop.'],
|
||||
DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'd. MMM y', 'd. MM. yy'],
|
||||
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
|
||||
TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
@@ -3661,6 +3862,44 @@ goog.i18n.DateTimeSymbols_sr = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale sr_Latn.
|
||||
*/
|
||||
goog.i18n.DateTimeSymbols_sr_Latn = {
|
||||
ERAS: ['p. n. e.', 'n. e.'],
|
||||
ERANAMES: ['Pre nove ere', 'Nove ere'],
|
||||
NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
|
||||
STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
|
||||
'n', 'd'],
|
||||
MONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust',
|
||||
'septembar', 'oktobar', 'novembar', 'decembar'],
|
||||
STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul',
|
||||
'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
|
||||
SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep',
|
||||
'okt', 'nov', 'dec'],
|
||||
STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
|
||||
'avg', 'sep', 'okt', 'nov', 'dec'],
|
||||
WEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak',
|
||||
'subota'],
|
||||
STANDALONEWEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak',
|
||||
'petak', 'subota'],
|
||||
SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
|
||||
STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
|
||||
NARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
|
||||
STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
|
||||
SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
|
||||
QUARTERS: ['Prvo tromesečje', 'Drugo tromesečje', 'Treće tromesečje',
|
||||
'Četvrto tromesečje'],
|
||||
AMPMS: ['pre podne', 'po podne'],
|
||||
DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd.MM.y.', 'd.M.yy.'],
|
||||
TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 0,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
FIRSTWEEKCUTOFFDAY: 6
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Date/time formatting symbols for locale sv.
|
||||
*/
|
||||
@@ -3726,7 +3965,7 @@ goog.i18n.DateTimeSymbols_sw = {
|
||||
'Alhamisi', 'Ijumaa', 'Jumamosi'],
|
||||
NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
||||
SHORTQUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
|
||||
SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
|
||||
QUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
|
||||
@@ -4189,7 +4428,7 @@ goog.i18n.DateTimeSymbols_zh = {
|
||||
QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
|
||||
AMPMS: ['上午', '下午'],
|
||||
DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'yy/M/d'],
|
||||
TIMEFORMATS: ['zzzzah:mm:ss', 'zah:mm:ss', 'ah:mm:ss', 'ah:mm'],
|
||||
TIMEFORMATS: ['zzzz ah:mm:ss', 'z ah:mm:ss', 'ah:mm:ss', 'ah:mm'],
|
||||
DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
@@ -4330,12 +4569,16 @@ if (goog.LOCALE == 'af') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar;
|
||||
} else if (goog.LOCALE == 'az') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az;
|
||||
} else if (goog.LOCALE == 'be') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_be;
|
||||
} else if (goog.LOCALE == 'bg') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bg;
|
||||
} else if (goog.LOCALE == 'bn') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bn;
|
||||
} else if (goog.LOCALE == 'br') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_br;
|
||||
} else if (goog.LOCALE == 'bs') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs;
|
||||
} else if (goog.LOCALE == 'ca') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca;
|
||||
} else if (goog.LOCALE == 'chr') {
|
||||
@@ -4358,6 +4601,8 @@ if (goog.LOCALE == 'af') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
|
||||
} else if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_AU;
|
||||
} else if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CA;
|
||||
} else if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GB;
|
||||
} else if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
|
||||
@@ -4376,6 +4621,10 @@ if (goog.LOCALE == 'af') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_419;
|
||||
} else if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es;
|
||||
} else if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_MX;
|
||||
} else if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_US;
|
||||
} else if (goog.LOCALE == 'et') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_et;
|
||||
} else if (goog.LOCALE == 'eu') {
|
||||
@@ -4492,6 +4741,8 @@ if (goog.LOCALE == 'af') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sq;
|
||||
} else if (goog.LOCALE == 'sr') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr;
|
||||
} else if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn;
|
||||
} else if (goog.LOCALE == 'sv') {
|
||||
goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv;
|
||||
} else if (goog.LOCALE == 'sw') {
|
||||
|
||||
+541
-1281
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@
|
||||
* This file is autogenerated by script:
|
||||
* http://go/generate_number_constants.py
|
||||
* using the --for_closure flag.
|
||||
* File generated from CLDR ver. 26
|
||||
* File generated from CLDR ver. 27.0.1
|
||||
*
|
||||
* To reduce the file size (which may cause issues in some JS
|
||||
* developing environments), this file will only contain locales
|
||||
@@ -41,14 +41,21 @@ goog.provide('goog.i18n.NumberFormatSymbols_am');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_am_ET');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ar');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ar_001');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ar_EG');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_az');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_az_Latn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_az_Latn_AZ');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_be');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_be_BY');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bg');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bg_BG');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bn_BD');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_br');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_br_FR');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bs');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bs_Latn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_bs_Latn_BA');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ca');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ca_AD');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ca_ES');
|
||||
@@ -71,11 +78,13 @@ goog.provide('goog.i18n.NumberFormatSymbols_de_CH');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_de_DE');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_de_LU');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_el');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_el_CY');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_el_GR');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_001');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_AS');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_AU');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_CA');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_DG');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_FM');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_en_GB');
|
||||
@@ -100,6 +109,8 @@ goog.provide('goog.i18n.NumberFormatSymbols_es_419');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_es_EA');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_es_ES');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_es_IC');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_es_MX');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_es_US');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_et');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_et_EE');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_eu');
|
||||
@@ -157,6 +168,7 @@ goog.provide('goog.i18n.NumberFormatSymbols_ja_JP');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ka');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ka_GE');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_kk');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_kk_Cyrl');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_km');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_km_KH');
|
||||
@@ -165,6 +177,7 @@ goog.provide('goog.i18n.NumberFormatSymbols_kn_IN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ko');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ko_KR');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ky');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ky_Cyrl');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ky_Cyrl_KG');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ln');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ln_CD');
|
||||
@@ -179,10 +192,12 @@ goog.provide('goog.i18n.NumberFormatSymbols_mk_MK');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ml');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ml_IN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mn_Cyrl');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mn_Cyrl_MN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mr');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mr_IN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ms');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn_MY');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mt');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_mt_MT');
|
||||
@@ -200,6 +215,7 @@ goog.provide('goog.i18n.NumberFormatSymbols_no_NO');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_or');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_or_IN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_pa');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_pa_Guru');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_pa_Guru_IN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_pl');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_pl_PL');
|
||||
@@ -219,7 +235,10 @@ goog.provide('goog.i18n.NumberFormatSymbols_sl_SI');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sq');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sq_AL');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sr');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl_RS');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn_RS');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sv');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sv_SE');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_sw');
|
||||
@@ -238,12 +257,14 @@ goog.provide('goog.i18n.NumberFormatSymbols_uk_UA');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ur');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_ur_PK');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_uz');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_uz_Latn');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_uz_Latn_UZ');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_vi');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_vi_VN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zh');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zh_CN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zh_HK');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans_CN');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zh_TW');
|
||||
goog.provide('goog.i18n.NumberFormatSymbols_zu');
|
||||
@@ -340,6 +361,13 @@ goog.i18n.NumberFormatSymbols_ar = {
|
||||
goog.i18n.NumberFormatSymbols_ar_001 = goog.i18n.NumberFormatSymbols_ar;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale ar_EG.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_ar_EG = goog.i18n.NumberFormatSymbols_ar;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale az.
|
||||
* @enum {string}
|
||||
@@ -363,6 +391,13 @@ goog.i18n.NumberFormatSymbols_az = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale az_Latn.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_az_Latn = goog.i18n.NumberFormatSymbols_az;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale az_Latn_AZ.
|
||||
* @enum {string}
|
||||
@@ -370,6 +405,36 @@ goog.i18n.NumberFormatSymbols_az = {
|
||||
goog.i18n.NumberFormatSymbols_az_Latn_AZ = goog.i18n.NumberFormatSymbols_az;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale be.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_be = {
|
||||
DECIMAL_SEP: ',',
|
||||
GROUP_SEP: '\u00A0',
|
||||
PERCENT: '%',
|
||||
ZERO_DIGIT: '0',
|
||||
PLUS_SIGN: '+',
|
||||
MINUS_SIGN: '-',
|
||||
EXP_SYMBOL: 'E',
|
||||
PERMILL: '\u2030',
|
||||
INFINITY: '\u221E',
|
||||
NAN: 'NaN',
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0%',
|
||||
CURRENCY_PATTERN: '\u00A4#,##0.00',
|
||||
DEF_CURRENCY_CODE: 'BYR'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale be_BY.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_be_BY = goog.i18n.NumberFormatSymbols_be;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale bg.
|
||||
* @enum {string}
|
||||
@@ -460,6 +525,43 @@ goog.i18n.NumberFormatSymbols_br = {
|
||||
goog.i18n.NumberFormatSymbols_br_FR = goog.i18n.NumberFormatSymbols_br;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale bs.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_bs = {
|
||||
DECIMAL_SEP: ',',
|
||||
GROUP_SEP: '.',
|
||||
PERCENT: '%',
|
||||
ZERO_DIGIT: '0',
|
||||
PLUS_SIGN: '+',
|
||||
MINUS_SIGN: '-',
|
||||
EXP_SYMBOL: 'E',
|
||||
PERMILL: '\u2030',
|
||||
INFINITY: '\u221E',
|
||||
NAN: 'NaN',
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0%',
|
||||
CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
|
||||
DEF_CURRENCY_CODE: 'BAM'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale bs_Latn.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_bs_Latn = goog.i18n.NumberFormatSymbols_bs;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale bs_Latn_BA.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_bs_Latn_BA = goog.i18n.NumberFormatSymbols_bs;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale ca.
|
||||
* @enum {string}
|
||||
@@ -758,6 +860,13 @@ goog.i18n.NumberFormatSymbols_el = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale el_CY.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_el_CY = goog.i18n.NumberFormatSymbols_el;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale el_GR.
|
||||
* @enum {string}
|
||||
@@ -825,6 +934,29 @@ goog.i18n.NumberFormatSymbols_en_AU = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale en_CA.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_en_CA = {
|
||||
DECIMAL_SEP: '.',
|
||||
GROUP_SEP: ',',
|
||||
PERCENT: '%',
|
||||
ZERO_DIGIT: '0',
|
||||
PLUS_SIGN: '+',
|
||||
MINUS_SIGN: '-',
|
||||
EXP_SYMBOL: 'E',
|
||||
PERMILL: '\u2030',
|
||||
INFINITY: '\u221E',
|
||||
NAN: 'NaN',
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0%',
|
||||
CURRENCY_PATTERN: '\u00A4#,##0.00',
|
||||
DEF_CURRENCY_CODE: 'CAD'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale en_DG.
|
||||
* @enum {string}
|
||||
@@ -1105,6 +1237,52 @@ goog.i18n.NumberFormatSymbols_es_ES = goog.i18n.NumberFormatSymbols_es;
|
||||
goog.i18n.NumberFormatSymbols_es_IC = goog.i18n.NumberFormatSymbols_es;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale es_MX.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_es_MX = {
|
||||
DECIMAL_SEP: '.',
|
||||
GROUP_SEP: ',',
|
||||
PERCENT: '%',
|
||||
ZERO_DIGIT: '0',
|
||||
PLUS_SIGN: '+',
|
||||
MINUS_SIGN: '-',
|
||||
EXP_SYMBOL: 'E',
|
||||
PERMILL: '\u2030',
|
||||
INFINITY: '\u221E',
|
||||
NAN: 'NaN',
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0%',
|
||||
CURRENCY_PATTERN: '\u00A4#,##0.00',
|
||||
DEF_CURRENCY_CODE: 'MXN'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale es_US.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_es_US = {
|
||||
DECIMAL_SEP: '.',
|
||||
GROUP_SEP: ',',
|
||||
PERCENT: '%',
|
||||
ZERO_DIGIT: '0',
|
||||
PLUS_SIGN: '+',
|
||||
MINUS_SIGN: '-',
|
||||
EXP_SYMBOL: 'E',
|
||||
PERMILL: '\u2030',
|
||||
INFINITY: '\u221E',
|
||||
NAN: 'NaN',
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0\u00A0%',
|
||||
CURRENCY_PATTERN: '\u00A4#,##0.00',
|
||||
DEF_CURRENCY_CODE: 'USD'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale et.
|
||||
* @enum {string}
|
||||
@@ -1905,6 +2083,13 @@ goog.i18n.NumberFormatSymbols_kk = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale kk_Cyrl.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_kk_Cyrl = goog.i18n.NumberFormatSymbols_kk;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale kk_Cyrl_KZ.
|
||||
* @enum {string}
|
||||
@@ -2025,6 +2210,13 @@ goog.i18n.NumberFormatSymbols_ky = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale ky_Cyrl.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_ky_Cyrl = goog.i18n.NumberFormatSymbols_ky;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale ky_Cyrl_KG.
|
||||
* @enum {string}
|
||||
@@ -2236,6 +2428,13 @@ goog.i18n.NumberFormatSymbols_mn = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale mn_Cyrl.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_mn_Cyrl = goog.i18n.NumberFormatSymbols_mn;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale mn_Cyrl_MN.
|
||||
* @enum {string}
|
||||
@@ -2296,6 +2495,13 @@ goog.i18n.NumberFormatSymbols_ms = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale ms_Latn.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_ms_Latn = goog.i18n.NumberFormatSymbols_ms;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale ms_Latn_MY.
|
||||
* @enum {string}
|
||||
@@ -2449,7 +2655,7 @@ goog.i18n.NumberFormatSymbols_nl = {
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0%',
|
||||
CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
|
||||
CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0-#,##0.00',
|
||||
DEF_CURRENCY_CODE: 'EUR'
|
||||
};
|
||||
|
||||
@@ -2544,6 +2750,13 @@ goog.i18n.NumberFormatSymbols_pa = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale pa_Guru.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_pa_Guru = goog.i18n.NumberFormatSymbols_pa;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale pa_Guru_IN.
|
||||
* @enum {string}
|
||||
@@ -2837,6 +3050,13 @@ goog.i18n.NumberFormatSymbols_sr = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale sr_Cyrl.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_sr_Cyrl = goog.i18n.NumberFormatSymbols_sr;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale sr_Cyrl_RS.
|
||||
* @enum {string}
|
||||
@@ -2844,6 +3064,37 @@ goog.i18n.NumberFormatSymbols_sr = {
|
||||
goog.i18n.NumberFormatSymbols_sr_Cyrl_RS = goog.i18n.NumberFormatSymbols_sr;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale sr_Latn.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_sr_Latn = {
|
||||
DECIMAL_SEP: ',',
|
||||
GROUP_SEP: '.',
|
||||
PERCENT: '%',
|
||||
ZERO_DIGIT: '0',
|
||||
PLUS_SIGN: '+',
|
||||
MINUS_SIGN: '-',
|
||||
EXP_SYMBOL: 'E',
|
||||
PERMILL: '\u2030',
|
||||
INFINITY: '\u221E',
|
||||
NAN: 'NaN',
|
||||
DECIMAL_PATTERN: '#,##0.###',
|
||||
SCIENTIFIC_PATTERN: '#E0',
|
||||
PERCENT_PATTERN: '#,##0%',
|
||||
CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
|
||||
DEF_CURRENCY_CODE: 'RSD'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale sr_Latn_RS.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_sr_Latn_RS =
|
||||
goog.i18n.NumberFormatSymbols_sr_Latn;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale sv.
|
||||
* @enum {string}
|
||||
@@ -3130,6 +3381,13 @@ goog.i18n.NumberFormatSymbols_uz = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale uz_Latn.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_uz_Latn = goog.i18n.NumberFormatSymbols_uz;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale uz_Latn_UZ.
|
||||
* @enum {string}
|
||||
@@ -3220,6 +3478,13 @@ goog.i18n.NumberFormatSymbols_zh_HK = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale zh_Hans.
|
||||
* @enum {string}
|
||||
*/
|
||||
goog.i18n.NumberFormatSymbols_zh_Hans = goog.i18n.NumberFormatSymbols_zh;
|
||||
|
||||
|
||||
/**
|
||||
* Number formatting symbols for locale zh_Hans_CN.
|
||||
* @enum {string}
|
||||
@@ -3309,14 +3574,30 @@ if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'az') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'be') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_be;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_be;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'bg') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bg;
|
||||
}
|
||||
@@ -3341,6 +3622,18 @@ if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_br;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'bs') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'ca') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
|
||||
}
|
||||
@@ -3429,6 +3722,10 @@ if (goog.LOCALE == 'el') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
|
||||
}
|
||||
@@ -3449,6 +3746,10 @@ if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_AU;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CA;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
|
||||
}
|
||||
@@ -3545,6 +3846,14 @@ if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_MX;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_US;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'et') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_et;
|
||||
}
|
||||
@@ -3773,6 +4082,10 @@ if (goog.LOCALE == 'kk') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
|
||||
}
|
||||
@@ -3805,6 +4118,10 @@ if (goog.LOCALE == 'ky') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
|
||||
}
|
||||
@@ -3861,6 +4178,10 @@ if (goog.LOCALE == 'mn') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
|
||||
}
|
||||
@@ -3877,6 +4198,10 @@ if (goog.LOCALE == 'ms') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
|
||||
}
|
||||
@@ -3945,6 +4270,10 @@ if (goog.LOCALE == 'pa') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
|
||||
}
|
||||
@@ -4021,10 +4350,22 @@ if (goog.LOCALE == 'sr') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'sv') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sv;
|
||||
}
|
||||
@@ -4097,6 +4438,10 @@ if (goog.LOCALE == 'uz') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
|
||||
}
|
||||
@@ -4121,6 +4466,10 @@ if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_HK;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
|
||||
}
|
||||
|
||||
if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
|
||||
goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
|
||||
}
|
||||
|
||||
+106
-1362
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* This file is autogenerated by script:
|
||||
* http://go/generate_pluralrules.py
|
||||
* File generated from CLDR ver. 26
|
||||
* File generated from CLDR ver. 27.0.1
|
||||
*
|
||||
* Before check in, this file could have been manually edited. This is to
|
||||
* incorporate changes before we could fix CLDR. All manual modification must be
|
||||
@@ -821,6 +821,9 @@ if (goog.LOCALE == 'ar') {
|
||||
if (goog.LOCALE == 'az') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'be') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.beSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'bg') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
|
||||
}
|
||||
@@ -830,6 +833,9 @@ if (goog.LOCALE == 'bn') {
|
||||
if (goog.LOCALE == 'br') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.brSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'bs') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'ca') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
|
||||
}
|
||||
@@ -863,6 +869,9 @@ if (goog.LOCALE == 'en') {
|
||||
if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
|
||||
}
|
||||
@@ -890,6 +899,12 @@ if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
|
||||
if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'et') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
|
||||
}
|
||||
@@ -1070,6 +1085,9 @@ if (goog.LOCALE == 'sq') {
|
||||
if (goog.LOCALE == 'sr') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
|
||||
}
|
||||
if (goog.LOCALE == 'sv') {
|
||||
goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
|
||||
}
|
||||
|
||||
@@ -38,16 +38,16 @@ describe('parsePattern', function() {
|
||||
parseAndExpect('#,##,##0.00\u00A4', '', '-', '\u00A4', '\u00A4', 1, 2, 2, 2, 3);
|
||||
parseAndExpect('#,##,##0.00\u00A4;(#,##,##0.00\u00A4)',
|
||||
'', '(', '\u00A4', '\u00A4)', 1, 2, 2, 2, 3);
|
||||
parseAndExpect('\u00A4#,##0.00', '\u00A4', '\u00A4-', '', '', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4#,##0.00', '\u00A4', '-\u00A4', '', '', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4#,##0.00;(\u00A4#,##0.00)',
|
||||
'\u00A4', '(\u00A4', '', ')', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4#,##0.00;\u00A4-#,##0.00',
|
||||
'\u00A4', '\u00A4-', '', '', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4 #,##0.00', '\u00A4 ', '\u00A4 -', '', '', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4 #,##0.00', '\u00A4 ', '-\u00A4 ', '', '', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4 #,##0.00;\u00A4-#,##0.00',
|
||||
'\u00A4 ', '\u00A4-', '', '', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4 #,##0.00;\u00A4 #,##0.00-',
|
||||
'\u00A4 ', '\u00A4 ', '', '-', 1, 2, 2, 3, 3);
|
||||
parseAndExpect('\u00A4 #,##,##0.00', '\u00A4 ', '\u00A4 -', '', '', 1, 2, 2, 2, 3);
|
||||
parseAndExpect('\u00A4 #,##,##0.00', '\u00A4 ', '-\u00A4 ', '', '', 1, 2, 2, 2, 3);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ function parsePattern(pattern) {
|
||||
p.negSuf = negative.substr(pos + trunkLen).replace(/\'/g, '');
|
||||
} else {
|
||||
// hardcoded '-' sign is fine as all locale use '-' as MINUS_SIGN. (\u2212 is the same as '-')
|
||||
p.negPre = p.posPre + '-';
|
||||
p.negPre = '-' + p.posPre;
|
||||
p.negSuf = p.posSuf;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@ module.exports = function(config, specificOptions) {
|
||||
testName: specificOptions.testName || 'AngularJS',
|
||||
startConnect: true,
|
||||
options: {
|
||||
'selenium-version': '2.41.0'
|
||||
// We need selenium version +2.46 for Firefox 39 and the last selenium version for OS X is 2.45.
|
||||
// TODO: Uncomment when there is a selenium 2.46 available for OS X.
|
||||
// 'selenium-version': '2.46.0'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -35,12 +37,12 @@ module.exports = function(config, specificOptions) {
|
||||
'SL_Chrome': {
|
||||
base: 'SauceLabs',
|
||||
browserName: 'chrome',
|
||||
version: '39'
|
||||
version: '45'
|
||||
},
|
||||
'SL_Firefox': {
|
||||
base: 'SauceLabs',
|
||||
browserName: 'firefox',
|
||||
version: '31'
|
||||
version: '39'
|
||||
},
|
||||
'SL_Safari': {
|
||||
base: 'SauceLabs',
|
||||
|
||||
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().noInlineStyle && window.angular.element(document.head).prepend('<style type=\"text/css\">" + css + "</style>');";
|
||||
state.js.push(js);
|
||||
|
||||
return state;
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* HTML Parser By John Resig (ejohn.org)
|
||||
* Original code by Erik Arvidsson, Mozilla Public License
|
||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||
*
|
||||
* // Use like so:
|
||||
* htmlParser(htmlString, {
|
||||
* start: function(tag, attrs, unary) {},
|
||||
* end: function(tag) {},
|
||||
* chars: function(text) {},
|
||||
* comment: function(text) {}
|
||||
* });
|
||||
*
|
||||
* // or to get an XML string:
|
||||
* HTMLtoXML(htmlString);
|
||||
*
|
||||
* // or to get an XML DOM Document
|
||||
* HTMLtoDOM(htmlString);
|
||||
*
|
||||
* // or to inject into an existing document/DOM node
|
||||
* HTMLtoDOM(htmlString, document);
|
||||
* HTMLtoDOM(htmlString, document.body);
|
||||
*
|
||||
*/
|
||||
|
||||
(function(){
|
||||
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
var startTag = /^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
|
||||
endTag = /^<\/(\w+)[^>]*>/,
|
||||
attr = /(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
|
||||
|
||||
// Empty Elements - HTML 4.01
|
||||
var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed");
|
||||
|
||||
// Block Elements - HTML 4.01
|
||||
var block = makeMap("address,applet,blockquote,button,center,dd,del,dir,div,dl,dt,fieldset,form,frameset,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul");
|
||||
|
||||
// Inline Elements - HTML 4.01
|
||||
var inline = makeMap("a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
|
||||
|
||||
// Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
|
||||
|
||||
// Attributes that have their values filled in disabled="disabled"
|
||||
var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
|
||||
|
||||
// Special Elements (can contain anything)
|
||||
var special = makeMap("script,style");
|
||||
|
||||
var htmlParser = this.htmlParser = function( html, handler ) {
|
||||
var index, chars, match, stack = [], last = html;
|
||||
stack.last = function(){
|
||||
return this[ this.length - 1 ];
|
||||
};
|
||||
|
||||
while ( html ) {
|
||||
chars = true;
|
||||
|
||||
// Make sure we're not in a script or style element
|
||||
if ( !stack.last() || !special[ stack.last() ] ) {
|
||||
|
||||
// Comment
|
||||
if ( html.indexOf("<!--") == 0 ) {
|
||||
index = html.indexOf("-->");
|
||||
|
||||
if ( index >= 0 ) {
|
||||
if ( handler.comment )
|
||||
handler.comment( html.substring( 4, index ) );
|
||||
html = html.substring( index + 3 );
|
||||
chars = false;
|
||||
}
|
||||
|
||||
// end tag
|
||||
} else if ( html.indexOf("</") == 0 ) {
|
||||
match = html.match( endTag );
|
||||
|
||||
if ( match ) {
|
||||
html = html.substring( match[0].length );
|
||||
match[0].replace( endTag, parseEndTag );
|
||||
chars = false;
|
||||
}
|
||||
|
||||
// start tag
|
||||
} else if ( html.indexOf("<") == 0 ) {
|
||||
match = html.match( startTag );
|
||||
|
||||
if ( match ) {
|
||||
html = html.substring( match[0].length );
|
||||
match[0].replace( startTag, parseStartTag );
|
||||
chars = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( chars ) {
|
||||
index = html.indexOf("<");
|
||||
|
||||
var text = index < 0 ? html : html.substring( 0, index );
|
||||
html = index < 0 ? "" : html.substring( index );
|
||||
|
||||
if ( handler.chars )
|
||||
handler.chars( text );
|
||||
}
|
||||
|
||||
} else {
|
||||
html = html.replace(new RegExp("(.*)<\/" + stack.last() + "[^>]*>"), function(all, text){
|
||||
text = text.replace(/<!--(.*?)-->/g, "$1")
|
||||
.replace(/<!\[CDATA\[(.*?)]]>/g, "$1");
|
||||
|
||||
if ( handler.chars )
|
||||
handler.chars( text );
|
||||
|
||||
return "";
|
||||
});
|
||||
|
||||
parseEndTag( "", stack.last() );
|
||||
}
|
||||
|
||||
if ( html == last )
|
||||
throw "Parse Error: " + html;
|
||||
last = html;
|
||||
}
|
||||
|
||||
// Clean up any remaining tags
|
||||
parseEndTag();
|
||||
|
||||
function parseStartTag( tag, tagName, rest, unary ) {
|
||||
if ( block[ tagName ] ) {
|
||||
while ( stack.last() && inline[ stack.last() ] ) {
|
||||
parseEndTag( "", stack.last() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( closeSelf[ tagName ] && stack.last() == tagName ) {
|
||||
parseEndTag( "", tagName );
|
||||
}
|
||||
|
||||
unary = empty[ tagName ] || !!unary;
|
||||
|
||||
if ( !unary )
|
||||
stack.push( tagName );
|
||||
|
||||
if ( handler.start ) {
|
||||
var attrs = [];
|
||||
|
||||
rest.replace(attr, function(match, name) {
|
||||
var value = arguments[2] ? arguments[2] :
|
||||
arguments[3] ? arguments[3] :
|
||||
arguments[4] ? arguments[4] :
|
||||
fillAttrs[name] ? name : "";
|
||||
|
||||
attrs.push({
|
||||
name: name,
|
||||
value: value,
|
||||
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
|
||||
});
|
||||
});
|
||||
|
||||
if ( handler.start )
|
||||
handler.start( tagName, attrs, unary );
|
||||
}
|
||||
}
|
||||
|
||||
function parseEndTag( tag, tagName ) {
|
||||
// If no tag name is provided, clean shop
|
||||
if ( !tagName )
|
||||
var pos = 0;
|
||||
|
||||
// Find the closest opened tag of the same type
|
||||
else
|
||||
for ( var pos = stack.length - 1; pos >= 0; pos-- )
|
||||
if ( stack[ pos ] == tagName )
|
||||
break;
|
||||
|
||||
if ( pos >= 0 ) {
|
||||
// Close all the open elements, up the stack
|
||||
for ( var i = stack.length - 1; i >= pos; i-- )
|
||||
if ( handler.end )
|
||||
handler.end( stack[ i ] );
|
||||
|
||||
// Remove the open elements from the stack
|
||||
stack.length = pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.HTMLtoXML = function( html ) {
|
||||
var results = "";
|
||||
|
||||
htmlParser(html, {
|
||||
start: function( tag, attrs, unary ) {
|
||||
results += "<" + tag;
|
||||
|
||||
for ( var i = 0; i < attrs.length; i++ )
|
||||
results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';
|
||||
|
||||
results += (unary ? "/" : "") + ">";
|
||||
},
|
||||
end: function( tag ) {
|
||||
results += "</" + tag + ">";
|
||||
},
|
||||
chars: function( text ) {
|
||||
results += text;
|
||||
},
|
||||
comment: function( text ) {
|
||||
results += "<!--" + text + "-->";
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
this.HTMLtoDOM = function( html, doc ) {
|
||||
// There can be only one of these elements
|
||||
var one = makeMap("html,head,body,title");
|
||||
|
||||
// Enforce a structure for the document
|
||||
var structure = {
|
||||
link: "head",
|
||||
base: "head"
|
||||
};
|
||||
|
||||
if ( !doc ) {
|
||||
if ( typeof DOMDocument != "undefined" )
|
||||
doc = new DOMDocument();
|
||||
else if ( typeof document != "undefined" && document.implementation && document.implementation.createDocument )
|
||||
doc = document.implementation.createDocument("", "", null);
|
||||
else if ( typeof ActiveX != "undefined" )
|
||||
doc = new ActiveXObject("Msxml.DOMDocument");
|
||||
|
||||
} else
|
||||
doc = doc.ownerDocument ||
|
||||
doc.getOwnerDocument && doc.getOwnerDocument() ||
|
||||
doc;
|
||||
|
||||
var elems = [],
|
||||
documentElement = doc.documentElement ||
|
||||
doc.getDocumentElement && doc.getDocumentElement();
|
||||
|
||||
// If we're dealing with an empty document then we
|
||||
// need to pre-populate it with the HTML document structure
|
||||
if ( !documentElement && doc.createElement ) (function(){
|
||||
var html = doc.createElement("html");
|
||||
var head = doc.createElement("head");
|
||||
head.appendChild( doc.createElement("title") );
|
||||
html.appendChild( head );
|
||||
html.appendChild( doc.createElement("body") );
|
||||
doc.appendChild( html );
|
||||
})();
|
||||
|
||||
// Find all the unique elements
|
||||
if ( doc.getElementsByTagName )
|
||||
for ( var i in one )
|
||||
one[ i ] = doc.getElementsByTagName( i )[0];
|
||||
|
||||
// If we're working with a document, inject contents into
|
||||
// the body element
|
||||
var curParentNode = one.body;
|
||||
|
||||
htmlParser( html, {
|
||||
start: function( tagName, attrs, unary ) {
|
||||
// If it's a pre-built element, then we can ignore
|
||||
// its construction
|
||||
if ( one[ tagName ] ) {
|
||||
curParentNode = one[ tagName ];
|
||||
return;
|
||||
}
|
||||
|
||||
var elem = doc.createElement( tagName );
|
||||
|
||||
for ( var attr in attrs )
|
||||
elem.setAttribute( attrs[ attr ].name, attrs[ attr ].value );
|
||||
|
||||
if ( structure[ tagName ] && typeof one[ structure[ tagName ] ] != "boolean" )
|
||||
one[ structure[ tagName ] ].appendChild( elem );
|
||||
|
||||
else if ( curParentNode && curParentNode.appendChild )
|
||||
curParentNode.appendChild( elem );
|
||||
|
||||
if ( !unary ) {
|
||||
elems.push( elem );
|
||||
curParentNode = elem;
|
||||
}
|
||||
},
|
||||
end: function( tag ) {
|
||||
elems.length -= 1;
|
||||
|
||||
// Init the new parentNode
|
||||
curParentNode = elems[ elems.length - 1 ];
|
||||
},
|
||||
chars: function( text ) {
|
||||
curParentNode.appendChild( doc.createTextNode( text ) );
|
||||
},
|
||||
comment: function( text ) {
|
||||
// create comment node
|
||||
}
|
||||
});
|
||||
|
||||
return doc;
|
||||
};
|
||||
|
||||
function makeMap(str){
|
||||
var obj = {}, items = str.split(",");
|
||||
for ( var i = 0; i < items.length; i++ )
|
||||
obj[ items[i] ] = true;
|
||||
return obj;
|
||||
}
|
||||
})();
|
||||
@@ -4,6 +4,8 @@
|
||||
var isFunction = function isFunction(value){return typeof value == 'function';};
|
||||
var isPromiseLike = function isPromiseLike(obj) {return obj && isFunction(obj.then);};
|
||||
var isObject = function isObject(value){return value != null && typeof value === 'object';};
|
||||
var isUndefined = function isUndefined(value) {return typeof value === 'undefined';};
|
||||
|
||||
var minErr = function minErr (module, constructor) {
|
||||
return function (){
|
||||
var ErrorConstructor = constructor || Error;
|
||||
@@ -11,6 +13,20 @@ var minErr = function minErr (module, constructor) {
|
||||
};
|
||||
};
|
||||
|
||||
var extend = function extend(dst) {
|
||||
for (var i = 1, ii = arguments.length; i < ii; i++) {
|
||||
var obj = arguments[i];
|
||||
if (obj) {
|
||||
var keys = Object.keys(obj);
|
||||
for (var j = 0, jj = keys.length; j < jj; j++) {
|
||||
var key = keys[j];
|
||||
dst[key] = obj[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
};
|
||||
|
||||
var $q = qFactory(process.nextTick, function noopExceptionHandler() {});
|
||||
|
||||
exports.resolved = $q.resolve;
|
||||
|
||||
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"
|
||||
+3800
-51
File diff suppressed because it is too large
Load Diff
Generated
+5895
-115
File diff suppressed because it is too large
Load Diff
+18
-5
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"license": "MIT",
|
||||
"branchVersion": "^1.4.0-beta.0",
|
||||
"branchPattern": "1.4.*",
|
||||
"branchVersion": "^1.5.0-beta.0",
|
||||
"branchPattern": "1.5.*",
|
||||
"distTag": "beta",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.js.git"
|
||||
@@ -12,6 +13,11 @@
|
||||
"npm": "~2.5"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"scripts": {
|
||||
"preinstall": "node scripts/npm/check-node-modules.js --purge",
|
||||
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js",
|
||||
"commit": "git-cz"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-benchpress": "0.x.x",
|
||||
"benchmark": "1.x.x",
|
||||
@@ -19,8 +25,10 @@
|
||||
"browserstacktunnel-wrapper": "~1.3.1",
|
||||
"canonical-path": "0.0.2",
|
||||
"cheerio": "^0.17.0",
|
||||
"commitizen": "^2.3.0",
|
||||
"cz-conventional-changelog": "1.1.4",
|
||||
"dgeni": "^0.4.0",
|
||||
"dgeni-packages": "^0.10.0",
|
||||
"dgeni-packages": "^0.11.0",
|
||||
"event-stream": "~3.1.0",
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-bump": "~0.0.13",
|
||||
@@ -31,7 +39,7 @@
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"grunt-ddescribe-iit": "~0.0.1",
|
||||
"grunt-jasmine-node": "git://github.com/vojtajina/grunt-jasmine-node.git#fix-grunt-exit-code",
|
||||
"grunt-jscs": "~1.2.0",
|
||||
"grunt-jscs": "^2.1.0",
|
||||
"grunt-merge-conflict": "~0.0.1",
|
||||
"grunt-shell": "~1.1.1",
|
||||
"gulp": "~3.8.0",
|
||||
@@ -75,5 +83,10 @@
|
||||
"url": "https://github.com/angular/angular.js/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"dependencies": {}
|
||||
"dependencies": {},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-conventional-changelog"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ config.specs = [
|
||||
];
|
||||
|
||||
config.capabilities = {
|
||||
browserName: 'chrome',
|
||||
browserName: 'chrome'
|
||||
};
|
||||
|
||||
exports.config = config;
|
||||
|
||||
@@ -14,6 +14,8 @@ function init {
|
||||
TMP_DIR=$(resolveDir ../../tmp)
|
||||
BUILD_DIR=$(resolveDir ../../build)
|
||||
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
|
||||
# get the npm dist-tag from a custom property (distTag) in package.json
|
||||
DIST_TAG=$(readJsonProp "package.json" "distTag")
|
||||
}
|
||||
|
||||
|
||||
@@ -95,19 +97,8 @@ function publish {
|
||||
|
||||
# don't publish every build to npm
|
||||
if [ "${NEW_VERSION/+sha}" = "$NEW_VERSION" ] ; then
|
||||
if [ "${NEW_VERSION/-}" = "$NEW_VERSION" ] ; then
|
||||
if [[ $NEW_VERSION =~ ^1\.2\.[0-9]+$ ]] ; then
|
||||
# publish 1.2.x releases with the appropriate tag
|
||||
# this ensures that `npm install` by default will not grab `1.2.x` releases
|
||||
npm publish --tag=old
|
||||
else
|
||||
# publish releases as "latest"
|
||||
npm publish
|
||||
fi
|
||||
else
|
||||
# publish prerelease builds with the beta tag
|
||||
npm publish --tag=beta
|
||||
fi
|
||||
echo "-- Publishing to npm as $DIST_TAG"
|
||||
npm publish --tag=$DIST_TAG
|
||||
fi
|
||||
|
||||
cd $SCRIPT_DIR
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Implementation based on:
|
||||
// https://github.com/angular/angular/blob/3b9c08676a4c921bbfa847802e08566fb601ba7a/tools/npm/check-node-modules.js
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
var purgeIfStale = process.argv.indexOf('--purge') !== -1;
|
||||
|
||||
process.chdir(PROJECT_ROOT);
|
||||
checkNodeModules(purgeIfStale);
|
||||
}
|
||||
|
||||
function checkNodeModules(purgeIfStale) {
|
||||
var nodeModulesOk = compareMarkerFiles(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE);
|
||||
|
||||
if (nodeModulesOk) {
|
||||
console.log(':-) npm dependencies are looking good!');
|
||||
} else if (purgeIfStale) {
|
||||
console.log(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.log(' Purging \'' + NODE_MODULES_DIR + '\'...');
|
||||
deleteDirSync(NODE_MODULES_DIR);
|
||||
} else {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.warn(separator);
|
||||
console.warn(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.warn('You can rebuild the dependencies by running `npm install`.');
|
||||
console.warn(separator);
|
||||
}
|
||||
|
||||
return nodeModulesOk;
|
||||
}
|
||||
|
||||
function compareMarkerFiles(markerFilePath, cachedMarkerFilePath) {
|
||||
if (!fs.existsSync(cachedMarkerFilePath)) return false;
|
||||
|
||||
var opts = {encoding: 'utf-8'};
|
||||
var markerContent = fs.readFileSync(markerFilePath, opts);
|
||||
var cachedMarkerContent = fs.readFileSync(cachedMarkerFilePath, opts);
|
||||
|
||||
return markerContent === cachedMarkerContent;
|
||||
}
|
||||
|
||||
// Custom implementation of `rm -rf` that works consistently across OSes
|
||||
function deleteDirSync(path) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.readdirSync(path).forEach(deleteDirOrFileSync);
|
||||
fs.rmdirSync(path);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function deleteDirOrFileSync(subpath) {
|
||||
var curPath = path + '/' + subpath;
|
||||
|
||||
if (fs.lstatSync(curPath).isDirectory()) {
|
||||
deleteDirSync(curPath);
|
||||
} else {
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
process.chdir(PROJECT_ROOT);
|
||||
copyFile(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE, onCopied);
|
||||
}
|
||||
|
||||
// Implementation based on:
|
||||
// https://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js#answer-21995878
|
||||
function copyFile(srcPath, dstPath, callback) {
|
||||
var callbackCalled = false;
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
done(new Error('Missing source file: ' + srcPath));
|
||||
return;
|
||||
}
|
||||
|
||||
var rs = fs.createReadStream(srcPath);
|
||||
rs.on('error', done);
|
||||
|
||||
var ws = fs.createWriteStream(dstPath);
|
||||
ws.on('error', done);
|
||||
ws.on('finish', done);
|
||||
|
||||
rs.pipe(ws);
|
||||
|
||||
// Helpers
|
||||
function done(err) {
|
||||
if (callback && !callbackCalled) {
|
||||
callbackCalled = true;
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onCopied(err) {
|
||||
if (err) {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.error(separator);
|
||||
console.error(
|
||||
'Failed to copy `' + NPM_SHRINKWRAP_FILE + '` to `' + NPM_SHRINKWRAP_CACHED_FILE + '`:');
|
||||
console.error(err);
|
||||
console.error(separator);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SHRINKWRAP_FILE=npm-shrinkwrap.json
|
||||
SHRINKWRAP_CACHED_FILE=node_modules/npm-shrinkwrap.cached.json
|
||||
|
||||
if diff -q $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE; then
|
||||
echo 'No shrinkwrap changes detected. npm install will be skipped...';
|
||||
else
|
||||
echo 'Blowing away node_modules and reinstalling npm dependencies...'
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
cp $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE
|
||||
echo 'npm install successful!'
|
||||
fi
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Has to be run from project root directory.
|
||||
|
||||
./lib/${BROWSER_PROVIDER}/teardown_tunnel.sh
|
||||
@@ -94,8 +94,6 @@
|
||||
"VALIDITY_STATE_PROPERTY": false,
|
||||
"reloadWithDebugInfo": false,
|
||||
|
||||
"skipDestroyOnNextJQueryCleanData": true,
|
||||
|
||||
"NODE_TYPE_ELEMENT": false,
|
||||
"NODE_TYPE_ATTRIBUTE": false,
|
||||
"NODE_TYPE_TEXT": false,
|
||||
@@ -163,9 +161,6 @@
|
||||
/* ng/compile.js */
|
||||
"directiveNormalize": false,
|
||||
|
||||
/* ng/parse.js */
|
||||
"setter": false,
|
||||
|
||||
/* ng/directive/directives.js */
|
||||
"ngDirective": false,
|
||||
|
||||
|
||||
+169
-127
@@ -198,20 +198,24 @@ msie = document.documentMode;
|
||||
* String ...)
|
||||
*/
|
||||
function isArrayLike(obj) {
|
||||
if (obj == null || isWindow(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// `null`, `undefined` and `window` are not array-like
|
||||
if (obj == null || isWindow(obj)) return false;
|
||||
|
||||
// arrays, strings and jQuery/jqLite objects are array like
|
||||
// * jqLite is either the jQuery or jqLite constructor function
|
||||
// * we have to check the existance of jqLite first as this method is called
|
||||
// via the forEach method when constructing the jqLite object in the first place
|
||||
if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
return isString(obj) || isArray(obj) || length === 0 ||
|
||||
typeof length === 'number' && length > 0 && (length - 1) in obj;
|
||||
// NodeList objects (with `item` method) and
|
||||
// other objects with suitable length characteristics are array-like
|
||||
return isNumber(length) &&
|
||||
(length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,6 +358,12 @@ function baseExtend(dst, objs, deep) {
|
||||
if (deep && isObject(src)) {
|
||||
if (isDate(src)) {
|
||||
dst[key] = new Date(src.valueOf());
|
||||
} else if (isRegExp(src)) {
|
||||
dst[key] = new RegExp(src);
|
||||
} else if (src.nodeName) {
|
||||
dst[key] = src.cloneNode(true);
|
||||
} else if (isElement(src)) {
|
||||
dst[key] = src.clone();
|
||||
} else {
|
||||
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
|
||||
baseExtend(dst[key], [src], true);
|
||||
@@ -469,7 +479,7 @@ identity.$inject = [];
|
||||
function valueFn(value) {return function() {return value;};}
|
||||
|
||||
function hasCustomToString(obj) {
|
||||
return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
|
||||
return isFunction(obj.toString) && obj.toString !== toString;
|
||||
}
|
||||
|
||||
|
||||
@@ -668,9 +678,9 @@ function isPromiseLike(obj) {
|
||||
}
|
||||
|
||||
|
||||
var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/;
|
||||
var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
|
||||
function isTypedArray(value) {
|
||||
return TYPED_ARRAY_REGEXP.test(toString.call(value));
|
||||
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
|
||||
}
|
||||
|
||||
|
||||
@@ -792,98 +802,111 @@ function arrayRemove(array, value) {
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
function copy(source, destination, stackSource, stackDest) {
|
||||
if (isWindow(source) || isScope(source)) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}
|
||||
if (isTypedArray(destination)) {
|
||||
throw ngMinErr('cpta',
|
||||
"Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
function copy(source, destination) {
|
||||
var stackSource = [];
|
||||
var stackDest = [];
|
||||
|
||||
if (!destination) {
|
||||
destination = source;
|
||||
if (isObject(source)) {
|
||||
var index;
|
||||
if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
|
||||
return stackDest[index];
|
||||
}
|
||||
|
||||
// TypedArray, Date and RegExp have specific copy functionality and must be
|
||||
// pushed onto the stack before returning.
|
||||
// Array and other objects create the base object and recurse to copy child
|
||||
// objects. The array/object will be pushed onto the stack when recursed.
|
||||
if (isArray(source)) {
|
||||
return copy(source, [], stackSource, stackDest);
|
||||
} else if (isTypedArray(source)) {
|
||||
destination = new source.constructor(source);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else {
|
||||
var emptyObject = Object.create(getPrototypeOf(source));
|
||||
return copy(source, emptyObject, stackSource, stackDest);
|
||||
}
|
||||
|
||||
if (stackDest) {
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
}
|
||||
if (destination) {
|
||||
if (isTypedArray(destination)) {
|
||||
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
} else {
|
||||
if (source === destination) throw ngMinErr('cpi',
|
||||
"Can't copy! Source and destination are identical.");
|
||||
|
||||
stackSource = stackSource || [];
|
||||
stackDest = stackDest || [];
|
||||
|
||||
if (isObject(source)) {
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
if (source === destination) {
|
||||
throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
|
||||
}
|
||||
|
||||
// Empty the destination object
|
||||
if (isArray(destination)) {
|
||||
destination.length = 0;
|
||||
} else {
|
||||
forEach(destination, function(value, key) {
|
||||
if (key !== '$$hashKey') {
|
||||
delete destination[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
return copyRecurse(source, destination);
|
||||
}
|
||||
|
||||
return copyElement(source);
|
||||
|
||||
function copyRecurse(source, destination) {
|
||||
var h = destination.$$hashKey;
|
||||
var result, key;
|
||||
if (isArray(source)) {
|
||||
destination.length = 0;
|
||||
for (var i = 0; i < source.length; i++) {
|
||||
destination.push(copy(source[i], null, stackSource, stackDest));
|
||||
for (var i = 0, ii = source.length; i < ii; i++) {
|
||||
destination.push(copyElement(source[i]));
|
||||
}
|
||||
} else if (isBlankObject(source)) {
|
||||
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
||||
for (key in source) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
} else if (source && typeof source.hasOwnProperty === 'function') {
|
||||
// Slow path, which must rely on hasOwnProperty
|
||||
for (key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var h = destination.$$hashKey;
|
||||
if (isArray(destination)) {
|
||||
destination.length = 0;
|
||||
} else {
|
||||
forEach(destination, function(value, key) {
|
||||
delete destination[key];
|
||||
});
|
||||
}
|
||||
if (isBlankObject(source)) {
|
||||
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
||||
for (key in source) {
|
||||
destination[key] = copy(source[key], null, stackSource, stackDest);
|
||||
}
|
||||
} else if (source && typeof source.hasOwnProperty === 'function') {
|
||||
// Slow path, which must rely on hasOwnProperty
|
||||
for (key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
destination[key] = copy(source[key], null, stackSource, stackDest);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Slowest path --- hasOwnProperty can't be called as a method
|
||||
for (key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
destination[key] = copy(source[key], null, stackSource, stackDest);
|
||||
}
|
||||
// Slowest path --- hasOwnProperty can't be called as a method
|
||||
for (key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
}
|
||||
setHashKey(destination,h);
|
||||
}
|
||||
setHashKey(destination, h);
|
||||
return destination;
|
||||
}
|
||||
|
||||
function copyElement(source) {
|
||||
// Simple values
|
||||
if (!isObject(source)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// Already copied values
|
||||
var index = stackSource.indexOf(source);
|
||||
if (index !== -1) {
|
||||
return stackDest[index];
|
||||
}
|
||||
|
||||
if (isWindow(source) || isScope(source)) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}
|
||||
|
||||
var needsRecurse = false;
|
||||
var destination;
|
||||
|
||||
if (isArray(source)) {
|
||||
destination = [];
|
||||
needsRecurse = true;
|
||||
} else if (isTypedArray(source)) {
|
||||
destination = new source.constructor(source);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else if (isFunction(source.cloneNode)) {
|
||||
destination = source.cloneNode(true);
|
||||
} else {
|
||||
destination = Object.create(getPrototypeOf(source));
|
||||
needsRecurse = true;
|
||||
}
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
|
||||
return needsRecurse
|
||||
? copyRecurse(source, destination)
|
||||
: destination;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -973,7 +996,7 @@ function equals(o1, o2) {
|
||||
for (key in o2) {
|
||||
if (!(key in keySet) &&
|
||||
key.charAt(0) !== '$' &&
|
||||
o2[key] !== undefined &&
|
||||
isDefined(o2[key]) &&
|
||||
!isFunction(o2[key])) return false;
|
||||
}
|
||||
return true;
|
||||
@@ -984,22 +1007,39 @@ function equals(o1, o2) {
|
||||
}
|
||||
|
||||
var csp = function() {
|
||||
if (isDefined(csp.isActive_)) return csp.isActive_;
|
||||
if (!isDefined(csp.rules)) {
|
||||
|
||||
var active = !!(document.querySelector('[ng-csp]') ||
|
||||
document.querySelector('[data-ng-csp]'));
|
||||
|
||||
if (!active) {
|
||||
var ngCspElement = (document.querySelector('[ng-csp]') ||
|
||||
document.querySelector('[data-ng-csp]'));
|
||||
|
||||
if (ngCspElement) {
|
||||
var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
|
||||
ngCspElement.getAttribute('data-ng-csp');
|
||||
csp.rules = {
|
||||
noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
|
||||
noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
|
||||
};
|
||||
} else {
|
||||
csp.rules = {
|
||||
noUnsafeEval: noUnsafeEval(),
|
||||
noInlineStyle: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return csp.rules;
|
||||
|
||||
function noUnsafeEval() {
|
||||
try {
|
||||
/* jshint -W031, -W054 */
|
||||
new Function('');
|
||||
/* jshint +W031, +W054 */
|
||||
return false;
|
||||
} catch (e) {
|
||||
active = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (csp.isActive_ = active);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1231,13 +1271,19 @@ function tryDecodeURIComponent(value) {
|
||||
* @returns {Object.<string,boolean|Array>}
|
||||
*/
|
||||
function parseKeyValue(/**string*/keyValue) {
|
||||
var obj = {}, key_value, key;
|
||||
var obj = {};
|
||||
forEach((keyValue || "").split('&'), function(keyValue) {
|
||||
var splitPoint, key, val;
|
||||
if (keyValue) {
|
||||
key_value = keyValue.replace(/\+/g,'%20').split('=');
|
||||
key = tryDecodeURIComponent(key_value[0]);
|
||||
key = keyValue = keyValue.replace(/\+/g,'%20');
|
||||
splitPoint = keyValue.indexOf('=');
|
||||
if (splitPoint !== -1) {
|
||||
key = keyValue.substring(0, splitPoint);
|
||||
val = keyValue.substring(splitPoint + 1);
|
||||
}
|
||||
key = tryDecodeURIComponent(key);
|
||||
if (isDefined(key)) {
|
||||
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
|
||||
val = isDefined(val) ? tryDecodeURIComponent(val) : true;
|
||||
if (!hasOwnProperty.call(obj, key)) {
|
||||
obj[key] = val;
|
||||
} else if (isArray(obj[key])) {
|
||||
@@ -1636,7 +1682,6 @@ function snake_case(name, separator) {
|
||||
}
|
||||
|
||||
var bindJQueryFired = false;
|
||||
var skipDestroyOnNextJQueryCleanData;
|
||||
function bindJQuery() {
|
||||
var originalCleanData;
|
||||
|
||||
@@ -1646,10 +1691,9 @@ function bindJQuery() {
|
||||
|
||||
// bind to jQuery if present;
|
||||
var jqName = jq();
|
||||
jQuery = window.jQuery; // use default jQuery.
|
||||
if (isDefined(jqName)) { // `ngJq` present
|
||||
jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
|
||||
}
|
||||
jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
|
||||
!jqName ? undefined : // use jqLite
|
||||
window[jqName]; // use jQuery specified by `ngJq`
|
||||
|
||||
// Use jQuery if it exists with proper functionality, otherwise default to us.
|
||||
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
|
||||
@@ -1671,15 +1715,11 @@ function bindJQuery() {
|
||||
originalCleanData = jQuery.cleanData;
|
||||
jQuery.cleanData = function(elems) {
|
||||
var events;
|
||||
if (!skipDestroyOnNextJQueryCleanData) {
|
||||
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
|
||||
events = jQuery._data(elem, "events");
|
||||
if (events && events.$destroy) {
|
||||
jQuery(elem).triggerHandler('$destroy');
|
||||
}
|
||||
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
|
||||
events = jQuery._data(elem, "events");
|
||||
if (events && events.$destroy) {
|
||||
jQuery(elem).triggerHandler('$destroy');
|
||||
}
|
||||
} else {
|
||||
skipDestroyOnNextJQueryCleanData = false;
|
||||
}
|
||||
originalCleanData(elems);
|
||||
};
|
||||
@@ -1754,22 +1794,24 @@ function getter(obj, path, bindFnToScope) {
|
||||
/**
|
||||
* Return the DOM siblings between the first and last node in the given array.
|
||||
* @param {Array} array like object
|
||||
* @returns {jqLite} jqLite collection containing the nodes
|
||||
* @returns {Array} the inputted object or a jqLite collection containing the nodes
|
||||
*/
|
||||
function getBlockNodes(nodes) {
|
||||
// TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
|
||||
// collection, otherwise update the original collection.
|
||||
// TODO(perf): update `nodes` instead of creating a new object?
|
||||
var node = nodes[0];
|
||||
var endNode = nodes[nodes.length - 1];
|
||||
var blockNodes = [node];
|
||||
var blockNodes;
|
||||
|
||||
do {
|
||||
node = node.nextSibling;
|
||||
if (!node) break;
|
||||
blockNodes.push(node);
|
||||
} while (node !== endNode);
|
||||
for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
|
||||
if (blockNodes || nodes[i] !== node) {
|
||||
if (!blockNodes) {
|
||||
blockNodes = jqLite(slice.call(nodes, 0, i));
|
||||
}
|
||||
blockNodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
return jqLite(blockNodes);
|
||||
return blockNodes || nodes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-11
@@ -3,7 +3,6 @@
|
||||
/* global angularModule: true,
|
||||
version: true,
|
||||
|
||||
$LocaleProvider,
|
||||
$CompileProvider,
|
||||
|
||||
htmlAnchorDirective,
|
||||
@@ -20,7 +19,6 @@
|
||||
ngClassDirective,
|
||||
ngClassEvenDirective,
|
||||
ngClassOddDirective,
|
||||
ngCspDirective,
|
||||
ngCloakDirective,
|
||||
ngControllerDirective,
|
||||
ngFormDirective,
|
||||
@@ -57,14 +55,17 @@
|
||||
|
||||
$AnchorScrollProvider,
|
||||
$AnimateProvider,
|
||||
$CoreAnimateCssProvider,
|
||||
$$CoreAnimateQueueProvider,
|
||||
$$CoreAnimateRunnerProvider,
|
||||
$BrowserProvider,
|
||||
$CacheFactoryProvider,
|
||||
$ControllerProvider,
|
||||
$DateProvider,
|
||||
$DocumentProvider,
|
||||
$ExceptionHandlerProvider,
|
||||
$FilterProvider,
|
||||
$$ForceReflowProvider,
|
||||
$InterpolateProvider,
|
||||
$IntervalProvider,
|
||||
$$HashMapProvider,
|
||||
@@ -72,6 +73,7 @@
|
||||
$HttpParamSerializerProvider,
|
||||
$HttpParamSerializerJQLikeProvider,
|
||||
$HttpBackendProvider,
|
||||
$xhrFactoryProvider,
|
||||
$LocationProvider,
|
||||
$LogProvider,
|
||||
$ParseProvider,
|
||||
@@ -87,7 +89,6 @@
|
||||
$$TestabilityProvider,
|
||||
$TimeoutProvider,
|
||||
$$RAFProvider,
|
||||
$$AsyncCallbackProvider,
|
||||
$WindowProvider,
|
||||
$$jqLiteProvider,
|
||||
$$CookieReaderProvider
|
||||
@@ -99,8 +100,9 @@
|
||||
* @name angular.version
|
||||
* @module ng
|
||||
* @description
|
||||
* An object that contains information about the current AngularJS version. This object has the
|
||||
* following properties:
|
||||
* An object that contains information about the current AngularJS version.
|
||||
*
|
||||
* This object has the following properties:
|
||||
*
|
||||
* - `full` – `{string}` – Full version string, such as "0.9.18".
|
||||
* - `major` – `{number}` – Major version number, such as "0".
|
||||
@@ -152,11 +154,6 @@ function publishExternalAPI(angular) {
|
||||
});
|
||||
|
||||
angularModule = setupModuleLoader(window);
|
||||
try {
|
||||
angularModule('ngLocale');
|
||||
} catch (e) {
|
||||
angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
|
||||
}
|
||||
|
||||
angularModule('ng', ['ngLocale'], ['$provide',
|
||||
function ngModule($provide) {
|
||||
@@ -219,6 +216,7 @@ function publishExternalAPI(angular) {
|
||||
$provide.provider({
|
||||
$anchorScroll: $AnchorScrollProvider,
|
||||
$animate: $AnimateProvider,
|
||||
$animateCss: $CoreAnimateCssProvider,
|
||||
$$animateQueue: $$CoreAnimateQueueProvider,
|
||||
$$AnimateRunner: $$CoreAnimateRunnerProvider,
|
||||
$browser: $BrowserProvider,
|
||||
@@ -227,12 +225,14 @@ function publishExternalAPI(angular) {
|
||||
$document: $DocumentProvider,
|
||||
$exceptionHandler: $ExceptionHandlerProvider,
|
||||
$filter: $FilterProvider,
|
||||
$$forceReflow: $$ForceReflowProvider,
|
||||
$interpolate: $InterpolateProvider,
|
||||
$interval: $IntervalProvider,
|
||||
$http: $HttpProvider,
|
||||
$httpParamSerializer: $HttpParamSerializerProvider,
|
||||
$httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
|
||||
$httpBackend: $HttpBackendProvider,
|
||||
$xhrFactory: $xhrFactoryProvider,
|
||||
$location: $LocationProvider,
|
||||
$log: $LogProvider,
|
||||
$parse: $ParseProvider,
|
||||
@@ -248,7 +248,6 @@ function publishExternalAPI(angular) {
|
||||
$timeout: $TimeoutProvider,
|
||||
$window: $WindowProvider,
|
||||
$$rAF: $$RAFProvider,
|
||||
$$asyncCallback: $$AsyncCallbackProvider,
|
||||
$$jqLite: $$jqLiteProvider,
|
||||
$$HashMap: $$HashMapProvider,
|
||||
$$cookieReader: $$CookieReaderProvider
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
if (window.angular.bootstrap) {
|
||||
//AngularJS is already loaded, so we can return here...
|
||||
console.log('WARNING: Tried to load angular more than once.');
|
||||
return;
|
||||
}
|
||||
|
||||
//try to bind to jquery now so that one can write jqLite(document).ready()
|
||||
//but we will rebind on bootstrap again.
|
||||
bindJQuery();
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
if (window.angular.bootstrap) {
|
||||
//AngularJS is already loaded, so we can return here...
|
||||
console.log('WARNING: Tried to load angular more than once.');
|
||||
return;
|
||||
}
|
||||
|
||||
//try to bind to jquery now so that one can write jqLite(document).ready()
|
||||
//but we will rebind on bootstrap again.
|
||||
bindJQuery();
|
||||
|
||||
publishExternalAPI(angular);
|
||||
|
||||
jqLite(document).ready(function() {
|
||||
angularInit(document, bootstrap);
|
||||
});
|
||||
|
||||
+21
-11
@@ -62,17 +62,23 @@
|
||||
* Implicit module which gets automatically added to each {@link auto.$injector $injector}.
|
||||
*/
|
||||
|
||||
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
|
||||
var ARROW_ARG = /^([^\(]+?)=>/;
|
||||
var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
|
||||
var FN_ARG_SPLIT = /,/;
|
||||
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
|
||||
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
||||
var $injectorMinErr = minErr('$injector');
|
||||
|
||||
function extractArgs(fn) {
|
||||
var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
|
||||
args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
|
||||
return args;
|
||||
}
|
||||
|
||||
function anonFn(fn) {
|
||||
// For anonymous functions, showing at the very least the function signature can help in
|
||||
// debugging.
|
||||
var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
|
||||
args = fnText.match(FN_ARGS);
|
||||
var args = extractArgs(fn);
|
||||
if (args) {
|
||||
return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
|
||||
}
|
||||
@@ -81,7 +87,6 @@ function anonFn(fn) {
|
||||
|
||||
function annotate(fn, strictDi, name) {
|
||||
var $inject,
|
||||
fnText,
|
||||
argDecl,
|
||||
last;
|
||||
|
||||
@@ -96,8 +101,7 @@ function annotate(fn, strictDi, name) {
|
||||
throw $injectorMinErr('strictdi',
|
||||
'{0} is not using explicit annotation and cannot be invoked in strict mode', name);
|
||||
}
|
||||
fnText = fn.toString().replace(STRIP_COMMENTS, '');
|
||||
argDecl = fnText.match(FN_ARGS);
|
||||
argDecl = extractArgs(fn);
|
||||
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
|
||||
arg.replace(FN_ARG, function(all, underscore, name) {
|
||||
$inject.push(name);
|
||||
@@ -638,14 +642,19 @@ function createInjector(modulesToLoad, strictDi) {
|
||||
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
|
||||
})),
|
||||
instanceCache = {},
|
||||
instanceInjector = (instanceCache.$injector =
|
||||
protoInstanceInjector =
|
||||
createInternalInjector(instanceCache, function(serviceName, caller) {
|
||||
var provider = providerInjector.get(serviceName + providerSuffix, caller);
|
||||
return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
|
||||
}));
|
||||
return instanceInjector.invoke(
|
||||
provider.$get, provider, undefined, serviceName);
|
||||
}),
|
||||
instanceInjector = protoInstanceInjector;
|
||||
|
||||
|
||||
forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
|
||||
providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };
|
||||
var runBlocks = loadModules(modulesToLoad);
|
||||
instanceInjector = protoInstanceInjector.get('$injector');
|
||||
instanceInjector.strictDi = strictDi;
|
||||
forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });
|
||||
|
||||
return instanceInjector;
|
||||
|
||||
@@ -718,6 +727,7 @@ function createInjector(modulesToLoad, strictDi) {
|
||||
// Module Loading
|
||||
////////////////////////////////////
|
||||
function loadModules(modulesToLoad) {
|
||||
assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
|
||||
var runBlocks = [], moduleFn;
|
||||
forEach(modulesToLoad, function(module) {
|
||||
if (loadedModules.get(module)) return;
|
||||
|
||||
+78
-46
@@ -65,7 +65,7 @@
|
||||
* - [`html()`](http://api.jquery.com/html/)
|
||||
* - [`next()`](http://api.jquery.com/next/) - Does not support selectors
|
||||
* - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
|
||||
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
|
||||
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
|
||||
* - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
|
||||
* - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
|
||||
* - [`prepend()`](http://api.jquery.com/prepend/)
|
||||
@@ -79,7 +79,7 @@
|
||||
* - [`text()`](http://api.jquery.com/text/)
|
||||
* - [`toggleClass()`](http://api.jquery.com/toggleClass/)
|
||||
* - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
|
||||
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
|
||||
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
|
||||
* - [`val()`](http://api.jquery.com/val/)
|
||||
* - [`wrap()`](http://api.jquery.com/wrap/)
|
||||
*
|
||||
@@ -151,10 +151,10 @@ function camelCase(name) {
|
||||
replace(MOZ_HACK_REGEXP, 'Moz$1');
|
||||
}
|
||||
|
||||
var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
|
||||
var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
|
||||
var HTML_REGEXP = /<|&#?\w+;/;
|
||||
var TAG_NAME_REGEXP = /<([\w:]+)/;
|
||||
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
|
||||
var TAG_NAME_REGEXP = /<([\w:-]+)/;
|
||||
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
|
||||
|
||||
var wrapMap = {
|
||||
'option': [1, '<select multiple="multiple">', '</select>'],
|
||||
@@ -189,6 +189,12 @@ function jqLiteHasData(node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function jqLiteCleanData(nodes) {
|
||||
for (var i = 0, ii = nodes.length; i < ii; i++) {
|
||||
jqLiteRemoveData(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function jqLiteBuildFragment(html, context) {
|
||||
var tmp, tag, wrap,
|
||||
fragment = context.createDocumentFragment(),
|
||||
@@ -241,6 +247,14 @@ function jqLiteParseHTML(html, context) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
|
||||
var jqLiteContains = Node.prototype.contains || function(arg) {
|
||||
// jshint bitwise: false
|
||||
return !!(this.compareDocumentPosition(arg) & 16);
|
||||
// jshint bitwise: true
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////
|
||||
function JQLite(element) {
|
||||
if (element instanceof JQLite) {
|
||||
@@ -299,17 +313,23 @@ function jqLiteOff(element, type, fn, unsupported) {
|
||||
delete events[type];
|
||||
}
|
||||
} else {
|
||||
forEach(type.split(' '), function(type) {
|
||||
if (isDefined(fn)) {
|
||||
var listenerFns = events[type];
|
||||
arrayRemove(listenerFns || [], fn);
|
||||
if (listenerFns && listenerFns.length > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListenerFn(element, type, handle);
|
||||
delete events[type];
|
||||
var removeHandler = function(type) {
|
||||
var listenerFns = events[type];
|
||||
if (isDefined(fn)) {
|
||||
arrayRemove(listenerFns || [], fn);
|
||||
}
|
||||
if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
|
||||
removeEventListenerFn(element, type, handle);
|
||||
delete events[type];
|
||||
}
|
||||
};
|
||||
|
||||
forEach(type.split(' '), function(type) {
|
||||
removeHandler(type);
|
||||
if (MOUSE_EVENT_MAP[type]) {
|
||||
removeHandler(MOUSE_EVENT_MAP[type]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -450,7 +470,7 @@ function jqLiteInheritedData(element, name, value) {
|
||||
|
||||
while (element) {
|
||||
for (var i = 0, ii = names.length; i < ii; i++) {
|
||||
if ((value = jqLite.data(element, names[i])) !== undefined) return value;
|
||||
if (isDefined(value = jqLite.data(element, names[i]))) return value;
|
||||
}
|
||||
|
||||
// If dealing with a document fragment node with a host element, and no parent, use the host
|
||||
@@ -556,15 +576,15 @@ function getBooleanAttrName(element, name) {
|
||||
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
|
||||
}
|
||||
|
||||
function getAliasedAttrName(element, name) {
|
||||
var nodeName = element.nodeName;
|
||||
return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
|
||||
function getAliasedAttrName(name) {
|
||||
return ALIASED_ATTR[name];
|
||||
}
|
||||
|
||||
forEach({
|
||||
data: jqLiteData,
|
||||
removeData: jqLiteRemoveData,
|
||||
hasData: jqLiteHasData
|
||||
hasData: jqLiteHasData,
|
||||
cleanData: jqLiteCleanData
|
||||
}, function(fn, name) {
|
||||
JQLite[name] = fn;
|
||||
});
|
||||
@@ -695,7 +715,7 @@ forEach({
|
||||
// in a way that survives minification.
|
||||
// jqLiteEmpty takes no arguments but is a setter.
|
||||
if (fn !== jqLiteEmpty &&
|
||||
(((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
|
||||
(isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
|
||||
if (isObject(arg1)) {
|
||||
|
||||
// we are a write, but the object properties are the key/values
|
||||
@@ -716,7 +736,7 @@ forEach({
|
||||
// TODO: do we still need this?
|
||||
var value = fn.$dv;
|
||||
// Only if we have $dv do we iterate over all, otherwise it is just the first element.
|
||||
var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
|
||||
var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
|
||||
for (var j = 0; j < jj; j++) {
|
||||
var nodeValue = fn(this[j], arg1, arg2);
|
||||
value = value ? value + nodeValue : nodeValue;
|
||||
@@ -765,6 +785,9 @@ function createEventHandler(element, events) {
|
||||
return event.immediatePropagationStopped === true;
|
||||
};
|
||||
|
||||
// Some events have special handlers that wrap the real handler
|
||||
var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
|
||||
|
||||
// Copy event handlers in case event handlers array is modified during execution.
|
||||
if ((eventFnsLength > 1)) {
|
||||
eventFns = shallowCopy(eventFns);
|
||||
@@ -772,7 +795,7 @@ function createEventHandler(element, events) {
|
||||
|
||||
for (var i = 0; i < eventFnsLength; i++) {
|
||||
if (!event.isImmediatePropagationStopped()) {
|
||||
eventFns[i].call(element, event);
|
||||
handlerWrapper(element, event, eventFns[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -783,6 +806,22 @@ function createEventHandler(element, events) {
|
||||
return eventHandler;
|
||||
}
|
||||
|
||||
function defaultHandlerWrapper(element, event, handler) {
|
||||
handler.call(element, event);
|
||||
}
|
||||
|
||||
function specialMouseHandlerWrapper(target, event, handler) {
|
||||
// Refer to jQuery's implementation of mouseenter & mouseleave
|
||||
// Read about mouseenter and mouseleave:
|
||||
// http://www.quirksmode.org/js/events_mouse.html#link8
|
||||
var related = event.relatedTarget;
|
||||
// For mousenter/leave call the handler if related is outside the target.
|
||||
// NB: No relatedTarget if the mouse left/entered the browser window
|
||||
if (!related || (related !== target && !jqLiteContains.call(target, related))) {
|
||||
handler.call(target, event);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Functions iterating traversal.
|
||||
// These functions chain results into a single
|
||||
@@ -811,35 +850,28 @@ forEach({
|
||||
var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
|
||||
var i = types.length;
|
||||
|
||||
while (i--) {
|
||||
type = types[i];
|
||||
var addHandler = function(type, specialHandlerWrapper, noEventListener) {
|
||||
var eventFns = events[type];
|
||||
|
||||
if (!eventFns) {
|
||||
events[type] = [];
|
||||
|
||||
if (type === 'mouseenter' || type === 'mouseleave') {
|
||||
// Refer to jQuery's implementation of mouseenter & mouseleave
|
||||
// Read about mouseenter and mouseleave:
|
||||
// http://www.quirksmode.org/js/events_mouse.html#link8
|
||||
|
||||
jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
|
||||
var target = this, related = event.relatedTarget;
|
||||
// For mousenter/leave call the handler if related is outside the target.
|
||||
// NB: No relatedTarget if the mouse left/entered the browser window
|
||||
if (!related || (related !== target && !target.contains(related))) {
|
||||
handle(event, type);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
if (type !== '$destroy') {
|
||||
addEventListenerFn(element, type, handle);
|
||||
}
|
||||
eventFns = events[type] = [];
|
||||
eventFns.specialHandlerWrapper = specialHandlerWrapper;
|
||||
if (type !== '$destroy' && !noEventListener) {
|
||||
addEventListenerFn(element, type, handle);
|
||||
}
|
||||
eventFns = events[type];
|
||||
}
|
||||
|
||||
eventFns.push(fn);
|
||||
};
|
||||
|
||||
while (i--) {
|
||||
type = types[i];
|
||||
if (MOUSE_EVENT_MAP[type]) {
|
||||
addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
|
||||
addHandler(type, undefined, true);
|
||||
} else {
|
||||
addHandler(type);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+116
-3
@@ -38,8 +38,8 @@ function setupModuleLoader(window) {
|
||||
* All modules (angular core or 3rd party) that should be available to an application must be
|
||||
* registered using this mechanism.
|
||||
*
|
||||
* When passed two or more arguments, a new module is created. If passed only one argument, an
|
||||
* existing module (the name passed as the first argument to `module`) is retrieved.
|
||||
* Passing one argument retrieves an existing {@link angular.Module},
|
||||
* whereas passing more than one argument creates a new {@link angular.Module}
|
||||
*
|
||||
*
|
||||
* # Module
|
||||
@@ -188,7 +188,7 @@ function setupModuleLoader(window) {
|
||||
* @param {string} name constant name
|
||||
* @param {*} object Constant value.
|
||||
* @description
|
||||
* Because the constant are fixed, they get applied before other provide methods.
|
||||
* Because the constants are fixed, they get applied before other provide methods.
|
||||
* See {@link auto.$provide#constant $provide.constant()}.
|
||||
*/
|
||||
constant: invokeLater('$provide', 'constant', 'unshift'),
|
||||
@@ -282,6 +282,119 @@ function setupModuleLoader(window) {
|
||||
*/
|
||||
directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name angular.Module#component
|
||||
* @module ng
|
||||
* @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
|
||||
* @param {Object} options Component definition object (a simplified
|
||||
* {@link ng.$compile#directive-definition-object directive definition object}),
|
||||
* has the following properties (all optional):
|
||||
*
|
||||
* - `controller` – `{(string|function()=}` – Controller constructor function that should be
|
||||
* associated with newly created scope or the name of a {@link ng.$compile#-controller-
|
||||
* registered controller} if passed as a string. Empty function by default.
|
||||
* - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
|
||||
* If present, the controller will be published to scope under the `controllerAs` name.
|
||||
* If not present, this will default to be the same as the component name.
|
||||
* - `template` – `{string=|function()=}` – html template as a string or a function that
|
||||
* returns an html template as a string which should be used as the contents of this component.
|
||||
* Empty string by default.
|
||||
*
|
||||
* If `template` is a function, then it is {@link auto.$injector#invoke injected} with
|
||||
* the following locals:
|
||||
*
|
||||
* - `$element` - Current element
|
||||
* - `$attrs` - Current attributes object for the element
|
||||
*
|
||||
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
|
||||
* template that should be used as the contents of this component.
|
||||
*
|
||||
* If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with
|
||||
* the following locals:
|
||||
*
|
||||
* - `$element` - Current element
|
||||
* - `$attrs` - Current attributes object for the element
|
||||
* - `bindings` – `{object=}` – Define DOM attribute binding to component properties.
|
||||
* Component properties are always bound to the component controller and not to the scope.
|
||||
* - `transclude` – `{boolean=}` – Whether {@link $compile#transclusion transclusion} is enabled.
|
||||
* Enabled by default.
|
||||
* - `isolate` – `{boolean=}` – Whether the new scope is isolated. Isolated by default.
|
||||
* - `restrict` - `{string=}` - String of subset of {@link ng.$compile#-restrict- EACM} which
|
||||
* restricts the component to specific directive declaration style. If omitted, this defaults to 'E'.
|
||||
* - `$canActivate` – `{function()=}` – TBD.
|
||||
* - `$routeConfig` – `{object=}` – TBD.
|
||||
*
|
||||
* @description
|
||||
* Register a component definition with the compiler. This is short for registering a specific
|
||||
* subset of directives which represents actual UI components in your application. Component
|
||||
* definitions are very simple and do not require the complexity behind defining directives.
|
||||
* Component definitions usually consist only of the template and the controller backing it.
|
||||
* In order to make the definition easier, components enforce best practices like controllerAs
|
||||
* and default behaviors like scope isolation, restrict to elements and allow transclusion.
|
||||
*
|
||||
* Here are a few examples of how you would usually define components:
|
||||
*
|
||||
* ```js
|
||||
* var myMod = angular.module(...);
|
||||
* myMod.component('myComp', {
|
||||
* template: '<div>My name is {{myComp.name}}</div>',
|
||||
* controller: function() {
|
||||
* this.name = 'shahar';
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* myMod.component('myComp', {
|
||||
* template: '<div>My name is {{myComp.name}}</div>',
|
||||
* bindings: {name: '@'}
|
||||
* });
|
||||
*
|
||||
* myMod.component('myComp', {
|
||||
* templateUrl: 'views/my-comp.html',
|
||||
* controller: 'MyCtrl as ctrl',
|
||||
* bindings: {name: '@'}
|
||||
* });
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
|
||||
*/
|
||||
component: function(name, options) {
|
||||
function factory($injector) {
|
||||
function makeInjectable(fn) {
|
||||
if (angular.isFunction(fn)) {
|
||||
return function(tElement, tAttrs) {
|
||||
return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});
|
||||
};
|
||||
} else {
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
|
||||
var template = (!options.template && !options.templateUrl ? '' : options.template);
|
||||
return {
|
||||
controller: options.controller || function() {},
|
||||
controllerAs: identifierForController(options.controller) || options.controllerAs || name,
|
||||
template: makeInjectable(template),
|
||||
templateUrl: makeInjectable(options.templateUrl),
|
||||
transclude: options.transclude === undefined ? true : options.transclude,
|
||||
scope: options.isolate === false ? true : {},
|
||||
bindToController: options.bindings || {},
|
||||
restrict: options.restrict || 'E'
|
||||
};
|
||||
}
|
||||
|
||||
if (options.$canActivate) {
|
||||
factory.$canActivate = options.$canActivate;
|
||||
}
|
||||
if (options.$routeConfig) {
|
||||
factory.$routeConfig = options.$routeConfig;
|
||||
}
|
||||
factory.$inject = ['$injector'];
|
||||
|
||||
return moduleInstance.directive(name, factory);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name angular.Module#config
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
*/
|
||||
'use strict';
|
||||
(function() {
|
||||
function isFunction(value) {return typeof value === 'function';};
|
||||
@@ -41,7 +41,7 @@ function $AnchorScrollProvider() {
|
||||
* When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
|
||||
* current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
|
||||
* in the
|
||||
* [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
|
||||
* [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
|
||||
*
|
||||
* It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
|
||||
* match any anchor whenever it changes. This can be disabled by calling
|
||||
|
||||
+52
-47
@@ -105,61 +105,66 @@ var $$CoreAnimateQueueProvider = function() {
|
||||
}
|
||||
};
|
||||
|
||||
function addRemoveClassesPostDigest(element, add, remove) {
|
||||
var data = postDigestQueue.get(element);
|
||||
var classVal;
|
||||
|
||||
if (!data) {
|
||||
postDigestQueue.put(element, data = {});
|
||||
postDigestElements.push(element);
|
||||
}
|
||||
|
||||
if (add) {
|
||||
forEach(add.split(' '), function(className) {
|
||||
function updateData(data, classes, value) {
|
||||
var changed = false;
|
||||
if (classes) {
|
||||
classes = isString(classes) ? classes.split(' ') :
|
||||
isArray(classes) ? classes : [];
|
||||
forEach(classes, function(className) {
|
||||
if (className) {
|
||||
data[className] = true;
|
||||
changed = true;
|
||||
data[className] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
forEach(remove.split(' '), function(className) {
|
||||
if (className) {
|
||||
data[className] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (postDigestElements.length > 1) return;
|
||||
|
||||
$rootScope.$$postDigest(function() {
|
||||
forEach(postDigestElements, function(element) {
|
||||
var data = postDigestQueue.get(element);
|
||||
if (data) {
|
||||
var existing = splitClasses(element.attr('class'));
|
||||
var toAdd = '';
|
||||
var toRemove = '';
|
||||
forEach(data, function(status, className) {
|
||||
var hasClass = !!existing[className];
|
||||
if (status !== hasClass) {
|
||||
if (status) {
|
||||
toAdd += (toAdd.length ? ' ' : '') + className;
|
||||
} else {
|
||||
toRemove += (toRemove.length ? ' ' : '') + className;
|
||||
}
|
||||
function handleCSSClassChanges() {
|
||||
forEach(postDigestElements, function(element) {
|
||||
var data = postDigestQueue.get(element);
|
||||
if (data) {
|
||||
var existing = splitClasses(element.attr('class'));
|
||||
var toAdd = '';
|
||||
var toRemove = '';
|
||||
forEach(data, function(status, className) {
|
||||
var hasClass = !!existing[className];
|
||||
if (status !== hasClass) {
|
||||
if (status) {
|
||||
toAdd += (toAdd.length ? ' ' : '') + className;
|
||||
} else {
|
||||
toRemove += (toRemove.length ? ' ' : '') + className;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
forEach(element, function(elm) {
|
||||
toAdd && jqLiteAddClass(elm, toAdd);
|
||||
toRemove && jqLiteRemoveClass(elm, toRemove);
|
||||
});
|
||||
postDigestQueue.remove(element);
|
||||
}
|
||||
});
|
||||
|
||||
postDigestElements.length = 0;
|
||||
forEach(element, function(elm) {
|
||||
toAdd && jqLiteAddClass(elm, toAdd);
|
||||
toRemove && jqLiteRemoveClass(elm, toRemove);
|
||||
});
|
||||
postDigestQueue.remove(element);
|
||||
}
|
||||
});
|
||||
postDigestElements.length = 0;
|
||||
}
|
||||
|
||||
|
||||
function addRemoveClassesPostDigest(element, add, remove) {
|
||||
var data = postDigestQueue.get(element) || {};
|
||||
|
||||
var classesAdded = updateData(data, add, true);
|
||||
var classesRemoved = updateData(data, remove, false);
|
||||
|
||||
if (classesAdded || classesRemoved) {
|
||||
|
||||
postDigestQueue.put(element, data);
|
||||
postDigestElements.push(element);
|
||||
|
||||
if (postDigestElements.length === 1) {
|
||||
$rootScope.$$postDigest(handleCSSClassChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
};
|
||||
@@ -280,7 +285,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* when an animation is detected (and animations are enabled), $animate will do the heavy lifting
|
||||
* to ensure that animation runs with the triggered DOM operation.
|
||||
*
|
||||
* By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't
|
||||
* By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
|
||||
* included and only when it is active then the animation hooks that `$animate` triggers will be
|
||||
* functional. Once active then all structural `ng-` directives will trigger animations as they perform
|
||||
* their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $animateCss
|
||||
* @kind object
|
||||
*
|
||||
* @description
|
||||
* This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
|
||||
* then the `$animateCss` service will actually perform animations.
|
||||
*
|
||||
* Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
|
||||
*/
|
||||
var $CoreAnimateCssProvider = function() {
|
||||
this.$get = ['$$rAF', '$q', function($$rAF, $q) {
|
||||
|
||||
var RAFPromise = function() {};
|
||||
RAFPromise.prototype = {
|
||||
done: function(cancel) {
|
||||
this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
|
||||
},
|
||||
end: function() {
|
||||
this.done();
|
||||
},
|
||||
cancel: function() {
|
||||
this.done(true);
|
||||
},
|
||||
getPromise: function() {
|
||||
if (!this.defer) {
|
||||
this.defer = $q.defer();
|
||||
}
|
||||
return this.defer.promise;
|
||||
},
|
||||
then: function(f1,f2) {
|
||||
return this.getPromise().then(f1,f2);
|
||||
},
|
||||
'catch': function(f1) {
|
||||
return this.getPromise()['catch'](f1);
|
||||
},
|
||||
'finally': function(f1) {
|
||||
return this.getPromise()['finally'](f1);
|
||||
}
|
||||
};
|
||||
|
||||
return function(element, options) {
|
||||
// there is no point in applying the styles since
|
||||
// there is no animation that goes on at all in
|
||||
// this version of $animateCss.
|
||||
if (options.cleanupStyles) {
|
||||
options.from = options.to = null;
|
||||
}
|
||||
|
||||
if (options.from) {
|
||||
element.css(options.from);
|
||||
options.from = null;
|
||||
}
|
||||
|
||||
var closed, runner = new RAFPromise();
|
||||
return {
|
||||
start: run,
|
||||
end: run
|
||||
};
|
||||
|
||||
function run() {
|
||||
$$rAF(function() {
|
||||
close();
|
||||
if (!closed) {
|
||||
runner.done();
|
||||
}
|
||||
closed = true;
|
||||
});
|
||||
return runner;
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (options.addClass) {
|
||||
element.addClass(options.addClass);
|
||||
options.addClass = null;
|
||||
}
|
||||
if (options.removeClass) {
|
||||
element.removeClass(options.removeClass);
|
||||
options.removeClass = null;
|
||||
}
|
||||
if (options.to) {
|
||||
element.css(options.to);
|
||||
options.to = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
function $$AsyncCallbackProvider() {
|
||||
this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
|
||||
return $$rAF.supported
|
||||
? function(fn) { return $$rAF(fn); }
|
||||
: function(fn) {
|
||||
return $timeout(fn, 0, false);
|
||||
};
|
||||
}];
|
||||
}
|
||||
+11
-6
@@ -87,7 +87,7 @@ function Browser(window, document, $log, $sniffer) {
|
||||
var cachedState, lastHistoryState,
|
||||
lastBrowserUrl = location.href,
|
||||
baseElement = document.find('base'),
|
||||
reloadLocation = null;
|
||||
pendingLocation = null;
|
||||
|
||||
cacheState();
|
||||
lastHistoryState = cachedState;
|
||||
@@ -147,8 +147,8 @@ function Browser(window, document, $log, $sniffer) {
|
||||
// Do the assignment again so that those two variables are referentially identical.
|
||||
lastHistoryState = cachedState;
|
||||
} else {
|
||||
if (!sameBase || reloadLocation) {
|
||||
reloadLocation = url;
|
||||
if (!sameBase || pendingLocation) {
|
||||
pendingLocation = url;
|
||||
}
|
||||
if (replace) {
|
||||
location.replace(url);
|
||||
@@ -157,14 +157,18 @@ function Browser(window, document, $log, $sniffer) {
|
||||
} else {
|
||||
location.hash = getHash(url);
|
||||
}
|
||||
if (location.href !== url) {
|
||||
pendingLocation = url;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
// getter
|
||||
} else {
|
||||
// - reloadLocation is needed as browsers don't allow to read out
|
||||
// the new location.href if a reload happened.
|
||||
// - pendingLocation is needed as browsers don't allow to read out
|
||||
// the new location.href if a reload happened or if there is a bug like in iOS 9 (see
|
||||
// https://openradar.appspot.com/22186109).
|
||||
// - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
|
||||
return reloadLocation || location.href.replace(/%27/g,"'");
|
||||
return pendingLocation || location.href.replace(/%27/g,"'");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,6 +190,7 @@ function Browser(window, document, $log, $sniffer) {
|
||||
urlChangeInit = false;
|
||||
|
||||
function cacheStateAndFireUrlChange() {
|
||||
pendingLocation = null;
|
||||
cacheState();
|
||||
fireUrlChange();
|
||||
}
|
||||
|
||||
@@ -67,10 +67,10 @@
|
||||
$scope.keys = [];
|
||||
$scope.cache = $cacheFactory('cacheId');
|
||||
$scope.put = function(key, value) {
|
||||
if ($scope.cache.get(key) === undefined) {
|
||||
if (angular.isUndefined($scope.cache.get(key))) {
|
||||
$scope.keys.push(key);
|
||||
}
|
||||
$scope.cache.put(key, value === undefined ? null : value);
|
||||
$scope.cache.put(key, angular.isUndefined(value) ? null : value);
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
@@ -93,9 +93,9 @@ function $CacheFactoryProvider() {
|
||||
|
||||
var size = 0,
|
||||
stats = extend({}, options, {id: cacheId}),
|
||||
data = {},
|
||||
data = createMap(),
|
||||
capacity = (options && options.capacity) || Number.MAX_VALUE,
|
||||
lruHash = {},
|
||||
lruHash = createMap(),
|
||||
freshEnd = null,
|
||||
staleEnd = null;
|
||||
|
||||
@@ -223,6 +223,8 @@ function $CacheFactoryProvider() {
|
||||
delete lruHash[key];
|
||||
}
|
||||
|
||||
if (!(key in data)) return;
|
||||
|
||||
delete data[key];
|
||||
size--;
|
||||
},
|
||||
@@ -237,9 +239,9 @@ function $CacheFactoryProvider() {
|
||||
* Clears the cache object of any entries.
|
||||
*/
|
||||
removeAll: function() {
|
||||
data = {};
|
||||
data = createMap();
|
||||
size = 0;
|
||||
lruHash = {};
|
||||
lruHash = createMap();
|
||||
freshEnd = staleEnd = null;
|
||||
},
|
||||
|
||||
@@ -399,4 +401,3 @@ function $TemplateCacheProvider() {
|
||||
return $cacheFactory('templates');
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
+272
-145
@@ -146,18 +146,24 @@
|
||||
* and other directives used in the directive's template will also be excluded from execution.
|
||||
*
|
||||
* #### `scope`
|
||||
* **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
|
||||
* same element request a new scope, only one new scope is created. The new scope rule does not
|
||||
* apply for the root of the template since the root of the template always gets a new scope.
|
||||
* The scope property can be `true`, an object or a falsy value:
|
||||
*
|
||||
* **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
|
||||
* normal scope in that it does not prototypically inherit from the parent scope. This is useful
|
||||
* when creating reusable components, which should not accidentally read or modify data in the
|
||||
* parent scope.
|
||||
* * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
|
||||
*
|
||||
* The 'isolate' scope takes an object hash which defines a set of local scope properties
|
||||
* derived from the parent scope. These local properties are useful for aliasing values for
|
||||
* templates. Locals definition is a hash of local scope property to its source:
|
||||
* * **`true`:** A new child scope that prototypically inherits from its parent will be created for
|
||||
* the directive's element. If multiple directives on the same element request a new scope,
|
||||
* only one new scope is created. The new scope rule does not apply for the root of the template
|
||||
* since the root of the template always gets a new scope.
|
||||
*
|
||||
* * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
|
||||
* 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
|
||||
* scope. This is useful when creating reusable components, which should not accidentally read or modify
|
||||
* data in the parent scope.
|
||||
*
|
||||
* The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
|
||||
* directive's element. These local properties are useful for aliasing values for templates. The keys in
|
||||
* the object hash map to the name of the property on the isolate scope; the values define how the property
|
||||
* is bound to the parent scope, via matching attributes on the directive's element:
|
||||
*
|
||||
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
|
||||
* always a string since DOM attributes are strings. If no `attr` name is specified then the
|
||||
@@ -190,6 +196,20 @@
|
||||
* For example, if the expression is `increment(amount)` then we can specify the amount value
|
||||
* by calling the `localFn` as `localFn({amount: 22})`.
|
||||
*
|
||||
* In general it's possible to apply more than one directive to one element, but there might be limitations
|
||||
* depending on the type of scope required by the directives. The following points will help explain these limitations.
|
||||
* For simplicity only two directives are taken into account, but it is also applicable for several directives:
|
||||
*
|
||||
* * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
|
||||
* * **child scope** + **no scope** => Both directives will share one single child scope
|
||||
* * **child scope** + **child scope** => Both directives will share one single child scope
|
||||
* * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use
|
||||
* its parent's scope
|
||||
* * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
|
||||
* be applied to the same element.
|
||||
* * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives
|
||||
* cannot be applied to the same element.
|
||||
*
|
||||
*
|
||||
* #### `bindToController`
|
||||
* When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
|
||||
@@ -198,7 +218,7 @@
|
||||
*
|
||||
* #### `controller`
|
||||
* Controller constructor function. The controller is instantiated before the
|
||||
* pre-linking phase and it is shared with other directives (see
|
||||
* pre-linking phase and can be accessed by other directives (see
|
||||
* `require` attribute). This allows the directives to communicate with each other and augment
|
||||
* each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
|
||||
*
|
||||
@@ -238,9 +258,10 @@
|
||||
*
|
||||
* #### `controllerAs`
|
||||
* Identifier name for a reference to the controller in the directive's scope.
|
||||
* This allows the controller to be referenced from the directive template. The directive
|
||||
* needs to define a scope for this configuration to be used. Useful in the case when
|
||||
* directive is used as component.
|
||||
* This allows the controller to be referenced from the directive template. This is especially
|
||||
* useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
|
||||
* to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
|
||||
* `controllerAs` reference might overwrite a property that already exists on the parent scope.
|
||||
*
|
||||
*
|
||||
* #### `restrict`
|
||||
@@ -407,7 +428,7 @@
|
||||
* otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
|
||||
*
|
||||
* Note that you can also require the directive's own controller - it will be made available like
|
||||
* like any other controller.
|
||||
* any other controller.
|
||||
*
|
||||
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
|
||||
* This is the same as the `$transclude`
|
||||
@@ -433,7 +454,7 @@
|
||||
*
|
||||
* ### Transclusion
|
||||
*
|
||||
* Transclusion is the process of extracting a collection of DOM element from one part of the DOM and
|
||||
* Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
|
||||
* copying them to another part of the DOM, while maintaining their connection to the original AngularJS
|
||||
* scope from where they were taken.
|
||||
*
|
||||
@@ -1077,7 +1098,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
var node = this.$$element[0],
|
||||
booleanKey = getBooleanAttrName(node, key),
|
||||
aliasedKey = getAliasedAttrName(node, key),
|
||||
aliasedKey = getAliasedAttrName(key),
|
||||
observer = key,
|
||||
nodeName;
|
||||
|
||||
@@ -1103,7 +1124,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
nodeName = nodeName_(this.$$element);
|
||||
|
||||
if ((nodeName === 'a' && key === 'href') ||
|
||||
if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) ||
|
||||
(nodeName === 'img' && key === 'src')) {
|
||||
// sanitize a[href] and img[src] values
|
||||
this[key] = value = $$sanitizeUri(value, key === 'src');
|
||||
@@ -1144,7 +1165,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
}
|
||||
|
||||
if (writeAttr !== false) {
|
||||
if (value === null || value === undefined) {
|
||||
if (value === null || isUndefined(value)) {
|
||||
this.$$element.removeAttr(attrName);
|
||||
} else {
|
||||
this.$$element.attr(attrName, value);
|
||||
@@ -1188,7 +1209,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
listeners.push(fn);
|
||||
$rootScope.$evalAsync(function() {
|
||||
if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
|
||||
if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {
|
||||
// no one registered attribute interpolation function, so lets call it manually
|
||||
fn(attrs[key]);
|
||||
}
|
||||
@@ -1219,6 +1240,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
|
||||
},
|
||||
NG_ATTR_BINDING = /^ngAttr[A-Z]/;
|
||||
var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
|
||||
|
||||
compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
|
||||
var bindings = $element.data('$binding') || [];
|
||||
@@ -1259,7 +1281,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
// We can not compile top level text elements since text nodes can be merged and we will
|
||||
// not be able to attach scope data to them, so we will wrap them in <span>
|
||||
forEach($compileNodes, function(node, index) {
|
||||
if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
|
||||
if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */) {
|
||||
$compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
|
||||
}
|
||||
});
|
||||
@@ -1271,6 +1293,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return function publicLinkFn(scope, cloneConnectFn, options) {
|
||||
assertArg(scope, 'scope');
|
||||
|
||||
if (previousCompileContext && previousCompileContext.needsNewScope) {
|
||||
// A parent directive did a replace and a directive on this element asked
|
||||
// for transclusion, which caused us to lose a layer of element on which
|
||||
// we could hold the new transclusion scope, so we will create it manually
|
||||
// here.
|
||||
scope = scope.$parent.$new();
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
|
||||
transcludeControllers = options.transcludeControllers,
|
||||
@@ -1416,11 +1446,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
if (nodeLinkFn.scope) {
|
||||
childScope = scope.$new();
|
||||
compile.$$addScopeInfo(jqLite(node), childScope);
|
||||
var destroyBindings = nodeLinkFn.$$destroyBindings;
|
||||
if (destroyBindings) {
|
||||
nodeLinkFn.$$destroyBindings = null;
|
||||
childScope.$on('$destroyed', destroyBindings);
|
||||
}
|
||||
} else {
|
||||
childScope = scope;
|
||||
}
|
||||
@@ -1439,8 +1464,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
childBoundTranscludeFn = null;
|
||||
}
|
||||
|
||||
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn,
|
||||
nodeLinkFn);
|
||||
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
|
||||
|
||||
} else if (childLinkFn) {
|
||||
childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
|
||||
@@ -1465,6 +1489,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
});
|
||||
};
|
||||
|
||||
// We need to attach the transclusion slots onto the `boundTranscludeFn`
|
||||
// so that they are available inside the `controllersBoundTransclude` function
|
||||
var boundSlots = boundTranscludeFn.$$slots = createMap();
|
||||
for (var slotName in transcludeFn.$$slots) {
|
||||
boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn);
|
||||
}
|
||||
|
||||
return boundTranscludeFn;
|
||||
}
|
||||
|
||||
@@ -1509,13 +1540,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
});
|
||||
}
|
||||
|
||||
var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
|
||||
if (directiveIsMultiElement(directiveNName)) {
|
||||
if (ngAttrName === directiveNName + 'Start') {
|
||||
attrStartName = name;
|
||||
attrEndName = name.substr(0, name.length - 5) + 'end';
|
||||
name = name.substr(0, name.length - 6);
|
||||
}
|
||||
var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
|
||||
if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
|
||||
attrStartName = name;
|
||||
attrEndName = name.substr(0, name.length - 5) + 'end';
|
||||
name = name.substr(0, name.length - 6);
|
||||
}
|
||||
|
||||
nName = directiveNormalize(name.toLowerCase());
|
||||
@@ -1625,6 +1654,37 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A function generator that is used to support both eager and lazy compilation
|
||||
* linking function.
|
||||
* @param eager
|
||||
* @param $compileNodes
|
||||
* @param transcludeFn
|
||||
* @param maxPriority
|
||||
* @param ignoreDirective
|
||||
* @param previousCompileContext
|
||||
* @returns {Function}
|
||||
*/
|
||||
function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) {
|
||||
if (eager) {
|
||||
return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
|
||||
}
|
||||
|
||||
var compiled;
|
||||
|
||||
return function() {
|
||||
if (!compiled) {
|
||||
compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
|
||||
|
||||
// Null out all of these references in order to make them eligible for garbage collection
|
||||
// since this is a potentially long lived closure
|
||||
$compileNodes = transcludeFn = previousCompileContext = null;
|
||||
}
|
||||
|
||||
return compiled.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Once the directives have been collected, their compile functions are executed. This method
|
||||
* is responsible for inlining directive templates as well as terminating the application
|
||||
@@ -1669,6 +1729,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
replaceDirective = originalReplaceDirective,
|
||||
childTranscludeFn = transcludeFn,
|
||||
linkFn,
|
||||
didScanForMultipleTransclusion = false,
|
||||
mightHaveMultipleTransclusionError = false,
|
||||
directiveValue;
|
||||
|
||||
// executes all directives on the current element
|
||||
@@ -1711,6 +1773,27 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
directiveName = directive.name;
|
||||
|
||||
// If we encounter a condition that can result in transclusion on the directive,
|
||||
// then scan ahead in the remaining directives for others that may cause a multiple
|
||||
// transclusion error to be thrown during the compilation process. If a matching directive
|
||||
// is found, then we know that when we encounter a transcluded directive, we need to eagerly
|
||||
// compile the `transclude` function rather than doing it lazily in order to throw
|
||||
// exceptions at the correct time
|
||||
if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))
|
||||
|| (directive.transclude && !directive.$$tlb))) {
|
||||
var candidateDirective;
|
||||
|
||||
for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) {
|
||||
if ((candidateDirective.transclude && !candidateDirective.$$tlb)
|
||||
|| (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {
|
||||
mightHaveMultipleTransclusionError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
didScanForMultipleTransclusion = true;
|
||||
}
|
||||
|
||||
if (!directive.templateUrl && directive.controller) {
|
||||
directiveValue = directive.controller;
|
||||
controllerDirectives = controllerDirectives || createMap();
|
||||
@@ -1740,7 +1823,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
compileNode = $compileNode[0];
|
||||
replaceWith(jqCollection, sliceArgs($template), compileNode);
|
||||
|
||||
childTranscludeFn = compile($template, transcludeFn, terminalPriority,
|
||||
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,
|
||||
replaceDirective && replaceDirective.name, {
|
||||
// Don't pass in:
|
||||
// - controllerDirectives - otherwise we'll create duplicates controllers
|
||||
@@ -1752,9 +1835,56 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
nonTlbTranscludeDirective: nonTlbTranscludeDirective
|
||||
});
|
||||
} else {
|
||||
|
||||
var slots = createMap();
|
||||
$template = jqLite(jqLiteClone(compileNode)).contents();
|
||||
|
||||
if (isObject(directiveValue)) {
|
||||
|
||||
// We have transclusion slots - collect them up and compile them and store their
|
||||
// transclusion functions
|
||||
$template = [];
|
||||
var slotNames = createMap();
|
||||
var filledSlots = createMap();
|
||||
|
||||
// Parse the slot names: if they start with a ? then they are optional
|
||||
forEach(directiveValue, function(slotName, key) {
|
||||
var optional = (slotName.charAt(0) === '?');
|
||||
slotName = optional ? slotName.substring(1) : slotName;
|
||||
slotNames[key] = slotName;
|
||||
slots[slotName] = [];
|
||||
// filledSlots contains `true` for all slots that are either optional or have been
|
||||
// filled. This is used to check that we have not missed any required slots
|
||||
filledSlots[slotName] = optional;
|
||||
});
|
||||
|
||||
// Add the matching elements into their slot
|
||||
forEach($compileNode.children(), function(node) {
|
||||
var slotName = slotNames[directiveNormalize(nodeName_(node))];
|
||||
if (slotName) {
|
||||
filledSlots[slotName] = true;
|
||||
slots[slotName].push(node);
|
||||
} else {
|
||||
$template.push(node);
|
||||
}
|
||||
});
|
||||
|
||||
// Check for required slots that were not filled
|
||||
forEach(filledSlots, function(filled, slotName) {
|
||||
if (!filled) {
|
||||
throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName);
|
||||
}
|
||||
});
|
||||
|
||||
forEach(Object.keys(slots), function(slotName) {
|
||||
slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn);
|
||||
});
|
||||
}
|
||||
|
||||
$compileNode.empty(); // clear contents
|
||||
childTranscludeFn = compile($template, transcludeFn);
|
||||
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined,
|
||||
undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
|
||||
childTranscludeFn.$$slots = slots;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1796,8 +1926,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
|
||||
var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
|
||||
|
||||
if (newIsolateScopeDirective) {
|
||||
markDirectivesAsIsolate(templateDirectives);
|
||||
if (newIsolateScopeDirective || newScopeDirective) {
|
||||
// The original directive caused the current element to be replaced but this element
|
||||
// also needs to have a new scope, so we need to tell the template directives
|
||||
// that they would need to get their scope from further up, if they require transclusion
|
||||
markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
|
||||
}
|
||||
directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
|
||||
mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
|
||||
@@ -1950,10 +2083,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return elementControllers;
|
||||
}
|
||||
|
||||
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn,
|
||||
thisLinkFn) {
|
||||
var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,
|
||||
attrs;
|
||||
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
|
||||
var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
|
||||
attrs, removeScopeBindingWatches, removeControllerBindingWatches;
|
||||
|
||||
if (compileNode === linkNode) {
|
||||
attrs = templateAttrs;
|
||||
@@ -1963,8 +2095,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
attrs = new Attributes($element, templateAttrs);
|
||||
}
|
||||
|
||||
controllerScope = scope;
|
||||
if (newIsolateScopeDirective) {
|
||||
isolateScope = scope.$new(true);
|
||||
} else if (newScopeDirective) {
|
||||
controllerScope = scope.$parent;
|
||||
}
|
||||
|
||||
if (boundTranscludeFn) {
|
||||
@@ -1985,42 +2120,34 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
compile.$$addScopeClass($element, true);
|
||||
isolateScope.$$isolateBindings =
|
||||
newIsolateScopeDirective.$$isolateBindings;
|
||||
initializeDirectiveBindings(scope, attrs, isolateScope,
|
||||
isolateScope.$$isolateBindings,
|
||||
newIsolateScopeDirective, isolateScope);
|
||||
}
|
||||
if (elementControllers) {
|
||||
// Initialize bindToController bindings for new/isolate scopes
|
||||
var scopeDirective = newIsolateScopeDirective || newScopeDirective;
|
||||
var bindings;
|
||||
var controllerForBindings;
|
||||
if (scopeDirective && elementControllers[scopeDirective.name]) {
|
||||
bindings = scopeDirective.$$bindings.bindToController;
|
||||
controller = elementControllers[scopeDirective.name];
|
||||
|
||||
if (controller && controller.identifier && bindings) {
|
||||
controllerForBindings = controller;
|
||||
thisLinkFn.$$destroyBindings =
|
||||
initializeDirectiveBindings(scope, attrs, controller.instance,
|
||||
bindings, scopeDirective);
|
||||
}
|
||||
removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
|
||||
isolateScope.$$isolateBindings,
|
||||
newIsolateScopeDirective);
|
||||
if (removeScopeBindingWatches) {
|
||||
isolateScope.$on('$destroy', removeScopeBindingWatches);
|
||||
}
|
||||
for (i in elementControllers) {
|
||||
controller = elementControllers[i];
|
||||
var controllerResult = controller();
|
||||
}
|
||||
|
||||
if (controllerResult !== controller.instance) {
|
||||
// If the controller constructor has a return value, overwrite the instance
|
||||
// from setupControllers and update the element data
|
||||
controller.instance = controllerResult;
|
||||
$element.data('$' + i + 'Controller', controllerResult);
|
||||
if (controller === controllerForBindings) {
|
||||
// Remove and re-install bindToController bindings
|
||||
thisLinkFn.$$destroyBindings();
|
||||
thisLinkFn.$$destroyBindings =
|
||||
initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective);
|
||||
}
|
||||
}
|
||||
// Initialize bindToController bindings
|
||||
for (var name in elementControllers) {
|
||||
var controllerDirective = controllerDirectives[name];
|
||||
var controller = elementControllers[name];
|
||||
var bindings = controllerDirective.$$bindings.bindToController;
|
||||
|
||||
if (controller.identifier && bindings) {
|
||||
removeControllerBindingWatches =
|
||||
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
|
||||
}
|
||||
|
||||
var controllerResult = controller();
|
||||
if (controllerResult !== controller.instance) {
|
||||
// If the controller constructor has a return value, overwrite the instance
|
||||
// from setupControllers
|
||||
controller.instance = controllerResult;
|
||||
$element.data('$' + controllerDirective.name + 'Controller', controllerResult);
|
||||
removeControllerBindingWatches && removeControllerBindingWatches();
|
||||
removeControllerBindingWatches =
|
||||
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2059,11 +2186,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
// This is the function that is injected as `$transclude`.
|
||||
// Note: all arguments are optional!
|
||||
function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
|
||||
function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {
|
||||
var transcludeControllers;
|
||||
|
||||
// No scope passed in:
|
||||
if (!isScope(scope)) {
|
||||
slotName = futureParentElement;
|
||||
futureParentElement = cloneAttachFn;
|
||||
cloneAttachFn = scope;
|
||||
scope = undefined;
|
||||
@@ -2075,15 +2202,30 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
if (!futureParentElement) {
|
||||
futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
|
||||
}
|
||||
if (slotName) {
|
||||
var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
|
||||
if (!slotTranscludeFn) {
|
||||
throw $compileMinErr('noslot',
|
||||
'No parent directive that requires a transclusion with slot name "{0}". ' +
|
||||
'Element: {1}',
|
||||
slotName, startingTag($element));
|
||||
}
|
||||
return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
|
||||
}
|
||||
return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function markDirectivesAsIsolate(directives) {
|
||||
// mark all directives as needing isolate scope.
|
||||
// Depending upon the context in which a directive finds itself it might need to have a new isolated
|
||||
// or child scope created. For instance:
|
||||
// * if the directive has been pulled into a template because another directive with a higher priority
|
||||
// asked for element transclusion
|
||||
// * if the directive itself asks for transclusion but it is at the root of a template and the original
|
||||
// element was replaced. See https://github.com/angular/angular.js/issues/12936
|
||||
function markDirectiveScope(directives, isolateScope, newScope) {
|
||||
for (var j = 0, jj = directives.length; j < jj; j++) {
|
||||
directives[j] = inherit(directives[j], {$$isolateScope: true});
|
||||
directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2110,7 +2252,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
i = 0, ii = directives.length; i < ii; i++) {
|
||||
try {
|
||||
directive = directives[i];
|
||||
if ((maxPriority === undefined || maxPriority > directive.priority) &&
|
||||
if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
|
||||
directive.restrict.indexOf(location) != -1) {
|
||||
if (startAttrName) {
|
||||
directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
|
||||
@@ -2230,7 +2372,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
|
||||
|
||||
if (isObject(origAsyncDirective.scope)) {
|
||||
markDirectivesAsIsolate(templateDirectives);
|
||||
// the original directive that caused the template to be loaded async required
|
||||
// an isolate scope
|
||||
markDirectiveScope(templateDirectives, true);
|
||||
}
|
||||
directives = templateDirectives.concat(directives);
|
||||
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
|
||||
@@ -2279,7 +2423,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
childBoundTranscludeFn = boundTranscludeFn;
|
||||
}
|
||||
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
|
||||
childBoundTranscludeFn, afterTemplateNodeLinkFn);
|
||||
childBoundTranscludeFn);
|
||||
}
|
||||
linkQueue = null;
|
||||
});
|
||||
@@ -2296,8 +2440,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
|
||||
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
|
||||
}
|
||||
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn,
|
||||
afterTemplateNodeLinkFn);
|
||||
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2406,7 +2549,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
compile: function() {
|
||||
return {
|
||||
pre: function attrInterpolatePreLinkFn(scope, element, attr) {
|
||||
var $$observers = (attr.$$observers || (attr.$$observers = {}));
|
||||
var $$observers = (attr.$$observers || (attr.$$observers = createMap()));
|
||||
|
||||
if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
|
||||
throw $compileMinErr('nodomevents',
|
||||
@@ -2501,41 +2644,33 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
parent.replaceChild(newNode, firstElementToRemove);
|
||||
}
|
||||
|
||||
// TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
|
||||
// Append all the `elementsToRemove` to a fragment. This will...
|
||||
// - remove them from the DOM
|
||||
// - allow them to still be traversed with .nextSibling
|
||||
// - allow a single fragment.qSA to fetch all elements being removed
|
||||
var fragment = document.createDocumentFragment();
|
||||
fragment.appendChild(firstElementToRemove);
|
||||
for (i = 0; i < removeCount; i++) {
|
||||
fragment.appendChild(elementsToRemove[i]);
|
||||
}
|
||||
|
||||
if (jqLite.hasData(firstElementToRemove)) {
|
||||
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
|
||||
// data here because there's no public interface in jQuery to do that and copying over
|
||||
// event listeners (which is the main use of private data) wouldn't work anyway.
|
||||
jqLite(newNode).data(jqLite(firstElementToRemove).data());
|
||||
jqLite.data(newNode, jqLite.data(firstElementToRemove));
|
||||
|
||||
// Remove data of the replaced element. We cannot just call .remove()
|
||||
// on the element it since that would deallocate scope that is needed
|
||||
// for the new node. Instead, remove the data "manually".
|
||||
if (!jQuery) {
|
||||
delete jqLite.cache[firstElementToRemove[jqLite.expando]];
|
||||
} else {
|
||||
// jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
|
||||
// the replaced element. The cleanData version monkey-patched by Angular would cause
|
||||
// the scope to be trashed and we do need the very same scope to work with the new
|
||||
// element. However, we cannot just cache the non-patched version and use it here as
|
||||
// that would break if another library patches the method after Angular does (one
|
||||
// example is jQuery UI). Instead, set a flag indicating scope destroying should be
|
||||
// skipped this one time.
|
||||
skipDestroyOnNextJQueryCleanData = true;
|
||||
jQuery.cleanData([firstElementToRemove]);
|
||||
}
|
||||
// Remove $destroy event listeners from `firstElementToRemove`
|
||||
jqLite(firstElementToRemove).off('$destroy');
|
||||
}
|
||||
|
||||
for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
|
||||
var element = elementsToRemove[k];
|
||||
jqLite(element).remove(); // must do this way to clean up expando
|
||||
fragment.appendChild(element);
|
||||
delete elementsToRemove[k];
|
||||
}
|
||||
// Cleanup any data/listeners on the elements and children.
|
||||
// This includes invoking the $destroy event on any elements with listeners.
|
||||
jqLite.cleanData(fragment.querySelectorAll('*'));
|
||||
|
||||
// Update the jqLite collection to only contain the `newNode`
|
||||
for (i = 1; i < removeCount; i++) {
|
||||
delete elementsToRemove[i];
|
||||
}
|
||||
elementsToRemove[0] = newNode;
|
||||
elementsToRemove.length = 1;
|
||||
}
|
||||
@@ -2557,9 +2692,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
// Set up $watches for isolate scope and controller bindings. This process
|
||||
// only occurs for isolate scopes and new scopes with controllerAs.
|
||||
function initializeDirectiveBindings(scope, attrs, destination, bindings,
|
||||
directive, newScope) {
|
||||
var onNewScopeDestroyed;
|
||||
function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
|
||||
var removeWatchCollection = [];
|
||||
forEach(bindings, function(definition, scopeName) {
|
||||
var attrName = definition.attrName,
|
||||
optional = definition.optional,
|
||||
@@ -2567,24 +2701,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
lastValue,
|
||||
parentGet, parentSet, compare;
|
||||
|
||||
if (!hasOwnProperty.call(attrs, attrName)) {
|
||||
// In the case of user defined a binding with the same name as a method in Object.prototype but didn't set
|
||||
// the corresponding attribute. We need to make sure subsequent code won't access to the prototype function
|
||||
attrs[attrName] = undefined;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
|
||||
case '@':
|
||||
if (!attrs[attrName] && !optional) {
|
||||
destination[scopeName] = undefined;
|
||||
if (!optional && !hasOwnProperty.call(attrs, attrName)) {
|
||||
destination[scopeName] = attrs[attrName] = void 0;
|
||||
}
|
||||
|
||||
attrs.$observe(attrName, function(value) {
|
||||
destination[scopeName] = value;
|
||||
if (isString(value)) {
|
||||
destination[scopeName] = value;
|
||||
}
|
||||
});
|
||||
attrs.$$observers[attrName].$$scope = scope;
|
||||
if (attrs[attrName]) {
|
||||
if (isString(attrs[attrName])) {
|
||||
// If the attribute has been provided then we trigger an interpolation to ensure
|
||||
// the value is there for use in the link fn
|
||||
destination[scopeName] = $interpolate(attrs[attrName])(scope);
|
||||
@@ -2592,11 +2721,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
break;
|
||||
|
||||
case '=':
|
||||
if (optional && !attrs[attrName]) {
|
||||
return;
|
||||
if (!hasOwnProperty.call(attrs, attrName)) {
|
||||
if (optional) break;
|
||||
attrs[attrName] = void 0;
|
||||
}
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
if (optional && !attrs[attrName]) break;
|
||||
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
if (parentGet.literal) {
|
||||
compare = equals;
|
||||
} else {
|
||||
@@ -2624,18 +2755,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return lastValue = parentValue;
|
||||
};
|
||||
parentValueWatch.$stateful = true;
|
||||
var unwatch;
|
||||
var removeWatch;
|
||||
if (definition.collection) {
|
||||
unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
|
||||
removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
|
||||
} else {
|
||||
unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
|
||||
removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
|
||||
}
|
||||
onNewScopeDestroyed = (onNewScopeDestroyed || []);
|
||||
onNewScopeDestroyed.push(unwatch);
|
||||
removeWatchCollection.push(removeWatch);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
// Don't assign Object.prototype method to scope
|
||||
parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
|
||||
|
||||
// Don't assign noop to destination if expression is not valid
|
||||
if (parentGet === noop && optional) break;
|
||||
@@ -2646,16 +2777,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
var destroyBindings = onNewScopeDestroyed ? function destroyBindings() {
|
||||
for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) {
|
||||
onNewScopeDestroyed[i]();
|
||||
|
||||
return removeWatchCollection.length && function removeWatches() {
|
||||
for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
|
||||
removeWatchCollection[i]();
|
||||
}
|
||||
} : noop;
|
||||
if (newScope && destroyBindings !== noop) {
|
||||
newScope.$on('$destroy', destroyBindings);
|
||||
return noop;
|
||||
}
|
||||
return destroyBindings;
|
||||
};
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ function $$CookieReader($document) {
|
||||
// the first value that is seen for a cookie is the most
|
||||
// specific one. values for the same cookie name that
|
||||
// follow are for less specific paths.
|
||||
if (lastCookies[name] === undefined) {
|
||||
if (isUndefined(lastCookies[name])) {
|
||||
lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
+53
-21
@@ -25,6 +25,7 @@ function nullFormRenameControl(control, name) {
|
||||
* @property {boolean} $dirty True if user has already interacted with the form.
|
||||
* @property {boolean} $valid True if all of the containing forms and controls are valid.
|
||||
* @property {boolean} $invalid True if at least one containing control or form is invalid.
|
||||
* @property {boolean} $pending True if at least one containing control or form is pending.
|
||||
* @property {boolean} $submitted True if user has submitted the form even if its invalid.
|
||||
*
|
||||
* @property {Object} $error Is an object hash, containing references to controls or
|
||||
@@ -64,8 +65,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
var form = this,
|
||||
controls = [];
|
||||
|
||||
var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
|
||||
|
||||
// init state
|
||||
form.$error = {};
|
||||
form.$$success = {};
|
||||
@@ -76,8 +75,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
form.$valid = true;
|
||||
form.$invalid = false;
|
||||
form.$submitted = false;
|
||||
|
||||
parentForm.$addControl(form);
|
||||
form.$$parentForm = nullFormCtrl;
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -116,11 +114,23 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name form.FormController#$addControl
|
||||
* @param {object} control control object, either a {@link form.FormController} or an
|
||||
* {@link ngModel.NgModelController}
|
||||
*
|
||||
* @description
|
||||
* Register a control with the form.
|
||||
* Register a control with the form. Input elements using ngModelController do this automatically
|
||||
* when they are linked.
|
||||
*
|
||||
* Input elements using ngModelController do this automatically when they are linked.
|
||||
* Note that the current state of the control will not be reflected on the new parent form. This
|
||||
* is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
|
||||
* state.
|
||||
*
|
||||
* However, if the method is used programmatically, for example by adding dynamically created controls,
|
||||
* or controls that have been previously removed without destroying their corresponding DOM element,
|
||||
* it's the developers responsiblity to make sure the current state propagates to the parent form.
|
||||
*
|
||||
* For example, if an input control is added that is already `$dirty` and has `$error` properties,
|
||||
* calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
|
||||
*/
|
||||
form.$addControl = function(control) {
|
||||
// Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
|
||||
@@ -131,6 +141,8 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
if (control.$name) {
|
||||
form[control.$name] = control;
|
||||
}
|
||||
|
||||
control.$$parentForm = form;
|
||||
};
|
||||
|
||||
// Private API: rename a form control
|
||||
@@ -147,11 +159,18 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name form.FormController#$removeControl
|
||||
* @param {object} control control object, either a {@link form.FormController} or an
|
||||
* {@link ngModel.NgModelController}
|
||||
*
|
||||
* @description
|
||||
* Deregister a control from the form.
|
||||
*
|
||||
* Input elements using ngModelController do this automatically when they are destroyed.
|
||||
*
|
||||
* Note that only the removed control's validation state (`$errors`etc.) will be removed from the
|
||||
* form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
|
||||
* different from case to case. For example, removing the only `$dirty` control from a form may or
|
||||
* may not mean that the form is still `$dirty`.
|
||||
*/
|
||||
form.$removeControl = function(control) {
|
||||
if (control.$name && form[control.$name] === control) {
|
||||
@@ -168,6 +187,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
});
|
||||
|
||||
arrayRemove(controls, control);
|
||||
control.$$parentForm = nullFormCtrl;
|
||||
};
|
||||
|
||||
|
||||
@@ -204,7 +224,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
delete object[property];
|
||||
}
|
||||
},
|
||||
parentForm: parentForm,
|
||||
$animate: $animate
|
||||
});
|
||||
|
||||
@@ -223,7 +242,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
$animate.addClass(element, DIRTY_CLASS);
|
||||
form.$dirty = true;
|
||||
form.$pristine = false;
|
||||
parentForm.$setDirty();
|
||||
form.$$parentForm.$setDirty();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -279,7 +298,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
form.$setSubmitted = function() {
|
||||
$animate.addClass(element, SUBMITTED_CLASS);
|
||||
form.$submitted = true;
|
||||
parentForm.$setSubmitted();
|
||||
form.$$parentForm.$setSubmitted();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -329,6 +348,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
* # CSS classes
|
||||
* - `ng-valid` is set if the form is valid.
|
||||
* - `ng-invalid` is set if the form is invalid.
|
||||
* - `ng-pending` is set if the form is pending.
|
||||
* - `ng-pristine` is set if the form is pristine.
|
||||
* - `ng-dirty` is set if the form is dirty.
|
||||
* - `ng-submitted` is set if the form was submitted.
|
||||
@@ -404,7 +424,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
</script>
|
||||
<style>
|
||||
.my-form {
|
||||
-webkit-transition:all linear 0.5s;
|
||||
transition:all linear 0.5s;
|
||||
background: transparent;
|
||||
}
|
||||
@@ -449,10 +468,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
* related scope, under this name.
|
||||
*/
|
||||
var formDirectiveFactory = function(isNgForm) {
|
||||
return ['$timeout', function($timeout) {
|
||||
return ['$timeout', '$parse', function($timeout, $parse) {
|
||||
var formDirective = {
|
||||
name: 'form',
|
||||
restrict: isNgForm ? 'EAC' : 'E',
|
||||
require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
|
||||
controller: FormController,
|
||||
compile: function ngFormCompile(formElement, attr) {
|
||||
// Setup initial state of the control
|
||||
@@ -461,7 +481,9 @@ var formDirectiveFactory = function(isNgForm) {
|
||||
var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
|
||||
|
||||
return {
|
||||
pre: function ngFormPreLink(scope, formElement, attr, controller) {
|
||||
pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
|
||||
var controller = ctrls[0];
|
||||
|
||||
// if `action` attr is not present on the form, prevent the default action (submission)
|
||||
if (!('action' in attr)) {
|
||||
// we can't use jq events because if a form is destroyed during submission the default
|
||||
@@ -490,22 +512,24 @@ var formDirectiveFactory = function(isNgForm) {
|
||||
});
|
||||
}
|
||||
|
||||
var parentFormCtrl = controller.$$parentForm;
|
||||
var parentFormCtrl = ctrls[1] || controller.$$parentForm;
|
||||
parentFormCtrl.$addControl(controller);
|
||||
|
||||
var setter = nameAttr ? getSetter(controller.$name) : noop;
|
||||
|
||||
if (nameAttr) {
|
||||
setter(scope, controller.$name, controller, controller.$name);
|
||||
setter(scope, controller);
|
||||
attr.$observe(nameAttr, function(newValue) {
|
||||
if (controller.$name === newValue) return;
|
||||
setter(scope, controller.$name, undefined, controller.$name);
|
||||
parentFormCtrl.$$renameControl(controller, newValue);
|
||||
setter(scope, controller.$name, controller, controller.$name);
|
||||
setter(scope, undefined);
|
||||
controller.$$parentForm.$$renameControl(controller, newValue);
|
||||
setter = getSetter(controller.$name);
|
||||
setter(scope, controller);
|
||||
});
|
||||
}
|
||||
formElement.on('$destroy', function() {
|
||||
parentFormCtrl.$removeControl(controller);
|
||||
if (nameAttr) {
|
||||
setter(scope, attr[nameAttr], undefined, controller.$name);
|
||||
}
|
||||
controller.$$parentForm.$removeControl(controller);
|
||||
setter(scope, undefined);
|
||||
extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
|
||||
});
|
||||
}
|
||||
@@ -514,6 +538,14 @@ var formDirectiveFactory = function(isNgForm) {
|
||||
};
|
||||
|
||||
return formDirective;
|
||||
|
||||
function getSetter(expression) {
|
||||
if (expression === '') {
|
||||
//create an assignable expression, so forms with an empty name can be renamed later
|
||||
return $parse('this[""]').assign;
|
||||
}
|
||||
return $parse(expression).assign || noop;
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
|
||||
+73
-31
@@ -6,12 +6,13 @@
|
||||
DIRTY_CLASS: false,
|
||||
UNTOUCHED_CLASS: false,
|
||||
TOUCHED_CLASS: false,
|
||||
$ngModelMinErr: false,
|
||||
ngModelMinErr: false,
|
||||
*/
|
||||
|
||||
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
|
||||
var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
|
||||
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
|
||||
// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
|
||||
var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
|
||||
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
||||
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
|
||||
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||
@@ -138,9 +139,17 @@ var inputType = {
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
* @param {string=} name Property name of the form under which the control is published.
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
|
||||
* valid ISO date string (yyyy-MM-dd).
|
||||
* valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
|
||||
* (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
|
||||
* constraint validation.
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
|
||||
* a valid ISO date string (yyyy-MM-dd).
|
||||
* a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
|
||||
* (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
|
||||
* constraint validation.
|
||||
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
|
||||
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
||||
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
|
||||
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
||||
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
||||
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
||||
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
||||
@@ -232,10 +241,18 @@ var inputType = {
|
||||
*
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
* @param {string=} name Property name of the form under which the control is published.
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
|
||||
* valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
|
||||
* a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
||||
* This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
|
||||
* inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
|
||||
* Note that `min` will also add native HTML5 constraint validation.
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
||||
* This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
|
||||
* inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
|
||||
* Note that `max` will also add native HTML5 constraint validation.
|
||||
* @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
|
||||
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
||||
* @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
|
||||
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
||||
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
||||
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
||||
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
||||
@@ -316,7 +333,7 @@ var inputType = {
|
||||
*
|
||||
* @description
|
||||
* Input with time validation and transformation. In browsers that do not yet support
|
||||
* the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
|
||||
* the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
|
||||
* local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
|
||||
* Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
|
||||
*
|
||||
@@ -328,10 +345,18 @@ var inputType = {
|
||||
*
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
* @param {string=} name Property name of the form under which the control is published.
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
|
||||
* valid ISO time format (HH:mm:ss).
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
|
||||
* valid ISO time format (HH:mm:ss).
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
||||
* This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
|
||||
* attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
|
||||
* native HTML5 constraint validation.
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
||||
* This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
|
||||
* attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
|
||||
* native HTML5 constraint validation.
|
||||
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
|
||||
* `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
||||
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
|
||||
* `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
||||
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
||||
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
||||
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
||||
@@ -423,10 +448,18 @@ var inputType = {
|
||||
*
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
* @param {string=} name Property name of the form under which the control is published.
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
|
||||
* valid ISO week format (yyyy-W##).
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
|
||||
* a valid ISO week format (yyyy-W##).
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
||||
* This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
|
||||
* attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
|
||||
* native HTML5 constraint validation.
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
||||
* This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
|
||||
* attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
|
||||
* native HTML5 constraint validation.
|
||||
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
|
||||
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
||||
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
|
||||
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
||||
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
||||
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
||||
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
||||
@@ -520,10 +553,19 @@ var inputType = {
|
||||
*
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
* @param {string=} name Property name of the form under which the control is published.
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
|
||||
* a valid ISO month format (yyyy-MM).
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
|
||||
* be a valid ISO month format (yyyy-MM).
|
||||
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
||||
* This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
|
||||
* attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
|
||||
* native HTML5 constraint validation.
|
||||
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
||||
* This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
|
||||
* attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
|
||||
* native HTML5 constraint validation.
|
||||
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
|
||||
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
||||
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
|
||||
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
||||
|
||||
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
||||
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
||||
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
||||
@@ -1128,7 +1170,11 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
||||
element.on('change', listener);
|
||||
|
||||
ctrl.$render = function() {
|
||||
element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
|
||||
// Workaround for Firefox validation #12102.
|
||||
var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;
|
||||
if (element.val() !== value) {
|
||||
element.val(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1239,7 +1285,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;
|
||||
@@ -1281,7 +1327,7 @@ function createDateInputType(type, regexp, parseDate, format) {
|
||||
}
|
||||
|
||||
function parseObservedDateValue(val) {
|
||||
return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
|
||||
return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1292,11 +1338,7 @@ function badInputChecker(scope, element, attr, ctrl) {
|
||||
if (nativeValidation) {
|
||||
ctrl.$parsers.push(function(value) {
|
||||
var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
|
||||
// Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
|
||||
// - also sets validity.badInput (should only be validity.typeMismatch).
|
||||
// - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
|
||||
// - can ignore this case as we can still read out the erroneous email...
|
||||
return validity.badInput && !validity.typeMismatch ? undefined : value;
|
||||
return validity.badInput || validity.typeMismatch ? undefined : value;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1315,7 +1357,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();
|
||||
}
|
||||
@@ -1408,7 +1450,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);
|
||||
|
||||
@@ -60,7 +60,7 @@ var ngBindDirective = ['$compile', function($compile) {
|
||||
$compile.$$addBindingInfo(element, attr.ngBind);
|
||||
element = element[0];
|
||||
scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
|
||||
element.textContent = value === undefined ? '' : value;
|
||||
element.textContent = isUndefined(value) ? '' : value;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -128,7 +128,7 @@ var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate
|
||||
$compile.$$addBindingInfo(element, interpolateFn.expressions);
|
||||
element = element[0];
|
||||
attr.$observe('ngBindTemplate', function(value) {
|
||||
element.textContent = value === undefined ? '' : value;
|
||||
element.textContent = isUndefined(value) ? '' : value;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -262,7 +262,6 @@ function classDirective(name, selector) {
|
||||
</file>
|
||||
<file name="style.css">
|
||||
.base-class {
|
||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
}
|
||||
|
||||
|
||||
+47
-17
@@ -6,27 +6,29 @@
|
||||
*
|
||||
* @element html
|
||||
* @description
|
||||
* Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
|
||||
*
|
||||
* Angular has some features that can break certain
|
||||
* [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.
|
||||
*
|
||||
* If you intend to implement these rules then you must tell Angular not to use these features.
|
||||
*
|
||||
* This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
|
||||
*
|
||||
* CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
|
||||
* For Angular to be CSP compatible there are only two things that we need to do differently:
|
||||
*
|
||||
* - don't use `Function` constructor to generate optimized value getters
|
||||
* - don't inject custom stylesheet into the document
|
||||
* The following rules affect Angular:
|
||||
*
|
||||
* AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
|
||||
* directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
|
||||
* evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
|
||||
* be raised.
|
||||
* * `unsafe-eval`: this rule forbids apps to use `eval` or `Function(string)` generated functions
|
||||
* (among other things). Angular makes use of this in the {@link $parse} service to provide a 30%
|
||||
* increase in the speed of evaluating Angular expressions.
|
||||
*
|
||||
* CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
|
||||
* includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
|
||||
* To make those directives work in CSP mode, include the `angular-csp.css` manually.
|
||||
* * `unsafe-inline`: this rule forbids apps from inject custom styles into the document. Angular
|
||||
* makes use of this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}).
|
||||
* To make these directives work when a CSP rule is blocking inline styles, you must link to the
|
||||
* `angular-csp.css` in your HTML manually.
|
||||
*
|
||||
* Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
|
||||
* autodetection however triggers a CSP error to be logged in the console:
|
||||
* If you do not provide `ngCsp` then Angular tries to autodetect if CSP is blocking unsafe-eval
|
||||
* and automatically deactivates this feature in the {@link $parse} service. This autodetection,
|
||||
* however, triggers a CSP error to be logged in the console:
|
||||
*
|
||||
* ```
|
||||
* Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
|
||||
@@ -35,11 +37,39 @@
|
||||
* ```
|
||||
*
|
||||
* This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
|
||||
* directive on the root element of the application or on the `angular.js` script tag, whichever
|
||||
* appears first in the html document.
|
||||
* directive on an element of the HTML document that appears before the `<script>` tag that loads
|
||||
* the `angular.js` file.
|
||||
*
|
||||
* *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
|
||||
*
|
||||
* You can specify which of the CSP related Angular features should be deactivated by providing
|
||||
* a value for the `ng-csp` attribute. The options are as follows:
|
||||
*
|
||||
* * no-inline-style: this stops Angular from injecting CSS styles into the DOM
|
||||
*
|
||||
* * no-unsafe-eval: this stops Angular from optimising $parse with unsafe eval of strings
|
||||
*
|
||||
* You can use these values in the following combinations:
|
||||
*
|
||||
*
|
||||
* * No declaration means that Angular will assume that you can do inline styles, but it will do
|
||||
* a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous versions
|
||||
* of Angular.
|
||||
*
|
||||
* * A simple `ng-csp` (or `data-ng-csp`) attribute will tell Angular to deactivate both inline
|
||||
* styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous versions
|
||||
* of Angular.
|
||||
*
|
||||
* * Specifying only `no-unsafe-eval` tells Angular that we must not use eval, but that we can inject
|
||||
* inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
|
||||
*
|
||||
* * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
|
||||
* run eval - no automcatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
|
||||
*
|
||||
* * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
|
||||
* styles nor use eval, which is the same as an empty: ng-csp.
|
||||
* E.g.`<body ng-csp="no-inline-style;no-unsafe-eval">`
|
||||
*
|
||||
* @example
|
||||
* This example shows how to apply the `ngCsp` directive to the `html` tag.
|
||||
```html
|
||||
@@ -171,4 +201,4 @@
|
||||
|
||||
// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
|
||||
// bootstrap the system (before $parse is instantiated), for this reason we just have
|
||||
// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
|
||||
// the csp() fn that looks for the `ng-csp` attribute anywhere in the current doc
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
}
|
||||
|
||||
.animate-if.ng-enter, .animate-if.ng-leave {
|
||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,13 @@
|
||||
* @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
|
||||
* make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
|
||||
* @param {string=} onload Expression to evaluate when a new partial is loaded.
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* **Note:** When using onload on SVG elements in IE11, the browser will try to call
|
||||
* a function with the name on the window element, which will usually throw a
|
||||
* "function is undefined" error. To fix this, you can instead use `data-onload` or a
|
||||
* different form that {@link guide/directive#normalization matches} `onload`.
|
||||
* </div>
|
||||
*
|
||||
* @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
|
||||
* $anchorScroll} to scroll the viewport after the content is loaded.
|
||||
*
|
||||
@@ -85,7 +91,6 @@
|
||||
}
|
||||
|
||||
.slide-animate.ng-enter, .slide-animate.ng-leave {
|
||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
|
||||
position:absolute;
|
||||
|
||||
@@ -10,16 +10,18 @@
|
||||
* current scope.
|
||||
*
|
||||
* <div class="alert alert-danger">
|
||||
* The only appropriate use of `ngInit` is for aliasing special properties of
|
||||
* {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
|
||||
* should use {@link guide/controller controllers} rather than `ngInit`
|
||||
* to initialize values on a scope.
|
||||
* This directive can be abused to add unnecessary amounts of logic into your templates.
|
||||
* There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
|
||||
* {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
|
||||
* server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
|
||||
* rather than `ngInit` to initialize values on a scope.
|
||||
* </div>
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
|
||||
* sure you have parenthesis for correct precedence:
|
||||
* **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
|
||||
* sure you have parentheses to ensure correct operator precedence:
|
||||
* <pre class="prettyprint">
|
||||
* `<div ng-init="test1 = (data | orderBy:'name')"></div>`
|
||||
* `<div ng-init="test1 = ($index | toString)"></div>`
|
||||
* </pre>
|
||||
* </div>
|
||||
*
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
* </file>
|
||||
* </example>
|
||||
*
|
||||
* ### Example - splitting on whitespace
|
||||
* ### Example - splitting on newline
|
||||
* <example name="ngList-directive-newlines">
|
||||
* <file name="index.html">
|
||||
* <textarea ng-model="list" ng-list=" " ng-trim="false"></textarea>
|
||||
|
||||
+78
-51
@@ -14,16 +14,19 @@ var VALID_CLASS = 'ng-valid',
|
||||
DIRTY_CLASS = 'ng-dirty',
|
||||
UNTOUCHED_CLASS = 'ng-untouched',
|
||||
TOUCHED_CLASS = 'ng-touched',
|
||||
PENDING_CLASS = 'ng-pending';
|
||||
PENDING_CLASS = 'ng-pending',
|
||||
EMPTY_CLASS = 'ng-empty',
|
||||
NOT_EMPTY_CLASS = 'ng-not-empty';
|
||||
|
||||
|
||||
var $ngModelMinErr = new minErr('ngModel');
|
||||
var ngModelMinErr = minErr('ngModel');
|
||||
|
||||
/**
|
||||
* @ngdoc type
|
||||
* @name ngModel.NgModelController
|
||||
*
|
||||
* @property {string} $viewValue Actual string value in the view.
|
||||
* @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a
|
||||
* String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue
|
||||
* is set.
|
||||
* @property {*} $modelValue The value in the model that the control is bound to.
|
||||
* @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
|
||||
the control reads value from the DOM. The functions are called in array order, each passing
|
||||
@@ -237,7 +240,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
this.$$success = {}; // keep valid keys here
|
||||
this.$pending = undefined; // keep pending keys here
|
||||
this.$name = $interpolate($attr.name || '', false)($scope);
|
||||
|
||||
this.$$parentForm = nullFormCtrl;
|
||||
|
||||
var parsedNgModel = $parse($attr.ngModel),
|
||||
parsedNgModelAssign = parsedNgModel.assign,
|
||||
@@ -268,7 +271,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
}
|
||||
};
|
||||
} else if (!parsedNgModel.assign) {
|
||||
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
|
||||
throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
|
||||
$attr.ngModel, startingTag($element));
|
||||
}
|
||||
};
|
||||
@@ -317,8 +320,18 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
return isUndefined(value) || value === '' || value === null || value !== value;
|
||||
};
|
||||
|
||||
var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
|
||||
currentValidationRunId = 0;
|
||||
this.$$updateEmptyClasses = function(value) {
|
||||
if (ctrl.$isEmpty(value)) {
|
||||
$animate.removeClass($element, NOT_EMPTY_CLASS);
|
||||
$animate.addClass($element, EMPTY_CLASS);
|
||||
} else {
|
||||
$animate.removeClass($element, EMPTY_CLASS);
|
||||
$animate.addClass($element, NOT_EMPTY_CLASS);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var currentValidationRunId = 0;
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -351,7 +364,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
unset: function(object, property) {
|
||||
delete object[property];
|
||||
},
|
||||
parentForm: parentForm,
|
||||
$animate: $animate
|
||||
});
|
||||
|
||||
@@ -389,7 +401,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
ctrl.$pristine = false;
|
||||
$animate.removeClass($element, PRISTINE_CLASS);
|
||||
$animate.addClass($element, DIRTY_CLASS);
|
||||
parentForm.$setDirty();
|
||||
ctrl.$$parentForm.$setDirty();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -559,7 +571,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
|
||||
function processParseErrors() {
|
||||
var errorKey = ctrl.$$parserName || 'parse';
|
||||
if (parserValid === undefined) {
|
||||
if (isUndefined(parserValid)) {
|
||||
setValidity(errorKey, null);
|
||||
} else {
|
||||
if (!parserValid) {
|
||||
@@ -599,7 +611,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);
|
||||
@@ -655,6 +667,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
|
||||
return;
|
||||
}
|
||||
ctrl.$$updateEmptyClasses(viewValue);
|
||||
ctrl.$$lastCommittedViewValue = viewValue;
|
||||
|
||||
// change to dirty
|
||||
@@ -729,37 +742,47 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* @description
|
||||
* Update the view value.
|
||||
*
|
||||
* This method should be called when an input directive want to change the view value; typically,
|
||||
* this is done from within a DOM event handler.
|
||||
* This method should be called when a control wants to change the view value; typically,
|
||||
* this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
|
||||
* directive calls it when the value of the input changes and {@link ng.directive:select select}
|
||||
* calls it when an option is selected.
|
||||
*
|
||||
* For example {@link ng.directive:input input} calls it when the value of the input changes and
|
||||
* {@link ng.directive:select select} calls it when an option is selected.
|
||||
*
|
||||
* If the new `value` is an object (rather than a string or a number), we should make a copy of the
|
||||
* object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
|
||||
* watch of objects, it only looks for a change of identity. If you only change the property of
|
||||
* the object then ngModel will not realise that the object has changed and will not invoke the
|
||||
* `$parsers` and `$validators` pipelines.
|
||||
*
|
||||
* For this reason, you should not change properties of the copy once it has been passed to
|
||||
* `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
|
||||
*
|
||||
* When this method is called, the new `value` will be staged for committing through the `$parsers`
|
||||
* When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
|
||||
* and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
|
||||
* value sent directly for processing, finally to be applied to `$modelValue` and then the
|
||||
* **expression** specified in the `ng-model` attribute.
|
||||
*
|
||||
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
|
||||
* **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
|
||||
* in the `$viewChangeListeners` list, are called.
|
||||
*
|
||||
* In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
|
||||
* and the `default` trigger is not listed, all those actions will remain pending until one of the
|
||||
* `updateOn` events is triggered on the DOM element.
|
||||
* All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
|
||||
* directive is used with a custom debounce for this particular event.
|
||||
* Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
|
||||
* is specified, once the timer runs out.
|
||||
*
|
||||
* Note that calling this function does not trigger a `$digest`.
|
||||
* When used with standard inputs, the view value will always be a string (which is in some cases
|
||||
* parsed into another type, such as a `Date` object for `input[date]`.)
|
||||
* However, custom controls might also pass objects to this method. In this case, we should make
|
||||
* a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
|
||||
* perform a deep watch of objects, it only looks for a change of identity. If you only change
|
||||
* the property of the object then ngModel will not realise that the object has changed and
|
||||
* will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
|
||||
* not change properties of the copy once it has been passed to `$setViewValue`.
|
||||
* Otherwise you may cause the model value on the scope to change incorrectly.
|
||||
*
|
||||
* @param {string} value Value from the view.
|
||||
* <div class="alert alert-info">
|
||||
* In any case, the value passed to the method should always reflect the current value
|
||||
* of the control. For example, if you are calling `$setViewValue` for an input element,
|
||||
* you should pass the input DOM value. Otherwise, the control and the scope model become
|
||||
* out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
|
||||
* the control's DOM value in any way. If we want to change the control's DOM value
|
||||
* programmatically, we should update the `ngModel` scope expression. Its new value will be
|
||||
* picked up by the model controller, which will run it through the `$formatters`, `$render` it
|
||||
* to update the DOM, and finally call `$validate` on it.
|
||||
* </div>
|
||||
*
|
||||
* @param {*} value value from the view.
|
||||
* @param {string} trigger Event that triggered the update.
|
||||
*/
|
||||
this.$setViewValue = function(value, trigger) {
|
||||
@@ -827,6 +850,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
viewValue = formatters[idx](viewValue);
|
||||
}
|
||||
if (ctrl.$viewValue !== viewValue) {
|
||||
ctrl.$$updateEmptyClasses(viewValue);
|
||||
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
|
||||
ctrl.$render();
|
||||
|
||||
@@ -857,7 +881,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* require.
|
||||
* - Providing validation behavior (i.e. required, number, email, url).
|
||||
* - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
|
||||
* - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
|
||||
* - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`,
|
||||
* `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations.
|
||||
* - Registering the control with its parent {@link ng.directive:form form}.
|
||||
*
|
||||
* Note: `ngModel` will try to bind to the property given by evaluating the expression on the
|
||||
@@ -898,13 +923,16 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* - `ng-touched`: the control has been blurred
|
||||
* - `ng-untouched`: the control hasn't been blurred
|
||||
* - `ng-pending`: any `$asyncValidators` are unfulfilled
|
||||
* - `ng-empty`: the view does not contain a value or the value is deemed "empty", as defined
|
||||
* by the {@link ngModel.NgModelController#$isEmpty} method
|
||||
* - `ng-not-empty`: the view contains a non-empty value
|
||||
*
|
||||
* Keep in mind that ngAnimate can detect each of these classes when added and removed.
|
||||
*
|
||||
* ## Animation Hooks
|
||||
*
|
||||
* Animations within models are triggered when any of the associated CSS classes are added and removed
|
||||
* on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
|
||||
* on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`,
|
||||
* `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
|
||||
* The animations that are triggered within ngModel are similar to how they work in ngClass and
|
||||
* animations can be hooked into using CSS transitions, keyframes as well as JS animations.
|
||||
@@ -936,7 +964,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
</script>
|
||||
<style>
|
||||
.my-input {
|
||||
-webkit-transition:all linear 0.5s;
|
||||
transition:all linear 0.5s;
|
||||
background: transparent;
|
||||
}
|
||||
@@ -1023,7 +1050,7 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
|
||||
return {
|
||||
pre: function ngModelPreLink(scope, element, attr, ctrls) {
|
||||
var modelCtrl = ctrls[0],
|
||||
formCtrl = ctrls[1] || nullFormCtrl;
|
||||
formCtrl = ctrls[1] || modelCtrl.$$parentForm;
|
||||
|
||||
modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
|
||||
|
||||
@@ -1032,12 +1059,12 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
|
||||
|
||||
attr.$observe('name', function(newValue) {
|
||||
if (modelCtrl.$name !== newValue) {
|
||||
formCtrl.$$renameControl(modelCtrl, newValue);
|
||||
modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
|
||||
}
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
formCtrl.$removeControl(modelCtrl);
|
||||
modelCtrl.$$parentForm.$removeControl(modelCtrl);
|
||||
});
|
||||
},
|
||||
post: function ngModelPostLink(scope, element, attr, ctrls) {
|
||||
@@ -1133,12 +1160,13 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
||||
</label><br />
|
||||
</form>
|
||||
<pre>user.name = <span ng-bind="user.name"></span></pre>
|
||||
<pre>user.data = <span ng-bind="user.data"></span></pre>
|
||||
</div>
|
||||
</file>
|
||||
<file name="app.js">
|
||||
angular.module('optionsExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.user = { name: 'say', data: '' };
|
||||
$scope.user = { name: 'John', data: '' };
|
||||
|
||||
$scope.cancel = function(e) {
|
||||
if (e.keyCode == 27) {
|
||||
@@ -1153,20 +1181,20 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
||||
var other = element(by.model('user.data'));
|
||||
|
||||
it('should allow custom events', function() {
|
||||
input.sendKeys(' hello');
|
||||
input.sendKeys(' Doe');
|
||||
input.click();
|
||||
expect(model.getText()).toEqual('say');
|
||||
expect(model.getText()).toEqual('John');
|
||||
other.click();
|
||||
expect(model.getText()).toEqual('say hello');
|
||||
expect(model.getText()).toEqual('John Doe');
|
||||
});
|
||||
|
||||
it('should $rollbackViewValue when model changes', function() {
|
||||
input.sendKeys(' hello');
|
||||
expect(input.getAttribute('value')).toEqual('say hello');
|
||||
input.sendKeys(' Doe');
|
||||
expect(input.getAttribute('value')).toEqual('John Doe');
|
||||
input.sendKeys(protractor.Key.ESCAPE);
|
||||
expect(input.getAttribute('value')).toEqual('say');
|
||||
expect(input.getAttribute('value')).toEqual('John');
|
||||
other.click();
|
||||
expect(model.getText()).toEqual('say');
|
||||
expect(model.getText()).toEqual('John');
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
@@ -1192,7 +1220,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
||||
<file name="app.js">
|
||||
angular.module('optionsExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.user = { name: 'say' };
|
||||
$scope.user = { name: 'Igor' };
|
||||
}]);
|
||||
</file>
|
||||
</example>
|
||||
@@ -1236,7 +1264,7 @@ var ngModelOptionsDirective = function() {
|
||||
var that = this;
|
||||
this.$options = copy($scope.$eval($attrs.ngModelOptions));
|
||||
// Allow adding/overriding bound events
|
||||
if (this.$options.updateOn !== undefined) {
|
||||
if (isDefined(this.$options.updateOn)) {
|
||||
this.$options.updateOnDefault = false;
|
||||
// extract "default" pseudo-event from list of events that can trigger a model update
|
||||
this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
|
||||
@@ -1259,7 +1287,6 @@ function addSetValidityMethod(context) {
|
||||
classCache = {},
|
||||
set = context.set,
|
||||
unset = context.unset,
|
||||
parentForm = context.parentForm,
|
||||
$animate = context.$animate;
|
||||
|
||||
classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
|
||||
@@ -1267,7 +1294,7 @@ function addSetValidityMethod(context) {
|
||||
ctrl.$setValidity = setValidity;
|
||||
|
||||
function setValidity(validationErrorKey, state, controller) {
|
||||
if (state === undefined) {
|
||||
if (isUndefined(state)) {
|
||||
createAndSet('$pending', validationErrorKey, controller);
|
||||
} else {
|
||||
unsetAndCleanup('$pending', validationErrorKey, controller);
|
||||
@@ -1311,7 +1338,7 @@ function addSetValidityMethod(context) {
|
||||
}
|
||||
|
||||
toggleValidationCss(validationErrorKey, combinedState);
|
||||
parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
|
||||
ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
|
||||
}
|
||||
|
||||
function createAndSet(name, value, controller) {
|
||||
|
||||
@@ -33,19 +33,27 @@ var ngOptionsMinErr = minErr('ngOptions');
|
||||
*
|
||||
* ## Complex Models (objects or collections)
|
||||
*
|
||||
* **Note:** By default, `ngModel` watches the model by reference, not value. This is important when
|
||||
* binding any input directive to a model that is an object or a collection.
|
||||
* By default, `ngModel` watches the model by reference, not value. This is important to know when
|
||||
* binding the select to a model that is an object or a collection.
|
||||
*
|
||||
* Since this is a common situation for `ngOptions` the directive additionally watches the model using
|
||||
* `$watchCollection` when the select has the `multiple` attribute or when there is a `track by` clause in
|
||||
* the options expression. This allows ngOptions to trigger a re-rendering of the options even if the actual
|
||||
* object/collection has not changed identity but only a property on the object or an item in the collection
|
||||
* changes.
|
||||
* One issue occurs if you want to preselect an option. For example, if you set
|
||||
* the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
|
||||
* because the objects are not identical. So by default, you should always reference the item in your collection
|
||||
* for preselections, e.g.: `$scope.selected = $scope.collection[3]`.
|
||||
*
|
||||
* Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
|
||||
* of the item not by reference, but by the result of the `track by` expression. For example, if your
|
||||
* collection items have an id property, you would `track by item.id`.
|
||||
*
|
||||
* A different issue with objects or collections is that ngModel won't detect if an object property or
|
||||
* a collection item changes. For that reason, `ngOptions` additionally watches the model using
|
||||
* `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
|
||||
* This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
|
||||
* has not changed identity, but only a property on the object or an item in the collection changes.
|
||||
*
|
||||
* Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
|
||||
* if the model is an array). This means that changing a property deeper inside the object/collection that the
|
||||
* first level will not trigger a re-rendering.
|
||||
*
|
||||
* if the model is an array). This means that changing a property deeper than the first level inside the
|
||||
* object/collection will not trigger a re-rendering.
|
||||
*
|
||||
* ## `select` **`as`**
|
||||
*
|
||||
@@ -58,17 +66,13 @@ var ngOptionsMinErr = minErr('ngOptions');
|
||||
* ### `select` **`as`** and **`track by`**
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
|
||||
* Be careful when using `select` **`as`** and **`track by`** in the same expression.
|
||||
* </div>
|
||||
*
|
||||
* Consider the following example:
|
||||
*
|
||||
* ```html
|
||||
* <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
|
||||
* ```
|
||||
* Given this array of items on the $scope:
|
||||
*
|
||||
* ```js
|
||||
* $scope.values = [{
|
||||
* $scope.items = [{
|
||||
* id: 1,
|
||||
* label: 'aLabel',
|
||||
* subItem: { name: 'aSubItem' }
|
||||
@@ -77,20 +81,33 @@ var ngOptionsMinErr = minErr('ngOptions');
|
||||
* label: 'bLabel',
|
||||
* subItem: { name: 'bSubItem' }
|
||||
* }];
|
||||
*
|
||||
* $scope.selected = { name: 'aSubItem' };
|
||||
* ```
|
||||
*
|
||||
* With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
|
||||
* of the data source (to `item` in this example). To calculate whether an element is selected, we do the
|
||||
* following:
|
||||
* This will work:
|
||||
*
|
||||
* 1. Apply **`track by`** to the elements 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'}`, so the **`track by`** expression is applied to
|
||||
* a wrong object, the selected element can't be found, `<select>` is always reset to the "not
|
||||
* selected" option.
|
||||
* ```html
|
||||
* <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
|
||||
* ```
|
||||
* ```js
|
||||
* $scope.selected = $scope.items[0];
|
||||
* ```
|
||||
*
|
||||
* but this will not work:
|
||||
*
|
||||
* ```html
|
||||
* <select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
|
||||
* ```
|
||||
* ```js
|
||||
* $scope.selected = $scope.items[0].subItem;
|
||||
* ```
|
||||
*
|
||||
* In both examples, the **`track by`** expression is applied successfully to each `item` in the
|
||||
* `items` array. Because the selected option has been set programmatically in the controller, the
|
||||
* **`track by`** expression is also applied to the `ngModel` value. In the first example, the
|
||||
* `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
|
||||
* no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
|
||||
* expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
|
||||
* is not matched against any `<option>` and the `<select>` appears as having no selected value.
|
||||
*
|
||||
*
|
||||
* @param {string} ngModel Assignable angular expression to data-bind to.
|
||||
@@ -392,17 +409,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
var optionTemplate = document.createElement('option'),
|
||||
optGroupTemplate = document.createElement('optgroup');
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
terminal: true,
|
||||
require: ['select', '?ngModel'],
|
||||
link: function(scope, selectElement, attr, ctrls) {
|
||||
|
||||
// if ngModel is not defined, we don't need to do anything
|
||||
var ngModelCtrl = ctrls[1];
|
||||
if (!ngModelCtrl) return;
|
||||
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
|
||||
|
||||
var selectCtrl = ctrls[0];
|
||||
var ngModelCtrl = ctrls[1];
|
||||
var multiple = attr.multiple;
|
||||
|
||||
// The emptyOption allows the application developer to provide their own custom "empty"
|
||||
@@ -451,7 +461,6 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
unknownOption.remove();
|
||||
};
|
||||
|
||||
|
||||
// Update the controller methods for multiple selectable options
|
||||
if (!multiple) {
|
||||
|
||||
@@ -526,7 +535,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
|
||||
forEach(selectedValues, function(value) {
|
||||
var option = options.selectValueMap[value];
|
||||
if (!option.disabled) selections.push(options.getViewValueFromOption(option));
|
||||
if (option && !option.disabled) selections.push(options.getViewValueFromOption(option));
|
||||
});
|
||||
|
||||
return selections;
|
||||
@@ -579,11 +588,16 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
function updateOptionElement(option, element) {
|
||||
option.element = element;
|
||||
element.disabled = option.disabled;
|
||||
if (option.value !== element.value) element.value = option.selectValue;
|
||||
// NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
|
||||
// selects in certain circumstances when multiple selects are next to each other and display
|
||||
// the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
|
||||
// See https://github.com/angular/angular.js/issues/11314 for more info.
|
||||
// This is unfortunately untestable with unit / e2e tests
|
||||
if (option.label !== element.label) {
|
||||
element.label = option.label;
|
||||
element.textContent = option.label;
|
||||
}
|
||||
if (option.value !== element.value) element.value = option.selectValue;
|
||||
}
|
||||
|
||||
function addOrReuseElement(parent, current, type, templateElement) {
|
||||
@@ -621,10 +635,15 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
var emptyOption_ = emptyOption && emptyOption[0];
|
||||
var unknownOption_ = unknownOption && unknownOption[0];
|
||||
|
||||
// We cannot rely on the extracted empty option being the same as the compiled empty option,
|
||||
// because the compiled empty option might have been replaced by a comment because
|
||||
// it had an "element" transclusion directive on it (such as ngIf)
|
||||
if (emptyOption_ || unknownOption_) {
|
||||
while (current &&
|
||||
(current === emptyOption_ ||
|
||||
current === unknownOption_)) {
|
||||
current === unknownOption_ ||
|
||||
current.nodeType === NODE_TYPE_COMMENT ||
|
||||
current.value === '')) {
|
||||
current = current.nextSibling;
|
||||
}
|
||||
}
|
||||
@@ -653,7 +672,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
var groupElement;
|
||||
var optionElement;
|
||||
|
||||
if (option.group) {
|
||||
if (isDefined(option.group)) {
|
||||
|
||||
// This option is to live in a group
|
||||
// See if we have already created this group
|
||||
@@ -721,7 +740,20 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
terminal: true,
|
||||
require: ['select', 'ngModel'],
|
||||
link: {
|
||||
pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
|
||||
// Deactivate the SelectController.register method to prevent
|
||||
// option directives from accidentally registering themselves
|
||||
// (and unwanted $destroy handlers etc.)
|
||||
ctrls[0].registerOption = noop;
|
||||
},
|
||||
post: ngOptionsPostLink
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
* | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
|
||||
* | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
|
||||
*
|
||||
* Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
|
||||
* This may be useful when, for instance, nesting ngRepeats.
|
||||
* <div class="alert alert-info">
|
||||
* Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
|
||||
* This may be useful when, for instance, nesting ngRepeats.
|
||||
* </div>
|
||||
*
|
||||
*
|
||||
* # Iterating over object properties
|
||||
@@ -41,7 +43,7 @@
|
||||
* Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
|
||||
* when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
|
||||
* keys in the order in which they were defined, although there are exceptions when keys are deleted
|
||||
* and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
|
||||
* and reinstated. See the [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).
|
||||
*
|
||||
* If this is not desired, the recommended workaround is to convert your object into an array
|
||||
* that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
|
||||
@@ -51,15 +53,21 @@
|
||||
*
|
||||
* # Tracking and Duplicates
|
||||
*
|
||||
* When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
|
||||
* `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in
|
||||
* the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
|
||||
*
|
||||
* * When an item is added, a new instance of the template is added to the DOM.
|
||||
* * When an item is removed, its template instance is removed from the DOM.
|
||||
* * When items are reordered, their respective templates are reordered in the DOM.
|
||||
*
|
||||
* By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
|
||||
* there are duplicates, it is not possible to maintain a one-to-one mapping between collection
|
||||
* items and DOM elements.
|
||||
* To minimize creation of DOM elements, `ngRepeat` uses a function
|
||||
* to "keep track" of all items in the collection and their corresponding DOM elements.
|
||||
* For example, if an item is added to the collection, ngRepeat will know that all other items
|
||||
* already have DOM elements, and will not re-render them.
|
||||
*
|
||||
* The default tracking function (which tracks items by their identity) does not allow
|
||||
* duplicate items in arrays. This is because when there are duplicates, it is not possible
|
||||
* to maintain a one-to-one mapping between collection items and DOM elements.
|
||||
*
|
||||
* If you do need to repeat duplicate items, you can substitute the default tracking behavior
|
||||
* with your own using the `track by` expression.
|
||||
@@ -72,7 +80,7 @@
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* You may use arbitrary expressions in `track by`, including references to custom functions
|
||||
* You may also use arbitrary expressions in `track by`, including references to custom functions
|
||||
* on the scope:
|
||||
* ```html
|
||||
* <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
|
||||
@@ -80,10 +88,14 @@
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* If you are working with objects that have an identifier property, you can track
|
||||
* <div class="alert alert-success">
|
||||
* If you are working with objects that have an identifier property, you should track
|
||||
* by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
|
||||
* will not have to rebuild the DOM elements for items it has already rendered, even if the
|
||||
* JavaScript objects in the collection have been substituted for new ones:
|
||||
* JavaScript objects in the collection have been substituted for new ones. For large collections,
|
||||
* this signifincantly improves rendering performance. If you don't have a unique identifier,
|
||||
* `track by $index` can also provide a performance boost.
|
||||
* </div>
|
||||
* ```html
|
||||
* <div ng-repeat="model in collection track by model.id">
|
||||
* {{model.name}}
|
||||
@@ -256,7 +268,6 @@
|
||||
.animate-repeat.ng-move,
|
||||
.animate-repeat.ng-enter,
|
||||
.animate-repeat.ng-leave {
|
||||
-webkit-transition:all linear 0.5s;
|
||||
transition:all linear 0.5s;
|
||||
}
|
||||
|
||||
@@ -428,7 +439,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
||||
// if object, extract keys, in enumeration order, unsorted
|
||||
collectionKeys = [];
|
||||
for (var itemKey in collection) {
|
||||
if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
|
||||
if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
|
||||
collectionKeys.push(itemKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,9 +125,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
|
||||
background: white;
|
||||
}
|
||||
|
||||
.animate-show.ng-hide-add.ng-hide-add-active,
|
||||
.animate-show.ng-hide-remove.ng-hide-remove-active {
|
||||
-webkit-transition: all linear 0.5s;
|
||||
.animate-show.ng-hide-add, .animate-show.ng-hide-remove {
|
||||
transition: all linear 0.5s;
|
||||
}
|
||||
|
||||
@@ -284,7 +282,6 @@ var ngShowDirective = ['$animate', function($animate) {
|
||||
</file>
|
||||
<file name="animations.css">
|
||||
.animate-hide {
|
||||
-webkit-transition: all linear 0.5s;
|
||||
transition: all linear 0.5s;
|
||||
line-height: 20px;
|
||||
opacity: 1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user