Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3468ad1b61 | |||
| e9c79cad43 | |||
| e455e7d878 | |||
| 3410f65e79 | |||
| f3de5b6eac | |||
| fcd2a8131a | |||
| 62dbe85798 | |||
| 1d5e18b062 | |||
| a0ed371389 | |||
| 05e4fd3488 | |||
| 30a8b7d0b5 | |||
| f8944efe70 | |||
| 43072e3812 | |||
| 9396d55414 | |||
| 82e97cf53e | |||
| cf2a7614a4 | |||
| 9e538e7c31 | |||
| 4ac21ac039 | |||
| f69dc16241 | |||
| f1a8d419d5 | |||
| 8864e54f1f | |||
| dc4df93177 | |||
| 043190f397 | |||
| f4d850e168 | |||
| 8ec2743ca1 | |||
| ecbee8147b | |||
| f8c6ee3df5 | |||
| fe84f7bef8 | |||
| d653607162 | |||
| 082fe180ec | |||
| d3491083a5 | |||
| c3d6ca97e1 | |||
| a14266e464 | |||
| b4d44e1298 | |||
| ca116c35a6 |
+7
-5
@@ -3,13 +3,16 @@ node_js:
|
||||
- 0.10
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- JOB=unit
|
||||
- JOB=e2e
|
||||
global:
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
- SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready
|
||||
- BROWSER_STACK_USERNAME=VojtaJina
|
||||
- BROWSER_STACK_ACCESS_KEY=HAfHZaypxAc3PEUrUU9a
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
@@ -18,11 +21,10 @@ before_script:
|
||||
- grunt bower
|
||||
- grunt bower
|
||||
- grunt package-without-bower
|
||||
- ./lib/sauce/sauce_connect_block.sh
|
||||
- ./scripts/travis/wait_for_browser_provider.sh
|
||||
|
||||
script:
|
||||
- grunt ci-checks
|
||||
- ./travis_build.sh
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
after_script:
|
||||
- ./travis_print_logs.sh
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
<a name="1.2.5"></a>
|
||||
# 1.2.5 singularity-expansion (2013-12-13)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** allow literals in isolate scope references
|
||||
([43072e38](https://github.com/angular/angular.js/commit/43072e3812e32b89b97ad03144577cba50d4b776),
|
||||
[#5296](https://github.com/angular/angular.js/issues/5296))
|
||||
- **angular-mocks:** use copy of mock data in $httpBackend
|
||||
([f69dc162](https://github.com/angular/angular.js/commit/f69dc16241c8b631123ad0b09674f0a5e0ff32fe))
|
||||
- **closure:** add missing FormController extern definitions
|
||||
([1d5e18b0](https://github.com/angular/angular.js/commit/1d5e18b062c3e33b2a8d96aa58d905ed2cd48649),
|
||||
[#5303](https://github.com/angular/angular.js/issues/5303))
|
||||
- **ngInclude:** add template to DOM before linking other directives
|
||||
([30a8b7d0](https://github.com/angular/angular.js/commit/30a8b7d0b5d4882c2bf3b20eb696a02f5b667726),
|
||||
[#5247](https://github.com/angular/angular.js/issues/5247))
|
||||
- **ngView:** add template to DOM before linking other directives
|
||||
([f8944efe](https://github.com/angular/angular.js/commit/f8944efe70b81e02704df9b53ea2546c80c73d3b))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$injector:** remove invoke optimization that doesn't work
|
||||
([05e4fd34](https://github.com/angular/angular.js/commit/05e4fd3488b89e670c36869f18defe26deac2efa),
|
||||
[#5388](https://github.com/angular/angular.js/issues/5388))
|
||||
- **$resource:** use shallow copy instead of angular.copy
|
||||
([fcd2a813](https://github.com/angular/angular.js/commit/fcd2a8131a3cb3e59a616bf31e61510b5c3a97d3),
|
||||
[#5300](https://github.com/angular/angular.js/issues/5300))
|
||||
- **a:** do not link when href or name exists in template
|
||||
([f3de5b6e](https://github.com/angular/angular.js/commit/f3de5b6eac90baf649506072162f36dbc6d2f028),
|
||||
[#5362](https://github.com/angular/angular.js/issues/5362))
|
||||
- **jqLite:** implement and use the `empty` method in place of `html(‘’)`
|
||||
([3410f65e](https://github.com/angular/angular.js/commit/3410f65e790a81d457b4f4601a1e760a6f8ede5e),
|
||||
[#4457](https://github.com/angular/angular.js/issues/4457))
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **angular-mocks:** due to [f69dc162](https://github.com/angular/angular.js/commit/f69dc16241c8b631123ad0b09674f0a5e0ff32fe),
|
||||
some tests that rely on identity comparison rather than equality comparison in checking mock http responses will be broken,
|
||||
since now each mock response is a copy of the original response. This is usually fixable by changing a `.toBe()` comparison
|
||||
to `toEqual()` inside of tests.
|
||||
|
||||
<a name="1.2.4"></a>
|
||||
# 1.2.4 wormhole-blaster (2013-12-06)
|
||||
|
||||
|
||||
@@ -198,6 +198,7 @@ Must be one of the following:
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
|
||||
semi-colons, etc)
|
||||
* **refactor**: A code change that neither fixes a bug or adds a feature
|
||||
* **perf**: A code change that improves performance
|
||||
* **test**: Adding missing tests
|
||||
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
|
||||
generation
|
||||
|
||||
+9
-3
@@ -10,6 +10,13 @@ The labels are used later on for planning releases.
|
||||
* these tags can be used for labeling a closed issue/PR with a reason why it was closed. (we can add reasons as we need them, right there are only a few rejection reasons. it doesn't make sense to label issues that were fixed or prs that were merged)
|
||||
|
||||
|
||||
## Automatic processing ##
|
||||
|
||||
We have automatic tools (e.g. Mary Poppins) that automatically add comments / labels to issues and PRs.
|
||||
The following is done automatically and should not be done manually:
|
||||
|
||||
* Label "cla: yes" or "cla: no" for pull requests
|
||||
|
||||
## Process ##
|
||||
|
||||
1. Open list of [non triaged issues](https://github.com/angular/angular.js/issues?direction=desc&milestone=none&page=1&sort=created&state=open)
|
||||
@@ -29,8 +36,9 @@ The labels are used later on for planning releases.
|
||||
* Reproducible on master? - http://code.angularjs.org/snapshot/
|
||||
|
||||
1. Non bugs:
|
||||
* Label "Type: Feature" or "Type: Chore"
|
||||
* Label "Type: Feature" or "Type: Chore" or "Type: Perf"
|
||||
* Label "needs: breaking change" - if needed
|
||||
* Label "needs: public api" - if a new public api is needed
|
||||
* Understandable? - verify if the description of the request is clear. if not ask for clarification
|
||||
* Goals of angular core? - Often new features should be implemented as a third-party module rather than an addition to the core.
|
||||
|
||||
@@ -46,8 +54,6 @@ The labels are used later on for planning releases.
|
||||
* large - changes to many components in angular or any changes to $compile, ngRepeat or other "fun" components
|
||||
1. Label "PRs welcome" for "GH: issue"
|
||||
* if complexity is small or medium and the problem as well as solution are well captured in the issue
|
||||
1. Label "cla: yes" for "GH: PR":
|
||||
* otherwise prompt the contributor to sign the CLA
|
||||
1. Label "origin: google" for issues from Google
|
||||
1. Label "high priority" for security issues, major performance regressions or memory leaks
|
||||
|
||||
|
||||
+3
-1
@@ -142,6 +142,7 @@ var writeChangelog = function(stream, commits, version) {
|
||||
var sections = {
|
||||
fix: {},
|
||||
feat: {},
|
||||
perf: {},
|
||||
breaks: {}
|
||||
};
|
||||
|
||||
@@ -169,6 +170,7 @@ var writeChangelog = function(stream, commits, version) {
|
||||
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
|
||||
printSection(stream, 'Bug Fixes', sections.fix);
|
||||
printSection(stream, 'Features', sections.feat);
|
||||
printSection(stream, 'Performance Improvements', sections.perf);
|
||||
printSection(stream, 'Breaking Changes', sections.breaks, false);
|
||||
}
|
||||
|
||||
@@ -186,7 +188,7 @@ var getPreviousTag = function() {
|
||||
var generate = function(version, file) {
|
||||
getPreviousTag().then(function(tag) {
|
||||
console.log('Reading git log since', tag);
|
||||
readGitLog('^fix|^feat|BREAKING', tag).then(function(commits) {
|
||||
readGitLog('^fix|^feat|^perf|BREAKING', tag).then(function(commits) {
|
||||
console.log('Parsed', commits.length, 'commits');
|
||||
console.log('Generating changelog to', file || 'stdout', '(', version, ')');
|
||||
writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version);
|
||||
|
||||
Vendored
+33
@@ -1441,6 +1441,11 @@ angular.NgModelController.prototype.$viewValue;
|
||||
*/
|
||||
angular.FormController = function() {};
|
||||
|
||||
/**
|
||||
* @param {*} control
|
||||
*/
|
||||
angular.FormController.prototype.$addControl = function(control) {};
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@@ -1456,11 +1461,39 @@ angular.FormController.prototype.$error;
|
||||
*/
|
||||
angular.FormController.prototype.$invalid;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
angular.FormController.prototype.$name;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
angular.FormController.prototype.$pristine;
|
||||
|
||||
/**
|
||||
* @param {*} control
|
||||
*/
|
||||
angular.FormController.prototype.$removeControl = function(control) {};
|
||||
|
||||
/**
|
||||
* @type {function()}
|
||||
*/
|
||||
angular.FormController.prototype.$setDirty = function() {};
|
||||
|
||||
/**
|
||||
* @type {function()}
|
||||
*/
|
||||
angular.FormController.prototype.$setPristine = function() {};
|
||||
|
||||
/**
|
||||
* @param {string} validationToken
|
||||
* @param {boolean} isValid
|
||||
* @param {*} control
|
||||
*/
|
||||
angular.FormController.prototype.$setValidity = function(
|
||||
validationToken, isValid, control) {};
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,7 @@ describe('Docs Annotations', function() {
|
||||
var body;
|
||||
beforeEach(function() {
|
||||
body = angular.element(document.body);
|
||||
body.html('');
|
||||
body.empty();
|
||||
});
|
||||
|
||||
var normalizeHtml = function(html) {
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ function escape(text) {
|
||||
function setHtmlIe8SafeWay(element, html) {
|
||||
var newElement = angular.element('<pre>' + html + '</pre>');
|
||||
|
||||
element.html('');
|
||||
element.empty();
|
||||
element.append(newElement.contents());
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
@fullName Orphan ngTransclude Directive
|
||||
@description
|
||||
|
||||
Occurs when an `ngTransclude` occurs without a transcluded ancesstor element.
|
||||
Occurs when an `ngTransclude` occurs without a transcluded ancestor element.
|
||||
|
||||
This error often occurs when you have forgotten to set `transclude: true` in some directive definition, and then used `ngTranslude` in the driective's template.
|
||||
This error often occurs when you have forgotten to set `transclude: true` in some directive definition, and then used `ngTransclude` in the directive's template.
|
||||
|
||||
To resolve, either remove the offending `ngTransclude` or check that `transclude: true` is included in the intended directive definition.
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ var pc = new PasswordCtrl();
|
||||
input.val('abc');
|
||||
pc.grade();
|
||||
expect(span.text()).toEqual('weak');
|
||||
$('body').html('');
|
||||
$('body').empty();
|
||||
</pre>
|
||||
|
||||
In angular the controllers are strictly separated from the DOM manipulation logic and this results in
|
||||
|
||||
@@ -18,7 +18,7 @@ It might be tempting to think of Angular view expressions as JavaScript expressi
|
||||
not entirely correct, since Angular does not use a JavaScript `eval()` to evaluate expressions.
|
||||
You can think of Angular expressions as JavaScript expressions with following differences:
|
||||
|
||||
* **Attribute Evaluation:** evaluation of all properties are against the scope, doing the
|
||||
* **Attribute Evaluation:** evaluation of all properties are against the scope doing the
|
||||
evaluation, unlike in JavaScript where the expressions are evaluated against the global
|
||||
`window`.
|
||||
|
||||
|
||||
@@ -115,9 +115,14 @@ This ensures that the user is not distracted with an error until after interacti
|
||||
|
||||
A form is an instance of {@link api/ng.directive:form.FormController FormController}.
|
||||
The form instance can optionally be published into the scope using the `name` attribute.
|
||||
Similarly, control is an instance of {@link api/ng.directive:ngModel.NgModelController NgModelController}.
|
||||
The control instance can similarly be published into the form instance using the `name` attribute.
|
||||
This implies that the internal state of both the form and the control is available for binding in the view using the standard binding primitives.
|
||||
|
||||
Similarly, an input control that has the {@link api.ng.directive:ng-model} directive holds an
|
||||
instance of {@link api/ng.directive:ngModel.NgModelController NgModelController}.
|
||||
Such a control instance can be published as a property of the form instance using the `name` attribute
|
||||
on the input control. The name attribute specifies the name of the property on the form instance.
|
||||
|
||||
This implies that the internal state of both the form and the control is available for binding in
|
||||
the view using the standard binding primitives.
|
||||
|
||||
This allows us to extend the above example with these features:
|
||||
|
||||
|
||||
@@ -7,19 +7,14 @@
|
||||
Everything you need to know about AngularJS
|
||||
|
||||
* {@link guide/introduction What is AngularJS?}
|
||||
|
||||
* {@link guide/concepts Conceptual Overview}
|
||||
|
||||
## Tutorials
|
||||
|
||||
* {@link tutorial/index Official AngularJS Tutorial}
|
||||
|
||||
* [10 Reasons Why You Should Use AngularJS](http://www.sitepoint.com/10-reasons-use-angularjs/)
|
||||
|
||||
* [Design Principles of AngularJS (video)](https://www.youtube.com/watch?v=HCR7i5F5L8c)
|
||||
|
||||
* [Fundamentals in 60 Minutes (video)](http://www.youtube.com/watch?v=i9MHigUZKEM)
|
||||
|
||||
* [For folks with jQuery background](http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background)
|
||||
|
||||
## Core Concepts
|
||||
@@ -29,63 +24,44 @@ Everything you need to know about AngularJS
|
||||
In Angular applications, you move the job of filling page templates with data from the server to the client. The result is a system better structured for dynamic page updates. Below are the core features you'll use.
|
||||
|
||||
* {@link guide/databinding Data binding}
|
||||
|
||||
* {@link guide/expression Expressions}
|
||||
|
||||
* {@link guide/directive Directives}
|
||||
|
||||
* {@link api/ngRoute.$route Views and routes (see the example)}
|
||||
|
||||
* {@link guide/filter Filters}
|
||||
|
||||
* {@link guide/forms Forms} and [Concepts of AngularJS Forms](http://mrbool.com/the-concepts-of-angularjs-forms/29117)
|
||||
|
||||
### Application Structure
|
||||
|
||||
* **Blog post: **[When to use directives, controllers or services](http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/)
|
||||
|
||||
* **App wiring:** {@link guide/di Dependency injection}
|
||||
|
||||
* **Exposing model to templates:** {@link guide/scope Scopes}
|
||||
|
||||
* **Communicating with servers:** {@link api/ng.$http $http}, {@link api/ngResource.$resource $resource}
|
||||
|
||||
### Other AngularJS Features
|
||||
|
||||
* **Animation:** {@link guide/animations Core concepts}, {@link api/ngAnimate ngAnimate API}, and [Animation in AngularJS 1.2](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html)
|
||||
|
||||
* **Security:** {@link api/ng.$sce Strict Contextual Escaping}, {@link api/ng.directive:ngCsp Content Security Policy}, {@link api/ngSanitize.$sanitize $sanitize}, [video](https://www.youtube.com/watch?v=18ifoT-Id54)
|
||||
|
||||
* **Internationalization and Localization:** {@link guide/i18n Angular Guide to i18n and l10n}, {@link api/ng.filter:date date filter}, {@link api/ng.filter:currency currency filter}, [Creating multilingual support](http://www.novanet.no/blog/hallstein-brotan/dates/2013/10/creating-multilingual-support-using-angularjs/)
|
||||
|
||||
* **Mobile:** {@link api/ngTouch Touch events}
|
||||
|
||||
### Testing
|
||||
|
||||
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), {@link guide/dev_guide.unit-testing Unit testing}, {@link guide/dev_guide.services.testing_services Testing services}, [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
|
||||
|
||||
* **Scenario testing:** [Protractor](https://github.com/angular/protractor)
|
||||
|
||||
## Specific Topics
|
||||
|
||||
* **Login: **[Google example](https://developers.google.com/+/photohunt/python), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
|
||||
|
||||
* **Mobile:** [Angular on Mobile Guide](http://www.ng-newsletter.com/posts/angular-on-mobile.html), [PhoneGap](http://devgirl.org/2013/06/10/quick-start-guide-phonegap-and-angularjs/)
|
||||
|
||||
* **Other Languages:** [CoffeeScript](http://www.coffeescriptlove.com/2013/08/angularjs-and-coffeescript-tutorials.html), [Dart](https://github.com/angular/angular.dart.tutorial/wiki)
|
||||
|
||||
* **Realtime: **[Socket.io](http://www.creativebloq.com/javascript/angularjs-collaboration-board-socketio-2132885), [OmniBinder](https://github.com/jeffbcross/omnibinder)
|
||||
|
||||
* **Visualization:** [SVG](http://gaslight.co/blog/angular-backed-svgs), [D3.js](http://www.ng-newsletter.com/posts/d3-on-angular.html)
|
||||
|
||||
## Tools
|
||||
|
||||
* **Debugging:** [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en)
|
||||
|
||||
* **Testing:** [Karma](http://karma-runner.github.io), [Protractor](https://github.com/angular/protractor)
|
||||
|
||||
* **Editor support:** [Webstorm](http://plugins.jetbrains.com/plugin/6971) (and [video](http://www.youtube.com/watch?v=LJOyrSh1kDU)), [Sublime Text](https://github.com/angular-ui/AngularJS-sublime-package), [Visual Studio](http://madskristensen.net/post/angularjs-intellisense-in-visual-studio-2012)
|
||||
|
||||
* **Workflow:** [Yeoman.io](https://github.com/yeoman/generator-angular) and [Angular Yeoman Tutorial](http://www.sitepoint.com/kickstart-your-angularjs-development-with-yeoman-grunt-and-bower/)
|
||||
|
||||
## Complementary Libraries
|
||||
@@ -93,37 +69,26 @@ In Angular applications, you move the job of filling page templates with data fr
|
||||
This is a short list of libraries with specific support and documentation for working with Angular. You can find a full list of all known Angular external libraries at [ngmodules.org](http://ngmodules.org/).
|
||||
|
||||
* **Internationalization:** [angular-translate](http://pascalprecht.github.io/angular-translate/), [angular-gettext](http://angular-gettext.rocketeer.be/)
|
||||
|
||||
* **RESTful services:** [Restangular](https://github.com/mgonto/restangular)
|
||||
|
||||
* **SQL and NoSQL backends:** [BreezeJS](http://www.breezejs.com/), [AngularFire](http://angularfire.com/)
|
||||
|
||||
* **UI Widgets: **[KendoUI](http://kendo-labs.github.io/angular-kendo/#/), [UI Bootstrap](http://angular-ui.github.io/bootstrap/), [Wijmo](http://wijmo.com/tag/angularjs-2/)
|
||||
|
||||
## Deployment
|
||||
|
||||
### General
|
||||
### General
|
||||
|
||||
* **Javascript minification: **[Background](http://thegreenpizza.github.io/2013/05/25/building-minification-safe-angular.js-applications/), [ngmin automation tool](http://www.thinkster.io/pick/XlWneEZCqY/angularjs-ngmin)
|
||||
|
||||
* **Tracking:** [Angularyitcs (Google Analytics)](http://ngmodules.org/modules/angularytics), [Logging Client-Side Errors](http://www.bennadel.com/blog/2542-Logging-Client-Side-Errors-With-AngularJS-And-Stacktrace-js.htm)
|
||||
|
||||
* **SEO:** [By hand](http://www.yearofmoo.com/2012/11/angularjs-and-seo.html), [prerender.io](http://prerender.io/), [Brombone](http://www.brombone.com/), [SEO.js](http://getseojs.com/), [SEO4Ajax](http://www.seo4ajax.com/)
|
||||
|
||||
### Server-Specific
|
||||
|
||||
* **Django:** [Tutorial](http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework), [Integrating AngularJS with Django](http://django-angular.readthedocs.org/en/latest/integration.html)
|
||||
|
||||
* **FireBase:** [AngularFire](http://angularfire.com/), [Realtime Apps with AngularJS and FireBase (video)](http://www.youtube.com/watch?v=C7ZI7z7qnHU)
|
||||
|
||||
* **Google Cloud Platform: **[with Cloud Endpoints](https://cloud.google.com/resources/articles/angularjs-cloud-endpoints-recipe-for-building-modern-web-applications), [with Go](https://github.com/GoogleCloudPlatform/appengine-angular-gotodos)
|
||||
|
||||
* **Hood.ie:** [60 Minutes to Awesome](http://www.roberthorvick.com/2013/06/30/todomvc-angularjs-hood-ie-60-minutes-to-awesome/)
|
||||
|
||||
* **MEAN Stack: **[Blog post](http://blog.mongodb.org/post/49262866911/the-mean-stack-mongodb-expressjs-angularjs-and), [Setup](http://thecodebarbarian.wordpress.com/2013/07/22/introduction-to-the-mean-stack-part-one-setting-up-your-tools/), [GDL Video](https://developers.google.com/live/shows/913996610)
|
||||
|
||||
* **Rails: **[Tutorial](http://coderberry.me/blog/2013/04/22/angularjs-on-rails-4-part-1/), [AngularJS with Rails4](https://shellycloud.com/blog/2013/10/how-to-integrate-angularjs-with-rails-4), [angularjs-rails](https://github.com/hiravgandhi/angularjs-rails)
|
||||
|
||||
* **PHP: **[Building a RESTful web service](http://blog.brunoscopelliti.com/building-a-restful-web-service-with-angularjs-and-php-more-power-with-resource), [End to End with Laravel 4 (video)](http://www.youtube.com/watch?v=hqAyiqUs93c)
|
||||
|
||||
## Learning Resources
|
||||
@@ -137,18 +102,18 @@ This is a short list of libraries with specific support and documentation for wo
|
||||
* [ng-book: The Complete Book on AngularJS](http://ng-book.com/) by Ari Lerner
|
||||
|
||||
###Videos:
|
||||
* [egghead.io](http://egghead.io/),
|
||||
* [egghead.io](http://egghead.io/)
|
||||
* [Angular on YouTube](http://youtube.com/angularjs)
|
||||
|
||||
###Courses
|
||||
* **Free on-line:**
|
||||
### Courses
|
||||
* **Free online:**
|
||||
[thinkster.io](http://thinkster.io),
|
||||
[CodeAcademy](http://www.codecademy.com/courses/javascript-advanced-en-2hJ3J/0/1)
|
||||
* **Paid on-line:**
|
||||
* **Paid online:**
|
||||
[Pluralsite (3 courses)](http://www.pluralsight.com/training/Courses/Find?highlight=true&searchTerm=angularjs),
|
||||
[Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/),
|
||||
[lynda.com](http://www.lynda.com/AngularJS-tutorials/Up-Running-AngularJS/133318-2.html)
|
||||
* **Paid on-site:**
|
||||
* **Paid onsite:**
|
||||
[angularbootcamp.com](http://angularbootcamp.com/)
|
||||
|
||||
## Getting Help
|
||||
@@ -156,19 +121,14 @@ This is a short list of libraries with specific support and documentation for wo
|
||||
The recipe for getting help on your unique issue is to create an example that could work (even if it doesn't) in a shareable example on [Plunker](http://plnkr.co/), [JSFiddle](http://jsfiddle.net/), or similar site and then post to one of the following:
|
||||
|
||||
* [Stackoverflow.com](http://stackoverflow.com/search?q=angularjs)
|
||||
|
||||
* [AngularJS mailing list](https://groups.google.com/forum/#!forum/angular)
|
||||
|
||||
* [AngularJS IRC channel](http://webchat.freenode.net/?channels=angularjs&uio=d4)
|
||||
|
||||
## Social Channels
|
||||
|
||||
* **Daily updates:** [Google+](https://plus.google.com/u/0/+AngularJS) or [Twitter](https://twitter.com/angularjs)
|
||||
|
||||
* **Weekly newsletter:** [ng-newsletter](http://www.ng-newsletter.com/)
|
||||
|
||||
* **Meetups: **[meetup.com](http://www.meetup.com/find/?keywords=angularJS&radius=Infinity&userFreeform=San+Francisco%2C+CA&mcId=z94108&mcName=San+Francisco%2C+CA&sort=member_count&eventFilter=mysugg)
|
||||
|
||||
* **Official news and releases: **[AngularJS Blog](http://blog.angularjs.org/)
|
||||
|
||||
## Contributing to AngularJS
|
||||
|
||||
@@ -23,7 +23,7 @@ for how to contribute your own code to AngularJS.
|
||||
Before you can build AngularJS, you must install and configure the following dependencies on your
|
||||
machine:
|
||||
|
||||
* {@link http://git-scm.com/ Git}: The {@link http://help.github.com/mac-git-installation Github Guide to
|
||||
* {@link http://git-scm.com/ Git}: The {@link https://help.github.com/articles/set-up-git Github Guide to
|
||||
Installing Git} is a good source of information.
|
||||
|
||||
* {@link http://nodejs.org Node.js}: We use Node to generate the documentation, run a
|
||||
|
||||
@@ -258,7 +258,7 @@ to various URLs and verify that the correct view was rendered.
|
||||
<pre>
|
||||
...
|
||||
it('should redirect index.html to index.html#/phones', function() {
|
||||
browser().navigateTo('../../app/index.html');
|
||||
browser().navigateTo('app/index.html');
|
||||
expect(browser().location().url()).toBe('/phones');
|
||||
});
|
||||
...
|
||||
@@ -266,7 +266,7 @@ to various URLs and verify that the correct view was rendered.
|
||||
describe('Phone detail view', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
browser().navigateTo('../../app/index.html#/phones/nexus-s');
|
||||
browser().navigateTo('app/index.html#/phones/nexus-s');
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -144,6 +144,27 @@
|
||||
.content h4,
|
||||
.content h5 {
|
||||
margin-top: 1em;
|
||||
letter-spacing: -0.06em;
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
font-size: 36px;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.content h3 {
|
||||
font-size: 24px;
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: .5em;
|
||||
}
|
||||
|
||||
.content h4 {
|
||||
font-size: 16px;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
.content ul {
|
||||
margin-top: .5em;
|
||||
}
|
||||
|
||||
ul.parameters > li > p,
|
||||
|
||||
@@ -273,10 +273,10 @@ docsApp.directive.docTutorialNav = function(templateMerge) {
|
||||
element.addClass('btn-group');
|
||||
element.addClass('tutorial-nav');
|
||||
element.append(templateMerge(
|
||||
'<li class="btn btn-primary"><a href="tutorial/{{prev}}"><i class="icon-step-backward"></i> Previous</a></li>\n' +
|
||||
'<li class="btn btn-primary"><a href="http://angular.github.com/angular-phonecat/step-{{seq}}/app"><i class="icon-play"></i> Live Demo</a></li>\n' +
|
||||
'<li class="btn btn-primary"><a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><i class="icon-search"></i> Code Diff</a></li>\n' +
|
||||
'<li class="btn btn-primary"><a href="tutorial/{{next}}">Next <i class="icon-step-forward"></i></a></li>', props));
|
||||
'<a href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="icon-step-backward"></i> Previous</li></a>\n' +
|
||||
'<a href="http://angular.github.com/angular-phonecat/step-{{seq}}/app"><li class="btn btn-primary"><i class="icon-play"></i> Live Demo</li></a>\n' +
|
||||
'<a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><li class="btn btn-primary"><i class="icon-search"></i> Code Diff</li></a>\n' +
|
||||
'<a href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="icon-step-forward"></i></li></a>', props));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -36,8 +36,8 @@ ARGS=""
|
||||
if [ ! -z "$TRAVIS_JOB_NUMBER" ]; then
|
||||
ARGS="$ARGS --tunnel-identifier $TRAVIS_JOB_NUMBER"
|
||||
fi
|
||||
if [ ! -z "$SAUCE_CONNECT_READY_FILE" ]; then
|
||||
ARGS="$ARGS --readyfile $SAUCE_CONNECT_READY_FILE"
|
||||
if [ ! -z "$BROWSER_PROVIDER_READY_FILE" ]; then
|
||||
ARGS="$ARGS --readyfile $BROWSER_PROVIDER_READY_FILE"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"version": "1.2.4",
|
||||
"cdnVersion": "1.2.3",
|
||||
"codename": "wormhole-baster",
|
||||
"version": "1.2.5",
|
||||
"cdnVersion": "1.2.4",
|
||||
"codename": "singularity-expansion",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.js.git"
|
||||
|
||||
@@ -33,8 +33,10 @@ REPOS=(
|
||||
# download and unzip the file
|
||||
#
|
||||
|
||||
#wget $ZIP_FILE_URL
|
||||
unzip $ZIP_FILE
|
||||
if [ ! -f $ZIP_FILE ]; then
|
||||
wget $ZIP_FILE_URL
|
||||
unzip $ZIP_FILE
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
@@ -46,8 +48,10 @@ do
|
||||
if [ -f $ZIP_DIR/$repo.js ] # ignore i18l
|
||||
then
|
||||
cd bower-$repo
|
||||
git checkout master
|
||||
git reset --hard HEAD
|
||||
git checkout master
|
||||
git fetch --all
|
||||
git reset --hard origin/master
|
||||
cd ..
|
||||
mv $ZIP_DIR/$repo.* bower-$repo/
|
||||
fi
|
||||
@@ -76,7 +80,6 @@ echo $NEW_VERSION
|
||||
for repo in "${REPOS[@]}"
|
||||
do
|
||||
cd bower-$repo
|
||||
pwd
|
||||
sed -i '' -e "s/$OLD_VERSION/$NEW_VERSION/g" bower.json
|
||||
git add -A
|
||||
git commit -m "v$NEW_VERSION"
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
if [ $JOB = "unit" ]; then
|
||||
grunt ci-checks
|
||||
grunt test:docgen
|
||||
grunt test:promises-aplus
|
||||
grunt test:unit --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_8,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots
|
||||
elif [ $JOB = "e2e" ]; then
|
||||
grunt test:e2e --browsers SL_Chrome --reporters dots
|
||||
else
|
||||
echo "Unknown job type. Please set JOB=unit or JOB=e2e."
|
||||
fi
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
|
||||
# Wait for Connect to be ready before exiting
|
||||
while [ ! -f $SAUCE_CONNECT_READY_FILE ]; do
|
||||
while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do
|
||||
sleep .5
|
||||
done
|
||||
+13
-13
@@ -393,7 +393,7 @@ function valueFn(value) {return function() {return value;};}
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is undefined.
|
||||
*/
|
||||
function isUndefined(value){return typeof value == 'undefined';}
|
||||
function isUndefined(value){return typeof value === 'undefined';}
|
||||
|
||||
|
||||
/**
|
||||
@@ -407,7 +407,7 @@ function isUndefined(value){return typeof value == 'undefined';}
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is defined.
|
||||
*/
|
||||
function isDefined(value){return typeof value != 'undefined';}
|
||||
function isDefined(value){return typeof value !== 'undefined';}
|
||||
|
||||
|
||||
/**
|
||||
@@ -422,7 +422,7 @@ function isDefined(value){return typeof value != 'undefined';}
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is an `Object` but not `null`.
|
||||
*/
|
||||
function isObject(value){return value != null && typeof value == 'object';}
|
||||
function isObject(value){return value != null && typeof value === 'object';}
|
||||
|
||||
|
||||
/**
|
||||
@@ -436,7 +436,7 @@ function isObject(value){return value != null && typeof value == 'object';}
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is a `String`.
|
||||
*/
|
||||
function isString(value){return typeof value == 'string';}
|
||||
function isString(value){return typeof value === 'string';}
|
||||
|
||||
|
||||
/**
|
||||
@@ -450,7 +450,7 @@ function isString(value){return typeof value == 'string';}
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is a `Number`.
|
||||
*/
|
||||
function isNumber(value){return typeof value == 'number';}
|
||||
function isNumber(value){return typeof value === 'number';}
|
||||
|
||||
|
||||
/**
|
||||
@@ -465,7 +465,7 @@ function isNumber(value){return typeof value == 'number';}
|
||||
* @returns {boolean} True if `value` is a `Date`.
|
||||
*/
|
||||
function isDate(value){
|
||||
return toString.apply(value) == '[object Date]';
|
||||
return toString.call(value) === '[object Date]';
|
||||
}
|
||||
|
||||
|
||||
@@ -481,7 +481,7 @@ function isDate(value){
|
||||
* @returns {boolean} True if `value` is an `Array`.
|
||||
*/
|
||||
function isArray(value) {
|
||||
return toString.apply(value) == '[object Array]';
|
||||
return toString.call(value) === '[object Array]';
|
||||
}
|
||||
|
||||
|
||||
@@ -496,7 +496,7 @@ function isArray(value) {
|
||||
* @param {*} value Reference to check.
|
||||
* @returns {boolean} True if `value` is a `Function`.
|
||||
*/
|
||||
function isFunction(value){return typeof value == 'function';}
|
||||
function isFunction(value){return typeof value === 'function';}
|
||||
|
||||
|
||||
/**
|
||||
@@ -507,7 +507,7 @@ function isFunction(value){return typeof value == 'function';}
|
||||
* @returns {boolean} True if `value` is a `RegExp`.
|
||||
*/
|
||||
function isRegExp(value) {
|
||||
return toString.apply(value) == '[object RegExp]';
|
||||
return toString.call(value) === '[object RegExp]';
|
||||
}
|
||||
|
||||
|
||||
@@ -529,12 +529,12 @@ function isScope(obj) {
|
||||
|
||||
|
||||
function isFile(obj) {
|
||||
return toString.apply(obj) === '[object File]';
|
||||
return toString.call(obj) === '[object File]';
|
||||
}
|
||||
|
||||
|
||||
function isBoolean(value) {
|
||||
return typeof value == 'boolean';
|
||||
return typeof value === 'boolean';
|
||||
}
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ function includes(array, obj) {
|
||||
function indexOf(array, obj) {
|
||||
if (array.indexOf) return array.indexOf(obj);
|
||||
|
||||
for ( var i = 0; i < array.length; i++) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (obj === array[i]) return i;
|
||||
}
|
||||
return -1;
|
||||
@@ -974,7 +974,7 @@ function startingTag(element) {
|
||||
try {
|
||||
// turns out IE does not let you set .html() on elements which
|
||||
// are not allowed to have children. So we just ignore it.
|
||||
element.html('');
|
||||
element.empty();
|
||||
} catch(e) {}
|
||||
// As Per DOM Standards
|
||||
var TEXT_NODE = 3;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
ngHideDirective,
|
||||
ngIfDirective,
|
||||
ngIncludeDirective,
|
||||
ngIncludeFillContentDirective,
|
||||
ngInitDirective,
|
||||
ngNonBindableDirective,
|
||||
ngPluralizeDirective,
|
||||
@@ -181,6 +182,9 @@ function publishExternalAPI(angular){
|
||||
ngRequired: requiredDirective,
|
||||
ngValue: ngValueDirective
|
||||
}).
|
||||
directive({
|
||||
ngInclude: ngIncludeFillContentDirective
|
||||
}).
|
||||
directive(ngAttributeAliasDirectives).
|
||||
directive(ngEventDirectives);
|
||||
$provide.provider({
|
||||
|
||||
+25
-18
@@ -27,6 +27,28 @@
|
||||
* $rootScope.$digest();
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* Sometimes you want to get access to the injector of a currently running Angular app
|
||||
* from outside Angular. Perhaps, you want to inject and compile some markup after the
|
||||
* application has been bootstrapped. You can do this using extra `injector()` added
|
||||
* to JQuery/jqLite elements. See {@link angular.element}.
|
||||
*
|
||||
* *This is fairly rare but could be the case if a third party library is injecting the
|
||||
* markup.*
|
||||
*
|
||||
* In the following example a new block of HTML containing a `ng-controller`
|
||||
* directive is added to the end of the document body by JQuery. We then compile and link
|
||||
* it into the current AngularJS scope.
|
||||
*
|
||||
* <pre>
|
||||
* var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
|
||||
* $(document.body).append($div);
|
||||
*
|
||||
* angular.element(document).injector().invoke(function($compile) {
|
||||
* var scope = angular.element($div).scope();
|
||||
* $compile($div)(scope);
|
||||
* });
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
|
||||
@@ -747,24 +769,9 @@ function createInjector(modulesToLoad) {
|
||||
fn = fn[length];
|
||||
}
|
||||
|
||||
|
||||
// Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
|
||||
switch (self ? -1 : args.length) {
|
||||
case 0: return fn();
|
||||
case 1: return fn(args[0]);
|
||||
case 2: return fn(args[0], args[1]);
|
||||
case 3: return fn(args[0], args[1], args[2]);
|
||||
case 4: return fn(args[0], args[1], args[2], args[3]);
|
||||
case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
|
||||
case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
||||
case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||
case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
|
||||
args[8]);
|
||||
case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
|
||||
args[8], args[9]);
|
||||
default: return fn.apply(self, args);
|
||||
}
|
||||
// http://jsperf.com/angularjs-invoke-apply-vs-switch
|
||||
// #5388
|
||||
return fn.apply(self, args);
|
||||
}
|
||||
|
||||
function instantiate(Type, locals) {
|
||||
|
||||
+18
-4
@@ -46,6 +46,7 @@
|
||||
* - [`contents()`](http://api.jquery.com/contents/)
|
||||
* - [`css()`](http://api.jquery.com/css/)
|
||||
* - [`data()`](http://api.jquery.com/data/)
|
||||
* - [`empty()`](http://api.jquery.com/empty/)
|
||||
* - [`eq()`](http://api.jquery.com/eq/)
|
||||
* - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
|
||||
* - [`hasClass()`](http://api.jquery.com/hasClass/)
|
||||
@@ -358,6 +359,15 @@ function jqLiteInheritedData(element, name, value) {
|
||||
}
|
||||
}
|
||||
|
||||
function jqLiteEmpty(element) {
|
||||
for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
|
||||
jqLiteDealoc(childNodes[i]);
|
||||
}
|
||||
while (element.firstChild) {
|
||||
element.removeChild(element.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Functions which are declared directly.
|
||||
//////////////////////////////////////////
|
||||
@@ -552,7 +562,9 @@ forEach({
|
||||
jqLiteDealoc(childNodes[i]);
|
||||
}
|
||||
element.innerHTML = value;
|
||||
}
|
||||
},
|
||||
|
||||
empty: jqLiteEmpty
|
||||
}, function(fn, name){
|
||||
/**
|
||||
* Properties: writes return selection, reads return first value
|
||||
@@ -562,11 +574,13 @@ forEach({
|
||||
|
||||
// jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
|
||||
// in a way that survives minification.
|
||||
if (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined) {
|
||||
// jqLiteEmpty takes no arguments but is a setter.
|
||||
if (fn !== jqLiteEmpty &&
|
||||
(((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
|
||||
if (isObject(arg1)) {
|
||||
|
||||
// we are a write, but the object properties are the key/values
|
||||
for(i=0; i < this.length; i++) {
|
||||
for (i = 0; i < this.length; i++) {
|
||||
if (fn === jqLiteData) {
|
||||
// data() takes the whole object in jQuery
|
||||
fn(this[i], arg1);
|
||||
@@ -591,7 +605,7 @@ forEach({
|
||||
}
|
||||
} else {
|
||||
// we are a write, so apply to all children
|
||||
for(i=0; i < this.length; i++) {
|
||||
for (i = 0; i < this.length; i++) {
|
||||
fn(this[i], arg1, arg2);
|
||||
}
|
||||
// return self for chaining
|
||||
|
||||
+11
-7
@@ -1219,7 +1219,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
});
|
||||
} else {
|
||||
$template = jqLite(jqLiteClone(compileNode)).contents();
|
||||
$compileNode.html(''); // clear contents
|
||||
$compileNode.empty(); // clear contents
|
||||
childTranscludeFn = compile($template, transcludeFn);
|
||||
}
|
||||
}
|
||||
@@ -1400,7 +1400,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
optional = (match[2] == '?'),
|
||||
mode = match[1], // @, =, or &
|
||||
lastValue,
|
||||
parentGet, parentSet;
|
||||
parentGet, parentSet, compare;
|
||||
|
||||
isolateScope.$$isolateBindings[scopeName] = mode + attrName;
|
||||
|
||||
@@ -1423,6 +1423,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return;
|
||||
}
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
if (parentGet.literal) {
|
||||
compare = equals;
|
||||
} else {
|
||||
compare = function(a,b) { return a === b; };
|
||||
}
|
||||
parentSet = parentGet.assign || function() {
|
||||
// reset the change, or we will throw this exception on every $digest
|
||||
lastValue = isolateScope[scopeName] = parentGet(scope);
|
||||
@@ -1433,10 +1438,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
lastValue = isolateScope[scopeName] = parentGet(scope);
|
||||
isolateScope.$watch(function parentValueWatch() {
|
||||
var parentValue = parentGet(scope);
|
||||
|
||||
if (parentValue !== isolateScope[scopeName]) {
|
||||
if (!compare(parentValue, isolateScope[scopeName])) {
|
||||
// we are out of sync and need to copy
|
||||
if (parentValue !== lastValue) {
|
||||
if (!compare(parentValue, lastValue)) {
|
||||
// parent changed and it has precedence
|
||||
isolateScope[scopeName] = parentValue;
|
||||
} else {
|
||||
@@ -1445,7 +1449,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
}
|
||||
}
|
||||
return lastValue = parentValue;
|
||||
});
|
||||
}, null, parentGet.literal);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
@@ -1647,7 +1651,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
? origAsyncDirective.templateUrl($compileNode, tAttrs)
|
||||
: origAsyncDirective.templateUrl;
|
||||
|
||||
$compileNode.html('');
|
||||
$compileNode.empty();
|
||||
|
||||
$http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
|
||||
success(function(content) {
|
||||
|
||||
+10
-8
@@ -32,13 +32,15 @@ var htmlAnchorDirective = valueFn({
|
||||
element.append(document.createComment('IE fix'));
|
||||
}
|
||||
|
||||
return function(scope, element) {
|
||||
element.on('click', function(event){
|
||||
// if we have no href url, then don't navigate anywhere.
|
||||
if (!element.attr('href')) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
if (!attr.href && !attr.name) {
|
||||
return function(scope, element) {
|
||||
element.on('click', function(event){
|
||||
// if we have no href url, then don't navigate anywhere.
|
||||
if (!element.attr('href')) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1432,7 +1432,6 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
|
||||
id="{{name}}"
|
||||
name="favorite">
|
||||
</label>
|
||||
</span>
|
||||
<div>You chose {{my.favorite}}</div>
|
||||
</form>
|
||||
</doc:source>
|
||||
|
||||
@@ -147,13 +147,14 @@
|
||||
* @description
|
||||
* Emitted every time the ngInclude content is reloaded.
|
||||
*/
|
||||
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animate', '$sce',
|
||||
function($http, $templateCache, $anchorScroll, $compile, $animate, $sce) {
|
||||
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
|
||||
function($http, $templateCache, $anchorScroll, $animate, $sce) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: 400,
|
||||
terminal: true,
|
||||
transclude: 'element',
|
||||
controller: angular.noop,
|
||||
compile: function(element, attr) {
|
||||
var srcExp = attr.ngInclude || attr.src,
|
||||
onloadExp = attr.onload || '',
|
||||
@@ -187,6 +188,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
|
||||
$http.get(src, {cache: $templateCache}).success(function(response) {
|
||||
if (thisChangeId !== changeCounter) return;
|
||||
var newScope = scope.$new();
|
||||
ctrl.template = response;
|
||||
|
||||
// Note: This will also link all children of ng-include that were contained in the original
|
||||
// html. If that content contains controllers, ... they could pollute/change the scope.
|
||||
@@ -194,15 +196,14 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
|
||||
// Note: We can't remove them in the cloneAttchFn of $transclude as that
|
||||
// function is called before linking the content, which would apply child
|
||||
// directives to non existing elements.
|
||||
var clone = $transclude(newScope, noop);
|
||||
cleanupLastIncludeContent();
|
||||
var clone = $transclude(newScope, function(clone) {
|
||||
cleanupLastIncludeContent();
|
||||
$animate.enter(clone, null, $element, afterAnimation);
|
||||
});
|
||||
|
||||
currentScope = newScope;
|
||||
currentElement = clone;
|
||||
|
||||
currentElement.html(response);
|
||||
$animate.enter(currentElement, null, $element, afterAnimation);
|
||||
$compile(currentElement.contents())(currentScope);
|
||||
currentScope.$emit('$includeContentLoaded');
|
||||
scope.$eval(onloadExp);
|
||||
}).error(function() {
|
||||
@@ -211,9 +212,28 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
|
||||
scope.$emit('$includeContentRequested');
|
||||
} else {
|
||||
cleanupLastIncludeContent();
|
||||
ctrl.template = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
// This directive is called during the $transclude call of the first `ngInclude` directive.
|
||||
// It will replace and compile the content of the element with the loaded template.
|
||||
// We need this directive so that the element content is already filled when
|
||||
// the link function of another directive on the same element as ngInclude
|
||||
// is called.
|
||||
var ngIncludeFillContentDirective = ['$compile',
|
||||
function($compile) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: -400,
|
||||
require: 'ngInclude',
|
||||
link: function(scope, $element, $attr, ctrl) {
|
||||
$element.html(ctrl.template);
|
||||
$compile($element.contents())(scope);
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
@@ -6,19 +6,26 @@
|
||||
* @restrict EA
|
||||
*
|
||||
* @description
|
||||
* The ngSwitch directive is used to conditionally swap DOM structure on your template based on a scope expression.
|
||||
* Elements within ngSwitch but without ngSwitchWhen or ngSwitchDefault directives will be preserved at the location
|
||||
* The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
|
||||
* Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
|
||||
* as specified in the template.
|
||||
*
|
||||
* The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
|
||||
* from the template cache), ngSwitch simply choses one of the nested elements and makes it visible based on which element
|
||||
* from the template cache), `ngSwitch` simply choses one of the nested elements and makes it visible based on which element
|
||||
* matches the value obtained from the evaluated expression. In other words, you define a container element
|
||||
* (where you place the directive), place an expression on the **on="..." attribute**
|
||||
* (or the **ng-switch="..." attribute**), define any inner elements inside of the directive and place
|
||||
* (where you place the directive), place an expression on the **`on="..."` attribute**
|
||||
* (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
|
||||
* a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
|
||||
* expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
|
||||
* attribute is displayed.
|
||||
*
|
||||
* <div class="alert alert-info">
|
||||
* Be aware that the attribute values to match against cannot be expressions. They are interpreted
|
||||
* as literal string values to match against.
|
||||
* For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
|
||||
* value of the expression `$scope.someVal`.
|
||||
* </div>
|
||||
|
||||
* @animations
|
||||
* enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
|
||||
* leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
|
||||
@@ -30,6 +37,7 @@
|
||||
* <ANY ng-switch-default>...</ANY>
|
||||
* </ANY>
|
||||
*
|
||||
*
|
||||
* @scope
|
||||
* @priority 800
|
||||
* @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
|
||||
|
||||
@@ -69,7 +69,7 @@ var ngTranscludeDirective = ngDirective({
|
||||
|
||||
link: function($scope, $element, $attrs, controller) {
|
||||
controller.$transclude(function(clone) {
|
||||
$element.html('');
|
||||
$element.empty();
|
||||
$element.append(clone);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -333,13 +333,13 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
||||
// becomes the compilation root
|
||||
nullOption.removeClass('ng-scope');
|
||||
|
||||
// we need to remove it before calling selectElement.html('') because otherwise IE will
|
||||
// we need to remove it before calling selectElement.empty() because otherwise IE will
|
||||
// remove the label from the element. wtf?
|
||||
nullOption.remove();
|
||||
}
|
||||
|
||||
// clear contents, we'll add what's needed based on the model
|
||||
selectElement.html('');
|
||||
selectElement.empty();
|
||||
|
||||
selectElement.on('change', function() {
|
||||
scope.$apply(function() {
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@
|
||||
*
|
||||
* # Differences between Kris Kowal's Q and $q
|
||||
*
|
||||
* There are three main differences:
|
||||
* There are two main differences:
|
||||
*
|
||||
* - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
|
||||
* mechanism in angular, which means faster propagation of resolution or rejection into your
|
||||
|
||||
+32
-32
@@ -156,11 +156,11 @@ function $RootScopeProvider(){
|
||||
* @description
|
||||
* Creates a new child {@link ng.$rootScope.Scope scope}.
|
||||
*
|
||||
* The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and
|
||||
* {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the
|
||||
* scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
|
||||
* The parent scope will propagate the {@link ng.$rootScope.Scope#methods_$digest $digest()} and
|
||||
* {@link ng.$rootScope.Scope#methods_$digest $digest()} events. The scope can be removed from the
|
||||
* scope hierarchy using {@link ng.$rootScope.Scope#methods_$destroy $destroy()}.
|
||||
*
|
||||
* {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
|
||||
* {@link ng.$rootScope.Scope#methods_$destroy $destroy()} must be called on a scope when it is
|
||||
* desired for the scope and its child scopes to be permanently detached from the parent and
|
||||
* thus stop participating in model change detection and listener notification by invoking.
|
||||
*
|
||||
@@ -213,11 +213,11 @@ function $RootScopeProvider(){
|
||||
* @description
|
||||
* Registers a `listener` callback to be executed whenever the `watchExpression` changes.
|
||||
*
|
||||
* - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
|
||||
* - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#methods_$digest
|
||||
* $digest()} and should return the value that will be watched. (Since
|
||||
* {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
|
||||
* {@link ng.$rootScope.Scope#methods_$digest $digest()} reruns when it detects changes the
|
||||
* `watchExpression` can execute multiple times per
|
||||
* {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
|
||||
* {@link ng.$rootScope.Scope#methods_$digest $digest()} and should be idempotent.)
|
||||
* - The `listener` is called only when the value from the current `watchExpression` and the
|
||||
* previous call to `watchExpression` are not equal (with the exception of the initial run,
|
||||
* see below). The inequality is determined according to
|
||||
@@ -229,13 +229,13 @@ function $RootScopeProvider(){
|
||||
* iteration limit is 10 to prevent an infinite loop deadlock.
|
||||
*
|
||||
*
|
||||
* If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
|
||||
* If you want to be notified whenever {@link ng.$rootScope.Scope#methods_$digest $digest} is called,
|
||||
* you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
|
||||
* can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
|
||||
* can execute multiple times per {@link ng.$rootScope.Scope#methods_$digest $digest} cycle when a
|
||||
* change is detected, be prepared for multiple calls to your listener.)
|
||||
*
|
||||
* After a watcher is registered with the scope, the `listener` fn is called asynchronously
|
||||
* (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
|
||||
* (via {@link ng.$rootScope.Scope#methods_$evalAsync $evalAsync}) to initialize the
|
||||
* watcher. In rare cases, this is undesirable because the listener is called when the result
|
||||
* of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
|
||||
* can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
|
||||
@@ -299,7 +299,7 @@ function $RootScopeProvider(){
|
||||
*
|
||||
*
|
||||
* @param {(function()|string)} watchExpression Expression that is evaluated on each
|
||||
* {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
|
||||
* {@link ng.$rootScope.Scope#methods_$digest $digest} cycle. A change in the return value triggers
|
||||
* a call to the `listener`.
|
||||
*
|
||||
* - `string`: Evaluated as {@link guide/expression expression}
|
||||
@@ -397,7 +397,7 @@ function $RootScopeProvider(){
|
||||
*
|
||||
* @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The
|
||||
* expression value should evaluate to an object or an array which is observed on each
|
||||
* {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
|
||||
* {@link ng.$rootScope.Scope#methods_$digest $digest} cycle. Any shallow change within the
|
||||
* collection will trigger a call to the `listener`.
|
||||
*
|
||||
* @param {function(newCollection, oldCollection, scope)} listener a callback function that is
|
||||
@@ -502,9 +502,9 @@ function $RootScopeProvider(){
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
|
||||
* its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
|
||||
* the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
|
||||
* Processes all of the {@link ng.$rootScope.Scope#methods_$watch watchers} of the current scope and
|
||||
* its children. Because a {@link ng.$rootScope.Scope#methods_$watch watcher}'s listener can change
|
||||
* the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#methods_$watch watchers}
|
||||
* until no more listeners are firing. This means that it is possible to get into an infinite
|
||||
* loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
|
||||
* iterations exceeds 10.
|
||||
@@ -512,12 +512,12 @@ function $RootScopeProvider(){
|
||||
* Usually, you don't call `$digest()` directly in
|
||||
* {@link ng.directive:ngController controllers} or in
|
||||
* {@link ng.$compileProvider#methods_directive directives}.
|
||||
* Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
|
||||
* Instead, you should call {@link ng.$rootScope.Scope#methods_$apply $apply()} (typically from within
|
||||
* a {@link ng.$compileProvider#methods_directive directives}), which will force a `$digest()`.
|
||||
*
|
||||
* If you want to be notified whenever `$digest()` is called,
|
||||
* you can register a `watchExpression` function with
|
||||
* {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
|
||||
* {@link ng.$rootScope.Scope#methods_$watch $watch()} with no `listener`.
|
||||
*
|
||||
* In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
|
||||
*
|
||||
@@ -672,7 +672,7 @@ function $RootScopeProvider(){
|
||||
*
|
||||
* @description
|
||||
* Removes the current scope (and all of its children) from the parent scope. Removal implies
|
||||
* that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
|
||||
* that calls to {@link ng.$rootScope.Scope#methods_$digest $digest()} will no longer
|
||||
* propagate to the current scope and its children. Removal also implies that the current
|
||||
* scope is eligible for garbage collection.
|
||||
*
|
||||
@@ -754,7 +754,7 @@ function $RootScopeProvider(){
|
||||
*
|
||||
* - it will execute after the function that scheduled the evaluation (preferably before DOM
|
||||
* rendering).
|
||||
* - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
|
||||
* - at least one {@link ng.$rootScope.Scope#methods_$digest $digest cycle} will be performed after
|
||||
* `expression` execution.
|
||||
*
|
||||
* Any exceptions from the execution of the expression are forwarded to the
|
||||
@@ -799,7 +799,7 @@ function $RootScopeProvider(){
|
||||
* framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
|
||||
* Because we are calling into the angular framework we need to perform proper scope life
|
||||
* cycle of {@link ng.$exceptionHandler exception handling},
|
||||
* {@link ng.$rootScope.Scope#$digest executing watches}.
|
||||
* {@link ng.$rootScope.Scope#methods_$digest executing watches}.
|
||||
*
|
||||
* ## Life cycle
|
||||
*
|
||||
@@ -820,11 +820,11 @@ function $RootScopeProvider(){
|
||||
* Scope's `$apply()` method transitions through the following stages:
|
||||
*
|
||||
* 1. The {@link guide/expression expression} is executed using the
|
||||
* {@link ng.$rootScope.Scope#$eval $eval()} method.
|
||||
* {@link ng.$rootScope.Scope#methods_$eval $eval()} method.
|
||||
* 2. Any exceptions from the execution of the expression are forwarded to the
|
||||
* {@link ng.$exceptionHandler $exceptionHandler} service.
|
||||
* 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
|
||||
* expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
|
||||
* 3. The {@link ng.$rootScope.Scope#methods_$watch watch} listeners are fired immediately after the
|
||||
* expression was executed using the {@link ng.$rootScope.Scope#methods_$digest $digest()} method.
|
||||
*
|
||||
*
|
||||
* @param {(string|function())=} exp An angular expression to be executed.
|
||||
@@ -858,7 +858,7 @@ function $RootScopeProvider(){
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
|
||||
* Listens on events of a given type. See {@link ng.$rootScope.Scope#methods_$emit $emit} for
|
||||
* discussion of event life cycle.
|
||||
*
|
||||
* The event listener function format is: `function(event, args...)`. The `event` object
|
||||
@@ -899,20 +899,20 @@ function $RootScopeProvider(){
|
||||
*
|
||||
* @description
|
||||
* Dispatches an event `name` upwards through the scope hierarchy notifying the
|
||||
* registered {@link ng.$rootScope.Scope#$on} listeners.
|
||||
* registered {@link ng.$rootScope.Scope#methods_$on} listeners.
|
||||
*
|
||||
* The event life cycle starts at the scope on which `$emit` was called. All
|
||||
* {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
|
||||
* {@link ng.$rootScope.Scope#methods_$on listeners} listening for `name` event on this scope get
|
||||
* notified. Afterwards, the event traverses upwards toward the root scope and calls all
|
||||
* registered listeners along the way. The event will stop propagating if one of the listeners
|
||||
* cancels it.
|
||||
*
|
||||
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
|
||||
* Any exception emitted from the {@link ng.$rootScope.Scope#methods_$on listeners} will be passed
|
||||
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
|
||||
*
|
||||
* @param {string} name Event name to emit.
|
||||
* @param {...*} args Optional set of arguments which will be passed onto the event listeners.
|
||||
* @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
|
||||
* @return {Object} Event object (see {@link ng.$rootScope.Scope#methods_$on}).
|
||||
*/
|
||||
$emit: function(name, args) {
|
||||
var empty = [],
|
||||
@@ -968,19 +968,19 @@ function $RootScopeProvider(){
|
||||
*
|
||||
* @description
|
||||
* Dispatches an event `name` downwards to all child scopes (and their children) notifying the
|
||||
* registered {@link ng.$rootScope.Scope#$on} listeners.
|
||||
* registered {@link ng.$rootScope.Scope#methods_$on} listeners.
|
||||
*
|
||||
* The event life cycle starts at the scope on which `$broadcast` was called. All
|
||||
* {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
|
||||
* {@link ng.$rootScope.Scope#methods_$on listeners} listening for `name` event on this scope get
|
||||
* notified. Afterwards, the event propagates to all direct and indirect scopes of the current
|
||||
* scope and calls all registered listeners along the way. The event cannot be canceled.
|
||||
*
|
||||
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
|
||||
* Any exception emitted from the {@link ng.$rootScope.Scope#methods_$on listeners} will be passed
|
||||
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
|
||||
*
|
||||
* @param {string} name Event name to broadcast.
|
||||
* @param {...*} args Optional set of arguments which will be passed onto the event listeners.
|
||||
* @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
|
||||
* @return {Object} Event object, see {@link ng.$rootScope.Scope#methods_$on}
|
||||
*/
|
||||
$broadcast: function(name, args) {
|
||||
var target = this,
|
||||
|
||||
@@ -1237,7 +1237,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
//make the element super hidden and override any CSS style values
|
||||
clone.attr('style','position:absolute; top:-9999px; left:-9999px');
|
||||
clone.removeAttr('id');
|
||||
clone.html('');
|
||||
clone.empty();
|
||||
|
||||
forEach(oldClasses.split(' '), function(klass) {
|
||||
clone.removeClass(klass);
|
||||
|
||||
Vendored
+3
-2
@@ -1087,7 +1087,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
||||
var definitions = [],
|
||||
expectations = [],
|
||||
responses = [],
|
||||
responsesPush = angular.bind(responses, responses.push);
|
||||
responsesPush = angular.bind(responses, responses.push),
|
||||
copy = angular.copy;
|
||||
|
||||
function createResponse(status, data, headers) {
|
||||
if (angular.isFunction(status)) return status;
|
||||
@@ -1119,7 +1120,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
|
||||
function handleResponse() {
|
||||
var response = wrapped.response(method, url, data, headers);
|
||||
xhr.$$respHeaders = response[2];
|
||||
callback(response[0], response[1], xhr.getAllResponseHeaders());
|
||||
callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders());
|
||||
}
|
||||
|
||||
function handleTimeout() {
|
||||
|
||||
@@ -24,6 +24,25 @@ function lookupDottedPath(obj, path) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shallow copy of an object and clear other fields from the destination
|
||||
*/
|
||||
function shallowClearAndCopy(src, dst) {
|
||||
dst = dst || {};
|
||||
|
||||
angular.forEach(dst, function(value, key){
|
||||
delete dst[key];
|
||||
});
|
||||
|
||||
for (var key in src) {
|
||||
if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
|
||||
dst[key] = src[key];
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name ngResource
|
||||
@@ -393,7 +412,7 @@ angular.module('ngResource', ['ng']).
|
||||
}
|
||||
|
||||
function Resource(value){
|
||||
copy(value || {}, this);
|
||||
shallowClearAndCopy(value || {}, this);
|
||||
}
|
||||
|
||||
forEach(actions, function(action, name) {
|
||||
@@ -465,7 +484,7 @@ angular.module('ngResource', ['ng']).
|
||||
if (data) {
|
||||
// Need to convert action.isArray to boolean in case it is undefined
|
||||
// jshint -W018
|
||||
if ( angular.isArray(data) !== (!!action.isArray) ) {
|
||||
if (angular.isArray(data) !== (!!action.isArray)) {
|
||||
throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +
|
||||
'response to contain an {0} but got an {1}',
|
||||
action.isArray?'array':'object', angular.isArray(data)?'array':'object');
|
||||
@@ -477,7 +496,7 @@ angular.module('ngResource', ['ng']).
|
||||
value.push(new Resource(item));
|
||||
});
|
||||
} else {
|
||||
copy(data, value);
|
||||
shallowClearAndCopy(data, value);
|
||||
value.$promise = promise;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
ngRouteModule.directive('ngView', ngViewFactory);
|
||||
ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
@@ -166,8 +168,8 @@ ngRouteModule.directive('ngView', ngViewFactory);
|
||||
* @description
|
||||
* Emitted every time the ngView content is reloaded.
|
||||
*/
|
||||
ngViewFactory.$inject = ['$route', '$anchorScroll', '$compile', '$controller', '$animate'];
|
||||
function ngViewFactory( $route, $anchorScroll, $compile, $controller, $animate) {
|
||||
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
|
||||
function ngViewFactory( $route, $anchorScroll, $animate) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
terminal: true,
|
||||
@@ -199,6 +201,7 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
||||
|
||||
if (template) {
|
||||
var newScope = scope.$new();
|
||||
var current = $route.current;
|
||||
|
||||
// Note: This will also link all children of ng-view that were contained in the original
|
||||
// html. If that content contains controllers, ... they could pollute/change the scope.
|
||||
@@ -206,34 +209,18 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
||||
// Note: We can't remove them in the cloneAttchFn of $transclude as that
|
||||
// function is called before linking the content, which would apply child
|
||||
// directives to non existing elements.
|
||||
var clone = $transclude(newScope, angular.noop);
|
||||
clone.html(template);
|
||||
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
||||
if (angular.isDefined(autoScrollExp)
|
||||
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
}
|
||||
var clone = $transclude(newScope, function(clone) {
|
||||
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
||||
if (angular.isDefined(autoScrollExp)
|
||||
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
}
|
||||
});
|
||||
cleanupLastView();
|
||||
});
|
||||
|
||||
cleanupLastView();
|
||||
|
||||
var link = $compile(clone.contents()),
|
||||
current = $route.current;
|
||||
|
||||
currentScope = current.scope = newScope;
|
||||
currentElement = clone;
|
||||
|
||||
if (current.controller) {
|
||||
locals.$scope = currentScope;
|
||||
var controller = $controller(current.controller, locals);
|
||||
if (current.controllerAs) {
|
||||
currentScope[current.controllerAs] = controller;
|
||||
}
|
||||
clone.data('$ngControllerController', controller);
|
||||
clone.children().data('$ngControllerController', controller);
|
||||
}
|
||||
|
||||
link(currentScope);
|
||||
currentScope = current.scope = newScope;
|
||||
currentScope.$emit('$viewContentLoaded');
|
||||
currentScope.$eval(onloadExp);
|
||||
} else {
|
||||
@@ -243,3 +230,36 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This directive is called during the $transclude call of the first `ngView` directive.
|
||||
// It will replace and compile the content of the element with the loaded template.
|
||||
// We need this directive so that the element content is already filled when
|
||||
// the link function of another directive on the same element as ngView
|
||||
// is called.
|
||||
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
|
||||
function ngViewFillContentFactory($compile, $controller, $route) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: -400,
|
||||
link: function(scope, $element) {
|
||||
var current = $route.current,
|
||||
locals = current.locals;
|
||||
|
||||
$element.html(locals.$template);
|
||||
|
||||
var link = $compile($element.contents());
|
||||
|
||||
if (current.controller) {
|
||||
locals.$scope = scope;
|
||||
var controller = $controller(current.controller, locals);
|
||||
if (current.controllerAs) {
|
||||
scope[current.controllerAs] = controller;
|
||||
}
|
||||
$element.data('$ngControllerController', controller);
|
||||
$element.children().data('$ngControllerController', controller);
|
||||
}
|
||||
|
||||
link(scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,13 +52,13 @@ function $RouteProvider(){
|
||||
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
|
||||
* route definition.
|
||||
*
|
||||
* * `path` can contain named groups starting with a colon (`:name`). All characters up
|
||||
* * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
|
||||
* to the next slash are matched and stored in `$routeParams` under the given `name`
|
||||
* when the route matches.
|
||||
* * `path` can contain named groups starting with a colon and ending with a star (`:name*`).
|
||||
* All characters are eagerly stored in `$routeParams` under the given `name`
|
||||
* * `path` can contain named groups starting with a colon and ending with a star:
|
||||
* e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
|
||||
* when the route matches.
|
||||
* * `path` can contain optional named groups with a question mark (`:name?`).
|
||||
* * `path` can contain optional named groups with a question mark: e.g.`:name?`.
|
||||
*
|
||||
* For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
|
||||
* `/color/brown/largecode/code/with/slashs/edit` and extract:
|
||||
|
||||
@@ -29,8 +29,7 @@ beforeEach(function() {
|
||||
bindJQuery();
|
||||
}
|
||||
|
||||
|
||||
angular.element(document.body).html('').removeData();
|
||||
angular.element(document.body).empty().removeData();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
|
||||
+23
-2
@@ -322,7 +322,7 @@ describe('jqLite', function() {
|
||||
});
|
||||
|
||||
|
||||
it('should emit $destroy event if an element is removed via html()', inject(function(log) {
|
||||
it('should emit $destroy event if an element is removed via html(\'\')', inject(function(log) {
|
||||
var element = jqLite('<div><span>x</span></div>');
|
||||
element.find('span').on('$destroy', log.fn('destroyed'));
|
||||
|
||||
@@ -333,6 +333,17 @@ describe('jqLite', function() {
|
||||
}));
|
||||
|
||||
|
||||
it('should emit $destroy event if an element is removed via empty()', inject(function(log) {
|
||||
var element = jqLite('<div><span>x</span></div>');
|
||||
element.find('span').on('$destroy', log.fn('destroyed'));
|
||||
|
||||
element.empty();
|
||||
|
||||
expect(element.html()).toBe('');
|
||||
expect(log).toEqual('destroyed');
|
||||
}));
|
||||
|
||||
|
||||
it('should retrieve all data if called without params', function() {
|
||||
var element = jqLite(a);
|
||||
expect(element.data()).toEqual({});
|
||||
@@ -786,7 +797,7 @@ describe('jqLite', function() {
|
||||
});
|
||||
|
||||
|
||||
it('should read/write value', function() {
|
||||
it('should read/write a value', function() {
|
||||
var element = jqLite('<div>abc</div>');
|
||||
expect(element.length).toEqual(1);
|
||||
expect(element[0].innerHTML).toEqual('abc');
|
||||
@@ -797,6 +808,16 @@ describe('jqLite', function() {
|
||||
});
|
||||
|
||||
|
||||
describe('empty', function() {
|
||||
it('should write a value', function() {
|
||||
var element = jqLite('<div>abc</div>');
|
||||
expect(element.length).toEqual(1);
|
||||
expect(element.empty() == element).toBeTruthy();
|
||||
expect(element.html()).toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('on', function() {
|
||||
it('should bind to window on hashchange', function() {
|
||||
if (jqLite.fn) return; // don't run in jQuery
|
||||
|
||||
+60
-4
@@ -170,26 +170,26 @@ describe('$compile', function() {
|
||||
// First with only elements at the top level
|
||||
element = jqLite('<div><div></div></div>');
|
||||
$compile(element.contents())($rootScope);
|
||||
element.html('');
|
||||
element.empty();
|
||||
expect(calcCacheSize()).toEqual(0);
|
||||
|
||||
// Next with non-empty text nodes at the top level
|
||||
// (in this case the compiler will wrap them in a <span>)
|
||||
element = jqLite('<div>xxx</div>');
|
||||
$compile(element.contents())($rootScope);
|
||||
element.html('');
|
||||
element.empty();
|
||||
expect(calcCacheSize()).toEqual(0);
|
||||
|
||||
// Next with comment nodes at the top level
|
||||
element = jqLite('<div><!-- comment --></div>');
|
||||
$compile(element.contents())($rootScope);
|
||||
element.html('');
|
||||
element.empty();
|
||||
expect(calcCacheSize()).toEqual(0);
|
||||
|
||||
// Finally with empty text nodes at the top level
|
||||
element = jqLite('<div> \n<div></div> </div>');
|
||||
$compile(element.contents())($rootScope);
|
||||
element.html('');
|
||||
element.empty();
|
||||
expect(calcCacheSize()).toEqual(0);
|
||||
});
|
||||
|
||||
@@ -2492,6 +2492,62 @@ describe('$compile', function() {
|
||||
|
||||
expect(lastRefValueInParent).toBe('new');
|
||||
}));
|
||||
|
||||
describe('literal objects', function() {
|
||||
it('should copy parent changes', inject(function() {
|
||||
compile('<div><span my-component reference="{name: name}">');
|
||||
|
||||
$rootScope.name = 'a';
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toEqual({name: 'a'});
|
||||
|
||||
$rootScope.name = 'b';
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toEqual({name: 'b'});
|
||||
}));
|
||||
|
||||
it('should not change the component when parent does not change', inject(function() {
|
||||
compile('<div><span my-component reference="{name: name}">');
|
||||
|
||||
$rootScope.name = 'a';
|
||||
$rootScope.$apply();
|
||||
var lastComponentValue = componentScope.reference;
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toBe(lastComponentValue);
|
||||
}));
|
||||
|
||||
it('should complain when the component changes', inject(function() {
|
||||
compile('<div><span my-component reference="{name: name}">');
|
||||
|
||||
$rootScope.name = 'a';
|
||||
$rootScope.$apply();
|
||||
componentScope.reference = {name: 'b'};
|
||||
expect(function() {
|
||||
$rootScope.$apply();
|
||||
}).toThrowMinErr("$compile", "nonassign", "Expression '{name: name}' used with directive 'myComponent' is non-assignable!");
|
||||
|
||||
}));
|
||||
|
||||
it('should work for primitive literals', inject(function() {
|
||||
test('1', 1);
|
||||
test('null', null);
|
||||
test('undefined', undefined);
|
||||
test("'someString'", 'someString');
|
||||
|
||||
|
||||
function test(literalString, literalValue) {
|
||||
compile('<div><span my-component reference="'+literalString+'">');
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(componentScope.reference).toBe(literalValue);
|
||||
dealoc(element);
|
||||
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -58,4 +58,30 @@ describe('a', function() {
|
||||
|
||||
expect(element.text()).toBe('hello@you');
|
||||
});
|
||||
|
||||
|
||||
it('should not link and hookup an event if href is present at compile', function() {
|
||||
var jq = jQuery || jqLite;
|
||||
element = jq('<a href="//a.com">hello@you</a>');
|
||||
var linker = $compile(element);
|
||||
|
||||
spyOn(jq.prototype, 'on');
|
||||
|
||||
linker($rootScope);
|
||||
|
||||
expect(jq.prototype.on).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should not link and hookup an event if name is present at compile', function() {
|
||||
var jq = jQuery || jqLite;
|
||||
element = jq('<a name="bobby">hello@you</a>');
|
||||
var linker = $compile(element);
|
||||
|
||||
spyOn(jq.prototype, 'on');
|
||||
|
||||
linker($rootScope);
|
||||
|
||||
expect(jq.prototype.on).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -216,7 +216,7 @@ describe('form', function() {
|
||||
// yes, I know, scope methods should not do direct DOM manipulation, but I wanted to keep
|
||||
// this test small. Imagine that the destroy action will cause a model change (e.g.
|
||||
// $location change) that will cause some directive to destroy the dom (e.g. ngView+$route)
|
||||
doc.html('');
|
||||
doc.empty();
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('ngInclude', function() {
|
||||
$rootScope.url = 'myUrl';
|
||||
$rootScope.$digest();
|
||||
expect(body.text()).toEqual('misko');
|
||||
body.html('');
|
||||
body.empty();
|
||||
}));
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('ngInclude', function() {
|
||||
$rootScope.url = 'myUrl';
|
||||
$rootScope.$digest();
|
||||
expect(element.text()).toEqual('Alibaba');
|
||||
jqLite(document.body).html('');
|
||||
jqLite(document.body).empty();
|
||||
}));
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('ngInclude', function() {
|
||||
expect(function() { $rootScope.$digest(); }).toThrowMinErr(
|
||||
'$sce', 'insecurl',
|
||||
/Blocked loading resource from url not allowed by \$sceDelegate policy. URL: http:\/\/example.com\/myUrl.*/);
|
||||
jqLite(document.body).html('');
|
||||
jqLite(document.body).empty();
|
||||
}));
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ describe('ngInclude', function() {
|
||||
expect(function() { $rootScope.$digest(); }).toThrowMinErr(
|
||||
'$sce', 'insecurl',
|
||||
/Blocked loading resource from url not allowed by \$sceDelegate policy. URL: http:\/\/example.com\/myUrl.*/);
|
||||
jqLite(document.body).html('');
|
||||
jqLite(document.body).empty();
|
||||
}));
|
||||
|
||||
|
||||
@@ -524,6 +524,46 @@ describe('ngInclude and transcludes', function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should link directives on the same element after the content has been loaded', function() {
|
||||
var contentOnLink;
|
||||
module(function() {
|
||||
directive('test', function() {
|
||||
return {
|
||||
link: function(scope, element) {
|
||||
contentOnLink = element.text();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET('include.html').respond('someContent');
|
||||
element = $compile('<div><div ng-include="\'include.html\'" test></div>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
$httpBackend.flush();
|
||||
expect(contentOnLink).toBe('someContent');
|
||||
});
|
||||
});
|
||||
|
||||
it('should add the content to the element before compiling it', function() {
|
||||
var root;
|
||||
module(function() {
|
||||
directive('test', function() {
|
||||
return {
|
||||
link: function(scope, element) {
|
||||
root = element.parent().parent();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET('include.html').respond('<span test></span>');
|
||||
element = $compile('<div><div ng-include="\'include.html\'"></div>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
$httpBackend.flush();
|
||||
expect(root[0]).toBe(element[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngInclude animations', function() {
|
||||
|
||||
@@ -301,7 +301,7 @@ describe("ngAnimate", function() {
|
||||
inject(function($animate, $compile, $rootScope, $timeout, $sniffer) {
|
||||
|
||||
$rootScope.$digest();
|
||||
element.html('');
|
||||
element.empty();
|
||||
|
||||
var child1 = $compile('<div>1</div>')($rootScope);
|
||||
var child2 = $compile('<div>2</div>')($rootScope);
|
||||
|
||||
Vendored
+28
-2
@@ -766,7 +766,7 @@ describe('ngMock', function() {
|
||||
|
||||
describe('object literal format', function() {
|
||||
var mock = { log: 'module' };
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
module({
|
||||
'service': mock,
|
||||
@@ -782,7 +782,7 @@ describe('ngMock', function() {
|
||||
expect(service).toEqual(mock);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should support multiple key value pairs', function() {
|
||||
inject(function(service, other) {
|
||||
expect(other.some).toEqual('replacement');
|
||||
@@ -891,6 +891,32 @@ describe('ngMock', function() {
|
||||
});
|
||||
|
||||
|
||||
it('should respond with a copy of the mock data', function() {
|
||||
var mockObject = {a: 'b'};
|
||||
|
||||
hb.when('GET', '/url1').respond(200, mockObject, {});
|
||||
|
||||
callback.andCallFake(function(status, response) {
|
||||
expect(status).toBe(200);
|
||||
expect(response).toEqual({a: 'b'});
|
||||
expect(response).not.toBe(mockObject);
|
||||
response.a = 'c';
|
||||
});
|
||||
|
||||
hb('GET', '/url1', null, callback);
|
||||
hb.flush();
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
|
||||
// Fire it again and verify that the returned mock data has not been
|
||||
// modified.
|
||||
callback.reset();
|
||||
hb('GET', '/url1', null, callback);
|
||||
hb.flush();
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
expect(mockObject).toEqual({a: 'b'});
|
||||
});
|
||||
|
||||
|
||||
it('should throw error when unexpected request', function() {
|
||||
hb.when('GET', '/url1').respond(200, 'content');
|
||||
expect(function() {
|
||||
|
||||
@@ -582,6 +582,46 @@ describe('ngView and transcludes', function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should link directives on the same element after the content has been loaded', function() {
|
||||
var contentOnLink;
|
||||
module(function($compileProvider, $routeProvider) {
|
||||
$routeProvider.when('/view', {template: 'someContent'});
|
||||
$compileProvider.directive('test', function() {
|
||||
return {
|
||||
link: function(scope, element) {
|
||||
contentOnLink = element.text();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, $location) {
|
||||
element = $compile('<div><div ng-view test></div>')($rootScope);
|
||||
$location.url('/view');
|
||||
$rootScope.$apply();
|
||||
expect(contentOnLink).toBe('someContent');
|
||||
});
|
||||
});
|
||||
|
||||
it('should add the content to the element before compiling it', function() {
|
||||
var root;
|
||||
module(function($compileProvider, $routeProvider) {
|
||||
$routeProvider.when('/view', {template: '<span test></span>'});
|
||||
$compileProvider.directive('test', function() {
|
||||
return {
|
||||
link: function(scope, element) {
|
||||
root = element.parent().parent();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, $location) {
|
||||
element = $compile('<div><div ng-view></div>')($rootScope);
|
||||
$location.url('/view');
|
||||
$rootScope.$apply();
|
||||
expect(root[0]).toBe(element[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngView animations', function() {
|
||||
|
||||
@@ -53,7 +53,7 @@ describe("angular.scenario.dsl", function() {
|
||||
// Just use the real one since it delegates to this.addFuture
|
||||
$root.addFutureAction = angular.scenario.
|
||||
SpecRunner.prototype.addFutureAction;
|
||||
jqLite($window.document).html('');
|
||||
jqLite($window.document).empty();
|
||||
}));
|
||||
|
||||
afterEach(function(){
|
||||
|
||||
@@ -152,7 +152,7 @@ describe('ngClick (touch)', function() {
|
||||
}));
|
||||
|
||||
afterEach(inject(function($document) {
|
||||
$document.find('body').html('');
|
||||
$document.find('body').empty();
|
||||
}));
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
grunt parallel:travis --reporters dots \
|
||||
--browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_8,SL_IE_9,SL_IE_10,SL_IE_11 \
|
||||
--e2e-browsers SL_Chrome
|
||||
@@ -21,6 +21,7 @@ var TYPES = {
|
||||
docs: true,
|
||||
style: true,
|
||||
refactor: true,
|
||||
perf: true,
|
||||
test: true,
|
||||
chore: true,
|
||||
revert: true
|
||||
|
||||
Reference in New Issue
Block a user