Compare commits
166 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 874392464b | |||
| 7e7244402d | |||
| 4b94b9e34f | |||
| a2e7f54320 | |||
| 9b2e11b6fa | |||
| 2114a50c9a | |||
| 38f92c3a27 | |||
| 7dbf1ef2d1 | |||
| e13aae1ed0 | |||
| 36eacb172a | |||
| f2683f956f | |||
| 1a670aa466 | |||
| 578425303f | |||
| 528cf09e3f | |||
| c849098fbf | |||
| 145d397988 | |||
| 26d4d0dc22 | |||
| 64a9faaf8e | |||
| b7aba16839 | |||
| a72e1c4767 | |||
| 6545212d24 | |||
| 3fabbdb804 | |||
| ce8be9c47f | |||
| b3878a36d9 | |||
| ebd84e8008 | |||
| e721169738 | |||
| cdfbe25c00 | |||
| 0d4b15a4c9 | |||
| 0dd061c239 | |||
| 7288be25a7 | |||
| 2b279dd8a1 | |||
| 63b9956faf | |||
| 92767c098f | |||
| 2fe9b1dd9e | |||
| b9ad91cf1e | |||
| 40752a520a | |||
| 21369943fa | |||
| 190ea883c5 | |||
| 3a093123ef | |||
| b8e8f9af78 | |||
| 01161a0e9f | |||
| 75abbd525f | |||
| 01a725a769 | |||
| f5781dbb60 | |||
| 59205d7809 | |||
| 0cf170df16 | |||
| 05a3b088fd | |||
| 65df5da07a | |||
| 0689c3697f | |||
| 0f53c29954 | |||
| 11bfe85598 | |||
| 93c503fa16 | |||
| 9d4e948e82 | |||
| 26f19d0399 | |||
| 5cd2e2291b | |||
| 69bbbe675e | |||
| 825de1cdf2 | |||
| e5318c61ee | |||
| 67b40a19fb | |||
| 5fbac749c9 | |||
| 0daadeb3d3 | |||
| 6b7625a095 | |||
| ab7e0cd100 | |||
| dee5f7fea5 | |||
| 140d149cee | |||
| 4d65ddddf8 | |||
| abfce5327c | |||
| 944c150e6c | |||
| d8dc53d215 | |||
| 0ec206f5a6 | |||
| ce49d4d61b | |||
| 69ee593fd2 | |||
| 39ddef6829 | |||
| 11aedbd741 | |||
| e4d1e12f7f | |||
| 9c2b32d6f3 | |||
| 4b3a590b00 | |||
| 7f50e97628 | |||
| e5ee6123fc | |||
| 923b6aba0d | |||
| 955e20eb61 | |||
| 286a40751c | |||
| eca0535457 | |||
| 7ace77a5d7 | |||
| 7f362af153 | |||
| 35dee2abac | |||
| 29c926201d | |||
| 9b6852a8c9 | |||
| 53efc8d5d0 | |||
| 0b8461c9cb | |||
| abd8e2a9eb | |||
| bc4dadc894 | |||
| ec53089bb1 | |||
| 7bb50e2823 | |||
| 632b2ddd34 | |||
| 7caad2205a | |||
| 9bf5f89659 | |||
| f41ca4a53e | |||
| 0bcd0872d8 | |||
| 6ec5946094 | |||
| 784ea8e160 | |||
| 6ec53bdfd3 | |||
| d1b6480dcf | |||
| ef6fed3ef8 | |||
| 473dee5786 | |||
| 779e3f6b5f | |||
| 71bca00651 | |||
| 9a9fce0abc | |||
| 939ca37cfe | |||
| 4ae8a2a4b6 | |||
| 113d3954b9 | |||
| 7cb5983750 | |||
| 2b149ca6d4 | |||
| e77866c18c | |||
| 0dc6418d20 | |||
| 837a077578 | |||
| adf91fe6ee | |||
| dea1c0d34c | |||
| f533acc9aa | |||
| d01cae2a0d | |||
| d015c8a80b | |||
| 8d2717146b | |||
| 3d598dae64 | |||
| 0a58986f52 | |||
| 6e69b85f9a | |||
| 7a9e336028 | |||
| 9b8df52aa9 | |||
| 7fab29fbe1 | |||
| 1a47fcbb8b | |||
| ffd4dab611 | |||
| 13edaa95c7 | |||
| 47b1f54bba | |||
| cdc7280dd3 | |||
| 0bb282bc6d | |||
| fdb09ef858 | |||
| 5e69cb2f9f | |||
| 5c2da38e3f | |||
| 3a799df0f1 | |||
| 511c765a44 | |||
| bf55d76d27 | |||
| c9efc80cd0 | |||
| fa15f2a6df | |||
| c023a0bfbb | |||
| b470e005e8 | |||
| c959191882 | |||
| e4adebd07a | |||
| ac94f6125f | |||
| c5686c5271 | |||
| 7fdb54d12b | |||
| 869008140a | |||
| 26ee32ec79 | |||
| a06193f97b | |||
| ba9dee170c | |||
| d4b60ada1e | |||
| b839f73ad0 | |||
| aee32931fd | |||
| 7ee5f46bbc | |||
| 2b97854bf4 | |||
| 316ee8f7ca | |||
| 2e18f44fcd | |||
| c85d064ecf | |||
| 7b9b82281a | |||
| aab632b330 | |||
| 4c8d8ad508 | |||
| 3a8f3dc9ea | |||
| c139e68d99 |
@@ -1,5 +0,0 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# JS files must always use LF for tools to work
|
||||
*.js eol=lf
|
||||
@@ -0,0 +1,15 @@
|
||||
// This is an incomplete TODO list of checks we want to start enforcing
|
||||
//
|
||||
// The goal is to enable these checks one by one by moving them to .jscs.json along with commits
|
||||
// that correct the existing code base issues and make the new check pass.
|
||||
|
||||
{
|
||||
"validateParameterSeparator": ", ", // Re-assert this rule when JSCS allows multiple spaces
|
||||
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
|
||||
"disallowImplicitTypeConversion": ["string"],
|
||||
"disallowMultipleLineBreaks": true,
|
||||
"validateJSDoc": {
|
||||
"checkParamNames": true,
|
||||
"requireParamTypes": true
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '0.10'
|
||||
|
||||
|
||||
+2
-801
@@ -1,745 +1,3 @@
|
||||
<a name="1.4.1"></a>
|
||||
# 1.4.1 hyperionic-illumination (2015-06-16)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- workaround for IE11 MutationObserver
|
||||
([f3b1d0b7](https://github.com/angular/angular.js/commit/f3b1d0b723298a5f8ea21d0704405649cce1b5fc),
|
||||
[#11781](https://github.com/angular/angular.js/issues/11781))
|
||||
- prevent exception when using `watch` as isolated scope binding property in Firefox
|
||||
([a6339d30](https://github.com/angular/angular.js/commit/a6339d30d1379689da5eec9647a953f64821f8b0),
|
||||
[#11627](https://github.com/angular/angular.js/issues/11627))
|
||||
- assign controller return values correctly for multiple directives
|
||||
([8caf1802](https://github.com/angular/angular.js/commit/8caf1802e0e93389dec626ef35e04a302aa6c39d),
|
||||
[#12029](https://github.com/angular/angular.js/issues/12029), [#12036](https://github.com/angular/angular.js/issues/12036))
|
||||
- **$location:** do not get caught in infinite digest in IE9 when redirecting in `$locationChangeSuccess`
|
||||
([91b60226](https://github.com/angular/angular.js/commit/91b602263b96b6fce1331208462e18eb647f4d60),
|
||||
[#11439](https://github.com/angular/angular.js/issues/11439), [#11675](https://github.com/angular/angular.js/issues/11675), [#11935](https://github.com/angular/angular.js/issues/11935), [#12083](https://github.com/angular/angular.js/issues/12083))
|
||||
- **$parse:** set null reference properties to `undefined`
|
||||
([71fc3f4f](https://github.com/angular/angular.js/commit/71fc3f4fa0cd12eff335d57efed7c033554749f4),
|
||||
[#12099](https://github.com/angular/angular.js/issues/12099))
|
||||
([d19504a1](https://github.com/angular/angular.js/commit/d19504a179355d7801d59a8db0285a1322e04601),
|
||||
[#11959](https://github.com/angular/angular.js/issues/11959))
|
||||
- **$sanitize:** do not remove `tabindex` attribute
|
||||
([799353c7](https://github.com/angular/angular.js/commit/799353c75de28e6fbf52dac6e0721e85b578575a),
|
||||
[#8371](https://github.com/angular/angular.js/issues/8371), [#5853](https://github.com/angular/angular.js/issues/5853))
|
||||
- **copy:** do not copy the same object twice
|
||||
([0e622f7b](https://github.com/angular/angular.js/commit/0e622f7b5bc3d5d0ab0fbc1a1bc69404bd7216d5))
|
||||
- **forms:** parse exponential notation in `numberInputType` directive
|
||||
([ebd0fbba](https://github.com/angular/angular.js/commit/ebd0fbba8ff90bee0cd016d574643d56a7f81ed0),
|
||||
[#12121](https://github.com/angular/angular.js/issues/12121), [#12122](https://github.com/angular/angular.js/issues/12122))
|
||||
- **linky:** allow case insensitive scheme detection
|
||||
([8dc09e6d](https://github.com/angular/angular.js/commit/8dc09e6dabb84c2c611cdc9e40adfac989648200),
|
||||
[#12073](https://github.com/angular/angular.js/issues/12073), [#12073](https://github.com/angular/angular.js/issues/12073))
|
||||
- **ngAria:**
|
||||
- update `aria-valuemin/max` when `min/max` change
|
||||
([ebaa0f59](https://github.com/angular/angular.js/commit/ebaa0f598501702ae64d59ada0ae492eaf0e2db6),
|
||||
[#11770](https://github.com/angular/angular.js/issues/11770), [#11774](https://github.com/angular/angular.js/issues/11774))
|
||||
- ensure boolean values for aria-hidden and aria-disabled
|
||||
([59273354](https://github.com/angular/angular.js/commit/59273354b57dd8d1ad2cd2f4740ffa8923e480f9),
|
||||
[#11365](https://github.com/angular/angular.js/issues/11365))
|
||||
- **ngModel:** ignore Object.prototype properties on the form validation object
|
||||
([0934b76b](https://github.com/angular/angular.js/commit/0934b76b72cec86093414834ac4cb7f0946b651d),
|
||||
[#12066](https://github.com/angular/angular.js/issues/12066))
|
||||
- **ngOptions:**
|
||||
- do not watch properties starting with $
|
||||
([34a6da24](https://github.com/angular/angular.js/commit/34a6da24c17356d4ffc70aec3f621a140a9a61ab),
|
||||
[#11930](https://github.com/angular/angular.js/issues/11930), [#12010](https://github.com/angular/angular.js/issues/12010))
|
||||
- use reference check only when not using trackBy
|
||||
([d7dc14dc](https://github.com/angular/angular.js/commit/d7dc14dc0cdeb9c187d227e19acc8aca7df9d740),
|
||||
[#11936](https://github.com/angular/angular.js/issues/11936), [#11996](https://github.com/angular/angular.js/issues/11996))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$compile:** show module name during `multidir` error
|
||||
([351fe4b7](https://github.com/angular/angular.js/commit/351fe4b79c50a45a11af2fcd2aa7b6fd3b70058d),
|
||||
[#11775](https://github.com/angular/angular.js/issues/11775))
|
||||
- **$q:** $q.resolve as an alias for $q.when
|
||||
([3ef52980](https://github.com/angular/angular.js/commit/3ef529806fef28b41ca4af86a330f39a95699cf6),
|
||||
[#11944](https://github.com/angular/angular.js/issues/11944), [#11987](https://github.com/angular/angular.js/issues/11987))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$compile:** avoid jquery data calls when there is no data
|
||||
([9efb0d5e](https://github.com/angular/angular.js/commit/9efb0d5ee961b57c8fc144a3138a15955e4010e2))
|
||||
|
||||
|
||||
|
||||
<a name="1.3.16"></a>
|
||||
# 1.3.16 cookie-oatmealification (2015-06-05)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** throw error on invalid directive name
|
||||
([634e4671](https://github.com/angular/angular.js/commit/634e467172efa696eb32ef8942ffbedeecbd030e),
|
||||
[#11281](https://github.com/angular/angular.js/issues/11281), [#11109](https://github.com/angular/angular.js/issues/11109))
|
||||
- **$cookies:** update $cookies to prevent duplicate cookie writes and play nice with external code
|
||||
([706a93ab](https://github.com/angular/angular.js/commit/706a93ab6960e3474698ccf9a8048b3c32e567c6),
|
||||
[#11490](https://github.com/angular/angular.js/issues/11490), [#11515](https://github.com/angular/angular.js/issues/11515))
|
||||
- **$http:** throw error if `success` and `error` methods do not receive a function
|
||||
([731e1f65](https://github.com/angular/angular.js/commit/731e1f6534ab7fd1e053b8d7a25c902fcd934fea),
|
||||
[#11330](https://github.com/angular/angular.js/issues/11330), [#11333](https://github.com/angular/angular.js/issues/11333))
|
||||
- **core:** ensure that multiple requests to requestAnimationFrame are buffered
|
||||
([0adc0364](https://github.com/angular/angular.js/commit/0adc0364265b06c567ccc8e90a7f09cc46f235b2),
|
||||
[#11791](https://github.com/angular/angular.js/issues/11791))
|
||||
- **filterFilter:** fix matching against `null`/`undefined`
|
||||
([9dd0fe35](https://github.com/angular/angular.js/commit/9dd0fe35d1027e59b84b2396abee00d8683f3b50),
|
||||
[#11573](https://github.com/angular/angular.js/issues/11573), [#11617](https://github.com/angular/angular.js/issues/11617))
|
||||
- **jqLite:**
|
||||
- check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
|
||||
([647f3f55](https://github.com/angular/angular.js/commit/647f3f55eb7100a255272f7277f0f962de234a32),
|
||||
[#11508](https://github.com/angular/angular.js/issues/11508))
|
||||
- attr should ignore comment, text and attribute nodes
|
||||
([181e5ebc](https://github.com/angular/angular.js/commit/181e5ebc3fce5312feacaeace4fcad0d32f4d73c))
|
||||
- **ngAnimate:**
|
||||
- ensure that minified repaint code isn't removed
|
||||
([d5c99ea4](https://github.com/angular/angular.js/commit/d5c99ea42b834343fd0362cfc572f47e7536ccfb),
|
||||
[#9936](https://github.com/angular/angular.js/issues/9936))
|
||||
- **ngAria:** handle elements with role="checkbox/menuitemcheckbox"
|
||||
([1c282af5](https://github.com/angular/angular.js/commit/1c282af5abc205d4aac37c05c5cb725d71747134),
|
||||
[#11317](https://github.com/angular/angular.js/issues/11317), [#11321](https://github.com/angular/angular.js/issues/11321))
|
||||
- **ngModel:** allow setting model to NaN when asyncValidator is present
|
||||
([b64519fe](https://github.com/angular/angular.js/commit/b64519fea7f1a5ec75e32c4b71b012b827314153),
|
||||
[#11315](https://github.com/angular/angular.js/issues/11315), [#11411](https://github.com/angular/angular.js/issues/11411))
|
||||
- **ngTouch:**
|
||||
- check undefined tagName for SVG event target
|
||||
([7560a8d2](https://github.com/angular/angular.js/commit/7560a8d2d65955ddb60ede9d586502f4e3cbd062))
|
||||
- register touches properly when jQuery is used
|
||||
([40441f6d](https://github.com/angular/angular.js/commit/40441f6dfc5ebd5cdc679c269c4639238f5351eb),
|
||||
[#4001](https://github.com/angular/angular.js/issues/4001), [#8584](https://github.com/angular/angular.js/issues/8584), [#10797](https://github.com/angular/angular.js/issues/10797), [#11488](https://github.com/angular/angular.js/issues/11488))
|
||||
- **select:** prevent unknown option being added to select when bound to null property
|
||||
([9e3f82bb](https://github.com/angular/angular.js/commit/9e3f82bbaf83cad7bb3121db756099b0880562e6),
|
||||
[#11872](https://github.com/angular/angular.js/issues/11872), [#11875](https://github.com/angular/angular.js/issues/11875))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **travis:** run unit tests on iOS 8
|
||||
([1f650871](https://github.com/angular/angular.js/commit/1f650871266b88b3dab4a894a839a82ac9a06b69),
|
||||
[#11479](https://github.com/angular/angular.js/issues/11479))
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0"></a>
|
||||
# 1.4.0 jaracimrman-existence (2015-05-26)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ignore invalid option parameter values
|
||||
([72edd4df](https://github.com/angular/angular.js/commit/72edd4dff931c644eecb8f0d1c878dc839c76947),
|
||||
[#11826](https://github.com/angular/angular.js/issues/11826))
|
||||
- accept unwrapped DOM elements as inputs for enter + move
|
||||
([f26fc26f](https://github.com/angular/angular.js/commit/f26fc26f6ea283b2fc5ddb18627b13850de2663e),
|
||||
[#11848](https://github.com/angular/angular.js/issues/11848))
|
||||
- **$animateCss:** ensure that custom durations do not confuse the gcs cache
|
||||
([e0e1b520](https://github.com/angular/angular.js/commit/e0e1b5208767dd62f5586fdc607cb2e31dac9516),
|
||||
[#11723](https://github.com/angular/angular.js/issues/11723), [#11852](https://github.com/angular/angular.js/issues/11852))
|
||||
- **$http:** do not modify the config object passed into $http short methods
|
||||
([f7a4b481](https://github.com/angular/angular.js/commit/f7a4b48121ed2b04af89bd2b754f500d1872360d))
|
||||
- **ngAnimate:**
|
||||
- close follow-up class-based animations when the same class is added/removed when removed/added
|
||||
([db246eb7](https://github.com/angular/angular.js/commit/db246eb701529b41049fc118908e528920f13b24),
|
||||
[#11717](https://github.com/angular/angular.js/issues/11717))
|
||||
- ensure nested class-based animations are spaced out with a RAF
|
||||
([213c2a70](https://github.com/angular/angular.js/commit/213c2a703293ee0af8229dde2b608687cd77ccfa),
|
||||
[#11812](https://github.com/angular/angular.js/issues/11812))
|
||||
- class-based animations must not set addClass/removeClass CSS classes on the element
|
||||
([3a3db690](https://github.com/angular/angular.js/commit/3a3db690a16e888aa7371e3b02e2954b9ec2d558),
|
||||
[#11810](https://github.com/angular/angular.js/issues/11810))
|
||||
- ensure that repeated structural calls during pre-digest function
|
||||
([2327f5a0](https://github.com/angular/angular.js/commit/2327f5a0a7e018a9b03aefabe1fbd0c9330e2eeb),
|
||||
[#11867](https://github.com/angular/angular.js/issues/11867))
|
||||
- ensure that cancelled class-based animations are properly cleaned up
|
||||
([718ff844](https://github.com/angular/angular.js/commit/718ff84405558ac64402e1fca5caefd7d307ea1e),
|
||||
[#11652](https://github.com/angular/angular.js/issues/11652))
|
||||
- throw an error if a callback is passed to animate methods
|
||||
([9bb4d6cc](https://github.com/angular/angular.js/commit/9bb4d6ccbe80b7704c6b7f53317ca8146bc103ca),
|
||||
[#11826](https://github.com/angular/angular.js/issues/11826), [#11713](https://github.com/angular/angular.js/issues/11713))
|
||||
- ensure anchored animations remove the leave element at correct time
|
||||
([64c66d0e](https://github.com/angular/angular.js/commit/64c66d0eea11b575d2a71d00c70cfc5be12cd450),
|
||||
[#11850](https://github.com/angular/angular.js/issues/11850))
|
||||
- **select:** prevent unknown option being added to select when bound to null property
|
||||
([4090491c](https://github.com/angular/angular.js/commit/4090491c73910c169d4fba0494a4e26b45dca7ec),
|
||||
[#11872](https://github.com/angular/angular.js/issues/11872), [#11875](https://github.com/angular/angular.js/issues/11875))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **filterFilter:** allow array like objects to be filtered
|
||||
([1b0d0fd8](https://github.com/angular/angular.js/commit/1b0d0fd8d00b42dffd798845fe0947d594372613),
|
||||
[#11782](https://github.com/angular/angular.js/issues/11782), [#11787](https://github.com/angular/angular.js/issues/11787))
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-rc.2"></a>
|
||||
# 1.4.0-rc.2 rocket-zambonimation (2015-05-12)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** ensure directive names have no leading or trailing whitespace
|
||||
([bab474aa](https://github.com/angular/angular.js/commit/bab474aa8b146f6732857c3af1a8b3b010fda8b0),
|
||||
[#11397](https://github.com/angular/angular.js/issues/11397), [#11772](https://github.com/angular/angular.js/issues/11772))
|
||||
- **$httpParamSerializerJQLike:** follow jQuery logic for nested params
|
||||
([2420a0a7](https://github.com/angular/angular.js/commit/2420a0a77e27b530dbb8c41319b2995eccf76791),
|
||||
[#11551](https://github.com/angular/angular.js/issues/11551), [#11635](https://github.com/angular/angular.js/issues/11635))
|
||||
- **jqLite:** check for "length" in obj in isArrayLike to prevent iOS8 JIT bug from surfacing
|
||||
([426a5ac0](https://github.com/angular/angular.js/commit/426a5ac0547109648e5c5e358f668c274a111ab2),
|
||||
[#11508](https://github.com/angular/angular.js/issues/11508))
|
||||
- **ngAnimate:**
|
||||
- ensure that multiple requests to requestAnimationFrame are buffered
|
||||
([db20b830](https://github.com/angular/angular.js/commit/db20b830fc6074a00dc11d3f47d665c55e8bb515),
|
||||
[#11791](https://github.com/angular/angular.js/issues/11791))
|
||||
- ensure that an object is always returned even when no animation is set to run
|
||||
([d5683d21](https://github.com/angular/angular.js/commit/d5683d21165e725bc5a850e795f681b0a8a008f5))
|
||||
- force use of `ng-anchor` instead of a suffixed `-anchor` CSS class when triggering anchor animations
|
||||
([df24410c](https://github.com/angular/angular.js/commit/df24410c17d51a8d44929b9cffee2c91cedfed72))
|
||||
- rename `ng-animate-anchor` to `ng-anchor`
|
||||
([e6d053de](https://github.com/angular/angular.js/commit/e6d053de0993c0d38de46ad8a9c6760537316430))
|
||||
- ensure that shared CSS classes between anchor nodes are retained
|
||||
([e0014002](https://github.com/angular/angular.js/commit/e0014002370278778077d0612f9fab6beb80d07a),
|
||||
[#11681](https://github.com/angular/angular.js/issues/11681))
|
||||
- prohibit usage of the `ng-animate` class with classNameFilter
|
||||
([1002b80a](https://github.com/angular/angular.js/commit/1002b80a6fb5d98c424a01330234276d65d93c0b),
|
||||
[#11431](https://github.com/angular/angular.js/issues/11431), [#11807](https://github.com/angular/angular.js/issues/11807))
|
||||
- ensure that the temporary CSS classes are applied before detection
|
||||
([f7e9ff1a](https://github.com/angular/angular.js/commit/f7e9ff1aba9ed70835c084e6e154f6b0bf9c3a19),
|
||||
[#11769](https://github.com/angular/angular.js/issues/11769), [#11804](https://github.com/angular/angular.js/issues/11804))
|
||||
- ensure that all jqLite elements are deconstructed properly
|
||||
([64d05180](https://github.com/angular/angular.js/commit/64d05180a667e586328fbdbd328889d3b003571d),
|
||||
[#11658](https://github.com/angular/angular.js/issues/11658))
|
||||
- ensure animations are not attempted on text nodes
|
||||
([2aacc2d6](https://github.com/angular/angular.js/commit/2aacc2d622893e05eb94b3974d562e681cc3a17f),
|
||||
[#11703](https://github.com/angular/angular.js/issues/11703))
|
||||
- ensure JS animations recognize $animateCss directly
|
||||
([0681a540](https://github.com/angular/angular.js/commit/0681a5400e4150a961f9c8651e55623ca23b0cc2))
|
||||
- **ngClass:** add/remove classes which are properties of Object.prototype
|
||||
([f7b99970](https://github.com/angular/angular.js/commit/f7b999703f4f3bdaea035ce692f1a656b0c1a933),
|
||||
[#11813](https://github.com/angular/angular.js/issues/11813), [#11814](https://github.com/angular/angular.js/issues/11814))
|
||||
- **ngOptions:**
|
||||
- ensure that tracked properties are always watched
|
||||
([b5a9053b](https://github.com/angular/angular.js/commit/b5a9053ba33d48db2482ca6736d1fcae8b33d0f8),
|
||||
[#11784](https://github.com/angular/angular.js/issues/11784))
|
||||
- ensure label is watched in all cases
|
||||
([ae98dadf](https://github.com/angular/angular.js/commit/ae98dadf6dca3313746f42a441c7659654dd9d50),
|
||||
[#11765](https://github.com/angular/angular.js/issues/11765))
|
||||
- iterate over the options collection in the same way as `ngRepeat`
|
||||
([dfa722a8](https://github.com/angular/angular.js/commit/dfa722a8a6864793fd9580d8ae704a06d10b5509),
|
||||
[#11733](https://github.com/angular/angular.js/issues/11733))
|
||||
- use watchCollection not deep watch of ngModel
|
||||
([47f9fc3e](https://github.com/angular/angular.js/commit/47f9fc3e70bc361e8c11fe68dc3ec4489238efb3),
|
||||
[#11372](https://github.com/angular/angular.js/issues/11372), [#11653](https://github.com/angular/angular.js/issues/11653), [#11743](https://github.com/angular/angular.js/issues/11743))
|
||||
- **ngTouch:**
|
||||
- check undefined tagName for SVG event target
|
||||
([74eb17d7](https://github.com/angular/angular.js/commit/74eb17d7c8232f72f134bf2546f10fed7234d276))
|
||||
- don't prevent click event after a touchmove
|
||||
([95521876](https://github.com/angular/angular.js/commit/95521876eb9eb330548b0549f0cfe22a26d88f6e),
|
||||
[#10985](https://github.com/angular/angular.js/issues/10985))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$resource:** include request context in error message
|
||||
([266bc652](https://github.com/angular/angular.js/commit/266bc6520ba4d188dbc949643def102604f98905),
|
||||
[#11363](https://github.com/angular/angular.js/issues/11363))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
### ngAnimate
|
||||
|
||||
- **$animateCss:** due to [d5683d21](https://github.com/angular/angular.js/commit/d5683d21165e725bc5a850e795f681b0a8a008f5),
|
||||
The $animateCss service will now always return an
|
||||
object even if the animation is not set to run. If your code is using
|
||||
$animateCss then please consider the following code change:
|
||||
|
||||
```
|
||||
// before
|
||||
var animator = $animateCss(element, { ... });
|
||||
if (!animator) {
|
||||
continueApp();
|
||||
return;
|
||||
}
|
||||
var runner = animator.start();
|
||||
runner.done(continueApp);
|
||||
runner.then(continueApp);
|
||||
|
||||
// now
|
||||
var animator = $animateCss(element, { ... });
|
||||
var runner = animator.start();
|
||||
runner.done(continueApp);
|
||||
runner.then(continueApp);
|
||||
```
|
||||
|
||||
- due to [df24410c](https://github.com/angular/angular.js/commit/df24410c17d51a8d44929b9cffee2c91cedfed72),
|
||||
Prior to this fix there were to ways to apply CSS
|
||||
animation code to an anchor animation. With this fix, the suffixed
|
||||
CSS -anchor classes are now not used anymore for CSS anchor animations.
|
||||
|
||||
Instead just use the `ng-anchor` CSS class like so:
|
||||
|
||||
```html
|
||||
<div class="container-animation" ng-if="on">
|
||||
<div ng-animate-ref="1" class="my-anchor-element"></div>
|
||||
</div>
|
||||
|
||||
<div class="container-animation" ng-if="!on">
|
||||
<div ng-animate-ref="1" class="my-anchor-element"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**before**:
|
||||
```css
|
||||
/* before (notice the container-animation CSS class) */
|
||||
.container-animation-anchor {
|
||||
transition:0.5s linear all;
|
||||
}
|
||||
```
|
||||
|
||||
**now**:
|
||||
```css
|
||||
/* now (just use `ng-anchor` on a class that both the
|
||||
elements that contain `ng-animate-ref` share) */
|
||||
.my-anchor-element.ng-anchor {
|
||||
transition:0.5s linear all;
|
||||
}
|
||||
```
|
||||
|
||||
- due to [e6d053de](https://github.com/angular/angular.js/commit/e6d053de0993c0d38de46ad8a9c6760537316430),
|
||||
if your CSS code made use of the `ng-animate-anchor`
|
||||
CSS class for referencing the anchored animation element then your
|
||||
code must now use `ng-anchor` instead.
|
||||
|
||||
- due to [1002b80a](https://github.com/angular/angular.js/commit/1002b80a6fb5d98c424a01330234276d65d93c0b),
|
||||
partially or fully using a regex value containing
|
||||
`ng-animate` as a token is not allowed anymore. Doing so will trigger a
|
||||
minErr exception to be thrown.
|
||||
|
||||
So don't do this:
|
||||
|
||||
```js
|
||||
// only animate elements that contain the `ng-animate` CSS class
|
||||
$animateProvider.classNameFilter(/ng-animate/);
|
||||
|
||||
// or partially contain it
|
||||
$animateProvider.classNameFilter(/some-class ng-animate another-class/);
|
||||
```
|
||||
|
||||
but this is OK:
|
||||
|
||||
```js
|
||||
$animateProvider.classNameFilter(/ng-animate-special/);
|
||||
```
|
||||
|
||||
|
||||
### ngOptions
|
||||
|
||||
- ** due to [dfa722a8](https://github.com/angular/angular.js/commit/dfa722a8a6864793fd9580d8ae704a06d10b5509),
|
||||
|
||||
|
||||
Although it is unlikely that anyone is using it in this way, this change does change the
|
||||
behaviour of `ngOptions` in the following case:
|
||||
|
||||
* you are iterating over an array-like object, using the array form of the `ngOptions` syntax
|
||||
(`item.label for item in items`) and that object contains non-numeric property keys.
|
||||
|
||||
In this case these properties with non-numeric keys will be ignored.
|
||||
|
||||
** Here array-like is defined by the result of a call to this internal function:
|
||||
https://github.com/angular/angular.js/blob/v1.4.0-rc.1/src/Angular.js#L198-L211 **
|
||||
|
||||
To get the desired behaviour you need to iterate using the object form of the `ngOptions` syntax
|
||||
(`value.label` for (key, value) in items)`).
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="v1.4.0-rc.1"></a>
|
||||
# v1.4.0-rc.1 sartorial-chronography (2015-04-24)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ensure that from styles are applied for class-based animations
|
||||
([8f819d2c](https://github.com/angular/angular.js/commit/8f819d2cb5c8025b25534529a6e897dc8805885b))
|
||||
- make sure the JS animation lookup is an object lookup
|
||||
([103a39ca](https://github.com/angular/angular.js/commit/103a39ca8dad0300bead15c358aad846510b2229),
|
||||
[#11619](https://github.com/angular/angular.js/issues/11619))
|
||||
- **$animateCss:** ensure that rAF waiting loop doesn't ignore pending items during a flush
|
||||
([90e424b2](https://github.com/angular/angular.js/commit/90e424b206239e261024e8ef7fcac762236cd8b7))
|
||||
- **$http:** stop coercing falsy HTTP request bodies to null / empty body
|
||||
([e04a887c](https://github.com/angular/angular.js/commit/e04a887c9b506de18516600310fe6e529d9d2ca3),
|
||||
[#11552](https://github.com/angular/angular.js/issues/11552), [#11593](https://github.com/angular/angular.js/issues/11593))
|
||||
- **ngAnimate:**
|
||||
- close parent animations only when there are classes to resolve
|
||||
([1459be17](https://github.com/angular/angular.js/commit/1459be170dabfca40501dcf219dfced5ba513169))
|
||||
- ensure ngClass-based classes are always resolved for CSS-enabled animations
|
||||
([89f081e4](https://github.com/angular/angular.js/commit/89f081e452e9a75c2d3bf86bfef8b7f9bd1f2b0e))
|
||||
- do not abort animation if only `ng-anchor-in` is used
|
||||
([3333a5c3](https://github.com/angular/angular.js/commit/3333a5c380f830cba8efec5825cb6648f930f206))
|
||||
- ensure that a filtered-out leave animation always runs its DOM operation
|
||||
([6dd64ab5](https://github.com/angular/angular.js/commit/6dd64ab5f34fa19db8f90e6eabc810843089ba14),
|
||||
[#11555](https://github.com/angular/angular.js/issues/11555))
|
||||
- ensure that animations work when the app is bootstrapped on the document node
|
||||
([bee14ed1](https://github.com/angular/angular.js/commit/bee14ed1e7b77ea7dc62326611380da36dec297e),
|
||||
[#11574](https://github.com/angular/angular.js/issues/11574))
|
||||
- ensure SVG classes are properly removed
|
||||
([fa0bbded](https://github.com/angular/angular.js/commit/fa0bbded1ea040fbfdb1a4339e4a374fe9717a82))
|
||||
- **ngAria:** change accessibility keypress event to use event.which if it is provided
|
||||
([249f9b81](https://github.com/angular/angular.js/commit/249f9b81cbad5c57cf978a47842744aadd85cdb4),
|
||||
[#11340](https://github.com/angular/angular.js/issues/11340))
|
||||
- **ngMessageFormat:**
|
||||
- ensure bindings are valid for Protractor
|
||||
([992114f7](https://github.com/angular/angular.js/commit/992114f7a7f5f39778753e0c49458f14b6290ffc),
|
||||
[#11644](https://github.com/angular/angular.js/issues/11644), [#11649](https://github.com/angular/angular.js/issues/11649))
|
||||
- minified symbol and nested required expression
|
||||
([8a45064f](https://github.com/angular/angular.js/commit/8a45064f2bdec13ba3de5b0a0785df76188ab172),
|
||||
[#11414](https://github.com/angular/angular.js/issues/11414), [#11592](https://github.com/angular/angular.js/issues/11592))
|
||||
- **select:** allow empty option to be added dynamically by ng-repeat
|
||||
([abf59c28](https://github.com/angular/angular.js/commit/abf59c285c3ff6af20dbf4236eba5204ae735abb),
|
||||
[#11470](https://github.com/angular/angular.js/issues/11470), [#11512](https://github.com/angular/angular.js/issues/11512))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$animate:** provide support for animations on elements outside of $rootElement
|
||||
([e41faaa2](https://github.com/angular/angular.js/commit/e41faaa2a155a42bcc66952497a6f33866878508))
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="v1.4.0-rc.0"></a>
|
||||
# v1.4.0-rc.0 smooth-unwinding (2015-04-10)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- throw error on invalid directive name
|
||||
([170ff9a3](https://github.com/angular/angular.js/commit/170ff9a37dea8772dda7c89e84176ac1a8992878),
|
||||
[#11281](https://github.com/angular/angular.js/issues/11281), [#11109](https://github.com/angular/angular.js/issues/11109))
|
||||
- update data() when controller returns custom value
|
||||
([9900610e](https://github.com/angular/angular.js/commit/9900610eea4ece87b063f2aa9d82c75c369927df),
|
||||
[#11147](https://github.com/angular/angular.js/issues/11147), [#11326](https://github.com/angular/angular.js/issues/11326))
|
||||
- **$http:** throw error if `success` and `error` methods do not receive a function
|
||||
([1af563d4](https://github.com/angular/angular.js/commit/1af563d43e74cb7be53e815b66fd91dd93986ed6),
|
||||
[#11330](https://github.com/angular/angular.js/issues/11330), [#11333](https://github.com/angular/angular.js/issues/11333))
|
||||
- **$parse:** fix parse errors on older Android WebViews which choke with reserved keywords
|
||||
([10ae33b2](https://github.com/angular/angular.js/commit/10ae33b2d88b04df76f519edc50a47fa30f83e96),
|
||||
[#11455](https://github.com/angular/angular.js/issues/11455))
|
||||
- **$rootScope:** allow destroying a root scope
|
||||
([f8c8cf69](https://github.com/angular/angular.js/commit/f8c8cf698aa23640249d79fd405605694478e4f7),
|
||||
[#11241](https://github.com/angular/angular.js/issues/11241), [#10895](https://github.com/angular/angular.js/issues/10895))
|
||||
- **cookieReader:** safely access $document so it can be mocked
|
||||
([a057e089](https://github.com/angular/angular.js/commit/a057e0896a7fe2fdaba50b2515555b86e4f4be27),
|
||||
[#11373](https://github.com/angular/angular.js/issues/11373), [#11388](https://github.com/angular/angular.js/issues/11388))
|
||||
- **filterFilter:** fix matching against `null`/`undefined`
|
||||
([b5002ab6](https://github.com/angular/angular.js/commit/b5002ab62ad6e13f4339e20106e1fdece14912a2),
|
||||
[#11432](https://github.com/angular/angular.js/issues/11432), [#11445](https://github.com/angular/angular.js/issues/11445))
|
||||
- **ngAnimate:** ensure that minified repaint code isn't removed
|
||||
([c55a4944](https://github.com/angular/angular.js/commit/c55a494433e619aad0c7ef9fddadc0b3fdf53915),
|
||||
[#9936](https://github.com/angular/angular.js/issues/9936))
|
||||
- **ngAria:** handle elements with role="checkbox/menuitemcheckbox"
|
||||
([44337f63](https://github.com/angular/angular.js/commit/44337f63fa94116795e83e3a764a6ba6782809c7),
|
||||
[#11317](https://github.com/angular/angular.js/issues/11317), [#11321](https://github.com/angular/angular.js/issues/11321))
|
||||
- **ngModel:** allow setting model to NaN when asyncValidator is present
|
||||
([948120ec](https://github.com/angular/angular.js/commit/948120ecdbc4dd07880c0107564c50c7675b8a93),
|
||||
[#11315](https://github.com/angular/angular.js/issues/11315), [#11411](https://github.com/angular/angular.js/issues/11411))
|
||||
- **ngTouch:** register touches properly when jQuery is used
|
||||
([06a9f0a9](https://github.com/angular/angular.js/commit/06a9f0a95f0e72fa2e9879fe8a49e9bf69986a5f),
|
||||
[#4001](https://github.com/angular/angular.js/issues/4001), [#8584](https://github.com/angular/angular.js/issues/8584), [#10797](https://github.com/angular/angular.js/issues/10797), [#11488](https://github.com/angular/angular.js/issues/11488))
|
||||
- **select:** don't call $render twice if $viewValue ref changes
|
||||
([7e5c447f](https://github.com/angular/angular.js/commit/7e5c447fa9ad7d81cc818d6e79392c3e4a6b23a0),
|
||||
[#11329](https://github.com/angular/angular.js/issues/11329), [#11412](https://github.com/angular/angular.js/issues/11412))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$anchorScroll:** allow scrolling to a specified element
|
||||
([731c8b5e](https://github.com/angular/angular.js/commit/731c8b5e2d01a44aa91f967f1a6acbadb8005a8b),
|
||||
[#4568](https://github.com/angular/angular.js/issues/4568), [#9596](https://github.com/angular/angular.js/issues/9596))
|
||||
- **$animate:** complete refactor of internal animation code
|
||||
([c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef))
|
||||
- **$http:** support custom params serializers
|
||||
([6c8464ad](https://github.com/angular/angular.js/commit/6c8464ad14dd308349f632245c1a064c9aae242a),
|
||||
[#3740](https://github.com/angular/angular.js/issues/3740), [#7429](https://github.com/angular/angular.js/issues/7429), [#9224](https://github.com/angular/angular.js/issues/9224), [#11461](https://github.com/angular/angular.js/issues/11461))
|
||||
- **$interpolate:** extend interpolation with MessageFormat like syntax
|
||||
([1e58488a](https://github.com/angular/angular.js/commit/1e58488ad65abf7031bab5813523bb9d86dbd28c),
|
||||
[#11152](https://github.com/angular/angular.js/issues/11152))
|
||||
- **angular.Module:** add `decorator` method
|
||||
([e57138d7](https://github.com/angular/angular.js/commit/e57138d7eff1210f99238c475fff57530bf0ab19),
|
||||
[#11305](https://github.com/angular/angular.js/issues/11305), [#11300](https://github.com/angular/angular.js/issues/11300))
|
||||
- **ngClass:** add support for conditional map within an array.
|
||||
([4588e627](https://github.com/angular/angular.js/commit/4588e627bb7238b2113241919b948d0e5166c76d),
|
||||
[#4807](https://github.com/angular/angular.js/issues/4807))
|
||||
- **travis:** run unit tests on iOS 8
|
||||
([2cdb2016](https://github.com/angular/angular.js/commit/2cdb2016b9d89abfb5ab988b67d5f26f3bf21908),
|
||||
[#11479](https://github.com/angular/angular.js/issues/11479))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$rootScope:** remove history event handler when app is torn down
|
||||
([d996305b](https://github.com/angular/angular.js/commit/d996305b4470f80fbb1cbddf54b7d10ffbb6ab47),
|
||||
[#9897](https://github.com/angular/angular.js/issues/9897), [#9905](https://github.com/angular/angular.js/issues/9905))
|
||||
- **benchmark:** add ngmodel benchmarks to largetable-bp
|
||||
([b8dbdb0c](https://github.com/angular/angular.js/commit/b8dbdb0c5e2cd176c6d94d60f781cfc02e646592),
|
||||
[#11082](https://github.com/angular/angular.js/issues/11082))
|
||||
- **ngOptions:** only perform deep equality check on ngModel if using track by
|
||||
([171b9f7f](https://github.com/angular/angular.js/commit/171b9f7f2339ef9047b8526b2c3f36bb58d14feb),
|
||||
[#11448](https://github.com/angular/angular.js/issues/11448), [#11447](https://github.com/angular/angular.js/issues/11447))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
JavaScript and CSS animations can no longer be run in
|
||||
parallel. With earlier versions of ngAnimate, both CSS and JS animations
|
||||
would be run together when multiple animations were detected. This
|
||||
feature has now been removed, however, the same effect, with even more
|
||||
possibilities, can be achieved by injecting `$animateCss` into a
|
||||
JavaScript-defined animation and creating custom CSS-based animations
|
||||
from there. Read the ngAnimate docs for more info.
|
||||
|
||||
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
The function params for `$animate.enabled()` when an
|
||||
element is used are now flipped. This fix allows the function to act as
|
||||
a getter when a single element param is provided.
|
||||
|
||||
```js
|
||||
// < 1.4
|
||||
$animate.enabled(false, element);
|
||||
|
||||
// 1.4+
|
||||
$animate.enabled(element, false);
|
||||
```
|
||||
|
||||
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
In addition to disabling the children of the element,
|
||||
`$animate.enabled(element, false)` will now also disable animations on
|
||||
the element itself.
|
||||
|
||||
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
Animation-related callbacks are now fired on
|
||||
`$animate.on` instead of directly being on the element.
|
||||
|
||||
```js
|
||||
// < 1.4
|
||||
element.on('$animate:before', function(e, data) {
|
||||
if (data.event === 'enter') { ... }
|
||||
});
|
||||
element.off('$animate:before', fn);
|
||||
|
||||
// 1.4+
|
||||
$animate.on(element, 'enter', function(data) {
|
||||
//...
|
||||
});
|
||||
$animate.off(element, 'enter', fn);
|
||||
```
|
||||
|
||||
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
There is no need to call `$scope.$apply` or
|
||||
`$scope.$digest` inside of an animation promise callback anymore
|
||||
since the promise is resolved within a digest automatically (but a
|
||||
digest is not run unless the promise is chained).
|
||||
|
||||
```js
|
||||
// < 1.4
|
||||
$animate.enter(element).then(function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.explode = true;
|
||||
});
|
||||
});
|
||||
|
||||
// 1.4+
|
||||
$animate.enter(element).then(function() {
|
||||
$scope.explode = true;
|
||||
});
|
||||
```
|
||||
|
||||
- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
When an enter, leave or move animation is triggered then it
|
||||
will always end any pending or active parent class based animations
|
||||
(animations triggered via ngClass) in order to ensure that any CSS
|
||||
styles are resolved in time.
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-beta.6"></a>
|
||||
# 1.4.0-beta.6 cookie-liberation (2015-03-17)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:** call `applyStyles` from options on `leave`
|
||||
([4374f892](https://github.com/angular/angular.js/commit/4374f892c6fa4af6ba1f2ed47c5f888fdb5fadc5),
|
||||
[#10068](https://github.com/angular/angular.js/issues/10068))
|
||||
- **$browser:** don't crash if `history.state` access causes error in IE
|
||||
([3b8163b7](https://github.com/angular/angular.js/commit/3b8163b7b664f24499e75460ab50c066eaec0f78),
|
||||
[#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369))
|
||||
- **$sanitize:** disallow unsafe svg animation tags
|
||||
([67688d5c](https://github.com/angular/angular.js/commit/67688d5ca00f6de4c7fe6084e2fa762a00d25610),
|
||||
[#11290](https://github.com/angular/angular.js/issues/11290))
|
||||
- **Angular:** properly compare RegExp with other objects for equality
|
||||
([f22e1fc9](https://github.com/angular/angular.js/commit/f22e1fc9610ae111a3ea8746a3a57169c99ce142),
|
||||
[#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205))
|
||||
- **date filter:** display localised era for `G` format codes
|
||||
([2b4dfa9e](https://github.com/angular/angular.js/commit/2b4dfa9e2b63d7ebb78f3b0fd3439d18f932e1cd),
|
||||
[#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266))
|
||||
- **filterFilter:**
|
||||
- fix filtering using an object expression when the filter value is undefined
|
||||
([c62fa6bd](https://github.com/angular/angular.js/commit/c62fa6bd898e1048d4690d41034489dc60ba6ac2),
|
||||
[#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424))
|
||||
- do not throw an error if property is null when comparing objects
|
||||
([2c4ffd6a](https://github.com/angular/angular.js/commit/2c4ffd6af4eb012c4054fe7c096267bbc5510af0),
|
||||
[#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116))
|
||||
- **form:** allow dynamic form names which initially evaluate to blank
|
||||
([410f7c68](https://github.com/angular/angular.js/commit/410f7c682633c681be641cd2a321f9e51671d474))
|
||||
- **jqLite:** attr should ignore comment, text and attribute nodes
|
||||
([bb5bf7f8](https://github.com/angular/angular.js/commit/bb5bf7f8162d11610a53428e630b47030bdc38e5))
|
||||
- **ng/$locale:** add ERA info in generic locale
|
||||
([4acb0af2](https://github.com/angular/angular.js/commit/4acb0af24c7fb3705a197ca96adc532de4766a7a))
|
||||
- **ngJq:** don't rely on existence of jqlite
|
||||
([342e5f3c](https://github.com/angular/angular.js/commit/342e5f3ce38d2fd10c5d5a98ca66f864286a7922),
|
||||
[#11044](https://github.com/angular/angular.js/issues/11044))
|
||||
- **ngMessages:** ensure that multi-level transclusion works with `ngMessagesInclude`
|
||||
([d7ec5f39](https://github.com/angular/angular.js/commit/d7ec5f392e1550658ddf271a30627b1749eccb69),
|
||||
[#11196](https://github.com/angular/angular.js/issues/11196))
|
||||
- **ngOptions:** fix model<->option interaction when using `track by`
|
||||
([6a03ca27](https://github.com/angular/angular.js/commit/6a03ca274314352052c3082163367a146bb11c2d),
|
||||
[#10869](https://github.com/angular/angular.js/issues/10869), [#10893](https://github.com/angular/angular.js/issues/10893))
|
||||
- **rootScope:** prevent memory leak when destroying scopes
|
||||
([fb7db4a0](https://github.com/angular/angular.js/commit/fb7db4a07bd1b0b67824d3808fe315419b272689),
|
||||
[#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$cookies:**
|
||||
- allow passing cookie options
|
||||
([92c366d2](https://github.com/angular/angular.js/commit/92c366d205da36ec26502aded23db71a6473dad7),
|
||||
[#8324](https://github.com/angular/angular.js/issues/8324), [#3988](https://github.com/angular/angular.js/issues/3988), [#1786](https://github.com/angular/angular.js/issues/1786), [#950](https://github.com/angular/angular.js/issues/950))
|
||||
- move logic into $cookies and deprecate $cookieStore
|
||||
([38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
|
||||
[#6411](https://github.com/angular/angular.js/issues/6411), [#7631](https://github.com/angular/angular.js/issues/7631))
|
||||
- **$cookiesProvider:** provide path, domain, expires and secure options
|
||||
([53c66369](https://github.com/angular/angular.js/commit/53c663699126815eabc2a3bc1e3bafc8b3874268))
|
||||
- **$interval:** pass additional arguments to the callback
|
||||
([4f1f9cfd](https://github.com/angular/angular.js/commit/4f1f9cfdb721cf308ca1162b2227836dc1d28388),
|
||||
[#10632](https://github.com/angular/angular.js/issues/10632))
|
||||
- **$timeout:** pass additional arguments to the callback
|
||||
([3a4b6b83](https://github.com/angular/angular.js/commit/3a4b6b83efdb8051e5c4803c0892c19ceb2cba50),
|
||||
[#10631](https://github.com/angular/angular.js/issues/10631))
|
||||
- **angular.merge:** provide an alternative to `angular.extend` that merges 'deeply'
|
||||
([c0498d45](https://github.com/angular/angular.js/commit/c0498d45feb913c318224ea70b5adf7112df6bac),
|
||||
[#10507](https://github.com/angular/angular.js/issues/10507), [#10519](https://github.com/angular/angular.js/issues/10519))
|
||||
- **filterFilter:** compare object with custom `toString()` to primitive
|
||||
([f8c42161](https://github.com/angular/angular.js/commit/f8c421617096a8d613f4eb6d0f5b098ee149c029),
|
||||
[#10464](https://github.com/angular/angular.js/issues/10464), [#10548](https://github.com/angular/angular.js/issues/10548))
|
||||
- **ngAria:**
|
||||
- add `button` role to `ngClick`
|
||||
([bb365070](https://github.com/angular/angular.js/commit/bb365070a3ed7c2d26056d378ab6a8ef493b23cc),
|
||||
[#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- add roles to custom inputs
|
||||
([29cdaee2](https://github.com/angular/angular.js/commit/29cdaee2b6e853bc3f8882a00661698d146ecd18),
|
||||
[#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- **ngLocale:** Add FIRSTDAYOFWEEK and WEEKENDRANGE from google data
|
||||
([3d149c7f](https://github.com/angular/angular.js/commit/3d149c7f20ffabab5a635af9ddcfc7105112ab4a))
|
||||
- **ngMock:**
|
||||
- allow mock $controller service to set up controller bindings
|
||||
([d02d0585](https://github.com/angular/angular.js/commit/d02d0585a086ecd2e1de628218b5a6d85c8fc7bd),
|
||||
[#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239))
|
||||
- add `they` helpers for testing multiple specs
|
||||
([e650c458](https://github.com/angular/angular.js/commit/e650c45894abe6314a806e6b3e32c908df5c00fd),
|
||||
[#10864](https://github.com/angular/angular.js/issues/10864))
|
||||
- **ngModel:** support conversion to timezone other than UTC
|
||||
([0413bee8](https://github.com/angular/angular.js/commit/0413bee8cc563a6555f8d42d5f183f6fbefc7350),
|
||||
[#11005](https://github.com/angular/angular.js/issues/11005))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$cookies:** due to [38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
|
||||
|
||||
|
||||
`$cookies` no longer exposes properties that represent the current browser cookie
|
||||
values. Now you must explicitly the methods described above to access the cookie
|
||||
values. This also means that you can no longer watch the `$cookies` properties for
|
||||
changes to the browser's cookies.
|
||||
|
||||
This feature is generally only needed if a 3rd party library was programmatically
|
||||
changing the cookies at runtime. If you rely on this then you must either write code that
|
||||
can react to the 3rd party library making the changes to cookies or implement your own polling
|
||||
mechanism.
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.3.15"></a>
|
||||
# 1.3.15 locality-filtration (2015-03-17)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:** call `applyStyles` with options on `leave`
|
||||
([ebd84e80](https://github.com/angular/angular.js/commit/ebd84e8008f45ccaa84290f6da8c2a114fcfa8cd),
|
||||
[#10068](https://github.com/angular/angular.js/issues/10068))
|
||||
- **$browser:** don't crash if history.state access causes error in IE
|
||||
([92767c09](https://github.com/angular/angular.js/commit/92767c098feaf8c58faf2d67f882305019d8160e),
|
||||
[#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369))
|
||||
- **Angular:** properly compare RegExp with other objects for equality
|
||||
([b8e8f9af](https://github.com/angular/angular.js/commit/b8e8f9af78f4ef3e556dd3cef6bfee35ad4cb82a),
|
||||
[#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205))
|
||||
- **date filter:** display localised era for `G` format codes
|
||||
([f2683f95](https://github.com/angular/angular.js/commit/f2683f956fcd3216eaa263db20b31e0d46338800),
|
||||
[#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266))
|
||||
- **filterFilter:**
|
||||
- fix filtering using an object expression when the filter value is `undefined`
|
||||
([63b9956f](https://github.com/angular/angular.js/commit/63b9956faf4c3679c88a9401b8ccbb111c0294ee),
|
||||
[#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424))
|
||||
- do not throw an error if property is null when comparing objects
|
||||
([01161a0e](https://github.com/angular/angular.js/commit/01161a0e9fb1af93e9f06535aed8392ed7f116a4),
|
||||
[#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116))
|
||||
- **form:** allow dynamic form names which initially evaluate to blank
|
||||
([190ea883](https://github.com/angular/angular.js/commit/190ea883c588d63f8b900a8de1d45c6c9ebb01ec),
|
||||
[#11096](https://github.com/angular/angular.js/issues/11096))
|
||||
- **ng/$locale:** add ERA info in generic locale
|
||||
([57842530](https://github.com/angular/angular.js/commit/578425303f2480959da80f31920d08f277d42010))
|
||||
- **rootScope:** prevent memory leak when destroying scopes
|
||||
([528cf09e](https://github.com/angular/angular.js/commit/528cf09e3f78ad4e3bb6a329ebe315c4f29b4cdb),
|
||||
[#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169))
|
||||
- **templateRequest:** avoid throwing syntax error in Android 2.3
|
||||
([75abbd52](https://github.com/angular/angular.js/commit/75abbd525f07866fdcc6fb311802b8fe700af174),
|
||||
[#11089](https://github.com/angular/angular.js/issues/11089), [#11051](https://github.com/angular/angular.js/issues/11051), [#11088](https://github.com/angular/angular.js/issues/11088))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **ngAria:**
|
||||
- add `button` role to `ngClick`
|
||||
([b9ad91cf](https://github.com/angular/angular.js/commit/b9ad91cf1e86310a2d2bf13b29fa13a9b835e1ce),
|
||||
[#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- add roles to custom inputs
|
||||
([21369943](https://github.com/angular/angular.js/commit/21369943fafd577b36827a641b021b1c14cefb57),
|
||||
[#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318))
|
||||
- **ngMock:**
|
||||
- allow mock $controller service to set up controller bindings
|
||||
([b3878a36](https://github.com/angular/angular.js/commit/b3878a36d9f8e56ad7be1eedb9691c9bd12568cb),
|
||||
[#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239))
|
||||
- add `they` helpers for testing multiple specs
|
||||
([7288be25](https://github.com/angular/angular.js/commit/7288be25a75d6ca6ac7eca05a7d6b12ccb3a22f8),
|
||||
[#10864](https://github.com/angular/angular.js/issues/10864))
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-beta.5"></a>
|
||||
# 1.4.0-beta.5 karmic-stabilization (2015-02-24)
|
||||
|
||||
@@ -825,35 +83,6 @@ end of the container containing the ngMessages directive).
|
||||
</div>
|
||||
```
|
||||
|
||||
- **$http:** due to [5da1256](https://github.com/angular/angular.js/commit/5da1256fc2812d5b28fb0af0de81256054856369),
|
||||
|
||||
`transformRequest` functions can no longer modify request headers.
|
||||
|
||||
Before this commit `transformRequest` could modify request headers, ex.:
|
||||
|
||||
```javascript
|
||||
function requestTransform(data, headers) {
|
||||
headers = angular.extend(headers(), {
|
||||
'X-MY_HEADER': 'abcd'
|
||||
});
|
||||
}
|
||||
return angular.toJson(data);
|
||||
}
|
||||
```
|
||||
|
||||
This behavior was unintended and undocumented, so the change should affect very few applications. If one
|
||||
needs to dynamically add / remove headers it should be done in a header function, for example:
|
||||
|
||||
```javascript
|
||||
$http.get(url, {
|
||||
headers: {
|
||||
'X-MY_HEADER': function(config) {
|
||||
return 'abcd'; //you've got access to a request config object to specify header value dynamically
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
<a name="1.3.14"></a>
|
||||
# 1.3.14 instantaneous-browserification (2015-02-24)
|
||||
|
||||
@@ -928,8 +157,6 @@ $http.get(url, {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.4.0-beta.3"></a>
|
||||
# 1.4.0-beta.3 substance-mimicry (2015-02-02)
|
||||
|
||||
@@ -1280,33 +507,7 @@ But in practice this is not what people want and so this change iterates over pr
|
||||
in the order they are returned by Object.keys(obj), which is almost always the order
|
||||
in which the properties were defined.
|
||||
|
||||
- **select:** due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
|
||||
|
||||
the `select` directive will now use strict comparison of the `ngModel` scope value against `option`
|
||||
values to determine which option is selected. This means `Number` scope values will not be matched
|
||||
against numeric option strings.
|
||||
In Angular 1.3.x, setting `scope.x = 200` would select the `option` with the value 200 in the following `select`:
|
||||
|
||||
```
|
||||
<select ng-model="x">
|
||||
<option value="100">100</option>
|
||||
<option value="200">200</option>
|
||||
</select>
|
||||
```
|
||||
|
||||
In Angular 1.4.x, the 'unknown option' will be selected.
|
||||
To remedy this, you can simply initialize the model as a string: `scope.x = '200'`, or if you want to
|
||||
keep the model as a `Number`, you can do the conversion via `$formatters` and `$parsers` on `ngModel`:
|
||||
|
||||
```js
|
||||
ngModelCtrl.$parsers.push(function(value) {
|
||||
return parseInt(value, 10); // Convert option value to number
|
||||
});
|
||||
|
||||
ngModelCtrl.$formatters.push(function(value) {
|
||||
return value.toString(); // Convert scope value to string
|
||||
});
|
||||
```
|
||||
|
||||
<a name="1.3.9"></a>
|
||||
# 1.3.9 multidimensional-awareness (2015-01-13)
|
||||
@@ -5266,7 +4467,7 @@ For more info: http://blog.angularjs.org/2013/12/angularjs-13-new-release-approa
|
||||
- properly toggle multiple classes
|
||||
([4e73c80b](https://github.com/angular/angular.js/commit/4e73c80b17bd237a8491782bcf9e19f1889e12ed),
|
||||
[#4467](https://github.com/angular/angular.js/issues/4467), [#6448](https://github.com/angular/angular.js/issues/6448))
|
||||
- make `jqLite(<iframe src="someurl">').contents()` return iframe document, as in jQuery
|
||||
- make jqLite('<iframe src="someurl">').contents() return iframe document, as in jQuery
|
||||
([05fbed57](https://github.com/angular/angular.js/commit/05fbed5710b702c111c1425a9e241c40d13b0a54),
|
||||
[#6320](https://github.com/angular/angular.js/issues/6320), [#6323](https://github.com/angular/angular.js/issues/6323))
|
||||
- **numberFilter:** convert all non-finite/non-numbers/non-numeric strings to the empty string
|
||||
@@ -9642,7 +8843,7 @@ with the `$route` service
|
||||
mocks now part of `angular-mocks.js` (commit f5d08963)
|
||||
|
||||
### Bug Fixes
|
||||
- `<select>` (one/multiple) could not chose from a list of objects (commit 347be5ae)
|
||||
- <select> (one/multiple) could not chose from a list of objects (commit 347be5ae)
|
||||
- null and other falsy values should not be rendered in the view (issue #242)
|
||||
|
||||
### Docs
|
||||
|
||||
+1
-9
@@ -126,9 +126,6 @@ module.exports = function(grunt) {
|
||||
ngLocale: {
|
||||
files: { src: 'src/ngLocale/**/*.js' },
|
||||
},
|
||||
ngMessageFormat: {
|
||||
files: { src: 'src/ngMessageFormat/**/*.js' },
|
||||
},
|
||||
ngMessages: {
|
||||
files: { src: 'src/ngMessages/**/*.js' },
|
||||
},
|
||||
@@ -158,7 +155,7 @@ module.exports = function(grunt) {
|
||||
jscs: {
|
||||
src: ['src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
config: ".jscsrc"
|
||||
config: ".jscs.json"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -203,10 +200,6 @@ module.exports = function(grunt) {
|
||||
dest: 'build/angular-resource.js',
|
||||
src: util.wrap(files['angularModules']['ngResource'], 'module')
|
||||
},
|
||||
messageformat: {
|
||||
dest: 'build/angular-message-format.js',
|
||||
src: util.wrap(files['angularModules']['ngMessageFormat'], 'module')
|
||||
},
|
||||
messages: {
|
||||
dest: 'build/angular-messages.js',
|
||||
src: util.wrap(files['angularModules']['ngMessages'], 'module')
|
||||
@@ -239,7 +232,6 @@ module.exports = function(grunt) {
|
||||
animate: 'build/angular-animate.js',
|
||||
cookies: 'build/angular-cookies.js',
|
||||
loader: 'build/angular-loader.js',
|
||||
messageformat: 'build/angular-message-format.js',
|
||||
messages: 'build/angular-messages.js',
|
||||
touch: 'build/angular-touch.js',
|
||||
resource: 'build/angular-resource.js',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||
Copyright (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
Using AngularJS with the Closure Compiler
|
||||
=========================================
|
||||
|
||||
The Closure Compiler project contains definitions for the AngularJS JavaScript
|
||||
in its `contrib/externs` directory.
|
||||
The Closure Compiler project contains externs definitions for AngularJS
|
||||
JavaScript in its `contrib/externs` directory.
|
||||
|
||||
The definitions contain externs for use with the Closure compiler (aka
|
||||
JSCompiler). Passing these files to the --externs parameter of a compiler
|
||||
|
||||
@@ -10,7 +10,7 @@ the browser how to do dependency injection and inversion of control.
|
||||
|
||||
Oh yeah and it helps with server-side communication, taming async callbacks with promises and
|
||||
deferreds. It also makes client-side navigation and deeplinking with hashbang urls or HTML5 pushState a
|
||||
piece of cake. Best of all?? It makes development fun!
|
||||
piece of cake. The best of all: it makes development fun!
|
||||
|
||||
* Web site: http://angularjs.org
|
||||
* Tutorial: http://docs.angularjs.org/tutorial
|
||||
|
||||
Vendored
+4
-27
@@ -40,7 +40,6 @@ var angularFiles = {
|
||||
'src/ng/timeout.js',
|
||||
'src/ng/urlUtils.js',
|
||||
'src/ng/window.js',
|
||||
'src/ng/cookieReader.js',
|
||||
|
||||
'src/ng/filter.js',
|
||||
'src/ng/filter/filter.js',
|
||||
@@ -66,7 +65,6 @@ var angularFiles = {
|
||||
'src/ng/directive/ngList.js',
|
||||
'src/ng/directive/ngModel.js',
|
||||
'src/ng/directive/ngNonBindable.js',
|
||||
'src/ng/directive/ngOptions.js',
|
||||
'src/ng/directive/ngPluralize.js',
|
||||
'src/ng/directive/ngRepeat.js',
|
||||
'src/ng/directive/ngShowHide.js',
|
||||
@@ -87,29 +85,10 @@ var angularFiles = {
|
||||
|
||||
'angularModules': {
|
||||
'ngAnimate': [
|
||||
'src/ngAnimate/shared.js',
|
||||
'src/ngAnimate/rafScheduler.js',
|
||||
'src/ngAnimate/animateChildrenDirective.js',
|
||||
'src/ngAnimate/animateCss.js',
|
||||
'src/ngAnimate/animateCssDriver.js',
|
||||
'src/ngAnimate/animateJs.js',
|
||||
'src/ngAnimate/animateJsDriver.js',
|
||||
'src/ngAnimate/animateQueue.js',
|
||||
'src/ngAnimate/animateRunner.js',
|
||||
'src/ngAnimate/animation.js',
|
||||
'src/ngAnimate/module.js'
|
||||
'src/ngAnimate/animate.js'
|
||||
],
|
||||
'ngCookies': [
|
||||
'src/ngCookies/cookies.js',
|
||||
'src/ngCookies/cookieStore.js',
|
||||
'src/ngCookies/cookieWriter.js'
|
||||
],
|
||||
'ngMessageFormat': [
|
||||
'src/ngMessageFormat/messageFormatCommon.js',
|
||||
'src/ngMessageFormat/messageFormatSelector.js',
|
||||
'src/ngMessageFormat/messageFormatInterpolationParts.js',
|
||||
'src/ngMessageFormat/messageFormatParser.js',
|
||||
'src/ngMessageFormat/messageFormatService.js'
|
||||
'src/ngCookies/cookies.js'
|
||||
],
|
||||
'ngMessages': [
|
||||
'src/ngMessages/messages.js'
|
||||
@@ -182,7 +161,7 @@ var angularFiles = {
|
||||
'src/publishExternalApis.js',
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest'
|
||||
'@angularTest',
|
||||
],
|
||||
|
||||
'karmaExclude': [
|
||||
@@ -201,7 +180,6 @@ var angularFiles = {
|
||||
'@angularSrcModules',
|
||||
'src/ngScenario/browserTrigger.js',
|
||||
'test/helpers/*.js',
|
||||
'test/ngMessageFormat/*.js',
|
||||
'test/ngMock/*.js',
|
||||
'test/ngCookies/*.js',
|
||||
'test/ngRoute/**/*.js',
|
||||
@@ -218,7 +196,7 @@ var angularFiles = {
|
||||
'src/publishExternalApis.js',
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest'
|
||||
'@angularTest',
|
||||
],
|
||||
|
||||
'karmaJqueryExclude': [
|
||||
@@ -230,7 +208,6 @@ var angularFiles = {
|
||||
|
||||
angularFiles['angularSrcModules'] = [].concat(
|
||||
angularFiles['angularModules']['ngAnimate'],
|
||||
angularFiles['angularModules']['ngMessageFormat'],
|
||||
angularFiles['angularModules']['ngMessages'],
|
||||
angularFiles['angularModules']['ngCookies'],
|
||||
angularFiles['angularModules']['ngResource'],
|
||||
|
||||
@@ -14,14 +14,11 @@
|
||||
<div>ngBind: <input type="radio" ng-model="benchmarkType" value="ngBind"></div>
|
||||
<div>ngBindOnce: <input type="radio" ng-model="benchmarkType" value="ngBindOnce"></div>
|
||||
<div>interpolation: <input type="radio" ng-model="benchmarkType" value="interpolation"></div>
|
||||
<div>interpolation + bind-once: <input type="radio" ng-model="benchmarkType" value="bindOnceInterpolation"></div>
|
||||
<div>attribute interpolation: <input type="radio" ng-model="benchmarkType" value="interpolationAttr"></div>
|
||||
<div>ngBind + fnInvocation: <input type="radio" ng-model="benchmarkType" value="ngBindFn"></div>
|
||||
<div>interpolation + fnInvocation: <input type="radio" ng-model="benchmarkType" value="interpolationFn"></div>
|
||||
<div>ngBind + filter: <input type="radio" ng-model="benchmarkType" value="ngBindFilter"></div>
|
||||
<div>interpolation + filter: <input type="radio" ng-model="benchmarkType" value="interpolationFilter"></div>
|
||||
<div>ngModel (const name): <input type="radio" ng-model="benchmarkType" value="ngModelConstName"></div>
|
||||
<div>ngModel (interp name): <input type="radio" ng-model="benchmarkType" value="ngModelInterpName"></div>
|
||||
|
||||
<ng-switch on="benchmarkType">
|
||||
<baseline-binding-table ng-switch-when="baselineBinding">
|
||||
@@ -38,7 +35,7 @@
|
||||
</div>
|
||||
<div ng-switch-when="ngBindOnce">
|
||||
<h2>baseline binding once</h2>
|
||||
<div ng-repeat="row in ::data">
|
||||
<div ng-repeat="row in data">
|
||||
<span ng-repeat="column in ::row">
|
||||
<span ng-bind="::column.i"></span>:<span ng-bind="::column.j"></span>|
|
||||
</span>
|
||||
@@ -50,12 +47,6 @@
|
||||
<span ng-repeat="column in row">{{column.i}}:{{column.j}}|</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-when="bindOnceInterpolation">
|
||||
<h2>baseline one-time interpolation</h2>
|
||||
<div ng-repeat="row in ::data">
|
||||
<span ng-repeat="column in ::row">{{::column.i}}:{{::column.j}}|</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-when="interpolationAttr">
|
||||
<h2>attribute interpolation</h2>
|
||||
<div ng-repeat="row in data">
|
||||
@@ -86,20 +77,6 @@
|
||||
<span ng-repeat="column in row">{{column.i | noop}}:{{column.j | noop}}|</span>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-when="ngModelConstName">
|
||||
<h2>ngModel (const name)</h2>
|
||||
<div ng-repeat="row in data">
|
||||
<input type="text" ng-model="row.i" name="constName" />
|
||||
<input type="text" ng-model="row.j" />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-when="ngModelInterpName">
|
||||
<h2>ngModel (interp name)</h2>
|
||||
<div ng-repeat="(rowIdx, row) in data">
|
||||
<input type="text" ng-model="row.i" name="input-{{rowIdx}}" />
|
||||
<input type="text" ng-model="row.j" name="input2-{{rowIdx}}" />
|
||||
</div>
|
||||
</div>
|
||||
</ng-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
/* globals angular, benchmarkSteps */
|
||||
|
||||
var app = angular.module('ngOptionsBenchmark', []);
|
||||
|
||||
app.config(function($compileProvider) {
|
||||
if ($compileProvider.debugInfoEnabled) {
|
||||
$compileProvider.debugInfoEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.controller('DataController', function($scope, $element) {
|
||||
$scope.items = [];
|
||||
$scope.count = 10000;
|
||||
|
||||
function changeOptions() {
|
||||
$scope.items = [];
|
||||
for (var i = 0; i < $scope.count; ++i) {
|
||||
$scope.items.push({
|
||||
id: i,
|
||||
label: 'item-' + i,
|
||||
group: 'group-' + i % 100
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var selectElement = $element.find('select');
|
||||
console.log(selectElement);
|
||||
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'add-options',
|
||||
fn: function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.count = 10000;
|
||||
changeOptions();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'set-model-1',
|
||||
fn: function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.x = $scope.items[1000];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'set-model-2',
|
||||
fn: function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.x = $scope.items[10];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'remove-options',
|
||||
fn: function() {
|
||||
$scope.count = 100;
|
||||
changeOptions();
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'add-options',
|
||||
fn: function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.count = 10000;
|
||||
changeOptions();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'set-view-1',
|
||||
fn: function() {
|
||||
selectElement.val('2000');
|
||||
selectElement.triggerHandler('change');
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'set-view-2',
|
||||
fn: function() {
|
||||
selectElement.val('1000');
|
||||
selectElement.triggerHandler('change');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [ {
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},
|
||||
{
|
||||
src: 'app.js',
|
||||
}]
|
||||
});
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
<div ng-app="ngOptionsBenchmark" ng-cloak>
|
||||
<div ng-controller="DataController">
|
||||
<div class="container-fluid">
|
||||
<p>
|
||||
Tests the execution of ng-options for rendering during model and option updates.
|
||||
</p>
|
||||
<select ng-model="x" ng-options="a as a.label group by a.group for a in items track by a.id"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,10 +103,10 @@ then(function (tags) {
|
||||
sort(semver.rcompare);
|
||||
}).
|
||||
then(function (tags) {
|
||||
var major = tags[0].split('.')[0];
|
||||
var major = tags[0].split('.')[0] + '.x';
|
||||
return tags.
|
||||
filter(function (ver) {
|
||||
return semver(ver).major == major;
|
||||
return semver.satisfies(ver, major);
|
||||
});
|
||||
}).
|
||||
then(function (tags) {
|
||||
|
||||
@@ -9,11 +9,3 @@
|
||||
ng\:form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ng-animate-shim {
|
||||
visibility:hidden;
|
||||
}
|
||||
|
||||
.ng-anchor {
|
||||
position:absolute;
|
||||
}
|
||||
|
||||
@@ -583,12 +583,6 @@ ul.events > li {
|
||||
margin-bottom:40px;
|
||||
}
|
||||
|
||||
.definition-table td {
|
||||
padding: 8px;
|
||||
border: 1px solid #eee;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 769px) and (max-width: 991px) {
|
||||
.main-body-grid {
|
||||
margin-top: 160px;
|
||||
@@ -701,7 +695,3 @@ ul.events > li {
|
||||
padding-bottom:0px;
|
||||
}
|
||||
}
|
||||
|
||||
iframe[name="example-anchoringExample"] {
|
||||
height:400px;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ angular.module('tutorials', [])
|
||||
'step': '@docTutorialReset'
|
||||
},
|
||||
template:
|
||||
'<p><button class="btn" ng-click="show=!show">Workspace Reset Instructions ➤</button></p>\n' +
|
||||
'<p><a href="" ng-click="show=!show;$event.stopPropagation()">Workspace Reset Instructions ➤</a></p>\n' +
|
||||
'<div class="alert alert-info" ng-show="show">\n' +
|
||||
' <p>Reset the workspace to step {{step}}.</p>' +
|
||||
' <p><pre>git checkout -f step-{{step}}</pre></p>\n' +
|
||||
@@ -43,7 +43,7 @@ angular.module('tutorials', [])
|
||||
'<a href="http://angular.github.io/angular-phonecat/step-{{step}}/app">Step {{step}} Live Demo</a>.</p>\n' +
|
||||
'</div>\n' +
|
||||
'<p>The most important changes are listed below. You can see the full diff on ' +
|
||||
'<a ng-href="https://github.com/angular/angular-phonecat/compare/step-{{step ? (step - 1): \'0~1\'}}...step-{{step}}" title="See diff on Github">GitHub</a>\n' +
|
||||
'<a ng-href="https://github.com/angular/angular-phonecat/compare/step-{{step ? (step - 1): \'0~1\'}}...step-{{step}}">GitHub</a>\n' +
|
||||
'</p>'
|
||||
};
|
||||
});
|
||||
@@ -21,13 +21,11 @@ angular.module('versions', [])
|
||||
};
|
||||
|
||||
$scope.jumpToDocsVersion = function(version) {
|
||||
var currentPagePath = $location.path().replace(/\/$/, ''),
|
||||
url = '';
|
||||
if (version.isOldDocsUrl) {
|
||||
url = version.docsUrl;
|
||||
}else{
|
||||
url = version.docsUrl + currentPagePath;
|
||||
}
|
||||
$window.location = url;
|
||||
var currentPagePath = $location.path().replace(/\/$/, '');
|
||||
|
||||
// TODO: We need to do some munging of the path for different versions of the API...
|
||||
|
||||
|
||||
$window.location = version.docsUrl + currentPagePath;
|
||||
};
|
||||
}]);
|
||||
|
||||
+6
-11
@@ -6,18 +6,18 @@ var packagePath = __dirname;
|
||||
var Package = require('dgeni').Package;
|
||||
|
||||
// Create and export a new Dgeni package called angularjs. This package depends upon
|
||||
// the ngdoc, nunjucks, and examples packages defined in the dgeni-packages npm module.
|
||||
// the ngdoc,nunjucks and examples packages defined in the dgeni-packages npm module.
|
||||
module.exports = new Package('angularjs', [
|
||||
require('dgeni-packages/ngdoc'),
|
||||
require('dgeni-packages/nunjucks'),
|
||||
require('dgeni-packages/examples'),
|
||||
require('dgeni-packages/git')
|
||||
require('dgeni-packages/examples')
|
||||
])
|
||||
|
||||
|
||||
.factory(require('./services/errorNamespaceMap'))
|
||||
.factory(require('./services/getMinerrInfo'))
|
||||
.factory(require('./services/getVersion'))
|
||||
.factory(require('./services/gitData'))
|
||||
|
||||
.factory(require('./services/deployments/debug'))
|
||||
.factory(require('./services/deployments/default'))
|
||||
@@ -26,6 +26,7 @@ module.exports = new Package('angularjs', [
|
||||
|
||||
.factory(require('./inline-tag-defs/type'))
|
||||
|
||||
|
||||
.processor(require('./processors/error-docs'))
|
||||
.processor(require('./processors/index-page'))
|
||||
.processor(require('./processors/keywords'))
|
||||
@@ -124,16 +125,10 @@ module.exports = new Package('angularjs', [
|
||||
});
|
||||
|
||||
computeIdsProcessor.idTemplates.push({
|
||||
docTypes: ['error'],
|
||||
getId: function(doc) { return 'error:' + doc.namespace + ':' + doc.name; },
|
||||
getAliases: function(doc) { return [doc.name, doc.namespace + ':' + doc.name, doc.id]; }
|
||||
},
|
||||
{
|
||||
docTypes: ['errorNamespace'],
|
||||
docTypes: ['error', 'errorNamespace'],
|
||||
getId: function(doc) { return 'error:' + doc.name; },
|
||||
getAliases: function(doc) { return [doc.id]; }
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
|
||||
.config(function(checkAnchorLinksProcessor) {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
var versionInfo = require('../../../lib/versions/version-info');
|
||||
|
||||
/**
|
||||
* @dgService gitData
|
||||
* @description
|
||||
* Information from the local git repository
|
||||
*/
|
||||
module.exports = function gitData() {
|
||||
return {
|
||||
version: versionInfo.currentVersion,
|
||||
versions: versionInfo.previousVersions,
|
||||
info: versionInfo.gitRepoInfo
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
{% extends "base.template.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Error: {$ doc.namespace $}:{$ doc.name $}
|
||||
<h1>Error: {$ doc.id $}
|
||||
<div><span class='hint'>{$ doc.fullName $}</span></div>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="Description"
|
||||
content="AngularJS is what HTML would have been, had it been designed for building web-apps.
|
||||
Declarative templates with data-binding, MVC, dependency injection and great
|
||||
@@ -76,7 +76,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-9 header-branding">
|
||||
<a class="brand navbar-brand" href="http://angularjs.org">
|
||||
<img width="117" height="30" class="logo" alt="Link to Angular JS Homepage" ng-src="img/angularjs-for-header-only.svg">
|
||||
<img width="117" height="30" class="logo" ng-src="img/angularjs-for-header-only.svg">
|
||||
</a>
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="divider-vertical"></li>
|
||||
@@ -220,10 +220,10 @@
|
||||
<p class="pull-right"><a back-to-top>Back to top</a></p>
|
||||
|
||||
<p>
|
||||
Super-powered by Google ©2010-2015
|
||||
Super-powered by Google ©2010-2014
|
||||
( <a id="version"
|
||||
ng-href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md#{{versionNumber}}"
|
||||
ng-bind-template="v{{version}}" title="Changelog of this version of Angular JS">
|
||||
ng-bind-template="v{{version}}">
|
||||
</a>
|
||||
)
|
||||
</p>
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
{% macro typeList(types) -%}
|
||||
{% for typeName in types %}<a href="" class="{$ typeName | typeClass $}">{$ typeName | escape $}</a>{% endfor %}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro paramTable(params) %}
|
||||
<table class="variables-matrix input-arguments">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for param in params %}
|
||||
<tr>
|
||||
<td>
|
||||
{$ param.name $}
|
||||
{% if param.alias %}| {$ param.alias $}{% endif %}
|
||||
{% if param.optional %}<div><em>(optional)</em></div>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{$ typeList(param.typeList) $}
|
||||
</td>
|
||||
<td>
|
||||
{$ param.description | marked $}
|
||||
{% if param.defaultValue %}<p><em>(default: {$ param.defaultValue $})</em></p>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endmacro -%}
|
||||
|
||||
|
||||
{%- macro directiveParam(name, type, join, sep) %}
|
||||
{%- if type.optional %}[{% endif -%}
|
||||
{$ name | dashCase $}{$ join $}{$ type.name $}{$ sep $}
|
||||
{%- if type.optional %}]{% endif -%}
|
||||
{% endmacro -%}
|
||||
|
||||
{%- macro functionSyntax(fn) %}
|
||||
{%- set sep = joiner(', ') -%}
|
||||
{% marked -%}
|
||||
`{$ fn.name $}({%- for param in fn.params %}{$ sep() $}
|
||||
{%- if param.type.optional %}[{% endif -%}
|
||||
{$ param.name $}
|
||||
{%- if param.type.optional %}]{% endif -%}
|
||||
{% endfor %});`
|
||||
{%- endmarked %}
|
||||
{% endmacro -%}
|
||||
|
||||
{%- macro typeInfo(fn) -%}
|
||||
<table class="variables-matrix return-arguments">
|
||||
<tr>
|
||||
<td>{$ typeList(fn.typeList) $}</td>
|
||||
<td>{$ fn.description | marked $}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{%- endmacro -%}
|
||||
@@ -140,7 +140,7 @@ or JavaScript callbacks.
|
||||
{@link ngAnimate#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
Use {@link ng.$animate $animate} to trigger animation operations within your directive code.
|
||||
Use {@link ngAnimate.$animate $animate} to trigger animation operations within your directive code.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $animate:nocb
|
||||
@fullName Do not pass a callback to animate methods
|
||||
@description
|
||||
|
||||
Since Angular 1.3, the methods of {@link ng.$animate} do not accept a callback as the last parameter.
|
||||
Instead, they return a promise to which you can attach `then` handlers to be run when the animation completes.
|
||||
|
||||
If you are getting this error then you need to update your code to use the promise-based API.
|
||||
|
||||
See https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9 for information about
|
||||
the change to the animation API and the changes you need to make.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:baddir
|
||||
@fullName Invalid Directive Name
|
||||
@description
|
||||
|
||||
This error occurs when the name of a directive is not valid.
|
||||
|
||||
Directives must start with a lowercase character and must not contain leading or trailing whitespaces.
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:noctrl
|
||||
@fullName Controller is required.
|
||||
@description
|
||||
|
||||
When using the `bindToController` feature of AngularJS, a directive is required
|
||||
to have a Controller. A controller may be specified by adding a "controller"
|
||||
property to the directive definition object. Its value should be either a
|
||||
string, or an invokable object (a function, or an array whose last element is a
|
||||
function).
|
||||
|
||||
For more information, see the {@link guide/directive directives guide}.
|
||||
@@ -1,71 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:noident
|
||||
@fullName Controller identifier is required.
|
||||
@description
|
||||
|
||||
When using the `bindToController` feature of AngularJS, a directive is required
|
||||
to have a Controller identifier, which is initialized in scope with the value of
|
||||
the controller instance. This can be supplied using the "controllerAs" property
|
||||
of the directive object, or alternatively by adding " as IDENTIFIER" to the controller
|
||||
name.
|
||||
|
||||
For example, the following directives are valid:
|
||||
|
||||
```js
|
||||
// OKAY, because controller is a string with an identifier component.
|
||||
directive("okay", function() {
|
||||
return {
|
||||
bindToController: true,
|
||||
controller: "myCtrl as $ctrl"
|
||||
scope: {
|
||||
text: "@text"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
// OKAY, because the directive uses the controllerAs property to override
|
||||
// the controller identifier.
|
||||
directive("okay2", function() {
|
||||
return {
|
||||
bindToController: true,
|
||||
controllerAs: "$ctrl",
|
||||
controller: function() {
|
||||
|
||||
},
|
||||
scope: {
|
||||
text: "@text"
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
While the following are invalid:
|
||||
|
||||
```js
|
||||
// BAD, because the controller property is a string with no identifier.
|
||||
directive("bad", function() {
|
||||
return {
|
||||
bindToController: true,
|
||||
controller: "noIdentCtrl",
|
||||
scope: {
|
||||
text: "@text"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
// BAD because the controller is not a string (therefore has no identifier),
|
||||
// and there is no controllerAs property.
|
||||
directive("bad2", function() {
|
||||
return {
|
||||
bindToController: true,
|
||||
controller: function noControllerAs() {
|
||||
|
||||
},
|
||||
scope: {
|
||||
text: "@text"
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
@@ -36,25 +36,9 @@ Following are invalid uses of this directive:
|
||||
```
|
||||
|
||||
|
||||
To resolve this error, do one of the following options:
|
||||
|
||||
- use path expressions with scope properties that are two-way data-bound like so:
|
||||
|
||||
To resolve this error, always use path expressions with scope properties that are two-way data-bound:
|
||||
```
|
||||
<my-directive bind="some.property">
|
||||
<my-directive bind="some[3]['property']">
|
||||
```
|
||||
|
||||
- Make the binding optional
|
||||
|
||||
```
|
||||
myModule.directive('myDirective', function factory() {
|
||||
return {
|
||||
...
|
||||
scope: {
|
||||
localValue: '=?bind' // <-- the '?' makes it optional
|
||||
}
|
||||
...
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
@@ -69,15 +69,3 @@ angular.module('myModule', [])
|
||||
```
|
||||
|
||||
Use the `$controller` service if you want to instantiate controllers yourself.
|
||||
|
||||
Attempting to inject a scope object into anything that's not a controller or a directive,
|
||||
for example a service, will also throw an `Unknown provider: $scopeProvider <- $scope` error.
|
||||
This might happen if one mistakenly registers a controller as a service, ex.:
|
||||
|
||||
```
|
||||
angular.module('myModule', [])
|
||||
.service('MyController', ['$scope', function($scope) {
|
||||
// This controller throws an unknown provider error because
|
||||
// a scope object cannot be injected into a service.
|
||||
}]);
|
||||
```
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:badexpr
|
||||
@fullName Expecting end operator
|
||||
@description
|
||||
|
||||
The Angular expression is missing the corresponding closing operator.
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:dupvalue
|
||||
@fullName Duplicate choice in plural/select
|
||||
@description
|
||||
|
||||
You have repeated a match selection for your plural or select MessageFormat
|
||||
extension in your interpolation expression. The different choices have to be unique.
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:logicbug
|
||||
@fullName Bug in ngMessageFormat module
|
||||
@description
|
||||
|
||||
You've just hit a bug in the ngMessageFormat module provided by angular-message-format.min.js.
|
||||
Please file a github issue for this and provide the interpolation text that caused you to hit this
|
||||
bug mentioning the exact version of AngularJS used and we will fix it!
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,17 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:nochgmustache
|
||||
@fullName Redefinition of start/endSymbol incompatible with MessageFormat extensions
|
||||
@description
|
||||
|
||||
You have redefined `$interpolate.startSymbol`/`$interpolate.endSymbol` and also
|
||||
loaded the `ngMessageFormat` module (provided by angular-message-format.min.js)
|
||||
while creating your injector.
|
||||
|
||||
`ngMessageFormat` currently does not support redefinition of the
|
||||
startSymbol/endSymbol used by `$interpolate`. If this is affecting you, please
|
||||
file an issue and mention @chirayuk on it. This is intended to be fixed in a
|
||||
future commit and the github issue will help gauge urgency.
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:reqarg
|
||||
@fullName Missing required argument for MessageFormat
|
||||
@description
|
||||
|
||||
You must specify the MessageFormat function that you're using right after the
|
||||
comma following the Angular expression. Currently, the supported functions are
|
||||
"plural" and "select" (for gender selections.)
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:reqcomma
|
||||
@fullName Missing comma following MessageFormat plural/select keyword
|
||||
@description
|
||||
|
||||
The MessageFormat syntax requires a comma following the "plural" or "select"
|
||||
extension keyword in the extended interpolation syntax.
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:reqendbrace
|
||||
@fullName Unterminated message for plural/select value
|
||||
@description
|
||||
|
||||
The plural or select message for a value or keyword choice has no matching end
|
||||
brace to mark the end of the message.
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,6 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:reqendinterp
|
||||
@fullName Unterminated interpolation
|
||||
@description
|
||||
|
||||
The interpolation text does not have an ending `endSymbol` ("}}" by default) and is unterminated.
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:reqopenbrace
|
||||
@fullName An opening brace was expected but not found
|
||||
@description
|
||||
|
||||
The plural or select extension keyword or values (such as "other", "male",
|
||||
"female", "=0", "one", "many", etc.) MUST be followed by a message enclosed in
|
||||
braces.
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,13 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:reqother
|
||||
@fullName Required choice "other" for select/plural in MessageFormat
|
||||
@description
|
||||
|
||||
Your interpolation expression with a MessageFormat extension for either
|
||||
"plural" or "select" (typically used for gender selection) does not contain a
|
||||
message for the choice "other". Using either select or plural MessageFormat
|
||||
extensions require that you provide a message for the selection "other".
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:unknarg
|
||||
@fullName Unrecognized MessageFormat extension
|
||||
@description
|
||||
|
||||
The MessageFormat extensions provided by `ngMessageFormat` are currently
|
||||
limited to "plural" and "select". The extension that you have used is either
|
||||
unsupported or invalid.
|
||||
|
||||
For more information about the MessageFormat syntax in interpolation
|
||||
expressions, please refer to MessageFormat extensions section at
|
||||
{@link guide/i18n#MessageFormat Angular i18n MessageFormat}
|
||||
@@ -1,10 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:unsafe
|
||||
@fullName MessageFormat extensions not allowed in secure context
|
||||
@description
|
||||
|
||||
You have attempted to use a MessageFormat extension in your interpolation expression that is marked as a secure context. For security purposes, this is not supported.
|
||||
|
||||
Read more about secure contexts at {@link ng.$sce Strict Contextual Escaping
|
||||
(SCE)} and about the MessageFormat extensions at {@link
|
||||
guide/i18n#MessageFormat Angular i18n MessageFormat}.
|
||||
@@ -1,6 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:untermstr
|
||||
@fullName Unterminated string literal
|
||||
@description
|
||||
|
||||
The string literal was not terminated in your Angular expression.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:wantstring
|
||||
@fullName Expected the beginning of a string
|
||||
@description
|
||||
|
||||
We expected to see the beginning of a string (either a single quote or a double
|
||||
quote character) in the expression but it was not found. The expression is
|
||||
invalid. If this is incorrect, please file an issue on github.
|
||||
@@ -35,7 +35,7 @@ URL of the subcontext:
|
||||
|
||||
```html
|
||||
<head>
|
||||
<base href="/subapp/">
|
||||
<base href="/subapp">
|
||||
...
|
||||
</head>
|
||||
```
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
@ngdoc error
|
||||
@name filter:notarray
|
||||
@fullName Not an array
|
||||
@description
|
||||
|
||||
This error occurs when {@link ng.filter filter} is not used with an array:
|
||||
```html
|
||||
<input ng-model="search">
|
||||
<div ng-repeat="(key, value) in myObj | filter:search">
|
||||
{{ key }} : {{ value }}
|
||||
</div>
|
||||
```
|
||||
|
||||
Filter must be used with an array so a subset of items can be returned.
|
||||
The array can be initialized asynchronously and therefore null or undefined won't throw this error.
|
||||
|
||||
To filter an object by the value of its properties you can create your own custom filter:
|
||||
```js
|
||||
angular.module('customFilter',[])
|
||||
.filter('custom', function() {
|
||||
return function(input, search) {
|
||||
if (!input) return input;
|
||||
if (!search) return input;
|
||||
var expected = ('' + search).toLowerCase();
|
||||
var result = {};
|
||||
angular.forEach(input, function(value, key) {
|
||||
var actual = ('' + value).toLowerCase();
|
||||
if (actual.indexOf(expected) !== -1) {
|
||||
result[key] = value;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
});
|
||||
```
|
||||
That can be used as:
|
||||
```html
|
||||
<input ng-model="search">
|
||||
<div ng-repeat="(key, value) in myObj | custom:search">
|
||||
{{ key }} : {{ value }}
|
||||
</div>
|
||||
```
|
||||
|
||||
You could as well convert the object to an array using a filter such as
|
||||
[toArrayFilter](https://github.com/petebacondarwin/angular-toArrayFilter):
|
||||
```html
|
||||
<input ng-model="search">
|
||||
<div ng-repeat="item in myObj | toArray:false | filter:search">
|
||||
{{ item }}
|
||||
</div>
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ng:cpta
|
||||
@fullName Copying TypedArray
|
||||
@description
|
||||
|
||||
Copying TypedArray's with a destination is not supported because TypedArray
|
||||
objects can not be mutated, they are fixed length.
|
||||
@@ -1,56 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngModel:numfmt
|
||||
@fullName Model is not of type `number`
|
||||
@description
|
||||
|
||||
The number input directive `<input type="number">` requires the model to be a `number`.
|
||||
|
||||
If the model is something else, this error will be thrown.
|
||||
|
||||
Angular does not set validation errors on the `<input>` in this case
|
||||
as this error is caused by incorrect application logic and not by bad input from the user.
|
||||
|
||||
If your model does not contain actual numbers then it is up to the application developer
|
||||
to use a directive that will do the conversion in the `ngModel` `$formatters` and `$parsers`
|
||||
pipeline.
|
||||
|
||||
## Example
|
||||
|
||||
In this example, our model stores the number as a string, so we provide the `stringToNumber`
|
||||
directive to convert it into the format the `input[number]` directive expects.
|
||||
|
||||
|
||||
<example module="numfmt-error-module">
|
||||
<file name="index.html">
|
||||
<table>
|
||||
<tr ng-repeat="x in ['0', '1']">
|
||||
<td>
|
||||
<input type="number" string-to-number ng-model="x" /> {{ x }} : {{ typeOf(x) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</file>
|
||||
<file name="app.js">
|
||||
angular.module('numfmt-error-module', [])
|
||||
|
||||
.run(function($rootScope) {
|
||||
$rootScope.typeOf = function(value) {
|
||||
return typeof value;
|
||||
};
|
||||
})
|
||||
|
||||
.directive('stringToNumber', function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, element, attrs, ngModel) {
|
||||
ngModel.$parsers.push(function(value) {
|
||||
return '' + value;
|
||||
});
|
||||
ngModel.$formatters.push(function(value) {
|
||||
return parseFloat(value, 10);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
@@ -165,7 +165,7 @@ encoded.
|
||||
|
||||
`$location` service has two configuration modes which control the format of the URL in the browser
|
||||
address bar: **Hashbang mode** (the default) and the **HTML5 mode** which is based on using the
|
||||
[HTML5 History API](https://html.spec.whatwg.org/multipage/browsers.html#the-history-interface). Applications use the same API in
|
||||
HTML5 [History API](http://www.w3.org/TR/html5/introduction.html#history-0). Applications use the same API in
|
||||
both modes and the `$location` service will work with appropriate URL segments and browser APIs to
|
||||
facilitate the browser URL change and history management.
|
||||
|
||||
@@ -693,7 +693,7 @@ A path should always begin with forward slash (`/`); the `$location.path()` sett
|
||||
forward slash if it is missing.
|
||||
|
||||
Note that the `!` prefix in the hashbang mode is not part of `$location.path()`; it is actually
|
||||
`hashPrefix`.
|
||||
hashPrefix.
|
||||
|
||||
## Crawling your app
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Currently, ngAria interfaces with the following directives:
|
||||
|
||||
Most of ngAria's heavy lifting happens in the {@link ngModel ngModel}
|
||||
directive. For elements using ngModel, special attention is paid by ngAria if that element also
|
||||
has a role or type of `checkbox`, `radio`, `range` or `textbox`.
|
||||
has a a role or type of `checkbox`, `radio`, `range` or `textbox`.
|
||||
|
||||
For those elements using ngModel, ngAria will dynamically bind and update the following ARIA
|
||||
attributes (if they have not been explicitly specified by the developer):
|
||||
@@ -235,7 +235,7 @@ Becomes:
|
||||
|
||||
The new ngMessages module makes it easy to display form validation or other messages with priority
|
||||
sequencing and animation. To expose these visual messages to screen readers,
|
||||
ngAria injects `aria-live="assertive"`, causing them to be read aloud any time a message is shown,
|
||||
ngAria injects `aria-live="polite"`, causing them to be read aloud any time a message is shown,
|
||||
regardless of the user's focus location.
|
||||
###Example
|
||||
|
||||
@@ -249,7 +249,7 @@ regardless of the user's focus location.
|
||||
Becomes:
|
||||
|
||||
```html
|
||||
<div ng-messages="myForm.myName.$error" aria-live="assertive">
|
||||
<div ng-messages="myForm.myName.$error" aria-live="polite">
|
||||
<div ng-message="required">You did not enter a field</div>
|
||||
<div ng-message="maxlength">Your field is too long</div>
|
||||
</div>
|
||||
|
||||
@@ -253,7 +253,7 @@ The table below explains in detail which animation events are triggered
|
||||
| {@link ng.directive:ngClass#animations ngClass or {{class}}} | add and remove |
|
||||
| {@link ng.directive:ngShow#animations ngShow & ngHide} | add and remove (the ng-hide class value) |
|
||||
|
||||
For a full breakdown of the steps involved during each animation event, refer to the {@link ng.$animate API docs}.
|
||||
For a full breakdown of the steps involved during each animation event, refer to the {@link ngAnimate.$animate API docs}.
|
||||
|
||||
## How do I use animations in my own directives?
|
||||
|
||||
@@ -276,6 +276,6 @@ myModule.directive('my-directive', ['$animate', function($animate) {
|
||||
|
||||
## More about animations
|
||||
|
||||
For a full breakdown of each method available on `$animate`, see the {@link ng.$animate API documentation}.
|
||||
For a full breakdown of each method available on `$animate`, see the {@link ngAnimate.$animate API documentation}.
|
||||
|
||||
To see a complete demo, see the {@link tutorial/step_12 animation step within the AngularJS phonecat tutorial}.
|
||||
|
||||
@@ -55,11 +55,11 @@ Try out the Live Preview above, and then let's walk through the example and desc
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding1.png">
|
||||
|
||||
This looks like normal HTML, with some new markup. In Angular, a file like this is called a
|
||||
<a name="template">{@link templates template}</a>. When Angular starts your application, it parses and
|
||||
processes this new markup from the template using the <a name="compiler">{@link compiler compiler}</a>.
|
||||
The loaded, transformed and rendered DOM is then called the <a name="view"></a>*view*.
|
||||
<a name="template">"{@link templates template}"</a>. When Angular starts your application, it parses and
|
||||
processes this new markup from the template using the so-called <a name="compiler">"{@link compiler compiler}"</a>.
|
||||
The loaded, transformed and rendered DOM is then called the <a name="view">"view"</a>.
|
||||
|
||||
The first kind of new markup are the <a name="directive">{@link directive directives}</a>.
|
||||
The first kind of new markup are the so-called <a name="directive">"{@link directive directives}"</a>.
|
||||
They apply special behavior to attributes or elements in the HTML. In the example above we use the
|
||||
{@link ng.directive:ngApp `ng-app`} attribute, which is linked to a directive that automatically
|
||||
initializes our application. Angular also defines a directive for the {@link ng.directive:input `input`}
|
||||
@@ -75,16 +75,16 @@ 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
|
||||
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.
|
||||
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*
|
||||
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">"model"</a>
|
||||
in the rest of the documentation.
|
||||
Applied to the example above, the markup directs Angular to "take the data we got from the input widgets
|
||||
and multiply them together".
|
||||
|
||||
The example above also contains a <a name="filter">{@link guide/filter filter}</a>.
|
||||
The example above also contains a <a name="filter">"{@link guide/filter filter}"</a>.
|
||||
A filter formats the value of an expression for display to the user.
|
||||
In the example above, the filter {@link ng.filter:currency `currency`} formats a number
|
||||
into an output that looks like money.
|
||||
@@ -92,7 +92,7 @@ into an output that looks like money.
|
||||
The important thing in the example is that Angular provides _live_ bindings:
|
||||
Whenever the input values change, the value of the expressions are automatically
|
||||
recalculated and the DOM is updated with their values.
|
||||
The concept behind this is <a name="databinding">{@link databinding two-way data binding}</a>.
|
||||
The concept behind this is <a name="databinding">"{@link databinding two-way data binding}"</a>.
|
||||
|
||||
|
||||
## Adding UI logic: Controllers
|
||||
@@ -150,7 +150,7 @@ different currencies and also pay the invoice.
|
||||
|
||||
What changed?
|
||||
|
||||
First, there is a new JavaScript file that contains a <a name="controller">{@link controller controller}</a>.
|
||||
First, there is a new JavaScript file that contains a so-called <a name="controller">"{@link controller controller}"</a>.
|
||||
More exactly, the file contains a constructor function that creates the actual controller instance.
|
||||
The purpose of controllers is to expose variables and functionality to expressions and directives.
|
||||
|
||||
@@ -255,15 +255,15 @@ We moved the `convertCurrency` function and the definition of the existing curre
|
||||
into the new file `finance2.js`. But how does the controller
|
||||
get a hold of the now separated function?
|
||||
|
||||
This is where <a name="di">{@link di Dependency Injection}</a> comes into play.
|
||||
This is where <a name="di">"{@link di Dependency Injection}"</a> comes into play.
|
||||
Dependency Injection (DI) is a software design pattern that
|
||||
deals with how objects and functions get created and how they get a hold of their dependencies.
|
||||
Everything within Angular (directives, filters, controllers,
|
||||
services, ...) is created and wired using dependency injection. Within Angular,
|
||||
the DI container is called the <a name="injector">{@link di injector}</a>.
|
||||
the DI container is called the <a name="injector">"{@link di injector}"</a>.
|
||||
|
||||
To use DI, there needs to be a place where all the things that should work together are registered.
|
||||
In Angular, this is the purpose of the <a name="module">{@link module modules}</a>.
|
||||
In Angular, this is the purpose of the so-called <a name="module">"{@link module modules}"</a>.
|
||||
When Angular starts, it will use the configuration of the module with the name defined by the `ng-app` directive,
|
||||
including the configuration of all modules that this module depends on.
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ Do not use controllers to:
|
||||
services} instead.
|
||||
- Manage the life-cycle of other components (for example, to create service instances).
|
||||
|
||||
## Setting up the initial state of a `$scope` object
|
||||
# Setting up the initial state of a `$scope` object
|
||||
|
||||
Typically, when you create an application you need to set up the initial state for the Angular
|
||||
`$scope`. You set up the initial state of a scope by attaching properties to the `$scope` object.
|
||||
The properties contain the **view model** (the model that will be presented by the view). All the
|
||||
`$scope` properties will be available to the {@link templates template} at the point in the DOM where the Controller
|
||||
`$scope` properties will be available to the template at the point in the DOM where the Controller
|
||||
is registered.
|
||||
|
||||
The following example demonstrates creating a `GreetingController`, which attaches a `greeting`
|
||||
@@ -69,13 +69,13 @@ now be data-bound to the template:
|
||||
```
|
||||
|
||||
|
||||
## Adding Behavior to a Scope Object
|
||||
# Adding Behavior to a Scope Object
|
||||
|
||||
In order to react to events or execute computation in the view we must provide behavior to the
|
||||
scope. We add behavior to the scope by attaching methods to the `$scope` object. These methods are
|
||||
then available to be called from the template/view.
|
||||
|
||||
The following example uses a Controller to add a method, which doubles a number, to the scope:
|
||||
The following example uses a Controller to add a method to the scope, which doubles a number:
|
||||
|
||||
```js
|
||||
var myApp = angular.module('myApp',[]);
|
||||
@@ -99,7 +99,7 @@ objects (or primitives) assigned to the scope become model properties. Any metho
|
||||
the scope are available in the template/view, and can be invoked via angular expressions
|
||||
and `ng` event handler directives (e.g. {@link ng.directive:ngClick ngClick}).
|
||||
|
||||
## Using Controllers Correctly
|
||||
# Using Controllers Correctly
|
||||
|
||||
In general, a Controller shouldn't try to do too much. It should contain only the business logic
|
||||
needed for a single view.
|
||||
@@ -125,7 +125,7 @@ following components:
|
||||
- A model consisting of a string named `spice`
|
||||
- A Controller with two functions that set the value of `spice`
|
||||
|
||||
The message in our template contains a binding to the `spice` model which, by default, is set to the
|
||||
The message in our template contains a binding to the `spice` model, which by default is set to the
|
||||
string "very". Depending on which button is clicked, the `spice` model is set to `chili` or
|
||||
`jalapeño`, and the message is automatically updated by data-binding.
|
||||
|
||||
@@ -259,7 +259,7 @@ Inheritance works with methods in the same way as it does with properties. So in
|
||||
examples, all of the properties could be replaced with methods that return string values.
|
||||
|
||||
|
||||
# Testing Controllers
|
||||
## Testing Controllers
|
||||
|
||||
Although there are many ways to test a Controller, one of the best conventions, shown below,
|
||||
involves injecting the {@link ng.$rootScope $rootScope} and {@link ng.$controller $controller}:
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
@sortOrder 210
|
||||
@description
|
||||
|
||||
# Data Binding
|
||||
|
||||
Data-binding in Angular apps is the automatic synchronization of data between the model and view
|
||||
components. The way that Angular implements data-binding lets you treat the model as the
|
||||
single-source-of-truth in your application. The view is a projection of the model at all times.
|
||||
|
||||
@@ -51,7 +51,7 @@ In the following example, we say that the `<input>` element **matches** the `ngM
|
||||
The following also **matches** `ngModel`:
|
||||
|
||||
```html
|
||||
<input data-ng-model="foo">
|
||||
<input data-ng:model="foo">
|
||||
```
|
||||
|
||||
### Normalization
|
||||
@@ -831,39 +831,37 @@ element?
|
||||
<file name="script.js">
|
||||
angular.module('dragModule', [])
|
||||
.directive('myDraggable', ['$document', function($document) {
|
||||
return {
|
||||
link: function(scope, element, attr) {
|
||||
var startX = 0, startY = 0, x = 0, y = 0;
|
||||
return function(scope, element, attr) {
|
||||
var startX = 0, startY = 0, x = 0, y = 0;
|
||||
|
||||
element.css({
|
||||
position: 'relative',
|
||||
border: '1px solid red',
|
||||
backgroundColor: 'lightgrey',
|
||||
cursor: 'pointer'
|
||||
});
|
||||
|
||||
element.on('mousedown', function(event) {
|
||||
// Prevent default dragging of selected content
|
||||
event.preventDefault();
|
||||
startX = event.pageX - x;
|
||||
startY = event.pageY - y;
|
||||
$document.on('mousemove', mousemove);
|
||||
$document.on('mouseup', mouseup);
|
||||
});
|
||||
|
||||
function mousemove(event) {
|
||||
y = event.pageY - startY;
|
||||
x = event.pageX - startX;
|
||||
element.css({
|
||||
position: 'relative',
|
||||
border: '1px solid red',
|
||||
backgroundColor: 'lightgrey',
|
||||
cursor: 'pointer'
|
||||
top: y + 'px',
|
||||
left: x + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
element.on('mousedown', function(event) {
|
||||
// Prevent default dragging of selected content
|
||||
event.preventDefault();
|
||||
startX = event.pageX - x;
|
||||
startY = event.pageY - y;
|
||||
$document.on('mousemove', mousemove);
|
||||
$document.on('mouseup', mouseup);
|
||||
});
|
||||
|
||||
function mousemove(event) {
|
||||
y = event.pageY - startY;
|
||||
x = event.pageX - startX;
|
||||
element.css({
|
||||
top: y + 'px',
|
||||
left: x + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
function mouseup() {
|
||||
$document.off('mousemove', mousemove);
|
||||
$document.off('mouseup', mouseup);
|
||||
}
|
||||
function mouseup() {
|
||||
$document.off('mousemove', mousemove);
|
||||
$document.off('mouseup', mouseup);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
@@ -28,13 +28,13 @@ Angular expressions are like JavaScript expressions with the following differenc
|
||||
|
||||
* **No Control Flow Statements:** You cannot use the following in an Angular expression:
|
||||
conditionals, loops, or exceptions.
|
||||
|
||||
|
||||
* **No Function Declarations:** You cannot declare functions in an Angular expression,
|
||||
even inside `ng-init` directive.
|
||||
|
||||
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
|
||||
|
||||
* **No RegExp Creation With Literal Notation:** You cannot create regular expressions
|
||||
in an Angular expression.
|
||||
|
||||
|
||||
* **No Comma And Void Operators:** You cannot use `,` or `void` in an Angular expression.
|
||||
|
||||
* **Filters:** You can use {@link guide/filter filters} within expressions to format data before
|
||||
@@ -175,7 +175,7 @@ expression, delegate to a JavaScript method instead.
|
||||
## No function declarations or RegExp creation with literal notation
|
||||
|
||||
You can't declare functions or create regular expressions from within AngularJS expressions. This is
|
||||
to avoid complex model transformation logic inside templates. Such logic is better placed in a
|
||||
to avoid complex model transformation logic inside templates. Such logic is better placed in a
|
||||
controller or in a dedicated filter where it can be tested properly.
|
||||
|
||||
## `$event`
|
||||
@@ -297,29 +297,25 @@ then the expression is not fulfilled and will remain watched.
|
||||
2. If V is not undefined, mark the result of the expression as stable and schedule a task
|
||||
to deregister the watch for this expression when we exit the digest loop
|
||||
3. Process the digest loop as normal
|
||||
4. When digest loop is done and all the values have settled, process the queue of watch
|
||||
deregistration tasks. For each watch to be deregistered, check if it still evaluates
|
||||
to a value that is not `undefined`. If that's the case, deregister the watch. Otherwise,
|
||||
4. When digest loop is done and all the values have settled process the queue of watch
|
||||
deregistration tasks. For each watch to be deregistered check if it still evaluates
|
||||
to value that is not `undefined`. If that's the case, deregister the watch. Otherwise
|
||||
keep dirty-checking the watch in the future digest loops by following the same
|
||||
algorithm starting from step 1
|
||||
|
||||
#### Special case for object literals
|
||||
|
||||
Unlike simple values, object-literals are watched until every key is defined.
|
||||
See http://www.bennadel.com/blog/2760-one-time-data-bindings-for-object-literal-expressions-in-angularjs-1-3.htm
|
||||
|
||||
### How to benefit from one-time binding
|
||||
|
||||
If the expression will not change once set, it is a candidate for one-time binding.
|
||||
If the expression will not change once set, it is a candidate for one-time binding.
|
||||
Here are three example cases.
|
||||
|
||||
When interpolating text or attributes:
|
||||
|
||||
```html
|
||||
<div name="attr: {{::color}}">text: {{::name | uppercase}}</div>
|
||||
<div name="attr: {{::color}}">text: {{::name}}</div>
|
||||
```
|
||||
|
||||
When using a directive with bidirectional binding and parameters that will not change:
|
||||
When using a directive with bidirectional binding and the parameters will not change:
|
||||
|
||||
```js
|
||||
someModule.directive('someDirective', function() {
|
||||
@@ -342,6 +338,7 @@ When using a directive that takes an expression:
|
||||
|
||||
```html
|
||||
<ul>
|
||||
<li ng-repeat="item in ::items | orderBy:'name'">{{item.name}};</li>
|
||||
<li ng-repeat="item in ::items">{{item.name}};</li>
|
||||
</ul>
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
@@ -92,10 +92,8 @@ means that it should be stateless and idempotent. Angular relies on these proper
|
||||
the filter only when the inputs to the function change.
|
||||
|
||||
<div class="alert alert-warning">
|
||||
**Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
|
||||
your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
|
||||
(`myapp_subsection_filterx`).
|
||||
**Note:** filter names must be valid angular expression identifiers, such as `uppercase` or `orderBy`.
|
||||
Names with special characters, such as hyphens and dots, are not allowed.
|
||||
</div>
|
||||
|
||||
The following sample filter reverses a text string. In addition, it conditionally makes the
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
@sortOrder 290
|
||||
@description
|
||||
|
||||
# Forms
|
||||
|
||||
Controls (`input`, `select`, `textarea`) are ways for a user to enter data.
|
||||
A Form is a collection of controls for the purpose of grouping related controls together.
|
||||
|
||||
@@ -16,7 +14,7 @@ be circumvented and thus can not be trusted. Server-side validation is still nec
|
||||
secure application.
|
||||
|
||||
|
||||
## Simple form
|
||||
# Simple form
|
||||
The key directive in understanding two-way data-binding is {@link ng.directive:ngModel ngModel}.
|
||||
The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view,
|
||||
as well as view to the model. In addition it provides an {@link ngModel.NgModelController API}
|
||||
@@ -64,7 +62,7 @@ For example: inputs of type `email` must have a value in the form of `user@domai
|
||||
|
||||
|
||||
|
||||
## Using CSS classes
|
||||
# Using CSS classes
|
||||
|
||||
To allow styling of form as well as controls, `ngModel` adds these CSS classes:
|
||||
|
||||
@@ -128,7 +126,7 @@ and failing to satisfy its validity.
|
||||
|
||||
|
||||
|
||||
## Binding to form and control state
|
||||
# Binding to form and control state
|
||||
|
||||
A form is an instance of {@link form.FormController FormController}.
|
||||
The form instance can optionally be published into the scope using the `name` attribute.
|
||||
@@ -210,7 +208,7 @@ didn't interact with a control
|
||||
|
||||
|
||||
|
||||
## Custom model update triggers
|
||||
# Custom model update triggers
|
||||
|
||||
By default, any change to the content will trigger a model update and form validation. You can
|
||||
override this behavior using the {@link ng.directive:ngModelOptions ngModelOptions} directive to
|
||||
@@ -251,7 +249,7 @@ will update the model only when the control loses focus (blur event).
|
||||
|
||||
|
||||
|
||||
## Non-immediate (debounced) model updates
|
||||
# Non-immediate (debounced) model updates
|
||||
|
||||
You can delay the model update/validation by using the `debounce` key with the
|
||||
{@link ng.directive:ngModelOptions ngModelOptions} directive. This delay will also apply to
|
||||
@@ -292,7 +290,7 @@ after last change.
|
||||
</file>
|
||||
</example>
|
||||
|
||||
## Custom Validation
|
||||
# Custom Validation
|
||||
|
||||
Angular provides basic implementation for most common HTML5 {@link ng.directive:input input}
|
||||
types: ({@link input[text] text}, {@link input[number] number}, {@link input[url] url},
|
||||
@@ -409,7 +407,7 @@ In the following example we create two directives:
|
||||
</file>
|
||||
</example>
|
||||
|
||||
## Modifying built-in validators
|
||||
# Modifying built-in validators
|
||||
|
||||
Since Angular itself uses `$validators`, you can easily replace or remove built-in validators,
|
||||
should you find it necessary. The following example shows you how to overwrite the email validator
|
||||
@@ -454,7 +452,7 @@ Note that you can alternatively use `ng-pattern` to further restrict the validat
|
||||
</example>
|
||||
|
||||
|
||||
## Implementing custom form controls (using `ngModel`)
|
||||
# Implementing custom form controls (using `ngModel`)
|
||||
Angular implements all of the basic HTML form controls ({@link ng.directive:input input},
|
||||
{@link ng.directive:select select}, {@link ng.directive:textarea textarea}),
|
||||
which should be sufficient for most cases. However, if you need more flexibility,
|
||||
@@ -491,7 +489,9 @@ The following example shows how to add two-way data-binding to contentEditable e
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
// view -> model
|
||||
elm.on('blur', function() {
|
||||
ctrl.$setViewValue(elm.html());
|
||||
scope.$apply(function() {
|
||||
ctrl.$setViewValue(elm.html());
|
||||
});
|
||||
});
|
||||
|
||||
// model -> view
|
||||
|
||||
@@ -18,10 +18,8 @@ application means providing translations and localized formats for the abstracte
|
||||
Angular supports i18n/l10n for {@link ng.filter:date date}, {@link ng.filter:number number} and
|
||||
{@link ng.filter:currency currency} filters.
|
||||
|
||||
Localizable pluralization is supported via the {@link ng.directive:ngPluralize `ngPluralize`
|
||||
directive}. Additionally, you can use {@link guide/i18n#messageformat-extensions MessageFormat extensions} to
|
||||
`$interpolate` for localizable pluralization and gender support in all interpolations via the
|
||||
`ngMessageFormat` module.
|
||||
Additionally, Angular supports localizable pluralization support through the {@link
|
||||
ng.directive:ngPluralize `ngPluralize` directive}.
|
||||
|
||||
All localizable Angular components depend on locale-specific rule sets managed by the {@link
|
||||
ng.$locale `$locale` service}.
|
||||
@@ -139,242 +137,3 @@ The Angular datetime filter uses the time zone settings of the browser. The same
|
||||
application will show different time information depending on the time zone settings of the
|
||||
computer that the application is running on. Neither JavaScript nor Angular currently supports
|
||||
displaying the date with a timezone specified by the developer.
|
||||
|
||||
|
||||
<a name="MessageFormat"></a>
|
||||
## MessageFormat extensions
|
||||
|
||||
You can write localizable plural and gender based messages in Angular interpolation expressions and
|
||||
`$interpolate` calls.
|
||||
|
||||
This syntax extension is provided by way of the `ngMessageFormat` module that your application can
|
||||
depend upon (shipped separately as `angular-message-format.min.js` and `angular-message-format.js`.)
|
||||
A current limitation of the `ngMessageFormat` module, is that it does not support redefining the
|
||||
`$interpolate` start and end symbols. Only the default `{{` and `}}` are allowed.
|
||||
|
||||
The syntax extension is based on a subset of the ICU MessageFormat syntax that covers plurals and
|
||||
gender selections. Please refer to the links in the “Further Reading” section at the bottom of this
|
||||
section.
|
||||
|
||||
You may find it helpful to play with our [Plnkr Example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview)
|
||||
as you read the examples below.
|
||||
|
||||
### Plural Syntax
|
||||
|
||||
The syntax for plural based message selection looks like the following:
|
||||
|
||||
```text
|
||||
{{NUMERIC_EXPRESSION, plural,
|
||||
=0 {MESSAGE_WHEN_VALUE_IS_0}
|
||||
=1 {MESSAGE_WHEN_VALUE_IS_1}
|
||||
=2 {MESSAGE_WHEN_VALUE_IS_2}
|
||||
=3 {MESSAGE_WHEN_VALUE_IS_3}
|
||||
...
|
||||
zero {MESSAGE_WHEN_PLURAL_CATEGORY_IS_ZERO}
|
||||
one {MESSAGE_WHEN_PLURAL_CATEGORY_IS_ONE}
|
||||
two {MESSAGE_WHEN_PLURAL_CATEGORY_IS_TWO}
|
||||
few {MESSAGE_WHEN_PLURAL_CATEGORY_IS_FEW}
|
||||
many {MESSAGE_WHEN_PLURAL_CATEGORY_IS_MANY}
|
||||
other {MESSAGE_WHEN_THERE_IS_NO_MATCH}
|
||||
}}
|
||||
```
|
||||
|
||||
Please note that whitespace (including newline) is generally insignificant except as part of the
|
||||
actual message text that occurs in curly braces. Whitespace is generally used to aid readability.
|
||||
|
||||
Here, `NUMERIC_EXPRESSION` is an expression that evaluates to a numeric value based on which the
|
||||
displayed message should change based on pluralization rules.
|
||||
|
||||
Following the Angular expression, you would denote the plural extension syntax by the `, plural,`
|
||||
syntax element. The spaces there are optional.
|
||||
|
||||
This is followed by a list of selection keyword and corresponding message pairs. The "other"
|
||||
keyword and corresponding message are **required** but you may have as few or as many of the other
|
||||
categories as you need.
|
||||
|
||||
#### Selection Keywords
|
||||
|
||||
The selection keywords can be either exact matches or language dependent [plural
|
||||
categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html).
|
||||
|
||||
Exact matches are written as the equal sign followed by the exact value. `=0`, `=1`, `=2` and
|
||||
`=123` are all examples of exact matches. Note that there should be no space between the equal sign
|
||||
and the numeric value.
|
||||
|
||||
Plural category matches are single words corresponding to the [plural
|
||||
categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) of
|
||||
the CLDR plural category spec. These categories vary by locale. The "en" (English) locale, for
|
||||
example, defines just "one" and "other" while the "ga" (Irish) locale defines "one", "two", "few",
|
||||
"many" and "other". Typically, you would just write the categories for your language. During
|
||||
translation, the translators will add or remove more categories depending on the target locale.
|
||||
|
||||
Exact matches always win over keyword matches. Therefore, if you define both `=0` and `zero`, when
|
||||
the value of the expression is zero, the `=0` message is the one that will be selected. (The
|
||||
duplicate keyword categories are helpful when used with the optional `offset` syntax described
|
||||
later.)
|
||||
|
||||
|
||||
#### Messages
|
||||
|
||||
Messages immediately follow a selection keyword and are optionally preceded by whitespace. They are
|
||||
written in single curly braces (`{}`). They may contain Angular interpolation syntax inside them.
|
||||
In addition, the `#` symbol is a placeholder for the actual numeric value of the expression.
|
||||
|
||||
### Simple plural example
|
||||
|
||||
```text
|
||||
{{numMessages, plural,
|
||||
=0 {You have no new messages}
|
||||
=1 {You have one new message}
|
||||
other {You have # new messages}
|
||||
}}
|
||||
```
|
||||
|
||||
Because these messages can themselves contain Angular expressions, you could also write this as
|
||||
follows:
|
||||
|
||||
```text
|
||||
{{numMessages, plural,
|
||||
=0 {You have no new messages}
|
||||
=1 {You have one new message}
|
||||
other {You have {{numMessages}} new messages}
|
||||
}}
|
||||
```
|
||||
|
||||
|
||||
### Plural syntax with optional `offset`
|
||||
|
||||
The plural syntax supports an optional `offset` syntax that is used in matching. It's simpler to
|
||||
explain this with an example.
|
||||
|
||||
```text
|
||||
{{recipients.length, plural, offset:1
|
||||
=0 {You gave no gifts}
|
||||
=1 {You gave {{recipients[0].name}} a gift}
|
||||
one {You gave {{recipients[0].name}} and one other person a gift}
|
||||
other {You gave {{recipients[0].name}} and # other people a gift}
|
||||
}}
|
||||
```
|
||||
|
||||
When an `offset` is specified, the matching works as follows. First, the exact value of the Angular
|
||||
expression is matched against the exact matches (i.e. `=N` selectors) to find a match. If there is
|
||||
one, that message is used. If there was no match, then the offset value is subtracted from the
|
||||
value of the expression and locale specific pluralization rules are applied to this new value to
|
||||
obtain its plural category (such as “one”, “few”, “many”, etc.) and a match is attempted against the
|
||||
keyword selectors and the matching message is used. If there was no match, then the “other”
|
||||
category (required) is used. The value of the `#` character inside a message is the value of
|
||||
original expression reduced by the offset value that was specified.
|
||||
|
||||
### Escaping / Quoting
|
||||
|
||||
You will need to escape curly braces or the `#` character inside message texts if you want them to
|
||||
be treated literally with no special meaning. You may quote/escape any character in your message
|
||||
text by preceding it with a `\` (backslash) character. The backslash character removes any special
|
||||
meaning to the character that immediately follows it. Therefore, you can escape or quote the
|
||||
backslash itself by preceding it with another backslash character.
|
||||
|
||||
|
||||
### Gender (aka select) Syntax
|
||||
|
||||
The gender support is provided by the more generic "select" syntax that is more akin to a switch
|
||||
statement. It is general enough to support use for gender based messages.
|
||||
|
||||
The syntax for gender based message selection looks like the following:
|
||||
|
||||
```text
|
||||
{{EXPRESSION, select,
|
||||
male {MESSAGE_WHEN_EXPRESSION_IS_MALE}
|
||||
female {MESSAGE_WHEN_EXPRESSION_IS_FEMALE}
|
||||
...
|
||||
other {MESSAGE_WHEN_THERE_IS_NO_GENDER_MATCH}
|
||||
}}
|
||||
```
|
||||
|
||||
Please note that whitespace (including newline) is generally insignificant except as part of the
|
||||
actual message text that occurs in curly braces. Whitespace is generally used to aid readability.
|
||||
|
||||
Here, `EXPRESSION` is an Angular expression that evaluates to the gender of the person that
|
||||
is used to select the message that should be displayed.
|
||||
|
||||
The Angular expression is followed by `, select,` where the spaces are optional.
|
||||
|
||||
This is followed by a list of selection keyword and corresponding message pairs. The "other"
|
||||
keyword and corresponding message are **required** but you may have as few or as many of the other
|
||||
gender values as you need (i.e. it isn't restricted to male/female.) Note however, that the
|
||||
matching is **case-sensitive**.
|
||||
|
||||
#### Selection Keywords
|
||||
|
||||
Selection keywords are simple words like "male" and "female". The keyword, "other", and its
|
||||
corresponding message are required while others are optional. It is used when the Angular
|
||||
expression does not match (case-insensitively) any of the other keywords specified.
|
||||
|
||||
#### Messages
|
||||
|
||||
Messages immediately follow a selection keyword and are optionally preceded by whitespace. They are
|
||||
written in single curly braces (`{}`). They may contain Angular interpolation syntax inside them.
|
||||
|
||||
### Simple gender example
|
||||
|
||||
```text
|
||||
{{friendGender, select,
|
||||
male {Invite him}
|
||||
female {Invite her}
|
||||
other {Invite them}
|
||||
}}
|
||||
```
|
||||
|
||||
### Nesting
|
||||
|
||||
As mentioned in the syntax for plural and select, the embedded messages can contain Angular
|
||||
interpolation syntax. Since you can use MessageFormat extensions in Angular interpolation, this
|
||||
allows you to nest plural and gender expressions in any order.
|
||||
|
||||
Please note that if these are intended to reach a translator and be translated, it is recommended
|
||||
that the messages appear as a whole and not be split up.
|
||||
|
||||
### More complex example that demonstrates nesting
|
||||
|
||||
This is taken from the [plunker example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview) linked to earlier.
|
||||
|
||||
```text
|
||||
{{recipients.length, plural, offset:1
|
||||
=0 {You ({{sender.name}}) gave no gifts}
|
||||
=1 { {{ recipients[0].gender, select,
|
||||
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) a gift.}
|
||||
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) a gift.}
|
||||
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) a gift.}
|
||||
}}
|
||||
}
|
||||
one { {{ recipients[0].gender, select,
|
||||
male {You ({{sender.name}}) gave him ({{recipients[0].name}}) and one other person a gift.}
|
||||
female {You ({{sender.name}}) gave her ({{recipients[0].name}}) and one other person a gift.}
|
||||
other {You ({{sender.name}}) gave them ({{recipients[0].name}}) and one other person a gift.}
|
||||
}}
|
||||
}
|
||||
other {You ({{sender.name}}) gave {{recipients.length}} people gifts. }
|
||||
}}
|
||||
```
|
||||
|
||||
### Differences from the ICU MessageFormat syntax
|
||||
|
||||
This section is useful to you if you're already familiar with the ICU MessageFormat syntax.
|
||||
|
||||
This syntax extension, while based on MessageFormat, has been designed to be backwards compatible
|
||||
with existing AngularJS interpolation expressions. The key rule is simply this: **All
|
||||
interpolations are done inside double curlies.** The top level comma operator after an expression
|
||||
inside the double curlies causes MessageFormat extensions to be recognized. Such a top level comma
|
||||
is otherwise illegal in an Angular expression and is used by MessageFormat to specify the function
|
||||
(such as plural/select) and it's related syntax.
|
||||
|
||||
To understand the extension, take a look at the ICU MessageFormat syntax as specified by the ICU
|
||||
documentation. Anywhere in that MessageFormat that you have regular message text and you want to
|
||||
substitute an expression, just put it in double curlies instead of single curlies that MessageFormat
|
||||
dictates. This has a huge advantage. **You are no longer limited to simple identifiers for
|
||||
substitutions**. Because you are using double curlies, you can stick in any arbitrary interpolation
|
||||
syntax there, including nesting more MessageFormat expressions!
|
||||
|
||||
### Further Reading
|
||||
For more details, please refer to our [design doc](https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit).
|
||||
You can read more about the ICU MessageFormat syntax at
|
||||
[Formatting Messages | ICU User Guide](http://userguide.icu-project.org/formatparse/messages#TOC-MessageFormat).
|
||||
|
||||
@@ -13,335 +13,6 @@ which drives many of these changes.
|
||||
* Several new features, especially animations, would not be possible without a few changes.
|
||||
* Finally, some outstanding bugs were best fixed by changing an existing API.
|
||||
|
||||
# Migrating from 1.3 to 1.4
|
||||
|
||||
Angular 1.4 fixes major animation issues and introduces a new API for `ngCookies`. Further, there
|
||||
are changes to `ngMessages`, `$compile`, `ngRepeat`, `ngOptions `and some fixes to core filters:
|
||||
`limitTo` and `filter`.
|
||||
|
||||
The reason for the ngAnimate refactor was to fix timing issues and to expose new APIs to allow
|
||||
for developers to construct more versatile animations. We now have access to `$animateCss`
|
||||
and the many timing-oriented bugs were fixed which results in smoother animations.
|
||||
If animation is something of interest, then please read over the breaking changes below for animations when
|
||||
`ngAnimate` is used.
|
||||
|
||||
`ngMessages` has been upgraded to allow for dynamic message resolution. This handy feature allows for developers
|
||||
to render error messages with ngMessages that are listed with a directive such as ngRepeat. A great usecase for this
|
||||
involves pulling error message data from a server and then displaying that data via the mechanics of ngMessages. Be
|
||||
sure to read the breaking change involved with `ngMessagesInclude` to upgrade your template code.
|
||||
|
||||
Other changes, such as the ordering of elements with ngRepeat and ngOptions, may also affect the behavior of your
|
||||
application. And be sure to also read up on the changes to `$cookies`. The migration jump from 1.3 to 1.4 should be
|
||||
relatively straightforward otherwise.
|
||||
|
||||
|
||||
|
||||
|
||||
## Animation (`ngAnimate`)
|
||||
|
||||
Animations in 1.4 have been refactored internally, but the API has stayed much the same. There are, however,
|
||||
some breaking changes that need to be addressed when upgrading to 1.4.
|
||||
|
||||
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
JavaScript and CSS animations can no longer be run in
|
||||
parallel. With earlier versions of ngAnimate, both CSS and JS animations
|
||||
would be run together when multiple animations were detected. This
|
||||
feature has been removed, however, the same effect, with even more
|
||||
possibilities, can be achieved by injecting `$animateCss` into a
|
||||
JavaScript-defined animation and creating custom CSS-based animations
|
||||
from there.
|
||||
|
||||
By using `$animateCss` inside of a JavaScript animation in Angular 1.4, we can trigger custom CSS-based animations
|
||||
directly from our JavaScript code.
|
||||
|
||||
```js
|
||||
ngModule.animation('.slide-animation', ['$animateCss', function($animateCss) {
|
||||
return {
|
||||
enter: function(element, doneFn) {
|
||||
// this will trigger a `.ng-enter` and `.ng-enter-active` CSS animation
|
||||
var animation = $animateCss(element, {
|
||||
event: 'enter'
|
||||
// any other CSS-related properties
|
||||
// addClass: 'some-class',
|
||||
// removeClass: 'some-other-class',
|
||||
// from: {},
|
||||
// to: {}
|
||||
});
|
||||
|
||||
// make sure to read the ngAnimate docs to understand how this works
|
||||
animation.start().done(doneFn);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
```
|
||||
|
||||
{@link ngAnimate.$animateCss Click here to learn how to use $animateCss in your animation code}
|
||||
|
||||
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
animation-related callbacks are now fired on `$animate.on` instead of directly being on the element.
|
||||
|
||||
```js
|
||||
// < 1.4
|
||||
element.on('$animate:before', function(e, data) {
|
||||
if (data.event === 'enter') { ... }
|
||||
});
|
||||
element.off('$animate:before', fn);
|
||||
|
||||
// 1.4+
|
||||
$animate.on('enter', element, function(data) {
|
||||
//...
|
||||
});
|
||||
$animate.off('enter', element, fn);
|
||||
```
|
||||
|
||||
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
the function params for `$animate.enabled()` when an element is used are now flipped. This fix allows
|
||||
the function to act as a getter when a single element param is provided.
|
||||
|
||||
```js
|
||||
// < 1.4
|
||||
$animate.enabled(false, element);
|
||||
|
||||
// 1.4+
|
||||
$animate.enabled(element, false);
|
||||
```
|
||||
|
||||
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
in addition to disabling the children of the element, `$animate.enabled(element, false)` will now also
|
||||
disable animations on the element itself.
|
||||
|
||||
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
there is no need to call `$scope.$apply` or `$scope.$digest` inside of a animation promise callback anymore
|
||||
since the promise is resolved within a digest automatically. (Not to worry, any extra digests will not be
|
||||
run unless the promise is used.)
|
||||
|
||||
```js
|
||||
// < 1.4
|
||||
$animate.enter(element).then(function() {
|
||||
$scope.$apply(function() {
|
||||
$scope.explode = true;
|
||||
});
|
||||
});
|
||||
|
||||
// 1.4+
|
||||
$animate.enter(element).then(function() {
|
||||
$scope.explode = true;
|
||||
});
|
||||
```
|
||||
|
||||
Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef),
|
||||
when an enter, leave or move animation is triggered then it will always end any pending or active parent
|
||||
class based animations (animations triggered via ngClass) in order to ensure that any CSS styles are resolved in time.
|
||||
|
||||
|
||||
|
||||
|
||||
## Forms (`ngMessages`, `ngOptions`, `select`)
|
||||
|
||||
### ngMessages
|
||||
The ngMessages module has also been subject to an internal refactor to allow it to be more flexible
|
||||
and compatible with dynamic message data. The `ngMessage` directive now supports a new attribute
|
||||
called `ng-message-exp` which will evaluate an expression and will keep track of that expression
|
||||
as it changes in order to re-evaluate the listed messages.
|
||||
|
||||
[Click here to learn more about dynamic ng-messages](https://docs.angularjs.org/api/ngMessages#dynamic-messaging)
|
||||
|
||||
There is only one breaking change. Please consider the following when including remote
|
||||
message templates via `ng-messages-include`:
|
||||
|
||||
Due to [c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0),
|
||||
the `ngMessagesInclude` attribute has now been removed and cannot be used in the same element containing
|
||||
the `ngMessages` directive. Instead, `ngMessagesInclude` is to be used on its own element inline with
|
||||
other inline messages situated as children within the `ngMessages` container directive.
|
||||
|
||||
```html
|
||||
<!-- AngularJS 1.3.x -->
|
||||
<div ng-messages="model.$error" ng-messages-include="remote.html">
|
||||
<div ng-message="required">Your message is required</div>
|
||||
</div>
|
||||
|
||||
<!-- AngularJS 1.4.x -->
|
||||
<div ng-messages="model.$error">
|
||||
<div ng-message="required">Your message is required</div>
|
||||
<div ng-messages-include="remote.html"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
Depending on where the `ngMessagesInclude` directive is placed it will be prioritized inline with the other messages
|
||||
before and after it.
|
||||
|
||||
### ngOptions
|
||||
|
||||
The `ngOptions` directive has also been refactored and as a result some long-standing bugs
|
||||
have been fixed. The breaking changes are comparatively minor and should not affect most applications.
|
||||
|
||||
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
|
||||
when `ngOptions` renders the option values within the DOM, the resulting HTML code is different.
|
||||
Normally this should not affect your application at all, however, if your code relies on inspecting
|
||||
the value property of `<option>` elements (that `ngOptions` generates) then be sure
|
||||
to [read the details](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef).
|
||||
|
||||
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
|
||||
when iterating over an object's properties using the `(key, value) in obj` syntax
|
||||
the order of the elements used to be sorted alphabetically. This was an artificial
|
||||
attempt to create a deterministic ordering since browsers don't guarantee the order.
|
||||
But in practice this is not what people want and so this change iterates over properties
|
||||
in the order they are returned by Object.keys(obj), which is almost always the order
|
||||
in which the properties were defined.
|
||||
|
||||
|
||||
### select
|
||||
|
||||
Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef),
|
||||
the `select` directive will now use strict comparison of the `ngModel` scope value against `option`
|
||||
values to determine which option is selected. This means `Number` scope values will not be matched
|
||||
against numeric option strings.
|
||||
In Angular 1.3.x, setting `scope.x = 200` would select the option with the value 200 in the following `select`:
|
||||
|
||||
```
|
||||
<select ng-model="x">
|
||||
<option value="100">100</option>
|
||||
<option value="200">200</option>
|
||||
</select>
|
||||
```
|
||||
|
||||
In Angular 1.4.x, the 'unknown option' will be selected.
|
||||
To remedy this, you can simply initialize the model as a string: `scope.x = '200'`, or if you want to
|
||||
keep the model as a `Number`, you can do the conversion via `$formatters` and `$parsers` on `ngModel`:
|
||||
|
||||
```js
|
||||
ngModelCtrl.$parsers.push(function(value) {
|
||||
return parseInt(value, 10); // Convert option value to number
|
||||
});
|
||||
|
||||
ngModelCtrl.$formatters.push(function(value) {
|
||||
return value.toString(); // Convert scope value to string
|
||||
});
|
||||
```
|
||||
|
||||
## Templating (`ngRepeat`, `$compile`)
|
||||
|
||||
### ngRepeat
|
||||
|
||||
Due to [c260e738](https://github.com/angular/angular.js/commit/c260e7386391877625eda086480de73e8a0ba921),
|
||||
previously, the order of items when using ngRepeat to iterate over object properties was guaranteed to be consistent
|
||||
by sorting the keys into alphabetic order.
|
||||
|
||||
Now, the order of the items is browser dependent based on the order returned
|
||||
from iterating over the object using the `for key in obj` syntax.
|
||||
|
||||
It seems that browsers generally follow the strategy of providing
|
||||
keys in the order in which they were defined, although there are exceptions
|
||||
when keys are deleted and reinstated. See
|
||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
|
||||
|
||||
The best approach is to convert Objects into Arrays by a filter such as
|
||||
https://github.com/petebacondarwin/angular-toArrayFilter
|
||||
or some other mechanism, and then sort them manually in the order you need.
|
||||
|
||||
|
||||
### $compile
|
||||
|
||||
Due to [6a38dbfd](https://github.com/angular/angular.js/commit/6a38dbfd3c34c8f9efff503d17eb3cbeb666d422),
|
||||
previously, '&' expressions would always set up a function in the isolate scope. Now, if the binding
|
||||
is marked as optional and the attribute is not specified, no function will be added to the isolate scope.
|
||||
|
||||
Due to [62d514b](https://github.com/angular/angular.js/commit/62d514b06937cc7dd86e973ea11165c88343b42d),
|
||||
returning an object from a controller constructor function will now override the scope. Views that use the
|
||||
controllerAs method will no longer get the this reference, but the returned object.
|
||||
|
||||
|
||||
## Cookies (`ngCookies`)
|
||||
|
||||
Due to [38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe),
|
||||
`$cookies` will no longer expose properties that represent the current browser cookie
|
||||
values. `$cookies` no longer polls the browser for changes to the cookies and ***no longer copies
|
||||
cookie values onto the `$cookies` object***.
|
||||
|
||||
This was changed because the polling is expensive and caused issues with the `$cookies` properties
|
||||
not synchronizing correctly with the actual browser cookie values (The reason the polling
|
||||
was originally added was to allow communication between different tabs,
|
||||
but there are better ways to do this today, for example `localStorage`.)
|
||||
|
||||
The new API on `$cookies` is as follows:
|
||||
|
||||
* `get`
|
||||
* `put`
|
||||
* `getObject`
|
||||
* `putObject`
|
||||
* `getAll`
|
||||
* `remove`
|
||||
|
||||
You must explictly use the methods above in order to access cookie data. This also means that
|
||||
you can no longer watch the properties on `$cookies` to detect changes
|
||||
that occur on the browsers cookies.
|
||||
|
||||
This feature is generally only needed if a 3rd party library was programmatically
|
||||
changing the cookies at runtime. If you rely on this then you must either write code that
|
||||
can react to the 3rd party library making the changes to cookies or implement your own polling
|
||||
mechanism.
|
||||
|
||||
**DEPRECATION NOTICE**
|
||||
|
||||
`$cookieStore` is now deprecated as all the useful logic
|
||||
has been moved to `$cookies`, to which `$cookieStore` now simply
|
||||
delegates calls.
|
||||
|
||||
|
||||
|
||||
|
||||
## Server Requests (`$http`)
|
||||
|
||||
Due to [5da1256](https://github.com/angular/angular.js/commit/5da1256fc2812d5b28fb0af0de81256054856369),
|
||||
`transformRequest` functions can no longer modify request headers.
|
||||
|
||||
Before this commit `transformRequest` could modify request headers, ex.:
|
||||
|
||||
```javascript
|
||||
function requestTransform(data, headers) {
|
||||
headers = angular.extend(headers(), {
|
||||
'X-MY_HEADER': 'abcd'
|
||||
});
|
||||
}
|
||||
return angular.toJson(data);
|
||||
}
|
||||
```
|
||||
|
||||
This behavior was unintended and undocumented, so the change should affect very few applications. If one
|
||||
needs to dynamically add / remove headers it should be done in a header function, for example:
|
||||
|
||||
```javascript
|
||||
$http.get(url, {
|
||||
headers: {
|
||||
'X-MY_HEADER': function(config) {
|
||||
return 'abcd'; //you've got access to a request config object to specify header value dynamically
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Filters (`filter`, `limitTo`)
|
||||
|
||||
### `filter` filter
|
||||
Due to [cea8e751](https://github.com/angular/angular.js/commit/cea8e75144e6910b806b63a6ec2a6d118316fddd),
|
||||
the `filter` filter will throw an error when used with a non-array. Beforehand it would silently
|
||||
return an empty array.
|
||||
|
||||
If necessary, this can be worked around by converting an object to an array,
|
||||
using a filter such as https://github.com/petebacondarwin/angular-toArrayFilter.
|
||||
|
||||
### `limitTo` filter
|
||||
Due to [a3c3bf33](https://github.com/angular/angular.js/commit/a3c3bf3332e5685dc319c46faef882cb6ac246e1),
|
||||
the limitTo filter has changed behavior when the provided limit value is invalid.
|
||||
Now, instead of returning empty object/array, it returns unchanged input.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Migrating from 1.2 to 1.3
|
||||
|
||||
## Controllers
|
||||
|
||||
@@ -140,7 +140,7 @@ The above is a suggestion. Tailor it to your needs.
|
||||
# Module Loading & Dependencies
|
||||
|
||||
A module is a collection of configuration and run blocks which get applied to the application
|
||||
during the bootstrap process. In its simplest form the module consists of a collection of two kinds
|
||||
during the bootstrap process. In its simplest form the module consist of a collection of two kinds
|
||||
of blocks:
|
||||
|
||||
1. **Configuration blocks** - get executed during the provider registrations and configuration
|
||||
@@ -197,14 +197,14 @@ Then Angular applies configuration blocks in the same order they were registered
|
||||
## Run Blocks
|
||||
|
||||
Run blocks are the closest thing in Angular to the main method. A run block is the code which
|
||||
needs to run to kickstart the application. It is executed after all of the services have been
|
||||
needs to run to kickstart the application. It is executed after all of the service have been
|
||||
configured and the injector has been created. Run blocks typically contain code which is hard
|
||||
to unit-test, and for this reason should be declared in isolated modules, so that they can be
|
||||
ignored in the unit-tests.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Modules can list other modules as their dependencies. Depending on a module implies that the required
|
||||
Modules can list other modules as their dependencies. Depending on a module implies that required
|
||||
module needs to be loaded before the requiring module is loaded. In other words the configuration
|
||||
blocks of the required modules execute before the configuration blocks of the requiring module.
|
||||
The same is true for the run blocks. Each module can only be loaded once, even if multiple other
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# What are Scopes?
|
||||
|
||||
{@link ng.$rootScope.Scope Scope} is an object that refers to the application
|
||||
{@link ng.$rootScope.Scope scope} is an object that refers to the application
|
||||
model. It is an execution context for {@link expression expressions}. Scopes are
|
||||
arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can
|
||||
watch {@link guide/expression expressions} and propagate events.
|
||||
@@ -245,7 +245,7 @@ of the `$watch` expressions and compares them with the previous value. This dirt
|
||||
asynchronously. This means that assignment such as `$scope.username="angular"` will not
|
||||
immediately cause a `$watch` to be notified, instead the `$watch` notification is delayed until
|
||||
the `$digest` phase. This delay is desirable, since it coalesces multiple model updates into one
|
||||
`$watch` notification as well as guarantees that during the `$watch` notification no other
|
||||
`$watch` notification as well as it guarantees that during the `$watch` notification no other
|
||||
`$watch`es are running. If a `$watch` changes the value of the model, it will force additional
|
||||
`$digest` cycle.
|
||||
|
||||
@@ -264,7 +264,7 @@ the `$digest` phase. This delay is desirable, since it coalesces multiple model
|
||||
3. **Model mutation**
|
||||
|
||||
For mutations to be properly observed, you should make them only within the {@link
|
||||
ng.$rootScope.Scope#$apply scope.$apply()}. Angular APIs do this
|
||||
ng.$rootScope.Scope#$apply scope.$apply()}. (Angular APIs do this
|
||||
implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers,
|
||||
or asynchronous work with {@link ng.$http $http}, {@link ng.$timeout $timeout}
|
||||
or {@link ng.$interval $interval} services.
|
||||
|
||||
@@ -39,7 +39,7 @@ In general, we recommend against this because it can create unintended XSS vecto
|
||||
|
||||
However, it's ok to mix server-side templating in the bootstrap template (`index.html`) as long
|
||||
as user input cannot be used on the server to output html that would then be processed by Angular
|
||||
in a way that would allow for arbitrary code execution.
|
||||
in a way that would cause allow for arbitrary code execution.
|
||||
|
||||
For instance, you can use server-side templating to dynamically generate CSS, URLs, etc, but not
|
||||
for generating templates that are bootstrapped/compiled by Angular.
|
||||
|
||||
@@ -82,7 +82,7 @@ on the service.
|
||||
### Registering Services
|
||||
|
||||
Services are registered to modules via the {@link angular.Module Module API}.
|
||||
Typically you use the {@link angular.Module#factory Module factory} API to register a service:
|
||||
Typically you use the {@link angular.module Module#factory} API to register a service:
|
||||
|
||||
```js
|
||||
var myModule = angular.module('myModule', []);
|
||||
@@ -181,7 +181,7 @@ of a real browser alert.
|
||||
|
||||
```js
|
||||
var mock, notify;
|
||||
beforeEach(module('myServiceModule'));
|
||||
|
||||
beforeEach(function() {
|
||||
mock = {alert: jasmine.createSpy()};
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ are available on [the Karma website](http://karma-runner.github.io/0.12/intro/in
|
||||
|
||||
### Jasmine
|
||||
|
||||
[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a behavior driven development framework for
|
||||
[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a test driven development framework for
|
||||
JavaScript that has become the most popular choice for testing Angular applications. Jasmine
|
||||
provides functions to help with structuring your tests and also making assertions. As your tests
|
||||
grow, keeping them well structured and documented is vital, and Jasmine helps achieve this.
|
||||
@@ -260,13 +260,6 @@ myModule.filter('length', function() {
|
||||
});
|
||||
|
||||
describe('length filter', function() {
|
||||
|
||||
var $filter;
|
||||
|
||||
beforeEach(inject(function(_$filter_){
|
||||
$filter = _$filter_;
|
||||
}));
|
||||
|
||||
it('returns 0 when given null', function() {
|
||||
var length = $filter('length');
|
||||
expect(length(null)).toEqual(0);
|
||||
|
||||
@@ -153,7 +153,7 @@ grunt test:unit --browsers Opera,Firefox
|
||||
|
||||
Note there should be _no spaces between browsers_. `Opera, Firefox` is INVALID.
|
||||
|
||||
During development, however, it's more productive to continuously run unit tests every time the source or test files
|
||||
During development it's however more productive to continuously run unit tests every time the source or test files
|
||||
change. To execute tests in this mode run:
|
||||
|
||||
1. To start the Karma server, capture Chrome browser and run unit tests, run:
|
||||
|
||||
@@ -20,42 +20,6 @@ AngularJS is 100% JavaScript, 100% client-side and compatible with both desktop
|
||||
So it's definitely not a plugin or some other native browser extension.
|
||||
|
||||
|
||||
### What is the AngularJS versioning strategy?
|
||||
|
||||
In Angular 1 we do not allow intentional breaking changes to appear in versions where only the "patch"
|
||||
number changes. For example between 1.3.12 and 1.3.13 there can be no breaking changes. We do allow
|
||||
breaking changes happen between "minor" number changes. For example between 1.3.15 and 1.4.0 there
|
||||
will be a number of breaking changes. We also allow breaking changes between beta releases of Angular.
|
||||
For example between 1.4.0-beta.4 and 1.4.0-beta.5 there may be breaking changes. We try hard to minimize
|
||||
these kinds of change only to those where there is a strong use case such as a strongly requested feature
|
||||
improvement, a considerable simplification of the code or a measurable performance improvement.
|
||||
|
||||
When adding new code to branches of Angular, have a very stringent commit policy:
|
||||
|
||||
- Every commit must contain tests and documentation updates alongside the code changes and that all the
|
||||
tests must pass;
|
||||
- Commit messages must be written in a specific manner that allows us to parse them and extract the changes
|
||||
for release notes.
|
||||
|
||||
The Angular code base has a very large set of unit tests (over 4000) and end to end tests, which are pretty
|
||||
comprehensive. This means that a breaking change will require one or more tests to be changed to allow the
|
||||
tests to pass. So when a commit includes tests that are being removed or modified, this is a flag that the
|
||||
code might include a breaking change. When reviewing the commit we can then decide whether there really is
|
||||
a breaking change and if it is appropriate for the branch to which it is being merged. If so, then we
|
||||
require that the commit message contains an appropriate breaking change message.
|
||||
|
||||
Additionally, when a commit lands in our master repository it is synced to Google where we test it against
|
||||
over 2000 applications using the test suites of these applications. This allows us to catch regressions
|
||||
quickly before a release. We've had a pretty good experience with this setup. Only bugs that affect features
|
||||
not used at Google or without sufficient test coverage, have a chance of making it through.
|
||||
|
||||
Lastly, when we are making a release we generate updates to the changelog directly from the commits. This
|
||||
generated update contains a highlighted section that contains all the breaking changes that have been
|
||||
extracted from the commits. We can quickly see in the new changelog exactly what commits contain breaking
|
||||
changes and so can application developers when they are deciding whether to update to a new version of
|
||||
Angular.
|
||||
|
||||
|
||||
### Is AngularJS a templating system?
|
||||
|
||||
At the highest level, Angular does look like just another templating system. But there is one
|
||||
@@ -69,7 +33,7 @@ templating systems.
|
||||
### Do I need to worry about security holes in AngularJS?
|
||||
|
||||
Like any other technology, AngularJS is not impervious to attack. Angular does, however, provide
|
||||
built-in protection from basic security holes, including cross-site scripting and HTML injection
|
||||
built-in protection from basic security holes including cross-site scripting and HTML injection
|
||||
attacks. AngularJS does round-trip escaping on all strings for you and even offers XSRF protection
|
||||
for server-side communication.
|
||||
|
||||
@@ -88,7 +52,7 @@ Yes. See instructions in {@link downloading}.
|
||||
|
||||
We run our extensive test suite against the following browsers: Safari, Chrome, Firefox, Opera 15,
|
||||
IE9 and mobile browsers (Android, Chrome Mobile, iOS Safari). See {@link guide/ie Internet
|
||||
Explorer Compatibility} for more details on supporting legacy IE browsers.
|
||||
Explorer Compatibility} for more details in supporting legacy IE browsers.
|
||||
|
||||
|
||||
### What's Angular's performance like?
|
||||
@@ -97,8 +61,8 @@ The startup time heavily depends on your network connection, state of the cache,
|
||||
available hardware, but typically we measure bootstrap time in tens or hundreds of milliseconds.
|
||||
|
||||
The runtime performance will vary depending on the number and complexity of bindings on the page
|
||||
as well as the speed of your backend (for apps that fetch data from the backend). For an
|
||||
illustration, we typically build snappy apps with hundreds or thousands of active bindings.
|
||||
as well as the speed of your backend (for apps that fetch data from the backend). Just for an
|
||||
illustration we typically build snappy apps with hundreds or thousands of active bindings.
|
||||
|
||||
|
||||
### How big is the angular.js file that I need to include?
|
||||
@@ -124,7 +88,7 @@ but we don't guarantee that.
|
||||
|
||||
### What is testability like in Angular?
|
||||
|
||||
Very testable and designed this way from the ground up. It has an integrated dependency injection
|
||||
Very testable and designed this way from ground up. It has an integrated dependency injection
|
||||
framework, provides mocks for many heavy dependencies (server-side communication). See
|
||||
{@link ngMock} for details.
|
||||
|
||||
@@ -194,7 +158,7 @@ Conditionally showing and hiding things using jQuery is a common pattern in othe
|
||||
`ng-show` (and `ng-hide`) conditionally show and hide elements based on boolean expressions.
|
||||
Describe the conditions for showing and hiding an element in terms of `$scope` variables:
|
||||
|
||||
<div ng-show="!loggedIn"><a href="#/login">Click here to log in</a></div>
|
||||
<div ng-show="!loggedIn">Click <a href="#/login">here</a> to log in</div>
|
||||
|
||||
Note also the counterpart `ng-hide` and similar `ng-disabled`.
|
||||
Note especially the powerful `ng-switch` that should be used instead of several mutually exclusive `ng-show`s.
|
||||
@@ -225,7 +189,7 @@ Then whenever a value on a scope changes, all `$watch`es observing that element
|
||||
|
||||
Sometimes, usually when you're writing a custom directive, you will have to define your own `$watch` on a scope value to make the directive react to changes.
|
||||
|
||||
On the flip side, sometimes you change a scope value in some code, but the app doesn't react to it.
|
||||
On the flip side, sometimes you change a scope value in some code but the app doesn't react to it.
|
||||
Angular checks for scope variable changes after pieces of your code have finished running; for example, when `ng-click` calls a function on your scope, Angular will check for changes and react.
|
||||
However, some code is outside of Angular and you'll have to call `scope.$apply()` yourself to trigger the update.
|
||||
This is most commonly seen in event handlers in custom directives.
|
||||
|
||||
@@ -129,8 +129,7 @@ Once you have Node.js installed on your machine you can download the tool depend
|
||||
npm install
|
||||
```
|
||||
|
||||
This command reads angular-phonecat's `package.json` file and downloads the following tools
|
||||
into the `node_modules` directory:
|
||||
This command will download the following tools, into the `node_modules` directory:
|
||||
|
||||
- [Bower][bower] - client-side code package manager
|
||||
- [Http-Server][http-server] - simple local static web server
|
||||
@@ -199,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.
|
||||
You can use `-a` to set the address and `-p` to set the port.
|
||||
You can `-a` to set the address and `-p` to set the port.
|
||||
</div>
|
||||
|
||||
### Running Unit Tests
|
||||
@@ -271,7 +270,6 @@ It is good to run the end to end tests whenever you make changes to the HTML vie
|
||||
that the application as a whole is executing correctly. It is very common to run End to End tests
|
||||
before pushing a new commit of changes to a remote repository.
|
||||
|
||||
Now that you have set up your local machine, let's get started with the tutorial: {@link step_00 Step 0 - Bootstrapping}
|
||||
|
||||
[git]: http://git-scm.com/
|
||||
[node]: http://nodejs.org/
|
||||
|
||||
@@ -31,7 +31,7 @@ npm install
|
||||
|
||||
To see the app running in a browser, open a *separate* terminal/command line tab or window, then
|
||||
run `npm start` to start the web server. Now, open a browser window for the app and navigate to
|
||||
<a href="http://localhost:8000/app/" target="_blank" title="Open app on localhost">`http://localhost:8000/app/`</a>
|
||||
<a href="http://localhost:8000/app/" target="_blank">`http://localhost:8000/app/`</a>
|
||||
|
||||
Note that if you already ran the master branch app prior to checking out step-0, you may see the cached
|
||||
master version of the app in your browser window at this point. Just hit refresh to re-load the page.
|
||||
@@ -91,22 +91,22 @@ being the element on which the `ngApp` directive was defined.
|
||||
|
||||
Nothing here {{'yet' + '!'}}
|
||||
|
||||
This line demonstrates two core features of Angular's templating capabilities:
|
||||
This line demonstrates two core features of Angular's templating capabilities:
|
||||
|
||||
* a binding, denoted by double-curlies `{{ }}`
|
||||
* a simple expression `'yet' + '!'` used in this binding.
|
||||
* a binding, denoted by double-curlies `{{ }}`
|
||||
* a simple expression `'yet' + '!'` used in this binding.
|
||||
|
||||
The binding tells Angular that it should evaluate an expression and insert the result into the
|
||||
DOM in place of the binding. Rather than a one-time insert, as we'll see in the next steps, a
|
||||
binding will result in efficient continuous updates whenever the result of the expression
|
||||
evaluation changes.
|
||||
The binding tells Angular that it should evaluate an expression and insert the result into the
|
||||
DOM in place of the binding. Rather than a one-time insert, as we'll see in the next steps, a
|
||||
binding will result in efficient continuous updates whenever the result of the expression
|
||||
evaluation changes.
|
||||
|
||||
{@link guide/expression Angular expression} is a JavaScript-like code snippet that is
|
||||
evaluated by Angular in the context of the current model scope, rather than within the scope of
|
||||
the global context (`window`).
|
||||
{@link guide/expression Angular expression} is a JavaScript-like code snippet that is
|
||||
evaluated by Angular in the context of the current model scope, rather than within the scope of
|
||||
the global context (`window`).
|
||||
|
||||
As expected, once this template is processed by Angular, the html page contains the text:
|
||||
"Nothing here yet!".
|
||||
As expected, once this template is processed by Angular, the html page contains the text:
|
||||
"Nothing here yet!".
|
||||
|
||||
## Bootstrapping AngularJS apps
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ multiple views by adding routing, using an Angular module called 'ngRoute'.
|
||||
|
||||
* When you now navigate to `app/index.html`, you are redirected to `app/index.html/#/phones`
|
||||
and the phone list appears in the browser.
|
||||
* When you click on a phone link, the url changes to that specific phone and the stub of a
|
||||
* When you click on a phone link the url changes to one specific to that phone and the stub of a
|
||||
phone detail page is displayed.
|
||||
|
||||
<div doc-tutorial-reset="7"></div>
|
||||
|
||||
@@ -225,7 +225,7 @@ inserted into and removed from the list:
|
||||
* The `ng-leave` class is applied when they're removed from the list.
|
||||
|
||||
The phone listing items are added and removed depending on the data passed to the `ng-repeat` attribute.
|
||||
For example, if the filter data changes, the items will be animated in and out of the repeat list.
|
||||
For example, if the filter data changes the items will be animated in and out of the repeat list.
|
||||
|
||||
Something important to note is that when an animation occurs, two sets of CSS classes
|
||||
are added to the element:
|
||||
@@ -233,7 +233,7 @@ are added to the element:
|
||||
1. a "starting" class that represents the style at the beginning of the animation
|
||||
2. an "active" class that represents the style at the end of the animation
|
||||
|
||||
The name of the starting class is the name of the event that is fired (like `enter`, `move` or `leave`) prefixed with
|
||||
The name of the starting class is the name of event that is fired (like `enter`, `move` or `leave`) prefixed with
|
||||
`ng-`. So an `enter` event will result in a class called `ng-enter`.
|
||||
|
||||
The active class name is the same as the starting class's but with an `-active` suffix.
|
||||
|
||||
@@ -184,8 +184,6 @@ describe("extractDateTimeSymbols", function() {
|
||||
'nov.', 'déc.'],
|
||||
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
|
||||
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
|
||||
FIRSTDAYOFWEEK: 6,
|
||||
WEEKENDRANGE: [5, 6],
|
||||
AMPMS: ['AM', 'PM'],
|
||||
ERAS: ['av. J.-C.', 'ap. J.-C.'],
|
||||
ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
|
||||
|
||||
@@ -42,8 +42,6 @@ function convertDatetimeData(dataObj) {
|
||||
datetimeFormats.DAY = dataObj.WEEKDAYS;
|
||||
datetimeFormats.SHORTDAY = dataObj.SHORTWEEKDAYS;
|
||||
datetimeFormats.AMPMS = dataObj.AMPMS;
|
||||
datetimeFormats.FIRSTDAYOFWEEK = dataObj.FIRSTDAYOFWEEK;
|
||||
datetimeFormats.WEEKENDRANGE = dataObj.WEEKENDRANGE;
|
||||
datetimeFormats.ERAS = dataObj.ERAS;
|
||||
datetimeFormats.ERANAMES = dataObj.ERANAMES;
|
||||
|
||||
|
||||
@@ -66,12 +66,6 @@ module.exports = function(config, specificOptions) {
|
||||
platform: 'Windows 8.1',
|
||||
version: '11'
|
||||
},
|
||||
'SL_iOS': {
|
||||
base: "SauceLabs",
|
||||
browserName: "iphone",
|
||||
platform: "OS X 10.10",
|
||||
version: "8.1"
|
||||
},
|
||||
|
||||
'BS_Chrome': {
|
||||
base: 'BrowserStack',
|
||||
@@ -111,12 +105,6 @@ module.exports = function(config, specificOptions) {
|
||||
browser_version: '11.0',
|
||||
os: 'Windows',
|
||||
os_version: '8.1'
|
||||
},
|
||||
'BS_iOS': {
|
||||
base: 'BrowserStack',
|
||||
device: 'iPhone 6',
|
||||
os: 'ios',
|
||||
os_version: '8.0'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+2
-8
@@ -185,16 +185,14 @@ module.exports = {
|
||||
var mapFileName = mapFile.match(/[^\/]+$/)[0];
|
||||
var errorFileName = file.replace(/\.js$/, '-errors.json');
|
||||
var versionNumber = grunt.config('NG_VERSION').full;
|
||||
var compilationLevel = (file === 'build/angular-message-format.js') ?
|
||||
'ADVANCED_OPTIMIZATIONS' : 'SIMPLE_OPTIMIZATIONS';
|
||||
shell.exec(
|
||||
'java ' +
|
||||
this.java32flags() + ' ' +
|
||||
this.memoryRequirement() + ' ' +
|
||||
'-Xmx2g ' +
|
||||
'-cp bower_components/closure-compiler/compiler.jar' + classPathSep +
|
||||
'bower_components/ng-closure-runner/ngcompiler.jar ' +
|
||||
'org.angularjs.closurerunner.NgClosureRunner ' +
|
||||
'--compilation_level ' + compilationLevel + ' ' +
|
||||
'--compilation_level SIMPLE_OPTIMIZATIONS ' +
|
||||
'--language_in ECMASCRIPT5_STRICT ' +
|
||||
'--minerr_pass ' +
|
||||
'--minerr_errors ' + errorFileName + ' ' +
|
||||
@@ -217,10 +215,6 @@ module.exports = {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
memoryRequirement: function() {
|
||||
return (process.platform === 'win32') ? '' : '-Xmx2g';
|
||||
},
|
||||
|
||||
|
||||
//returns the 32-bit mode force flags for java compiler if supported, this makes the build much faster
|
||||
java32flags: function(){
|
||||
|
||||
@@ -16,9 +16,9 @@ var currentPackage, previousVersions, cdnVersion, gitRepoInfo;
|
||||
var getPackage = function() {
|
||||
// Search up the folder hierarchy for the first package.json
|
||||
var packageFolder = path.resolve('.');
|
||||
while (!fs.existsSync(path.join(packageFolder, 'package.json'))) {
|
||||
while ( !fs.existsSync(path.join(packageFolder, 'package.json')) ) {
|
||||
var parent = path.dirname(packageFolder);
|
||||
if (parent === packageFolder) { break; }
|
||||
if ( parent === packageFolder) { break; }
|
||||
packageFolder = parent;
|
||||
}
|
||||
return JSON.parse(fs.readFileSync(path.join(packageFolder,'package.json'), 'UTF-8'));
|
||||
@@ -48,11 +48,11 @@ var getGitRepoInfo = function() {
|
||||
* @return {String} The codename if found, otherwise null/undefined
|
||||
*/
|
||||
var getCodeName = function(tagName) {
|
||||
var gitCatOutput = shell.exec('git cat-file -p ' + tagName, {silent:true}).output;
|
||||
var gitCatOutput = shell.exec('git cat-file -p '+ tagName, {silent:true}).output;
|
||||
var tagMessage = gitCatOutput.match(/^.*codename.*$/mg)[0];
|
||||
var codeName = tagMessage && tagMessage.match(/codename\((.*)\)/)[1];
|
||||
if (!codeName) {
|
||||
throw new Error("Could not extract release code name. The message of tag " + tagName +
|
||||
throw new Error("Could not extract release code name. The message of tag "+tagName+
|
||||
" must match '*codename(some release name)*'");
|
||||
}
|
||||
return codeName;
|
||||
@@ -65,7 +65,7 @@ var getCodeName = function(tagName) {
|
||||
*/
|
||||
function getBuild() {
|
||||
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
|
||||
return 'sha.' + hash;
|
||||
return 'sha.'+hash;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,14 +76,14 @@ function getBuild() {
|
||||
var getTaggedVersion = function() {
|
||||
var gitTagResult = shell.exec('git describe --exact-match', {silent:true});
|
||||
|
||||
if (gitTagResult.code === 0) {
|
||||
if ( gitTagResult.code === 0 ) {
|
||||
var tag = gitTagResult.output.trim();
|
||||
var version = semver.parse(tag);
|
||||
|
||||
if (version && semver.satisfies(version, currentPackage.branchVersion)) {
|
||||
if ( version && semver.satisfies(version, currentPackage.branchVersion)) {
|
||||
version.codeName = getCodeName(tag);
|
||||
version.full = version.version;
|
||||
version.branch = 'v' + currentPackage.branchPattern.replace('*', 'x');
|
||||
version.branch = 'v' + currentPackage.branchVersion.replace('*', 'x');
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ var getPreviousVersions = function() {
|
||||
var repo_url = currentPackage.repository.url;
|
||||
var tagResults = shell.exec('git ls-remote --tags ' + repo_url,
|
||||
{silent: true});
|
||||
if (tagResults.code === 0) {
|
||||
if ( tagResults.code === 0 ) {
|
||||
return _(tagResults.output.match(/v[0-9].*[0-9]$/mg))
|
||||
.map(function(tag) {
|
||||
var version = semver.parse(tag);
|
||||
@@ -110,16 +110,10 @@ var getPreviousVersions = function() {
|
||||
})
|
||||
.filter()
|
||||
.map(function(version) {
|
||||
// angular.js didn't follow semantic version until 1.20rc1
|
||||
if ((version.major === 1 && version.minor === 0 && version.prerelease.length > 0) || (version.major === 1 && version.minor === 2 && version.prerelease[0] === 'rc1')) {
|
||||
version.version = [version.major, version.minor, version.patch].join('.') + version.prerelease.join('');
|
||||
version.raw = 'v' + version.version;
|
||||
}
|
||||
version.docsUrl = 'http://code.angularjs.org/' + version.version + '/docs';
|
||||
// Versions before 1.0.2 had a different docs folder name
|
||||
if (version.major < 1 || (version.major === 1 && version.minor === 0 && version.patch < 2)) {
|
||||
if ( version.major < 1 || (version.major === 1 && version.minor === 0 && version.dot < 2 ) ) {
|
||||
version.docsUrl += '-' + version.version;
|
||||
version.isOldDocsUrl = true;
|
||||
}
|
||||
return version;
|
||||
})
|
||||
@@ -140,10 +134,10 @@ var getCdnVersion = function() {
|
||||
if (!cdnVersion) {
|
||||
// Note: need to use shell.exec and curl here
|
||||
// as version-infos returns its result synchronously...
|
||||
var cdnResult = shell.exec('curl http://ajax.googleapis.com/ajax/libs/angularjs/' + version + '/angular.min.js ' +
|
||||
var cdnResult = shell.exec('curl http://ajax.googleapis.com/ajax/libs/angularjs/'+version+'/angular.min.js '+
|
||||
'--head --write-out "%{http_code}" -o /dev/null -silent',
|
||||
{silent: true});
|
||||
if (cdnResult.code === 0) {
|
||||
if ( cdnResult.code === 0 ) {
|
||||
var statusCode = cdnResult.output.trim();
|
||||
if (statusCode === '200') {
|
||||
cdnVersion = version;
|
||||
@@ -165,9 +159,9 @@ var getSnapshotVersion = function() {
|
||||
})
|
||||
.last();
|
||||
|
||||
if (!version) {
|
||||
if ( !version ) {
|
||||
// a snapshot version before the first tag on the branch
|
||||
version = semver(currentPackage.branchPattern.replace('*','0-beta.1'));
|
||||
version = semver(currentPackage.branchVersion.replace('*','0-beta.1'));
|
||||
}
|
||||
|
||||
// We need to clone to ensure that we are not modifying another version
|
||||
|
||||
+295
-513
File diff suppressed because it is too large
Load Diff
Generated
+1059
-1396
File diff suppressed because it is too large
Load Diff
+2
-4
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"license": "MIT",
|
||||
"branchVersion": "^1.4.0-beta.0",
|
||||
"branchPattern": "1.4.*",
|
||||
"branchVersion": "1.3.*",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.js.git"
|
||||
@@ -59,7 +57,7 @@
|
||||
"marked": "~0.3.0",
|
||||
"node-html-encoder": "0.0.2",
|
||||
"promises-aplus-tests": "~2.1.0",
|
||||
"protractor": "^2.1.0",
|
||||
"protractor": "^1.6.0",
|
||||
"q": "~1.0.0",
|
||||
"q-io": "^1.10.9",
|
||||
"qq": "^0.3.5",
|
||||
|
||||
@@ -17,7 +17,7 @@ ARG_DEFS=(
|
||||
)
|
||||
|
||||
function checkVersionNumber() {
|
||||
BRANCH_PATTERN=$(readJsonProp "package.json" "branchPattern")
|
||||
BRANCH_PATTERN=$(readJsonProp "package.json" "branchVersion")
|
||||
if [[ $VERSION_NUMBER != $BRANCH_PATTERN ]]; then
|
||||
echo "version-number needs to match $BRANCH_PATTERN on this branch"
|
||||
usage
|
||||
|
||||
@@ -14,6 +14,21 @@ function init {
|
||||
TMP_DIR=$(resolveDir ../../tmp)
|
||||
BUILD_DIR=$(resolveDir ../../build)
|
||||
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
|
||||
REPOS=(
|
||||
angular
|
||||
angular-animate
|
||||
angular-aria
|
||||
angular-cookies
|
||||
angular-i18n
|
||||
angular-loader
|
||||
angular-mocks
|
||||
angular-route
|
||||
angular-resource
|
||||
angular-sanitize
|
||||
angular-scenario
|
||||
angular-touch
|
||||
angular-messages
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -114,5 +129,4 @@ function publish {
|
||||
done
|
||||
}
|
||||
|
||||
source $(dirname $0)/repos.inc
|
||||
source $(dirname $0)/../utils.inc
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/false
|
||||
# -*- mode: sh; -*- vim: set filetype=sh:
|
||||
|
||||
REPOS=(
|
||||
angular
|
||||
angular-animate
|
||||
angular-aria
|
||||
angular-cookies
|
||||
angular-i18n
|
||||
angular-loader
|
||||
angular-message-format
|
||||
angular-messages
|
||||
angular-mocks
|
||||
angular-resource
|
||||
angular-route
|
||||
angular-sanitize
|
||||
angular-scenario
|
||||
angular-touch
|
||||
)
|
||||
@@ -13,6 +13,21 @@ ARG_DEFS=(
|
||||
|
||||
function init {
|
||||
TMP_DIR=$(resolveDir ../../tmp)
|
||||
REPOS=(
|
||||
angular
|
||||
angular-animate
|
||||
angular-aria
|
||||
angular-cookies
|
||||
angular-i18n
|
||||
angular-loader
|
||||
angular-messages
|
||||
angular-mocks
|
||||
angular-route
|
||||
angular-resource
|
||||
angular-sanitize
|
||||
angular-scenario
|
||||
angular-touch
|
||||
)
|
||||
}
|
||||
|
||||
function prepare {
|
||||
@@ -38,5 +53,4 @@ function publish {
|
||||
done
|
||||
}
|
||||
|
||||
source $(dirname $0)/repos.inc
|
||||
source $(dirname $0)/../utils.inc
|
||||
|
||||
@@ -23,26 +23,22 @@ function init {
|
||||
}
|
||||
|
||||
function prepare {
|
||||
if [[ $IS_SNAPSHOT_BUILD ]]; then
|
||||
# nothing to prepare for snapshot builds as
|
||||
# code.angularjs.org will fetch the current snapshot from
|
||||
# the build server during publish
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "-- Cloning code.angularjs.org"
|
||||
git clone git@github.com:angular/code.angularjs.org.git $REPO_DIR --depth=1
|
||||
git clone git@github.com:angular/code.angularjs.org.git $REPO_DIR
|
||||
|
||||
#
|
||||
# copy the files from the build
|
||||
#
|
||||
echo "-- Updating code.angularjs.org"
|
||||
|
||||
if [[ $IS_SNAPSHOT_BUILD ]]; then
|
||||
#
|
||||
# update the snapshot folder
|
||||
#
|
||||
rm -rf $REPO_DIR/snapshot
|
||||
mkdir $REPO_DIR/snapshot
|
||||
cp -r $BUILD_DIR/* $REPO_DIR/snapshot/
|
||||
else
|
||||
#
|
||||
# copy the files from the build
|
||||
#
|
||||
mkdir $REPO_DIR/$NEW_VERSION
|
||||
cp -r $BUILD_DIR/* $REPO_DIR/$NEW_VERSION/
|
||||
fi
|
||||
mkdir $REPO_DIR/$NEW_VERSION
|
||||
cp -r $BUILD_DIR/* $REPO_DIR/$NEW_VERSION/
|
||||
|
||||
#
|
||||
# commit
|
||||
@@ -54,6 +50,13 @@ function prepare {
|
||||
}
|
||||
|
||||
|
||||
function _update_snapshot() {
|
||||
for backend in "$@" ; do
|
||||
echo "-- Updating snapshot version: backend=$backend"
|
||||
curl -G --data-urlencode "ver=$NEW_VERSION" http://$backend:8003/fetchLatestSnapshot.php
|
||||
done
|
||||
}
|
||||
|
||||
function _update_code() {
|
||||
cd $REPO_DIR
|
||||
|
||||
@@ -71,7 +74,12 @@ function publish {
|
||||
# the currently serving Compute Engine backends.
|
||||
# code.angularjs.org is served out of port 8003 on these backends.
|
||||
backends=("$(dig backends.angularjs.org +short TXT | python -c 'print raw_input()[1:-1].replace(",", "\n")')")
|
||||
_update_code ${backends[@]}
|
||||
|
||||
if [[ $IS_SNAPSHOT_BUILD ]]; then
|
||||
_update_snapshot ${backends[@]}
|
||||
else
|
||||
_update_code ${backends[@]}
|
||||
fi
|
||||
}
|
||||
|
||||
source $(dirname $0)/../utils.inc
|
||||
|
||||
@@ -7,9 +7,9 @@ export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
if [ $JOB = "unit" ]; then
|
||||
if [ "$BROWSER_PROVIDER" == "browserstack" ]; then
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS"
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11"
|
||||
else
|
||||
BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11,SL_iOS"
|
||||
BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11"
|
||||
fi
|
||||
|
||||
grunt test:promises-aplus
|
||||
|
||||
@@ -2,18 +2,6 @@
|
||||
|
||||
|
||||
# Wait for Connect to be ready before exiting
|
||||
# Time out if we wait for more than 2 minutes, so that we can print logs.
|
||||
let "counter=0"
|
||||
|
||||
while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do
|
||||
let "counter++"
|
||||
if [ $counter -gt 240 ]; then
|
||||
echo "Timed out after 2 minutes waiting for browser provider ready file"
|
||||
# We must manually print logs here because travis will not run
|
||||
# after_script commands if the failure occurs before the script
|
||||
# phase.
|
||||
./scripts/travis/print_logs.sh
|
||||
exit 5
|
||||
fi
|
||||
sleep .5
|
||||
done
|
||||
|
||||
+2
-9
@@ -28,14 +28,14 @@
|
||||
"manualUppercase": false,
|
||||
"isArrayLike": false,
|
||||
"forEach": false,
|
||||
"sortedKeys": false,
|
||||
"forEachSorted": false,
|
||||
"reverseParams": false,
|
||||
"nextUid": false,
|
||||
"setHashKey": false,
|
||||
"extend": false,
|
||||
"toInt": false,
|
||||
"int": false,
|
||||
"inherit": false,
|
||||
"merge": false,
|
||||
"noop": false,
|
||||
"identity": false,
|
||||
"valueFn": false,
|
||||
@@ -55,7 +55,6 @@
|
||||
"isBlob": false,
|
||||
"isBoolean": false,
|
||||
"isPromiseLike": false,
|
||||
"hasCustomToString": false,
|
||||
"trim": false,
|
||||
"escapeForRegexp": false,
|
||||
"isElement": false,
|
||||
@@ -72,8 +71,6 @@
|
||||
"toJsonReplacer": false,
|
||||
"toJson": false,
|
||||
"fromJson": false,
|
||||
"convertTimezoneToLocal": false,
|
||||
"timezoneToOffset": false,
|
||||
"startingTag": false,
|
||||
"tryDecodeURIComponent": false,
|
||||
"parseKeyValue": false,
|
||||
@@ -97,7 +94,6 @@
|
||||
"skipDestroyOnNextJQueryCleanData": true,
|
||||
|
||||
"NODE_TYPE_ELEMENT": false,
|
||||
"NODE_TYPE_ATTRIBUTE": false,
|
||||
"NODE_TYPE_TEXT": false,
|
||||
"NODE_TYPE_COMMENT": false,
|
||||
"NODE_TYPE_COMMENT": false,
|
||||
@@ -157,9 +153,6 @@
|
||||
"urlResolve": false,
|
||||
"urlIsSameOrigin": false,
|
||||
|
||||
/* ng/controller.js */
|
||||
"identifierForController": false,
|
||||
|
||||
/* ng/compile.js */
|
||||
"directiveNormalize": false,
|
||||
|
||||
|
||||
+59
-238
@@ -22,21 +22,20 @@
|
||||
nodeName_: true,
|
||||
isArrayLike: true,
|
||||
forEach: true,
|
||||
sortedKeys: true,
|
||||
forEachSorted: true,
|
||||
reverseParams: true,
|
||||
nextUid: true,
|
||||
setHashKey: true,
|
||||
extend: true,
|
||||
toInt: true,
|
||||
int: true,
|
||||
inherit: true,
|
||||
merge: true,
|
||||
noop: true,
|
||||
identity: true,
|
||||
valueFn: true,
|
||||
isUndefined: true,
|
||||
isDefined: true,
|
||||
isObject: true,
|
||||
isBlankObject: true,
|
||||
isString: true,
|
||||
isNumber: true,
|
||||
isDate: true,
|
||||
@@ -60,15 +59,12 @@
|
||||
shallowCopy: true,
|
||||
equals: true,
|
||||
csp: true,
|
||||
jq: true,
|
||||
concat: true,
|
||||
sliceArgs: true,
|
||||
bind: true,
|
||||
toJsonReplacer: true,
|
||||
toJson: true,
|
||||
fromJson: true,
|
||||
convertTimezoneToLocal: true,
|
||||
timezoneToOffset: true,
|
||||
startingTag: true,
|
||||
tryDecodeURIComponent: true,
|
||||
parseKeyValue: true,
|
||||
@@ -89,7 +85,6 @@
|
||||
createMap: true,
|
||||
|
||||
NODE_TYPE_ELEMENT: true,
|
||||
NODE_TYPE_ATTRIBUTE: true,
|
||||
NODE_TYPE_TEXT: true,
|
||||
NODE_TYPE_COMMENT: true,
|
||||
NODE_TYPE_DOCUMENT: true,
|
||||
@@ -176,7 +171,6 @@ var
|
||||
splice = [].splice,
|
||||
push = [].push,
|
||||
toString = Object.prototype.toString,
|
||||
getPrototypeOf = Object.getPrototypeOf,
|
||||
ngMinErr = minErr('ng'),
|
||||
|
||||
/** @name angular */
|
||||
@@ -202,9 +196,7 @@ function isArrayLike(obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Support: iOS 8.2 (not reproducible in simulator)
|
||||
// "length" in obj used to prevent JIT error (gh-11508)
|
||||
var length = "length" in Object(obj) && obj.length;
|
||||
var length = obj.length;
|
||||
|
||||
if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
|
||||
return true;
|
||||
@@ -269,32 +261,23 @@ function forEach(obj, iterator, context) {
|
||||
}
|
||||
} else if (obj.forEach && obj.forEach !== forEach) {
|
||||
obj.forEach(iterator, context, obj);
|
||||
} else if (isBlankObject(obj)) {
|
||||
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
||||
for (key in obj) {
|
||||
iterator.call(context, obj[key], key, obj);
|
||||
}
|
||||
} else if (typeof obj.hasOwnProperty === 'function') {
|
||||
// Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
|
||||
} else {
|
||||
for (key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
iterator.call(context, obj[key], key, obj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Slow path for objects which do not have a method `hasOwnProperty`
|
||||
for (key in obj) {
|
||||
if (hasOwnProperty.call(obj, key)) {
|
||||
iterator.call(context, obj[key], key, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function sortedKeys(obj) {
|
||||
return Object.keys(obj).sort();
|
||||
}
|
||||
|
||||
function forEachSorted(obj, iterator, context) {
|
||||
var keys = Object.keys(obj).sort();
|
||||
var keys = sortedKeys(obj);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
iterator.call(context, obj[keys[i]], keys[i]);
|
||||
}
|
||||
@@ -339,35 +322,6 @@ function setHashKey(obj, h) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function baseExtend(dst, objs, deep) {
|
||||
var h = dst.$$hashKey;
|
||||
|
||||
for (var i = 0, ii = objs.length; i < ii; ++i) {
|
||||
var obj = objs[i];
|
||||
if (!isObject(obj) && !isFunction(obj)) continue;
|
||||
var keys = Object.keys(obj);
|
||||
for (var j = 0, jj = keys.length; j < jj; j++) {
|
||||
var key = keys[j];
|
||||
var src = obj[key];
|
||||
|
||||
if (deep && isObject(src)) {
|
||||
if (isDate(src)) {
|
||||
dst[key] = new Date(src.valueOf());
|
||||
} else {
|
||||
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
|
||||
baseExtend(dst[key], [src], true);
|
||||
}
|
||||
} else {
|
||||
dst[key] = src;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setHashKey(dst, h);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.extend
|
||||
@@ -378,44 +332,31 @@ function baseExtend(dst, objs, deep) {
|
||||
* Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
|
||||
* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
|
||||
* by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
|
||||
*
|
||||
* **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
|
||||
* {@link angular.merge} for this.
|
||||
* Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).
|
||||
*
|
||||
* @param {Object} dst Destination object.
|
||||
* @param {...Object} src Source object(s).
|
||||
* @returns {Object} Reference to `dst`.
|
||||
*/
|
||||
function extend(dst) {
|
||||
return baseExtend(dst, slice.call(arguments, 1), false);
|
||||
var h = dst.$$hashKey;
|
||||
|
||||
for (var i = 1, ii = arguments.length; i < ii; i++) {
|
||||
var obj = arguments[i];
|
||||
if (obj) {
|
||||
var keys = Object.keys(obj);
|
||||
for (var j = 0, jj = keys.length; j < jj; j++) {
|
||||
var key = keys[j];
|
||||
dst[key] = obj[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setHashKey(dst, h);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.merge
|
||||
* @module ng
|
||||
* @kind function
|
||||
*
|
||||
* @description
|
||||
* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
|
||||
* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
|
||||
* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
|
||||
*
|
||||
* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
|
||||
* objects, performing a deep copy.
|
||||
*
|
||||
* @param {Object} dst Destination object.
|
||||
* @param {...Object} src Source object(s).
|
||||
* @returns {Object} Reference to `dst`.
|
||||
*/
|
||||
function merge(dst) {
|
||||
return baseExtend(dst, slice.call(arguments, 1), true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function toInt(str) {
|
||||
function int(str) {
|
||||
return parseInt(str, 10);
|
||||
}
|
||||
|
||||
@@ -468,11 +409,6 @@ identity.$inject = [];
|
||||
|
||||
function valueFn(value) {return function() {return value;};}
|
||||
|
||||
function hasCustomToString(obj) {
|
||||
return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.isUndefined
|
||||
@@ -522,16 +458,6 @@ function isObject(value) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a value is an object with a null prototype
|
||||
*
|
||||
* @returns {boolean} True if `value` is an `Object` with a null prototype
|
||||
*/
|
||||
function isBlankObject(value) {
|
||||
return value !== null && typeof value === 'object' && !getPrototypeOf(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.isString
|
||||
@@ -668,12 +594,6 @@ function isPromiseLike(obj) {
|
||||
}
|
||||
|
||||
|
||||
var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/;
|
||||
function isTypedArray(value) {
|
||||
return TYPED_ARRAY_REGEXP.test(toString.call(value));
|
||||
}
|
||||
|
||||
|
||||
var trim = function(value) {
|
||||
return isString(value) ? value.trim() : value;
|
||||
};
|
||||
@@ -711,9 +631,8 @@ function isElement(node) {
|
||||
*/
|
||||
function makeMap(str) {
|
||||
var obj = {}, items = str.split(","), i;
|
||||
for (i = 0; i < items.length; i++) {
|
||||
for (i = 0; i < items.length; i++)
|
||||
obj[items[i]] = true;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -728,10 +647,9 @@ function includes(array, obj) {
|
||||
|
||||
function arrayRemove(array, value) {
|
||||
var index = array.indexOf(value);
|
||||
if (index >= 0) {
|
||||
if (index >= 0)
|
||||
array.splice(index, 1);
|
||||
}
|
||||
return index;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -797,40 +715,20 @@ function copy(source, destination, stackSource, stackDest) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}
|
||||
if (isTypedArray(destination)) {
|
||||
throw ngMinErr('cpta',
|
||||
"Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
|
||||
if (!destination) {
|
||||
destination = source;
|
||||
if (isObject(source)) {
|
||||
var index;
|
||||
if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
|
||||
return stackDest[index];
|
||||
}
|
||||
|
||||
// TypedArray, Date and RegExp have specific copy functionality and must be
|
||||
// pushed onto the stack before returning.
|
||||
// Array and other objects create the base object and recurse to copy child
|
||||
// objects. The array/object will be pushed onto the stack when recursed.
|
||||
if (source) {
|
||||
if (isArray(source)) {
|
||||
return copy(source, [], stackSource, stackDest);
|
||||
} else if (isTypedArray(source)) {
|
||||
destination = new source.constructor(source);
|
||||
destination = copy(source, [], stackSource, stackDest);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else {
|
||||
var emptyObject = Object.create(getPrototypeOf(source));
|
||||
return copy(source, emptyObject, stackSource, stackDest);
|
||||
}
|
||||
|
||||
if (stackDest) {
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
} else if (isObject(source)) {
|
||||
var emptyObject = Object.create(Object.getPrototypeOf(source));
|
||||
destination = copy(source, emptyObject, stackSource, stackDest);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -841,15 +739,23 @@ function copy(source, destination, stackSource, stackDest) {
|
||||
stackDest = stackDest || [];
|
||||
|
||||
if (isObject(source)) {
|
||||
var index = stackSource.indexOf(source);
|
||||
if (index !== -1) return stackDest[index];
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
}
|
||||
|
||||
var result, key;
|
||||
var result;
|
||||
if (isArray(source)) {
|
||||
destination.length = 0;
|
||||
for (var i = 0; i < source.length; i++) {
|
||||
destination.push(copy(source[i], null, stackSource, stackDest));
|
||||
result = copy(source[i], null, stackSource, stackDest);
|
||||
if (isObject(source[i])) {
|
||||
stackSource.push(source[i]);
|
||||
stackDest.push(result);
|
||||
}
|
||||
destination.push(result);
|
||||
}
|
||||
} else {
|
||||
var h = destination.$$hashKey;
|
||||
@@ -860,28 +766,19 @@ function copy(source, destination, stackSource, stackDest) {
|
||||
delete destination[key];
|
||||
});
|
||||
}
|
||||
if (isBlankObject(source)) {
|
||||
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
||||
for (key in source) {
|
||||
destination[key] = copy(source[key], null, stackSource, stackDest);
|
||||
}
|
||||
} else if (source && typeof source.hasOwnProperty === 'function') {
|
||||
// Slow path, which must rely on hasOwnProperty
|
||||
for (key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
destination[key] = copy(source[key], null, stackSource, stackDest);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Slowest path --- hasOwnProperty can't be called as a method
|
||||
for (key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
destination[key] = copy(source[key], null, stackSource, stackDest);
|
||||
for (var key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
result = copy(source[key], null, stackSource, stackDest);
|
||||
if (isObject(source[key])) {
|
||||
stackSource.push(source[key]);
|
||||
stackDest.push(result);
|
||||
}
|
||||
destination[key] = result;
|
||||
}
|
||||
}
|
||||
setHashKey(destination,h);
|
||||
}
|
||||
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
@@ -964,14 +861,14 @@ function equals(o1, o2) {
|
||||
} else {
|
||||
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
|
||||
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
|
||||
keySet = createMap();
|
||||
keySet = {};
|
||||
for (key in o1) {
|
||||
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
|
||||
if (!equals(o1[key], o2[key])) return false;
|
||||
keySet[key] = true;
|
||||
}
|
||||
for (key in o2) {
|
||||
if (!(key in keySet) &&
|
||||
if (!keySet.hasOwnProperty(key) &&
|
||||
key.charAt(0) !== '$' &&
|
||||
o2[key] !== undefined &&
|
||||
!isFunction(o2[key])) return false;
|
||||
@@ -1002,58 +899,7 @@ var csp = function() {
|
||||
return (csp.isActive_ = active);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @module ng
|
||||
* @name ngJq
|
||||
*
|
||||
* @element ANY
|
||||
* @param {string=} ngJq the name of the library available under `window`
|
||||
* to be used for angular.element
|
||||
* @description
|
||||
* Use this directive to force the angular.element library. This should be
|
||||
* used to force either jqLite by leaving ng-jq blank or setting the name of
|
||||
* the jquery variable under window (eg. jQuery).
|
||||
*
|
||||
* Since angular looks for this directive when it is loaded (doesn't wait for the
|
||||
* DOMContentLoaded event), it must be placed on an element that comes before the script
|
||||
* which loads angular. Also, only the first instance of `ng-jq` will be used and all
|
||||
* others ignored.
|
||||
*
|
||||
* @example
|
||||
* This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
|
||||
```html
|
||||
<!doctype html>
|
||||
<html ng-app ng-jq>
|
||||
...
|
||||
...
|
||||
</html>
|
||||
```
|
||||
* @example
|
||||
* This example shows how to use a jQuery based library of a different name.
|
||||
* The library name must be available at the top most 'window'.
|
||||
```html
|
||||
<!doctype html>
|
||||
<html ng-app ng-jq="jQueryLib">
|
||||
...
|
||||
...
|
||||
</html>
|
||||
```
|
||||
*/
|
||||
var jq = function() {
|
||||
if (isDefined(jq.name_)) return jq.name_;
|
||||
var el;
|
||||
var i, ii = ngAttrPrefixes.length, prefix, name;
|
||||
for (i = 0; i < ii; ++i) {
|
||||
prefix = ngAttrPrefixes[i];
|
||||
if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
|
||||
name = el.getAttribute(prefix + 'jq');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (jq.name_ = name);
|
||||
};
|
||||
|
||||
function concat(array1, array2, index) {
|
||||
return array1.concat(slice.call(array2, index));
|
||||
@@ -1132,8 +978,8 @@ function toJsonReplacer(key, value) {
|
||||
* stripped since angular uses this notation internally.
|
||||
*
|
||||
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
|
||||
* @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
|
||||
* If set to an integer, the JSON output will contain that many spaces per indentation.
|
||||
* @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
|
||||
* If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
|
||||
* @returns {string|undefined} JSON-ified string representing `obj`.
|
||||
*/
|
||||
function toJson(obj, pretty) {
|
||||
@@ -1164,26 +1010,6 @@ function fromJson(json) {
|
||||
}
|
||||
|
||||
|
||||
function timezoneToOffset(timezone, fallback) {
|
||||
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
|
||||
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
|
||||
}
|
||||
|
||||
|
||||
function addDateMinutes(date, minutes) {
|
||||
date = new Date(date.getTime());
|
||||
date.setMinutes(date.getMinutes() + minutes);
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
function convertTimezoneToLocal(date, timezone, reverse) {
|
||||
reverse = reverse ? -1 : 1;
|
||||
var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
|
||||
return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @returns {string} Returns the string representation of the element.
|
||||
*/
|
||||
@@ -1312,9 +1138,10 @@ var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
|
||||
|
||||
function getNgAttribute(element, ngAttr) {
|
||||
var attr, i, ii = ngAttrPrefixes.length;
|
||||
element = jqLite(element);
|
||||
for (i = 0; i < ii; ++i) {
|
||||
attr = ngAttrPrefixes[i] + ngAttr;
|
||||
if (isString(attr = element.getAttribute(attr))) {
|
||||
if (isString(attr = element.attr(attr))) {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
@@ -1645,12 +1472,7 @@ function bindJQuery() {
|
||||
}
|
||||
|
||||
// bind to jQuery if present;
|
||||
var jqName = jq();
|
||||
jQuery = window.jQuery; // use default jQuery.
|
||||
if (isDefined(jqName)) { // `ngJq` present
|
||||
jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
|
||||
}
|
||||
|
||||
jQuery = window.jQuery;
|
||||
// Use jQuery if it exists with proper functionality, otherwise default to us.
|
||||
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
|
||||
// Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
|
||||
@@ -1789,7 +1611,6 @@ function createMap() {
|
||||
}
|
||||
|
||||
var NODE_TYPE_ELEMENT = 1;
|
||||
var NODE_TYPE_ATTRIBUTE = 2;
|
||||
var NODE_TYPE_TEXT = 3;
|
||||
var NODE_TYPE_COMMENT = 8;
|
||||
var NODE_TYPE_DOCUMENT = 9;
|
||||
|
||||
+2
-15
@@ -57,8 +57,6 @@
|
||||
|
||||
$AnchorScrollProvider,
|
||||
$AnimateProvider,
|
||||
$$CoreAnimateQueueProvider,
|
||||
$$CoreAnimateRunnerProvider,
|
||||
$BrowserProvider,
|
||||
$CacheFactoryProvider,
|
||||
$ControllerProvider,
|
||||
@@ -67,10 +65,7 @@
|
||||
$FilterProvider,
|
||||
$InterpolateProvider,
|
||||
$IntervalProvider,
|
||||
$$HashMapProvider,
|
||||
$HttpProvider,
|
||||
$HttpParamSerializerProvider,
|
||||
$HttpParamSerializerJQLikeProvider,
|
||||
$HttpBackendProvider,
|
||||
$LocationProvider,
|
||||
$LogProvider,
|
||||
@@ -89,8 +84,7 @@
|
||||
$$RAFProvider,
|
||||
$$AsyncCallbackProvider,
|
||||
$WindowProvider,
|
||||
$$jqLiteProvider,
|
||||
$$CookieReaderProvider
|
||||
$$jqLiteProvider
|
||||
*/
|
||||
|
||||
|
||||
@@ -122,7 +116,6 @@ function publishExternalAPI(angular) {
|
||||
'bootstrap': bootstrap,
|
||||
'copy': copy,
|
||||
'extend': extend,
|
||||
'merge': merge,
|
||||
'equals': equals,
|
||||
'element': jqLite,
|
||||
'forEach': forEach,
|
||||
@@ -219,8 +212,6 @@ function publishExternalAPI(angular) {
|
||||
$provide.provider({
|
||||
$anchorScroll: $AnchorScrollProvider,
|
||||
$animate: $AnimateProvider,
|
||||
$$animateQueue: $$CoreAnimateQueueProvider,
|
||||
$$AnimateRunner: $$CoreAnimateRunnerProvider,
|
||||
$browser: $BrowserProvider,
|
||||
$cacheFactory: $CacheFactoryProvider,
|
||||
$controller: $ControllerProvider,
|
||||
@@ -230,8 +221,6 @@ function publishExternalAPI(angular) {
|
||||
$interpolate: $InterpolateProvider,
|
||||
$interval: $IntervalProvider,
|
||||
$http: $HttpProvider,
|
||||
$httpParamSerializer: $HttpParamSerializerProvider,
|
||||
$httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
|
||||
$httpBackend: $HttpBackendProvider,
|
||||
$location: $LocationProvider,
|
||||
$log: $LogProvider,
|
||||
@@ -249,9 +238,7 @@ function publishExternalAPI(angular) {
|
||||
$window: $WindowProvider,
|
||||
$$rAF: $$RAFProvider,
|
||||
$$asyncCallback: $$AsyncCallbackProvider,
|
||||
$$jqLite: $$jqLiteProvider,
|
||||
$$HashMap: $$HashMapProvider,
|
||||
$$cookieReader: $$CookieReaderProvider
|
||||
$$jqLite: $$jqLiteProvider
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license AngularJS v"NG_VERSION_FULL"
|
||||
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, document, undefined) {
|
||||
|
||||
@@ -73,9 +73,3 @@ HashMap.prototype = {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
var $$HashMapProvider = [function() {
|
||||
this.$get = [function() {
|
||||
return HashMap;
|
||||
}];
|
||||
}];
|
||||
|
||||
@@ -179,7 +179,7 @@ function annotate(fn, strictDi, name) {
|
||||
* Return an instance of the service.
|
||||
*
|
||||
* @param {string} name The name of the instance to retrieve.
|
||||
* @param {string=} caller An optional string to provide the origin of the function call for error messages.
|
||||
* @param {string} caller An optional string to provide the origin of the function call for error messages.
|
||||
* @return {*} The instance.
|
||||
*/
|
||||
|
||||
@@ -190,8 +190,8 @@ function annotate(fn, strictDi, name) {
|
||||
* @description
|
||||
* Invoke the method and supply the method arguments from the `$injector`.
|
||||
*
|
||||
* @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
|
||||
* injected according to the {@link guide/di $inject Annotation} rules.
|
||||
* @param {!Function} fn The function to invoke. Function parameters are injected according to the
|
||||
* {@link guide/di $inject Annotation} rules.
|
||||
* @param {Object=} self The `this` for the invoked method.
|
||||
* @param {Object=} locals Optional object. If preset then any argument names are read from this
|
||||
* object first, before the `$injector` is consulted.
|
||||
@@ -458,8 +458,8 @@ function annotate(fn, strictDi, name) {
|
||||
* configure your service in a provider.
|
||||
*
|
||||
* @param {string} name The name of the instance.
|
||||
* @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
|
||||
* Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
|
||||
* @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
|
||||
* for `$provide.provider(name, {$get: $getFn})`.
|
||||
* @returns {Object} registered provider instance
|
||||
*
|
||||
* @example
|
||||
@@ -494,8 +494,7 @@ function annotate(fn, strictDi, name) {
|
||||
* as a type/class.
|
||||
*
|
||||
* @param {string} name The name of the instance.
|
||||
* @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
|
||||
* that will be instantiated.
|
||||
* @param {Function} constructor A class (constructor function) that will be instantiated.
|
||||
* @returns {Object} registered provider instance
|
||||
*
|
||||
* @example
|
||||
@@ -594,7 +593,7 @@ function annotate(fn, strictDi, name) {
|
||||
* object which replaces or wraps and delegates to the original service.
|
||||
*
|
||||
* @param {string} name The name of the service to decorate.
|
||||
* @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
|
||||
* @param {function()} decorator This function will be invoked when the service needs to be
|
||||
* instantiated and should return the decorated service instance. The function is called using
|
||||
* the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
|
||||
* Local injection arguments:
|
||||
@@ -645,7 +644,7 @@ function createInjector(modulesToLoad, strictDi) {
|
||||
}));
|
||||
|
||||
|
||||
forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
|
||||
forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
|
||||
|
||||
return instanceInjector;
|
||||
|
||||
|
||||
+4
-17
@@ -39,7 +39,7 @@
|
||||
* Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
|
||||
* commonly needed functionality with the goal of having a very small footprint.</div>
|
||||
*
|
||||
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
|
||||
* To use jQuery, simply load it before `DOMContentLoaded` event fired.
|
||||
*
|
||||
* <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
|
||||
* jqLite; they are never raw DOM references.</div>
|
||||
@@ -55,7 +55,7 @@
|
||||
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
|
||||
* - [`clone()`](http://api.jquery.com/clone/)
|
||||
* - [`contents()`](http://api.jquery.com/contents/)
|
||||
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. 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()`
|
||||
* - [`data()`](http://api.jquery.com/data/)
|
||||
* - [`detach()`](http://api.jquery.com/detach/)
|
||||
* - [`empty()`](http://api.jquery.com/empty/)
|
||||
@@ -182,13 +182,6 @@ function jqLiteAcceptsData(node) {
|
||||
return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
|
||||
}
|
||||
|
||||
function jqLiteHasData(node) {
|
||||
for (var key in jqCache[node.ng339]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function jqLiteBuildFragment(html, context) {
|
||||
var tmp, tag, wrap,
|
||||
fragment = context.createDocumentFragment(),
|
||||
@@ -563,8 +556,7 @@ function getAliasedAttrName(element, name) {
|
||||
|
||||
forEach({
|
||||
data: jqLiteData,
|
||||
removeData: jqLiteRemoveData,
|
||||
hasData: jqLiteHasData
|
||||
removeData: jqLiteRemoveData
|
||||
}, function(fn, name) {
|
||||
JQLite[name] = fn;
|
||||
});
|
||||
@@ -606,10 +598,6 @@ forEach({
|
||||
},
|
||||
|
||||
attr: function(element, name, value) {
|
||||
var nodeType = element.nodeType;
|
||||
if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
|
||||
return;
|
||||
}
|
||||
var lowercasedName = lowercase(name);
|
||||
if (BOOLEAN_ATTR[lowercasedName]) {
|
||||
if (isDefined(value)) {
|
||||
@@ -874,9 +862,8 @@ forEach({
|
||||
children: function(element) {
|
||||
var children = [];
|
||||
forEach(element.childNodes, function(element) {
|
||||
if (element.nodeType === NODE_TYPE_ELEMENT) {
|
||||
if (element.nodeType === NODE_TYPE_ELEMENT)
|
||||
children.push(element);
|
||||
}
|
||||
});
|
||||
return children;
|
||||
},
|
||||
|
||||
+9
-41
@@ -146,7 +146,7 @@ function setupModuleLoader(window) {
|
||||
* @description
|
||||
* See {@link auto.$provide#provider $provide.provider()}.
|
||||
*/
|
||||
provider: invokeLaterAndSetModuleName('$provide', 'provider'),
|
||||
provider: invokeLater('$provide', 'provider'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -157,7 +157,7 @@ function setupModuleLoader(window) {
|
||||
* @description
|
||||
* See {@link auto.$provide#factory $provide.factory()}.
|
||||
*/
|
||||
factory: invokeLaterAndSetModuleName('$provide', 'factory'),
|
||||
factory: invokeLater('$provide', 'factory'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -168,7 +168,7 @@ function setupModuleLoader(window) {
|
||||
* @description
|
||||
* See {@link auto.$provide#service $provide.service()}.
|
||||
*/
|
||||
service: invokeLaterAndSetModuleName('$provide', 'service'),
|
||||
service: invokeLater('$provide', 'service'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -193,18 +193,6 @@ function setupModuleLoader(window) {
|
||||
*/
|
||||
constant: invokeLater('$provide', 'constant', 'unshift'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name angular.Module#decorator
|
||||
* @module ng
|
||||
* @param {string} The name of the service to decorate.
|
||||
* @param {Function} This function will be invoked when the service needs to be
|
||||
* instantiated and should return the decorated service instance.
|
||||
* @description
|
||||
* See {@link auto.$provide#decorator $provide.decorator()}.
|
||||
*/
|
||||
decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name angular.Module#animation
|
||||
@@ -218,7 +206,7 @@ function setupModuleLoader(window) {
|
||||
*
|
||||
*
|
||||
* Defines an animation hook that can be later used with
|
||||
* {@link $animate $animate} service and directives that use this service.
|
||||
* {@link ngAnimate.$animate $animate} service and directives that use this service.
|
||||
*
|
||||
* ```js
|
||||
* module.animation('.animation-name', function($inject1, $inject2) {
|
||||
@@ -237,25 +225,18 @@ function setupModuleLoader(window) {
|
||||
* See {@link ng.$animateProvider#register $animateProvider.register()} and
|
||||
* {@link ngAnimate ngAnimate module} for more information.
|
||||
*/
|
||||
animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
|
||||
animation: invokeLater('$animateProvider', 'register'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name angular.Module#filter
|
||||
* @module ng
|
||||
* @param {string} name Filter name - this must be a valid angular expression identifier
|
||||
* @param {string} name Filter name.
|
||||
* @param {Function} filterFactory Factory function for creating new instance of filter.
|
||||
* @description
|
||||
* See {@link ng.$filterProvider#register $filterProvider.register()}.
|
||||
*
|
||||
* <div class="alert alert-warning">
|
||||
* **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
* Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
|
||||
* your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
|
||||
* (`myapp_subsection_filterx`).
|
||||
* </div>
|
||||
*/
|
||||
filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
|
||||
filter: invokeLater('$filterProvider', 'register'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -267,7 +248,7 @@ function setupModuleLoader(window) {
|
||||
* @description
|
||||
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
|
||||
*/
|
||||
controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
|
||||
controller: invokeLater('$controllerProvider', 'register'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -280,7 +261,7 @@ function setupModuleLoader(window) {
|
||||
* @description
|
||||
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
|
||||
*/
|
||||
directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
|
||||
directive: invokeLater('$compileProvider', 'directive'),
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -330,19 +311,6 @@ function setupModuleLoader(window) {
|
||||
return moduleInstance;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} provider
|
||||
* @param {string} method
|
||||
* @returns {angular.Module}
|
||||
*/
|
||||
function invokeLaterAndSetModuleName(provider, method) {
|
||||
return function(recipeName, factoryFunction) {
|
||||
if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
|
||||
invokeQueue.push([provider, method, arguments]);
|
||||
return moduleInstance;
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license AngularJS v"NG_VERSION_FULL"
|
||||
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
+13
-18
@@ -33,33 +33,28 @@
|
||||
function minErr(module, ErrorConstructor) {
|
||||
ErrorConstructor = ErrorConstructor || Error;
|
||||
return function() {
|
||||
var SKIP_INDEXES = 2;
|
||||
var code = arguments[0],
|
||||
prefix = '[' + (module ? module + ':' : '') + code + '] ',
|
||||
template = arguments[1],
|
||||
templateArgs = arguments,
|
||||
|
||||
var templateArgs = arguments,
|
||||
code = templateArgs[0],
|
||||
message = '[' + (module ? module + ':' : '') + code + '] ',
|
||||
template = templateArgs[1],
|
||||
paramPrefix, i;
|
||||
message, i;
|
||||
|
||||
message += template.replace(/\{\d+\}/g, function(match) {
|
||||
var index = +match.slice(1, -1),
|
||||
shiftedIndex = index + SKIP_INDEXES;
|
||||
message = prefix + template.replace(/\{\d+\}/g, function(match) {
|
||||
var index = +match.slice(1, -1), arg;
|
||||
|
||||
if (shiftedIndex < templateArgs.length) {
|
||||
return toDebugString(templateArgs[shiftedIndex]);
|
||||
if (index + 2 < templateArgs.length) {
|
||||
return toDebugString(templateArgs[index + 2]);
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
|
||||
message += '\nhttp://errors.angularjs.org/"NG_VERSION_FULL"/' +
|
||||
message = message + '\nhttp://errors.angularjs.org/"NG_VERSION_FULL"/' +
|
||||
(module ? module + '/' : '') + code;
|
||||
|
||||
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
|
||||
message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
|
||||
encodeURIComponent(toDebugString(templateArgs[i]));
|
||||
for (i = 2; i < arguments.length; i++) {
|
||||
message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
|
||||
encodeURIComponent(toDebugString(arguments[i]));
|
||||
}
|
||||
|
||||
return new ErrorConstructor(message);
|
||||
};
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license AngularJS v"NG_VERSION_FULL"
|
||||
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular, undefined) {
|
||||
|
||||
+5
-10
@@ -38,10 +38,9 @@ function $AnchorScrollProvider() {
|
||||
* @requires $rootScope
|
||||
*
|
||||
* @description
|
||||
* When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
|
||||
* current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
|
||||
* in the
|
||||
* [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
|
||||
* When called, it checks the current value of {@link ng.$location#hash $location.hash()} and
|
||||
* scrolls to the related element, according to the rules specified in the
|
||||
* [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
|
||||
*
|
||||
* It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
|
||||
* match any anchor whenever it changes. This can be disabled by calling
|
||||
@@ -50,9 +49,6 @@ function $AnchorScrollProvider() {
|
||||
* Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
|
||||
* vertical scroll-offset (either fixed or dynamic).
|
||||
*
|
||||
* @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of
|
||||
* {@link ng.$location#hash $location.hash()} will be used.
|
||||
*
|
||||
* @property {(number|function|jqLite)} yOffset
|
||||
* If set, specifies a vertical scroll-offset. This is often useful when there are fixed
|
||||
* positioned elements at the top of the page, such as navbars, headers etc.
|
||||
@@ -236,9 +232,8 @@ function $AnchorScrollProvider() {
|
||||
}
|
||||
}
|
||||
|
||||
function scroll(hash) {
|
||||
hash = isString(hash) ? hash : $location.hash();
|
||||
var elm;
|
||||
function scroll() {
|
||||
var hash = $location.hash(), elm;
|
||||
|
||||
// empty hash, scroll to the top of the page
|
||||
if (!hash) scrollTo(null);
|
||||
|
||||
+247
-465
@@ -1,168 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
var $animateMinErr = minErr('$animate');
|
||||
var ELEMENT_NODE = 1;
|
||||
var NG_ANIMATE_CLASSNAME = 'ng-animate';
|
||||
|
||||
function mergeClasses(a,b) {
|
||||
if (!a && !b) return '';
|
||||
if (!a) return b;
|
||||
if (!b) return a;
|
||||
if (isArray(a)) a = a.join(' ');
|
||||
if (isArray(b)) b = b.join(' ');
|
||||
return a + ' ' + b;
|
||||
}
|
||||
|
||||
function extractElementNode(element) {
|
||||
for (var i = 0; i < element.length; i++) {
|
||||
var elm = element[i];
|
||||
if (elm.nodeType === ELEMENT_NODE) {
|
||||
return elm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function splitClasses(classes) {
|
||||
if (isString(classes)) {
|
||||
classes = classes.split(' ');
|
||||
}
|
||||
|
||||
// Use createMap() to prevent class assumptions involving property names in
|
||||
// Object.prototype
|
||||
var obj = createMap();
|
||||
forEach(classes, function(klass) {
|
||||
// sometimes the split leaves empty string values
|
||||
// incase extra spaces were applied to the options
|
||||
if (klass.length) {
|
||||
obj[klass] = true;
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
// if any other type of options value besides an Object value is
|
||||
// passed into the $animate.method() animation then this helper code
|
||||
// will be run which will ignore it. While this patch is not the
|
||||
// greatest solution to this, a lot of existing plugins depend on
|
||||
// $animate to either call the callback (< 1.2) or return a promise
|
||||
// that can be changed. This helper function ensures that the options
|
||||
// are wiped clean incase a callback function is provided.
|
||||
function prepareAnimateOptions(options) {
|
||||
return isObject(options)
|
||||
? 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;
|
||||
}];
|
||||
};
|
||||
|
||||
// this is prefixed with Core since it conflicts with
|
||||
// the animateQueueProvider defined in ngAnimate/animateQueue.js
|
||||
var $$CoreAnimateQueueProvider = function() {
|
||||
var postDigestQueue = new HashMap();
|
||||
var postDigestElements = [];
|
||||
|
||||
this.$get = ['$$AnimateRunner', '$rootScope',
|
||||
function($$AnimateRunner, $rootScope) {
|
||||
return {
|
||||
enabled: noop,
|
||||
on: noop,
|
||||
off: noop,
|
||||
pin: noop,
|
||||
|
||||
push: function(element, event, options, domOperation) {
|
||||
domOperation && domOperation();
|
||||
|
||||
options = options || {};
|
||||
options.from && element.css(options.from);
|
||||
options.to && element.css(options.to);
|
||||
|
||||
if (options.addClass || options.removeClass) {
|
||||
addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
|
||||
}
|
||||
|
||||
return new $$AnimateRunner(); // jshint ignore:line
|
||||
}
|
||||
};
|
||||
|
||||
function addRemoveClassesPostDigest(element, add, remove) {
|
||||
var data = postDigestQueue.get(element);
|
||||
var classVal;
|
||||
|
||||
if (!data) {
|
||||
postDigestQueue.put(element, data = {});
|
||||
postDigestElements.push(element);
|
||||
}
|
||||
|
||||
if (add) {
|
||||
forEach(add.split(' '), function(className) {
|
||||
if (className) {
|
||||
data[className] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
forEach(remove.split(' '), function(className) {
|
||||
if (className) {
|
||||
data[className] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (postDigestElements.length > 1) return;
|
||||
|
||||
$rootScope.$$postDigest(function() {
|
||||
forEach(postDigestElements, function(element) {
|
||||
var data = postDigestQueue.get(element);
|
||||
if (data) {
|
||||
var existing = splitClasses(element.attr('class'));
|
||||
var toAdd = '';
|
||||
var toRemove = '';
|
||||
forEach(data, function(status, className) {
|
||||
var hasClass = !!existing[className];
|
||||
if (status !== hasClass) {
|
||||
if (status) {
|
||||
toAdd += (toAdd.length ? ' ' : '') + className;
|
||||
} else {
|
||||
toRemove += (toRemove.length ? ' ' : '') + className;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
forEach(element, function(elm) {
|
||||
toAdd && jqLiteAddClass(elm, toAdd);
|
||||
toRemove && jqLiteRemoveClass(elm, toRemove);
|
||||
});
|
||||
postDigestQueue.remove(element);
|
||||
}
|
||||
});
|
||||
|
||||
postDigestElements.length = 0;
|
||||
});
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc provider
|
||||
@@ -170,18 +8,20 @@ var $$CoreAnimateQueueProvider = function() {
|
||||
*
|
||||
* @description
|
||||
* Default implementation of $animate that doesn't perform any animations, instead just
|
||||
* synchronously performs DOM updates and resolves the returned runner promise.
|
||||
* synchronously performs DOM
|
||||
* updates and calls done() callbacks.
|
||||
*
|
||||
* In order to enable animations the `ngAnimate` module has to be loaded.
|
||||
* In order to enable animations the ngAnimate module has to be loaded.
|
||||
*
|
||||
* To see the functional implementation check out `src/ngAnimate/animate.js`.
|
||||
* To see the functional implementation check out src/ngAnimate/animate.js
|
||||
*/
|
||||
var $AnimateProvider = ['$provide', function($provide) {
|
||||
var provider = this;
|
||||
|
||||
this.$$registeredAnimations = Object.create(null);
|
||||
|
||||
/**
|
||||
this.$$selectors = {};
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $animateProvider#register
|
||||
*
|
||||
@@ -190,43 +30,33 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* animation object which contains callback functions for each event that is expected to be
|
||||
* animated.
|
||||
*
|
||||
* * `eventFn`: `function(element, ... , doneFunction, options)`
|
||||
* The element to animate, the `doneFunction` and the options fed into the animation. Depending
|
||||
* on the type of animation additional arguments will be injected into the animation function. The
|
||||
* list below explains the function signatures for the different animation methods:
|
||||
* * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
|
||||
* must be called once the element animation is complete. If a function is returned then the
|
||||
* animation service will use this function to cancel the animation whenever a cancel event is
|
||||
* triggered.
|
||||
*
|
||||
* - setClass: function(element, addedClasses, removedClasses, doneFunction, options)
|
||||
* - addClass: function(element, addedClasses, doneFunction, options)
|
||||
* - removeClass: function(element, removedClasses, doneFunction, options)
|
||||
* - enter, leave, move: function(element, doneFunction, options)
|
||||
* - animate: function(element, fromStyles, toStyles, doneFunction, options)
|
||||
*
|
||||
* Make sure to trigger the `doneFunction` once the animation is fully complete.
|
||||
*
|
||||
* ```js
|
||||
* return {
|
||||
* //enter, leave, move signature
|
||||
* eventFn : function(element, done, options) {
|
||||
* //code to run the animation
|
||||
* //once complete, then run done()
|
||||
* return function endFunction(wasCancelled) {
|
||||
* //code to cancel the animation
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* eventFn : function(element, done) {
|
||||
* //code to run the animation
|
||||
* //once complete, then run done()
|
||||
* return function cancellationFunction() {
|
||||
* //code to cancel the animation
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).
|
||||
* @param {string} name The name of the animation.
|
||||
* @param {Function} factory The factory function that will be executed to return the animation
|
||||
* object.
|
||||
*/
|
||||
this.register = function(name, factory) {
|
||||
if (name && name.charAt(0) !== '.') {
|
||||
throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name);
|
||||
}
|
||||
|
||||
var key = name + '-animation';
|
||||
provider.$$registeredAnimations[name.substr(1)] = key;
|
||||
if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
|
||||
"Expecting class selector starting with '.' got '{0}'.", name);
|
||||
this.$$selectors[name.substr(1)] = key;
|
||||
$provide.factory(key, factory);
|
||||
};
|
||||
|
||||
@@ -237,8 +67,8 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* @description
|
||||
* Sets and/or returns the CSS class regular expression that is checked when performing
|
||||
* an animation. Upon bootstrap the classNameFilter value is not set at all and will
|
||||
* therefore enable $animate to attempt to perform an animation on any element that is triggered.
|
||||
* When setting the `classNameFilter` value, animations will only be performed on elements
|
||||
* therefore enable $animate to attempt to perform an animation on any element.
|
||||
* When setting the classNameFilter value, animations will only be performed on elements
|
||||
* that successfully match the filter expression. This in turn can boost performance
|
||||
* for low-powered devices as well as applications containing a lot of structural operations.
|
||||
* @param {RegExp=} expression The className expression which will be checked against all animations
|
||||
@@ -247,167 +77,102 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
this.classNameFilter = function(expression) {
|
||||
if (arguments.length === 1) {
|
||||
this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
|
||||
if (this.$$classNameFilter) {
|
||||
var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
|
||||
if (reservedRegex.test(this.$$classNameFilter.toString())) {
|
||||
throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.$$classNameFilter;
|
||||
};
|
||||
|
||||
this.$get = ['$$animateQueue', function($$animateQueue) {
|
||||
function domInsert(element, parentElement, afterElement) {
|
||||
// if for some reason the previous element was removed
|
||||
// from the dom sometime before this code runs then let's
|
||||
// just stick to using the parent element as the anchor
|
||||
if (afterElement) {
|
||||
var afterNode = extractElementNode(afterElement);
|
||||
if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {
|
||||
afterElement = null;
|
||||
this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {
|
||||
|
||||
var currentDefer;
|
||||
|
||||
function runAnimationPostDigest(fn) {
|
||||
var cancelFn, defer = $$q.defer();
|
||||
defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {
|
||||
cancelFn && cancelFn();
|
||||
};
|
||||
|
||||
$rootScope.$$postDigest(function ngAnimatePostDigest() {
|
||||
cancelFn = fn(function ngAnimateNotifyComplete() {
|
||||
defer.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
function resolveElementClasses(element, classes) {
|
||||
var toAdd = [], toRemove = [];
|
||||
|
||||
var hasClasses = createMap();
|
||||
forEach((element.attr('class') || '').split(/\s+/), function(className) {
|
||||
hasClasses[className] = true;
|
||||
});
|
||||
|
||||
forEach(classes, function(status, className) {
|
||||
var hasClass = hasClasses[className];
|
||||
|
||||
// If the most recent class manipulation (via $animate) was to remove the class, and the
|
||||
// element currently has the class, the class is scheduled for removal. Otherwise, if
|
||||
// the most recent class manipulation (via $animate) was to add the class, and the
|
||||
// element does not currently have the class, the class is scheduled to be added.
|
||||
if (status === false && hasClass) {
|
||||
toRemove.push(className);
|
||||
} else if (status === true && !hasClass) {
|
||||
toAdd.push(className);
|
||||
}
|
||||
});
|
||||
|
||||
return (toAdd.length + toRemove.length) > 0 &&
|
||||
[toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];
|
||||
}
|
||||
|
||||
function cachedClassManipulation(cache, classes, op) {
|
||||
for (var i=0, ii = classes.length; i < ii; ++i) {
|
||||
var className = classes[i];
|
||||
cache[className] = op;
|
||||
}
|
||||
}
|
||||
|
||||
function asyncPromise() {
|
||||
// only serve one instance of a promise in order to save CPU cycles
|
||||
if (!currentDefer) {
|
||||
currentDefer = $$q.defer();
|
||||
$$asyncCallback(function() {
|
||||
currentDefer.resolve();
|
||||
currentDefer = null;
|
||||
});
|
||||
}
|
||||
return currentDefer.promise;
|
||||
}
|
||||
|
||||
function applyStyles(element, options) {
|
||||
if (angular.isObject(options)) {
|
||||
var styles = extend(options.from || {}, options.to || {});
|
||||
element.css(styles);
|
||||
}
|
||||
afterElement ? afterElement.after(element) : parentElement.prepend(element);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc service
|
||||
* @name $animate
|
||||
* @description The $animate service exposes a series of DOM utility methods that provide support
|
||||
* for animation hooks. The default behavior is the application of DOM operations, however,
|
||||
* when an animation is detected (and animations are enabled), $animate will do the heavy lifting
|
||||
* to ensure that animation runs with the triggered DOM operation.
|
||||
* @description The $animate service provides rudimentary DOM manipulation functions to
|
||||
* insert, remove and move elements within the DOM, as well as adding and removing classes.
|
||||
* This service is the core service used by the ngAnimate $animator service which provides
|
||||
* high-level animation hooks for CSS and JavaScript.
|
||||
*
|
||||
* By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't
|
||||
* included and only when it is active then the animation hooks that `$animate` triggers will be
|
||||
* functional. Once active then all structural `ng-` directives will trigger animations as they perform
|
||||
* their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
|
||||
* `ngShow`, `ngHide` and `ngMessages` also provide support for animations.
|
||||
* $animate is available in the AngularJS core, however, the ngAnimate module must be included
|
||||
* to enable full out animation support. Otherwise, $animate will only perform simple DOM
|
||||
* manipulation operations.
|
||||
*
|
||||
* It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.
|
||||
*
|
||||
* To learn more about enabling animation support, click here to visit the
|
||||
* {@link ngAnimate ngAnimate module page}.
|
||||
* To learn more about enabling animation support, click here to visit the {@link ngAnimate
|
||||
* ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
|
||||
* page}.
|
||||
*/
|
||||
return {
|
||||
// we don't call it directly since non-existant arguments may
|
||||
// be interpreted as null within the sub enabled function
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc method
|
||||
* @name $animate#on
|
||||
* @kind function
|
||||
* @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)
|
||||
* has fired on the given element or among any of its children. Once the listener is fired, the provided callback
|
||||
* is fired with the following params:
|
||||
*
|
||||
* ```js
|
||||
* $animate.on('enter', container,
|
||||
* function callback(element, phase) {
|
||||
* // cool we detected an enter animation within the container
|
||||
* }
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)
|
||||
* @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself
|
||||
* as well as among its children
|
||||
* @param {Function} callback the callback function that will be fired when the listener is triggered
|
||||
*
|
||||
* The arguments present in the callback function are:
|
||||
* * `element` - The captured DOM element that the animation was fired on.
|
||||
* * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).
|
||||
*/
|
||||
on: $$animateQueue.on,
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc method
|
||||
* @name $animate#off
|
||||
* @kind function
|
||||
* @description Deregisters an event listener based on the event which has been associated with the provided element. This method
|
||||
* can be used in three different ways depending on the arguments:
|
||||
*
|
||||
* ```js
|
||||
* // remove all the animation event listeners listening for `enter`
|
||||
* $animate.off('enter');
|
||||
*
|
||||
* // remove all the animation event listeners listening for `enter` on the given element and its children
|
||||
* $animate.off('enter', container);
|
||||
*
|
||||
* // remove the event listener function provided by `listenerFn` that is set
|
||||
* // to listen for `enter` on the given `element` as well as its children
|
||||
* $animate.off('enter', container, callback);
|
||||
* ```
|
||||
*
|
||||
* @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
|
||||
* @param {DOMElement=} container the container element the event listener was placed on
|
||||
* @param {Function=} callback the callback function that was registered as the listener
|
||||
*/
|
||||
off: $$animateQueue.off,
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $animate#pin
|
||||
* @kind function
|
||||
* @description Associates the provided element with a host parent element to allow the element to be animated even if it exists
|
||||
* outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the
|
||||
* element despite being outside the realm of the application or within another application. Say for example if the application
|
||||
* was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated
|
||||
* as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind
|
||||
* that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.
|
||||
*
|
||||
* Note that this feature is only active when the `ngAnimate` module is used.
|
||||
*
|
||||
* @param {DOMElement} element the external element that will be pinned
|
||||
* @param {DOMElement} parentElement the host parent element that will be associated with the external element
|
||||
*/
|
||||
pin: $$animateQueue.pin,
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc method
|
||||
* @name $animate#enabled
|
||||
* @kind function
|
||||
* @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This
|
||||
* function can be called in four ways:
|
||||
*
|
||||
* ```js
|
||||
* // returns true or false
|
||||
* $animate.enabled();
|
||||
*
|
||||
* // changes the enabled state for all animations
|
||||
* $animate.enabled(false);
|
||||
* $animate.enabled(true);
|
||||
*
|
||||
* // returns true or false if animations are enabled for an element
|
||||
* $animate.enabled(element);
|
||||
*
|
||||
* // changes the enabled state for an element and its children
|
||||
* $animate.enabled(element, true);
|
||||
* $animate.enabled(element, false);
|
||||
* ```
|
||||
*
|
||||
* @param {DOMElement=} element the element that will be considered for checking/setting the enabled state
|
||||
* @param {boolean=} enabled whether or not the animations will be enabled for the element
|
||||
*
|
||||
* @return {boolean} whether or not animations are enabled
|
||||
*/
|
||||
enabled: $$animateQueue.enabled,
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $animate#cancel
|
||||
* @kind function
|
||||
* @description Cancels the provided animation.
|
||||
*
|
||||
* @param {Promise} animationPromise The animation promise that is returned when an animation is started.
|
||||
*/
|
||||
cancel: function(runner) {
|
||||
runner.end && runner.end();
|
||||
animate: function(element, from, to) {
|
||||
applyStyles(element, { from: from, to: to });
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -415,25 +180,39 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* @ngdoc method
|
||||
* @name $animate#enter
|
||||
* @kind function
|
||||
* @description Inserts the element into the DOM either after the `after` element (if provided) or
|
||||
* as the first child within the `parent` element and then triggers an animation.
|
||||
* A promise is returned that will be resolved during the next digest once the animation
|
||||
* has completed.
|
||||
*
|
||||
* @description Inserts the element into the DOM either after the `after` element or
|
||||
* as the first child within the `parent` element. When the function is called a promise
|
||||
* is returned that will be resolved at a later time.
|
||||
* @param {DOMElement} element the element which will be inserted into the DOM
|
||||
* @param {DOMElement} parent the parent element which will append the element as
|
||||
* a child (so long as the after element is not present)
|
||||
* @param {DOMElement=} after the sibling element after which the element will be appended
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
*
|
||||
* a child (if the after element is not present)
|
||||
* @param {DOMElement} after the sibling element which will append the element
|
||||
* after itself
|
||||
* @param {object=} options an optional collection of styles that will be applied to the element.
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
enter: function(element, parent, after, options) {
|
||||
parent = parent && jqLite(parent);
|
||||
after = after && jqLite(after);
|
||||
parent = parent || after.parent();
|
||||
domInsert(element, parent, after);
|
||||
return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));
|
||||
applyStyles(element, options);
|
||||
after ? after.after(element)
|
||||
: parent.prepend(element);
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc method
|
||||
* @name $animate#leave
|
||||
* @kind function
|
||||
* @description Removes the element from the DOM. When the function is called a promise
|
||||
* is returned that will be resolved at a later time.
|
||||
* @param {DOMElement} element the element which will be removed from the DOM
|
||||
* @param {object=} options an optional collection of options that will be applied to the element.
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
leave: function(element, options) {
|
||||
applyStyles(element, options);
|
||||
element.remove();
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -441,150 +220,153 @@ var $AnimateProvider = ['$provide', function($provide) {
|
||||
* @ngdoc method
|
||||
* @name $animate#move
|
||||
* @kind function
|
||||
* @description Inserts (moves) the element into its new position in the DOM either after
|
||||
* the `after` element (if provided) or as the first child within the `parent` element
|
||||
* and then triggers an animation. A promise is returned that will be resolved
|
||||
* during the next digest once the animation has completed.
|
||||
*
|
||||
* @param {DOMElement} element the element which will be moved into the new DOM position
|
||||
* @param {DOMElement} parent the parent element which will append the element as
|
||||
* a child (so long as the after element is not present)
|
||||
* @param {DOMElement=} after the sibling element after which the element will be appended
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
* @description Moves the position of the provided element within the DOM to be placed
|
||||
* either after the `after` element or inside of the `parent` element. When the function
|
||||
* is called a promise is returned that will be resolved at a later time.
|
||||
*
|
||||
* @param {DOMElement} element the element which will be moved around within the
|
||||
* DOM
|
||||
* @param {DOMElement} parent the parent element where the element will be
|
||||
* inserted into (if the after element is not present)
|
||||
* @param {DOMElement} after the sibling element where the element will be
|
||||
* positioned next to
|
||||
* @param {object=} options an optional collection of options that will be applied to the element.
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
move: function(element, parent, after, options) {
|
||||
parent = parent && jqLite(parent);
|
||||
after = after && jqLite(after);
|
||||
parent = parent || after.parent();
|
||||
domInsert(element, parent, after);
|
||||
return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));
|
||||
// Do not remove element before insert. Removing will cause data associated with the
|
||||
// element to be dropped. Insert will implicitly do the remove.
|
||||
return this.enter(element, parent, after, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $animate#leave
|
||||
* @kind function
|
||||
* @description Triggers an animation and then removes the element from the DOM.
|
||||
* When the function is called a promise is returned that will be resolved during the next
|
||||
* digest once the animation has completed.
|
||||
*
|
||||
* @param {DOMElement} element the element which will be removed from the DOM
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
*
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
leave: function(element, options) {
|
||||
return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
|
||||
element.remove();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $animate#addClass
|
||||
* @kind function
|
||||
*
|
||||
* @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon
|
||||
* execution, the addClass operation will only be handled after the next digest and it will not trigger an
|
||||
* animation if element already contains the CSS class or if the class is removed at a later step.
|
||||
* Note that class-based animations are treated differently compared to structural animations
|
||||
* (like enter, move and leave) since the CSS classes may be added/removed at different points
|
||||
* depending if CSS or JavaScript animations are used.
|
||||
*
|
||||
* @param {DOMElement} element the element which the CSS classes will be applied to
|
||||
* @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
*
|
||||
* @description Adds the provided className CSS class value to the provided element.
|
||||
* When the function is called a promise is returned that will be resolved at a later time.
|
||||
* @param {DOMElement} element the element which will have the className value
|
||||
* added to it
|
||||
* @param {string} className the CSS class which will be added to the element
|
||||
* @param {object=} options an optional collection of options that will be applied to the element.
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
addClass: function(element, className, options) {
|
||||
options = prepareAnimateOptions(options);
|
||||
options.addClass = mergeClasses(options.addclass, className);
|
||||
return $$animateQueue.push(element, 'addClass', options);
|
||||
return this.setClass(element, className, [], options);
|
||||
},
|
||||
|
||||
$$addClassImmediately: function(element, className, options) {
|
||||
element = jqLite(element);
|
||||
className = !isString(className)
|
||||
? (isArray(className) ? className.join(' ') : '')
|
||||
: className;
|
||||
forEach(element, function(element) {
|
||||
jqLiteAddClass(element, className);
|
||||
});
|
||||
applyStyles(element, options);
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc method
|
||||
* @name $animate#removeClass
|
||||
* @kind function
|
||||
*
|
||||
* @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon
|
||||
* execution, the removeClass operation will only be handled after the next digest and it will not trigger an
|
||||
* animation if element does not contain the CSS class or if the class is added at a later step.
|
||||
* Note that class-based animations are treated differently compared to structural animations
|
||||
* (like enter, move and leave) since the CSS classes may be added/removed at different points
|
||||
* depending if CSS or JavaScript animations are used.
|
||||
*
|
||||
* @param {DOMElement} element the element which the CSS classes will be applied to
|
||||
* @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
*
|
||||
* @description Removes the provided className CSS class value from the provided element.
|
||||
* When the function is called a promise is returned that will be resolved at a later time.
|
||||
* @param {DOMElement} element the element which will have the className value
|
||||
* removed from it
|
||||
* @param {string} className the CSS class which will be removed from the element
|
||||
* @param {object=} options an optional collection of options that will be applied to the element.
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
removeClass: function(element, className, options) {
|
||||
options = prepareAnimateOptions(options);
|
||||
options.removeClass = mergeClasses(options.removeClass, className);
|
||||
return $$animateQueue.push(element, 'removeClass', options);
|
||||
return this.setClass(element, [], className, options);
|
||||
},
|
||||
|
||||
$$removeClassImmediately: function(element, className, options) {
|
||||
element = jqLite(element);
|
||||
className = !isString(className)
|
||||
? (isArray(className) ? className.join(' ') : '')
|
||||
: className;
|
||||
forEach(element, function(element) {
|
||||
jqLiteRemoveClass(element, className);
|
||||
});
|
||||
applyStyles(element, options);
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @ngdoc method
|
||||
* @name $animate#setClass
|
||||
* @kind function
|
||||
*
|
||||
* @description Performs both the addition and removal of a CSS classes on an element and (during the process)
|
||||
* triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and
|
||||
* `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has
|
||||
* passed. Note that class-based animations are treated differently compared to structural animations
|
||||
* (like enter, move and leave) since the CSS classes may be added/removed at different points
|
||||
* depending if CSS or JavaScript animations are used.
|
||||
*
|
||||
* @param {DOMElement} element the element which the CSS classes will be applied to
|
||||
* @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)
|
||||
* @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
*
|
||||
* @description Adds and/or removes the given CSS classes to and from the element.
|
||||
* When the function is called a promise is returned that will be resolved at a later time.
|
||||
* @param {DOMElement} element the element which will have its CSS classes changed
|
||||
* removed from it
|
||||
* @param {string} add the CSS classes which will be added to the element
|
||||
* @param {string} remove the CSS class which will be removed from the element
|
||||
* @param {object=} options an optional collection of options that will be applied to the element.
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
setClass: function(element, add, remove, options) {
|
||||
options = prepareAnimateOptions(options);
|
||||
options.addClass = mergeClasses(options.addClass, add);
|
||||
options.removeClass = mergeClasses(options.removeClass, remove);
|
||||
return $$animateQueue.push(element, 'setClass', options);
|
||||
var self = this;
|
||||
var STORAGE_KEY = '$$animateClasses';
|
||||
var createdCache = false;
|
||||
element = jqLite(element);
|
||||
|
||||
var cache = element.data(STORAGE_KEY);
|
||||
if (!cache) {
|
||||
cache = {
|
||||
classes: {},
|
||||
options: options
|
||||
};
|
||||
createdCache = true;
|
||||
} else if (options && cache.options) {
|
||||
cache.options = angular.extend(cache.options || {}, options);
|
||||
}
|
||||
|
||||
var classes = cache.classes;
|
||||
|
||||
add = isArray(add) ? add : add.split(' ');
|
||||
remove = isArray(remove) ? remove : remove.split(' ');
|
||||
cachedClassManipulation(classes, add, true);
|
||||
cachedClassManipulation(classes, remove, false);
|
||||
|
||||
if (createdCache) {
|
||||
cache.promise = runAnimationPostDigest(function(done) {
|
||||
var cache = element.data(STORAGE_KEY);
|
||||
element.removeData(STORAGE_KEY);
|
||||
|
||||
// in the event that the element is removed before postDigest
|
||||
// is run then the cache will be undefined and there will be
|
||||
// no need anymore to add or remove and of the element classes
|
||||
if (cache) {
|
||||
var classes = resolveElementClasses(element, cache.classes);
|
||||
if (classes) {
|
||||
self.$$setClassImmediately(element, classes[0], classes[1], cache.options);
|
||||
}
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
element.data(STORAGE_KEY, cache);
|
||||
}
|
||||
|
||||
return cache.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $animate#animate
|
||||
* @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).
|
||||
*
|
||||
* @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.
|
||||
* @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
|
||||
* @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
|
||||
* this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
|
||||
* (Note that if no animation is detected then this value will not be appplied to the element.)
|
||||
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
||||
*
|
||||
* @return {Promise} the animation callback promise
|
||||
*/
|
||||
animate: function(element, from, to, className, options) {
|
||||
options = prepareAnimateOptions(options);
|
||||
options.from = options.from ? extend(options.from, from) : from;
|
||||
options.to = options.to ? extend(options.to, to) : to;
|
||||
$$setClassImmediately: function(element, add, remove, options) {
|
||||
add && this.$$addClassImmediately(element, add);
|
||||
remove && this.$$removeClassImmediately(element, remove);
|
||||
applyStyles(element, options);
|
||||
return asyncPromise();
|
||||
},
|
||||
|
||||
className = className || 'ng-inline-animate';
|
||||
options.tempClasses = mergeClasses(options.tempClasses, className);
|
||||
return $$animateQueue.push(element, 'animate', options);
|
||||
}
|
||||
enabled: noop,
|
||||
cancel: noop
|
||||
};
|
||||
}];
|
||||
}];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user