Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a84393eadb | |||
| c429ad82f5 | |||
| 900c7cd923 | |||
| 2d3303ddda | |||
| a985adfdab | |||
| ca41996ef7 | |||
| 9a60408c80 | |||
| 09f6061a8e | |||
| 2d1ee4bffd | |||
| a412622f69 | |||
| 63ffe5c360 | |||
| 2fc954d33a | |||
| 512c081187 | |||
| 2563ff7ba9 | |||
| 0a641c0181 | |||
| da04571dbc | |||
| 7f1cd3e6a2 | |||
| 6d85f24e20 | |||
| 0afd775433 | |||
| 8eb01216b4 | |||
| 323f9ab736 | |||
| 5ba4419e26 | |||
| 529b2507bd | |||
| 6d19aa2e7c | |||
| bf35d53855 | |||
| 6c4581fcb6 | |||
| 620a20d1b3 | |||
| 1f8431bfaa | |||
| b8773a71b5 | |||
| 8a63071ab0 | |||
| e2a0368726 | |||
| d9157849df | |||
| d558dc5f95 | |||
| 616695eb05 | |||
| 9ac4e5a64b | |||
| fcb6e1e96b | |||
| cf972fd0bd | |||
| ffc3115705 | |||
| 9590bcf062 | |||
| 689c01f599 | |||
| 2334a5101d | |||
| ed7777d3e1 | |||
| a1648737bd | |||
| 420586bd09 | |||
| d89afc488f | |||
| 0a8a6fa36b | |||
| e1a182b105 | |||
| 214f6822c3 | |||
| 9c5a1cd43c | |||
| 8120ab2f77 | |||
| 2f08eae48f | |||
| 6610ae816f | |||
| fa56f8eadb | |||
| 7882c1c6ae | |||
| 84a6ef4d21 | |||
| 4d680c3fad | |||
| bab3069dff | |||
| 4cb8ac61c7 | |||
| 9d28a79219 | |||
| c4489eb3cb | |||
| 7caf91300f | |||
| 0c1b54f04c | |||
| 85e392f354 | |||
| c98e08fd87 | |||
| 33cc75e6fc | |||
| 474865242c | |||
| 0292e6a1a8 | |||
| de193422a3 | |||
| ff228fb524 | |||
| 8709539d4c | |||
| 2995b54afd | |||
| e26256fb70 | |||
| e45f9b66fa | |||
| 158f1aec86 | |||
| f53a7f62bb | |||
| d2b08a0465 | |||
| 43c4029c8a | |||
| 55ac985373 | |||
| 37b6ed3225 | |||
| c5bf9daef6 | |||
| be01cebfae | |||
| 7a81e6fe2d | |||
| 9c49eb131a | |||
| 374a302b90 | |||
| b3da88077f | |||
| 6454f51741 | |||
| e509ab5be6 | |||
| 592bf516e5 | |||
| 8cdafe46e3 | |||
| 45c5688d42 | |||
| 7bb2414bf6 | |||
| da11c1bcee | |||
| a80697938e | |||
| 1d9ad76f1f | |||
| 01387ba3c3 | |||
| f163c90555 | |||
| 4e94864e54 | |||
| 54c4041ebc | |||
| f780aba434 | |||
| 057f78de8b | |||
| 7a36128efc | |||
| d2cd8b9bb6 | |||
| 937942f5ad |
+14
-20
@@ -1,7 +1,7 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '0.10'
|
||||
- '4.2'
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -15,28 +15,26 @@ branches:
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- JOB=ci-checks
|
||||
- JOB=unit BROWSER_PROVIDER=saucelabs
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
|
||||
- JOB=unit BROWSER_PROVIDER=browserstack
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack
|
||||
global:
|
||||
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
- BROWSER_STACK_USERNAME=VojtaJina
|
||||
- BROWSER_STACK_ACCESS_KEY=QCQJ1ZpWXpBkSwEdD8ev
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: "JOB=unit BROWSER_PROVIDER=browserstack"
|
||||
- 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"
|
||||
# node 4 likes the G++ v4.8 compiler
|
||||
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
|
||||
install:
|
||||
# Check the size of caches
|
||||
@@ -46,16 +44,12 @@ install:
|
||||
- npm config set spin false
|
||||
# Log HTTP requests
|
||||
- npm config set loglevel http
|
||||
- npm install -g npm@2.5
|
||||
# Instal npm dependecies and ensure that npm cache is not stale
|
||||
#- npm install -g npm@2.5
|
||||
# Install npm dependencies and ensure that npm cache is not stale
|
||||
- npm install
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
- ./scripts/travis/start_browser_provider.sh
|
||||
- npm install -g grunt-cli
|
||||
- grunt package
|
||||
- ./scripts/travis/wait_for_browser_provider.sh
|
||||
- ./scripts/travis/before_build.sh
|
||||
|
||||
script:
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
+29
-2
@@ -313,8 +313,6 @@ the built-in pattern validator:
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.4.5"></a>
|
||||
# 1.4.5 permanent-internship (2015-08-28)
|
||||
|
||||
@@ -2588,7 +2586,36 @@ We also added a documentation page focused on security, which contains some of t
|
||||
[#9578](https://github.com/angular/angular.js/issues/9578), [#9751](https://github.com/angular/angular.js/issues/9751))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$observe:** Due to [531a8de7](https://github.com/angular/angular.js/commit/531a8de72c439d8ddd064874bf364c00cedabb11),
|
||||
observers no longer register on undefined attributes. For example, if you were using `$observe` on
|
||||
an absent optional attribute to set a default value, the following would not work anymore:
|
||||
|
||||
```html
|
||||
<my-dir></my-dir>
|
||||
```
|
||||
|
||||
```js
|
||||
// link function for directive myDir
|
||||
link: function(scope, element, attr) {
|
||||
attr.$observe('myAttr', function(newVal) {
|
||||
scope.myValue = newVal ? newVal : 'myDefaultValue';
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Instead, check if the attribute is set before registering the observer:
|
||||
|
||||
```js
|
||||
link: function(scope, element, attr) {
|
||||
if (attr.myAttr) {
|
||||
// register the observer
|
||||
} else {
|
||||
// set the default
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<a name="1.3.0"></a>
|
||||
# 1.3.0 superluminal-nudge (2014-10-13)
|
||||
|
||||
+7
-1
@@ -123,13 +123,19 @@ Before you submit your pull request consider the following guidelines:
|
||||
* If we suggest changes then:
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suite to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
* Commit your changes to your branch (e.g. `my-fix-branch`).
|
||||
* Push the changes to your GitHub repository (this will update your Pull Request).
|
||||
|
||||
If the PR gets too outdated we may ask you to rebase and force push to update the PR:
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push origin my-fix-branch -f
|
||||
```
|
||||
|
||||
*WARNING. Squashing or reverting commits and forced push thereafter may remove GitHub comments
|
||||
on code that were previously made by you and others in your commits.*
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
#### After your pull request is merged
|
||||
|
||||
+13
-11
@@ -162,7 +162,7 @@ module.exports = function(grunt) {
|
||||
'!src/angular.bind.js' // we ignore this file since contains an early return statement
|
||||
],
|
||||
options: {
|
||||
config: ".jscsrc"
|
||||
config: '.jscsrc'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -231,9 +231,9 @@ module.exports = function(grunt) {
|
||||
dest: 'build/angular-aria.js',
|
||||
src: util.wrap(files['angularModules']['ngAria'], 'module')
|
||||
},
|
||||
"promises-aplus-adapter": {
|
||||
'promises-aplus-adapter': {
|
||||
dest:'tmp/promises-aplus-adapter++.js',
|
||||
src:['src/ng/q.js','lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
src:['src/ng/q.js', 'lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
}
|
||||
},
|
||||
|
||||
@@ -253,7 +253,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
|
||||
"ddescribe-iit": {
|
||||
'ddescribe-iit': {
|
||||
files: [
|
||||
'src/**/*.js',
|
||||
'test/**/*.js',
|
||||
@@ -274,7 +274,7 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
"merge-conflict": {
|
||||
'merge-conflict': {
|
||||
files: [
|
||||
'src/**/*',
|
||||
'test/**/*',
|
||||
@@ -304,11 +304,11 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
shell: {
|
||||
"npm-install": {
|
||||
'npm-install': {
|
||||
command: 'node scripts/npm/check-node-modules.js'
|
||||
},
|
||||
|
||||
"promises-aplus-tests": {
|
||||
'promises-aplus-tests': {
|
||||
options: {
|
||||
stdout: false,
|
||||
stderr: true,
|
||||
@@ -339,8 +339,10 @@ module.exports = function(grunt) {
|
||||
grunt.task.run('shell:npm-install');
|
||||
}
|
||||
|
||||
|
||||
|
||||
//alias tasks
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package', 'test:unit', 'test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
|
||||
grunt.registerTask('test:jquery', 'Run the jQuery unit tests with Karma', ['tests:jquery']);
|
||||
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['build', 'tests:modules']);
|
||||
@@ -350,11 +352,11 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
|
||||
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
|
||||
grunt.registerTask('test:e2e', 'Alias for test:protractor', ['test:protractor']);
|
||||
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
|
||||
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter', 'shell:promises-aplus-tests']);
|
||||
|
||||
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
|
||||
grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
|
||||
grunt.registerTask('default', ['package']);
|
||||
};
|
||||
|
||||
Vendored
+3
-2
@@ -14,6 +14,7 @@ var angularFiles = {
|
||||
|
||||
'src/ng/anchorScroll.js',
|
||||
'src/ng/animate.js',
|
||||
'src/ng/animateRunner.js',
|
||||
'src/ng/animateCss.js',
|
||||
'src/ng/browser.js',
|
||||
'src/ng/cacheFactory.js',
|
||||
@@ -33,6 +34,7 @@ var angularFiles = {
|
||||
'src/ng/q.js',
|
||||
'src/ng/raf.js',
|
||||
'src/ng/rootScope.js',
|
||||
'src/ng/rootElement.js',
|
||||
'src/ng/sanitizeUri.js',
|
||||
'src/ng/sce.js',
|
||||
'src/ng/sniffer.js',
|
||||
@@ -84,7 +86,7 @@ var angularFiles = {
|
||||
],
|
||||
|
||||
'angularLoader': [
|
||||
'stringify.js',
|
||||
'src/stringify.js',
|
||||
'src/minErr.js',
|
||||
'src/loader.js'
|
||||
],
|
||||
@@ -99,7 +101,6 @@ var angularFiles = {
|
||||
'src/ngAnimate/animateJs.js',
|
||||
'src/ngAnimate/animateJsDriver.js',
|
||||
'src/ngAnimate/animateQueue.js',
|
||||
'src/ngAnimate/animateRunner.js',
|
||||
'src/ngAnimate/animation.js',
|
||||
'src/ngAnimate/module.js'
|
||||
],
|
||||
|
||||
@@ -124,7 +124,7 @@ h1,h2,h3,h4,h5,h6 {
|
||||
font-size:1.2em;
|
||||
padding:0;
|
||||
margin:0;
|
||||
border-bottom:1px soild #aaa;
|
||||
border-bottom:1px solid #aaa;
|
||||
margin-bottom:5px;
|
||||
}
|
||||
|
||||
@@ -589,6 +589,12 @@ ul.events > li {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.table > tbody > tr.head > td,
|
||||
.table > tbody > tr.head > th {
|
||||
border-bottom: 2px solid #ddd;
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 769px) and (max-width: 991px) {
|
||||
.main-body-grid {
|
||||
margin-top: 160px;
|
||||
|
||||
@@ -170,4 +170,8 @@ module.exports = new Package('angularjs', [
|
||||
jqueryDeployment,
|
||||
productionDeployment
|
||||
];
|
||||
})
|
||||
|
||||
.config(function(generateKeywordsProcessor) {
|
||||
generateKeywordsProcessor.docTypesToIgnore = ['componentGroup'];
|
||||
});
|
||||
|
||||
@@ -16,9 +16,11 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
ignoreWordsFile: undefined,
|
||||
areasToSearch: ['api', 'guide', 'misc', 'error', 'tutorial'],
|
||||
propertiesToIgnore: [],
|
||||
docTypesToIgnore: [],
|
||||
$validate: {
|
||||
ignoreWordsFile: { },
|
||||
areasToSearch: { presence: true },
|
||||
docTypesToIgnore: { },
|
||||
propertiesToIgnore: { }
|
||||
},
|
||||
$runAfter: ['memberDocsProcessor'],
|
||||
@@ -28,6 +30,7 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
// Keywords to ignore
|
||||
var wordsToIgnore = [];
|
||||
var propertiesToIgnore;
|
||||
var docTypesToIgnore;
|
||||
var areasToSearch;
|
||||
|
||||
// Keywords start with "ng:" or one of $, _ or a letter
|
||||
@@ -47,6 +50,8 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
areasToSearch = _.indexBy(this.areasToSearch);
|
||||
propertiesToIgnore = _.indexBy(this.propertiesToIgnore);
|
||||
log.debug('Properties to ignore', propertiesToIgnore);
|
||||
docTypesToIgnore = _.indexBy(this.docTypesToIgnore);
|
||||
log.debug('Doc types to ignore', docTypesToIgnore);
|
||||
|
||||
var ignoreWordsMap = _.indexBy(wordsToIgnore);
|
||||
|
||||
@@ -78,34 +83,36 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
|
||||
// We are only interested in docs that live in the right area
|
||||
docs = _.filter(docs, function(doc) { return areasToSearch[doc.area]; });
|
||||
docs = _.filter(docs, function(doc) { return !docTypesToIgnore[doc.docType]; });
|
||||
|
||||
_.forEach(docs, function(doc) {
|
||||
|
||||
var words = [];
|
||||
var keywordMap = _.clone(ignoreWordsMap);
|
||||
var members = [];
|
||||
var membersMap = {};
|
||||
|
||||
// Search each top level property of the document for search terms
|
||||
_.forEach(doc, function(value, key) {
|
||||
var words = [];
|
||||
var keywordMap = _.clone(ignoreWordsMap);
|
||||
var members = [];
|
||||
var membersMap = {};
|
||||
|
||||
if ( _.isString(value) && !propertiesToIgnore[key] ) {
|
||||
extractWords(value, words, keywordMap);
|
||||
}
|
||||
// Search each top level property of the document for search terms
|
||||
_.forEach(doc, function(value, key) {
|
||||
|
||||
if ( key === 'methods' || key === 'properties' || key === 'events' ) {
|
||||
_.forEach(value, function(member) {
|
||||
extractWords(member.name, members, membersMap);
|
||||
});
|
||||
}
|
||||
});
|
||||
if ( _.isString(value) && !propertiesToIgnore[key] ) {
|
||||
extractWords(value, words, keywordMap);
|
||||
}
|
||||
|
||||
if ( key === 'methods' || key === 'properties' || key === 'events' ) {
|
||||
_.forEach(value, function(member) {
|
||||
extractWords(member.name, members, membersMap);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
doc.searchTerms = {
|
||||
titleWords: extractTitleWords(doc.name),
|
||||
keywords: _.sortBy(words).join(' '),
|
||||
members: _.sortBy(members).join(' ')
|
||||
};
|
||||
doc.searchTerms = {
|
||||
titleWords: extractTitleWords(doc.name),
|
||||
keywords: _.sortBy(words).join(' '),
|
||||
members: _.sortBy(members).join(' ')
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{# Be aware that we need these extra new lines here or marked will not realise that the <div>
|
||||
{# Be aware that we need these extra new lines here or marked will not realize that the <div>
|
||||
is HTML and wrap each line in a <p> - thus breaking the HTML #}
|
||||
|
||||
<div>
|
||||
@@ -24,5 +24,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Be aware that we need these extra new lines here or marked will not realise that the <div>
|
||||
{# Be aware that we need these extra new lines here or marked will not realize that the <div>
|
||||
above is HTML and wrap each line in a <p> - thus breaking the HTML #}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@ngdoc error
|
||||
@name $location:nobase
|
||||
@fullName $location in HTML5 mode requires a <base> tag to be present!
|
||||
@fullName $location in HTML5 mode requires a `<base>` tag to be present!
|
||||
@description
|
||||
|
||||
If you configure {@link ng.$location `$location`} to use
|
||||
@@ -15,7 +15,7 @@ $locationProvider.html5Mode({
|
||||
});
|
||||
```
|
||||
|
||||
Note that removing the requirement for a <base> tag will have adverse side effects when resolving
|
||||
Note that removing the requirement for a `<base>` tag will have adverse side effects when resolving
|
||||
relative paths with `$location` in IE9.
|
||||
|
||||
The base URL is then used to resolve all relative URLs throughout the application regardless of the
|
||||
|
||||
@@ -100,7 +100,7 @@ To resolve this type of issue, either fix the api to be always synchronous or as
|
||||
your callback handler to always run asynchronously by using the `$timeout` service.
|
||||
|
||||
```
|
||||
function MyController($scope, thirdPartyComponent) {
|
||||
function MyController($scope, $timeout, thirdPartyComponent) {
|
||||
thirdPartyComponent.getData(function(someData) {
|
||||
$timeout(function() {
|
||||
$scope.someData = someData;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
@ngdoc error
|
||||
@name ngModel:nopromise
|
||||
@fullName No promise
|
||||
@description
|
||||
|
||||
The return value of an async validator, must always be a promise. If you want to return a
|
||||
non-promise value, you can convert it to a promise using {@link ng.$q#resolve `$q.resolve()`} or
|
||||
{@link ng.$q#reject `$q.reject()`}.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
.directive('asyncValidator', function($q) {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elem, attrs, ngModel) {
|
||||
ngModel.$asyncValidators.myAsyncValidation = function(modelValue, viewValue) {
|
||||
if (/* I don't need to hit the backend API */) {
|
||||
return $q.resolve(); // to mark as valid or
|
||||
// return $q.reject(); // to mark as invalid
|
||||
} else {
|
||||
// ...send a request to the backend and return a promise
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
})
|
||||
```
|
||||
@@ -771,8 +771,8 @@ then uses the information it obtains to compose hashbang URLs (such as
|
||||
</tr>
|
||||
|
||||
<tr class="head">
|
||||
<td>Navigation outside the app</td>
|
||||
<td>Use lower level API</td>
|
||||
<th>Navigation outside the app</td>
|
||||
<th>Use lower level API</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -786,8 +786,8 @@ then uses the information it obtains to compose hashbang URLs (such as
|
||||
</tr>
|
||||
|
||||
<tr class="head">
|
||||
<td>Read access</td>
|
||||
<td>Change to</td>
|
||||
<th>Read access</td>
|
||||
<th>Change to</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -76,7 +76,7 @@ stores/updates the value of the input field into/from a variable.
|
||||
The second kind of new markup are the double curly braces `{{ expression | filter }}`:
|
||||
When the compiler encounters this markup, it will replace it with the evaluated value of the markup.
|
||||
An <a name="expression">{@link expression expression}</a> in a template is a JavaScript-like code snippet that allows
|
||||
to read and write variables. Note that those variables are not global variables.
|
||||
Angular to read and write variables. Note that those variables are not global variables.
|
||||
Just like variables in a JavaScript function live in a scope,
|
||||
Angular provides a <a name="scope">{@link scope scope}</a> for the variables accessible to expressions.
|
||||
The values that are stored in variables on the scope are referred to as the <a name="model"></a>*model*
|
||||
|
||||
@@ -141,63 +141,6 @@ directives when possible.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
### Text and attribute bindings
|
||||
|
||||
During the compilation process the {@link ng.$compile compiler} matches text and attributes
|
||||
using the {@link ng.$interpolate $interpolate} service to see if they contain embedded
|
||||
expressions. These expressions are registered as {@link ng.$rootScope.Scope#$watch watches}
|
||||
and will update as part of normal {@link ng.$rootScope.Scope#$digest digest} cycle. An
|
||||
example of interpolation is shown below:
|
||||
|
||||
```html
|
||||
<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>
|
||||
```
|
||||
|
||||
|
||||
### `ngAttr` attribute bindings
|
||||
|
||||
Web browsers are sometimes picky about what values they consider valid for attributes.
|
||||
|
||||
For example, considering this template:
|
||||
|
||||
```html
|
||||
<svg>
|
||||
<circle cx="{{cx}}"></circle>
|
||||
</svg>
|
||||
```
|
||||
|
||||
We would expect Angular to be able to bind to this, but when we check the console we see
|
||||
something like `Error: Invalid value for attribute cx="{{cx}}"`. Because of the SVG DOM API's
|
||||
restrictions, you cannot simply write `cx="{{cx}}"`.
|
||||
|
||||
With `ng-attr-cx` you can work around this problem.
|
||||
|
||||
If an attribute with a binding is prefixed with the `ngAttr` prefix (denormalized as `ng-attr-`)
|
||||
then during the binding it will be applied to the corresponding unprefixed attribute. This allows
|
||||
you to bind to attributes that would otherwise be eagerly processed by browsers
|
||||
(e.g. an SVG element's `circle[cx]` attributes). When using `ngAttr`, the `allOrNothing` flag of
|
||||
{@link ng.$interpolate $interpolate} is used, so if any expression in the interpolated string
|
||||
results in `undefined`, the attribute is removed and not added to the element.
|
||||
|
||||
For example, we could fix the example above by instead writing:
|
||||
|
||||
```html
|
||||
<svg>
|
||||
<circle ng-attr-cx="{{cx}}"></circle>
|
||||
</svg>
|
||||
```
|
||||
|
||||
If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes), such as `viewBox` on the `svg` element, one can use underscores to denote that the attribute to bind to is naturally camelcased.
|
||||
|
||||
For example, to bind to `viewBox`, we can write:
|
||||
|
||||
```html
|
||||
<svg ng-attr-view_box="{{viewBox}}">
|
||||
</svg>
|
||||
```
|
||||
|
||||
|
||||
## Creating Directives
|
||||
|
||||
First let's talk about the {@link ng.$compileProvider#directive API for registering directives}. Much like
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
# Angular Expressions
|
||||
|
||||
Angular expressions are JavaScript-like code snippets that are usually placed in bindings such as
|
||||
`{{ expression }}`.
|
||||
Angular expressions are JavaScript-like code snippets that are mainly placed in
|
||||
interpolation bindings such as `<span title="{{ attrBinding }}">{{ textBinding }}</span>`,
|
||||
but also used directly in directive attributes such as `ng-click="functionExpression()"`.
|
||||
|
||||
For example, these are valid expressions in Angular:
|
||||
|
||||
@@ -35,7 +36,9 @@ Angular expressions are like JavaScript expressions with the following differenc
|
||||
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
|
||||
in an Angular expression.
|
||||
|
||||
* **No Comma And Void Operators:** You cannot use `,` or `void` in an Angular expression.
|
||||
* **No Object Creation With New Operator:** You cannot use `new` operator in an Angular expression.
|
||||
|
||||
* **No Comma And Void Operators:** You cannot use `,` or `void` operators in an Angular expression.
|
||||
|
||||
* **Filters:** You can use {@link guide/filter filters} within expressions to format data before
|
||||
displaying it.
|
||||
@@ -280,7 +283,7 @@ result is a non-undefined value (see value stabilization algorithm below).
|
||||
</example>
|
||||
|
||||
|
||||
### Why this feature
|
||||
### Reasons for using one-time binding
|
||||
|
||||
The main purpose of one-time binding expression is to provide a way to create a binding
|
||||
that gets deregistered and frees up resources once the binding is stabilized.
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
@ngdoc overview
|
||||
@name Interpolation
|
||||
@sortOrder 275
|
||||
@description
|
||||
|
||||
# Interpolation and data-binding
|
||||
|
||||
Interpolation markup with embedded @link {guide/expressions expressions} is used by Angular to
|
||||
provide data-binding to text nodes and attribute values.
|
||||
|
||||
An example of interpolation is shown below:
|
||||
|
||||
```html
|
||||
<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>
|
||||
```
|
||||
|
||||
### How text and attribute bindings work
|
||||
|
||||
During the compilation process the {@link ng.$compile compiler} uses the {@link ng.$interpolate $interpolate}
|
||||
service to see if text nodes and element attributes contain interpolation markup with embedded expressions.
|
||||
|
||||
If that is the case, the compiler adds an interpolateDirective to the node and
|
||||
registers {@link ng.$rootScope.Scope#$watch watches} on the computed interpolation function,
|
||||
which will update the corresponding text nodes or attribute values as part of the
|
||||
normal {@link ng.$rootScope.Scope#$digest digest} cycle.
|
||||
|
||||
Note that the interpolateDirective has a priority of 100 and sets up the watch in the preLink function.
|
||||
|
||||
### Binding to boolean attributes
|
||||
|
||||
Attributes such as `disabled` are called `boolean` attributes, because their presence means `true` and
|
||||
their absence means `false`. We cannot use normal attribute bindings with them, because the HTML
|
||||
specification does not require browsers to preserve the values of boolean attributes. This means that
|
||||
if we put an Angular interpolation expression into such an attribute then the binding information
|
||||
would be lost, because the browser ignores the attribute value.
|
||||
|
||||
In the following example, the interpolation information would be ignored and the browser would simply
|
||||
interpret the attribute as present, meaning that the button would always be disabled.
|
||||
|
||||
```html
|
||||
Disabled: <input type="checkbox" ng-model="isDisabled" />
|
||||
<button disabled="{{isDisabled}}">Disabled</button>
|
||||
```
|
||||
|
||||
For this reason, Angular provides special `ng`-prefixed directives for the following boolean attributes:
|
||||
{@link ngDisabled `disabled`}, [@link ngRequired `required`}, [@link ngSelected `selected`},
|
||||
{@link ngChecked `checked`}, {@link ngReadonly `readOnly`} , and [@link ngOpen `open`}.
|
||||
|
||||
These directives take an expression inside the attribute, and set the corresponding boolean attribute
|
||||
to true when the expression evaluates to truthy.
|
||||
|
||||
```html
|
||||
Disabled: <input type="checkbox" ng-model="isDisabled" />
|
||||
<button ng-disabled="isDisabled">Disabled</button>
|
||||
```
|
||||
|
||||
### `ngAttr` for binding to arbitrary attributes
|
||||
|
||||
Web browsers are sometimes picky about what values they consider valid for attributes.
|
||||
|
||||
For example, considering this template:
|
||||
|
||||
```html
|
||||
<svg>
|
||||
<circle cx="{{cx}}"></circle>
|
||||
</svg>
|
||||
```
|
||||
|
||||
We would expect Angular to be able to bind to this, but when we check the console we see
|
||||
something like `Error: Invalid value for attribute cx="{{cx}}"`. Because of the SVG DOM API's
|
||||
restrictions, you cannot simply write `cx="{{cx}}"`.
|
||||
|
||||
With `ng-attr-cx` you can work around this problem.
|
||||
|
||||
If an attribute with a binding is prefixed with the `ngAttr` prefix (denormalized as `ng-attr-`)
|
||||
then during the binding it will be applied to the corresponding unprefixed attribute. This allows
|
||||
you to bind to attributes that would otherwise be eagerly processed by browsers
|
||||
(e.g. an SVG element's `circle[cx]` attributes). When using `ngAttr`, the `allOrNothing` flag of
|
||||
{@link ng.$interpolate $interpolate} is used, so if any expression in the interpolated string
|
||||
results in `undefined`, the attribute is removed and not added to the element.
|
||||
|
||||
For example, we could fix the example above by instead writing:
|
||||
|
||||
```html
|
||||
<svg>
|
||||
<circle ng-attr-cx="{{cx}}"></circle>
|
||||
</svg>
|
||||
```
|
||||
|
||||
If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes),
|
||||
such as `viewBox` on the `svg` element, one can use underscores to denote that the attribute to bind
|
||||
to is naturally camelcased.
|
||||
|
||||
For example, to bind to `viewBox`, we can write:
|
||||
|
||||
```html
|
||||
<svg ng-attr-view_box="{{viewBox}}">
|
||||
</svg>
|
||||
```
|
||||
|
||||
The following attributes are also known to cause problems when used with normal bindings:
|
||||
|
||||
- **size** in `<select>` elements (see [Github issue 1619](https://github.com/angular/angular.js/issues/1619))
|
||||
- **placeholder** in `<textarea>` in Internet Explorer 10/11 (see [Github issue 5025](https://github.com/angular/angular.js/issues/5025))
|
||||
|
||||
|
||||
### Embedding interpolation markup inside expressions
|
||||
|
||||
Angular directives take either expressions or interpolation markup with embedded expressions. So the
|
||||
following example which embeds interpolation inside an expression is a bad practice:
|
||||
|
||||
```html
|
||||
<div ng-show="form{{$index}}.$invalid"></div>
|
||||
```
|
||||
|
||||
You should instead delegate the computation of complex expressions to the scope, like this:
|
||||
|
||||
```html
|
||||
<div ng-show="getForm($index).$invalid"></div>
|
||||
```
|
||||
|
||||
```js
|
||||
function getForm() {
|
||||
return $scope['form' + $index];
|
||||
}
|
||||
```
|
||||
|
||||
You can also access the `scope` with `this` in your templates:
|
||||
|
||||
```html
|
||||
<div ng-show="this['form' + $index].$invalid"></div>
|
||||
```
|
||||
|
||||
#### Why mixing interpolation and expressions is bad practice:
|
||||
|
||||
- It increases the complexity of the markup
|
||||
- There is no guarantee that it works for every directive, because interpolation itself is a directive.
|
||||
If another directive accesses attribute data before interpolation has run, it will get the raw
|
||||
interpolation markup and not data.
|
||||
- It impacts performance, as interpolation adds another watcher to the scope.
|
||||
- Since this is not recommended usage, we do not test for this, and changes to
|
||||
Angular core may break your code.
|
||||
@@ -584,6 +584,36 @@ After:
|
||||
};
|
||||
});
|
||||
|
||||
- due to [531a8de7](https://github.com/angular/angular.js/commit/531a8de72c439d8ddd064874bf364c00cedabb11),
|
||||
`$observe` no longer registers on undefined attributes. For example, if you were using `$observe` on
|
||||
an absent optional attribute to set a default value, the following would not work anymore:
|
||||
|
||||
```html
|
||||
<my-dir></my-dir>
|
||||
```
|
||||
|
||||
```js
|
||||
// Link function for directive myDir
|
||||
link: function(scope, element, attr) {
|
||||
attr.$observe('myAttr', function(newVal) {
|
||||
scope.myValue = newVal ? newVal : 'myDefaultValue';
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Instead, check if the attribute is set before registering the observer:
|
||||
|
||||
```js
|
||||
link: function(scope, element, attr) {
|
||||
if (attr.myAttr) {
|
||||
// register the observer
|
||||
} else {
|
||||
// set the default
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -656,8 +686,15 @@ $scope.resetWithCancel = function (e) {
|
||||
[#5864](https://github.com/angular/angular.js/issues/5864))
|
||||
|
||||
|
||||
- {@link input[checkbox] `input[checkbox]`} now supports constant expressions in `ngTrueValue` and
|
||||
`ngFalseValue`, making it now possible to e.g. use boolean and integer values. Previously, these attributes would
|
||||
always be treated as strings, whereas they are now parsed as expressions, and will throw if an expression
|
||||
is non-constant. To convert non-constant strings into constant expressions, simply wrap them in an
|
||||
extra pair of quotes, like so:
|
||||
|
||||
`<input type="checkbox" ng-model="..." ng-true-value="'truthyValue'">`
|
||||
|
||||
See [c90cefe1614](https://github.com/angular/angular.js/commit/c90cefe16142d973a123e945fc9058e8a874c357)
|
||||
|
||||
|
||||
## Scopes and Digests (`$scope`)
|
||||
|
||||
@@ -419,4 +419,4 @@ user enters text into the text field.
|
||||
which in turn updates the DOM.
|
||||
6. Angular exits the execution context, which in turn exits the `keydown` event and with it
|
||||
the JavaScript execution context.
|
||||
7. The browser re-renders the view with update text.
|
||||
7. The browser re-renders the view with the updated text.
|
||||
|
||||
@@ -359,7 +359,7 @@ element, to which it can then insert the transcluded content into its template.
|
||||
|
||||
Before compilation:
|
||||
```html
|
||||
<div translude-directive>
|
||||
<div transclude-directive>
|
||||
Some transcluded content
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -61,7 +61,7 @@ a few git commands.
|
||||
|
||||
### Install Git
|
||||
|
||||
You can download and install Git from http://git-scm.com/download. Once installed you should have
|
||||
You can download and install Git from http://git-scm.com/download. Once installed, you should have
|
||||
access to the `git` command line tool. The main commands that you will need to use are:
|
||||
|
||||
- `git clone ...` : clone a remote repository onto your local machine
|
||||
@@ -123,7 +123,7 @@ npm --version
|
||||
</a>.
|
||||
</div>
|
||||
|
||||
Once you have Node.js installed on your machine you can download the tool dependencies by running:
|
||||
Once you have Node.js installed on your machine, you can download the tool dependencies by running:
|
||||
|
||||
```
|
||||
npm install
|
||||
@@ -198,7 +198,7 @@ http://localhost:8000/app/index.html
|
||||
```
|
||||
|
||||
<div class="alert alert-info">
|
||||
To serve the web app on a different ip address or port, edit the "start" script within package.json.
|
||||
To serve the web app on a different IP address or port, edit the "start" script within package.json.
|
||||
You can use `-a` to set the address and `-p` to set the port.
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ the AngularJS phonecat app. You will also learn how to start the development ser
|
||||
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}.
|
||||
dependencies, as described in {@link index#get-started Get Started}.
|
||||
|
||||
In the `angular-phonecat` directory, run this command:
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ by the value of the expressions.
|
||||
We have added a new directive, called `ng-controller`, which attaches a `PhoneListCtrl`
|
||||
__controller__ to the <body> tag. At this point:
|
||||
|
||||
* The expressions in curly braces (`{{phone.name}}` and `{{phone.snippet}}` denote
|
||||
* The expressions in curly braces (`{{phone.name}}` and `{{phone.snippet}}`) denote
|
||||
bindings, which are referring to our application model, which is set up in our `PhoneListCtrl`
|
||||
controller.
|
||||
|
||||
@@ -132,6 +132,8 @@ The "Angular way" of separating controller from the view, makes it easy to test
|
||||
developed. If our controller is available on the global namespace then we could simply instantiate it
|
||||
with a mock `scope` object:
|
||||
|
||||
__`test/e2e/scenarios.js`:__
|
||||
|
||||
```js
|
||||
describe('PhoneListCtrl', function(){
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ phonecatApp.controller('PhoneListCtrl', function ($scope, $http) {
|
||||
`$http` makes an HTTP GET request to our web server, asking for `phones/phones.json` (the url is
|
||||
relative to our `index.html` file). The server responds by providing the data in the json file.
|
||||
(The response might just as well have been dynamically generated by a backend server. To the
|
||||
browser and our app they both look the same. For the sake of simplicity we used a json file in this
|
||||
browser and our app, they both look the same. For the sake of simplicity, we used a json file in this
|
||||
tutorial.)
|
||||
|
||||
The `$http` service returns a {@link ng.$q promise object} with a `success`
|
||||
@@ -114,7 +114,7 @@ as strings, which will not get minified. There are two ways to provide these inj
|
||||
|
||||
* Create a `$inject` property on the controller function which holds an array of strings.
|
||||
Each string in the array is the name of the service to inject for the corresponding parameter.
|
||||
In our example we would write:
|
||||
In our example, we would write:
|
||||
|
||||
```js
|
||||
function PhoneListCtrl($scope, $http) {...}
|
||||
|
||||
@@ -59,8 +59,8 @@ the element attribute.
|
||||
We also added phone images next to each record using an image tag with the {@link
|
||||
ng.directive:ngSrc ngSrc} directive. That directive prevents the
|
||||
browser from treating the Angular `{{ expression }}` markup literally, and initiating a request to
|
||||
invalid URL `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had only
|
||||
specified an attribute binding in a regular `src` attribute (`<img src="{{phone.imageUrl}}">`).
|
||||
an invalid URL `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had
|
||||
only specified an attribute binding in a regular `src` attribute (`<img src="{{phone.imageUrl}}">`).
|
||||
Using the `ngSrc` directive prevents the browser from making an http request to an invalid location.
|
||||
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ phone in the phone list.
|
||||
* When you click on a phone on the list, the phone details page with phone-specific information
|
||||
is displayed.
|
||||
|
||||
To implement the phone details view we used {@link ng.$http $http} to fetch our data, and we
|
||||
fleshed out the `phone-detail.html` view template.
|
||||
To implement the phone details view we are going to use {@link ng.$http $http} to fetch our data,
|
||||
and then flesh out the `phone-detail.html` view template.
|
||||
|
||||
<div doc-tutorial-reset="8"></div>
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ function newTestLocaleInfo() {
|
||||
DATETIME_FORMATS: {
|
||||
MONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
|
||||
'octobre', 'novembre', 'décembre'],
|
||||
STANDALONEMONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
|
||||
'octobre', 'novembre', 'décembre'],
|
||||
SHORTMONTH: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.',
|
||||
'nov.', 'déc.'],
|
||||
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
|
||||
@@ -180,6 +182,8 @@ describe("extractDateTimeSymbols", function() {
|
||||
DATETIME_FORMATS: {
|
||||
MONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
|
||||
'octobre', 'novembre', 'décembre'],
|
||||
STANDALONEMONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
|
||||
'août', 'septembre', 'octobre', 'novembre', 'décembre'],
|
||||
SHORTMONTH: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.',
|
||||
'nov.', 'déc.'],
|
||||
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
|
||||
|
||||
@@ -27,6 +27,7 @@ describe("convertNumberData", function() {
|
||||
describe("convertDatetimeData", function() {
|
||||
var convert = converter.convertDatetimeData,
|
||||
dataObj = { MONTHS: ['Enero', 'Pebrero'],
|
||||
STANDALONEMONTHS: ['Enero', 'Pebrero'],
|
||||
SHORTMONTHS: ['Ene', 'Peb'],
|
||||
WEEKDAYS: ['Linggo', 'Lunes'],
|
||||
SHORTWEEKDAYS: ['Lin', 'Lun'],
|
||||
@@ -37,6 +38,7 @@ describe("convertDatetimeData", function() {
|
||||
it('should convert empty datetime obj', function() {
|
||||
var processedData = convert(dataObj);
|
||||
expect(processedData.MONTH).toEqual(['Enero', 'Pebrero']);
|
||||
expect(processedData.STANDALONEMONTH).toEqual(['Enero', 'Pebrero']);
|
||||
expect(processedData.SHORTMONTH).toEqual(['Ene', 'Peb']);
|
||||
expect(processedData.DAY).toEqual(['Linggo', 'Lunes']);
|
||||
expect(processedData.SHORTDAY).toEqual(['Lin', 'Lun']);
|
||||
|
||||
@@ -39,6 +39,7 @@ function convertDatetimeData(dataObj) {
|
||||
|
||||
datetimeFormats.MONTH = dataObj.MONTHS;
|
||||
datetimeFormats.SHORTMONTH = dataObj.SHORTMONTHS;
|
||||
datetimeFormats.STANDALONEMONTH = dataObj.STANDALONEMONTHS;
|
||||
datetimeFormats.DAY = dataObj.WEEKDAYS;
|
||||
datetimeFormats.SHORTDAY = dataObj.SHORTWEEKDAYS;
|
||||
datetimeFormats.AMPMS = dataObj.AMPMS;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var glob = require("glob");
|
||||
var _ = require('lodash');
|
||||
var files = require('../../angularFiles').files;
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('validate-angular-files', function() {
|
||||
var combinedFiles = _.clone(files.angularModules);
|
||||
combinedFiles.ng = files.angularSrc;
|
||||
combinedFiles.angularLoader = files.angularLoader;
|
||||
|
||||
var errorsDetected = false;
|
||||
var directories = [];
|
||||
var detectedFiles = {};
|
||||
|
||||
for (var section in combinedFiles) {
|
||||
var sectionFiles = combinedFiles[section];
|
||||
|
||||
if (section != 'angularLoader') {
|
||||
directories.push('src/' + section);
|
||||
}
|
||||
|
||||
grunt.log.debug('Validating ' + sectionFiles.length + ' files from the "' + section + '" module.');
|
||||
|
||||
sectionFiles.forEach(function(file) {
|
||||
detectedFiles[file] = true;
|
||||
|
||||
if (!fs.existsSync(file)) {
|
||||
grunt.log.error(file + ' does not exist in the local file structure.');
|
||||
errorsDetected = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
directories.forEach(function(directory) {
|
||||
glob.sync(directory + '/**/*').forEach(function(filePath) {
|
||||
if (!fs.lstatSync(filePath).isDirectory()) {
|
||||
var fileName = path.basename(filePath);
|
||||
var isHiddenFile = fileName[0] == '.';
|
||||
if (!isHiddenFile && !detectedFiles[filePath]) {
|
||||
grunt.log.error(filePath + ' exists in the local file structure but isn\'t used by any module.');
|
||||
errorsDetected = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (errorsDetected) {
|
||||
throw new Error('Not all files were properly detected in the local file structure.');
|
||||
} else {
|
||||
grunt.log.ok('All files were detected successfully!');
|
||||
}
|
||||
});
|
||||
};
|
||||
+1407
-822
File diff suppressed because it is too large
Load Diff
Generated
+2514
-1591
File diff suppressed because it is too large
Load Diff
+10
-9
@@ -30,6 +30,7 @@
|
||||
"dgeni": "^0.4.0",
|
||||
"dgeni-packages": "^0.11.0",
|
||||
"event-stream": "~3.1.0",
|
||||
"glob": "^6.0.1",
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-bump": "~0.0.13",
|
||||
"grunt-contrib-clean": "~0.6.0",
|
||||
@@ -53,15 +54,15 @@
|
||||
"jasmine-node": "~1.14.5",
|
||||
"jasmine-reporters": "~1.0.1",
|
||||
"jshint-stylish": "~1.0.0",
|
||||
"karma": "0.12.32",
|
||||
"karma-browserstack-launcher": "0.1.2",
|
||||
"karma-chrome-launcher": "0.1.5",
|
||||
"karma-firefox-launcher": "0.1.3",
|
||||
"karma-jasmine": "0.1.5",
|
||||
"karma-junit-reporter": "0.2.2",
|
||||
"karma-ng-scenario": "0.1.0",
|
||||
"karma-sauce-launcher": "0.2.10",
|
||||
"karma-script-launcher": "0.1.0",
|
||||
"karma": "^0.13.19",
|
||||
"karma-browserstack-launcher": "^0.1.8",
|
||||
"karma-chrome-launcher": "^0.2.2",
|
||||
"karma-firefox-launcher": "^0.1.7",
|
||||
"karma-jasmine": "^0.1.6",
|
||||
"karma-junit-reporter": "^0.3.8",
|
||||
"karma-ng-scenario": "^0.1.0",
|
||||
"karma-sauce-launcher": "^0.3.0",
|
||||
"karma-script-launcher": "^0.1.0",
|
||||
"load-grunt-tasks": "~0.6.0",
|
||||
"lodash": "~2.4.1",
|
||||
"marked": "~0.3.0",
|
||||
|
||||
@@ -14,8 +14,9 @@ function init {
|
||||
TMP_DIR=$(resolveDir ../../tmp)
|
||||
BUILD_DIR=$(resolveDir ../../build)
|
||||
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
|
||||
PROJECT_DIR=$(resolveDir ../..)
|
||||
# get the npm dist-tag from a custom property (distTag) in package.json
|
||||
DIST_TAG=$(readJsonProp "package.json" "distTag")
|
||||
DIST_TAG=$(readJsonProp "$PROJECT_DIR/package.json" "distTag")
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ echo "#################################"
|
||||
# Enable tracing and exit on first failure
|
||||
set -xe
|
||||
|
||||
scripts/jenkins/set-node-version.sh
|
||||
|
||||
# This is the default set of browsers to use on the CI server unless overridden via env variable
|
||||
if [[ -z "$BROWSERS" ]]
|
||||
then
|
||||
@@ -19,6 +21,7 @@ rm -f angular.js.size
|
||||
|
||||
|
||||
# BUILD #
|
||||
npm install -g grunt-cli
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
|
||||
@@ -4,9 +4,7 @@ echo "#################################"
|
||||
echo "#### Update master ##############"
|
||||
echo "#################################"
|
||||
|
||||
ARG_DEFS=(
|
||||
"[--no-test=(true|false)]"
|
||||
)
|
||||
ARG_DEFS=()
|
||||
|
||||
function init {
|
||||
if [[ ! $VERBOSE ]]; then
|
||||
@@ -17,14 +15,7 @@ function init {
|
||||
|
||||
function build {
|
||||
cd ../..
|
||||
|
||||
if [[ $NO_TEST == "true" ]]; then
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
else
|
||||
./jenkins_build.sh
|
||||
fi
|
||||
|
||||
scripts/jenkins/build.sh
|
||||
cd $SCRIPT_DIR
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ function init {
|
||||
}
|
||||
|
||||
function build {
|
||||
./set-node-version.sh
|
||||
cd ../..
|
||||
|
||||
npm install -g grunt-cli
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install nvm for this shell
|
||||
source ~/.nvm/nvm.sh
|
||||
|
||||
# Use node.js at 4.2.x
|
||||
nvm install 4.2
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p $LOGS_DIR
|
||||
|
||||
if [ $JOB != "ci-checks" ]; then
|
||||
echo "start_browser_provider"
|
||||
./scripts/travis/start_browser_provider.sh
|
||||
fi
|
||||
|
||||
npm install -g grunt-cli
|
||||
|
||||
if [ $JOB != "ci-checks" ]; then
|
||||
grunt package
|
||||
echo "wait_for_browser_provider"
|
||||
./scripts/travis/wait_for_browser_provider.sh
|
||||
fi
|
||||
@@ -5,7 +5,9 @@ set -e
|
||||
export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev`
|
||||
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
if [ $JOB = "unit" ]; then
|
||||
if [ $JOB = "ci-checks" ]; then
|
||||
grunt ci-checks
|
||||
elif [ $JOB = "unit" ]; then
|
||||
if [ "$BROWSER_PROVIDER" == "browserstack" ]; then
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS"
|
||||
else
|
||||
@@ -14,7 +16,6 @@ if [ $JOB = "unit" ]; then
|
||||
|
||||
grunt test:promises-aplus
|
||||
grunt test:unit --browsers $BROWSERS --reporters dots
|
||||
grunt ci-checks
|
||||
grunt tests:docs --browsers $BROWSERS --reporters dots
|
||||
elif [ $JOB = "docs-e2e" ]; then
|
||||
grunt test:travis-protractor --specs "docs/app/e2e/**/*.scenario.js"
|
||||
@@ -31,5 +32,5 @@ elif [ $JOB = "e2e" ]; then
|
||||
export TARGET_SPECS="test/e2e/tests/**/*.js,$TARGET_SPECS"
|
||||
grunt test:travis-protractor --specs "$TARGET_SPECS"
|
||||
else
|
||||
echo "Unknown job type. Please set JOB=unit or JOB=e2e-*."
|
||||
echo "Unknown job type. Please set JOB=ci-checks, JOB=unit or JOB=e2e-*."
|
||||
fi
|
||||
|
||||
+2
-1
@@ -215,7 +215,8 @@ function isArrayLike(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');
|
||||
(length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,8 +56,10 @@
|
||||
$AnchorScrollProvider,
|
||||
$AnimateProvider,
|
||||
$CoreAnimateCssProvider,
|
||||
$$CoreAnimateJsProvider,
|
||||
$$CoreAnimateQueueProvider,
|
||||
$$CoreAnimateRunnerProvider,
|
||||
$$AnimateRunnerFactoryProvider,
|
||||
$$AnimateAsyncRunFactoryProvider,
|
||||
$BrowserProvider,
|
||||
$CacheFactoryProvider,
|
||||
$ControllerProvider,
|
||||
@@ -216,8 +218,10 @@ function publishExternalAPI(angular) {
|
||||
$anchorScroll: $AnchorScrollProvider,
|
||||
$animate: $AnimateProvider,
|
||||
$animateCss: $CoreAnimateCssProvider,
|
||||
$$animateJs: $$CoreAnimateJsProvider,
|
||||
$$animateQueue: $$CoreAnimateQueueProvider,
|
||||
$$AnimateRunner: $$CoreAnimateRunnerProvider,
|
||||
$$AnimateRunner: $$AnimateRunnerFactoryProvider,
|
||||
$$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
|
||||
$browser: $BrowserProvider,
|
||||
$cacheFactory: $CacheFactoryProvider,
|
||||
$controller: $ControllerProvider,
|
||||
|
||||
@@ -589,7 +589,7 @@ function annotate(fn, strictDi, name) {
|
||||
* @description
|
||||
*
|
||||
* Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
|
||||
* intercepts the creation of a service, allowing it to override or modify the behaviour of the
|
||||
* intercepts the creation of a service, allowing it to override or modify the behavior of the
|
||||
* service. The object returned by the decorator may be the original service, or a new service
|
||||
* object which replaces or wraps and delegates to the original service.
|
||||
*
|
||||
|
||||
+15
-8
@@ -33,16 +33,22 @@
|
||||
*
|
||||
* If jQuery is available, `angular.element` is an alias for the
|
||||
* [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
|
||||
* delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
|
||||
* delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**.
|
||||
*
|
||||
* <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
|
||||
* Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
|
||||
* commonly needed functionality with the goal of having a very small footprint.</div>
|
||||
* jqLite is a tiny, API-compatible subset of jQuery that allows
|
||||
* Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most
|
||||
* commonly needed functionality with the goal of having a very small footprint.
|
||||
*
|
||||
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
|
||||
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the
|
||||
* {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a
|
||||
* specific version of jQuery if multiple versions exist on the page.
|
||||
*
|
||||
* <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
|
||||
* jqLite; they are never raw DOM references.</div>
|
||||
* <div class="alert alert-info">**Note:** All element references in Angular are always wrapped with jQuery or
|
||||
* jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>
|
||||
*
|
||||
* <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements
|
||||
* by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`
|
||||
* or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>
|
||||
*
|
||||
* ## Angular's jqLite
|
||||
* jqLite provides only the following jQuery methods:
|
||||
@@ -55,7 +61,8 @@
|
||||
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
|
||||
* - [`clone()`](http://api.jquery.com/clone/)
|
||||
* - [`contents()`](http://api.jquery.com/contents/)
|
||||
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
|
||||
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.
|
||||
* As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing.
|
||||
* - [`data()`](http://api.jquery.com/data/)
|
||||
* - [`detach()`](http://api.jquery.com/detach/)
|
||||
* - [`empty()`](http://api.jquery.com/empty/)
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ function setupModuleLoader(window) {
|
||||
* unspecified then the module is being retrieved for further configuration.
|
||||
* @param {Function=} configFn Optional configuration function for the module. Same as
|
||||
* {@link angular.Module#config Module#config()}.
|
||||
* @returns {module} new module with the {@link angular.Module} api.
|
||||
* @returns {angular.Module} new module with the {@link angular.Module} api.
|
||||
*/
|
||||
return function module(name, requires, configFn) {
|
||||
var assertNotHasOwnProperty = function(name, context) {
|
||||
|
||||
+25
-26
@@ -53,27 +53,8 @@ function prepareAnimateOptions(options) {
|
||||
: {};
|
||||
}
|
||||
|
||||
var $$CoreAnimateRunnerProvider = function() {
|
||||
this.$get = ['$q', '$$rAF', function($q, $$rAF) {
|
||||
function AnimateRunner() {}
|
||||
AnimateRunner.all = noop;
|
||||
AnimateRunner.chain = noop;
|
||||
AnimateRunner.prototype = {
|
||||
end: noop,
|
||||
cancel: noop,
|
||||
resume: noop,
|
||||
pause: noop,
|
||||
complete: noop,
|
||||
then: function(pass, fail) {
|
||||
return $q(function(resolve) {
|
||||
$$rAF(function() {
|
||||
resolve();
|
||||
});
|
||||
}).then(pass, fail);
|
||||
}
|
||||
};
|
||||
return AnimateRunner;
|
||||
}];
|
||||
var $$CoreAnimateJsProvider = function() {
|
||||
this.$get = function() {};
|
||||
};
|
||||
|
||||
// this is prefixed with Core since it conflicts with
|
||||
@@ -101,7 +82,12 @@ var $$CoreAnimateQueueProvider = function() {
|
||||
addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
|
||||
}
|
||||
|
||||
return new $$AnimateRunner(); // jshint ignore:line
|
||||
var runner = new $$AnimateRunner(); // jshint ignore:line
|
||||
|
||||
// since there are no animations to run the runner needs to be
|
||||
// notified that the animation call is complete.
|
||||
runner.complete();
|
||||
return runner;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -566,10 +552,23 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* @kind function
|
||||
*
|
||||
* @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
|
||||
* If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take
|
||||
* on the provided styles. For example, if a transition animation is set for the given className then the provided from and
|
||||
* to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles
|
||||
* will be given in as function paramters into the `animate` method (or as apart of the `options` parameter).
|
||||
* If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take
|
||||
* on the provided styles. For example, if a transition animation is set for the given className, then the provided `from` and
|
||||
* `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding
|
||||
* style in `to`, the style in `from` is applied immediately, and no animation is run.
|
||||
* If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate`
|
||||
* method (or as part of the `options` parameter):
|
||||
*
|
||||
* ```js
|
||||
* ngModule.animation('.my-inline-animation', function() {
|
||||
* return {
|
||||
* animate : function(element, from, to, done, options) {
|
||||
* //animation
|
||||
* done();
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param {DOMElement} element the element which the CSS styles will be applied to
|
||||
* @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
|
||||
|
||||
+14
-32
@@ -12,37 +12,18 @@
|
||||
* Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
|
||||
*/
|
||||
var $CoreAnimateCssProvider = function() {
|
||||
this.$get = ['$$rAF', '$q', function($$rAF, $q) {
|
||||
this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {
|
||||
|
||||
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, initialOptions) {
|
||||
// all of the animation functions should create
|
||||
// a copy of the options data, however, if a
|
||||
// parent service has already created a copy then
|
||||
// we should stick to using that
|
||||
var options = initialOptions || {};
|
||||
if (!options.$$prepared) {
|
||||
options = copy(options);
|
||||
}
|
||||
};
|
||||
|
||||
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.
|
||||
@@ -55,7 +36,8 @@ var $CoreAnimateCssProvider = function() {
|
||||
options.from = null;
|
||||
}
|
||||
|
||||
var closed, runner = new RAFPromise();
|
||||
/* jshint newcap: false*/
|
||||
var closed, runner = new $$AnimateRunner();
|
||||
return {
|
||||
start: run,
|
||||
end: run
|
||||
@@ -63,16 +45,16 @@ var $CoreAnimateCssProvider = function() {
|
||||
|
||||
function run() {
|
||||
$$rAF(function() {
|
||||
close();
|
||||
applyAnimationContents();
|
||||
if (!closed) {
|
||||
runner.done();
|
||||
runner.complete();
|
||||
}
|
||||
closed = true;
|
||||
});
|
||||
return runner;
|
||||
}
|
||||
|
||||
function close() {
|
||||
function applyAnimationContents() {
|
||||
if (options.addClass) {
|
||||
element.addClass(options.addClass);
|
||||
options.addClass = null;
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
'use strict';
|
||||
|
||||
var $$AnimateAsyncRunFactoryProvider = function() {
|
||||
this.$get = ['$$rAF', function($$rAF) {
|
||||
var waitQueue = [];
|
||||
|
||||
function waitForTick(fn) {
|
||||
waitQueue.push(fn);
|
||||
if (waitQueue.length > 1) return;
|
||||
$$rAF(function() {
|
||||
for (var i = 0; i < waitQueue.length; i++) {
|
||||
waitQueue[i]();
|
||||
}
|
||||
waitQueue = [];
|
||||
});
|
||||
}
|
||||
|
||||
return function() {
|
||||
var passed = false;
|
||||
waitForTick(function() {
|
||||
passed = true;
|
||||
});
|
||||
return function(callback) {
|
||||
passed ? callback() : waitForTick(callback);
|
||||
};
|
||||
};
|
||||
}];
|
||||
};
|
||||
|
||||
var $$AnimateRunnerFactoryProvider = function() {
|
||||
this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
|
||||
function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {
|
||||
|
||||
var INITIAL_STATE = 0;
|
||||
var DONE_PENDING_STATE = 1;
|
||||
var DONE_COMPLETE_STATE = 2;
|
||||
|
||||
AnimateRunner.chain = function(chain, callback) {
|
||||
var index = 0;
|
||||
|
||||
next();
|
||||
function next() {
|
||||
if (index === chain.length) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
chain[index](function(response) {
|
||||
if (response === false) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
AnimateRunner.all = function(runners, callback) {
|
||||
var count = 0;
|
||||
var status = true;
|
||||
forEach(runners, function(runner) {
|
||||
runner.done(onProgress);
|
||||
});
|
||||
|
||||
function onProgress(response) {
|
||||
status = status && response;
|
||||
if (++count === runners.length) {
|
||||
callback(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function AnimateRunner(host) {
|
||||
this.setHost(host);
|
||||
|
||||
var rafTick = $$animateAsyncRun();
|
||||
var timeoutTick = function(fn) {
|
||||
$timeout(fn, 0, false);
|
||||
};
|
||||
|
||||
this._doneCallbacks = [];
|
||||
this._tick = function(fn) {
|
||||
var doc = $document[0];
|
||||
|
||||
// the document may not be ready or attached
|
||||
// to the module for some internal tests
|
||||
if (doc && doc.hidden) {
|
||||
timeoutTick(fn);
|
||||
} else {
|
||||
rafTick(fn);
|
||||
}
|
||||
};
|
||||
this._state = 0;
|
||||
}
|
||||
|
||||
AnimateRunner.prototype = {
|
||||
setHost: function(host) {
|
||||
this.host = host || {};
|
||||
},
|
||||
|
||||
done: function(fn) {
|
||||
if (this._state === DONE_COMPLETE_STATE) {
|
||||
fn();
|
||||
} else {
|
||||
this._doneCallbacks.push(fn);
|
||||
}
|
||||
},
|
||||
|
||||
progress: noop,
|
||||
|
||||
getPromise: function() {
|
||||
if (!this.promise) {
|
||||
var self = this;
|
||||
this.promise = $q(function(resolve, reject) {
|
||||
self.done(function(status) {
|
||||
status === false ? reject() : resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
return this.promise;
|
||||
},
|
||||
|
||||
then: function(resolveHandler, rejectHandler) {
|
||||
return this.getPromise().then(resolveHandler, rejectHandler);
|
||||
},
|
||||
|
||||
'catch': function(handler) {
|
||||
return this.getPromise()['catch'](handler);
|
||||
},
|
||||
|
||||
'finally': function(handler) {
|
||||
return this.getPromise()['finally'](handler);
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
if (this.host.pause) {
|
||||
this.host.pause();
|
||||
}
|
||||
},
|
||||
|
||||
resume: function() {
|
||||
if (this.host.resume) {
|
||||
this.host.resume();
|
||||
}
|
||||
},
|
||||
|
||||
end: function() {
|
||||
if (this.host.end) {
|
||||
this.host.end();
|
||||
}
|
||||
this._resolve(true);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
if (this.host.cancel) {
|
||||
this.host.cancel();
|
||||
}
|
||||
this._resolve(false);
|
||||
},
|
||||
|
||||
complete: function(response) {
|
||||
var self = this;
|
||||
if (self._state === INITIAL_STATE) {
|
||||
self._state = DONE_PENDING_STATE;
|
||||
self._tick(function() {
|
||||
self._resolve(response);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_resolve: function(response) {
|
||||
if (this._state !== DONE_COMPLETE_STATE) {
|
||||
forEach(this._doneCallbacks, function(fn) {
|
||||
fn(response);
|
||||
});
|
||||
this._doneCallbacks.length = 0;
|
||||
this._state = DONE_COMPLETE_STATE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return AnimateRunner;
|
||||
}];
|
||||
};
|
||||
+37
-16
@@ -212,10 +212,23 @@
|
||||
*
|
||||
*
|
||||
* #### `bindToController`
|
||||
* When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
|
||||
* This property is used to bind scope properties directly to the controller. It can be either
|
||||
* `true` or an object hash with the same format as the `scope` property. Additionally, a controller
|
||||
* alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller
|
||||
* definition: `controller: 'myCtrl as myAlias'`.
|
||||
*
|
||||
* When an isolate scope is used for a directive (see above), `bindToController: true` will
|
||||
* allow a component to have its properties bound to the controller, rather than to scope. When the controller
|
||||
* is instantiated, the initial values of the isolate scope bindings are already available.
|
||||
*
|
||||
* It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.
|
||||
* This will set up the scope bindings to the controller directly. Note that `scope` can still be used
|
||||
* to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate
|
||||
* scope (useful for component directives).
|
||||
*
|
||||
* If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`.
|
||||
*
|
||||
*
|
||||
* #### `controller`
|
||||
* Controller constructor function. The controller is instantiated before the
|
||||
* pre-linking phase and can be accessed by other directives (see
|
||||
@@ -551,19 +564,19 @@
|
||||
*
|
||||
* The `$parent` scope hierarchy will look like this:
|
||||
*
|
||||
* ```
|
||||
* - $rootScope
|
||||
* - isolate
|
||||
* - transclusion
|
||||
* ```
|
||||
```
|
||||
- $rootScope
|
||||
- isolate
|
||||
- transclusion
|
||||
```
|
||||
*
|
||||
* but the scopes will inherit prototypically from different scopes to their `$parent`.
|
||||
*
|
||||
* ```
|
||||
* - $rootScope
|
||||
* - transclusion
|
||||
* - isolate
|
||||
* ```
|
||||
```
|
||||
- $rootScope
|
||||
- transclusion
|
||||
- isolate
|
||||
```
|
||||
*
|
||||
*
|
||||
* ### Attributes
|
||||
@@ -695,8 +708,15 @@
|
||||
* directives; if given, it will be passed through to the link functions of
|
||||
* directives found in `element` during compilation.
|
||||
* * `transcludeControllers` - an object hash with keys that map controller names
|
||||
* to controller instances; if given, it will make the controllers
|
||||
* available to directives.
|
||||
* to a hash with the key `instance`, which maps to the controller instance;
|
||||
* if given, it will make the controllers available to directives on the compileNode:
|
||||
* ```
|
||||
* {
|
||||
* parent: {
|
||||
* instance: parentControllerInstance
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
|
||||
* the cloned elements; only needed for transcludes that are allowed to contain non html
|
||||
* elements (e.g. SVG elements). See also the directive.controller property.
|
||||
@@ -985,9 +1005,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
|
||||
this.$get = [
|
||||
'$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
|
||||
'$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
|
||||
'$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',
|
||||
function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
|
||||
$controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
|
||||
$controller, $rootScope, $sce, $animate, $$sanitizeUri) {
|
||||
|
||||
var Attributes = function(element, attributesToCopy) {
|
||||
if (attributesToCopy) {
|
||||
@@ -1199,7 +1219,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
* @param {string} key Normalized key. (ie ngAttribute) .
|
||||
* @param {function(interpolatedValue)} fn Function that will be called whenever
|
||||
the interpolated value of the attribute changes.
|
||||
* See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
|
||||
* See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation
|
||||
* guide} for more info.
|
||||
* @returns {function()} Returns a deregistration function for this observer.
|
||||
*/
|
||||
$observe: function(key, fn) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
var $controllerMinErr = minErr('$controller');
|
||||
|
||||
|
||||
var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
|
||||
var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/;
|
||||
function identifierForController(controller, ident) {
|
||||
if (ident && isString(ident)) return ident;
|
||||
if (isString(controller)) {
|
||||
|
||||
+20
-43
@@ -163,20 +163,7 @@
|
||||
* {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
|
||||
*
|
||||
* A special directive is necessary because we cannot use interpolation inside the `disabled`
|
||||
* attribute. The following example would make the button enabled on Chrome/Firefox
|
||||
* but not on older IEs:
|
||||
*
|
||||
* ```html
|
||||
* <!-- See below for an example of ng-disabled being used correctly -->
|
||||
* <div ng-init="isDisabled = false">
|
||||
* <button disabled="{{isDisabled}}">Disabled</button>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* This is because the HTML specification does not require browsers to preserve the values of
|
||||
* boolean attributes such as `disabled` (Their presence means true and their absence means false.)
|
||||
* If we put an Angular interpolation expression into such an attribute then the
|
||||
* binding information would be lost when the browser removes the attribute.
|
||||
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
@@ -211,15 +198,9 @@
|
||||
* Note that this directive should not be used together with {@link ngModel `ngModel`},
|
||||
* as this can lead to unexpected behavior.
|
||||
*
|
||||
* ### Why do we need `ngChecked`?
|
||||
* A special directive is necessary because we cannot use interpolation inside the `checked`
|
||||
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
||||
*
|
||||
* The HTML specification does not require browsers to preserve the values of boolean attributes
|
||||
* such as checked. (Their presence means true and their absence means false.)
|
||||
* If we put an Angular interpolation expression into such an attribute then the
|
||||
* binding information would be lost when the browser removes the attribute.
|
||||
* The `ngChecked` directive solves this problem for the `checked` attribute.
|
||||
* This complementary directive is not removed by the browser and so provides
|
||||
* a permanent reliable place to store the binding information.
|
||||
* @example
|
||||
<example>
|
||||
<file name="index.html">
|
||||
@@ -248,13 +229,12 @@
|
||||
* @priority 100
|
||||
*
|
||||
* @description
|
||||
* The HTML specification does not require browsers to preserve the values of boolean attributes
|
||||
* such as readonly. (Their presence means true and their absence means false.)
|
||||
* If we put an Angular interpolation expression into such an attribute then the
|
||||
* binding information would be lost when the browser removes the attribute.
|
||||
* The `ngReadonly` directive solves this problem for the `readonly` attribute.
|
||||
* This complementary directive is not removed by the browser and so provides
|
||||
* a permanent reliable place to store the binding information.
|
||||
*
|
||||
* Sets the `readOnly` attribute on the element, if the expression inside `ngReadonly` is truthy.
|
||||
*
|
||||
* A special directive is necessary because we cannot use interpolation inside the `readOnly`
|
||||
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<file name="index.html">
|
||||
@@ -283,13 +263,11 @@
|
||||
* @priority 100
|
||||
*
|
||||
* @description
|
||||
* The HTML specification does not require browsers to preserve the values of boolean attributes
|
||||
* such as selected. (Their presence means true and their absence means false.)
|
||||
* If we put an Angular interpolation expression into such an attribute then the
|
||||
* binding information would be lost when the browser removes the attribute.
|
||||
* The `ngSelected` directive solves this problem for the `selected` attribute.
|
||||
* This complementary directive is not removed by the browser and so provides
|
||||
* a permanent reliable place to store the binding information.
|
||||
*
|
||||
* Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.
|
||||
*
|
||||
* A special directive is necessary because we cannot use interpolation inside the `selected`
|
||||
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
@@ -321,13 +299,12 @@
|
||||
* @priority 100
|
||||
*
|
||||
* @description
|
||||
* The HTML specification does not require browsers to preserve the values of boolean attributes
|
||||
* such as open. (Their presence means true and their absence means false.)
|
||||
* If we put an Angular interpolation expression into such an attribute then the
|
||||
* binding information would be lost when the browser removes the attribute.
|
||||
* The `ngOpen` directive solves this problem for the `open` attribute.
|
||||
* This complementary directive is not removed by the browser and so provides
|
||||
* a permanent reliable place to store the binding information.
|
||||
*
|
||||
* Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.
|
||||
*
|
||||
* A special directive is necessary because we cannot use interpolation inside the `open`
|
||||
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
||||
*
|
||||
* @example
|
||||
<example>
|
||||
<file name="index.html">
|
||||
|
||||
@@ -337,13 +337,9 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
*
|
||||
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
|
||||
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
|
||||
* `<form>` but can be nested. This allows you to have nested forms, which is very useful when
|
||||
* using Angular validation directives in forms that are dynamically generated using the
|
||||
* {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
|
||||
* attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
|
||||
* `ngForm` directive and nest these in an outer `form` element.
|
||||
*
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
|
||||
* `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
|
||||
* of controls needs to be determined.
|
||||
*
|
||||
* # CSS classes
|
||||
* - `ng-valid` is set if the form is valid.
|
||||
|
||||
@@ -12,7 +12,18 @@
|
||||
// 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)/;
|
||||
// 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#!:.?+=&%@\-/]*)?$/;
|
||||
// Note: We are being more lenient, because browsers are too.
|
||||
// 1. Scheme
|
||||
// 2. Slashes
|
||||
// 3. Username
|
||||
// 4. Password
|
||||
// 5. Hostname
|
||||
// 6. Port
|
||||
// 7. Path
|
||||
// 8. Query
|
||||
// 9. Fragment
|
||||
// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999
|
||||
var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i;
|
||||
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
||||
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
|
||||
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||
|
||||
@@ -232,6 +232,8 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
|
||||
//set the 2nd param to true to ignore the template request error so that the inner
|
||||
//contents and scope can be cleaned up.
|
||||
$templateRequest(src, true).then(function(response) {
|
||||
if (scope.$$destroyed) return;
|
||||
|
||||
if (thisChangeId !== changeCounter) return;
|
||||
var newScope = scope.$new();
|
||||
ctrl.template = response;
|
||||
@@ -253,6 +255,8 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
|
||||
currentScope.$emit('$includeContentLoaded', src);
|
||||
scope.$eval(onloadExp);
|
||||
}, function() {
|
||||
if (scope.$$destroyed) return;
|
||||
|
||||
if (thisChangeId === changeCounter) {
|
||||
cleanupLastIncludeContent();
|
||||
scope.$emit('$includeContentError', src);
|
||||
|
||||
+52
-25
@@ -435,11 +435,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* which may be caused by a pending debounced event or because the input is waiting for a some
|
||||
* future event.
|
||||
*
|
||||
* If you have an input that uses `ng-model-options` to set up debounced events or events such
|
||||
* as blur you can have a situation where there is a period when the `$viewValue`
|
||||
* is out of synch with the ngModel's `$modelValue`.
|
||||
* If you have an input that uses `ng-model-options` to set up debounced updates or updates that
|
||||
* depend on special events such as blur, you can have a situation where there is a period when
|
||||
* the `$viewValue` is out of sync with the ngModel's `$modelValue`.
|
||||
*
|
||||
* In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
|
||||
* In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update
|
||||
* and reset the input to the last committed view value.
|
||||
*
|
||||
* It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue`
|
||||
* programmatically before these debounced/future events have resolved/occurred, because Angular's
|
||||
* dirty checking mechanism is not able to tell whether the model has actually changed or not.
|
||||
*
|
||||
@@ -452,39 +455,63 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
* angular.module('cancel-update-example', [])
|
||||
*
|
||||
* .controller('CancelUpdateController', ['$scope', function($scope) {
|
||||
* $scope.resetWithCancel = function(e) {
|
||||
* $scope.model = {};
|
||||
*
|
||||
* $scope.setEmpty = function(e, value, rollback) {
|
||||
* if (e.keyCode == 27) {
|
||||
* $scope.myForm.myInput1.$rollbackViewValue();
|
||||
* $scope.myValue = '';
|
||||
* }
|
||||
* };
|
||||
* $scope.resetWithoutCancel = function(e) {
|
||||
* if (e.keyCode == 27) {
|
||||
* $scope.myValue = '';
|
||||
* e.preventDefault();
|
||||
* if (rollback) {
|
||||
* $scope.myForm[value].$rollbackViewValue();
|
||||
* }
|
||||
* $scope.model[value] = '';
|
||||
* }
|
||||
* };
|
||||
* }]);
|
||||
* </file>
|
||||
* <file name="index.html">
|
||||
* <div ng-controller="CancelUpdateController">
|
||||
* <p>Try typing something in each input. See that the model only updates when you
|
||||
* blur off the input.
|
||||
* </p>
|
||||
* <p>Now see what happens if you start typing then press the Escape key</p>
|
||||
* <p>Both of these inputs are only updated if they are blurred. Hitting escape should
|
||||
* empty them. Follow these steps and observe the difference:</p>
|
||||
* <ol>
|
||||
* <li>Type something in the input. You will see that the model is not yet updated</li>
|
||||
* <li>Press the Escape key.
|
||||
* <ol>
|
||||
* <li> In the first example, nothing happens, because the model is already '', and no
|
||||
* update is detected. If you blur the input, the model will be set to the current view.
|
||||
* </li>
|
||||
* <li> In the second example, the pending update is cancelled, and the input is set back
|
||||
* to the last committed view value (''). Blurring the input does nothing.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
|
||||
* <p id="inputDescription1">With $rollbackViewValue()</p>
|
||||
* <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue"
|
||||
* ng-keydown="resetWithCancel($event)"><br/>
|
||||
* myValue: "{{ myValue }}"
|
||||
* <div>
|
||||
* <p id="inputDescription1">Without $rollbackViewValue():</p>
|
||||
* <input name="value1" aria-describedby="inputDescription1" ng-model="model.value1"
|
||||
* ng-keydown="setEmpty($event, 'value1')">
|
||||
* value1: "{{ model.value1 }}"
|
||||
* </div>
|
||||
*
|
||||
* <p id="inputDescription2">Without $rollbackViewValue()</p>
|
||||
* <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue"
|
||||
* ng-keydown="resetWithoutCancel($event)"><br/>
|
||||
* myValue: "{{ myValue }}"
|
||||
* <div>
|
||||
* <p id="inputDescription2">With $rollbackViewValue():</p>
|
||||
* <input name="value2" aria-describedby="inputDescription2" ng-model="model.value2"
|
||||
* ng-keydown="setEmpty($event, 'value2', true)">
|
||||
* value2: "{{ model.value2 }}"
|
||||
* </div>
|
||||
* </form>
|
||||
* </div>
|
||||
* </file>
|
||||
<file name="style.css">
|
||||
div {
|
||||
display: table-cell;
|
||||
}
|
||||
div:nth-child(1) {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
</file>
|
||||
* </example>
|
||||
*/
|
||||
this.$rollbackViewValue = function() {
|
||||
@@ -598,7 +625,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
forEach(ctrl.$asyncValidators, function(validator, name) {
|
||||
var promise = validator(modelValue, viewValue);
|
||||
if (!isPromiseLike(promise)) {
|
||||
throw ngModelMinErr("$asyncValidators",
|
||||
throw ngModelMinErr('nopromise',
|
||||
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
|
||||
}
|
||||
setValidity(name, undefined);
|
||||
|
||||
@@ -647,7 +647,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
(current === emptyOption_ ||
|
||||
current === unknownOption_ ||
|
||||
current.nodeType === NODE_TYPE_COMMENT ||
|
||||
current.value === '')) {
|
||||
(nodeName_(current) === 'option' && current.value === ''))) {
|
||||
current = current.nextSibling;
|
||||
}
|
||||
}
|
||||
@@ -737,7 +737,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
// Check to see if the value has changed due to the update to the options
|
||||
if (!ngModelCtrl.$isEmpty(previousValue)) {
|
||||
var nextValue = selectCtrl.readValue();
|
||||
if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
|
||||
var isNotPrimitive = ngOptions.trackBy || multiple;
|
||||
if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
|
||||
ngModelCtrl.$setViewValue(nextValue);
|
||||
ngModelCtrl.$render();
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ var SelectController =
|
||||
*
|
||||
* The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
|
||||
* between the scope and the `<select>` control (including setting default values).
|
||||
* Ìt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
|
||||
* It also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
|
||||
* {@link ngOptions `ngOptions`} directives.
|
||||
*
|
||||
* When an item in the `<select>` menu is selected, the value of the selected option will be bound
|
||||
@@ -356,7 +356,8 @@ var selectDirective = function() {
|
||||
controller: SelectController,
|
||||
priority: 1,
|
||||
link: {
|
||||
pre: selectPreLink
|
||||
pre: selectPreLink,
|
||||
post: selectPostLink
|
||||
}
|
||||
};
|
||||
|
||||
@@ -370,13 +371,6 @@ var selectDirective = function() {
|
||||
|
||||
selectCtrl.ngModelCtrl = ngModelCtrl;
|
||||
|
||||
// We delegate rendering to the `writeValue` method, which can be changed
|
||||
// if the select can have multiple selected values or if the options are being
|
||||
// generated by `ngOptions`
|
||||
ngModelCtrl.$render = function() {
|
||||
selectCtrl.writeValue(ngModelCtrl.$viewValue);
|
||||
};
|
||||
|
||||
// When the selected item(s) changes we delegate getting the value of the select control
|
||||
// to the `readValue` method, which can be changed if the select can have multiple
|
||||
// selected values or if the options are being generated by `ngOptions`
|
||||
@@ -430,6 +424,23 @@ var selectDirective = function() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function selectPostLink(scope, element, attrs, ctrls) {
|
||||
// if ngModel is not defined, we don't need to do anything
|
||||
var ngModelCtrl = ctrls[1];
|
||||
if (!ngModelCtrl) return;
|
||||
|
||||
var selectCtrl = ctrls[0];
|
||||
|
||||
// We delegate rendering to the `writeValue` method, which can be changed
|
||||
// if the select can have multiple selected values or if the options are being
|
||||
// generated by `ngOptions`.
|
||||
// This must be done in the postLink fn to prevent $render to be called before
|
||||
// all nodes have been linked correctly.
|
||||
ngModelCtrl.$render = function() {
|
||||
selectCtrl.writeValue(ngModelCtrl.$viewValue);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,62 @@
|
||||
'use strict';
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngRequired
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
||||
* It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be
|
||||
* applied to custom controls.
|
||||
*
|
||||
* The directive sets the `required` attribute on the element if the Angular expression inside
|
||||
* `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we
|
||||
* cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide}
|
||||
* for more info.
|
||||
*
|
||||
* The validator will set the `required` error key to true if the `required` attribute is set and
|
||||
* calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty` with the
|
||||
* {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the
|
||||
* `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing
|
||||
* custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based.
|
||||
*
|
||||
* @example
|
||||
* <example name="ngRequiredDirective" module="ngRequiredExample">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* angular.module('ngRequiredExample', [])
|
||||
* .controller('ExampleController', ['$scope', function($scope) {
|
||||
* $scope.required = true;
|
||||
* }]);
|
||||
* </script>
|
||||
* <div ng-controller="ExampleController">
|
||||
* <form name="form">
|
||||
* <label for="required">Toggle required: </label>
|
||||
* <input type="checkbox" ng-model="required" id="required" />
|
||||
* <br>
|
||||
* <label for="input">This input must be filled if `required` is true: </label>
|
||||
* <input type="text" ng-model="model" id="input" name="input" ng-required="required" /><br>
|
||||
* <hr>
|
||||
* required error set? = <code>{{form.input.$error.required}}</code><br>
|
||||
* model = <code>{{model}}</code>
|
||||
* </form>
|
||||
* </div>
|
||||
* </file>
|
||||
* <file name="protractor.js" type="protractor">
|
||||
var required = element(by.binding('form.input.$error.required'));
|
||||
var model = element(by.binding('model'));
|
||||
var input = element(by.id('input'));
|
||||
|
||||
it('should set the required error', function() {
|
||||
expect(required.getText()).toContain('true');
|
||||
|
||||
input.sendKeys('123');
|
||||
expect(required.getText()).not.toContain('true');
|
||||
expect(model.getText()).toContain('123');
|
||||
});
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
var requiredDirective = function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
@@ -19,7 +76,81 @@ var requiredDirective = function() {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngPattern
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
||||
* It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
|
||||
*
|
||||
* The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
|
||||
* does not match a RegExp which is obtained by evaluating the Angular expression given in the
|
||||
* `ngPattern` attribute value:
|
||||
* * If the expression evaluates to a RegExp object, then this is used directly.
|
||||
* * If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it
|
||||
* in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
|
||||
*
|
||||
* <div class="alert alert-info">
|
||||
* **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
|
||||
* start at the index of the last search's match, thus not taking the whole input value into
|
||||
* account.
|
||||
* </div>
|
||||
*
|
||||
* <div class="alert alert-info">
|
||||
* **Note:** This directive is also added when the plain `pattern` attribute is used, with two
|
||||
* differences:
|
||||
* <ol>
|
||||
* <li>
|
||||
* `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is
|
||||
* not available.
|
||||
* </li>
|
||||
* <li>
|
||||
* The `ngPattern` attribute must be an expression, while the `pattern` value must be
|
||||
* interpolated.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </div>
|
||||
*
|
||||
* @example
|
||||
* <example name="ngPatternDirective" module="ngPatternExample">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* angular.module('ngPatternExample', [])
|
||||
* .controller('ExampleController', ['$scope', function($scope) {
|
||||
* $scope.regex = '\\d+';
|
||||
* }]);
|
||||
* </script>
|
||||
* <div ng-controller="ExampleController">
|
||||
* <form name="form">
|
||||
* <label for="regex">Set a pattern (regex string): </label>
|
||||
* <input type="text" ng-model="regex" id="regex" />
|
||||
* <br>
|
||||
* <label for="input">This input is restricted by the current pattern: </label>
|
||||
* <input type="text" ng-model="model" id="input" name="input" ng-pattern="regex" /><br>
|
||||
* <hr>
|
||||
* input valid? = <code>{{form.input.$valid}}</code><br>
|
||||
* model = <code>{{model}}</code>
|
||||
* </form>
|
||||
* </div>
|
||||
* </file>
|
||||
* <file name="protractor.js" type="protractor">
|
||||
var model = element(by.binding('model'));
|
||||
var input = element(by.id('input'));
|
||||
|
||||
it('should validate the input with the default pattern', function() {
|
||||
input.sendKeys('aaa');
|
||||
expect(model.getText()).not.toContain('aaa');
|
||||
|
||||
input.clear().then(function() {
|
||||
input.sendKeys('123');
|
||||
expect(model.getText()).toContain('123');
|
||||
});
|
||||
});
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
var patternDirective = function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
@@ -51,7 +182,72 @@ var patternDirective = function() {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngMaxlength
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
||||
* It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
|
||||
*
|
||||
* The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
|
||||
* is longer than the integer obtained by evaluating the Angular expression given in the
|
||||
* `ngMaxlength` attribute value.
|
||||
*
|
||||
* <div class="alert alert-info">
|
||||
* **Note:** This directive is also added when the plain `maxlength` attribute is used, with two
|
||||
* differences:
|
||||
* <ol>
|
||||
* <li>
|
||||
* `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint
|
||||
* validation is not available.
|
||||
* </li>
|
||||
* <li>
|
||||
* The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be
|
||||
* interpolated.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </div>
|
||||
*
|
||||
* @example
|
||||
* <example name="ngMaxlengthDirective" module="ngMaxlengthExample">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* angular.module('ngMaxlengthExample', [])
|
||||
* .controller('ExampleController', ['$scope', function($scope) {
|
||||
* $scope.maxlength = 5;
|
||||
* }]);
|
||||
* </script>
|
||||
* <div ng-controller="ExampleController">
|
||||
* <form name="form">
|
||||
* <label for="maxlength">Set a maxlength: </label>
|
||||
* <input type="number" ng-model="maxlength" id="maxlength" />
|
||||
* <br>
|
||||
* <label for="input">This input is restricted by the current maxlength: </label>
|
||||
* <input type="text" ng-model="model" id="input" name="input" ng-maxlength="maxlength" /><br>
|
||||
* <hr>
|
||||
* input valid? = <code>{{form.input.$valid}}</code><br>
|
||||
* model = <code>{{model}}</code>
|
||||
* </form>
|
||||
* </div>
|
||||
* </file>
|
||||
* <file name="protractor.js" type="protractor">
|
||||
var model = element(by.binding('model'));
|
||||
var input = element(by.id('input'));
|
||||
|
||||
it('should validate the input with the default maxlength', function() {
|
||||
input.sendKeys('abcdef');
|
||||
expect(model.getText()).not.toContain('abcdef');
|
||||
|
||||
input.clear().then(function() {
|
||||
input.sendKeys('abcde');
|
||||
expect(model.getText()).toContain('abcde');
|
||||
});
|
||||
});
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
var maxlengthDirective = function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
@@ -72,6 +268,70 @@ var maxlengthDirective = function() {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngMinlength
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
||||
* It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
|
||||
*
|
||||
* The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
|
||||
* is shorter than the integer obtained by evaluating the Angular expression given in the
|
||||
* `ngMinlength` attribute value.
|
||||
*
|
||||
* <div class="alert alert-info">
|
||||
* **Note:** This directive is also added when the plain `minlength` attribute is used, with two
|
||||
* differences:
|
||||
* <ol>
|
||||
* <li>
|
||||
* `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint
|
||||
* validation is not available.
|
||||
* </li>
|
||||
* <li>
|
||||
* The `ngMinlength` value must be an expression, while the `minlength` value must be
|
||||
* interpolated.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </div>
|
||||
*
|
||||
* @example
|
||||
* <example name="ngMinlengthDirective" module="ngMinlengthExample">
|
||||
* <file name="index.html">
|
||||
* <script>
|
||||
* angular.module('ngMinlengthExample', [])
|
||||
* .controller('ExampleController', ['$scope', function($scope) {
|
||||
* $scope.minlength = 3;
|
||||
* }]);
|
||||
* </script>
|
||||
* <div ng-controller="ExampleController">
|
||||
* <form name="form">
|
||||
* <label for="minlength">Set a minlength: </label>
|
||||
* <input type="number" ng-model="minlength" id="minlength" />
|
||||
* <br>
|
||||
* <label for="input">This input is restricted by the current minlength: </label>
|
||||
* <input type="text" ng-model="model" id="input" name="input" ng-minlength="minlength" /><br>
|
||||
* <hr>
|
||||
* input valid? = <code>{{form.input.$valid}}</code><br>
|
||||
* model = <code>{{model}}</code>
|
||||
* </form>
|
||||
* </div>
|
||||
* </file>
|
||||
* <file name="protractor.js" type="protractor">
|
||||
var model = element(by.binding('model'));
|
||||
var input = element(by.id('input'));
|
||||
|
||||
it('should validate the input with the default minlength', function() {
|
||||
input.sendKeys('ab');
|
||||
expect(model.getText()).not.toContain('ab');
|
||||
|
||||
input.sendKeys('abc');
|
||||
expect(model.getText()).toContain('abc');
|
||||
});
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
var minlengthDirective = function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
|
||||
+183
-80
@@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var MAX_DIGITS = 22;
|
||||
var DECIMAL_SEP = '.';
|
||||
var ZERO_CHAR = '0';
|
||||
|
||||
/**
|
||||
* @ngdoc filter
|
||||
* @name currency
|
||||
@@ -89,7 +93,7 @@ function currencyFilter($locale) {
|
||||
* @param {(number|string)=} fractionSize Number of decimal places to round the number to.
|
||||
* If this is not provided then the fraction size is computed from the current locale's number
|
||||
* formatting pattern. In the case of the default locale, it will be 3.
|
||||
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
|
||||
* @returns {string} Number rounded to fractionSize and places a “,” after each third digit.
|
||||
*
|
||||
* @example
|
||||
<example module="numberFilterExample">
|
||||
@@ -124,8 +128,6 @@ function currencyFilter($locale) {
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
|
||||
|
||||
numberFilter.$inject = ['$locale'];
|
||||
function numberFilter($locale) {
|
||||
var formats = $locale.NUMBER_FORMATS;
|
||||
@@ -139,93 +141,194 @@ function numberFilter($locale) {
|
||||
};
|
||||
}
|
||||
|
||||
var DECIMAL_SEP = '.';
|
||||
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
||||
if (isObject(number)) return '';
|
||||
/**
|
||||
* Parse a number (as a string) into three components that can be used
|
||||
* for formatting the number.
|
||||
*
|
||||
* (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/)
|
||||
*
|
||||
* @param {string} numStr The number to parse
|
||||
* @return {object} An object describing this number, containing the following keys:
|
||||
* - d : an array of digits containing leading zeros as necessary
|
||||
* - i : the number of the digits in `d` that are to the left of the decimal point
|
||||
* - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`
|
||||
*
|
||||
*/
|
||||
function parse(numStr) {
|
||||
var exponent = 0, digits, numberOfIntegerDigits;
|
||||
var i, j, zeros;
|
||||
|
||||
var isNegative = number < 0;
|
||||
number = Math.abs(number);
|
||||
|
||||
var isInfinity = number === Infinity;
|
||||
if (!isInfinity && !isFinite(number)) return '';
|
||||
|
||||
var numStr = number + '',
|
||||
formatedText = '',
|
||||
hasExponent = false,
|
||||
parts = [];
|
||||
|
||||
if (isInfinity) formatedText = '\u221e';
|
||||
|
||||
if (!isInfinity && numStr.indexOf('e') !== -1) {
|
||||
var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
|
||||
if (match && match[2] == '-' && match[3] > fractionSize + 1) {
|
||||
number = 0;
|
||||
} else {
|
||||
formatedText = numStr;
|
||||
hasExponent = true;
|
||||
}
|
||||
// Decimal point?
|
||||
if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
|
||||
numStr = numStr.replace(DECIMAL_SEP, '');
|
||||
}
|
||||
|
||||
if (!isInfinity && !hasExponent) {
|
||||
var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
|
||||
// Exponential form?
|
||||
if ((i = numStr.search(/e/i)) > 0) {
|
||||
// Work out the exponent.
|
||||
if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
|
||||
numberOfIntegerDigits += +numStr.slice(i + 1);
|
||||
numStr = numStr.substring(0, i);
|
||||
} else if (numberOfIntegerDigits < 0) {
|
||||
// There was no decimal point or exponent so it is an integer.
|
||||
numberOfIntegerDigits = numStr.length;
|
||||
}
|
||||
|
||||
// determine fractionSize if it is not specified
|
||||
if (isUndefined(fractionSize)) {
|
||||
fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
|
||||
}
|
||||
// Count the number of leading zeros.
|
||||
for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++);
|
||||
|
||||
// safely round numbers in JS without hitting imprecisions of floating-point arithmetics
|
||||
// inspired by:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
|
||||
number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
|
||||
|
||||
var fraction = ('' + number).split(DECIMAL_SEP);
|
||||
var whole = fraction[0];
|
||||
fraction = fraction[1] || '';
|
||||
|
||||
var i, pos = 0,
|
||||
lgroup = pattern.lgSize,
|
||||
group = pattern.gSize;
|
||||
|
||||
if (whole.length >= (lgroup + group)) {
|
||||
pos = whole.length - lgroup;
|
||||
for (i = 0; i < pos; i++) {
|
||||
if ((pos - i) % group === 0 && i !== 0) {
|
||||
formatedText += groupSep;
|
||||
}
|
||||
formatedText += whole.charAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = pos; i < whole.length; i++) {
|
||||
if ((whole.length - i) % lgroup === 0 && i !== 0) {
|
||||
formatedText += groupSep;
|
||||
}
|
||||
formatedText += whole.charAt(i);
|
||||
}
|
||||
|
||||
// format fraction part.
|
||||
while (fraction.length < fractionSize) {
|
||||
fraction += '0';
|
||||
}
|
||||
|
||||
if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
|
||||
if (i == (zeros = numStr.length)) {
|
||||
// The digits are all zero.
|
||||
digits = [0];
|
||||
numberOfIntegerDigits = 1;
|
||||
} else {
|
||||
if (fractionSize > 0 && number < 1) {
|
||||
formatedText = number.toFixed(fractionSize);
|
||||
number = parseFloat(formatedText);
|
||||
formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
|
||||
// Count the number of trailing zeros
|
||||
zeros--;
|
||||
while (numStr.charAt(zeros) == ZERO_CHAR) zeros--;
|
||||
|
||||
// Trailing zeros are insignificant so ignore them
|
||||
numberOfIntegerDigits -= i;
|
||||
digits = [];
|
||||
// Convert string to array of digits without leading/trailing zeros.
|
||||
for (j = 0; i <= zeros; i++, j++) {
|
||||
digits[j] = +numStr.charAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (number === 0) {
|
||||
isNegative = false;
|
||||
// If the number overflows the maximum allowed digits then use an exponent.
|
||||
if (numberOfIntegerDigits > MAX_DIGITS) {
|
||||
digits = digits.splice(0, MAX_DIGITS - 1);
|
||||
exponent = numberOfIntegerDigits - 1;
|
||||
numberOfIntegerDigits = 1;
|
||||
}
|
||||
|
||||
parts.push(isNegative ? pattern.negPre : pattern.posPre,
|
||||
formatedText,
|
||||
isNegative ? pattern.negSuf : pattern.posSuf);
|
||||
return parts.join('');
|
||||
return { d: digits, e: exponent, i: numberOfIntegerDigits };
|
||||
}
|
||||
|
||||
/**
|
||||
* Round the parsed number to the specified number of decimal places
|
||||
* This function changed the parsedNumber in-place
|
||||
*/
|
||||
function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
|
||||
var digits = parsedNumber.d;
|
||||
var fractionLen = digits.length - parsedNumber.i;
|
||||
|
||||
// determine fractionSize if it is not specified; `+fractionSize` converts it to a number
|
||||
fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;
|
||||
|
||||
// The index of the digit to where rounding is to occur
|
||||
var roundAt = fractionSize + parsedNumber.i;
|
||||
var digit = digits[roundAt];
|
||||
|
||||
if (roundAt > 0) {
|
||||
digits.splice(roundAt);
|
||||
} else {
|
||||
// We rounded to zero so reset the parsedNumber
|
||||
parsedNumber.i = 1;
|
||||
digits.length = roundAt = fractionSize + 1;
|
||||
for (var i=0; i < roundAt; i++) digits[i] = 0;
|
||||
}
|
||||
|
||||
if (digit >= 5) digits[roundAt - 1]++;
|
||||
|
||||
// Pad out with zeros to get the required fraction length
|
||||
for (; fractionLen < fractionSize; fractionLen++) digits.push(0);
|
||||
|
||||
|
||||
// Do any carrying, e.g. a digit was rounded up to 10
|
||||
var carry = digits.reduceRight(function(carry, d, i, digits) {
|
||||
d = d + carry;
|
||||
digits[i] = d % 10;
|
||||
return Math.floor(d / 10);
|
||||
}, 0);
|
||||
if (carry) {
|
||||
digits.unshift(carry);
|
||||
parsedNumber.i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a number into a string
|
||||
* @param {number} number The number to format
|
||||
* @param {{
|
||||
* minFrac, // the minimum number of digits required in the fraction part of the number
|
||||
* maxFrac, // the maximum number of digits required in the fraction part of the number
|
||||
* gSize, // number of digits in each group of separated digits
|
||||
* lgSize, // number of digits in the last group of digits before the decimal separator
|
||||
* negPre, // the string to go in front of a negative number (e.g. `-` or `(`))
|
||||
* posPre, // the string to go in front of a positive number
|
||||
* negSuf, // the string to go after a negative number (e.g. `)`)
|
||||
* posSuf // the string to go after a positive number
|
||||
* }} pattern
|
||||
* @param {string} groupSep The string to separate groups of number (e.g. `,`)
|
||||
* @param {string} decimalSep The string to act as the decimal separator (e.g. `.`)
|
||||
* @param {[type]} fractionSize The size of the fractional part of the number
|
||||
* @return {string} The number formatted as a string
|
||||
*/
|
||||
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
||||
|
||||
if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';
|
||||
|
||||
var isInfinity = !isFinite(number);
|
||||
var isZero = false;
|
||||
var numStr = Math.abs(number) + '',
|
||||
formattedText = '',
|
||||
parsedNumber;
|
||||
|
||||
if (isInfinity) {
|
||||
formattedText = '\u221e';
|
||||
} else {
|
||||
parsedNumber = parse(numStr);
|
||||
|
||||
roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);
|
||||
|
||||
var digits = parsedNumber.d;
|
||||
var integerLen = parsedNumber.i;
|
||||
var exponent = parsedNumber.e;
|
||||
var decimals = [];
|
||||
isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);
|
||||
|
||||
// pad zeros for small numbers
|
||||
while (integerLen < 0) {
|
||||
digits.unshift(0);
|
||||
integerLen++;
|
||||
}
|
||||
|
||||
// extract decimals digits
|
||||
if (integerLen > 0) {
|
||||
decimals = digits.splice(integerLen);
|
||||
} else {
|
||||
decimals = digits;
|
||||
digits = [0];
|
||||
}
|
||||
|
||||
// format the integer digits with grouping separators
|
||||
var groups = [];
|
||||
if (digits.length > pattern.lgSize) {
|
||||
groups.unshift(digits.splice(-pattern.lgSize).join(''));
|
||||
}
|
||||
while (digits.length > pattern.gSize) {
|
||||
groups.unshift(digits.splice(-pattern.gSize).join(''));
|
||||
}
|
||||
if (digits.length) {
|
||||
groups.unshift(digits.join(''));
|
||||
}
|
||||
formattedText = groups.join(groupSep);
|
||||
|
||||
// append the decimal digits
|
||||
if (decimals.length) {
|
||||
formattedText += decimalSep + decimals.join('');
|
||||
}
|
||||
|
||||
if (exponent) {
|
||||
formattedText += 'e+' + exponent;
|
||||
}
|
||||
}
|
||||
if (number < 0 && !isZero) {
|
||||
return pattern.negPre + formattedText + pattern.negSuf;
|
||||
} else {
|
||||
return pattern.posPre + formattedText + pattern.posSuf;
|
||||
}
|
||||
}
|
||||
|
||||
function padNumber(num, digits, trim) {
|
||||
@@ -235,7 +338,7 @@ function padNumber(num, digits, trim) {
|
||||
num = -num;
|
||||
}
|
||||
num = '' + num;
|
||||
while (num.length < digits) num = '0' + num;
|
||||
while (num.length < digits) num = ZERO_CHAR + num;
|
||||
if (trim) {
|
||||
num = num.substr(num.length - digits);
|
||||
}
|
||||
|
||||
+87
-67
@@ -41,17 +41,6 @@
|
||||
* `reverse` is not set, which means it defaults to `false`.
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
angular.module('orderByExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.friends =
|
||||
[{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}];
|
||||
}]);
|
||||
</script>
|
||||
<div ng-controller="ExampleController">
|
||||
<table class="friend">
|
||||
<tr>
|
||||
@@ -67,6 +56,17 @@
|
||||
</table>
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
angular.module('orderByExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.friends =
|
||||
[{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}];
|
||||
}]);
|
||||
</file>
|
||||
</example>
|
||||
*
|
||||
* The predicate and reverse parameters can be controlled dynamically through scope properties,
|
||||
@@ -74,49 +74,24 @@
|
||||
* @example
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
angular.module('orderByExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.friends =
|
||||
[{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}];
|
||||
$scope.predicate = 'age';
|
||||
$scope.reverse = true;
|
||||
$scope.order = function(predicate) {
|
||||
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
||||
$scope.predicate = predicate;
|
||||
};
|
||||
}]);
|
||||
</script>
|
||||
<style type="text/css">
|
||||
.sortorder:after {
|
||||
content: '\25b2';
|
||||
}
|
||||
.sortorder.reverse:after {
|
||||
content: '\25bc';
|
||||
}
|
||||
</style>
|
||||
<div ng-controller="ExampleController">
|
||||
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
||||
<hr/>
|
||||
[ <a href="" ng-click="predicate=''">unsorted</a> ]
|
||||
<button ng-click="predicate=''">Set to unsorted</button>
|
||||
<table class="friend">
|
||||
<tr>
|
||||
<th>
|
||||
<a href="" ng-click="order('name')">Name</a>
|
||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<a href="" ng-click="order('phone')">Phone Number</a>
|
||||
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<a href="" ng-click="order('age')">Age</a>
|
||||
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<button ng-click="order('name')">Name</button>
|
||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<button ng-click="order('phone')">Phone Number</button>
|
||||
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<button ng-click="order('age')">Age</button>
|
||||
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
|
||||
<td>{{friend.name}}</td>
|
||||
@@ -126,6 +101,31 @@
|
||||
</table>
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
angular.module('orderByExample', [])
|
||||
.controller('ExampleController', ['$scope', function($scope) {
|
||||
$scope.friends =
|
||||
[{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}];
|
||||
$scope.predicate = 'age';
|
||||
$scope.reverse = true;
|
||||
$scope.order = function(predicate) {
|
||||
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
||||
$scope.predicate = predicate;
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
<file name="style.css">
|
||||
.sortorder:after {
|
||||
content: '\25b2';
|
||||
}
|
||||
.sortorder.reverse:after {
|
||||
content: '\25bc';
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
*
|
||||
* It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
|
||||
@@ -137,21 +137,30 @@
|
||||
* @example
|
||||
<example module="orderByExample">
|
||||
<file name="index.html">
|
||||
<div ng-controller="ExampleController">
|
||||
<table class="friend">
|
||||
<tr>
|
||||
<th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
|
||||
(<a href="" ng-click="order('-name',false)">^</a>)</th>
|
||||
<th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
|
||||
<th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
|
||||
</tr>
|
||||
<tr ng-repeat="friend in friends">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<td>{{friend.age}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div ng-controller="ExampleController">
|
||||
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
||||
<table class="friend">
|
||||
<tr>
|
||||
<th>
|
||||
<button ng-click="order('name')">Name</button>
|
||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<button ng-click="order('phone')">Phone Number</button>
|
||||
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<button ng-click="order('age')">Age</button>
|
||||
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr ng-repeat="friend in friends">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<td>{{friend.age}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
@@ -165,12 +174,23 @@
|
||||
{ name: 'Adam', phone: '555-5678', age: 35 },
|
||||
{ name: 'Julie', phone: '555-8765', age: 29 }
|
||||
];
|
||||
$scope.order = function(predicate, reverse) {
|
||||
$scope.friends = orderBy($scope.friends, predicate, reverse);
|
||||
$scope.order = function(predicate) {
|
||||
$scope.predicate = predicate;
|
||||
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
||||
$scope.friends = orderBy($scope.friends, predicate, $scope.reverse);
|
||||
};
|
||||
$scope.order('-age',false);
|
||||
$scope.order('age', true);
|
||||
}]);
|
||||
</file>
|
||||
|
||||
<file name="style.css">
|
||||
.sortorder:after {
|
||||
content: '\25b2';
|
||||
}
|
||||
.sortorder.reverse:after {
|
||||
content: '\25bc';
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
orderByFilter.$inject = ['$parse'];
|
||||
|
||||
@@ -918,6 +918,10 @@ function $HttpProvider() {
|
||||
throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
|
||||
}
|
||||
|
||||
if (!isString(requestConfig.url)) {
|
||||
throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url);
|
||||
}
|
||||
|
||||
var config = extend({
|
||||
method: 'get',
|
||||
transformRequest: defaults.transformRequest,
|
||||
|
||||
@@ -21,7 +21,7 @@ $interpolateMinErr.interr = function(text, err) {
|
||||
* Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
|
||||
*
|
||||
* @example
|
||||
<example module="customInterpolationApp">
|
||||
<example name="custom-interpolation-markup" module="customInterpolationApp">
|
||||
<file name="index.html">
|
||||
<script>
|
||||
var customInterpolationApp = angular.module('customInterpolationApp', []);
|
||||
@@ -36,7 +36,7 @@ $interpolateMinErr.interr = function(text, err) {
|
||||
this.label = "This binding is brought you by // interpolation symbols.";
|
||||
});
|
||||
</script>
|
||||
<div ng-app="App" ng-controller="DemoController as demo">
|
||||
<div ng-controller="DemoController as demo">
|
||||
//demo.label//
|
||||
</div>
|
||||
</file>
|
||||
|
||||
+2
-5
@@ -1069,7 +1069,7 @@ ASTCompiler.prototype = {
|
||||
right = this.nextId();
|
||||
left = {};
|
||||
if (!isAssignable(ast.left)) {
|
||||
throw $parseMinErr('lval', 'Trying to assing a value to a non l-value');
|
||||
throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
|
||||
}
|
||||
this.recurse(ast.left, undefined, left, function() {
|
||||
self.if_(self.notNull(left.context), function() {
|
||||
@@ -1660,9 +1660,6 @@ Parser.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
var getterFnCacheDefault = createMap();
|
||||
var getterFnCacheExpensive = createMap();
|
||||
|
||||
function isPossiblyDangerousMemberName(name) {
|
||||
return name == 'constructor';
|
||||
}
|
||||
@@ -1775,7 +1772,7 @@ function $ParseProvider() {
|
||||
return addInterceptor(exp, interceptorFn);
|
||||
|
||||
default:
|
||||
return noop;
|
||||
return addInterceptor(noop, interceptorFn);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@ function $TimeoutProvider() {
|
||||
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
||||
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
||||
* @param {...*=} Pass additional parameters to the executed function.
|
||||
* @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
|
||||
* promise will be resolved with is the return value of the `fn` function.
|
||||
* @returns {Promise} Promise that will be resolved when the timeout is reached. The promise
|
||||
* will be resolved with the return value of the `fn` function.
|
||||
*
|
||||
*/
|
||||
function timeout(fn, delay, invokeApply) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"angular": false,
|
||||
"noop": false,
|
||||
|
||||
"copy": false,
|
||||
"forEach": false,
|
||||
"extend": false,
|
||||
"jqLite": false,
|
||||
|
||||
+57
-34
@@ -352,9 +352,9 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
var gcsStaggerLookup = createLocalCacheLookup();
|
||||
|
||||
this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
|
||||
'$$forceReflow', '$sniffer', '$$rAFScheduler', '$animate',
|
||||
'$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
|
||||
function($window, $$jqLite, $$AnimateRunner, $timeout,
|
||||
$$forceReflow, $sniffer, $$rAFScheduler, $animate) {
|
||||
$$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
|
||||
|
||||
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
|
||||
|
||||
@@ -446,17 +446,24 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
return timings;
|
||||
}
|
||||
|
||||
return function init(element, options) {
|
||||
return function init(element, initialOptions) {
|
||||
// all of the animation functions should create
|
||||
// a copy of the options data, however, if a
|
||||
// parent service has already created a copy then
|
||||
// we should stick to using that
|
||||
var options = initialOptions || {};
|
||||
if (!options.$$prepared) {
|
||||
options = prepareAnimationOptions(copy(options));
|
||||
}
|
||||
|
||||
var restoreStyles = {};
|
||||
var node = getDomNode(element);
|
||||
if (!node
|
||||
|| !node.parentNode
|
||||
|| !$animate.enabled()) {
|
||||
|| !$$animateQueue.enabled()) {
|
||||
return closeAndReturnNoopAnimator();
|
||||
}
|
||||
|
||||
options = prepareAnimationOptions(options);
|
||||
|
||||
var temporaryStyles = [];
|
||||
var classes = element.attr('class');
|
||||
var styles = packageStyles(options);
|
||||
@@ -469,6 +476,8 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
var maxDelayTime;
|
||||
var maxDuration;
|
||||
var maxDurationTime;
|
||||
var startTime;
|
||||
var events = [];
|
||||
|
||||
if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) {
|
||||
return closeAndReturnNoopAnimator();
|
||||
@@ -622,7 +631,12 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
}
|
||||
|
||||
if (options.delay != null) {
|
||||
var delayStyle = parseFloat(options.delay);
|
||||
var delayStyle;
|
||||
if (typeof options.delay !== "boolean") {
|
||||
delayStyle = parseFloat(options.delay);
|
||||
// number in options.delay means we have to recalculate the delay for the closing timeout
|
||||
maxDelay = Math.max(delayStyle, 0);
|
||||
}
|
||||
|
||||
if (flags.applyTransitionDelay) {
|
||||
temporaryStyles.push(getCssDelayStyle(delayStyle));
|
||||
@@ -737,6 +751,11 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
options.onDone();
|
||||
}
|
||||
|
||||
if (events && events.length) {
|
||||
// Remove the transitionend / animationend listener(s)
|
||||
element.off(events.join(' '), onAnimationProgress);
|
||||
}
|
||||
|
||||
// if the preparation function fails then the promise is not setup
|
||||
if (runner) {
|
||||
runner.complete(!rejected);
|
||||
@@ -772,6 +791,33 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
};
|
||||
}
|
||||
|
||||
function onAnimationProgress(event) {
|
||||
event.stopPropagation();
|
||||
var ev = event.originalEvent || event;
|
||||
|
||||
// we now always use `Date.now()` due to the recent changes with
|
||||
// event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info)
|
||||
var timeStamp = ev.$manualTimeStamp || Date.now();
|
||||
|
||||
/* Firefox (or possibly just Gecko) likes to not round values up
|
||||
* when a ms measurement is used for the animation */
|
||||
var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
|
||||
|
||||
/* $manualTimeStamp is a mocked timeStamp value which is set
|
||||
* within browserTrigger(). This is only here so that tests can
|
||||
* mock animations properly. Real events fallback to event.timeStamp,
|
||||
* or, if they don't, then a timeStamp is automatically created for them.
|
||||
* We're checking to see if the timeStamp surpasses the expected delay,
|
||||
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
||||
* pre-condition since animationPauseds sometimes close off early */
|
||||
if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
|
||||
// we set this flag to ensure that if the transition is paused then, when resumed,
|
||||
// the animation will automatically close itself since transitions cannot be paused.
|
||||
animationCompleted = true;
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
if (animationClosed) return;
|
||||
if (!node.parentNode) {
|
||||
@@ -779,8 +825,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
return;
|
||||
}
|
||||
|
||||
var startTime, events = [];
|
||||
|
||||
// even though we only pause keyframe animations here the pause flag
|
||||
// will still happen when transitions are used. Only the transition will
|
||||
// not be paused since that is not possible. If the animation ends when
|
||||
@@ -921,7 +965,10 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
element.data(ANIMATE_TIMER_KEY, animationsData);
|
||||
}
|
||||
|
||||
element.on(events.join(' '), onAnimationProgress);
|
||||
if (events.length) {
|
||||
element.on(events.join(' '), onAnimationProgress);
|
||||
}
|
||||
|
||||
if (options.to) {
|
||||
if (options.cleanupStyles) {
|
||||
registerRestorableStyles(restoreStyles, node, Object.keys(options.to));
|
||||
@@ -943,30 +990,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
||||
element.removeData(ANIMATE_TIMER_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
function onAnimationProgress(event) {
|
||||
event.stopPropagation();
|
||||
var ev = event.originalEvent || event;
|
||||
var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
|
||||
|
||||
/* Firefox (or possibly just Gecko) likes to not round values up
|
||||
* when a ms measurement is used for the animation */
|
||||
var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
|
||||
|
||||
/* $manualTimeStamp is a mocked timeStamp value which is set
|
||||
* within browserTrigger(). This is only here so that tests can
|
||||
* mock animations properly. Real events fallback to event.timeStamp,
|
||||
* or, if they don't, then a timeStamp is automatically created for them.
|
||||
* We're checking to see if the timeStamp surpasses the expected delay,
|
||||
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
||||
* pre-condition since animations sometimes close off early */
|
||||
if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
|
||||
// we set this flag to ensure that if the transition is paused then, when resumed,
|
||||
// the animation will automatically close itself since transitions cannot be paused.
|
||||
animationCompleted = true;
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
@@ -11,6 +11,8 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
||||
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
|
||||
// $animateJs(element, 'enter');
|
||||
return function(element, event, classes, options) {
|
||||
var animationClosed = false;
|
||||
|
||||
// the `classes` argument is optional and if it is not used
|
||||
// then the classes will be resolved from the element's className
|
||||
// property as well as options.addClass/options.removeClass.
|
||||
@@ -63,8 +65,32 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
||||
applyAnimationClasses(element, options);
|
||||
}
|
||||
|
||||
function close() {
|
||||
animationClosed = true;
|
||||
applyOptions();
|
||||
applyAnimationStyles(element, options);
|
||||
}
|
||||
|
||||
var runner;
|
||||
|
||||
return {
|
||||
$$willAnimate: true,
|
||||
end: function() {
|
||||
if (runner) {
|
||||
runner.end();
|
||||
} else {
|
||||
close();
|
||||
runner = new $$AnimateRunner();
|
||||
runner.complete(true);
|
||||
}
|
||||
return runner;
|
||||
},
|
||||
start: function() {
|
||||
if (runner) {
|
||||
return runner;
|
||||
}
|
||||
|
||||
runner = new $$AnimateRunner();
|
||||
var closeActiveAnimations;
|
||||
var chain = [];
|
||||
|
||||
@@ -89,8 +115,7 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
||||
});
|
||||
}
|
||||
|
||||
var animationClosed = false;
|
||||
var runner = new $$AnimateRunner({
|
||||
runner.setHost({
|
||||
end: function() {
|
||||
endAnimations();
|
||||
},
|
||||
@@ -103,9 +128,7 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
||||
return runner;
|
||||
|
||||
function onComplete(success) {
|
||||
animationClosed = true;
|
||||
applyOptions();
|
||||
applyAnimationStyles(element, options);
|
||||
close(success);
|
||||
runner.complete(success);
|
||||
}
|
||||
|
||||
|
||||
+101
-37
@@ -5,6 +5,7 @@ var NG_ANIMATE_PIN_DATA = '$ngAnimatePin';
|
||||
var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
var PRE_DIGEST_STATE = 1;
|
||||
var RUNNING_STATE = 2;
|
||||
var ONE_SPACE = ' ';
|
||||
|
||||
var rules = this.rules = {
|
||||
skip: [],
|
||||
@@ -12,6 +13,29 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
join: []
|
||||
};
|
||||
|
||||
function makeTruthyCssClassMap(classString) {
|
||||
if (!classString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var keys = classString.split(ONE_SPACE);
|
||||
var map = Object.create(null);
|
||||
|
||||
forEach(keys, function(key) {
|
||||
map[key] = true;
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
function hasMatchingClasses(newClassString, currentClassString) {
|
||||
if (newClassString && currentClassString) {
|
||||
var currentClassMap = makeTruthyCssClassMap(currentClassString);
|
||||
return newClassString.split(ONE_SPACE).some(function(className) {
|
||||
return currentClassMap[className];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isAllowed(ruleType, element, currentAnimation, previousAnimation) {
|
||||
return rules[ruleType].some(function(fn) {
|
||||
return fn(element, currentAnimation, previousAnimation);
|
||||
@@ -59,11 +83,19 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
});
|
||||
|
||||
rules.cancel.push(function(element, newAnimation, currentAnimation) {
|
||||
var nO = newAnimation.options;
|
||||
var cO = currentAnimation.options;
|
||||
|
||||
// if the exact same CSS class is added/removed then it's safe to cancel it
|
||||
return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass);
|
||||
|
||||
var nA = newAnimation.options.addClass;
|
||||
var nR = newAnimation.options.removeClass;
|
||||
var cA = currentAnimation.options.addClass;
|
||||
var cR = currentAnimation.options.removeClass;
|
||||
|
||||
// early detection to save the global CPU shortage :)
|
||||
if ((isUndefined(nA) && isUndefined(nR)) || (isUndefined(cA) && isUndefined(cR))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (hasMatchingClasses(nA, cR)) || (hasMatchingClasses(nR, cA));
|
||||
});
|
||||
|
||||
this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
|
||||
@@ -139,6 +171,13 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
return mergeAnimationOptions(element, options, {});
|
||||
}
|
||||
|
||||
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
|
||||
var contains = Node.prototype.contains || function(arg) {
|
||||
// jshint bitwise: false
|
||||
return this === arg || !!(this.compareDocumentPosition(arg) & 16);
|
||||
// jshint bitwise: true
|
||||
};
|
||||
|
||||
function findCallbacks(parent, element, event) {
|
||||
var targetNode = getDomNode(element);
|
||||
var targetParentNode = getDomNode(parent);
|
||||
@@ -147,9 +186,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
var entries = callbackRegistry[event];
|
||||
if (entries) {
|
||||
forEach(entries, function(entry) {
|
||||
if (entry.node.contains(targetNode)) {
|
||||
if (contains.call(entry.node, targetNode)) {
|
||||
matches.push(entry.callback);
|
||||
} else if (event === 'leave' && entry.node.contains(targetParentNode)) {
|
||||
} else if (event === 'leave' && contains.call(entry.node, targetParentNode)) {
|
||||
matches.push(entry.callback);
|
||||
}
|
||||
});
|
||||
@@ -224,12 +263,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
bool = !recordExists;
|
||||
} else {
|
||||
// (element, bool) - Element setter
|
||||
bool = !!bool;
|
||||
if (!bool) {
|
||||
disabledElementsLookup.put(node, true);
|
||||
} else if (recordExists) {
|
||||
disabledElementsLookup.remove(node);
|
||||
}
|
||||
disabledElementsLookup.put(node, !bool);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,7 +272,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
}
|
||||
};
|
||||
|
||||
function queueAnimation(element, event, options) {
|
||||
function queueAnimation(element, event, initialOptions) {
|
||||
// we always make a copy of the options since
|
||||
// there should never be any side effects on
|
||||
// the input data when running `$animateCss`.
|
||||
var options = copy(initialOptions);
|
||||
|
||||
var node, parent;
|
||||
element = stripCommentsFromElement(element);
|
||||
if (element) {
|
||||
@@ -298,7 +337,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
// this is a hard disable of all animations for the application or on
|
||||
// the element itself, therefore there is no need to continue further
|
||||
// past this point if not enabled
|
||||
var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node);
|
||||
// Animations are also disabled if the document is currently hidden (page is not visible
|
||||
// to the user), because browsers slow down or do not flush calls to requestAnimationFrame
|
||||
var skipAnimations = !animationsEnabled || $document[0].hidden || disabledElementsLookup.get(node);
|
||||
var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
|
||||
var hasExistingAnimation = !!existingAnimation.state;
|
||||
|
||||
@@ -507,15 +548,15 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
forEach(children, function(child) {
|
||||
var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME));
|
||||
var animationDetails = activeAnimationsLookup.get(child);
|
||||
switch (state) {
|
||||
case RUNNING_STATE:
|
||||
animationDetails.runner.end();
|
||||
/* falls through */
|
||||
case PRE_DIGEST_STATE:
|
||||
if (animationDetails) {
|
||||
if (animationDetails) {
|
||||
switch (state) {
|
||||
case RUNNING_STATE:
|
||||
animationDetails.runner.end();
|
||||
/* falls through */
|
||||
case PRE_DIGEST_STATE:
|
||||
activeAnimationsLookup.remove(child);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -530,12 +571,20 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB);
|
||||
}
|
||||
|
||||
/**
|
||||
* This fn returns false if any of the following is true:
|
||||
* a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
|
||||
* b) a parent element has an ongoing structural animation, and animateChildren is false
|
||||
* c) the element is not a child of the body
|
||||
* d) the element is not a child of the $rootElement
|
||||
*/
|
||||
function areAnimationsAllowed(element, parentElement, event) {
|
||||
var bodyElement = jqLite($document[0].body);
|
||||
var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML';
|
||||
var rootElementDetected = isMatchingElement(element, $rootElement);
|
||||
var parentAnimationDetected = false;
|
||||
var animateChildren;
|
||||
var elementDisabled = disabledElementsLookup.get(getDomNode(element));
|
||||
|
||||
var parentHost = element.data(NG_ANIMATE_PIN_DATA);
|
||||
if (parentHost) {
|
||||
@@ -560,7 +609,18 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
// therefore we can't allow any animations to take place
|
||||
// but if a parent animation is class-based then that's ok
|
||||
if (!parentAnimationDetected) {
|
||||
parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode);
|
||||
var parentElementDisabled = disabledElementsLookup.get(parentNode);
|
||||
|
||||
if (parentElementDisabled === true && elementDisabled !== false) {
|
||||
// disable animations if the user hasn't explicitly enabled animations on the
|
||||
// current element
|
||||
elementDisabled = true;
|
||||
// element is disabled via parent element, no need to check anything else
|
||||
break;
|
||||
} else if (parentElementDisabled === false) {
|
||||
elementDisabled = false;
|
||||
}
|
||||
parentAnimationDetected = details.structural;
|
||||
}
|
||||
|
||||
if (isUndefined(animateChildren) || animateChildren === true) {
|
||||
@@ -573,28 +633,32 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
// there is no need to continue traversing at this point
|
||||
if (parentAnimationDetected && animateChildren === false) break;
|
||||
|
||||
if (!rootElementDetected) {
|
||||
// angular doesn't want to attempt to animate elements outside of the application
|
||||
// therefore we need to ensure that the rootElement is an ancestor of the current element
|
||||
rootElementDetected = isMatchingElement(parentElement, $rootElement);
|
||||
if (!rootElementDetected) {
|
||||
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
|
||||
if (parentHost) {
|
||||
parentElement = parentHost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bodyElementDetected) {
|
||||
// we also need to ensure that the element is or will be apart of the body element
|
||||
// we also need to ensure that the element is or will be a part of the body element
|
||||
// otherwise it is pointless to even issue an animation to be rendered
|
||||
bodyElementDetected = isMatchingElement(parentElement, bodyElement);
|
||||
}
|
||||
|
||||
if (bodyElementDetected && rootElementDetected) {
|
||||
// If both body and root have been found, any other checks are pointless,
|
||||
// as no animation data should live outside the application
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rootElementDetected) {
|
||||
// If no rootElement is detected, check if the parentElement is pinned to another element
|
||||
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
|
||||
if (parentHost) {
|
||||
// The pin target element becomes the next parent element
|
||||
parentElement = parentHost;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
parentElement = parentElement.parent();
|
||||
}
|
||||
|
||||
var allowAnimation = !parentAnimationDetected || animateChildren;
|
||||
var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true;
|
||||
return allowAnimation && rootElementDetected && bodyElementDetected;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var $$AnimateAsyncRunFactory = ['$$rAF', function($$rAF) {
|
||||
var waitQueue = [];
|
||||
|
||||
function waitForTick(fn) {
|
||||
waitQueue.push(fn);
|
||||
if (waitQueue.length > 1) return;
|
||||
$$rAF(function() {
|
||||
for (var i = 0; i < waitQueue.length; i++) {
|
||||
waitQueue[i]();
|
||||
}
|
||||
waitQueue = [];
|
||||
});
|
||||
}
|
||||
|
||||
return function() {
|
||||
var passed = false;
|
||||
waitForTick(function() {
|
||||
passed = true;
|
||||
});
|
||||
return function(callback) {
|
||||
passed ? callback() : waitForTick(callback);
|
||||
};
|
||||
};
|
||||
}];
|
||||
|
||||
var $$AnimateRunnerFactory = ['$q', '$sniffer', '$$animateAsyncRun',
|
||||
function($q, $sniffer, $$animateAsyncRun) {
|
||||
|
||||
var INITIAL_STATE = 0;
|
||||
var DONE_PENDING_STATE = 1;
|
||||
var DONE_COMPLETE_STATE = 2;
|
||||
|
||||
AnimateRunner.chain = function(chain, callback) {
|
||||
var index = 0;
|
||||
|
||||
next();
|
||||
function next() {
|
||||
if (index === chain.length) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
chain[index](function(response) {
|
||||
if (response === false) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
AnimateRunner.all = function(runners, callback) {
|
||||
var count = 0;
|
||||
var status = true;
|
||||
forEach(runners, function(runner) {
|
||||
runner.done(onProgress);
|
||||
});
|
||||
|
||||
function onProgress(response) {
|
||||
status = status && response;
|
||||
if (++count === runners.length) {
|
||||
callback(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function AnimateRunner(host) {
|
||||
this.setHost(host);
|
||||
|
||||
this._doneCallbacks = [];
|
||||
this._runInAnimationFrame = $$animateAsyncRun();
|
||||
this._state = 0;
|
||||
}
|
||||
|
||||
AnimateRunner.prototype = {
|
||||
setHost: function(host) {
|
||||
this.host = host || {};
|
||||
},
|
||||
|
||||
done: function(fn) {
|
||||
if (this._state === DONE_COMPLETE_STATE) {
|
||||
fn();
|
||||
} else {
|
||||
this._doneCallbacks.push(fn);
|
||||
}
|
||||
},
|
||||
|
||||
progress: noop,
|
||||
|
||||
getPromise: function() {
|
||||
if (!this.promise) {
|
||||
var self = this;
|
||||
this.promise = $q(function(resolve, reject) {
|
||||
self.done(function(status) {
|
||||
status === false ? reject() : resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
return this.promise;
|
||||
},
|
||||
|
||||
then: function(resolveHandler, rejectHandler) {
|
||||
return this.getPromise().then(resolveHandler, rejectHandler);
|
||||
},
|
||||
|
||||
'catch': function(handler) {
|
||||
return this.getPromise()['catch'](handler);
|
||||
},
|
||||
|
||||
'finally': function(handler) {
|
||||
return this.getPromise()['finally'](handler);
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
if (this.host.pause) {
|
||||
this.host.pause();
|
||||
}
|
||||
},
|
||||
|
||||
resume: function() {
|
||||
if (this.host.resume) {
|
||||
this.host.resume();
|
||||
}
|
||||
},
|
||||
|
||||
end: function() {
|
||||
if (this.host.end) {
|
||||
this.host.end();
|
||||
}
|
||||
this._resolve(true);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
if (this.host.cancel) {
|
||||
this.host.cancel();
|
||||
}
|
||||
this._resolve(false);
|
||||
},
|
||||
|
||||
complete: function(response) {
|
||||
var self = this;
|
||||
if (self._state === INITIAL_STATE) {
|
||||
self._state = DONE_PENDING_STATE;
|
||||
self._runInAnimationFrame(function() {
|
||||
self._resolve(response);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_resolve: function(response) {
|
||||
if (this._state !== DONE_COMPLETE_STATE) {
|
||||
forEach(this._doneCallbacks, function(fn) {
|
||||
fn(response);
|
||||
});
|
||||
this._doneCallbacks.length = 0;
|
||||
this._state = DONE_COMPLETE_STATE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return AnimateRunner;
|
||||
}];
|
||||
@@ -5,7 +5,6 @@
|
||||
$$AnimateAsyncRunFactory,
|
||||
$$rAFSchedulerFactory,
|
||||
$$AnimateChildrenDirective,
|
||||
$$AnimateRunnerFactory,
|
||||
$$AnimateQueueProvider,
|
||||
$$AnimationProvider,
|
||||
$AnimateCssProvider,
|
||||
@@ -741,9 +740,6 @@ angular.module('ngAnimate', [])
|
||||
.directive('ngAnimateChildren', $$AnimateChildrenDirective)
|
||||
.factory('$$rAFScheduler', $$rAFSchedulerFactory)
|
||||
|
||||
.factory('$$AnimateRunner', $$AnimateRunnerFactory)
|
||||
.factory('$$animateAsyncRun', $$AnimateAsyncRunFactory)
|
||||
|
||||
.provider('$$animateQueue', $$AnimateQueueProvider)
|
||||
.provider('$$animation', $$AnimationProvider)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
/* jshint ignore:start */
|
||||
var noop = angular.noop;
|
||||
var copy = angular.copy;
|
||||
var extend = angular.extend;
|
||||
var jqLite = angular.element;
|
||||
var forEach = angular.forEach;
|
||||
@@ -71,6 +72,7 @@ var isPromiseLike = function(p) {
|
||||
return p && p.then ? true : false;
|
||||
};
|
||||
|
||||
var ngMinErr = angular.$$minErr('ng');
|
||||
function assertArg(arg, name, reason) {
|
||||
if (!arg) {
|
||||
throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"Nov",
|
||||
"Des"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"Januarie",
|
||||
"Februarie",
|
||||
"Maart",
|
||||
"April",
|
||||
"Mei",
|
||||
"Junie",
|
||||
"Julie",
|
||||
"Augustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"Nov",
|
||||
"Des"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"Januarie",
|
||||
"Februarie",
|
||||
"Maart",
|
||||
"April",
|
||||
"Mei",
|
||||
"Junie",
|
||||
"Julie",
|
||||
"Augustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"Nov",
|
||||
"Des"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"Januarie",
|
||||
"Februarie",
|
||||
"Maart",
|
||||
"April",
|
||||
"Mei",
|
||||
"Junie",
|
||||
"Julie",
|
||||
"Augustus",
|
||||
"September",
|
||||
"Oktober",
|
||||
"November",
|
||||
"Desember"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
+14
@@ -80,6 +80,20 @@ $provide.value("$locale", {
|
||||
"kaa",
|
||||
"fwo"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300k\u0197\u0300z\u00f9\u0294",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300d\u0289\u0300gh\u00e0",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300t\u01ceaf\u0289\u0304gh\u0101",
|
||||
"ndz\u0254\u0300\u014b\u00e8s\u00e8e",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300nz\u00f9gh\u00f2",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300d\u00f9mlo",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300kw\u00eef\u0254\u0300e",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300f\u0289\u0300gh\u00e0dzugh\u00f9",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300gh\u01d4uwel\u0254\u0300m",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300chwa\u0294\u00e0kaa wo",
|
||||
"ndz\u0254\u0300\u014b\u00e8fw\u00f2o"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -80,6 +80,20 @@ $provide.value("$locale", {
|
||||
"kaa",
|
||||
"fwo"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300k\u0197\u0300z\u00f9\u0294",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300d\u0289\u0300gh\u00e0",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300t\u01ceaf\u0289\u0304gh\u0101",
|
||||
"ndz\u0254\u0300\u014b\u00e8s\u00e8e",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300nz\u00f9gh\u00f2",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300d\u00f9mlo",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300kw\u00eef\u0254\u0300e",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300f\u0289\u0300gh\u00e0dzugh\u00f9",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300gh\u01d4uwel\u0254\u0300m",
|
||||
"ndz\u0254\u0300\u014b\u0254\u0300chwa\u0294\u00e0kaa wo",
|
||||
"ndz\u0254\u0300\u014b\u00e8fw\u00f2o"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -80,6 +80,20 @@ $provide.value("$locale", {
|
||||
"\u0186-O",
|
||||
"M-\u0186"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"Sanda-\u0186p\u025bp\u0254n",
|
||||
"Kwakwar-\u0186gyefuo",
|
||||
"Eb\u0254w-\u0186benem",
|
||||
"Eb\u0254bira-Oforisuo",
|
||||
"Esusow Aketseaba-K\u0254t\u0254nimba",
|
||||
"Obirade-Ay\u025bwohomumu",
|
||||
"Ay\u025bwoho-Kitawonsa",
|
||||
"Difuu-\u0186sandaa",
|
||||
"Fankwa-\u0190b\u0254",
|
||||
"\u0186b\u025bs\u025b-Ahinime",
|
||||
"\u0186ber\u025bf\u025bw-Obubuo",
|
||||
"Mumu-\u0186p\u025bnimba"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -80,6 +80,20 @@ $provide.value("$locale", {
|
||||
"\u0186-O",
|
||||
"M-\u0186"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"Sanda-\u0186p\u025bp\u0254n",
|
||||
"Kwakwar-\u0186gyefuo",
|
||||
"Eb\u0254w-\u0186benem",
|
||||
"Eb\u0254bira-Oforisuo",
|
||||
"Esusow Aketseaba-K\u0254t\u0254nimba",
|
||||
"Obirade-Ay\u025bwohomumu",
|
||||
"Ay\u025bwoho-Kitawonsa",
|
||||
"Difuu-\u0186sandaa",
|
||||
"Fankwa-\u0190b\u0254",
|
||||
"\u0186b\u025bs\u025b-Ahinime",
|
||||
"\u0186ber\u025bf\u025bw-Obubuo",
|
||||
"Mumu-\u0186p\u025bnimba"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u1296\u126c\u121d",
|
||||
"\u12f2\u1234\u121d"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u1303\u1295\u12e9\u12c8\u122a",
|
||||
"\u134c\u1265\u1229\u12c8\u122a",
|
||||
"\u121b\u122d\u127d",
|
||||
"\u12a4\u1355\u122a\u120d",
|
||||
"\u121c\u12ed",
|
||||
"\u1301\u1295",
|
||||
"\u1301\u120b\u12ed",
|
||||
"\u12a6\u1308\u1235\u1275",
|
||||
"\u1234\u1355\u1274\u121d\u1260\u122d",
|
||||
"\u12a6\u12ad\u1276\u1260\u122d",
|
||||
"\u1296\u126c\u121d\u1260\u122d",
|
||||
"\u12f2\u1234\u121d\u1260\u122d"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u1296\u126c\u121d",
|
||||
"\u12f2\u1234\u121d"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u1303\u1295\u12e9\u12c8\u122a",
|
||||
"\u134c\u1265\u1229\u12c8\u122a",
|
||||
"\u121b\u122d\u127d",
|
||||
"\u12a4\u1355\u122a\u120d",
|
||||
"\u121c\u12ed",
|
||||
"\u1301\u1295",
|
||||
"\u1301\u120b\u12ed",
|
||||
"\u12a6\u1308\u1235\u1275",
|
||||
"\u1234\u1355\u1274\u121d\u1260\u122d",
|
||||
"\u12a6\u12ad\u1276\u1260\u122d",
|
||||
"\u1296\u126c\u121d\u1260\u122d",
|
||||
"\u12f2\u1234\u121d\u1260\u122d"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u062c\u0627\u0646\u0641\u064a",
|
||||
"\u0641\u064a\u0641\u0631\u064a",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0641\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a",
|
||||
"\u062c\u0648\u0627\u0646",
|
||||
"\u062c\u0648\u064a\u0644\u064a\u0629",
|
||||
"\u0623\u0648\u062a",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0634\u0628\u0627\u0637",
|
||||
"\u0622\u0630\u0627\u0631",
|
||||
"\u0646\u064a\u0633\u0627\u0646",
|
||||
"\u0623\u064a\u0627\u0631",
|
||||
"\u062d\u0632\u064a\u0631\u0627\u0646",
|
||||
"\u062a\u0645\u0648\u0632",
|
||||
"\u0622\u0628",
|
||||
"\u0623\u064a\u0644\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0634\u0628\u0627\u0637",
|
||||
"\u0622\u0630\u0627\u0631",
|
||||
"\u0646\u064a\u0633\u0627\u0646",
|
||||
"\u0623\u064a\u0627\u0631",
|
||||
"\u062d\u0632\u064a\u0631\u0627\u0646",
|
||||
"\u062a\u0645\u0648\u0632",
|
||||
"\u0622\u0628",
|
||||
"\u0623\u064a\u0644\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0634\u0628\u0627\u0637",
|
||||
"\u0622\u0630\u0627\u0631",
|
||||
"\u0646\u064a\u0633\u0627\u0646",
|
||||
"\u0623\u064a\u0627\u0631",
|
||||
"\u062d\u0632\u064a\u0631\u0627\u0646",
|
||||
"\u062a\u0645\u0648\u0632",
|
||||
"\u0622\u0628",
|
||||
"\u0623\u064a\u0644\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0646\u0628\u0631",
|
||||
"\u062f\u062c\u0646\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648\u0632",
|
||||
"\u063a\u0634\u062a",
|
||||
"\u0634\u062a\u0646\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0646\u0628\u0631",
|
||||
"\u062f\u062c\u0646\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u062c\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0625\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0634\u062a",
|
||||
"\u0634\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u062c\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0634\u0628\u0627\u0637",
|
||||
"\u0622\u0630\u0627\u0631",
|
||||
"\u0646\u064a\u0633\u0627\u0646",
|
||||
"\u0623\u064a\u0627\u0631",
|
||||
"\u062d\u0632\u064a\u0631\u0627\u0646",
|
||||
"\u062a\u0645\u0648\u0632",
|
||||
"\u0622\u0628",
|
||||
"\u0623\u064a\u0644\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
|
||||
"\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
|
||||
"\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
5,
|
||||
6
|
||||
|
||||
Vendored
+14
@@ -62,6 +62,20 @@ $provide.value("$locale", {
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"STANDALONEMONTH": [
|
||||
"\u064a\u0646\u0627\u064a\u0631",
|
||||
"\u0641\u0628\u0631\u0627\u064a\u0631",
|
||||
"\u0645\u0627\u0631\u0633",
|
||||
"\u0623\u0628\u0631\u064a\u0644",
|
||||
"\u0645\u0627\u064a\u0648",
|
||||
"\u064a\u0648\u0646\u064a\u0648",
|
||||
"\u064a\u0648\u0644\u064a\u0648",
|
||||
"\u0623\u063a\u0633\u0637\u0633",
|
||||
"\u0633\u0628\u062a\u0645\u0628\u0631",
|
||||
"\u0623\u0643\u062a\u0648\u0628\u0631",
|
||||
"\u0646\u0648\u0641\u0645\u0628\u0631",
|
||||
"\u062f\u064a\u0633\u0645\u0628\u0631"
|
||||
],
|
||||
"WEEKENDRANGE": [
|
||||
4,
|
||||
5
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user