Compare commits

..

228 Commits

Author SHA1 Message Date
jenkins 07ee29c563 chore(release): cut v1.2.9 release 2014-01-15 10:02:10 -08:00
Peter Bacon Darwin 9f5d0cf79f docs(changelog): release notes for 1.2.9 2014-01-15 17:24:18 +00:00
Matias Niemelä 1413328e6a fix(ngMock): ensure ngAnimate isn't a required mock 2014-01-15 03:43:52 -05:00
Matias Niemelä 7d09bd30f9 chore($animate): remove Moz statements from requestAnimationFrame 2014-01-15 03:29:20 -05:00
Matias Niemelä dde1b29497 feat($animate): provide support for DOM callbacks 2014-01-14 13:21:28 -05:00
Matias Niemelä 4ae3184c59 feat($animate): use requestAnimationFrame instead of a timeout to issue a reflow
Closes #4278
Closes #4225
2014-01-14 13:21:19 -05:00
Matias Niemelä ed53100a0d fix($animate): ensure the final closing timeout respects staggering animations 2014-01-14 13:20:50 -05:00
Matias Niemelä 6df598d9f5 chore($animate): remove useless and expired test 2014-01-14 13:20:27 -05:00
Matias Niemelä 4aa9df7a7a fix($animate): prevent race conditions for class-based animations when animating on the same CSS class
Closes #5588
2014-01-14 13:20:10 -05:00
Matias Niemelä 7d5d62dafe fix($animate): correctly detect and handle CSS transition changes during class addition and removal
When a CSS class containing transition code is added to an element then an animation should kick off.
ngAnimate doesn't do this. It only respects transition styles that are already present on the element
or on the setup class (but not the addClass animation).
2014-01-14 13:19:09 -05:00
Matias Niemelä 524650a40e fix($animate): avoid accidentally matching substrings when resolving the presence of className tokens 2014-01-14 13:18:50 -05:00
Sebastian Müller 02a45826f1 docs(docs): preserve path to current doc page when switching versions
Preserve URL path when switching between doc versions.

Closes #4661
Closes #5773
2014-01-14 06:39:44 +00:00
Lukas Ruebbelke e324c14907 docs(provider): replaced coffeescript with comparable javascript example 2014-01-13 23:03:36 -05:00
Hendrixer e1cfb1957f fix($http): ensure default headers PUT and POST are different objects
Send PUT and POST through copy() to make sure they are not the same.

Closes #5742
Closes #5747
Closes #5764
2014-01-13 16:50:15 -08:00
marcwright 2a3586381f docs(tutorial): fix a typo
Closes #5769
2014-01-13 16:40:56 -08:00
Igor Minar 834d316829 docs(forEach): remove obsolte note 2014-01-13 16:31:43 -08:00
Mehul Patel c61be8d0e6 docs(angular.forEach): specifies that .forEach filters using .hasOwnProperty
Closes #5180
Closes #5776
2014-01-13 16:31:42 -08:00
Pop 465212835f docs(guide): fix a typo 2014-01-13 16:24:56 -08:00
Frederik Creemers b3acddea37 docs(CONTRIBUTING.md): add link to coding rules
add a link insie the Submitting a Pull Request section
2014-01-13 16:18:14 -08:00
Igor Minar 308598795a revert: fix($route): update current route upon $route instantiation
This reverts commit 2b344dbd20.

I think I merged this commit prematurely and in addition to that
we found out that it's breaking google apps.

Jen Bourey will provide more info at the original PR #5681
2014-01-13 15:12:17 -08:00
Noam Lewis 2cd09c9f0e fix($rootScope): prevent infinite $digest by checking if asyncQueue is empty when decrementing ttl
An infinite $digest loop can be caused by expressions that invoke a promise.
The problem is that $digest does not decrement ttl unless it finds dirty changes;
it should check also if asyncQueue is empty.
Generally the condition for decrementing ttl should be the same as the
condition for terminating the $digest loop.

Fixes #2622
2014-01-13 09:53:38 -08:00
Leniel Macaferi 34fee06ca7 docs(tutorial): referenced test.bat for Windows users in step 2
Closes #5748
2014-01-11 20:15:50 -08:00
Igor Minar c7a46d4b8a docs(ngView): moar better autoscroll docs
Closes #5734
2014-01-11 14:29:05 -08:00
Gias Kay Lee de065f1961 docs(ngView): add param info
Closes #5734
Closes #5741
2014-01-11 14:18:07 -08:00
Seth Stone c3ab915d2e docs(tutorial): add missing beforeEach(module()) to test
Test snippet was missing this necessary statement that was present in the sample code.

Closes #5743
2014-01-11 14:09:52 -08:00
Roy Ling f4a4f42abb docs(api/index): fix typo
Closes #5738
2014-01-10 23:43:32 -08:00
jesse b2c84ccde3 docs($sce): corrected typo & markup.
the --> that

value --> `value`

Closes #5735
2014-01-10 23:42:36 -08:00
Daniel Zimmermann 2b344dbd20 fix($route): update current route upon $route instantiation
This fixes cases where the first ngView is loaded in a template asynchronously (such as through ngInclude), as the service will miss the first  event otherwise.

Closes #4957
2014-01-10 23:42:36 -08:00
Jeff Cross cde840fdf8 docs(i18n): remove use of gendered pronoun 2014-01-10 20:15:18 -08:00
Naomi Black f9656dab2d docs: update step_04.ngdoc with a clarification
closes #5730
2014-01-10 17:11:39 -08:00
Naomi Black a0d759c613 docs: add clarification in step 2 of the tutorial 2014-01-10 16:54:20 -08:00
jenkins 0d421f093d chore(release): update cdn version 2014-01-10 14:33:27 -08:00
jenkins 5f937e54df chore(release): start v1.2.9 (1.2.9) 2014-01-10 12:51:00 -08:00
jenkins 0f9a1c21e6 chore(release): cut v1.2.8 release 2014-01-10 12:37:49 -08:00
Brian Ford ece7854972 docs(changelog): release notes for 1.2.8 2014-01-10 11:49:06 -08:00
Ajay Roopakalu 8ace8073fd docs(select): update regexp grouping cheat-sheat
Update the regexp grouping comment to reflect the changes needed for
multiline expressions in ng-options for <select>.

Closes #5602
2014-01-10 09:50:28 -08:00
Ajay Roopakalu 43a2f3d0bf feat(select): allow multiline ng-options
This patch allows the ng-options value of a <select> element to span
multiple lines, which would previously throw an error when used with filters.

Closes #5602
2014-01-10 09:50:28 -08:00
Igor Minar a9cccbe14f fix($http): return responseText on IE8 for requests with responseType set
Closes #4464
Closes #4738
Closes #5636
2014-01-10 02:25:36 -08:00
Narretz 36c9e42de2 docs: fix the 'view source' button for snapshots
Closes #5590
Closes #5641
2014-01-10 02:22:27 -08:00
René Wilhelm 9f566db33c docs(\$resource): fixed typo (s/seapph/search)
Closes #5718
2014-01-10 01:10:19 -08:00
Caitlin Potter c77b2bcca3 docs($location): fix link to $locationChangeSuccess event
Closes #5717
2014-01-10 00:58:40 -08:00
Igor Minar 5a4145fe16 revert: fix($location): return '/' for root path in hashbang mode
This reverts commit 63cd873fef.

The change breaks existing tests of Google apps. The problem is that
while we tried to avoid adding #/ to window.location.href unnecessarily
we failed doing so. Likely because by setting $path, at some point
(during a digest) we try to check if $location changed and we mistake the
default '/' with an explicit settign of the path via the `path()` method.
This results in us writing the url with '#/' into $browser.url() which updates
the window.location by adding "#/" to the url - something we tried to avoid
in the first place.

I'll reopen PR #5712.
2014-01-09 23:47:35 -08:00
Jeff Cross 039b990d8d test(docs): add protractor tests for docs app
Closes #5437
2014-01-09 22:41:52 -08:00
Tobias Bosch 5a9cb8be3f chore(build): bugfix for script utils 2014-01-09 17:37:27 -08:00
Caitlin Potter 63cd873fef fix($location): return '/' for root path in hashbang mode
Before this change, on the root of the application, $location.path() would return
the empty string. Following this change, it will always return a root of '/'.

Closes #5650
Closes #5712
2014-01-09 17:35:25 -08:00
Igor Minar 69452fa94f docs(tutorial): improve experiment instructions
Closes #5697
2014-01-09 17:24:10 -08:00
Julie 2ed4ad5502 feat(build): add a grunt test for running protractor tests extracted from the docs 2014-01-09 17:21:46 -08:00
René Wilhelm 1d2a388830 fix(docs): Add missing whitespace 2014-01-09 16:51:47 -08:00
stucash ac05276a51 fix(docs): Update reference to $routeProvider.otherwise 2014-01-09 16:48:15 -08:00
Craig Younkins cb9c0f200a fix(docs): Clarifying versions of IE that need special fixes 2014-01-09 16:34:16 -08:00
Tobias Bosch b1d676b7f7 chore(build): check cdn before executing the release-after-cdn script 2014-01-09 15:29:02 -08:00
Tobias Bosch 9ddef840b6 chore(build): add relase-after-cdn script 2014-01-09 14:59:55 -08:00
Rafał Jagoda 28fc80bba0 fix($httpBackend): Allow status code 0 from any protocol
Android 4.1 stock browser also returns status code 0 when
a template is loaded via `http` and the application is cached using
appcache.

Fixes #1356.
Closes #5547.
2014-01-09 10:10:11 -08:00
Julie b6c42d5e81 feat(docs): adding the <doc:protractor> ngdoc-tag
This is the first step in migrating tests from <doc:scenario> to <doc:protractor>.
In-documentation examples with doc:protractor sections will have their contents
output to a tab on the docs site as well as output to a standalone test file in
build/docs/ptore2e.
2014-01-08 13:07:58 -08:00
Gias Kay Lee 1c045f1b46 docs(script): add more detailed information
Closes #5671
Closes #5676
2014-01-08 00:49:29 -08:00
Artemy Tregubenko 95e1b2d612 fix($httpBackend): cancelled JSONP requests will not print error in the console
When you cancel a JSONP request, angular deletes the callback for it. However the script still executes, and since the callback is now deleted and undefined, the script throws an exception visible in the console. The quick fix for this is not to delete the callback, but replace it with `angular.noop`.

Closes #5615
Closes #5616
2014-01-08 00:35:19 -08:00
Igor Minar 75345e3487 docs($document): moar better description
Closes #5678
2014-01-07 17:07:48 -08:00
Igor Minar f4fe28bd92 docs($document): improve the description
Closes #5678
2014-01-07 17:06:22 -08:00
Tobias Bosch ace13b94e6 chore(build): fix typo in release script 2014-01-07 17:00:53 -08:00
Gias Kay Lee 5df7e73adf refactor(booleanAttrs, ngSwitch): use link function instead of compile function where appropriate
Replace two compile functions that immediately return a post-link function with link function definitions instead.

Closes #5664
2014-01-07 16:54:35 -08:00
Zhong Liang Ong e115342fce docs(directives): Fixed typo from HMTL to HTML in line 283
HTML was mis-spelt as HMTL
2014-01-07 16:51:47 -08:00
Tobias Bosch e89150ca0f chore(build): Add angular-seed and angular-phonecat to the release 2014-01-07 15:49:03 -08:00
Vojta Jina 9693a426e3 chore(travis): use Safari 7 2014-01-07 11:53:50 -08:00
Vojta Jina 162485d303 chore(travis): use FF26
I think it's better to not specify the version as that should give the latest available version.
We should probably revert this commit at some point.
2014-01-07 11:53:17 -08:00
Vojta Jina affcbad501 test(ngMock): fix the tests to not use global msie
My bad when merging 7e916455b3.

These tests are run with compiled Angular and then the msie is not defined.
2014-01-06 19:08:05 -08:00
Andrew C. Greenberg 7e916455b3 fix(ngMock window.inject): Remove Error 'stack' property changes
Recent browsers, particularly PhantomJS 1.9.2 and Safari 7.0
treat the stack property as non-configurable and unwritable.

Because window.inject captures the stack at the time of the inject,
and attempts to insert it into a captured throw from the injected
function by modifying e.stack, a meaningless error message and
stack is thrown instead.

This commit inserts two tests exposing the problem, and implements
a proposed solution that builds a new error-like object that mimicks
the old Error object, but with the additional stack information, and
captures the toString function from the Error object prototype.  This
appears to work for the browsers suppoerted here.
2014-01-06 17:47:06 -08:00
Ben Wiklund cdc4d485a6 refactor(input): wrapped validation logic in helper function
Closes #5643
2014-01-06 17:35:13 -08:00
Gias Kay Lee c894470d41 docs($compile): fix a typo
Closes #5639
2014-01-06 17:35:13 -08:00
Jay Goldman 1b0718bf89 docs(tutorial/step-12): replaced a missing apostrophe and fixed grammar errors
Fixed a missing apostrophe and some grammar in the Animating 'ngClass' with JavaScript section
2014-01-06 20:06:27 -05:00
jesse 53fd24ffcb docs(form): changed capitalization in CSS classes section
In order to improve readability from "Is set" (confused on my screen as 'Ls set') updated the
capitalization describing the setting of 4 CSS classes.

Closes #5642
2014-01-06 16:44:52 -08:00
Ben Wiklund eb90672aae chore(inputSpec): fixed typo 2014-01-06 16:37:47 -08:00
Roy Ling 28cfd96fdc docs(forms): show directive name instead of link path 2014-01-06 16:34:49 -08:00
Tyler McGinnis 99d5defb1a docs(guide/i18n): fix a typo
Closes #5651
2014-01-06 16:11:53 -08:00
Tobias Bosch efbc242875 chore(build): bugfixes to build scripts on Jenkins 2014-01-06 15:48:30 -08:00
Vojta Jina d4d58f287f docs(tutorial): do not recommend global install of Karma
Closes #5498
2014-01-06 14:48:50 -08:00
Tobias Bosch dc89db33df chore(build): bugfixes to build scripts on Jenkins. 2014-01-06 14:11:44 -08:00
Tobias Bosch 5dc27959d5 chore(build): refactor build scripts in prepare/publish phase
Refactored all scripts so that they are divided into a `prepare`
and a `publish` phase. By this we can build, test, tag, commit
everything first. Only if all of this is ok we start pushing
to Github. By this we keep Github consistent even in error cases.

Extracted include script `/scripts/utils.inc`:
- parse and validate named arguments in the style
  `--name=value`
- proxy git command and deactivate `git push` based on
  command option `--git_push_dry_run=true`
  (will be inherited to child scripts)
- enable/disable bash debug mode by command option
  `--verbose=true`
- dispatch to functions based on command option
  `--action=...`
- helper functions for dealing with json files
2014-01-06 12:27:54 -08:00
Vojta Jina 4c21355940 chore: strict deps Karma and plugins
So that we have a better control when updating Karma.
2014-01-06 11:27:19 -08:00
Matias Niemelä 6f6cb5c8d8 chore(docs): remove uppercase heading styling
Closes #5593
2014-01-06 10:22:16 -05:00
Chris Chua 821ed310a7 refactor(animate): remove duplicate line 2014-01-06 00:07:44 -05:00
Igor Minar a7aa4cc0a9 revert: fix(closure): add Closure externs for angular.$q.Promise.finally
This reverts commit caeb740265.

The commit breaks Google apps because most don't use closure compiler
with the ES5 mode flag on. We are investigating a solution...
2014-01-05 01:19:35 -08:00
RoyLING e0ce9ed36d refactor(filterFilter): simplify code by a ternary op instead of if-else
- use only one IIFE and a ternary op in it, instead of invoking separate IIFEs in if-else
(this also completely fixed the same issue closed by PR #3597)
- also add a spec to verify usage of '$' property in expression object (e.g. `{$: 'a'}`)

Closes #5637
2014-01-05 00:36:04 -08:00
Daniel Aden caeb740265 fix(closure): add Closure externs for angular.$q.Promise.finally
Closes #4757
2014-01-05 00:27:38 -08:00
Kenneth Lynne 1bb33cccbe docs(rootScope): fix typo
Closes #5633
2014-01-04 20:51:58 -08:00
Igor Minar d9ed9c5ac1 docs(ng/filter/filter): make docs human readable 2014-01-04 00:14:38 -08:00
MikeMac 00cac6ed10 docs($http): makes clear $httpProvider.defaults are available at run-time
Clarifies some confusion around $http.defaults existing and able to be modified
at run-time, for when run-time services may be needed in a transformation.

Closes #5559
Closes #5630
2014-01-03 22:35:14 -08:00
Wojciech Krzystek 2e9d7cc6cb docs(ngRepeat): add info about aliasing special properties of ngRepeat
This will safe peoples' time, since ngRepeat's docs, not ngInit's, is the first
place where one would search for such info.

Closes #5622
2014-01-03 16:07:26 -08:00
Bastian Buchholz 32cc6cbb6f style($httpBackend): fix typo 2014-01-03 16:04:50 -08:00
Brian Nenninger 3b1a4fe0c8 fix($parse): fix CSP nested property evaluation, and issue that prevented its tests from failing
cspSafeGetterFn incorrectly returned undefined if any of its key parameters were undefined. This
wasn't caught by the $parse unit tests because of a timing problem where $ParseProvider was reading
the CSP flag before the tests manually set it, so the CSP property evaluation tests never ran. Add
test that verifies evaluation of nested properties of multiple lengths.

Closes #5591
Closes #5592
2014-01-03 14:33:54 -08:00
Brian Ford 9569778f2f chore(release): fix release name 2014-01-03 13:16:39 -08:00
Brian Ford 0f61316b24 chore(release): update cdn version 2014-01-03 13:09:26 -08:00
Tobias Bosch 86151b0cea chore(release): set next release name 2014-01-03 12:02:29 -08:00
Igor Minar 1b7a6c66f8 core(Scope): rename 'debugger' to 'web inspector' to avoid woes with g3 presubmits 2014-01-03 11:17:43 -08:00
chimney-sweeper 0ef76dde41 chore(release): start v1.2.8 2014-01-03 10:40:31 -08:00
chimney-sweeper c6d04b3a3d chore(release): cut v1.2.7 release 2014-01-03 10:28:30 -08:00
Matias Niemelä e31560cf6b docs(CHANGELOG): add v1.2.7 changes 2014-01-03 13:19:38 -05:00
Igor Minar 3d38fff8b4 fix($httpBackend): don't delete xhr.onreadystatechange otherwise Safari :-O 2014-01-03 09:51:05 -08:00
Matias Niemelä bc492c0fc1 fix($animate): ensure class-based animations are always skipped before structural post-digest tasks are run
Closes #5582
2014-01-03 12:14:15 -05:00
Vojta Jina 162144202c chore: set Karma version to 0.11.11
Temporary reverting Karma, as 0.11.12 is causing some problems.
2014-01-03 08:22:17 -08:00
royling 05596527ed docs($filter): fix wrong param order in doc
fix wrong param order in doc for filter comparator
doc function param for filter expression

Closes #5365
Closes #5611
2014-01-03 02:43:22 -08:00
Tiago Ribeiro 5fea3471e8 docs(\$sniffer): fix minor typo
Closes #5544
2014-01-02 23:10:38 -08:00
Gias Kay Lee 131e4014b8 fix($resource): prevent URL template from collapsing into an empty string
if url template would result in an empty string, we should make a request
to '/' instead.

Closes #5455
Closes #5493
2014-01-02 23:07:27 -08:00
Brian Ford 01c5be4681 fix(ngShow/ngHide, ngIf): functions with zero args should be truthy
Previously, expressions that were a function with one or more arguments evaluated to
true, but functions with zero arguments evaluated to false.

This behavior seems both unintentional and undesirable. This patch makes a function
truthy regardless of its number of arguments.

Closes #5414
2014-01-02 22:59:43 -08:00
Igor Minar fd9a03e147 fix(httpBackend): fix 'type mismatch' error on IE8 after each request 2014-01-02 22:47:39 -08:00
Igor Minar 6c17d02bc4 fix($httpBackend): use ActiveX XHR when making PATCH requests on IE8
IE8's native XHR doesn't support PATCH requests, but the ActiveX one does.

I'm also removing the noxhr error doc because nobody will ever get that error.

Closes #2518
Closes #5043
2014-01-02 22:04:32 -08:00
Drew Perttula 6a6f71f238 docs(error/ngRepeat/dupes): fix typo
Closes #5610
2014-01-02 21:34:34 -08:00
Sebastian K cf686285c2 fix($location): $location.path() behaviour when $locationChangeStart is triggered by the browser
Fixed inconsistency in $location.path() behaviour on the $locationChangeStart event when using
back/forward buttons in the browser or manually changing the url in the address bar.
$location.path() now returns the target url in these cases.

Closes #4989
Closes #5089
Closes #5118
Closes #5580
2014-01-02 21:30:25 -08:00
Igor Minar 7dfedb732d style($browser): remove ws, fix typo 2014-01-02 21:30:00 -08:00
Caitlin Potter 760f2fb731 fix($browser): remove base href domain when url begins with '//'
This change prevents an incorrect appBase url from being calculated when the
<base> href's domain begins with '//'.

Closes #5606
2014-01-02 16:36:31 -08:00
Gias Kay Lee c9705b7556 fix(ngRepeat): allow for more flexible coding style in ngRepeat expression
With this change it's possible to split the ng-repeat expression into multiple
lines at any point in the expression where white-space is expected.

Closes #5537
Closes #5598
2014-01-02 16:14:16 -08:00
David Burrows 53ec33f07f docs($compile): fix typo
Closes #5599
2014-01-02 16:08:51 -08:00
Igor Minar 884ef0dbcd fix(Scope): don't let watch deregistration mess up the dirty-checking digest loop
Closes #5525
2014-01-02 15:28:56 -08:00
Igor Minar 010413f90a test(rootScope): reorganize $watch deregistration specs into a describe 2014-01-02 15:28:56 -08:00
Tobias Bosch 4f57236614 fix($httpBackend): Ignore multiple calls to onreadystatechange with readyState=4
On mobile webkit `onreadystatechange` might by called multiple times
with `readyState===4`  caused by xhrs that are resolved while the app is
in the background.

 Fixes #5426.
2014-01-02 14:37:48 -08:00
Olivier Louvignes 50bf029625 fix(animate): remove trailing s 2014-01-02 11:00:31 -05:00
Igor Minar eff52ad877 docs: moar analytics for all md files 2014-01-01 20:51:45 -08:00
Igor Minar e9ee492d35 docs(README): add analytics 2014-01-01 20:41:55 -08:00
Igor Minar e415e916e8 test(compileSpec): fix broken build on FF
FF 26.0 now throws:

"TypeError: NodeList doesn't have an indexed property setter."

when we try to assign to `childNodes[1]`, since this test still works properly
on Chrome and the issue being tested is not a cross-browser issues, I'm
just making the patchability check more robust instead of trying to figure
out how to make this test fully pass on FF.
2013-12-31 01:39:19 -08:00
Igor Minar 07084e1c8b test(injector): add missing test for #5577
Add a missing test for fix that was merged via #5577
2013-12-31 01:24:41 -08:00
Matt Ginzton 186a591228 fix($injector): remove INSTANTIATING entry when done
getService flags services as INSTANTIATING while it calls their
provider factory, in order to detect circular dependencies. If
the service is instantiated correctly, the INSTANTIATING flag is
overwritten with the actual service. However, if the service is
not instantiated correctly, the INSTANTIATING flag should still
be removed, or all further requests for this service will be
mis-detected as a circular dependency.

Closes #4361
Closes #5577
2013-12-31 01:17:43 -08:00
Igor Minar a80049fd0a fix(input): use apply on change event only when one isn't already in progress
Closes #5293
2013-12-31 00:41:15 -08:00
Igor Minar d158dd131e chore(release.sh): push both the release commit and tag 2013-12-30 16:58:28 -08:00
Michał Gołębiowski 1147f21999 fix(input): prevent double $digest when using jQuery trigger.
If an event was performed natively, jQuery sets the isTrigger property.
When triggering event manually, the field is not present. Manually
triggered events are performed synchronously which causes the "$digest
already in progress" error.

Closes #5293
2013-12-30 15:09:49 -08:00
kimwz bddd46c8ec fix($location): re-assign history after BFCache back on Android browser
Closes #5425
2013-12-30 14:58:04 -08:00
Karl Seamon 80e7a45584 perf(Scope): limit propagation of $broadcast to scopes that have listeners for the event
Update $on and $destroy to maintain a count of event keys registered for each scope and its children.
$broadcast will not descend past a node that has a count of 0/undefined for the $broadcasted event key.

Closes #5341
Closes #5371
2013-12-27 23:31:00 -08:00
Caitlin Potter 498365f219 fix(ngRoute): instantiate controller when template is empty
Before this change, $route controllers are not instantiated if the template is falsy, which includes
the empty string. This change tests if the template is not undefined, rather than just falsy, in
order to ensure that templates are instantiated even when the template is empty, which people may
have some reason to do.

This "bug" was reported in http://robb.weblaws.org/2013/06/21/angularjs-vs-emberjs/, as a "gotcha"
for AngularJS / ngRoute.

Closes #5550
2013-12-27 22:45:46 -08:00
Brady Isom 056c849352 fix($sanitize): consider size attribute as valid/allowed attribute
The "size" attribute gets set on <font> elements when using HTML5 rich
text editors, or elements with the contenteditable attribute, that rely
on the 'fontSize' command (execCommand).

Closes #5522
2013-12-27 16:22:35 -08:00
Vojta Jina 7d6e5a2d01 chore: update Karma and SauceLabs launcher
This should improve stability as it contains capture timeout (if a browser does not capture in a given timeout it gets killed) and retry (if a browser fails to start, Karma will try n times before failing).
2013-12-23 17:54:05 -08:00
mkolodny d1c4766d14 docs(guide/forms): update example
Right now, non-integers such as 'aawefwae' are valid.
This ensures that only integers are valid. Hopefully that makes the example more powerful.

Closes #5501
2013-12-20 21:22:15 -08:00
mkolodny 98473835a2 docs(guide/forms): code style changes for an example
Closes #5499
2013-12-20 21:21:18 -08:00
sanfords 870232bd05 style($http): fix a semi-colon 2013-12-20 16:23:06 -08:00
Vojta Jina c31df32ca0 chore(release): update cdn version 2013-12-20 10:29:03 -08:00
Klaus Weiss df2b88e230 docs(guide): fix typo
Closes #5481
2013-12-19 16:12:24 -08:00
Brian Ford 83451d552e chore(release): add codename for 1.2.7 2013-12-19 16:11:36 -08:00
chimney-sweeper af7203e0b8 chore(release): start v1.2.7 2013-12-19 16:02:57 -08:00
chimney-sweeper 98ee3719f9 chore(release): cut v1.2.6 release 2013-12-19 15:50:07 -08:00
Igor Minar 94b5f2dadb chore(release): improve the release script 2013-12-19 15:47:26 -08:00
Brian Ford fe7decd1b0 docs(CHANGELOG): add v1.2.6 changes 2013-12-19 13:55:10 -08:00
Matias Niemelä cef084ade9 feat(ngAnimate): provide configuration support to match specific className values to trigger animations
Closes #5357
Closes #5283
2013-12-19 16:37:29 -05:00
Matias Niemelä 937caab647 feat(jqLite): provide support for element.one() 2013-12-19 14:39:04 -05:00
Matias Niemelä 3fc8017119 style(animateSpec): ensure spacing between specs and describes is consistent 2013-12-19 12:02:00 -05:00
Matias Niemelä 54637a335f fix($animate): use a scheduled timeout in favor of a fallback property to close transitions
With ngAnimate, CSS transitions, that are not properlty triggered, are forceably closed off
by appling a fallback property. The fallback property approach works, however, its styling
itself may effect CSS inheritance or cause the element to render improperly. Therefore, its
best to stick to using a scheduled timeout to run sometime after the highest animation time
has passed.

Closes #5255
Closes #5241
Closes #5405
2013-12-19 12:01:12 -05:00
Josh Kurz 277a5ea05d docs($interval): remind the developer to destroy their intervals
It is essential that users of `$interval` destroy the interval when they are finished.
Otherwise you can get memory leaks.
Often `$intervals` are used in directives or controllers and developers don't think
about what happens when the component is destroyed.
If a directive/controller scope is destroyed, then the $interval should be destroyed as well.
This could cause some issues with developers who assume that the interval will be cleared
for them when the scope is destroyed.

Closes #5377

I believe that the library could/should handle this as well, but thats another issue.
2013-12-19 13:46:30 +00:00
snicolai 9865a7c0ad docs(ngCloak): style name is ng-cloak, not ngCloak
Closes #5374
2013-12-19 13:32:19 +00:00
Mark Jones efba4731e4 docs(booleanAttrs): add @priority to all the boolean directives
Closes #5361
2013-12-19 13:29:19 +00:00
Tony Cronin a965984733 docs(tutorial/step-4): fix typo
Closes #5356
2013-12-19 13:24:19 +00:00
mkolodny 14d3e559d4 docs($injector): use correct spacing convention for CoffeeScript functions
This convention is exhibited by http://coffeescript.org/ and https://github.com/polarmobile/coffeescript-style-guide#functions.

Closes #5354
2013-12-19 13:05:15 +00:00
James Watling 3d156a76e3 docs(ngEventDirs): adding quick examples for new events
Closes #5338
2013-12-19 12:57:33 +00:00
Alexandre Potvin Latreille c7a1d1ab0b fix($compile): remove invalid IE exceptional case for href
It appears that this exceptional case was only valid for IE<8 and that for IE>=8 it
was actually causing a bug with the `ng-href-attr` directive on `<a>` elements.

Closes #5479
2013-12-19 12:22:58 +00:00
Caitlin Potter 26d43cacdc fix($parse): return 'undefined' if a middle key's value is null
Prior to this fix, $parse/$eval would return 'null' if a middle key in
an expression's value is null, when it should be expected to be undefined.

This patch tries to remedy this by returning undefined for middle values in
expressions, when fetching a child of that null value.

For example:

```js
// Given the following object:
$scope.a = {
  b: null
};

// $scope.$eval('a.b.c') returns undefined, whereas previously it would return null
```

Closes #5480
2013-12-19 00:59:22 -08:00
Tobias Bosch 4f5758e666 fix($log): should work in IE8
In IE8, reading `console.log.apply` throws an error.
Catching this errow now.

Fixes #5400. Fixes #5147.
2013-12-18 21:44:00 -08:00
Tobias Bosch 274a6734ef fix(forEach): allow looping over result of querySelectorAll in IE8
In IE8 the result object
of calling `node.querySelectorAll` does not have a `hasOwnPropery`
function. However, it should be usable with `forEach`.

Related to #5400.
2013-12-18 21:44:00 -08:00
Zachary Babtkis f0e3dfd008 docs(guide): fixed *off typo in angular.injector example comment
Closes #5441
2013-12-18 20:57:20 -08:00
Caitlin Potter bc3ff2cecd fix($location): parse xlink:href for SVGAElements
Before this fix, the xlink:href property of an SVG <a> element could not be parsed
on click, as the property is an SVGAnimatedString rather than a DOMString.

This patch parses the xlink:href's animVal into a DOMString in order to prevent
an `Object #<SVGAnimatedString> has no method 'indexOf'` exception from being thrown,
and also to update the location if necessary as expected.

Closes #5472
Closes #5198
Closes #5199
Closes #4098
Closes #1420
2013-12-18 17:16:39 -08:00
oojerryoo 8f329ffb82 fix(closure): add type definition for Scope#$watchCollection
Closes #5475
2013-12-18 16:35:54 -08:00
Karl Seamon 864b2596b2 perf($parse) use a faster path when the number of path parts is low
Use a faster path when the number of path tokens is low (ie the common case).
This results in a better than 19x improvement in the time spent in $parse and
produces output that is about the same speed in chrome and substantially faster
in firefox.
http://jsperf.com/angularjs-parse-getter/6

Closes #5359
2013-12-18 15:44:15 -08:00
Karl Seamon f3a796e522 perf(compile): add class 'ng-scope' before cloning and other micro-optimizations
Add class ng-scope to dom nodes during directive compile rather than link.
Optimize handling of nodeLists.
This results in a savings of about 130ms during the startup of a product within Google.

Closes #5471
2013-12-18 15:31:49 -08:00
oweitz 09f8962df2 docs($resource): fix typo in server response example
The server is supposed to return the same card number as in the client request.
Adjust server response example to the value given in the client request.

Closes #5352
2013-12-18 21:22:21 +00:00
justmiaotou a13c4ba770 docs(tutorial/step-5): fix typo
Closes #5347
2013-12-18 21:15:38 +00:00
Jason Farnsworth 040e743b39 docs(ngInit): fix typo
Closes #5343
2013-12-18 21:14:46 +00:00
Pete Bacon Darwin bf816d3ade docs(guide/directive): improve access to isolate scope information
Closes #5329
2013-12-18 21:14:12 +00:00
Jesse Browne 74b4ab8867 docs(tutorial/step_11): fix indenting in an example
Closes #5322
2013-12-18 21:14:11 +00:00
Kurt Funai 6e2359caa0 docs(contribute): you may need sudo to install globally on unix systems
Closes #5318
2013-12-18 21:14:11 +00:00
Ziang Song 41534816a4 docs(error/noregexp): fix link to ng-pattern
Closes #5313
2013-12-18 21:14:10 +00:00
Kindy Lin 30252a0504 docs($compile): fix param name and improve example variable name
Closes #5310
2013-12-18 21:14:09 +00:00
Chia-liang Kao 3dc18037e8 fix(input): do not hold input for composition on android
Workaround for chrome for android until #2129 is ready.

Closes #5308, #5323
2013-12-18 12:28:07 -08:00
Chia-liang Kao 57d50582aa chore($sniffer): make android variable public 2013-12-18 11:49:39 -08:00
Pete Bacon Darwin 73c66715c9 docs(bootstrap-prettify): fix $timeout issues and update related docs
End 2 end tests wait for all `$timeout`s to be run before completing the test.
This was problematic where we were using timeouts that restarted themselves because
there would never be a point when all timeouts had completed, causing the tests to hang.

To fix this $timeout had been monkey-patched but this caused other issue itself.

Now that we have $interval we don't need to use $timeout handlers that re-trigger the $timeout
so we can ditch the monkey-patch.

This commit tidies up any examples that are using this approach and changes them to use $interval
instead.

Closes #5232
2013-12-17 22:53:28 +00:00
Karl Seamon cb29632a58 perf: use faster check for $$ prefix
Use two calls to charAt instead of substr to detect a $$prefix in the shallowCopy functions.
This makes shallowCopy 25-50% faster (depending on which browser is used).
http://jsperf.com/angular-shallow-copy

Closes #5457
2013-12-17 11:43:57 -08:00
Caitlin Potter 5c97731a22 fix(select): invalidate when 'multiple, required and model is []`
When `multiple` attribute is set on a `<select>` control and the model value is an empty array,
we should invalidate the control.  Previously, this directive was using incorrect logic for
determining if the model was empty.

Closes #5337
2013-12-17 13:10:40 +00:00
Stéphane Reynaud b2e472e7a2 docs(tutorial/step-11): change "last" to "next"
Since step 12 was added, step 11 is not the last. So this is not the last improvement.

Closes #5306
2013-12-17 12:30:59 +00:00
Pete Bacon Darwin 6ac773f350 docs(): fix jshint issues 2013-12-17 12:29:22 +00:00
unclejustin 3174f73336 docs($resource): add example for a custom PUT request
Closes #5302
2013-12-17 12:20:25 +00:00
Grigoriy Beziuk 3c62e4244e docs(tutorial/step-0): fix twitter bootstrap link
The url of twitter bootstrap was outdated.

Closes #5290
2013-12-17 12:15:52 +00:00
Oliver Schmidt c432999572 docs(ng): fix typo and line lengths
Closes #5288
2013-12-17 12:12:14 +00:00
Sharon DiOrio f8d319c11a docs(css): improve definition table style
Text in definition tables are now aligned to the top of the cell. These are used in
the API index page and makes it cleared what headings match what content.

Closes #5286
2013-12-17 12:09:08 +00:00
Pete Bacon Darwin 4f72433392 docs(ngIf): remove invalid comment from CSS
We cannot use valid /* ... */ CSS comments in examples because they break the parsing
of the ngdoc comments.  We can't use inline // comments because these are not valid in
CSS.

We could use the //!annotate extension to the ngdoc parser but this does not seem to be
working.  It is best to simply remove this line.

Closes #5234
2013-12-17 11:59:29 +00:00
Chris Chua 2f91cfd0d2 fix(jqLite): support unbind self within handler
If an event handler unbinds itself, the next event handler on the same
event and element doesn't get executed.

This works fine in jQuery, and since jqLite doesn't support .one, this
might be a common use case.
2013-12-16 16:39:13 -08:00
Vojta Jina d5c5e2b584 chore: run docs unit test only once
Before we would run them twice on Travis. I don't think it should be part of ci-check task.
2013-12-16 13:37:09 -08:00
Rhys Brett-bowen cbb3ce2c30 fix(ngRepeat): allow multiline expressions
allow and pass through new line characters when checking passed in expression

Closes #5000
2013-12-16 10:37:18 -08:00
Tobias Bosch 45af02de04 chore(build): simplify release scripts 2013-12-16 09:49:48 -08:00
Tobias Bosch 6144df52af chore(build): correct updating bower versions 2013-12-16 09:47:23 -08:00
Tobias Bosch b0474cb984 chore(build): remove stale build files 2013-12-13 21:49:22 -08:00
Tobias Bosch 9a4c9e6487 chore(build): correct and refactor release script 2013-12-13 21:49:05 -08:00
Tobias Bosch 11fff8fa0d chore(build): fix fetching for code.angularjs.org 2013-12-13 14:36:24 -08:00
Tobias Bosch da8ab2f928 chore(build): fix release.sh 2013-12-13 14:33:43 -08:00
Tobias Bosch 6d01384a55 chore(build): fixes to release.sh 2013-12-13 14:13:23 -08:00
Tobias Bosch 109ffac975 chore(build): set execute flag on scripts 2013-12-13 13:18:22 -08:00
Tobias Bosch 8c10db3847 chore(build): automate cutting a release, publishing to bower and to code.angular.js 2013-12-13 12:51:13 -08:00
Vojta Jina 03088d6010 docs: fix a broken link 2013-12-13 12:28:02 -08:00
Vojta Jina 18e0768a2b docs: use q-io instead of deprecated q-fs
This recursive process.nextTick error[1] was probably coming from q-fs,
which is not actively maintained. This updates to q-io/fs instead.


[1]: https://travis-ci.org/angular/angular.js/jobs/15391590
2013-12-13 12:23:53 -08:00
Vojta Jina ed4a1fddce chore(travis): force the latest version of selenium
This might solve some flakiness on SL. At least Santi said that ;-)
2013-12-13 12:23:53 -08:00
Jeff Cross cfde6f507c chore(release): start 1.2.6 taco-salsafication iteration 2013-12-13 11:53:09 -08:00
Jeff Cross 3468ad1b61 chore(release): cut 1.2.5 singularity-expansion release 2013-12-13 10:52:13 -08:00
Jeff Cross e9c79cad43 docs(CHANGELOG): add v1.2.5 changes 2013-12-13 10:44:40 -08:00
Igor Minar e455e7d878 docs(TRIAGING): add info about "needs: public api" 2013-12-13 08:53:33 -08:00
Michał Gołębiowski 3410f65e79 perf(jqLite): implement and use the empty method in place of html(‘’)
jQuery's elem.html('') is way slower than elem.empty(). As clearing
element contents happens quite often in certain scenarios, switching
to using .empty() provides a significant performance boost when using
Angular with jQuery.

Closes #4457
2013-12-13 02:07:11 -08:00
Karl Seamon f3de5b6eac perf(a): do not link when href or name exists in template
Change the a directive to link and hookup a click event only when
there is no href or name in the template element.
In a large Google app, this results in about 800 fewer registrations,
saving a small but measurable amount of time and memory.

Closes #5362
2013-12-13 00:31:25 -08:00
Karl Seamon fcd2a8131a perf($resource): use shallow copy instead of angular.copy
Replace calls to angular.copy with calls to a new function, shallowClearAndCopy.
Add calls to copy for cache access in $http in order to prevent modification of cached data.
Results in a measurable improvement to the startup time of complex apps within Google.

Closes #5300
2013-12-13 00:24:37 -08:00
Karl Seamon 62dbe85798 perf: use call and === instead of apply and == in type check functions
Updates isDate et al to use call instead of apply and === instead of ==.
The change to call brings minor performance improvement and === is just
better practice than ==.
http://jsperf.com/call-vs-apply-tostring

Closes #5295
2013-12-13 00:22:47 -08:00
Brian Atkinson 1d5e18b062 fix(closure): add missing FormController extern definitions
Closes #5303
2013-12-13 00:14:31 -08:00
Igor Minar a0ed371389 style($injector): remove ws 2013-12-12 23:51:45 -08:00
Ben Wiklund 05e4fd3488 perf($injector): remove invoke optimization that doesn't work
Closes #5388
2013-12-12 23:49:03 -08:00
Tobias Bosch 30a8b7d0b5 fix(ngInclude): Add template to DOM before linking other directives
The template needs to be added to the DOM before
other directives at the same element as `ngInclude` are linked.

Fixes #5247.
2013-12-12 17:18:44 -08:00
Tobias Bosch f8944efe70 fix(ngView): Add template to DOM before linking other directives
The template needs to be added to the DOM before
other directives at the same element as `ngView` are linked.

Related to #5247.
2013-12-12 17:18:44 -08:00
Tobias Bosch 43072e3812 fix($compile): Allow literals in isolate scope references
When a component uses an isolate scope reference
and the the component is used with an object literal
a new object is created on every evaluation.
Therefore the compiler needs to compare
the values of the parent and the isolate scope
using object equality and not object reference
equality.

Fixes #5296.
2013-12-12 16:30:31 -08:00
Pete Bacon Darwin 9396d55414 docs(ngSwitch): clarify that ngSwitch matches against string literals
Closes #5285
2013-12-12 11:42:49 +00:00
mbrookes 82e97cf53e docs(guide/expression): remove misplaced comma
Closes #5280
2013-12-12 11:25:41 +00:00
Jürgen Walter cf2a7614a4 docs(tutorial/step-07): update path to pages in e2e scenarios
The url paths in the tutorial are not in line with the actual tutorial code

Closes #5264
2013-12-12 11:22:31 +00:00
Vlad GURDIGA 9e538e7c31 docs(ng.$rootScope.Scope): fix API links
Also added a note to the Writing AngularJS Documentation:
https://github.com/angular/angular.js/wiki/Writing-AngularJS-Documentation/d0c715ef89

Closes #5261
2013-12-12 11:19:16 +00:00
Mattias Holmlund 4ac21ac039 docs(error/transclude/orphan): fix spelling mistakes
Closes #5259
2013-12-12 11:15:31 +00:00
Karl Seamon f69dc16241 fix(angular-mocks): use copy of mock data in $httpBackend
Copy mock data returned from the mock $httpBackend.
This prevents modifications to the response from affecting future responses.
Previously, this misbehavior was being mitigated by the deep copy in $resource, but that no longer exists.
2013-12-11 15:18:45 -08:00
Brian Ford f1a8d419d5 chore(scripts): fix bower script to pull from master before updating 2013-12-11 14:35:23 -08:00
Vojta Jina 8864e54f1f chore(scripts): refactor travis scripts
Refactoring so that it's easier to use both SL/BS just depending on a global switch.
2013-12-11 10:12:18 -08:00
Vojta Jina dc4df93177 chore(travis): run two jobs
Instead of parallelization on a single Travis VM, we use two VMs.
- output is nicer (we don't have to buffer e2e tests and then show it at the end)
- you can easily see faster the result of unit tests (as it's basically a separate build)

We should also make sure we only do the necesary stuff (for install we don't need to do `grunt
package` for unit tests, we only need to generate the docs for e2e tests.
2013-12-11 10:02:14 -08:00
Tobias Bosch 043190f397 docs(TRIAGING): Add Type:Perf label 2013-12-09 17:54:08 -08:00
Tobias Bosch f4d850e168 docs(TRIAGING): Labels cla yes/no are automatically set
The labels are set by a script and
should not be set manually any more.
2013-12-09 17:30:43 -08:00
Andy Ferra 8ec2743ca1 docs(design): guide index formatting
Just my first pass at a more readable format of the guide index.

Note: the styles apply to all content in the docs, not just the guide
index. This is intentional and I feel that the result is positive.
2013-12-09 16:32:10 -08:00
Vojta Jina ecbee8147b style($route): make jshint happy
Fix the broken build and earn a late (french spelling).
2013-12-09 14:57:49 -08:00
miknsh5 f8c6ee3df5 docs(input): remove redundant closing span tag
Closes #5257
2013-12-09 20:52:00 +00:00
hambyiii fe84f7bef8 docs($route): clarify examples of route parameters
Putting route parameter examples in braces was misleading newcomers.

Closes #5243
2013-12-09 20:48:50 +00:00
Robin Böhm d653607162 docs($q): correct typo in the 'Differences Q/$q' section
Closes #5230
2013-12-09 20:46:21 +00:00
gdi2290 082fe180ec docs(contribute) add platform agnostic git install link
Closes #5216
2013-12-09 20:27:08 +00:00
Shane M. Pelletier d3491083a5 docs(tutorial): enlarge clickable area of tutorial nav buttons
Change position of <a> and <li> tags in tutorial nav buttons
partial. This allows the full area of the button to be clicked
rather than just the text.

Closes #5074
Closes #5209
2013-12-09 20:24:54 +00:00
Wesley Cho c3d6ca97e1 docs(guide/forms): clarify how NgModelController can be added to scope
Closes #5200
2013-12-09 20:14:45 +00:00
Matias Niemelä a14266e464 chore(CHANGELOG): introduce perf() section for performance-related commits
Instead of using fix() or chore() when labelling a commit which improves
speed or performance use perf(). Perf commits will be listed in the
CHANGELOG under "Performance Improvements".

For example:
perf($animate): cache all getComputedStyle operations to reduce additional reflows
2013-12-09 11:52:28 -05:00
Joscha Feth b4d44e1298 docs($injector): add example on how to use the element.injector
Closes #5188
2013-12-09 16:32:09 +00:00
Matias Niemelä ca116c35a6 chore(release): start 1.2.5 singularity-expansion iteration 2013-12-06 14:51:45 -05:00
144 changed files with 4224 additions and 1282 deletions
+7 -5
View File
@@ -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
+243
View File
@@ -1,3 +1,243 @@
<a name="1.2.9"></a>
# 1.2.9 enchanted-articulacy (2014-01-15)
## Bug Fixes
- **$animate:**
- ensure the final closing timeout respects staggering animations
([ed53100a](https://github.com/angular/angular.js/commit/ed53100a0dbc9119d5dfc8b7248845d4f6989df2))
- prevent race conditions for class-based animations when animating on the same CSS class
([4aa9df7a](https://github.com/angular/angular.js/commit/4aa9df7a7ae533531dfae1e3eb9646245d6b5ff4),
[#5588](https://github.com/angular/angular.js/issues/5588))
- correctly detect and handle CSS transition changes during class addition and removal
([7d5d62da](https://github.com/angular/angular.js/commit/7d5d62dafe11620082c79da35958f8014eeb008c))
- avoid accidentally matching substrings when resolving the presence of className tokens
([524650a4](https://github.com/angular/angular.js/commit/524650a40ed20f01571e5466475749874ee67288))
- **$http:** ensure default headers PUT and POST are different objects
([e1cfb195](https://github.com/angular/angular.js/commit/e1cfb1957feaf89408bccf48fae6f529e57a82fe),
[#5742](https://github.com/angular/angular.js/issues/5742), [#5747](https://github.com/angular/angular.js/issues/5747), [#5764](https://github.com/angular/angular.js/issues/5764))
- **$rootScope:** prevent infinite $digest by checking if asyncQueue is empty when decrementing ttl
([2cd09c9f](https://github.com/angular/angular.js/commit/2cd09c9f0e7766bcd191662841b7b1ffc3b6dc3f),
[#2622](https://github.com/angular/angular.js/issues/2622))
- **$route:** update current route upon $route instantiation
([2b344dbd](https://github.com/angular/angular.js/commit/2b344dbd20777fb1283b3a5bcf35a6ae8d09469d),
[#4957](https://github.com/angular/angular.js/issues/4957))
## Features
- **$animate:**
- provide support for DOM callbacks
([dde1b294](https://github.com/angular/angular.js/commit/dde1b2949727c297e214c99960141bfad438d7a4))
- use requestAnimationFrame instead of a timeout to issue a reflow
([4ae3184c](https://github.com/angular/angular.js/commit/4ae3184c5915aac9aa00889aa2153c8e84c14966),
[#4278](https://github.com/angular/angular.js/issues/4278), [#4225](https://github.com/angular/angular.js/issues/4225))
<a name="1.2.8"></a>
# 1.2.8 interdimensional-cartography (2014-01-10)
## Bug Fixes
- **$http:**
- return responseText on IE8 for requests with responseType set
([a9cccbe1](https://github.com/angular/angular.js/commit/a9cccbe14f1bd9048f5dab4443f58c804d4259a1),
[#4464](https://github.com/angular/angular.js/issues/4464), [#4738](https://github.com/angular/angular.js/issues/4738), [#5636](https://github.com/angular/angular.js/issues/5636))
- Allow status code 0 from any protocol
([28fc80bb](https://github.com/angular/angular.js/commit/28fc80bba0107075ab371fd0a7634a38891626b2),
[#1356](https://github.com/angular/angular.js/issues/1356), [#5547](https://github.com/angular/angular.js/issues/5547))
- cancelled JSONP requests will not print error in the console
([95e1b2d6](https://github.com/angular/angular.js/commit/95e1b2d6121b4e26cf87dcf6746a7b8cb4c25e7f),
[#5615](https://github.com/angular/angular.js/issues/5615), [#5616](https://github.com/angular/angular.js/issues/5616))
- **$location:** return '/' for root path in hashbang mode
([63cd873f](https://github.com/angular/angular.js/commit/63cd873fef3207deef30c7a7ed66f4b8f647dc12),
[#5650](https://github.com/angular/angular.js/issues/5650), [#5712](https://github.com/angular/angular.js/issues/5712))
- **$parse:** fix CSP nested property evaluation, and issue that prevented its tests from failing
([3b1a4fe0](https://github.com/angular/angular.js/commit/3b1a4fe0c83c7898ecd7261ab4213998ee7be0ec),
[#5591](https://github.com/angular/angular.js/issues/5591), [#5592](https://github.com/angular/angular.js/issues/5592))
- **closure:** add Closure externs for angular.$q.Promise.finally
([caeb7402](https://github.com/angular/angular.js/commit/caeb7402651702cd13df2f1594e9827439a8b760),
[#4757](https://github.com/angular/angular.js/issues/4757))
- **ngMock window.inject:** Remove Error 'stack' property changes
([7e916455](https://github.com/angular/angular.js/commit/7e916455b36dc9ca4d4afc1e44cade90006d00e3))
## Features
- **select:** allow multiline ng-options
([43a2f3d0](https://github.com/angular/angular.js/commit/43a2f3d0bf435e3626cd679caff4281cfb3415bd),
[#5602](https://github.com/angular/angular.js/issues/5602))
<a name="1.2.7"></a>
# 1.2.7 emoji-clairvoyance (2014-01-03)
## Bug Fixes
- **$animate:**
- ensue class-based animations are always skipped before structural post-digest tasks are run
([bc492c0f](https://github.com/angular/angular.js/commit/bc492c0fc17257ddf2bc5964e205379aa766b3d8),
[#5582](https://github.com/angular/angular.js/issues/5582))
- remove trailing `s` from computed transition duration styles
([50bf0296](https://github.com/angular/angular.js/commit/50bf029625d603fc652f0f413e709f43803743db))
- **$http:**
([3d38fff8](https://github.com/angular/angular.js/commit/3d38fff8b4ea2fd60fadef2028ea4dcddfccb1a4))
- use ActiveX XHR when making PATCH requests on IE8
([6c17d02b](https://github.com/angular/angular.js/commit/6c17d02bc4cc02f478775d62e1f9f77da9da82ad),
[#2518](https://github.com/angular/angular.js/issues/2518), [#5043](https://github.com/angular/angular.js/issues/5043))
- fix 'type mismatch' error on IE8 after each request
([fd9a03e1](https://github.com/angular/angular.js/commit/fd9a03e147aac7e952c6dda1f381fd4662276ba2))
- Ignore multiple calls to onreadystatechange with readyState=4
([4f572366](https://github.com/angular/angular.js/commit/4f57236614415eea919221ea5f99c4d8689b3267),
[#5426](https://github.com/angular/angular.js/issues/5426))
- **$injector:** remove the `INSTANTIATING` flag properly when done
([186a5912](https://github.com/angular/angular.js/commit/186a5912288acfff0ee59dae29af83c37c987921),
[#4361](https://github.com/angular/angular.js/issues/4361), [#5577](https://github.com/angular/angular.js/issues/5577))
- **$location:**
- remove base href domain if the URL begins with '//'
([760f2fb7](https://github.com/angular/angular.js/commit/760f2fb73178e56c37397b3c5876f7dac96f0455),
[#5606](https://github.com/angular/angular.js/issues/5606))
- fix $location.path() behaviour when $locationChangeStart is triggered by the browser
([cf686285](https://github.com/angular/angular.js/commit/cf686285c22d528440e173fdb65ad1052d96df3c),
[#4989](https://github.com/angular/angular.js/issues/4989), [#5089](https://github.com/angular/angular.js/issues/5089), [#5118](https://github.com/angular/angular.js/issues/5118), [#5580](https://github.com/angular/angular.js/issues/5580))
- re-assign history after BFCache back on Android browser
([bddd46c8](https://github.com/angular/angular.js/commit/bddd46c8ecf49cfe6c999cd6b4a69b7d7e1f9a33),
[#5425](https://github.com/angular/angular.js/issues/5425))
- **$resource:** prevent URL template from collapsing into an empty string
([131e4014](https://github.com/angular/angular.js/commit/131e4014b831ac81b7979c4523da81ebc5861c70),
[#5455](https://github.com/angular/angular.js/issues/5455), [#5493](https://github.com/angular/angular.js/issues/5493))
- **$sanitize:** consider the `size` attribute as a valid/allowed attribute
([056c8493](https://github.com/angular/angular.js/commit/056c8493521988dbb330c6636135b505737da918),
[#5522](https://github.com/angular/angular.js/issues/5522))
- **Scope:** don't let watch deregistration mess up the dirty-checking digest loop
([884ef0db](https://github.com/angular/angular.js/commit/884ef0dbcdfe614cedc824d079361b53e675d033),
[#5525](https://github.com/angular/angular.js/issues/5525))
- **input:**
- use apply on the change event only when one isn't already in progress
([a80049fd](https://github.com/angular/angular.js/commit/a80049fd0ac858eeeb645a4209cb2a661d0b4c33),
[#5293](https://github.com/angular/angular.js/issues/5293))
- prevent double $digest when using jQuery trigger.
([1147f219](https://github.com/angular/angular.js/commit/1147f21999edf9a434cd8d24865a6455e744d858),
[#5293](https://github.com/angular/angular.js/issues/5293))
- **ngRepeat:** allow for more flexible coding style in ngRepeat expression
([c9705b75](https://github.com/angular/angular.js/commit/c9705b755645a4bfe066243f2ba15a733c3787e1),
[#5537](https://github.com/angular/angular.js/issues/5537), [#5598](https://github.com/angular/angular.js/issues/5598))
- **ngRoute:** instantiate controller when template is empty
([498365f2](https://github.com/angular/angular.js/commit/498365f219f65d6c29bdf2f03610a4d3646009bb),
[#5550](https://github.com/angular/angular.js/issues/5550))
- **ngShow/ngHide, ngIf:** functions with zero args should be truthy
([01c5be46](https://github.com/angular/angular.js/commit/01c5be4681e34cdc5f5c461b7a618fefe8038919),
[#5414](https://github.com/angular/angular.js/issues/5414))
## Performance Improvements
- **Scope:** limit propagation of $broadcast to scopes that have listeners for the event
([80e7a455](https://github.com/angular/angular.js/commit/80e7a4558490f7ffd33d142844b9153a5ed00e86),
[#5341](https://github.com/angular/angular.js/issues/5341), [#5371](https://github.com/angular/angular.js/issues/5371))
<a name="1.2.6"></a>
# 1.2.6 taco-salsafication (2013-12-19)
## Bug Fixes
- **$animate:** use a scheduled timeout in favor of a fallback property to close transitions
([54637a33](https://github.com/angular/angular.js/commit/54637a335f885110efaa702a3bab29c77644b36c),
[#5255](https://github.com/angular/angular.js/issues/5255), [#5241](https://github.com/angular/angular.js/issues/5241), [#5405](https://github.com/angular/angular.js/issues/5405))
- **$compile:** remove invalid IE exceptional case for `href`
([c7a1d1ab](https://github.com/angular/angular.js/commit/c7a1d1ab0b663edffc1ac7b54deea847e372468d),
[#5479](https://github.com/angular/angular.js/issues/5479))
- **$location:** parse xlink:href for SVGAElements
([bc3ff2ce](https://github.com/angular/angular.js/commit/bc3ff2cecd0861766a9e8606f3cc2c582d9875df),
[#5472](https://github.com/angular/angular.js/issues/5472), [#5198](https://github.com/angular/angular.js/issues/5198), [#5199](https://github.com/angular/angular.js/issues/5199), [#4098](https://github.com/angular/angular.js/issues/4098), [#1420](https://github.com/angular/angular.js/issues/1420))
- **$log:** should work in IE8
([4f5758e6](https://github.com/angular/angular.js/commit/4f5758e6669222369889c9e789601d25ff885530),
[#5400](https://github.com/angular/angular.js/issues/5400))
- **$parse:** return `undefined` if an intermetiate property's value is `null`
([26d43cac](https://github.com/angular/angular.js/commit/26d43cacdc106765bd928d41600352198f887aef),
[#5480](https://github.com/angular/angular.js/issues/5480))
- **closure:** add type definition for `Scope#$watchCollection`
([8f329ffb](https://github.com/angular/angular.js/commit/8f329ffb829410e1fd8f86a766929134e736e3e5),
[#5475](https://github.com/angular/angular.js/issues/5475))
- **forEach:** allow looping over result of `querySelectorAll` in IE8
([274a6734](https://github.com/angular/angular.js/commit/274a6734ef1fff543cc50388a0958d1988baeb57))
- **input:** do not hold input for composition on Android
([3dc18037](https://github.com/angular/angular.js/commit/3dc18037e8db8766641a4d39f0fee96077db1fcb),
[#5308](https://github.com/angular/angular.js/issues/5308))
- **jqLite:** support unbind self within handler
([2f91cfd0](https://github.com/angular/angular.js/commit/2f91cfd0d2986899c38641100c1851b2f9d3888a))
- **ngRepeat:** allow multiline expressions
([cbb3ce2c](https://github.com/angular/angular.js/commit/cbb3ce2c309052b951d0cc87e4c6daa9c48a3dd8),
[#5000](https://github.com/angular/angular.js/issues/5000))
- **select:** invalidate when `multiple`, `required`, and model is `[]`
([5c97731a](https://github.com/angular/angular.js/commit/5c97731a22ed87d64712e673efea0e8a05eae65f),
[#5337](https://github.com/angular/angular.js/issues/5337))
## Features
- **jqLite:** provide support for `element.one()`
([937caab6](https://github.com/angular/angular.js/commit/937caab6475e53a7ea0206e992f8a52449232e78))
- **ngAnimate:** provide configuration support to match specific className values to trigger animations
([cef084ad](https://github.com/angular/angular.js/commit/cef084ade9072090259d8c679751cac3ffeaed51),
[#5357](https://github.com/angular/angular.js/issues/5357), [#5283](https://github.com/angular/angular.js/issues/5283))
## Performance Improvements
- **compile:** add class 'ng-scope' before cloning and other micro-optimizations
([f3a796e5](https://github.com/angular/angular.js/commit/f3a796e522afdbd3b640d14426edb2fbfab463c5),
[#5471](https://github.com/angular/angular.js/issues/5471))
- **$parse:** use a faster path when the number of path parts is low
([f4462319](https://github.com/angular/angular.js/commit/864b2596b246470cca9d4e223eaed720f4462319))
- use faster check for `$$` prefix
([06c5cfc7](https://github.com/angular/angular.js/commit/cb29632a5802e930262919b3db64ca4806c5cfc7))
<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)
@@ -4283,3 +4523,6 @@ with the `$route` service
[module]: http://docs-next.angularjs.org/api/angular.mock.module
[guide2.di]: http://docs-next.angularjs.org/guide/dev_guide.di
[jqLite2]: http://docs.angularjs.org/#!/api/angular.element
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/CHANGELOG.md?pixel)](https://github.com/igrigorik/ga-beacon)
+4 -1
View File
@@ -80,7 +80,7 @@ Before you submit your pull request consider the following guidelines:
```
* Create your patch, including appropriate test cases.
* Follow our Coding Rules
* Follow our [Coding Rules](#coding-rules)
* Commit your changes and create a descriptive commit message (the
commit message is used to generate release notes, please check out our
[commit message conventions](#commit-message-format) and our commit message presubmit hook
@@ -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
@@ -257,3 +258,5 @@ You can find out more detailed information about contributing in the
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[github-pr-helper]: https://chrome.google.com/webstore/detail/github-pr-helper/mokbklfnaddkkbolfldepnkfmanfhpen
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/CONTRIBUTING.md?pixel)](https://github.com/igrigorik/ga-beacon)
+19 -2
View File
@@ -4,6 +4,7 @@ var path = require('path');
module.exports = function(grunt) {
//grunt plugins
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-connect');
@@ -100,6 +101,11 @@ module.exports = function(grunt) {
},
runprotractor: {
normal: 'protractor-conf.js'
},
clean: {
build: ['build'],
tmp: ['tmp']
@@ -268,18 +274,29 @@ module.exports = function(grunt) {
write: {
versionTXT: {file: 'build/version.txt', val: NG_VERSION.full},
versionJSON: {file: 'build/version.json', val: JSON.stringify(NG_VERSION)}
},
bump: {
options: {
files: ['package.json'],
commit: false,
createTag: false,
push: false
}
}
});
//alias tasks
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:e2e']);
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:e2e', 'webdriver', 'runprotractor:normal']);
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
grunt.registerTask('test:jquery', 'Run the jQuery unit tests with Karma', ['tests:jquery']);
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['tests:modules']);
grunt.registerTask('test:docs', 'Run the doc-page tests with Karma', ['package', 'tests:docs']);
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', ['tests:jqlite', 'tests:jquery', 'tests:modules']);
grunt.registerTask('test:e2e', 'Run the end to end tests with Karma and keep a test server running in the background', ['connect:testserver', 'tests:end2end']);
// This should eventually replace test:e2e
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'runprotractor:normal']);
grunt.registerTask('test:docgen', ['jasmine_node']);
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
@@ -287,6 +304,6 @@ module.exports = function(grunt) {
grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('package-without-bower', ['clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'test:docgen']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint']);
grunt.registerTask('default', ['package']);
};
+4
View File
@@ -38,3 +38,7 @@ To execute end-to-end (e2e) tests, use:
To learn more about the grunt tasks, run `grunt --help` and also read our
[contribution guidelines](http://docs.angularjs.org/misc/contribute).
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/README.md?pixel)](https://github.com/igrigorik/ga-beacon)
+11 -3
View File
@@ -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,10 +54,10 @@ 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
1. Unassign yourself from the issue
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/TRIAGING.md?pixel)](https://github.com/igrigorik/ga-beacon)
+3 -1
View File
@@ -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);
+43 -1
View File
@@ -762,7 +762,9 @@ angular.Module.requires;
* $parent: angular.Scope,
* $root: angular.Scope,
* $watch: function(
* (string|Function), (string|Function)=, boolean=):function()
* (string|Function), (string|Function)=, boolean=):function(),
* $watchCollection: function(
* (string|Function), (string|Function)=):function()
* }}
*/
angular.Scope;
@@ -834,6 +836,13 @@ angular.Scope.$root;
*/
angular.Scope.$watch = function(exp, opt_listener, opt_objectEquality) {};
/**
* @param {string|Function} exp
* @param {(string|Function)=} opt_listener
* @return {function()}
*/
angular.Scope.$watchCollection = function(exp, opt_listener) {};
/**
* @typedef {{
* currentScope: angular.Scope,
@@ -1441,6 +1450,11 @@ angular.NgModelController.prototype.$viewValue;
*/
angular.FormController = function() {};
/**
* @param {*} control
*/
angular.FormController.prototype.$addControl = function(control) {};
/**
* @type {boolean}
*/
@@ -1456,11 +1470,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}
*/
-11
View File
@@ -9,14 +9,3 @@
ng\:form {
display: block;
}
/* The styles below ensure that the CSS transition will ALWAYS
* animate and close. A nasty bug occurs with CSS transitions where
* when the active class isn't set, or if the active class doesn't
* contain any styles to transition to, then, if ngAnimate is used,
* it will appear as if the webpage is broken due to the forever hanging
* animations. The border-spacing (!ie) and zoom (ie) CSS properties are
* used below since they trigger a transition without making the browser
* animate anything and they're both highly underused CSS properties */
.ng-animate-start { border-spacing:1px 1px; -ms-zoom:1.0001; }
.ng-animate-active { border-spacing:0px 0px; -ms-zoom:1; }
+1 -1
View File
@@ -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) {
+2 -12
View File
@@ -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;
}
@@ -215,17 +215,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
}];
this.html5Mode = angular.noop;
});
$provide.decorator('$timeout', ['$rootScope', '$delegate', function($rootScope, $delegate) {
return angular.extend(function(fn, delay) {
if (delay && delay > 50) {
return setTimeout(function() {
$rootScope.$apply(fn);
}, delay);
} else {
return $delegate.apply(this, arguments);
}
}, $delegate);
}]);
$provide.decorator('$rootScope', ['$delegate', function($delegate) {
embedRootScope = $delegate;
+1 -1
View File
@@ -63,7 +63,7 @@ This module is provided by default and contains the core components of AngularJS
</td>
<td>
<p>
The core filters available in the ng module are used to transform template data before it is renders within directives and expressions.
The core filters available in the ng module are used to transform template data before it is rendered within directives and expressions.
</p>
<p>
Some examples include:
+4 -1
View File
@@ -3,6 +3,9 @@
@description
# ng (core module)
The ng module is loaded by default when an AngularJS application is started. The module itself contains the essential components to for an AngularJS application to function. The table below lists a high level breakdown of each of the services/factories, filters, directives and testing components available within this core module.
The ng module is loaded by default when an AngularJS application is started. The module itself
contains the essential components for an AngularJS application to function. The table below
lists a high level breakdown of each of the services/factories, filters, directives and testing
components available within this core module.
<div doc-module-components="ng"></div>
@@ -1,9 +0,0 @@
@ngdoc error
@name $httpBackend:noxhr
@fullName Unsupported XHR
@description
This error occurs in browsers that do not support XmlHttpRequest. AngularJS
supports Safari, Chrome, Firefox, Opera, IE8 and higher, and mobile browsers
(Android, Chrome Mobile, iOS Safari). To avoid this error, use an officially
supported browser.
+1 -1
View File
@@ -4,4 +4,4 @@
@description
This error occurs when 'ngPattern' is passed an expression that isn't a regular expression or doesn't have the expected format.
For more information on valid expression syntax, see 'ngPattern' in {@link api/ng.directive:select input} directive docs.
For more information on valid expression syntax, see 'ngPattern' in {@link api/ng.directive:input input} directive docs.
+1 -1
View File
@@ -13,7 +13,7 @@ For example the issue can be triggered by this *invalid* code:
<div ng-repeat="value in [4, 4]"></div>
```
To resolve this error either ensure that the items in the collection have unique identity of use the `track by` syntax to specify how to track the association between models and DOM.
To resolve this error either ensure that the items in the collection have unique identity or use the `track by` syntax to specify how to track the association between models and DOM.
To resolve the example above can be resolved by using `track by $index`, which will cause the items to be keyed by their position in the array instead of their value:
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -184,7 +184,7 @@ The following graphic shows how everything works together after we introduced th
# View independent business logic: Services
Right now, the `InvoiceController` contains all logic of our example. When the application grows it
is a good practise to move view independent logic from the controller into a so called
is a good practice to move view independent logic from the controller into a so called
<a name="service">"{@link dev_guide.services service}"</a>, so it can be reused by other parts
of the application as well. Later on, we could also change that service to load the exchange rates
from the web, e.g. by calling the Yahoo Finance API, without changing the controller.
@@ -19,7 +19,7 @@ testable.
To register a service, you must have a module that this service will be part of. Afterwards, you
can register the service with the module either via the {@link api/angular.Module Module api} or
by using the {@link api/AUTO.$provide $provide} service in the module configuration
function.The following pseudo-code shows both approaches:
function. The following pseudo-code shows both approaches:
Using the angular.Module api:
<pre>
@@ -50,7 +50,7 @@ of which depend on other services that are provided by the Angular framework:
* @param {*} message Message to be logged.
*/
function batchLogModule($provide){
$provide.factory('batchLog', ['$timeout', '$log', function($timeout, $log) {
$provide.factory('batchLog', ['$interval', '$log', function($interval, $log) {
var messageQueue = [];
function log() {
@@ -58,11 +58,10 @@ of which depend on other services that are provided by the Angular framework:
$log('batchLog messages: ', messageQueue);
messageQueue = [];
}
$timeout(log, 50000);
}
// start periodic checking
log();
$interval(log, 50000);
return function(message) {
messageQueue.push(message);
@@ -82,13 +81,13 @@ of which depend on other services that are provided by the Angular framework:
}]);
}
// get the main service to kick of the application
// get the main service to kick off the application
angular.injector([batchLogModule]).get('routeTemplateMonitor');
</pre>
Things to notice in this example:
* The `batchLog` service depends on the built-in {@link api/ng.$timeout $timeout} and
* The `batchLog` service depends on the built-in {@link api/ng.$interval $interval} and
{@link api/ng.$log $log} services, and allows messages to be logged into the
`console.log` in batches.
* The `routeTemplateMonitor` service depends on the built-in {@link api/ngRoute.$route
@@ -163,7 +163,7 @@ function MyClass(xhr) {
This is the preferred method since the code makes no assumptions about the origin of `xhr` and cares
instead about whoever created the class responsible for passing it in. Since the creator of the
class should be different code than the user of the class, it separates the responsibility of
creation from the logic. This is dependency-injection is in a nutshell.
creation from the logic. This is dependency-injection in a nutshell.
The class above is testable, since in the test we can write:
<pre>
@@ -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
+14 -16
View File
@@ -280,7 +280,7 @@ using `templateUrl` instead:
</example>
Great! But what if we wanted to have our directive match the tag name `<my-customer>` instead?
If we simply put a `<my-customer>` element into the HMTL, it doesn't work.
If we simply put a `<my-customer>` element into the HTML, it doesn't work.
<div class="alert alert-waring">
**Note:** When you create a directive, it is restricted to attribute only by default. In order to
@@ -506,6 +506,8 @@ that you explicitly pass in.
<div class="alert alert-warning">
**Note:** Normally, a scope prototypically inherits from its parent. An isolated scope does not.
See the {@link guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive
"Isolating the Scope of a Directive"} section for more information about isolate scopes.
</div>
<div class="alert alert-success">
@@ -528,8 +530,10 @@ where:
* `attrs` is an object with the normalized attribute names and their corresponding values.
In our `link` function, we want to update the displayed time once a second, or whenever a user
changes the time formatting string that our directive binds to. We also want to remove the timeout
if the directive is deleted so we don't introduce a memory leak.
changes the time formatting string that our directive binds to. We will use the `$interval` service
to call a handler on a regular basis. This is easier than using `$timeout` but also works better with
end 2 end testing, where we want to ensure that all $timeouts have completed before completing the test.
We also want to remove the `$interval` if the directive is deleted so we don't introduce a memory leak.
<example module="docsTimeDirective">
<file name="script.js">
@@ -537,7 +541,7 @@ if the directive is deleted so we don't introduce a memory leak.
.controller('Ctrl2', function($scope) {
$scope.format = 'M/d/yy h:mm:ss a';
})
.directive('myCurrentTime', function($timeout, dateFilter) {
.directive('myCurrentTime', function($interval, dateFilter) {
function link(scope, element, attrs) {
var format,
@@ -552,20 +556,14 @@ if the directive is deleted so we don't introduce a memory leak.
updateTime();
});
function scheduleUpdate() {
// save the timeoutId for canceling
timeoutId = $timeout(function() {
updateTime(); // update DOM
scheduleUpdate(); // schedule the next update
}, 1000);
}
element.on('$destroy', function() {
$timeout.cancel(timeoutId);
$interval.cancel(timeoutId);
});
// start the UI update process.
scheduleUpdate();
// start the UI update process; save the timeoutId for canceling
timeoutId = $interval(function() {
updateTime(); // update DOM
}, 1000);
}
return {
@@ -583,7 +581,7 @@ if the directive is deleted so we don't introduce a memory leak.
There are a couple of things to note here.
Just like the `module.controller` API, the function argument in `module.directive` is dependency
injected. Because of this, we can use `$timeout` and `dateFilter` inside our directive's `link`
injected. Because of this, we can use `$interval` and `dateFilter` inside our directive's `link`
function.
We register an event `element.on('$destroy', ...)`. What fires this `$destroy` event?
+1 -1
View File
@@ -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`.
+11 -6
View File
@@ -33,10 +33,10 @@ In addition it provides an {@link api/ng.directive:ngModel.NgModelController API
<script>
function Controller($scope) {
$scope.master= {};
$scope.master = {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
$scope.master = angular.copy(user);
};
$scope.reset = function() {
@@ -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:ngModel ngModel} 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:
@@ -230,7 +235,7 @@ In the following example we create two directives.
<script>
var app = angular.module('form-example1', []);
var INTEGER_REGEXP = /^\-?\d*$/;
var INTEGER_REGEXP = /^\-?\d+$/;
app.directive('integer', function() {
return {
require: 'ngModel',
+2 -2
View File
@@ -97,9 +97,9 @@ locale, it is fine to rely on the default currency symbol. However, if you antic
in other locales might use your app, you should provide your own currency symbol to make sure the
actual value is understood.
For example, if you want to display account balance of 1000 dollars with the following binding
For example, if you want to display an account balance of 1000 dollars with the following binding
containing currency filter: `{{ 1000 | currency }}`, and your app is currently in en-US locale.
'$1000.00' will be shown. However, if someone in a different local (say, Japan) views your app, her
'$1000.00' will be shown. However, if someone in a different local (say, Japan) views your app, their
browser will specify the locale as ja, and the balance of '¥1000.00' will be shown instead. This
will really upset your client.
+2 -2
View File
@@ -23,7 +23,7 @@ It is very unlikely that issues specific to IE7 or earlier will be given any tim
To make your Angular application work on IE please make sure that:
1. You polyfill JSON.stringify if necessary (IE7 will need this). You can use
1. You polyfill JSON.stringify for IE7 and below. You can use
[JSON2](https://github.com/douglascrockford/JSON-js) or
[JSON3](http://bestiejs.github.com/json3/) polyfills for this.
<pre>
@@ -51,7 +51,7 @@ To make your Angular application work on IE please make sure that:
3. you **do not** use custom element tags such as `<ng:view>` (use the attribute version
`<div ng-view>` instead), or
4. if you **do use** custom element tags, then you must take these steps to make IE happy:
4. if you **do use** custom element tags, then you must take these steps to make IE 8 and below happy:
<pre>
<!doctype html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="optionalModuleName">
+6 -46
View File
@@ -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
+10 -4
View File
@@ -18,8 +18,12 @@ watch {@link guide/expression expressions} and propagate events.
propagate any model changes through the system into the view from outside of the "Angular
realm" (controllers, services, Angular event handlers).
- Scopes can be nested to isolate application components while providing access to shared model
properties. A scope (prototypically) inherits properties from its parent scope.
- Scopes can be nested to limit access to the properties of application components while providing
access to shared model properties. Nested scopes are either "child scopes" or "isolate scopes".
A "child scope" (prototypically) inherits properties from its parent scope. An "isolate scope"
does not. See {@link
guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive isolated
scopes} for more information.
- Scopes provide context against which {@link guide/expression expressions} are evaluated. For
example `{{username}}` expression is meaningless, unless it is evaluated against a specific
@@ -259,8 +263,8 @@ the `$digest` phase. This delay is desirable, since it coalesces multiple model
For mutations to be properly observed, you should make them only within the {@link
api/ng.$rootScope.Scope#methods_$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 api/ng.$http $http} or {@link
api/ng.$timeout $timeout} services.
or asynchronous work with {@link api/ng.$http $http}, {@link api/ng.$timeout $timeout}
or {@link api/ng.$interval $interval} services.
4. **Mutation observation**
@@ -306,6 +310,8 @@ api/ng.directive:ngController ng-controller} and {@link
api/ng.directive:ngRepeat ng-repeat}, create new child scopes
and attach the child scope to the corresponding DOM element. You can retrieve a scope for any DOM
element by using an `angular.element(aDomElement).scope()` method call.
See the {@link guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive
directives guide} for more information about isolate scopes.
### Controllers and Scopes
+3 -1
View File
@@ -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
@@ -46,6 +46,8 @@ and included in your {@link http://docs.oracle.com/javase/tutorial/essential/env
npm install -g bower
```
**Note:** You may need to use sudo (for OSX, *nix, BSD etc) or run your command shell as Administrator (for Windows) to install Grunt &amp;
Bower globally.
## Forking Angular on Github
-1
View File
@@ -73,7 +73,6 @@ directory.</p></li>
<p>Additionally install <a href="http://karma-runner.github.io/">Karma</a> and its plugins if you
don't have it already:</p>
<pre>
npm install -g karma
npm install
</pre></li>
<li><p>You will need an http server running on your system. Mac and Linux machines typically
+1 -1
View File
@@ -179,7 +179,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi
* Removed the example app
* Added phone images to `app/img/phones/`
* Added phone data files (JSON) to `app/phones/`
* Added [Bootstrap](http://twitter.github.com/bootstrap/) files to `app/css/` and `app/img/`
* Added [Bootstrap](http://getbootstrap.com) files to `app/css/` and `app/img/`
+9 -5
View File
@@ -191,8 +191,8 @@ You can do this by issuing `npm install` into your terminal.
To run the test, do the following:
1. In a _separate_ terminal window or tab, go to the `angular-phonecat` directory and run
`./scripts/test.sh` to start the Karma server (the config file necessary to start the server
is located at `./config/karma.conf.js`).
`./scripts/test.sh` (if you are on Windows, run scripts\test.bat) to start the Karma server (the
config file necessary to start the server is located at `./config/karma.conf.js`).
2. Karma will start a new instance of Chrome browser automatically. Just ignore it and let it run in
the background. Karma will use this browser for test execution.
@@ -206,7 +206,7 @@ is located at `./config/karma.conf.js`).
Yay! The test passed! Or not...
4. To rerun the tests, just change any of the source or test files. Karma will notice the change
4. To rerun the tests, just change any of the source or test .js files. Karma will notice the change
and will rerun the tests for you. Now isn't that sweet?
# Experiments
@@ -217,9 +217,13 @@ is located at `./config/karma.conf.js`).
* Create a new model property in the controller and bind to it from the template. For example:
$scope.hello = "Hello, World!"
$scope.name = "World"
Refresh your browser to make sure it says, "Hello, World!"
Then add a new binding to `index.html`:
<p>Hello, {{name}}!</p>
Refresh your browser and verify that it says "Hello, World!".
* Create a repeater that constructs a simple table:
+2 -2
View File
@@ -88,8 +88,8 @@ phonecatApp.controller('PhoneListCtrl', function ($scope) {
record. This property is used to order phones by age.
* We added a line to the controller that sets the default value of `orderProp` to `age`. If we had
not set the default value here, the model would stay uninitialized until our user would pick an
option from the drop down menu.
not set a default value here, the `orderBy` filter would remain uninitialized until our
user picked an option from the drop down menu.
This is a good time to talk about two-way data-binding. Notice that when the app is loaded in the
browser, "Newest" is selected in the drop down menu. This is because we set `orderProp` to `'age'`
+4 -1
View File
@@ -170,6 +170,9 @@ describe('PhoneCat controllers', function() {
describe('PhoneListCtrl', function(){
var scope, ctrl, $httpBackend;
// Load our app module definition before each test.
beforeEach(module('phonecatApp'));
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
// This allows us to inject a service but then attach it to a variable
// with the same name as the service.
@@ -199,7 +202,7 @@ isolated from the work done in other tests.
* We created a new scope for our controller by calling `$rootScope.$new()`
* We called the injected `$controller` function passing the name of the`PhoneListCtrl` controller
* We called the injected `$controller` function passing the name of the `PhoneListCtrl` controller
and the created scope as parameters.
Because our code now uses the `$http` service to fetch the phone list data in our controller, before
+3 -3
View File
@@ -121,7 +121,7 @@ view, Angular will use the `phone-list.html` template and the `PhoneListCtrl` co
We reused the `PhoneListCtrl` controller that we constructed in previous steps and we added a new,
empty `PhoneDetailCtrl` controller to the `app/js/controllers.js` file for the phone details view.
`$route.otherwise({redirectTo: '/phones'})` triggers a redirection to `/phones` when the browser
`$routeProvider.otherwise({redirectTo: '/phones'})` triggers a redirection to `/phones` when the browser
address doesn't match either of our routes.
Note the use of the `:phoneId` parameter in the second route declaration. The `$route` service uses
@@ -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');
});
+2 -2
View File
@@ -11,7 +11,7 @@ In this step, you will improve the way our app fetches data.
<div doc-tutorial-reset="11"></div>
The last improvement we will make to our app is to define a custom service that represents a {@link
The next improvement we will make to our app is to define a custom service that represents a {@link
http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client. Using this client we
can make XHR requests for data in an easier way, without having to deal with the lower-level {@link
api/ng.$http $http} API, HTTP methods and URLs.
@@ -185,7 +185,7 @@ describe('PhoneCat controllers', function() {
xyzPhoneData = function() {
return {
name: 'phone xyz',
images: ['image/url1.png', 'image/url2.png']
images: ['image/url1.png', 'image/url2.png']
}
};
+1 -2
View File
@@ -293,8 +293,7 @@ Let's add another animation to our application. Switching to our `phone-detail.h
we see that we have a nice thumbnail swapper. By clicking on the thumbnails listed on the page,
the profile phone image changes. But how can we change this around to add animations?
Lets think about it first,
basically when you click on a thumbnail image, you're changing the state of the profile image to reflect the newly
Let's think about it first. Basically, when you click on a thumbnail image, you're changing the state of the profile image to reflect the newly
selected thumbnail image.
The best way to specify state changes within HTML is to use classes.
Much like before, how we used a CSS class to specify
+29
View File
@@ -1,5 +1,7 @@
var ngdoc = require('../src/ngdoc.js');
var DOM = require('../src/dom.js').DOM;
var gruntUtil = require('../../lib/grunt/utils.js');
describe('ngdoc', function() {
var Doc = ngdoc.Doc;
@@ -287,6 +289,33 @@ describe('ngdoc', function() {
});
});
describe('api section', function() {
it('should render a "view source" button with link to the source in master', function() {
var doc = new Doc({
id: 'ng.abc',
name: 'ng.abc',
section: 'api',
ngdoc: 'service',
file: 'fooService.js',
line: '333'
});
if (gruntUtil.getVersion().full.indexOf('-') === -1) {
expect(doc.html().match(/^(<a .*?<\/a>)/)[1]).toMatch(
/<a href="http:\/\/github\.com\/angular\/angular\.js\/tree\/v\d+\.\d+\.\d+\/fooService\.js#L333" class="view-source/
);
} else {
expect(doc.html().match(/^(<a .*?<\/a>)/)[1]).toMatch(
/<a href="http:\/\/github\.com\/angular\/angular\.js\/tree\/[a-z0-9]{7}\/fooService\.js#L333" class="view-source/
);
}
});
});
////////////////////////////////////////
describe('TAG', function() {
+1 -1
View File
@@ -3,7 +3,7 @@
*/
exports.appCache = appCache;
var fs = require('q-fs');
var fs = require('q-io/fs');
var Q = require('qq');
function identity($) {return $;}
+16 -3
View File
@@ -6,7 +6,8 @@ var makeUnique = {
'script.js': true,
'unit.js': true,
'spec.js': true,
'scenario.js': true
'scenario.js': true,
'protractorTest.js': true
}
function ids(list) {
@@ -14,7 +15,7 @@ function ids(list) {
};
exports.Example = function(scenarios) {
exports.Example = function(scenarios, protractorTests) {
this.module = '';
this.deps = ['angular.js'];
this.html = [];
@@ -24,6 +25,8 @@ exports.Example = function(scenarios) {
this.unit = [];
this.scenario = [];
this.scenarios = scenarios;
this.protractorTest = [];
this.protractorTests = protractorTests;
}
exports.Example.prototype.setModule = function(module) {
@@ -44,6 +47,10 @@ exports.Example.prototype.addSource = function(name, content) {
var ext = name == 'scenario.js' ? 'scenario' : name.split('.')[1],
id = name;
if (name == 'protractorTest.js') {
ext = 'protractorTest';
}
if (makeUnique[name] && usedIds[id]) {
id = name + '-' + (seqCount++);
}
@@ -56,6 +63,9 @@ exports.Example.prototype.addSource = function(name, content) {
if (ext == 'scenario') {
this.scenarios.push(content);
}
if (ext == 'protractorTest') {
this.protractorTests.push(content);
}
};
exports.Example.prototype.enableAnimations = function() {
@@ -92,6 +102,7 @@ exports.Example.prototype.toHtmlEdit = function() {
out.push(' source-edit-json="' + ids(this.json) + '"');
out.push(' source-edit-unit="' + ids(this.unit) + '"');
out.push(' source-edit-scenario="' + ids(this.scenario) + '"');
out.push(' source-edit-protractor="' + ids(this.protractorTest) + '"');
out.push('></div>\n');
return out.join('');
};
@@ -107,6 +118,7 @@ exports.Example.prototype.toHtmlTabs = function() {
htmlTabs(this.json);
htmlTabs(this.unit);
htmlTabs(this.scenario);
htmlTabs(this.protractorTest);
out.push('</div>');
return out.join('');
@@ -119,7 +131,8 @@ exports.Example.prototype.toHtmlTabs = function() {
if (name === 'index.html') {
wrap = ' ng-html-wrap="' + self.module + ' ' + self.deps.join(' ') + '"';
}
if (name == 'scenario.js') name = 'End to end test';
if (name == 'scenario.js') name = 'ngScenario e2e test';
if (name == 'protractorTest.js') name = 'Protractor e2e test';
out.push(
'<div class="tab-pane" title="' + name + '">\n' +
+10 -4
View File
@@ -17,6 +17,8 @@ writer.makeDir('build/docs/', true).then(function() {
return writer.makeDir('build/docs/components/bootstrap');
}).then(function() {
return writer.makeDir('build/docs/components/font-awesome');
}).then(function() {
return writer.makeDir('build/docs/e2etests');
}).then(function() {
console.log('Generating AngularJS Reference Documentation...');
return reader.collect();
@@ -53,6 +55,10 @@ writer.makeDir('build/docs/', true).then(function() {
var id = doc.id.replace('angular.Module', 'angular.IModule');
fileFutures.push(writer.output('partials/' + doc.section + '/' + id + '.html', doc.html()));
// If it has a sample Protractor test, output that as well.
if (doc.protractorTests.length) {
fileFutures.push(writer.output('ptore2e/' + doc.section + '/' + id + '_test.js', ngdoc.writeProtractorTest(doc)));
}
});
ngdoc.checkBrokenLinks(docs);
@@ -74,10 +80,10 @@ function writeTheRest(writesFuture) {
var versions = ngdoc.ngVersions();
var currentVersion = ngdoc.ngCurrentVersion();
writesFuture.push(writer.symlink('../../docs/content/notes', 'build/docs/notes', 'dir'));
writesFuture.push(writer.symlinkTemplate('css', 'dir'));
writesFuture.push(writer.symlink('../../docs/img', 'build/docs/img', 'dir'));
writesFuture.push(writer.symlinkTemplate('js', 'dir'));
writesFuture.push(writer.symlink('../../docs/content/notes', 'build/docs/notes', 'directory'));
writesFuture.push(writer.symlinkTemplate('css', 'directory'));
writesFuture.push(writer.symlink('../../docs/img', 'build/docs/img', 'directory'));
writesFuture.push(writer.symlinkTemplate('js', 'directory'));
var manifest = 'manifest="/build/docs/appcache.manifest"';
+23 -3
View File
@@ -35,6 +35,7 @@ var lookupMinerrMsg = function (doc) {
exports.trim = trim;
exports.metadata = metadata;
exports.scenarios = scenarios;
exports.writeProtractorTest = writeProtractorTest;
exports.merge = merge;
exports.checkBrokenLinks = checkBrokenLinks;
exports.Doc = Doc;
@@ -155,6 +156,7 @@ function Doc(text, file, line) {
this.line = line;
}
this.scenarios = this.scenarios || [];
this.protractorTests = this.protractorTests || [];
this.requires = this.requires || [];
this.param = this.param || [];
this.properties = this.properties || [];
@@ -292,7 +294,7 @@ Doc.prototype = {
replace(/<example(?:\s+module="([^"]*)")?(?:\s+deps="([^"]*)")?(\s+animations="true")?>([\s\S]*?)<\/example>/gmi,
function(_, module, deps, animations, content) {
var example = new Example(self.scenarios);
var example = new Example(self.scenarios, self.protractorTests);
if(animations) {
example.enableAnimations();
example.addDeps('angular-animate.js');
@@ -329,7 +331,7 @@ Doc.prototype = {
}).
replace(/^<doc:example(\s+[^>]*)?>([\s\S]*)<\/doc:example>/mi, function(_, attrs, content) {
var html, script, scenario,
example = new Example(self.scenarios);
example = new Example(self.scenarios, self.protractorTests);
example.setModule((attrs||'module=""').match(/^\s*module=["'](.*)["']\s*$/)[1]);
content.
@@ -347,6 +349,8 @@ Doc.prototype = {
}).
replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, function(_, before, content){
example.addSource('scenario.js', content);
}).replace(/(<doc:protractor>)([\s\S]*)(<\/doc:protractor>)/mi, function(_, before, content){
example.addSource('protractorTest.js', content);
});
return placeholder(example.toHtml());
@@ -548,7 +552,7 @@ Doc.prototype = {
minerrMsg;
var gitTagFromFullVersion = function(version) {
var match = version.match(/-(\w{7})/);
var match = version.match(/sha\.(\w{7})/);
if (match) {
// git sha
@@ -1106,6 +1110,22 @@ function scenarios(docs){
}
}
function writeProtractorTest(doc){
var lines = [];
lines.push('describe("' + doc.section + '/' + doc.id + '", function() {');
lines.push(' beforeEach(function() {');
lines.push(' browser.get("index-nocache.html#!/' + doc.section + '/' + doc.id + '");');
lines.push(' });');
lines.push('');
doc.protractorTests.forEach(function(test){
lines.push(indentCode(trim(test), 2));
lines.push('');
});
lines.push('});');
lines.push('');
return lines.join('\n');
}
//////////////////////////////////////////////////////////
function metadata(docs){
+1 -1
View File
@@ -7,7 +7,7 @@ exports.collect = collect;
var ngdoc = require('./ngdoc.js'),
Q = require('qq'),
qfs = require('q-fs'),
qfs = require('q-io/fs'),
PATH = require('path');
var NEW_LINE = /\n\r?/;
+30
View File
@@ -144,6 +144,32 @@
.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;
}
.content h6 {
text-transform:none;
color:black;
}
ul.parameters > li > p,
@@ -522,6 +548,10 @@ pre ol li {
margin-bottom:30px;
}
.definition-table td {
vertical-align: top;
}
.component-heading {
text-transform:capitalize;
}
+17 -9
View File
@@ -5,11 +5,19 @@ var docsApp = {
filter: {}
};
docsApp.controller.DocsVersionsCtrl = ['$scope', '$window', 'NG_VERSIONS', 'NG_VERSION', function($scope, $window, NG_VERSIONS, NG_VERSION) {
docsApp.controller.DocsVersionsCtrl = ['$scope', '$rootScope', '$window', 'NG_VERSIONS', 'NG_VERSION', function($scope, $rootScope, $window, NG_VERSIONS, NG_VERSION) {
$scope.docs_versions = NG_VERSIONS;
$scope.docs_version = NG_VERSIONS[0];
$scope.jumpToDocsVersion = function(version) {
$window.location = version.url;
var currentPagePath = '';
// preserve URL path when switching between doc versions
if (angular.isObject($rootScope.currentPage) && $rootScope.currentPage.section && $rootScope.currentPage.id) {
currentPagePath = '/' + $rootScope.currentPage.section + '/' + $rootScope.currentPage.id;
}
$window.location = version.url + currentPagePath;
};
}];
@@ -273,10 +281,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));
}
};
};
@@ -645,7 +653,7 @@ docsApp.serviceFactory.sections = ['NG_PAGES', function sections(NG_PAGES) {
}];
docsApp.controller.DocsController = function($scope, $location, $window, $cookies, sections) {
docsApp.controller.DocsController = function($scope, $rootScope, $location, $window, $cookies, sections) {
$scope.fold = function(url) {
if(url) {
$scope.docs_fold = '/notes/' + url;
@@ -736,9 +744,9 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
sectionName = SECTION_NAME[sectionId] || sectionId,
page = sections.getPage(sectionId, partialId);
$scope.currentPage = sections.getPage(sectionId, partialId);
$rootScope.currentPage = sections.getPage(sectionId, partialId);
if (!$scope.currentPage) {
if (!$rootScope.currentPage) {
$scope.partialTitle = 'Error: Page Not Found!';
}
+2 -2
View File
@@ -3,7 +3,7 @@
* for testability
*/
var pathUtils = require('path');
var qfs = require('q-fs');
var qfs = require('q-io/fs');
var Q = require('qq');
var OUTPUT_DIR = pathUtils.join('build','docs');
var TEMPLATES_DIR = pathUtils.join('docs','src','templates');
@@ -76,7 +76,7 @@ function symlink(from, to, type) {
// qfs will normalize the path arguments for us here
return qfs.exists(to).then(function(exists) {
if (!exists) {
return qfs.symbolicLink(to, from, type);
return qfs.symbolicLink(to, from, type || 'file');
}
});
}
+7 -2
View File
@@ -1,9 +1,12 @@
#!/bin/bash
echo "#################################"
echo "#### Jenkins Build ############"
echo "#################################"
# Enable tracing and exit on first failure
set -xe
# Define reasonable set of browsers in case we are running manually from commandline
if [[ -z "$BROWSERS" ]]
then
@@ -25,13 +28,15 @@ rm -f angular.js.size
npm install --color false
grunt ci-checks package --no-color
# DOCS generator unit tests #
grunt test:docgen --no-color
# UNIT TESTS #
grunt test:unit --browsers $BROWSERS --reporters=dots,junit --no-colors --no-color
# END TO END TESTS #
grunt test:e2e --browsers $BROWSERS_E2E --reporters=dots,junit --no-colors --no-color
grunt test:protractor
# Promises/A+ TESTS #
grunt test:promises-aplus --no-color
+1 -1
View File
@@ -10,12 +10,12 @@ module.exports = function(config) {
'build/angular.js',
'build/angular-cookies.js',
'build/angular-mocks.js',
'build/angular-resource.js',
'build/angular-touch.js',
'build/angular-sanitize.js',
'build/angular-route.js',
'build/angular-animate.js',
'build/angular-mocks.js',
'build/docs/components/lunr.js',
'build/docs/components/google-code-prettify.js',
+8 -4
View File
@@ -13,7 +13,10 @@ module.exports = function(config, specificOptions) {
// SauceLabs config for local development.
sauceLabs: {
testName: specificOptions.testName || 'AngularJS',
startConnect: true
startConnect: true,
options: {
'selenium-version': '2.37.0'
}
},
// BrowserStack config for local development.
@@ -33,13 +36,14 @@ module.exports = function(config, specificOptions) {
},
'SL_Firefox': {
base: 'SauceLabs',
browserName: 'firefox'
browserName: 'firefox',
version: '26'
},
'SL_Safari': {
base: 'SauceLabs',
browserName: 'safari',
platform: 'Mac 10.8',
version: '6'
platform: 'OS X 10.9',
version: '7'
},
'SL_IE_8': {
base: 'SauceLabs',
+8
View File
@@ -61,6 +61,14 @@ module.exports = function(grunt) {
util.startKarma.call(util, this.data, false, this.async());
});
grunt.registerTask('webdriver', 'Update webdriver', function() {
util.updateWebdriver.call(util, this.async());
});
grunt.registerMultiTask('runprotractor', 'Run Protractor integration tests', function() {
util.startProtractor.call(util, this.data, this.async());
});
grunt.registerTask('collect-errors', 'Combine stripped error files', function () {
util.collectErrors();
});
+39 -2
View File
@@ -36,13 +36,12 @@ module.exports = {
var package = JSON.parse(fs.readFileSync('package.json', 'UTF-8'));
var match = package.version.match(/^([^\-]*)(?:\-(.+))?$/);
var semver = match[1].split('.');
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
var fullVersion = match[1];
if (match[2]) {
fullVersion += '-';
fullVersion += (match[2] == 'snapshot') ? hash : match[2];
fullVersion += (match[2] == 'snapshot') ? getSnapshotSuffix() : match[2];
}
version = {
@@ -55,6 +54,12 @@ module.exports = {
};
return version;
function getSnapshotSuffix() {
var jenkinsBuild = process.env.BUILD_NUMBER || 'local';
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
return 'build.'+jenkinsBuild+'+sha.'+hash;
}
},
@@ -79,6 +84,38 @@ module.exports = {
},
updateWebdriver: function(done){
var p = spawn('node', ['node_modules/protractor/bin/webdriver-manager', 'update']);
p.stdout.pipe(process.stdout);
p.stderr.pipe(process.stderr);
p.on('exit', function(code){
if(code !== 0) grunt.fail.warn('Webdriver failed to update');
done();
});
},
startProtractor: function(config, done){
var sauceUser = grunt.option('sauceUser');
var sauceKey = grunt.option('sauceKey');
var tunnelIdentifier = grunt.option('capabilities.tunnel-identifier');
var sauceBuild = grunt.option('capabilities.build');
var args = ['node_modules/protractor/bin/protractor', config];
if (sauceUser) args.push('--sauceUser=' + sauceUser);
if (sauceKey) args.push('--sauceKey=' + sauceKey);
if (tunnelIdentifier) args.push('--capabilities.tunnel-identifier=' + tunnelIdentifier);
if (sauceBuild) args.push('--capabilities.build=' + sauceBuild);
var p = spawn('node', args);
p.stdout.pipe(process.stdout);
p.stderr.pipe(process.stderr);
p.on('exit', function(code){
if(code !== 0) grunt.fail.warn('Protractor test(s) failed. Exit code: ' + code);
done();
});
},
wrap: function(src, name){
src.unshift('src/' + name + '.prefix');
src.push('src/' + name + '.suffix');
+2 -2
View File
@@ -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
+15 -13
View File
@@ -1,8 +1,8 @@
{
"name": "angularjs",
"version": "1.2.4",
"cdnVersion": "1.2.3",
"codename": "wormhole-baster",
"version": "1.2.9",
"cdnVersion": "1.2.8",
"codename": "enchanted-articulacy",
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
@@ -10,23 +10,26 @@
"devDependencies": {
"grunt": "~0.4.1",
"bower": "~1.2.2",
"grunt-bump": "~0.0.13",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-connect": "~0.5.0",
"grunt-contrib-copy": "~0.4.1",
"jasmine-node": "~1.11.0",
"q": "~0.9.2",
"q-fs": "~0.1.36",
"q-io": "~1.10.6",
"qq": "~0.3.5",
"shelljs": "~0.2.6",
"karma": "~0.11",
"karma-jasmine": "~0.1.0",
"karma-chrome-launcher": "~0.1.0",
"karma-firefox-launcher": "~0.1.0",
"karma-ng-scenario": "~0.1.0",
"karma-junit-reporter": "~0.2.1",
"karma-sauce-launcher": "~0.1.1",
"karma-script-launcher": "~0.1.0",
"karma": "0.11.12",
"karma-jasmine": "0.1.5",
"karma-chrome-launcher": "0.1.2",
"karma-firefox-launcher": "0.1.3",
"karma-ng-scenario": "0.1.0",
"karma-junit-reporter": "0.2.1",
"karma-sauce-launcher": "0.2.0",
"karma-script-launcher": "0.1.0",
"karma-browserstack-launcher": "0.0.7",
"protractor": "~0.16.1",
"yaml-js": "~0.0.8",
"marked": "0.2.9",
"rewire": "1.1.3",
@@ -38,7 +41,6 @@
"grunt-shell": "~0.4.0",
"semver": "~2.1.0",
"lodash": "~2.1.0",
"karma-browserstack-launcher": "git://github.com/karma-runner/karma-browserstack-launcher.git#master",
"browserstacktunnel-wrapper": "~1.1.1"
},
"licenses": [
+20
View File
@@ -0,0 +1,20 @@
exports.config = {
allScriptsTimeout: 11000,
specs: [
'build/docs/ptore2e/**/*.js',
'test/e2e/docsAppE2E.js'
],
capabilities: {
'browserName': 'chrome'
},
baseUrl: 'http://localhost:8000/build/docs/',
framework: 'jasmine',
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};
-34
View File
@@ -1,34 +0,0 @@
#!/usr/bin/env bash
function catch_errors() {
echo "ERROR. That's life."
exit 1
}
trap catch_errors ERR
TMP_FILE='changelog.tmp'
CHANGELOG_FILE='CHANGELOG.md'
echo "Getting current version..."
VERSION=`./version.js --current`
echo "Generating changelog..."
./changelog.js $VERSION $TMP_FILE
cat $CHANGELOG_FILE >> $TMP_FILE
mv -f $TMP_FILE $CHANGELOG_FILE
echo "Updating version..."
./version.js --remove-snapshot
echo "CONFIRM TO COMMIT"
read WHATEVER
echo "Creating commit..."
git commit version.yaml CHANGELOG.md -m "chore(relase): cutting the v$VERSION release"
echo "Creating tag..."
git tag "v$VERSION"
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
# Script for updating angular-phonecat repo from current local build.
echo "#################################"
echo "## Update angular-phonecat ###"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
"[--no-test=(true|false)]"
)
function init {
TMP_DIR=$(resolveDir ../../tmp)
BUILD_DIR=$(resolveDir ../../build)
REPO_DIR=$TMP_DIR/angular-phonecat
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
}
function prepare {
echo "-- Cloning angular-phonecat"
git clone git@github.com:angular/angular-phonecat.git $REPO_DIR
#
# copy the files from the build
#
echo "-- Updating angular-phonecat"
cd $REPO_DIR
./scripts/private/update-angular.sh $BUILD_DIR
# Test
if [[ $NO_TEST != "true" ]]; then
./scripts/private/test-all.sh
fi
# Generate demo
./scripts/private/snapshot-web.sh
git checkout gh-pages
git pull
rm -r step*
mv angular-phonecat-snapshots-web/step* .
git add step*
git commit -am "Angular $NEW_VERSION release"
}
function publish {
cd $REPO_DIR
echo "-- Pushing angular-phonecat"
git push origin master -f --tags
git push origin gh-pages -f
}
source $(dirname $0)/../utils.inc
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
# Script for updating angular-seed repo from current local build.
echo "#################################"
echo "## Update angular-seed ###"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
"[--no-test=(true|false)]"
)
function init {
TMP_DIR=$(resolveDir ../../tmp)
BUILD_DIR=$(resolveDir ../../build)
REPO_DIR=$TMP_DIR/angular-seed
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
}
function prepare {
echo "-- Cloning angular-seed"
git clone git@github.com:angular/angular-seed.git $REPO_DIR
#
# copy the files from the build
#
echo "-- Updating angular-seed"
cd $REPO_DIR
./scripts/update-angular.sh $BUILD_DIR
# Test
if [[ $NO_TEST != "true" ]]; then
./scripts/test-all.sh
fi
}
function publish {
cd $REPO_DIR
echo "-- Pushing angular-seed"
git push origin master
}
source $(dirname $0)/../utils.inc
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
echo "############################################"
echo "## Remove "-snapshot" from version ########"
echo "############################################"
ARG_DEFS=()
function run {
cd ../..
replaceJsonProp "package.json" "version" "(.*)-snapshot" "\2"
VERSION=$(readJsonProp "package.json" "version")
git add package.json
git commit -m "chore(release): cut v$VERSION release"
git tag -m "v$VERSION" v$VERSION
}
source $(dirname $0)/../utils.inc
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
echo "############################################"
echo "## Increment version, add "-snapshot" and set version name ##"
echo "############################################"
ARG_DEFS=(
"--next-version-type=(patch|minor|major)"
"--next-version-name=(.+)"
)
function run {
cd ../..
grunt bump:$NEXT_VERSION_TYPE
NEXT_VERSION=$(readJsonProp "package.json" "version")
replaceJsonProp "package.json" "version" "(.*)" "\2-snapshot"
replaceJsonProp "package.json" "codename" ".*" "$NEXT_VERSION_NAME"
git add package.json
git commit -m "chore(release): start v$NEXT_VERSION ($NEXT_VERSION)"
}
source $(dirname $0)/../utils.inc
+30
View File
@@ -0,0 +1,30 @@
#!/bin/sh
# Script for updating cdnVersion of angular.js
echo "###################################"
echo "## Update angular.js cdnVersion ###"
echo "###################################"
ARG_DEFS=(
"--cdn-version=(.*)"
"--action=(prepare|publish)"
)
function init {
cd ../..
}
function prepare {
replaceJsonProp "package.json" "cdnVersion" "(.*)" "$CDN_VERSION"
git add package.json
git commit -m "chore(release): update cdn version"
}
function publish {
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# push the commits to github
git push origin $BRANCH
}
source $(dirname $0)/../utils.inc
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
# Script for updating angular.js repo from current local build.
echo "#################################"
echo "## Update angular.js ###"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
"--next-version-type=(patch|minor|major)"
"--next-version-name=(.+)"
"[--no-test=(true|false)]"
)
function init {
cd ../..
}
function prepare() {
./scripts/angular.js/finalize-version.sh
# Build
if [[ $NO_TEST == "true" ]]; then
npm install --color false
grunt ci-checks package --no-color
else
./jenkins_build.sh
fi
./scripts/angular.js/initialize-new-version.sh --next-version-type=$NEXT_VERSION_TYPE --next-version-name=$NEXT_VERSION_NAME
}
function publish() {
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# push the commits to github
git push origin $BRANCH
# push the release tag
git push origin v`cat build/version.txt`
}
source $(dirname $0)/../utils.inc
+47
View File
@@ -0,0 +1,47 @@
#!/bin/sh
# Script for updating angularjs.org repo
echo "#################################"
echo "##### Update angularjs.org ######"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
"--cdn-version=(.*)"
)
function init {
TMP_DIR=$(resolveDir ../../tmp)
REPO_DIR=$TMP_DIR/angularjs.org
}
function prepare {
echo "-- Cloning angularjs.org"
git clone git@github.com:angular/angularjs.org.git $REPO_DIR
#
# update files
#
echo "-- Updating angularjs.org"
cd $REPO_DIR
VERSION_REGEX="[a-z0-9\-\.\+]+"
replaceInFile "index.html" "(ajax\/libs\/angularjs\/)$VERSION_REGEX" "\1$CDN_VERSION"
replaceInFile "index.html" "(<span class=\"version\">[^<]*<span>)$VERSION_REGEX" "\1$CDN_VERSION"
replaceInFile "index.html" "(code.angularjs.org\/)$VERSION_REGEX" "\1$CDN_VERSION"
replaceInFile "js/homepage.js" "($scope.CURRENT_STABLE_VERSION[ ]*=[ ]*')$VERSION_REGEX" "\1$CDN_VERSION"
replaceInFile "js/homepage.js" "($scope.CURRENT_UNSTABLE_VERSION[ ]*=[ ]*')$VERSION_REGEX" "\1$CDN_VERSION"
git add index.html
git add js/homepage.js
git commit -m "update(version): update angular version to $CDN_VERSION"
}
function publish {
cd $REPO_DIR
echo "-- Pushing angularjs.org"
git push origin master
}
source $(dirname $0)/../utils.inc
-23
View File
@@ -1,23 +0,0 @@
# Angular Bower Script
Script for updating the Angular bower repos from a code.angularjs.org package
Requires `node` (for parsing `bower.json`) and `wget` (for fetching the `angular.zip` from `code.angularjs.org`)
## Instructions
You need to run `./init.sh` the first time you use this script to clone all the repos.
For subsequent updates:
```shell
./publish.sh NEW_VERSION
```
Where `NEW_VERSION` is a version number like `1.2.3`.
## License
MIT
-28
View File
@@ -1,28 +0,0 @@
#!/bin/bash
#
# init all of the bower repos
#
set -e # fail if any command fails
REPOS=(
angular \
angular-animate \
angular-cookies \
angular-i18n \
angular-loader \
angular-mocks \
angular-route \
angular-resource \
angular-sanitize \
angular-scenario \
angular-touch \
)
cd `dirname $0`
for repo in "${REPOS[@]}"
do
git clone git@github.com:angular/bower-$repo.git
done
+88 -74
View File
@@ -1,87 +1,101 @@
#!/bin/bash
#
# update all the things
#
# Script for updating the Angular bower repos from current local build.
set -e # fail if any command fails
echo "#################################"
echo "#### Update bower ###############"
echo "#################################"
cd `dirname $0`
NEW_VERSION=$1
ZIP_FILE=angular-$NEW_VERSION.zip
ZIP_FILE_URL=http://code.angularjs.org/$NEW_VERSION/angular-$NEW_VERSION.zip
ZIP_DIR=angular-$NEW_VERSION
REPOS=(
angular \
angular-animate \
angular-cookies \
angular-i18n \
angular-loader \
angular-mocks \
angular-route \
angular-resource \
angular-sanitize \
angular-scenario \
angular-touch \
ARG_DEFS=(
"--action=(prepare|publish)"
)
#
# download and unzip the file
#
#wget $ZIP_FILE_URL
unzip $ZIP_FILE
function init {
TMP_DIR=$(resolveDir ../../tmp)
BUILD_DIR=$(resolveDir ../../build)
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
REPOS=(
angular
angular-animate
angular-cookies
angular-i18n
angular-loader
angular-mocks
angular-route
angular-resource
angular-sanitize
angular-scenario
angular-touch
)
}
#
# move the files from the zip
#
for repo in "${REPOS[@]}"
do
if [ -f $ZIP_DIR/$repo.js ] # ignore i18l
then
cd bower-$repo
git checkout master
git reset --hard HEAD
cd ..
mv $ZIP_DIR/$repo.* bower-$repo/
fi
done
# move i18n files
mv $ZIP_DIR/i18n/*.js bower-angular-i18n/
# move csp.css
mv $ZIP_DIR/angular-csp.css bower-angular
function prepare {
#
# clone repos
#
for repo in "${REPOS[@]}"
do
echo "-- Cloning bower-$repo"
git clone git@github.com:angular/bower-$repo.git $TMP_DIR/bower-$repo
done
#
# get the old version number
#
#
# move the files from the build
#
OLD_VERSION=$(node -e "console.log(require('./bower-angular/bower').version)" | sed -e 's/\r//g')
echo $OLD_VERSION
echo $NEW_VERSION
for repo in "${REPOS[@]}"
do
if [ -f $BUILD_DIR/$repo.js ] # ignore i18l
then
echo "-- Updating files in bower-$repo"
cd $TMP_DIR/bower-$repo
git reset --hard HEAD
git checkout master
git fetch --all
git reset --hard origin/master
cd $SCRIPT_DIR
cp $BUILD_DIR/$repo.* $TMP_DIR/bower-$repo/
fi
done
#
# update bower.json
# tag each repo
#
# move i18n files
cp $BUILD_DIR/i18n/*.js $TMP_DIR/bower-angular-i18n/
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"
git tag v$NEW_VERSION
git push origin master
git push origin v$NEW_VERSION
cd ..
done
# move csp.css
cp $BUILD_DIR/angular-csp.css $TMP_DIR/bower-angular
#
# update bower.json
# tag each repo
#
for repo in "${REPOS[@]}"
do
echo "-- Updating version in bower-$repo to $NEW_VERSION"
cd $TMP_DIR/bower-$repo
replaceJsonProp "bower.json" "version" ".*" "$NEW_VERSION"
replaceJsonProp "bower.json" "angular.*" ".*" "$NEW_VERSION"
git add -A
echo "-- Committing and tagging bower-$repo"
git commit -m "v$NEW_VERSION"
git tag v$NEW_VERSION
cd $SCRIPT_DIR
done
}
function publish {
for repo in "${REPOS[@]}"
do
echo "-- Pushing bower-$repo"
cd $TMP_DIR/bower-$repo
git push origin master
git push origin v$NEW_VERSION
cd $SCRIPT_DIR
done
}
source $(dirname $0)/../utils.inc
+73
View File
@@ -0,0 +1,73 @@
#!/bin/bash
# Script for updating code.angularjs.org repo from current local build.
echo "#################################"
echo "## Update code.angular.js.org ###"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
)
function init {
TMP_DIR=$(resolveDir ../../tmp)
BUILD_DIR=$(resolveDir ../../build)
REPO_DIR=$TMP_DIR/code.angularjs.org
NEW_VERSION=$(cat $BUILD_DIR/version.txt)
if [[ "$NEW_VERSION" =~ sha ]]; then
IS_SNAPSHOT_BUILD=true
else
IS_SNAPSHOT_BUILD=
fi
}
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
#
# copy the files from the build
#
echo "-- Updating code.angularjs.org"
mkdir $REPO_DIR/$NEW_VERSION
cd $REPO_DIR
git reset --hard HEAD
git checkout master
git fetch --all
git reset --hard origin/master
cd $SCRIPT_DIR
cp -r $BUILD_DIR/* $REPO_DIR/$NEW_VERSION/
#
# commit
#
echo "-- Committing code.angularjs.org"
cd $REPO_DIR
git add -A
git commit -m "v$NEW_VERSION"
}
function publish {
if [[ $IS_SNAPSHOT_BUILD ]]; then
echo "-- Updating snapshot version"
curl -G --data-urlencode "ver=$NEW_VERSION" http://code.angularjs.org/fetchLatestSnapshot.php
exit 0;
fi
cd $REPO_DIR
echo "-- Pushing code.angularjs.org"
git push origin master
echo "-- Refreshing code.angularjs.org"
curl http://code.angularjs.org/gitFetchSite.php
}
source $(dirname $0)/../utils.inc
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
echo "#################################"
echo "#### Update master ##############"
echo "#################################"
ARG_DEFS=(
"[--no-test=(true|false)]"
)
function init {
if [[ ! $VERBOSE ]]; then
VERBOSE=false
fi
VERBOSE_ARG="--verbose=$VERBOSE"
}
function build {
cd ../..
if [[ $NO_TEST == "true" ]]; then
npm install --color false
grunt ci-checks package --no-color
else
./jenkins_build.sh
fi
cd $SCRIPT_DIR
}
function phase {
ACTION_ARG="--action=$1"
../code.angularjs.org/publish.sh $ACTION_ARG $VERBOSE_ARG
../bower/publish.sh $ACTION_ARG $VERBOSE_ARG
}
function run {
build
# First prepare all scripts (build, test, commit, tag, ...),
# so we are sure everything is all right
phase prepare
# only then publish to github
phase publish
}
source $(dirname $0)/../utils.inc
+41
View File
@@ -0,0 +1,41 @@
#!/bin/sh
ARG_DEFS=(
# require the git dryrun flag so the script can't be run without
# thinking about this!
"--git-push-dryrun=(true|false)"
"--cdn-version=(.*)"
)
function init {
NG_ARGS=("$@")
if [[ ! $VERBOSE ]]; then
VERBOSE=false
fi
VERBOSE_ARG="--verbose=$VERBOSE"
}
function phase {
ACTION_ARG="--action=$1"
CDN_VERSION_ARG="--cdn-version=$CDN_VERSION"
./scripts/angular.js/publish-cdn-version.sh $ACTION_ARG $CDN_VERSION_ARG $VERBOSE_ARG
./scripts/angularjs.org/publish.sh $ACTION_ARG $CDN_VERSION_ARG $VERBOSE_ARG
}
function checkCdn {
STATUS=$(curl http://ajax.googleapis.com/ajax/libs/angularjs/$CDN_VERSION/angular.min.js --write-out '%{http_code}' -o /dev/null -silent)
if [[ $STATUS != 200 ]]; then
echo "Could not find release $CDN_VERSION on CDN"
exit 1
fi
}
function run {
cd ../..
checkCdn
phase prepare
phase publish
}
source $(dirname $0)/../utils.inc
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
echo "#################################"
echo "#### Cut release ################"
echo "#################################"
ARG_DEFS=(
"--next-version-type=(patch|minor|major)"
"--next-version-name=(.+)"
# require the git dryrun flag so the script can't be run without
# thinking about this!
"--git-push-dryrun=(true|false)"
"[--no-test=(true|false)]"
)
function init {
NG_ARGS=("$@")
if [[ ! $VERBOSE ]]; then
VERBOSE=false
fi
if [[ ! $NO_TEST ]]; then
NO_TEST=false
fi
VERBOSE_ARG="--verbose=$VERBOSE"
NO_TEST_ARG="--no_test=$NO_TEST"
}
function phase {
ACTION_ARG="--action=$1"
../angular.js/publish.sh $ACTION_ARG $VERBOSE_ARG $NO_TEST_ARG \
--next-version-type=$NEXT_VERSION_TYPE --next-version-name=$NEXT_VERSION_NAME
../code.angularjs.org/publish.sh $ACTION_ARG $VERBOSE_ARG
../bower/publish.sh $ACTION_ARG $VERBOSE_ARG
../angular-seed/publish.sh $ACTION_ARG $VERBOSE_ARG $NO_TEST_ARG
../angular-phonecat/publish.sh $ACTION_ARG $VERBOSE_ARG $NO_TEST_ARG
}
function run {
# First prepare all scripts (build, test, commit, tag, ...),
# so we are sure everything is all right
phase prepare
# only then publish to github
phase publish
}
source $(dirname $0)/../utils.inc
+20
View File
@@ -0,0 +1,20 @@
#!/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
grunt test:protractor --sauceUser $SAUCE_USERNAME \
--sauceKey $SAUCE_ACCESS_KEY \
--capabilities.tunnel-identifier=$TRAVIS_JOB_NUMBER \
--capabilities.build=$TRAVIS_BUILD_NUMBER
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
+279
View File
@@ -0,0 +1,279 @@
# This file provides:
# - a default control flow
# * initializes the environment
# * able to mock "git push" in your script and in all sub scripts
# * call a function in your script based on the arguments
# - named argument parsing and automatic generation of the "usage" for your script
# - intercepting "git push" in your script and all sub scripts
# - utility functions
#
# Usage:
# - define the variable ARGS_DEF (see below) with the arguments for your script
# - include this file using `source utils.inc` at the end of your script.
#
# Default control flow:
# 0. Set the current directory to the directory of the script. By this
# the script can be called from anywhere.
# 1. Parse the named arguments
# 2. If the parameter "git_push_dryrun" is set, all calls the `git push` in this script
# or in child scripts will be intercepted so that the `--dry-run` and `--porcelain` is added
# to show what the push would do but not actually do it.
# 3. If the parameter "verbose" is set, the `-x` flag will be set in bash.
# 4. The function "init" will be called if it exists
# 5. If the parameter "action" is set, it will call the function with the name of that parameter.
# Otherwise the function "run" will be called.
#
# Named Argument Parsing:
# - The variable ARGS_DEF defines the valid command arguments
# * Required args syntax: --paramName=paramRegex
# * Optional args syntax: [--paramName=paramRegex]
# * e.g. ARG_DEFS=("--required_param=(.+)" "[--optional_param=(.+)]")
# - Checks that:
# * all arguments match to an entry in ARGS_DEF
# * all required arguments are present
# * all arguments match their regex
# - Afterwards, every paramter value will be stored in a variable
# with the name of the parameter in upper case (with dash converted to underscore).
#
# Special arguments that are always available:
# - "--action=.*": This parameter will be used to dispatch to a function with that name when the
# script is started
# - "--git_push_dryrun=true": This will intercept all calls to `git push` in this script
# or in child scripts so that the `--dry-run` and `--porcelain` is added
# to show what the push would do but not actually do it.
# - "--verbose=true": This will set the `-x` flag in bash so that all calls will be logged
#
# Utility functions:
# - readJsonProp
# - replaceJsonProp
# - resolveDir
# - getVar
# - serVar
# - isFunction
# always stop on errors
set -e
function usage {
echo "Usage: ${0} ${ARG_DEFS[@]}"
exit 1
}
function parseArgs {
local REQUIRED_ARG_NAMES=()
# -- helper functions
function varName {
# everything to upper case and dash to underscore
echo ${1//-/_} | tr '[:lower:]' '[:upper:]'
}
function readArgDefs {
local ARG_DEF
local AD_OPTIONAL
local AD_NAME
local AD_RE
# -- helper functions
function parseArgDef {
local ARG_DEF_REGEX="(\[?)--([^=]+)=(.*)"
if [[ ! $1 =~ $ARG_DEF_REGEX ]]; then
echo "Internal error: arg def has wrong format: $ARG_DEF"
exit 1
fi
AD_OPTIONAL="${BASH_REMATCH[1]}"
AD_NAME="${BASH_REMATCH[2]}"
AD_RE="${BASH_REMATCH[3]}"
if [[ $AD_OPTIONAL ]]; then
# Remove last bracket for optional args.
# Can't put this into the ARG_DEF_REGEX somehow...
AD_RE=${AD_RE%?}
fi
}
# -- run
for ARG_DEF in "${ARG_DEFS[@]}"
do
parseArgDef $ARG_DEF
local AD_NAME_UPPER=$(varName $AD_NAME)
setVar "${AD_NAME_UPPER}_OPTIONAL" "$AD_OPTIONAL"
setVar "${AD_NAME_UPPER}_RE" "$AD_RE"
if [[ ! $AD_OPTIONAL ]]; then
REQUIRED_ARG_NAMES+=($AD_NAME)
fi
done
}
function readAndValidateArgs {
local ARG_NAME
local ARG_VALUE
local ARG_NAME_UPPER
# -- helper functions
function parseArg {
local ARG_REGEX="--([^=]+)=?(.*)"
if [[ ! $1 =~ $ARG_REGEX ]]; then
echo "Can't parse argument $i"
usage
fi
ARG_NAME="${BASH_REMATCH[1]}"
ARG_VALUE="${BASH_REMATCH[2]}"
ARG_NAME_UPPER=$(varName $ARG_NAME)
}
function validateArg {
local AD_RE=$(getVar ${ARG_NAME_UPPER}_RE)
if [[ ! $AD_RE ]]; then
echo "Unknown option: $ARG_NAME"
usage
fi
if [[ ! $ARG_VALUE =~ ^${AD_RE}$ ]]; then
echo "Wrong format: $ARG_NAME"
usage;
fi
# validate that the "action" option points to a valid function
if [[ $ARG_NAME == "action" ]] && ! isFunction $ARG_VALUE; then
echo "No action $ARG_VALUE defined in this script"
usage;
fi
}
# -- run
for i in "$@"
do
parseArg $i
validateArg
setVar "${ARG_NAME_UPPER}" "$ARG_VALUE"
done
}
function checkMissingArgs {
local ARG_NAME
for ARG_NAME in "${REQUIRED_ARG_NAMES[@]}"
do
ARG_VALUE=$(getVar $(varName $ARG_NAME))
if [[ ! $ARG_VALUE ]]; then
echo "Missing: $ARG_NAME"
usage;
fi
done
}
# -- run
readArgDefs
readAndValidateArgs "$@"
checkMissingArgs
}
# getVar(varName)
function getVar {
echo ${!1}
}
# setVar(varName, varValue)
function setVar {
eval "$1=\"$2\""
}
# isFunction(name)
# - to be used in an if, so return 0 if successful and 1 if not!
function isFunction {
if [[ $(type -t $1) == "function" ]]; then
return 0
else
return 1
fi
}
# readJsonProp(jsonFile, property)
# - restriction: property needs to be on an own line!
function readJsonProp {
echo $(sed -En 's/.*"'$2'"[ ]*:[ ]*"(.*)".*/\1/p' $1)
}
# replaceJsonProp(jsonFile, propertyRegex, valueRegex, replacePattern)
# - note: propertyRegex will be automatically placed into a
# capturing group! -> all other groups start at index 2!
function replaceJsonProp {
replaceInFile $1 '"('$2')"[ ]*:[ ]*"'$3'"' '"\1": "'$4'"'
}
# replaceInFile(file, findPattern, replacePattern)
function replaceInFile {
sed -i .tmp -E "s/$2/$3/" $1
rm $1.tmp
}
# resolveDir(relativeDir)
# - resolves a directory relative to the current script
function resolveDir {
echo $(cd $SCRIPT_DIR; cd $1; pwd)
}
function git_push_dryrun_proxy {
echo "## git push dryrun proxy enabled!"
export ORIGIN_GIT=$(which git)
function git {
local ARGS=("$@")
local RC
if [[ $1 == "push" ]]; then
ARGS+=("--dry-run" "--porcelain")
echo "####### START GIT PUSH DRYRUN #######"
echo "${ARGS[@]}"
fi
if [[ $1 == "commit" ]]; then
echo "${ARGS[@]}"
fi
$ORIGIN_GIT "${ARGS[@]}"
RC=$?
if [[ $1 == "push" ]]; then
echo "####### END GIT PUSH DRYRUN #######"
fi
return $RC
}
export -f git
}
function main {
# normalize the working dir to the directory of the script
cd $(dirname $0);SCRIPT_DIR=$(pwd)
ARG_DEFS+=("[--git-push-dryrun=(true|false)]" "[--verbose=(true|false)]")
parseArgs "$@"
# --git_push_dryrun argument
if [[ $GIT_PUSH_DRYRUN == "true" ]]; then
git_push_dryrun_proxy
fi
# --verbose argument
if [[ $VERBOSE == "true" ]]; then
set -x
fi
if isFunction init; then
init "$@"
fi
# jump to the function denoted by the --action argument,
# otherwise call the "run" function
if [[ $ACTION ]]; then
$ACTION "$@"
else
run "$@"
fi
}
main "$@"
+22 -17
View File
@@ -192,7 +192,8 @@ function isArrayLike(obj) {
* is the value of an object property or an array element and `key` is the object property key or
* array element index. Specifying a `context` for the function is optional.
*
* Note: this function was previously known as `angular.foreach`.
* It is worth nothing that `.forEach` does not iterate over inherited properties because it filters
* using the `hasOwnProperty` method.
*
<pre>
var values = {name: 'misko', gender: 'male'};
@@ -213,7 +214,9 @@ function forEach(obj, iterator, context) {
if (obj) {
if (isFunction(obj)){
for (key in obj) {
if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
iterator.call(context, obj[key], key);
}
}
@@ -393,7 +396,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 +410,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 +425,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 +439,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 +453,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 +468,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 +484,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 +499,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 +510,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 +532,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 +641,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;
@@ -769,7 +772,7 @@ function shallowCopy(src, dst) {
for(var key in src) {
// shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
// so we don't need to worry about using our custom hasOwnProperty here
if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
if (src.hasOwnProperty(key) && key.charAt(0) !== '$' && key.charAt(1) !== '$') {
dst[key] = src[key];
}
}
@@ -957,7 +960,9 @@ function fromJson(json) {
function toBoolean(value) {
if (value && value.length !== 0) {
if (typeof value === 'function') {
value = true;
} else if (value && value.length !== 0) {
var v = lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
} else {
@@ -974,7 +979,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;
+4
View File
@@ -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({
+46 -29
View File
@@ -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>
*/
@@ -452,7 +474,7 @@ function annotate(fn) {
* constructor function that will be used to instantiate the service instance.
*
* You should use {@link AUTO.$provide#methods_service $provide.service(class)} if you define your service
* as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}.
* as a type/class.
*
* @param {string} name The name of the instance.
* @param {Function} constructor A class (constructor function) that will be instantiated.
@@ -460,20 +482,25 @@ function annotate(fn) {
*
* @example
* Here is an example of registering a service using
* {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class.
* {@link AUTO.$provide#methods_service $provide.service(class)}.
* <pre>
* class Ping
* constructor: (@$http)->
* send: ()=>
* @$http.get('/ping')
*
* $provide.service('ping', ['$http', Ping])
* $provide.service('ping', ['$http', function($http) {
* var Ping = function() {
* this.$http = $http;
* };
*
* Ping.prototype.send = function() {
* return this.$http.get('/ping');
* };
*
* return Ping;
* }]);
* </pre>
* You would then inject and use this service like this:
* <pre>
* someModule.controller 'Ctrl', ['ping', (ping)->
* ping.send()
* ]
* someModule.controller('Ctrl', ['ping', function(ping) {
* ping.send();
* }]);
* </pre>
*/
@@ -718,6 +745,11 @@ function createInjector(modulesToLoad) {
path.unshift(serviceName);
cache[serviceName] = INSTANTIATING;
return cache[serviceName] = factory(serviceName);
} catch (err) {
if (cache[serviceName] === INSTANTIATING) {
delete cache[serviceName];
}
throw err;
} finally {
path.shift();
}
@@ -747,24 +779,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) {
+36 -5
View File
@@ -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/)
@@ -53,6 +54,7 @@
* - [`next()`](http://api.jquery.com/next/) - Does not support selectors
* - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
* - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
* - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
* - [`prepend()`](http://api.jquery.com/prepend/)
* - [`prop()`](http://api.jquery.com/prop/)
@@ -358,6 +360,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 +563,9 @@ forEach({
jqLiteDealoc(childNodes[i]);
}
element.innerHTML = value;
}
},
empty: jqLiteEmpty
}, function(fn, name){
/**
* Properties: writes return selection, reads return first value
@@ -562,11 +575,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 +606,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
@@ -631,7 +646,10 @@ function createEventHandler(element, events) {
return event.defaultPrevented || event.returnValue === false;
};
forEach(events[type || event.type], function(fn) {
// Copy event handlers in case event handlers array is modified during execution.
var eventHandlersCopy = shallowCopy(events[type || event.type] || []);
forEach(eventHandlersCopy, function(fn) {
fn.call(element, event);
});
@@ -727,6 +745,19 @@ forEach({
off: jqLiteOff,
one: function(element, type, fn) {
element = jqLite(element);
//add the listener twice so that when it is called
//you can remove the original function and still be
//able to call element.off(ev, fn) normally
element.on(type, function onFn() {
element.off(type, fn);
element.off(type, onFn);
});
element.on(type, fn);
},
replaceWith: function(element, replaceNode) {
var index, parent = element.parentNode;
jqLiteDealoc(element);
+22
View File
@@ -61,6 +61,28 @@ var $AnimateProvider = ['$provide', function($provide) {
$provide.factory(key, factory);
};
/**
* @ngdoc function
* @name ng.$animateProvider#classNameFilter
* @methodOf ng.$animateProvider
*
* @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.
* 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
* @return {RegExp} The current CSS className expression value. If null then there is no expression value
*/
this.classNameFilter = function(expression) {
if(arguments.length === 1) {
this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
}
return this.$$classNameFilter;
};
this.$get = ['$timeout', function($timeout) {
/**
+7 -6
View File
@@ -148,8 +148,9 @@ function Browser(window, document, $log, $sniffer) {
* @param {boolean=} replace Should new url replace current history record ?
*/
self.url = function(url, replace) {
// Android Browser BFCache causes location reference to become stale.
// Android Browser BFCache causes location, history reference to become stale.
if (location !== window.location) location = window.location;
if (history !== window.history) history = window.history;
// setter
if (url) {
@@ -201,7 +202,7 @@ function Browser(window, document, $log, $sniffer) {
* @description
* Register callback function that will be called, when url changes.
*
* It's only called when the url is changed by outside of angular:
* It's only called when the url is changed from outside of angular:
* - user types different url into address bar
* - user clicks on history (forward/back) button
* - user clicks on a link
@@ -243,7 +244,7 @@ function Browser(window, document, $log, $sniffer) {
/**
* @name ng.$browser#baseHref
* @methodOf ng.$browser
*
*
* @description
* Returns current <base href>
* (always relative - without domain)
@@ -252,7 +253,7 @@ function Browser(window, document, $log, $sniffer) {
*/
self.baseHref = function() {
var href = baseElement.attr('href');
return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
};
//////////////////////////////////////////////////////////////
@@ -274,13 +275,13 @@ function Browser(window, document, $log, $sniffer) {
* It is not meant to be used directly, use the $cookie service instead.
*
* The return values vary depending on the arguments that the method was called with as follows:
*
*
* - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
* it
* - cookies(name, value) -> set name to value, if value is undefined delete the cookie
* - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
* way)
*
*
* @returns {Object} Hash of all cookies (if called without any parameter)
*/
self.cookies = function(name, value) {
+38 -31
View File
@@ -24,7 +24,7 @@
* @function
*
* @description
* Compiles a piece of HTML string or DOM into a template and produces a template function, which
* Compiles an HTML string or DOM into a template and produces a template function, which
* can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
*
* The compilation is a process of walking the DOM tree and matching DOM elements to
@@ -469,14 +469,14 @@
* example would not point to the clone, but rather to the original template that was cloned. In
* this case, you can access the clone via the cloneAttachFn:
* <pre>
* var templateHTML = angular.element('<p>{{total}}</p>'),
* var templateElement = angular.element('<p>{{total}}</p>'),
* scope = ....;
*
* var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {
* var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
* //attach the clone to DOM document at the right place
* });
*
* //now we have reference to the cloned DOM via `clone`
* //now we have reference to the cloned DOM via `clonedElement`
* </pre>
*
*
@@ -818,6 +818,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext);
safeAddClass($compileNodes, 'ng-scope');
return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
assertArg(scope, 'scope');
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
@@ -832,12 +833,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// Attach scope only to non-text nodes.
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
var node = $linkNode[i];
if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
var node = $linkNode[i],
nodeType = node.nodeType;
if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
$linkNode.eq(i).data('$scope', scope);
}
}
safeAddClass($linkNode, 'ng-scope');
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
return $linkNode;
@@ -865,15 +867,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
* the rootElement must be set the jqLite collection of the compile root. This is
* needed so that the jqLite collection items can be replaced with widgets.
* @param {number=} max directive priority
* @param {number=} maxPriority Max directive priority.
* @returns {?function} A composite linking function of all of the matched directives or null.
*/
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
previousCompileContext) {
var linkFns = [],
nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound;
for(var i = 0; i < nodeList.length; i++) {
for (var i = 0; i < nodeList.length; i++) {
attrs = new Attributes();
// we must always refer to nodeList[i] since the nodes can be replaced underneath us.
@@ -885,16 +887,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
null, [], [], previousCompileContext)
: null;
if (nodeLinkFn && nodeLinkFn.scope) {
safeAddClass(jqLite(nodeList[i]), 'ng-scope');
}
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
!nodeList[i].childNodes ||
!nodeList[i].childNodes.length)
!(childNodes = nodeList[i].childNodes) ||
!childNodes.length)
? null
: compileNodes(nodeList[i].childNodes,
: compileNodes(childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
linkFns.push(nodeLinkFn);
linkFns.push(childLinkFn);
linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
linkFns.push(nodeLinkFn, childLinkFn);
linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
//use the previous context only for the first element in the virtual group
previousCompileContext = null;
}
@@ -906,9 +911,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
// copy nodeList so that linking doesn't break due to live list updates.
var stableNodeList = [];
for (i = 0, ii = nodeList.length; i < ii; i++) {
stableNodeList.push(nodeList[i]);
var nodeListLength = nodeList.length,
stableNodeList = new Array(nodeListLength);
for (i = 0; i < nodeListLength; i++) {
stableNodeList[i] = nodeList[i];
}
for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
@@ -921,7 +927,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (nodeLinkFn.scope) {
childScope = scope.$new();
$node.data('$scope', childScope);
safeAddClass($node, 'ng-scope');
} else {
childScope = scope;
}
@@ -1004,9 +1009,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nName = directiveNormalize(name.toLowerCase());
attrsMap[nName] = name;
attrs[nName] = value = trim((msie && name == 'href')
? decodeURIComponent(node.getAttribute(name, 2))
: attr.value);
attrs[nName] = value = trim(attr.value);
if (getBooleanAttrName(node, nName)) {
attrs[nName] = true; // presence means true
}
@@ -1219,7 +1222,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 +1403,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 +1426,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 +1441,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 +1452,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}
return lastValue = parentValue;
});
}, null, parentGet.literal);
break;
case '&':
@@ -1647,7 +1654,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) {
@@ -1950,7 +1957,7 @@ function directiveNormalize(name) {
*
*
* @param {string} name Normalized element attribute name of the property to modify. The name is
* revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
* reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
* property to the original name.
* @param {string} value Value to set the attribute to. The value can be an interpolated string.
*/
+10 -8
View File
@@ -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();
}
});
};
}
}
});
+13 -9
View File
@@ -4,6 +4,7 @@
* @ngdoc directive
* @name ng.directive:ngHref
* @restrict A
* @priority 99
*
* @description
* Using Angular markup like `{{hash}}` in an href attribute will
@@ -87,6 +88,7 @@
* @ngdoc directive
* @name ng.directive:ngSrc
* @restrict A
* @priority 99
*
* @description
* Using Angular markup like `{{hash}}` in a `src` attribute doesn't
@@ -112,6 +114,7 @@
* @ngdoc directive
* @name ng.directive:ngSrcset
* @restrict A
* @priority 99
*
* @description
* Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
@@ -137,6 +140,7 @@
* @ngdoc directive
* @name ng.directive:ngDisabled
* @restrict A
* @priority 100
*
* @description
*
@@ -180,6 +184,7 @@
* @ngdoc directive
* @name ng.directive:ngChecked
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
@@ -214,6 +219,7 @@
* @ngdoc directive
* @name ng.directive:ngReadonly
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
@@ -223,7 +229,6 @@
* The `ngReadonly` directive solves this problem for the `readonly` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
* @example
<doc:example>
<doc:source>
@@ -249,6 +254,7 @@
* @ngdoc directive
* @name ng.directive:ngSelected
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
@@ -258,6 +264,7 @@
* The `ngSelected` directive solves this problem for the `selected` atttribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
*
* @example
<doc:example>
<doc:source>
@@ -285,6 +292,7 @@
* @ngdoc directive
* @name ng.directive:ngOpen
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
@@ -294,8 +302,6 @@
* The `ngOpen` directive solves this problem for the `open` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
*
* @example
<doc:example>
<doc:source>
@@ -330,12 +336,10 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) {
ngAttributeAliasDirectives[normalized] = function() {
return {
priority: 100,
compile: function() {
return function(scope, element, attr) {
scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
attr.$set(attrName, !!value);
});
};
link: function(scope, element, attr) {
scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
attr.$set(attrName, !!value);
});
}
};
};
+4 -4
View File
@@ -249,10 +249,10 @@ function FormController(element, attrs) {
*
*
* # CSS classes
* - `ng-valid` Is set if the form is valid.
* - `ng-invalid` Is set if the form is invalid.
* - `ng-pristine` Is set if the form is pristine.
* - `ng-dirty` Is set if the form is dirty.
* - `ng-valid` is set if the form is valid.
* - `ng-invalid` is set if the form is invalid.
* - `ng-pristine` is set if the form is pristine.
* - `ng-dirty` is set if the form is dirty.
*
*
* # Submitting a form and preventing the default action
+33 -72
View File
@@ -390,20 +390,28 @@ var inputType = {
'reset': noop
};
// A helper function to call $setValidity and return the value / undefined,
// a pattern that is repeated a lot in the input validation logic.
function validate(ctrl, validatorName, validity, value){
ctrl.$setValidity(validatorName, validity);
return validity ? value : undefined;
}
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// In composition mode, users are still inputing intermediate text buffer,
// hold the listener until composition is done.
// More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
var composing = false;
if (!$sniffer.android) {
var composing = false;
element.on('compositionstart', function() {
composing = true;
});
element.on('compositionstart', function(data) {
composing = true;
});
element.on('compositionend', function() {
composing = false;
});
element.on('compositionend', function() {
composing = false;
});
}
var listener = function() {
if (composing) return;
@@ -417,9 +425,13 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
if (ctrl.$viewValue !== value) {
scope.$apply(function() {
if (scope.$$phase) {
ctrl.$setViewValue(value);
});
} else {
scope.$apply(function() {
ctrl.$setViewValue(value);
});
}
}
};
@@ -468,22 +480,15 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
patternValidator,
match;
var validate = function(regexp, value) {
if (ctrl.$isEmpty(value) || regexp.test(value)) {
ctrl.$setValidity('pattern', true);
return value;
} else {
ctrl.$setValidity('pattern', false);
return undefined;
}
};
if (pattern) {
var validateRegex = function(regexp, value) {
return validate(ctrl, 'pattern', ctrl.$isEmpty(value) || regexp.test(value), value);
};
match = pattern.match(/^\/(.*)\/([gim]*)$/);
if (match) {
pattern = new RegExp(match[1], match[2]);
patternValidator = function(value) {
return validate(pattern, value);
return validateRegex(pattern, value);
};
} else {
patternValidator = function(value) {
@@ -494,7 +499,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern,
patternObj, startingTag(element));
}
return validate(patternObj, value);
return validateRegex(patternObj, value);
};
}
@@ -506,13 +511,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
if (attr.ngMinlength) {
var minlength = int(attr.ngMinlength);
var minLengthValidator = function(value) {
if (!ctrl.$isEmpty(value) && value.length < minlength) {
ctrl.$setValidity('minlength', false);
return undefined;
} else {
ctrl.$setValidity('minlength', true);
return value;
}
return validate(ctrl, 'minlength', ctrl.$isEmpty(value) || value.length >= minlength, value);
};
ctrl.$parsers.push(minLengthValidator);
@@ -523,13 +522,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
if (attr.ngMaxlength) {
var maxlength = int(attr.ngMaxlength);
var maxLengthValidator = function(value) {
if (!ctrl.$isEmpty(value) && value.length > maxlength) {
ctrl.$setValidity('maxlength', false);
return undefined;
} else {
ctrl.$setValidity('maxlength', true);
return value;
}
return validate(ctrl, 'maxlength', ctrl.$isEmpty(value) || value.length <= maxlength, value);
};
ctrl.$parsers.push(maxLengthValidator);
@@ -558,13 +551,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
if (attr.min) {
var minValidator = function(value) {
var min = parseFloat(attr.min);
if (!ctrl.$isEmpty(value) && value < min) {
ctrl.$setValidity('min', false);
return undefined;
} else {
ctrl.$setValidity('min', true);
return value;
}
return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value);
};
ctrl.$parsers.push(minValidator);
@@ -574,13 +561,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
if (attr.max) {
var maxValidator = function(value) {
var max = parseFloat(attr.max);
if (!ctrl.$isEmpty(value) && value > max) {
ctrl.$setValidity('max', false);
return undefined;
} else {
ctrl.$setValidity('max', true);
return value;
}
return validate(ctrl, 'max', ctrl.$isEmpty(value) || value <= max, value);
};
ctrl.$parsers.push(maxValidator);
@@ -588,14 +569,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
ctrl.$formatters.push(function(value) {
if (ctrl.$isEmpty(value) || isNumber(value)) {
ctrl.$setValidity('number', true);
return value;
} else {
ctrl.$setValidity('number', false);
return undefined;
}
return validate(ctrl, 'number', ctrl.$isEmpty(value) || isNumber(value), value);
});
}
@@ -603,13 +577,7 @@ function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
var urlValidator = function(value) {
if (ctrl.$isEmpty(value) || URL_REGEXP.test(value)) {
ctrl.$setValidity('url', true);
return value;
} else {
ctrl.$setValidity('url', false);
return undefined;
}
return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);
};
ctrl.$formatters.push(urlValidator);
@@ -620,13 +588,7 @@ function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
var emailValidator = function(value) {
if (ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value)) {
ctrl.$setValidity('email', true);
return value;
} else {
ctrl.$setValidity('email', false);
return undefined;
}
return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);
};
ctrl.$formatters.push(emailValidator);
@@ -1432,7 +1394,6 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
id="{{name}}"
name="favorite">
</label>
</span>
<div>You chose {{my.favorite}}</div>
</form>
</doc:source>
+1 -1
View File
@@ -35,7 +35,7 @@
*
* Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
* cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
* class `ngCloak` in addition to the `ngCloak` directive as shown in the example below.
* class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
*
* @element ANY
*
+97 -18
View File
@@ -20,13 +20,13 @@
</button>
count: {{count}}
</doc:source>
<doc:scenario>
<doc:protractor>
it('should check ng-click', function() {
expect(binding('count')).toBe('0');
element('.doc-example-live :button').click();
expect(binding('count')).toBe('1');
expect(element(by.binding('count')).getText()).toMatch('0');
element(by.css('.doc-example-live button')).click();
expect(element(by.binding('count')).getText()).toMatch('1');
});
</doc:scenario>
</doc:protractor>
</doc:example>
*/
/*
@@ -69,7 +69,14 @@ forEach(
* a dblclick. (The Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-dblclick="count = count + 1" ng-init="count=0">
Increment (on double click)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -85,7 +92,14 @@ forEach(
* mousedown. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mousedown="count = count + 1" ng-init="count=0">
Increment (on mouse down)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -101,7 +115,14 @@ forEach(
* mouseup. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseup="count = count + 1" ng-init="count=0">
Increment (on mouse up)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
/**
@@ -116,7 +137,14 @@ forEach(
* mouseover. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseover="count = count + 1" ng-init="count=0">
Increment (when mouse is over)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -132,7 +160,14 @@ forEach(
* mouseenter. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseenter="count = count + 1" ng-init="count=0">
Increment (when mouse enters)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -148,7 +183,14 @@ forEach(
* mouseleave. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseleave="count = count + 1" ng-init="count=0">
Increment (when mouse leaves)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -164,7 +206,14 @@ forEach(
* mousemove. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mousemove="count = count + 1" ng-init="count=0">
Increment (when mouse moves)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -180,7 +229,12 @@ forEach(
* keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-keydown="count = count + 1" ng-init="count=0">
key down count: {{count}}
</doc:source>
</doc:example>
*/
@@ -196,7 +250,12 @@ forEach(
* keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-keyup="count = count + 1" ng-init="count=0">
key up count: {{count}}
</doc:source>
</doc:example>
*/
@@ -212,7 +271,12 @@ forEach(
* keypress. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-keypress="count = count + 1" ng-init="count=0">
key press count: {{count}}
</doc:source>
</doc:example>
*/
@@ -311,7 +375,12 @@ forEach(
* copy. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
copied: {{copied}}
</doc:source>
</doc:example>
*/
/**
@@ -326,7 +395,12 @@ forEach(
* cut. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
cut: {{cut}}
</doc:source>
</doc:example>
*/
/**
@@ -341,5 +415,10 @@ forEach(
* paste. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
pasted: {{paste}}
</doc:source>
</doc:example>
*/
-3
View File
@@ -59,9 +59,6 @@
padding:10px;
}
/&#42;
The transition styles can also be placed on the CSS base class above
&#42;/
.animate-if.ng-enter, .animate-if.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+27 -7
View File
@@ -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);
}
};
}];
+1 -1
View File
@@ -10,7 +10,7 @@
* current scope.
*
* <div class="alert alert-error">
* The only appropriate use of `ngInit` for aliasing special properties of
* The only appropriate use of `ngInit` is for aliasing special properties of
* {@link api/ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
* should use {@link guide/controller controllers} rather than `ngInit`
* to initialize values on a scope.
+4 -2
View File
@@ -20,6 +20,8 @@
* | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
* | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
*
* Creating aliases for these properties is possible with {@link api/ng.directive:ngInit `ngInit`}.
* This may be useful when, for instance, nesting ngRepeats.
*
* # Special repeat start and end points
* To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
@@ -203,7 +205,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
$$tlb: true,
link: function($scope, $element, $attr, ctrl, $transclude){
var expression = $attr.ngRepeat;
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
lhs, rhs, valueIdentifier, keyIdentifier,
hashFnLocals = {$id: hashKey};
@@ -215,7 +217,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
lhs = match[1];
rhs = match[2];
trackByExp = match[4];
trackByExp = match[3];
if (trackByExp) {
trackByExpGetter = $parse(trackByExp);
+16 -10
View File
@@ -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>.
@@ -160,11 +168,9 @@ var ngSwitchWhenDirective = ngDirective({
transclude: 'element',
priority: 800,
require: '^ngSwitch',
compile: function(element, attrs) {
return function(scope, element, attr, ctrl, $transclude) {
ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
};
link: function(scope, element, attrs, ctrl, $transclude) {
ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
}
});
+1 -1
View File
@@ -69,7 +69,7 @@ var ngTranscludeDirective = ngDirective({
link: function($scope, $element, $attrs, controller) {
controller.$transclude(function(clone) {
$element.html('');
$element.empty();
$element.append(clone);
});
}
+7 -3
View File
@@ -6,10 +6,14 @@
* @restrict E
*
* @description
* Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the
* template can be used by `ngInclude`, `ngView` or directive templates.
* Load the content of a `<script>` element into {@link api/ng.$templateCache `$templateCache`}, so that the
* template can be used by {@link api/ng.directive:ngInclude `ngInclude`},
* {@link api/ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
* `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
* assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
*
* @param {'text/ng-template'} type must be set to `'text/ng-template'`
* @param {'text/ng-template'} type Must be set to `'text/ng-template'`.
* @param {string} id Cache name of the template.
*
* @example
<doc:example>
+7 -15
View File
@@ -128,8 +128,8 @@ var ngOptionsMinErr = minErr('ngOptions');
var ngOptionsDirective = valueFn({ terminal: true });
// jshint maxlen: false
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
//0000111110000000000022220000000000000000000000333300000000000000444444444444444000000000555555555555555000000066666666666666600000000000000007777000000000000000000088888
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/,
//000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
nullModelCtrl = {$setViewValue: noop};
// jshint maxlen: 100
@@ -221,18 +221,10 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
// required validator
if (multiple && (attr.required || attr.ngRequired)) {
var requiredValidator = function(value) {
ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));
return value;
if (multiple) {
ngModelCtrl.$isEmpty = function(value) {
return !value || value.length === 0;
};
ngModelCtrl.$parsers.push(requiredValidator);
ngModelCtrl.$formatters.unshift(requiredValidator);
attr.$observe('required', function() {
requiredValidator(ngModelCtrl.$viewValue);
});
}
if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
@@ -333,13 +325,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 -2
View File
@@ -6,8 +6,7 @@
* @requires $window
*
* @description
* A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`
* element.
* A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
*/
function $DocumentProvider(){
this.$get = ['$window', function(window){
+12 -23
View File
@@ -14,8 +14,8 @@
*
* Can be one of:
*
* - `string`: Predicate that results in a substring match using the value of `expression`
* string. All strings or objects with string properties in `array` that contain this string
* - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
* the contents of the `array`. All strings or objects with string properties in `array` that contain this string
* will be returned. The predicate can be negated by prefixing the string with `!`.
*
* - `Object`: A pattern object can be used to filter specific properties on objects contained
@@ -25,21 +25,21 @@
* property of the object. That's equivalent to the simple substring match with a `string`
* as described above.
*
* - `function`: A predicate function can be used to write arbitrary filters. The function is
* - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
* called for each element of `array`. The final result is an array of those elements that
* the predicate returned true for.
*
* @param {function(expected, actual)|true|undefined} comparator Comparator which is used in
* @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
* determining if the expected value (from the filter expression) and actual value (from
* the object in the array) should be considered a match.
*
* Can be one of:
*
* - `function(expected, actual)`:
* - `function(actual, expected)`:
* The function will be given the object value and the predicate value to compare and
* should return true if the item should be included in filtered result.
*
* - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`.
* - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
* this is essentially strict comparison of expected and actual.
*
* - `false|undefined`: A short hand for a function which will look for a substring match in case
@@ -173,23 +173,12 @@ function filterFilter() {
case "object":
// jshint +W086
for (var key in expression) {
if (key == '$') {
(function() {
if (!expression[key]) return;
var path = key;
predicates.push(function(value) {
return search(value, expression[path]);
});
})();
} else {
(function() {
if (typeof(expression[key]) == 'undefined') { return; }
var path = key;
predicates.push(function(value) {
return search(getter(value,path), expression[path]);
});
})();
}
(function(path) {
if (typeof expression[path] == 'undefined') return;
predicates.push(function(value) {
return search(path == '$' ? value : getter(value, path), expression[path]);
});
})(key);
}
break;
case 'function':
+22 -10
View File
@@ -111,9 +111,9 @@ function $HttpProvider() {
common: {
'Accept': 'application/json, text/plain, */*'
},
post: CONTENT_TYPE_APPLICATION_JSON,
put: CONTENT_TYPE_APPLICATION_JSON,
patch: CONTENT_TYPE_APPLICATION_JSON
post: copy(CONTENT_TYPE_APPLICATION_JSON),
put: copy(CONTENT_TYPE_APPLICATION_JSON),
patch: copy(CONTENT_TYPE_APPLICATION_JSON)
},
xsrfCookieName: 'XSRF-TOKEN',
@@ -222,7 +222,7 @@ function $HttpProvider() {
* will result in the success callback being called. Note that if the response is a redirect,
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
* called for such responses.
*
*
* # Calling $http from outside AngularJS
* The `$http` service will not actually send the request until the next `$digest()` is
* executed. Normally this is not an issue, since almost all the time your call to `$http` will
@@ -291,7 +291,15 @@ function $HttpProvider() {
* `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.
*
* The defaults can also be set at runtime via the `$http.defaults` object in the same
* fashion. In addition, you can supply a `headers` property in the config object passed when
* fashion. For example:
*
* ```
* module.run(function($http) {
* $http.defaults.headers.common.Authentication = 'Basic YmVlcDpib29w'
* });
* ```
*
* In addition, you can supply a `headers` property in the config object passed when
* calling `$http(config)`, which overrides the defaults without changing them globally.
*
*
@@ -315,7 +323,9 @@ function $HttpProvider() {
* properties. These properties are by default an array of transform functions, which allows you
* to `push` or `unshift` a new transformation function into the transformation chain. You can
* also decide to completely override any default transformations by assigning your
* transformation functions to these properties directly without the array wrapper.
* transformation functions to these properties directly without the array wrapper. These defaults
* are again available on the $http factory at run-time, which may be useful if you have run-time
* services you wish to be involved in your transformations.
*
* Similarly, to locally override the request/response transforms, augment the
* `transformRequest` and/or `transformResponse` properties of the configuration object passed
@@ -409,19 +419,20 @@ function $HttpProvider() {
* return responseOrNewPromise
* }
* return $q.reject(rejection);
* };
* }
* }
* };
* });
*
* $httpProvider.interceptors.push('myHttpInterceptor');
*
*
* // register the interceptor via an anonymous factory
* // alternatively, register the interceptor via an anonymous factory
* $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
* return {
* 'request': function(config) {
* // same as above
* },
*
* 'response': function(response) {
* // same as above
* }
@@ -528,7 +539,8 @@ function $HttpProvider() {
* for added security.
*
* The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
* properties of either $httpProvider.defaults, or the per-request config object.
* properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
* or the per-request config object.
*
*
* @param {object} config Object describing the request to be made and how it should be
+28 -18
View File
@@ -1,12 +1,12 @@
'use strict';
var XHR = window.XMLHttpRequest || function() {
function createXhr(method) {
// IE8 doesn't support PATCH method, but the ActiveX object does
/* global ActiveXObject */
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest.");
};
return (msie <= 8 && lowercase(method) === 'patch')
? new ActiveXObject('Microsoft.XMLHTTP')
: new window.XMLHttpRequest();
}
/**
@@ -28,11 +28,11 @@ var XHR = window.XMLHttpRequest || function() {
*/
function $HttpBackendProvider() {
this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks, $document[0]);
return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
}];
}
function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument) {
function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
var ABORTED = -1;
// TODO(vojta): fix the signature
@@ -54,10 +54,12 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument)
} else {
completeRequest(callback, status || -2);
}
delete callbacks[callbackId];
callbacks[callbackId] = angular.noop;
});
} else {
var xhr = new XHR();
var xhr = createXhr(method);
xhr.open(method, url, true);
forEach(headers, function(value, key) {
if (isDefined(value)) {
@@ -69,17 +71,25 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument)
// response is in the cache. the promise api will ensure that to the app code the api is
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// onreadystatechange might get called multiple times with readyState === 4 on mobile webkit caused by
// xhrs that are resolved while the app is in the background (see #5426).
// since calling completeRequest sets the `xhr` variable to null, we just check if it's not null before
// continuing
//
// we can't set xhr.onreadystatechange to undefined or delete it because that breaks IE8 (method=PATCH) and
// Safari respectively.
if (xhr && xhr.readyState == 4) {
var responseHeaders = null,
response = null;
if(status !== ABORTED) {
responseHeaders = xhr.getAllResponseHeaders();
response = xhr.responseType ? xhr.response : xhr.responseText;
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
response = ('response' in xhr) ? xhr.response : xhr.responseText;
}
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
completeRequest(callback,
status || xhr.status,
response,
@@ -112,14 +122,14 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument)
}
function completeRequest(callback, status, response, headersString) {
var protocol = urlResolve(url).protocol;
// cancel timeout and subsequent timeout promise resolution
timeoutId && $browserDefer.cancel(timeoutId);
jsonpDone = xhr = null;
// fix status code for file protocol (it's always 0)
status = (protocol == 'file' && status === 0) ? (response ? 200 : 404) : status;
// fix status code when it is 0 (0 status is undocumented).
// Occurs when accessing file resources.
// On Android 4.1 stock browser it occurs while retrieving files from application cache.
status = (status === 0) ? (response ? 200 : 404) : status;
// normalize IE bug (http://bugs.jquery.com/ticket/1450)
status = status == 1223 ? 204 : status;
+97
View File
@@ -24,6 +24,14 @@ function $IntervalProvider() {
* In tests you can use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to
* move forward by `millis` milliseconds and trigger any functions scheduled to run in that
* time.
*
* <div class="alert alert-warning">
* **Note**: Intervals created by this service must be explicitly destroyed when you are finished
* with them. In particular they are not automatically destroyed when a controller's scope or a
* directive's element are destroyed.
* You should take this into consideration and make sure to always cancel the interval at the
* appropriate moment. See the example below for more details on how and when to do this.
* </div>
*
* @param {function()} fn A function that should be called repeatedly.
* @param {number} delay Number of milliseconds between each function call.
@@ -32,6 +40,95 @@ function $IntervalProvider() {
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
* will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
* @returns {promise} A promise which will be notified on each iteration.
*
* @example
<doc:example module="time">
<doc:source>
<script>
function Ctrl2($scope,$interval) {
$scope.format = 'M/d/yy h:mm:ss a';
$scope.blood_1 = 100;
$scope.blood_2 = 120;
var stop;
$scope.fight = function() {
// Don't start a new fight if we are already fighting
if ( angular.isDefined(stop) ) return;
stop = $interval(function() {
if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
$scope.blood_1 = $scope.blood_1 - 3;
$scope.blood_2 = $scope.blood_2 - 4;
} else {
$scope.stopFight();
}
}, 100);
};
$scope.stopFight = function() {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
};
$scope.resetFight = function() {
$scope.blood_1 = 100;
$scope.blood_2 = 120;
}
$scope.$on('$destroy', function() {
// Make sure that the interval is destroyed too
$scope.stopFight();
});
}
angular.module('time', [])
// Register the 'myCurrentTime' directive factory method.
// We inject $interval and dateFilter service since the factory method is DI.
.directive('myCurrentTime', function($interval, dateFilter) {
// return the directive link function. (compile function not needed)
return function(scope, element, attrs) {
var format, // date format
stopTime; // so that we can cancel the time updates
// used to update the UI
function updateTime() {
element.text(dateFilter(new Date(), format));
}
// watch the expression, and update the UI on change.
scope.$watch(attrs.myCurrentTime, function(value) {
format = value;
updateTime();
});
stopTime = $interval(updateTime, 1000);
// listen on DOM destroy (removal) event, and cancel the next UI update
// to prevent updating time ofter the DOM element was removed.
element.bind('$destroy', function() {
$interval.cancel(stopTime);
});
}
});
</script>
<div>
<div ng-controller="Ctrl2">
Date format: <input ng-model="format"> <hr/>
Current time is: <span my-current-time="format"></span>
<hr/>
Blood 1 : <font color='red'>{{blood_1}}</font>
Blood 2 : <font color='red'>{{blood_2}}</font>
<button type="button" data-ng-click="fight()">Fight</button>
<button type="button" data-ng-click="stopFight()">StopFight</button>
<button type="button" data-ng-click="resetFight()">resetFight</button>
</div>
</div>
</doc:source>
</doc:example>
*/
function interval(fn, delay, count, invokeApply) {
var setInterval = $window.setInterval,
+15 -7
View File
@@ -576,7 +576,7 @@ function $LocationProvider(){
* Broadcasted before a URL will change. This change can be prevented by calling
* `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
* details about event object. Upon successful change
* {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
* {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.
*
* @param {Object} angularEvent Synthetic event object.
* @param {string} newUrl New URL
@@ -629,6 +629,13 @@ function $LocationProvider(){
}
var absHref = elm.prop('href');
if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
// SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
// an animation.
absHref = urlResolve(absHref.animVal).href;
}
var rewrittenUrl = $location.$$rewrite(absHref);
if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
@@ -652,16 +659,17 @@ function $LocationProvider(){
// update $location when $browser url changes
$browser.onUrlChange(function(newUrl) {
if ($location.absUrl() != newUrl) {
if ($rootScope.$broadcast('$locationChangeStart', newUrl,
$location.absUrl()).defaultPrevented) {
$browser.url($location.absUrl());
return;
}
$rootScope.$evalAsync(function() {
var oldUrl = $location.absUrl();
$location.$$parse(newUrl);
afterLocationChange(oldUrl);
if ($rootScope.$broadcast('$locationChangeStart', newUrl,
oldUrl).defaultPrevented) {
$location.$$parse(oldUrl);
$browser.url(oldUrl);
} else {
afterLocationChange(oldUrl);
}
});
if (!$rootScope.$$phase) $rootScope.$digest();
}

Some files were not shown because too many files have changed in this diff Show More